feat: change to new end node

This commit is contained in:
Joel 2024-03-14 18:42:55 +08:00
parent d129d7951c
commit d9edcb2250
5 changed files with 90 additions and 127 deletions

View File

@ -1,13 +1,9 @@
import type { NodeDefault } from '../../types' import type { NodeDefault } from '../../types'
import { type EndNodeType, EndVarType } from './types' import { type EndNodeType } from './types'
const nodeDefault: NodeDefault<EndNodeType> = { const nodeDefault: NodeDefault<EndNodeType> = {
defaultValue: { defaultValue: {
outputs: { outputs: [],
type: EndVarType.none,
plain_text_selector: [],
structured_variables: [],
},
}, },
getAvailablePrevNodes() { getAvailablePrevNodes() {
return [] return []

View File

@ -1,26 +1,80 @@
import type { FC } from 'react' import type { FC } from 'react'
import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next'
import type { EndNodeType } from './types' import type { EndNodeType } from './types'
import type { NodeProps } from '@/app/components/workflow/types' import type { NodeProps, ValueSelector, Variable } from '@/app/components/workflow/types'
import { toNodeOutputVars } from '@/app/components/workflow/nodes/_base/components/variable/utils'
const i18nPrefix = 'workflow.nodes.end' import {
useIsChatMode,
useWorkflow,
} from '@/app/components/workflow/hooks'
import { VarBlockIcon } from '@/app/components/workflow/block-icon'
import { Line3 } from '@/app/components/base/icons/src/public/common'
import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development'
import { BlockEnum, VarType } from '@/app/components/workflow/types'
const Node: FC<NodeProps<EndNodeType>> = ({ const Node: FC<NodeProps<EndNodeType>> = ({
id,
data, data,
}) => { }) => {
const { t } = useTranslation() const { getBeforeNodesInSameBranch } = useWorkflow()
const availableNodes = getBeforeNodesInSameBranch(id)
const isChatMode = useIsChatMode()
const outputVars = toNodeOutputVars(availableNodes, isChatMode)
const getNode = (id: string) => {
return availableNodes.find(node => node.id === id)
}
const getVarType = (nodeId: string, value: ValueSelector) => {
const targetVar = outputVars.find(v => v.nodeId === nodeId)
if (!targetVar)
return 'undefined'
let type: VarType = VarType.string
let curr: any = targetVar.vars;
(value).slice(1).forEach((key, i) => {
const isLast = i === value.length - 2
curr = curr.find((v: any) => v.variable === key)
if (isLast) {
type = curr.type
}
else {
if (curr.type === VarType.object)
curr = curr.children
}
})
return type
}
const { outputs } = data const { outputs } = data
return ( return (
<div className='px-3'> <div className='px-3'>
<div className='flex items-center h-6 justify-between bg-gray-100 rounded-md px-1 space-x-1 text-xs font-normal text-gray-700'> {(outputs as Variable[]).map(({ value_selector }, index) => {
<div className='text-xs font-medium text-gray-500 uppercase'> const node = getNode(value_selector[0])
{t(`${i18nPrefix}.outputs`)} const varName = value_selector[value_selector.length - 1]
</div> return (
<div className='text-xs font-normal text-gray-700'> <div key={index} className='flex items-center h-6 justify-between bg-gray-100 rounded-md px-1 space-x-1 text-xs font-normal text-gray-700'>
{t(`${i18nPrefix}.type.${outputs.type}`)} <div className='flex items-center text-xs font-medium text-gray-500'>
</div> <div className='p-[1px]'>
</div> <VarBlockIcon
className='!text-gray-900'
type={node?.data.type || BlockEnum.Tool}
/>
</div>
<div>{node?.data.title}</div>
<Line3 className='mr-0.5'></Line3>
<div className='flex items-center text-primary-600'>
<Variable02 className='w-3.5 h-3.5' />
<div className='ml-0.5 text-xs font-medium'>{varName}</div>
</div>
</div>
<div className='text-xs font-normal text-gray-700'>
<div className='ml-0.5 text-xs font-normal text-gray-500 capitalize'>{getVarType(node?.id || '', value_selector)}</div>
</div>
</div>
)
})}
</div> </div>
) )
} }

View File

@ -1,11 +1,8 @@
import { type FC, useCallback } from 'react' import { type FC } from 'react'
import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import cn from 'classnames'
import VarReferencePicker from '../_base/components/variable/var-reference-picker'
import useConfig from './use-config' import useConfig from './use-config'
import type { EndNodeType } from './types' import type { EndNodeType } from './types'
import { EndVarType } from './types'
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 Field from '@/app/components/workflow/nodes/_base/components/field' import Field from '@/app/components/workflow/nodes/_base/components/field'
import AddButton from '@/app/components/base/button/add-button' import AddButton from '@/app/components/base/button/add-button'
@ -13,29 +10,6 @@ import { type NodePanelProps } from '@/app/components/workflow/types'
const i18nPrefix = 'workflow.nodes.end' const i18nPrefix = 'workflow.nodes.end'
const TypeItem = ({ type, current, onClick }: { type: EndVarType; current: EndVarType; onClick: (type: EndVarType) => void }) => {
const { t } = useTranslation()
const handleOnClick = useCallback(() => {
if (type === current)
return
onClick(type)
}, [type, current, onClick])
return (
<div
onClick={handleOnClick}
className={cn(
'grow flex items-center h-8 justify-center cursor-pointer rounded-lg bg-gray-25 text-[13px] font-normal text-gray-900',
type === current ? 'border-[1.5px] border-primary-400' : 'border border-gray-100',
)}
>
{t(`${i18nPrefix}.type.${type}`)}
</div>
)
}
const allTypes = [EndVarType.plainText, EndVarType.structured, EndVarType.none]
const Panel: FC<NodePanelProps<EndNodeType>> = ({ const Panel: FC<NodePanelProps<EndNodeType>> = ({
id, id,
data, data,
@ -45,9 +19,7 @@ const Panel: FC<NodePanelProps<EndNodeType>> = ({
const { const {
inputs, inputs,
handleOutputTypeChange,
handleVarListChange, handleVarListChange,
handelPlainTextSelectorChange,
handleAddVariable, handleAddVariable,
} = useConfig(id, data) } = useConfig(id, data)
@ -55,49 +27,20 @@ const Panel: FC<NodePanelProps<EndNodeType>> = ({
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'>
<Field
title={t(`${i18nPrefix}.output.type`)}
>
<div className='flex space-x-2'>
{allTypes.map(type => (
<TypeItem
key={type}
type={type}
current={outputs.type}
onClick={handleOutputTypeChange}
/>
))}
</div>
</Field>
{outputs.type !== EndVarType.none && (
<Field
title={t(`${i18nPrefix}.output.variable`)}
operations={
outputs.type === EndVarType.structured ? <AddButton onClick={handleAddVariable} /> : undefined
}
>
{outputs.type
=== EndVarType.structured
? (
<VarList
nodeId={id}
readonly={readOnly}
list={outputs.structured_variables!}
onChange={handleVarListChange}
/>
)
: (
<VarReferencePicker
isShowNodeName
nodeId={id}
readonly={readOnly}
value={outputs.plain_text_selector!}
onChange={handelPlainTextSelectorChange}
/>
)}
</Field> <Field
)} title={t(`${i18nPrefix}.output.variable`)}
operations={
<AddButton onClick={handleAddVariable} />
}
>
<VarList
nodeId={id}
readonly={readOnly}
list={outputs}
onChange={handleVarListChange}
/>
</Field>
</div> </div>
</div> </div>
) )

View File

@ -1,15 +1,5 @@
import type { CommonNodeType, Variable } from '@/app/components/workflow/types' import type { CommonNodeType, Variable } from '@/app/components/workflow/types'
export enum EndVarType {
none = 'none',
plainText = 'plain-text',
structured = 'structured',
}
export type OutPuts = {
type: EndVarType
plain_text_selector?: string[]
structured_variables?: Variable[]
}
export type EndNodeType = CommonNodeType & { export type EndNodeType = CommonNodeType & {
outputs: OutPuts outputs: Variable[]
} }

View File

@ -1,41 +1,21 @@
import produce from 'immer'
import { useCallback } from 'react'
import useVarList from '../_base/hooks/use-var-list' import useVarList from '../_base/hooks/use-var-list'
import type { EndNodeType, EndVarType, OutPuts } from './types' import type { EndNodeType } from './types'
import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud' import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
const useConfig = (id: string, payload: EndNodeType) => { const useConfig = (id: string, payload: EndNodeType) => {
const { inputs, setInputs } = useNodeCrud<EndNodeType>(id, payload) const { inputs, setInputs } = useNodeCrud<EndNodeType>(id, payload)
const handleOutputTypeChange = useCallback((type: EndVarType) => {
const newInputs = produce(inputs, (draft: any) => {
draft.outputs.type = type
})
setInputs(newInputs)
}, [inputs, setInputs])
const handelPlainTextSelectorChange = useCallback((newList: string[] | string) => { const { handleVarListChange, handleAddVariable } = useVarList<EndNodeType>({
const newInputs = produce(inputs, (draft: any) => { inputs,
draft.outputs.plain_text_selector = newList as string[] setInputs: (newInputs) => {
})
setInputs(newInputs)
}
, [inputs, setInputs])
const { handleVarListChange, handleAddVariable } = useVarList<OutPuts>({
inputs: inputs.outputs,
setInputs: (newOutputs) => {
const newInputs = produce(inputs, (draft: any) => {
draft.outputs = newOutputs
})
setInputs(newInputs) setInputs(newInputs)
}, },
varKey: 'structured_variables', varKey: 'outputs',
}) })
console.log(inputs)
return { return {
inputs, inputs,
handleOutputTypeChange,
handelPlainTextSelectorChange,
handleVarListChange, handleVarListChange,
handleAddVariable, handleAddVariable,
} }