feat(web): iteration add output_type ;

docs(web): add comments
This commit is contained in:
zhaoying
2026-02-03 15:40:18 +08:00
parent df8706983b
commit be01f1869e
3 changed files with 99 additions and 9 deletions

View File

@@ -1,18 +1,36 @@
/*
* @Author: ZhaoYing
* @Date: 2026-02-03 15:40:13
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-02-03 15:40:13
*/
import { type FC } from 'react'
import clsx from 'clsx';
import { Select, type SelectProps } from 'antd'
import type { Suggestion } from '../Editor/plugin/AutocompletePlugin'
type LabelRender = SelectProps['labelRender'];
/**
* Props for VariableSelect component
*/
interface VariableSelectProps extends SelectProps {
/** Available variable options */
options: Suggestion[];
/** Current selected value */
value?: string;
onChange?: (value: string) => void;
/** Whether to show clear button */
allowClear?: boolean;
/** Filter out boolean type variables */
filterBooleanType?: boolean;
/** Size of the select component */
size?: 'small' | 'middle' | 'large'
}
/**
* VariableSelect component
* Custom select component for workflow variables with grouped options and custom rendering
* @param props - Component props
*/
const VariableSelect: FC<VariableSelectProps> = ({
placeholder,
options,
@@ -24,9 +42,19 @@ const VariableSelect: FC<VariableSelectProps> = ({
...resetPorps
}) => {
const handleChange = (value: string) => {
onChange?.(value);
/**
* Handle value change and pass selected option to parent
* @param value - Selected value
*/
const handleChange: SelectProps['onChange'] = (value: string) => {
const filterItem = options.find(option => `{{${option.value}}}` === value)
onChange?.(value, filterItem);
}
/**
* Custom label renderer for selected value
* Displays node icon, name and variable label
* @param props - Label render props
*/
const labelRender: LabelRender = (props) => {
const { value } = props
const filterOption = filteredOptions.find(vo => `{{${vo.value}}}` === value)
@@ -57,10 +85,14 @@ const VariableSelect: FC<VariableSelectProps> = ({
}
return null
}
// Filter options based on boolean type if needed
const filteredOptions = filterBooleanType
? options.filter(option => option.dataType !== 'boolean')
: options;
/**
* Group suggestions by node ID
*/
const groupedSuggestions = filteredOptions.reduce((groups: Record<string, any[]>, suggestion) => {
const { nodeData } = suggestion
const nodeId = nodeData.id as string;
@@ -71,6 +103,9 @@ const VariableSelect: FC<VariableSelectProps> = ({
return groups;
}, {});
/**
* Format grouped options for Select component
*/
const groupedOptions = Object.entries(groupedSuggestions).map(([_nodeId, suggestions]) => ({
label: suggestions[0].nodeData.name,
options: suggestions.map(s => ({

View File

@@ -1,3 +1,9 @@
/*
* @Author: ZhaoYing
* @Date: 2026-02-03 15:39:59
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-02-03 15:39:59
*/
import { type FC, useEffect, useState, useMemo } from "react";
import clsx from 'clsx'
import { useTranslation } from 'react-i18next'
@@ -31,17 +37,35 @@ import RbSlider from './RbSlider'
import JinjaRender from './JinjaRender'
import CodeExecution from './CodeExecution'
/**
* Props for Properties component
*/
interface PropertiesProps {
/** Currently selected node */
selectedNode?: Node | null;
/** Function to update selected node */
setSelectedNode: (node: Node | null) => void;
/** Reference to graph instance */
graphRef: React.MutableRefObject<Graph | undefined>;
/** Handler for blank canvas click */
blankClick: () => void;
/** Handler for delete event */
deleteEvent: () => void;
/** Handler for copy event */
copyEvent: () => void;
/** Handler for paste event */
parseEvent: () => void;
/** Workflow configuration */
config?: any;
/** Chat variables */
chatVariables: ChatVariable[];
}
/**
* Properties panel component
* Displays and manages configuration for selected workflow node
* @param props - Component props
*/
const Properties: FC<PropertiesProps> = ({
selectedNode,
graphRef,
@@ -83,6 +107,10 @@ const Properties: FC<PropertiesProps> = ({
}
}, [selectedNode, form])
/**
* Update node label in graph
* @param newLabel - New label text
*/
const updateNodeLabel = (newLabel: string) => {
if (selectedNode && form) {
const nodeData = selectedNode.data as NodeProperties;
@@ -107,8 +135,6 @@ const Properties: FC<PropertiesProps> = ({
}))
}
Object.keys(values).forEach(key => {
if (selectedNode.data?.config?.[key]) {
// Create a deep copy to avoid reference sharing between nodes
@@ -131,7 +157,12 @@ const Properties: FC<PropertiesProps> = ({
// Filter out boolean type variables for loop and llm nodes
/**
* Get filtered variable list based on node type and config key
* @param nodeType - Type of the node
* @param key - Configuration key
* @returns Filtered variable list
*/
const getFilteredVariableList = (nodeType?: string, key?: string) => {
// Check if current node is a child of iteration node
const parentIterationNode = selectedNode ? (() => {
@@ -321,15 +352,33 @@ const Properties: FC<PropertiesProps> = ({
console.log('values', values)
/**
* Get current node output variables
*/
const currentNodeVariables = useMemo(() => {
if (!selectedNode) return []
return getCurrentNodeVariables(selectedNode?.getData(), values)
}, [selectedNode?.getData(), values])
const [outputCollapsed, setOutputCollapsed] = useState(true)
/**
* Toggle output section collapsed state
*/
const handleToggle = () => {
setOutputCollapsed((prev: boolean) => !prev)
}
/**
* Handle variable list change and update output type for iteration nodes
* @param _value - Selected value
* @param option - Selected option
* @param key - Configuration key
*/
const handleChangeVariableList = (_value: string, option: any, key: string) => {
if (selectedNode?.data?.type === 'iteration' && key === 'output') {
form.setFieldValue('output_type', option?.dataType)
}
}
console.log('variableList', variableList, currentNodeVariables)
return (
@@ -422,6 +471,9 @@ const Properties: FC<PropertiesProps> = ({
</Form.Item>
)
}
if (selectedNode?.data?.type === 'iteration' && key === 'output_type') {
return (<Form.Item key={key} name={key} hidden />)
}
if (config.type === 'define') {
return null
}
@@ -628,8 +680,8 @@ const Properties: FC<PropertiesProps> = ({
);
}
return baseVariableList;
})()
}
})()}
onChange={(value, option) => handleChangeVariableList(value, option, key)}
size="small"
/>
: config.type === 'switch'

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing
* @Date: 2026-02-03 15:06:18
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-02-03 15:10:19
* @Last Modified time: 2026-02-03 15:25:25
*/
import LoopNode from './components/Nodes/LoopNode';
import NormalNode from './components/Nodes/NormalNode';
@@ -317,6 +317,9 @@ export const nodeLibrary: NodeLibrary[] = [
output: {
type: 'variableList',
filterChildNodes: true
},
output_type: {
type: 'define',
}
},
},