feat: last run frontend (#21369)

The frontend of feat: Persist Variables for Enhanced Debugging Workflow (#20699).

Co-authored-by: jZonG <jzongcode@gmail.com>
This commit is contained in:
Joel
2025-06-24 09:10:30 +08:00
committed by GitHub
parent 10b738a296
commit 1a1bfd4048
122 changed files with 5888 additions and 2061 deletions

View File

@@ -1,6 +1,6 @@
import { useCallback, useState } from 'react'
import { useCallback, useRef, useState } from 'react'
import produce from 'immer'
import { useBoolean } from 'ahooks'
import { useBoolean, useDebounceFn } from 'ahooks'
import { v4 as uuid4 } from 'uuid'
import type { ValueSelector, Var } from '../../types'
import { VarType } from '../../types'
@@ -12,8 +12,13 @@ import {
useNodesReadOnly,
useWorkflow,
} from '@/app/components/workflow/hooks'
import useInspectVarsCrud from '../../hooks/use-inspect-vars-crud'
const useConfig = (id: string, payload: VariableAssignerNodeType) => {
const {
deleteNodeInspectorVars,
renameInspectVarName,
} = useInspectVarsCrud()
const { nodesReadOnly: readOnly } = useNodesReadOnly()
const { handleOutVarRenameChange, isVarUsedInNodes, removeUsedVarInNodes } = useWorkflow()
@@ -113,7 +118,8 @@ const useConfig = (id: string, payload: VariableAssignerNodeType) => {
draft.advanced_settings.group_enabled = enabled
})
setInputs(newInputs)
}, [handleOutVarRenameChange, id, inputs, isVarUsedInNodes, setInputs, showRemoveVarConfirm])
deleteNodeInspectorVars(id)
}, [deleteNodeInspectorVars, handleOutVarRenameChange, id, inputs, isVarUsedInNodes, setInputs, showRemoveVarConfirm])
const handleAddGroup = useCallback(() => {
let maxInGroupName = 1
@@ -134,7 +140,22 @@ const useConfig = (id: string, payload: VariableAssignerNodeType) => {
})
})
setInputs(newInputs)
}, [inputs, setInputs])
deleteNodeInspectorVars(id)
}, [deleteNodeInspectorVars, id, inputs, setInputs])
// record the first old name value
const oldNameRecord = useRef<Record<string, string>>({})
const {
run: renameInspectNameWithDebounce,
} = useDebounceFn(
(id: string, newName: string) => {
const oldName = oldNameRecord.current[id]
renameInspectVarName(id, oldName, newName)
delete oldNameRecord.current[id]
},
{ wait: 500 },
)
const handleVarGroupNameChange = useCallback((groupId: string) => {
return (name: string) => {
@@ -144,8 +165,11 @@ const useConfig = (id: string, payload: VariableAssignerNodeType) => {
})
handleOutVarRenameChange(id, [id, inputs.advanced_settings.groups[index].group_name, 'output'], [id, name, 'output'])
setInputs(newInputs)
if(!(id in oldNameRecord.current))
oldNameRecord.current[id] = inputs.advanced_settings.groups[index].group_name
renameInspectNameWithDebounce(id, name)
}
}, [handleOutVarRenameChange, id, inputs, setInputs])
}, [handleOutVarRenameChange, id, inputs, renameInspectNameWithDebounce, setInputs])
const onRemoveVarConfirm = useCallback(() => {
removedVars.forEach((v) => {

View File

@@ -0,0 +1,92 @@
import type { MutableRefObject } from 'react'
import type { InputVar, ValueSelector, Variable } from '@/app/components/workflow/types'
import { useCallback } from 'react'
import type { VariableAssignerNodeType } from './types'
type Params = {
id: string,
payload: VariableAssignerNodeType,
runInputData: Record<string, any>
runInputDataRef: MutableRefObject<Record<string, any>>
getInputVars: (textList: string[]) => InputVar[]
setRunInputData: (data: Record<string, any>) => void
toVarInputs: (variables: Variable[]) => InputVar[]
varSelectorsToVarInputs: (variables: ValueSelector[]) => InputVar[]
}
const useSingleRunFormParams = ({
payload,
runInputData,
setRunInputData,
varSelectorsToVarInputs,
}: Params) => {
const setInputVarValues = useCallback((newPayload: Record<string, any>) => {
setRunInputData(newPayload)
}, [setRunInputData])
const inputVarValues = (() => {
const vars: Record<string, any> = {}
Object.keys(runInputData)
.forEach((key) => {
vars[key] = runInputData[key]
})
return vars
})()
const forms = (() => {
const allInputs: ValueSelector[] = []
const isGroupEnabled = !!payload.advanced_settings?.group_enabled
if (!isGroupEnabled && payload.variables && payload.variables.length) {
payload.variables.forEach((varSelector) => {
allInputs.push(varSelector)
})
}
if (isGroupEnabled && payload.advanced_settings && payload.advanced_settings.groups && payload.advanced_settings.groups.length) {
payload.advanced_settings.groups.forEach((group) => {
group.variables?.forEach((varSelector) => {
allInputs.push(varSelector)
})
})
}
const varInputs = varSelectorsToVarInputs(allInputs)
// remove duplicate inputs
const existVarsKey: Record<string, boolean> = {}
const uniqueVarInputs: InputVar[] = []
varInputs.forEach((input) => {
if(!input)
return
if (!existVarsKey[input.variable]) {
existVarsKey[input.variable] = true
uniqueVarInputs.push({
...input,
required: false, // just one of the inputs is required
})
}
})
return [
{
inputs: uniqueVarInputs,
values: inputVarValues,
onChange: setInputVarValues,
},
]
})()
const getDependentVars = () => {
if(payload.advanced_settings?.group_enabled) {
const vars: ValueSelector[][] = []
payload.advanced_settings.groups.forEach((group) => {
if(group.variables)
vars.push([...group.variables])
})
return vars
}
return [payload.variables]
}
return {
forms,
getDependentVars,
}
}
export default useSingleRunFormParams