feat: synchronize input/output variables in the panel with generated code by the code generator (#10150)
This commit is contained in:
parent
fafa5938da
commit
f674de4f5d
@ -31,6 +31,7 @@ export type Props = {
|
|||||||
noWrapper?: boolean
|
noWrapper?: boolean
|
||||||
isExpand?: boolean
|
isExpand?: boolean
|
||||||
showFileList?: boolean
|
showFileList?: boolean
|
||||||
|
onGenerated?: (value: string) => void
|
||||||
showCodeGenerator?: boolean
|
showCodeGenerator?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ const CodeEditor: FC<Props> = ({
|
|||||||
noWrapper,
|
noWrapper,
|
||||||
isExpand,
|
isExpand,
|
||||||
showFileList,
|
showFileList,
|
||||||
|
onGenerated,
|
||||||
showCodeGenerator = false,
|
showCodeGenerator = false,
|
||||||
}) => {
|
}) => {
|
||||||
const [isFocus, setIsFocus] = React.useState(false)
|
const [isFocus, setIsFocus] = React.useState(false)
|
||||||
@ -151,9 +153,6 @@ const CodeEditor: FC<Props> = ({
|
|||||||
|
|
||||||
return isFocus ? 'focus-theme' : 'blur-theme'
|
return isFocus ? 'focus-theme' : 'blur-theme'
|
||||||
})()
|
})()
|
||||||
const handleGenerated = (code: string) => {
|
|
||||||
handleEditorChange(code)
|
|
||||||
}
|
|
||||||
|
|
||||||
const main = (
|
const main = (
|
||||||
<>
|
<>
|
||||||
@ -205,7 +204,7 @@ const CodeEditor: FC<Props> = ({
|
|||||||
isFocus={isFocus && !readOnly}
|
isFocus={isFocus && !readOnly}
|
||||||
minHeight={minHeight}
|
minHeight={minHeight}
|
||||||
isInNode={isInNode}
|
isInNode={isInNode}
|
||||||
onGenerated={handleGenerated}
|
onGenerated={onGenerated}
|
||||||
codeLanguages={language}
|
codeLanguages={language}
|
||||||
fileList={fileList}
|
fileList={fileList}
|
||||||
showFileList={showFileList}
|
showFileList={showFileList}
|
||||||
|
326
web/app/components/workflow/nodes/code/code-parser.spec.ts
Normal file
326
web/app/components/workflow/nodes/code/code-parser.spec.ts
Normal file
@ -0,0 +1,326 @@
|
|||||||
|
import { VarType } from '../../types'
|
||||||
|
import { extractFunctionParams, extractReturnType } from './code-parser'
|
||||||
|
import { CodeLanguage } from './types'
|
||||||
|
|
||||||
|
const SAMPLE_CODES = {
|
||||||
|
python3: {
|
||||||
|
noParams: 'def main():',
|
||||||
|
singleParam: 'def main(param1):',
|
||||||
|
multipleParams: `def main(param1, param2, param3):
|
||||||
|
return {"result": param1}`,
|
||||||
|
withTypes: `def main(param1: str, param2: int, param3: List[str]):
|
||||||
|
result = process_data(param1, param2)
|
||||||
|
return {"output": result}`,
|
||||||
|
withDefaults: `def main(param1: str = "default", param2: int = 0):
|
||||||
|
return {"data": param1}`,
|
||||||
|
},
|
||||||
|
javascript: {
|
||||||
|
noParams: 'function main() {',
|
||||||
|
singleParam: 'function main(param1) {',
|
||||||
|
multipleParams: `function main(param1, param2, param3) {
|
||||||
|
return { result: param1 }
|
||||||
|
}`,
|
||||||
|
withComments: `// Main function
|
||||||
|
function main(param1, param2) {
|
||||||
|
// Process data
|
||||||
|
return { output: process(param1, param2) }
|
||||||
|
}`,
|
||||||
|
withSpaces: 'function main( param1 , param2 ) {',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('extractFunctionParams', () => {
|
||||||
|
describe('Python3', () => {
|
||||||
|
test('handles no parameters', () => {
|
||||||
|
const result = extractFunctionParams(SAMPLE_CODES.python3.noParams, CodeLanguage.python3)
|
||||||
|
expect(result).toEqual([])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('extracts single parameter', () => {
|
||||||
|
const result = extractFunctionParams(SAMPLE_CODES.python3.singleParam, CodeLanguage.python3)
|
||||||
|
expect(result).toEqual(['param1'])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('extracts multiple parameters', () => {
|
||||||
|
const result = extractFunctionParams(SAMPLE_CODES.python3.multipleParams, CodeLanguage.python3)
|
||||||
|
expect(result).toEqual(['param1', 'param2', 'param3'])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('handles type hints', () => {
|
||||||
|
const result = extractFunctionParams(SAMPLE_CODES.python3.withTypes, CodeLanguage.python3)
|
||||||
|
expect(result).toEqual(['param1', 'param2', 'param3'])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('handles default values', () => {
|
||||||
|
const result = extractFunctionParams(SAMPLE_CODES.python3.withDefaults, CodeLanguage.python3)
|
||||||
|
expect(result).toEqual(['param1', 'param2'])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// JavaScriptのテストケース
|
||||||
|
describe('JavaScript', () => {
|
||||||
|
test('handles no parameters', () => {
|
||||||
|
const result = extractFunctionParams(SAMPLE_CODES.javascript.noParams, CodeLanguage.javascript)
|
||||||
|
expect(result).toEqual([])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('extracts single parameter', () => {
|
||||||
|
const result = extractFunctionParams(SAMPLE_CODES.javascript.singleParam, CodeLanguage.javascript)
|
||||||
|
expect(result).toEqual(['param1'])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('extracts multiple parameters', () => {
|
||||||
|
const result = extractFunctionParams(SAMPLE_CODES.javascript.multipleParams, CodeLanguage.javascript)
|
||||||
|
expect(result).toEqual(['param1', 'param2', 'param3'])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('handles comments in code', () => {
|
||||||
|
const result = extractFunctionParams(SAMPLE_CODES.javascript.withComments, CodeLanguage.javascript)
|
||||||
|
expect(result).toEqual(['param1', 'param2'])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('handles whitespace', () => {
|
||||||
|
const result = extractFunctionParams(SAMPLE_CODES.javascript.withSpaces, CodeLanguage.javascript)
|
||||||
|
expect(result).toEqual(['param1', 'param2'])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const RETURN_TYPE_SAMPLES = {
|
||||||
|
python3: {
|
||||||
|
singleReturn: `
|
||||||
|
def main(param1):
|
||||||
|
return {"result": "value"}`,
|
||||||
|
|
||||||
|
multipleReturns: `
|
||||||
|
def main(param1, param2):
|
||||||
|
return {"result": "value", "status": "success"}`,
|
||||||
|
|
||||||
|
noReturn: `
|
||||||
|
def main():
|
||||||
|
print("Hello")`,
|
||||||
|
|
||||||
|
complexReturn: `
|
||||||
|
def main():
|
||||||
|
data = process()
|
||||||
|
return {"result": data, "count": 42, "messages": ["hello"]}`,
|
||||||
|
nestedObject: `
|
||||||
|
def main(name, age, city):
|
||||||
|
return {
|
||||||
|
'personal_info': {
|
||||||
|
'name': name,
|
||||||
|
'age': age,
|
||||||
|
'city': city
|
||||||
|
},
|
||||||
|
'timestamp': int(time.time()),
|
||||||
|
'status': 'active'
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
|
||||||
|
javascript: {
|
||||||
|
singleReturn: `
|
||||||
|
function main(param1) {
|
||||||
|
return { result: "value" }
|
||||||
|
}`,
|
||||||
|
|
||||||
|
multipleReturns: `
|
||||||
|
function main(param1) {
|
||||||
|
return { result: "value", status: "success" }
|
||||||
|
}`,
|
||||||
|
|
||||||
|
withParentheses: `
|
||||||
|
function main() {
|
||||||
|
return ({ result: "value", status: "success" })
|
||||||
|
}`,
|
||||||
|
|
||||||
|
noReturn: `
|
||||||
|
function main() {
|
||||||
|
console.log("Hello")
|
||||||
|
}`,
|
||||||
|
|
||||||
|
withQuotes: `
|
||||||
|
function main() {
|
||||||
|
return { "result": 'value', 'status': "success" }
|
||||||
|
}`,
|
||||||
|
nestedObject: `
|
||||||
|
function main(name, age, city) {
|
||||||
|
return {
|
||||||
|
personal_info: {
|
||||||
|
name: name,
|
||||||
|
age: age,
|
||||||
|
city: city
|
||||||
|
},
|
||||||
|
timestamp: Date.now(),
|
||||||
|
status: 'active'
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
withJSDoc: `
|
||||||
|
/**
|
||||||
|
* Creates a user profile with personal information and metadata
|
||||||
|
* @param {string} name - The user's name
|
||||||
|
* @param {number} age - The user's age
|
||||||
|
* @param {string} city - The user's city of residence
|
||||||
|
* @returns {Object} An object containing the user profile
|
||||||
|
*/
|
||||||
|
function main(name, age, city) {
|
||||||
|
return {
|
||||||
|
result: {
|
||||||
|
personal_info: {
|
||||||
|
name: name,
|
||||||
|
age: age,
|
||||||
|
city: city
|
||||||
|
},
|
||||||
|
timestamp: Date.now(),
|
||||||
|
status: 'active'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}`,
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('extractReturnType', () => {
|
||||||
|
// Python3のテスト
|
||||||
|
describe('Python3', () => {
|
||||||
|
test('extracts single return value', () => {
|
||||||
|
const result = extractReturnType(RETURN_TYPE_SAMPLES.python3.singleReturn, CodeLanguage.python3)
|
||||||
|
expect(result).toEqual({
|
||||||
|
result: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('extracts multiple return values', () => {
|
||||||
|
const result = extractReturnType(RETURN_TYPE_SAMPLES.python3.multipleReturns, CodeLanguage.python3)
|
||||||
|
expect(result).toEqual({
|
||||||
|
result: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('returns empty object when no return statement', () => {
|
||||||
|
const result = extractReturnType(RETURN_TYPE_SAMPLES.python3.noReturn, CodeLanguage.python3)
|
||||||
|
expect(result).toEqual({})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('handles complex return statement', () => {
|
||||||
|
const result = extractReturnType(RETURN_TYPE_SAMPLES.python3.complexReturn, CodeLanguage.python3)
|
||||||
|
expect(result).toEqual({
|
||||||
|
result: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
count: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
messages: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
test('handles nested object structure', () => {
|
||||||
|
const result = extractReturnType(RETURN_TYPE_SAMPLES.python3.nestedObject, CodeLanguage.python3)
|
||||||
|
expect(result).toEqual({
|
||||||
|
personal_info: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
timestamp: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// JavaScriptのテスト
|
||||||
|
describe('JavaScript', () => {
|
||||||
|
test('extracts single return value', () => {
|
||||||
|
const result = extractReturnType(RETURN_TYPE_SAMPLES.javascript.singleReturn, CodeLanguage.javascript)
|
||||||
|
expect(result).toEqual({
|
||||||
|
result: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('extracts multiple return values', () => {
|
||||||
|
const result = extractReturnType(RETURN_TYPE_SAMPLES.javascript.multipleReturns, CodeLanguage.javascript)
|
||||||
|
expect(result).toEqual({
|
||||||
|
result: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('handles return with parentheses', () => {
|
||||||
|
const result = extractReturnType(RETURN_TYPE_SAMPLES.javascript.withParentheses, CodeLanguage.javascript)
|
||||||
|
expect(result).toEqual({
|
||||||
|
result: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('returns empty object when no return statement', () => {
|
||||||
|
const result = extractReturnType(RETURN_TYPE_SAMPLES.javascript.noReturn, CodeLanguage.javascript)
|
||||||
|
expect(result).toEqual({})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('handles quoted keys', () => {
|
||||||
|
const result = extractReturnType(RETURN_TYPE_SAMPLES.javascript.withQuotes, CodeLanguage.javascript)
|
||||||
|
expect(result).toEqual({
|
||||||
|
result: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
test('handles nested object structure', () => {
|
||||||
|
const result = extractReturnType(RETURN_TYPE_SAMPLES.javascript.nestedObject, CodeLanguage.javascript)
|
||||||
|
expect(result).toEqual({
|
||||||
|
personal_info: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
timestamp: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
86
web/app/components/workflow/nodes/code/code-parser.ts
Normal file
86
web/app/components/workflow/nodes/code/code-parser.ts
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import { VarType } from '../../types'
|
||||||
|
import type { OutputVar } from './types'
|
||||||
|
import { CodeLanguage } from './types'
|
||||||
|
|
||||||
|
export const extractFunctionParams = (code: string, language: CodeLanguage) => {
|
||||||
|
if (language === CodeLanguage.json)
|
||||||
|
return []
|
||||||
|
|
||||||
|
const patterns: Record<Exclude<CodeLanguage, CodeLanguage.json>, RegExp> = {
|
||||||
|
[CodeLanguage.python3]: /def\s+main\s*\((.*?)\)/,
|
||||||
|
[CodeLanguage.javascript]: /function\s+main\s*\((.*?)\)/,
|
||||||
|
}
|
||||||
|
const match = code.match(patterns[language])
|
||||||
|
const params: string[] = []
|
||||||
|
|
||||||
|
if (match?.[1]) {
|
||||||
|
params.push(...match[1].split(',')
|
||||||
|
.map(p => p.trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
.map(p => p.split(':')[0].trim()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
export const extractReturnType = (code: string, language: CodeLanguage): OutputVar => {
|
||||||
|
const codeWithoutComments = code.replace(/\/\*\*[\s\S]*?\*\//, '')
|
||||||
|
console.log(codeWithoutComments)
|
||||||
|
|
||||||
|
const returnIndex = codeWithoutComments.indexOf('return')
|
||||||
|
if (returnIndex === -1)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
// returnから始まる部分文字列を取得
|
||||||
|
const codeAfterReturn = codeWithoutComments.slice(returnIndex)
|
||||||
|
|
||||||
|
let bracketCount = 0
|
||||||
|
let startIndex = codeAfterReturn.indexOf('{')
|
||||||
|
|
||||||
|
if (language === CodeLanguage.javascript && startIndex === -1) {
|
||||||
|
const parenStart = codeAfterReturn.indexOf('(')
|
||||||
|
if (parenStart !== -1)
|
||||||
|
startIndex = codeAfterReturn.indexOf('{', parenStart)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startIndex === -1)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
let endIndex = -1
|
||||||
|
|
||||||
|
for (let i = startIndex; i < codeAfterReturn.length; i++) {
|
||||||
|
if (codeAfterReturn[i] === '{')
|
||||||
|
bracketCount++
|
||||||
|
if (codeAfterReturn[i] === '}') {
|
||||||
|
bracketCount--
|
||||||
|
if (bracketCount === 0) {
|
||||||
|
endIndex = i + 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endIndex === -1)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
const returnContent = codeAfterReturn.slice(startIndex + 1, endIndex - 1)
|
||||||
|
console.log(returnContent)
|
||||||
|
|
||||||
|
const result: OutputVar = {}
|
||||||
|
|
||||||
|
const keyRegex = /['"]?(\w+)['"]?\s*:(?![^{]*})/g
|
||||||
|
const matches = returnContent.matchAll(keyRegex)
|
||||||
|
|
||||||
|
for (const match of matches) {
|
||||||
|
console.log(`Found key: "${match[1]}" from match: "${match[0]}"`)
|
||||||
|
const key = match[1]
|
||||||
|
result[key] = {
|
||||||
|
type: VarType.string,
|
||||||
|
children: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(result)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
@ -5,6 +5,7 @@ import RemoveEffectVarConfirm from '../_base/components/remove-effect-var-confir
|
|||||||
import useConfig from './use-config'
|
import useConfig from './use-config'
|
||||||
import type { CodeNodeType } from './types'
|
import type { CodeNodeType } from './types'
|
||||||
import { CodeLanguage } from './types'
|
import { CodeLanguage } from './types'
|
||||||
|
import { extractFunctionParams, extractReturnType } from './code-parser'
|
||||||
import VarList from '@/app/components/workflow/nodes/_base/components/variable/var-list'
|
import VarList from '@/app/components/workflow/nodes/_base/components/variable/var-list'
|
||||||
import OutputVarList from '@/app/components/workflow/nodes/_base/components/variable/output-var-list'
|
import OutputVarList from '@/app/components/workflow/nodes/_base/components/variable/output-var-list'
|
||||||
import AddButton from '@/app/components/base/button/add-button'
|
import AddButton from '@/app/components/base/button/add-button'
|
||||||
@ -12,10 +13,9 @@ import Field from '@/app/components/workflow/nodes/_base/components/field'
|
|||||||
import Split from '@/app/components/workflow/nodes/_base/components/split'
|
import Split from '@/app/components/workflow/nodes/_base/components/split'
|
||||||
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
|
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
|
||||||
import TypeSelector from '@/app/components/workflow/nodes/_base/components/selector'
|
import TypeSelector from '@/app/components/workflow/nodes/_base/components/selector'
|
||||||
import type { NodePanelProps } from '@/app/components/workflow/types'
|
import { type NodePanelProps } from '@/app/components/workflow/types'
|
||||||
import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form'
|
import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form'
|
||||||
import ResultPanel from '@/app/components/workflow/run/result-panel'
|
import ResultPanel from '@/app/components/workflow/run/result-panel'
|
||||||
|
|
||||||
const i18nPrefix = 'workflow.nodes.code'
|
const i18nPrefix = 'workflow.nodes.code'
|
||||||
|
|
||||||
const codeLanguages = [
|
const codeLanguages = [
|
||||||
@ -38,6 +38,7 @@ const Panel: FC<NodePanelProps<CodeNodeType>> = ({
|
|||||||
readOnly,
|
readOnly,
|
||||||
inputs,
|
inputs,
|
||||||
outputKeyOrders,
|
outputKeyOrders,
|
||||||
|
handleCodeAndVarsChange,
|
||||||
handleVarListChange,
|
handleVarListChange,
|
||||||
handleAddVariable,
|
handleAddVariable,
|
||||||
handleRemoveVariable,
|
handleRemoveVariable,
|
||||||
@ -61,6 +62,18 @@ const Panel: FC<NodePanelProps<CodeNodeType>> = ({
|
|||||||
setInputVarValues,
|
setInputVarValues,
|
||||||
} = useConfig(id, data)
|
} = useConfig(id, data)
|
||||||
|
|
||||||
|
const handleGeneratedCode = (value: string) => {
|
||||||
|
const params = extractFunctionParams(value, inputs.code_language)
|
||||||
|
const codeNewInput = params.map((p) => {
|
||||||
|
return {
|
||||||
|
variable: p,
|
||||||
|
value_selector: [],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const returnTypes = extractReturnType(value, inputs.code_language)
|
||||||
|
handleCodeAndVarsChange(value, codeNewInput, returnTypes)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='mt-2'>
|
<div className='mt-2'>
|
||||||
<div className='px-4 pb-4 space-y-4'>
|
<div className='px-4 pb-4 space-y-4'>
|
||||||
@ -92,6 +105,7 @@ const Panel: FC<NodePanelProps<CodeNodeType>> = ({
|
|||||||
language={inputs.code_language}
|
language={inputs.code_language}
|
||||||
value={inputs.code}
|
value={inputs.code}
|
||||||
onChange={handleCodeChange}
|
onChange={handleCodeChange}
|
||||||
|
onGenerated={handleGeneratedCode}
|
||||||
showCodeGenerator={true}
|
showCodeGenerator={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,7 +3,7 @@ import produce from 'immer'
|
|||||||
import useVarList from '../_base/hooks/use-var-list'
|
import useVarList from '../_base/hooks/use-var-list'
|
||||||
import useOutputVarList from '../_base/hooks/use-output-var-list'
|
import useOutputVarList from '../_base/hooks/use-output-var-list'
|
||||||
import { BlockEnum, VarType } from '../../types'
|
import { BlockEnum, VarType } from '../../types'
|
||||||
import type { Var } from '../../types'
|
import type { Var, Variable } from '../../types'
|
||||||
import { useStore } from '../../store'
|
import { useStore } from '../../store'
|
||||||
import type { CodeNodeType, OutputVar } from './types'
|
import type { CodeNodeType, OutputVar } from './types'
|
||||||
import { CodeLanguage } from './types'
|
import { CodeLanguage } from './types'
|
||||||
@ -136,7 +136,15 @@ const useConfig = (id: string, payload: CodeNodeType) => {
|
|||||||
const setInputVarValues = useCallback((newPayload: Record<string, any>) => {
|
const setInputVarValues = useCallback((newPayload: Record<string, any>) => {
|
||||||
setRunInputData(newPayload)
|
setRunInputData(newPayload)
|
||||||
}, [setRunInputData])
|
}, [setRunInputData])
|
||||||
|
const handleCodeAndVarsChange = useCallback((code: string, inputVariables: Variable[], outputVariables: OutputVar) => {
|
||||||
|
const newInputs = produce(inputs, (draft) => {
|
||||||
|
draft.code = code
|
||||||
|
draft.variables = inputVariables
|
||||||
|
draft.outputs = outputVariables
|
||||||
|
})
|
||||||
|
setInputs(newInputs)
|
||||||
|
syncOutputKeyOrders(outputVariables)
|
||||||
|
}, [inputs, setInputs, syncOutputKeyOrders])
|
||||||
return {
|
return {
|
||||||
readOnly,
|
readOnly,
|
||||||
inputs,
|
inputs,
|
||||||
@ -163,6 +171,7 @@ const useConfig = (id: string, payload: CodeNodeType) => {
|
|||||||
inputVarValues,
|
inputVarValues,
|
||||||
setInputVarValues,
|
setInputVarValues,
|
||||||
runResult,
|
runResult,
|
||||||
|
handleCodeAndVarsChange,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user