| @@ -0,0 +1,27 @@ | |||
| 'use client' | |||
| import type { FC } from 'react' | |||
| import React from 'react' | |||
| import { RiRefreshLine } from '@remixicon/react' | |||
| import cn from '@/utils/classnames' | |||
| import TooltipPlus from '@/app/components/base/tooltip' | |||
| type Props = { | |||
| className?: string, | |||
| popupContent?: string, | |||
| onClick: () => void | |||
| } | |||
| const SyncButton: FC<Props> = ({ | |||
| className, | |||
| popupContent = '', | |||
| onClick, | |||
| }) => { | |||
| return ( | |||
| <TooltipPlus popupContent={popupContent}> | |||
| <div className={cn(className, 'cursor-pointer select-none rounded-md p-1 hover:bg-state-base-hover')} onClick={onClick}> | |||
| <RiRefreshLine className='h-4 w-4 text-text-tertiary' /> | |||
| </div> | |||
| </TooltipPlus> | |||
| ) | |||
| } | |||
| export default React.memo(SyncButton) | |||
| @@ -65,10 +65,11 @@ const VarList: FC<Props> = ({ | |||
| }, [list, onVarNameChange, onChange]) | |||
| const handleVarReferenceChange = useCallback((index: number) => { | |||
| return (value: ValueSelector | string, varKindType: VarKindType) => { | |||
| return (value: ValueSelector | string, varKindType: VarKindType, varInfo?: Var) => { | |||
| const newList = produce(list, (draft) => { | |||
| if (!isSupportConstantValue || varKindType === VarKindType.variable) { | |||
| draft[index].value_selector = value as ValueSelector | |||
| draft[index].value_type = varInfo?.type | |||
| if (isSupportConstantValue) | |||
| draft[index].variable_type = VarKindType.variable | |||
| @@ -14,6 +14,7 @@ import Split from '@/app/components/workflow/nodes/_base/components/split' | |||
| import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor' | |||
| import TypeSelector from '@/app/components/workflow/nodes/_base/components/selector' | |||
| import type { NodePanelProps } from '@/app/components/workflow/types' | |||
| import SyncButton from '@/app/components/base/button/sync-button' | |||
| const i18nPrefix = 'workflow.nodes.code' | |||
| const codeLanguages = [ | |||
| @@ -40,6 +41,7 @@ const Panel: FC<NodePanelProps<CodeNodeType>> = ({ | |||
| handleVarListChange, | |||
| handleAddVariable, | |||
| handleRemoveVariable, | |||
| handleSyncFunctionSignature, | |||
| handleCodeChange, | |||
| handleCodeLanguageChange, | |||
| handleVarsChange, | |||
| @@ -68,7 +70,12 @@ const Panel: FC<NodePanelProps<CodeNodeType>> = ({ | |||
| <Field | |||
| title={t(`${i18nPrefix}.inputVars`)} | |||
| operations={ | |||
| !readOnly ? <AddButton onClick={handleAddVariable} /> : undefined | |||
| !readOnly ? ( | |||
| <div className="flex gap-2"> | |||
| <SyncButton popupContent={t(`${i18nPrefix}.syncFunctionSignature`)} onClick={handleSyncFunctionSignature} /> | |||
| <AddButton onClick={handleAddVariable} /> | |||
| </div> | |||
| ) : undefined | |||
| } | |||
| > | |||
| <VarList | |||
| @@ -84,6 +84,65 @@ const useConfig = (id: string, payload: CodeNodeType) => { | |||
| setInputs(newInputs) | |||
| }, [allLanguageDefault, inputs, setInputs]) | |||
| const handleSyncFunctionSignature = useCallback(() => { | |||
| const generateSyncSignatureCode = (code: string) => { | |||
| let mainDefRe | |||
| let newMainDef | |||
| if (inputs.code_language === CodeLanguage.javascript) { | |||
| mainDefRe = /function\s+main\b\s*\([\s\S]*?\)/g | |||
| newMainDef = 'function main({{var_list}})' | |||
| let param_list = inputs.variables?.map(item => item.variable).join(', ') || '' | |||
| param_list = param_list ? `{${param_list}}` : '' | |||
| newMainDef = newMainDef.replace('{{var_list}}', param_list) | |||
| } | |||
| else if (inputs.code_language === CodeLanguage.python3) { | |||
| mainDefRe = /def\s+main\b\s*\([\s\S]*?\)/g | |||
| const param_list = [] | |||
| for (const item of inputs.variables) { | |||
| let param = item.variable | |||
| let param_type = '' | |||
| switch (item.value_type) { | |||
| case VarType.string: | |||
| param_type = ': str' | |||
| break | |||
| case VarType.number: | |||
| param_type = ': float' | |||
| break | |||
| case VarType.object: | |||
| param_type = ': dict' | |||
| break | |||
| case VarType.array: | |||
| param_type = ': list' | |||
| break | |||
| case VarType.arrayNumber: | |||
| param_type = ': list[float]' | |||
| break | |||
| case VarType.arrayString: | |||
| param_type = ': list[str]' | |||
| break | |||
| case VarType.arrayObject: | |||
| param_type = ': list[dict]' | |||
| break | |||
| } | |||
| param += param_type | |||
| param_list.push(`${param}`) | |||
| } | |||
| newMainDef = `def main(${param_list.join(', ')})` | |||
| } | |||
| else { return code } | |||
| const newCode = code.replace(mainDefRe, newMainDef) | |||
| return newCode | |||
| } | |||
| const newInputs = produce(inputs, (draft) => { | |||
| draft.code = generateSyncSignatureCode(draft.code) | |||
| }) | |||
| setInputs(newInputs) | |||
| }, [inputs, setInputs]) | |||
| const { | |||
| handleVarsChange, | |||
| handleAddVariable: handleAddOutputVariable, | |||
| @@ -119,6 +178,7 @@ const useConfig = (id: string, payload: CodeNodeType) => { | |||
| handleVarListChange, | |||
| handleAddVariable, | |||
| handleRemoveVariable, | |||
| handleSyncFunctionSignature, | |||
| handleCodeChange, | |||
| handleCodeLanguageChange, | |||
| handleVarsChange, | |||
| @@ -136,6 +136,7 @@ export type Variable = { | |||
| variable: string | |||
| } | |||
| value_selector: ValueSelector | |||
| value_type?: VarType | |||
| variable_type?: VarKindType | |||
| value?: string | |||
| options?: string[] | |||
| @@ -549,6 +549,7 @@ const translation = { | |||
| advancedDependencies: 'Advanced Dependencies', | |||
| advancedDependenciesTip: 'Add some preloaded dependencies that take more time to consume or are not default built-in here', | |||
| searchDependencies: 'Search Dependencies', | |||
| syncFunctionSignature: 'Sync function signature to code', | |||
| }, | |||
| templateTransform: { | |||
| inputVars: 'Input Variables', | |||
| @@ -550,6 +550,7 @@ const translation = { | |||
| advancedDependencies: '高度な依存関係', | |||
| advancedDependenciesTip: '消費に時間がかかる、またはデフォルトで組み込まれていない事前ロードされた依存関係を追加します', | |||
| searchDependencies: '依存関係を検索', | |||
| syncFunctionSignature: 'コードの関数署名を同期', | |||
| }, | |||
| templateTransform: { | |||
| inputVars: '入力変数', | |||
| @@ -550,6 +550,7 @@ const translation = { | |||
| advancedDependencies: '高级依赖', | |||
| advancedDependenciesTip: '在这里添加一些预加载需要消耗较多时间或非默认内置的依赖包', | |||
| searchDependencies: '搜索依赖', | |||
| syncFunctionSignature: '同步函数签名至代码', | |||
| }, | |||
| templateTransform: { | |||
| inputVars: '输入变量', | |||
| @@ -544,6 +544,7 @@ const translation = { | |||
| advancedDependencies: '高級依賴', | |||
| advancedDependenciesTip: '在這裡添加一些預加載需要消耗較多時間或非默認內置的依賴包', | |||
| searchDependencies: '搜索依賴', | |||
| syncFunctionSignature: '同步函數簽名至代碼', | |||
| }, | |||
| templateTransform: { | |||
| inputVars: '輸入變量', | |||