available nodes

This commit is contained in:
StyleZhang
2024-03-15 13:24:09 +08:00
parent 8d9c86ac4c
commit 5fbf8ee6c6
17 changed files with 165 additions and 38 deletions

View File

@ -3,23 +3,33 @@ import {
useCallback,
} from 'react'
import { useTranslation } from 'react-i18next'
import { useNodesInteractions } from '@/app/components/workflow/hooks'
import {
useNodesExtraData,
useNodesInteractions,
} from '@/app/components/workflow/hooks'
import BlockSelector from '@/app/components/workflow/block-selector'
import { Plus } from '@/app/components/base/icons/src/vender/line/general'
import type { OnSelectBlock } from '@/app/components/workflow/types'
import type {
BlockEnum,
OnSelectBlock,
} from '@/app/components/workflow/types'
type AddProps = {
nodeId: string
nodeType: BlockEnum
sourceHandle: string
branchName?: string
}
const Add = ({
nodeId,
nodeType,
sourceHandle,
branchName,
}: AddProps) => {
const { t } = useTranslation()
const { handleNodeAdd } = useNodesInteractions()
const nodesExtraData = useNodesExtraData()
const availableNextNodes = nodesExtraData[nodeType].availableNextNodes
const handleSelect = useCallback<OnSelectBlock>((type, toolDefaultValue) => {
handleNodeAdd(
@ -65,6 +75,7 @@ const Add = ({
offset={0}
trigger={renderTrigger}
popupClassName='!w-[328px]'
availableBlocksTypes={availableNextNodes}
/>
)
}

View File

@ -51,6 +51,7 @@ const NextStep = ({
!nodeWithBranches && !outgoers.length && (
<Add
nodeId={selectedNode!.id}
nodeType={selectedNode!.data.type}
sourceHandle='source'
/>
)
@ -81,6 +82,7 @@ const NextStep = ({
<Add
key={branch.id}
nodeId={selectedNode!.id}
nodeType={selectedNode!.data.type}
sourceHandle={branch.id}
branchName={branch.name}
/>

View File

@ -3,13 +3,17 @@ import {
useCallback,
} from 'react'
import { useTranslation } from 'react-i18next'
import { union } from 'lodash-es'
import type {
CommonNodeType,
OnSelectBlock,
} from '@/app/components/workflow/types'
import BlockIcon from '@/app/components/workflow/block-icon'
import BlockSelector from '@/app/components/workflow/block-selector'
import { useNodesInteractions } from '@/app/components/workflow/hooks'
import {
useNodesExtraData,
useNodesInteractions,
} from '@/app/components/workflow/hooks'
import Button from '@/app/components/base/button'
type ItemProps = {
@ -26,6 +30,9 @@ const Item = ({
}: ItemProps) => {
const { t } = useTranslation()
const { handleNodeChange } = useNodesInteractions()
const nodesExtraData = useNodesExtraData()
const availablePrevNodes = nodesExtraData[data.type].availablePrevNodes
const availableNextNodes = nodesExtraData[data.type].availableNextNodes
const handleSelect = useCallback<OnSelectBlock>((type, toolDefaultValue) => {
handleNodeChange(nodeId, type, sourceHandle, toolDefaultValue)
}, [nodeId, sourceHandle, handleNodeChange])
@ -68,6 +75,7 @@ const Item = ({
}}
trigger={renderTrigger}
popupClassName='!w-[328px]'
availableBlocksTypes={union(availablePrevNodes, availableNextNodes)}
/>
</div>
)

View File

@ -13,7 +13,10 @@ import { BlockEnum } from '../../../types'
import type { Node } from '../../../types'
import BlockSelector from '../../../block-selector'
import type { ToolDefaultValue } from '../../../block-selector/types'
import { useNodesInteractions } from '../../../hooks'
import {
useNodesExtraData,
useNodesInteractions,
} from '../../../hooks'
import { useStore } from '../../../store'
type NodeHandleProps = {
@ -31,7 +34,10 @@ export const NodeTargetHandle = memo(({
}: NodeHandleProps) => {
const [open, setOpen] = useState(false)
const { handleNodeAdd } = useNodesInteractions()
const nodesExtraData = useNodesExtraData()
const connected = data._connectedTargetHandleIds?.includes(handleId)
const availablePrevNodes = nodesExtraData[data.type].availablePrevNodes
const isConnectable = !!availablePrevNodes.length
const handleOpenChange = useCallback((v: boolean) => {
setOpen(v)
@ -67,11 +73,11 @@ export const NodeTargetHandle = memo(({
${data.type === BlockEnum.Start && 'opacity-0'}
${handleClassName}
`}
isConnectable={data.type !== BlockEnum.Start}
isConnectable={isConnectable}
onClick={handleHandleClick}
>
{
!connected && data.type !== BlockEnum.Start && (
!connected && isConnectable && (
<BlockSelector
open={open}
onOpenChange={handleOpenChange}
@ -84,6 +90,7 @@ export const NodeTargetHandle = memo(({
group-hover:flex
${open && '!flex'}
`}
availableBlocksTypes={availablePrevNodes}
/>
)
}
@ -103,6 +110,9 @@ export const NodeSourceHandle = memo(({
const notInitialWorkflow = useStore(s => s.notInitialWorkflow)
const [open, setOpen] = useState(false)
const { handleNodeAdd } = useNodesInteractions()
const nodesExtraData = useNodesExtraData()
const availableNextNodes = nodesExtraData[data.type].availableNextNodes
const isConnectable = !!availableNextNodes.length
const connected = data._connectedSourceHandleIds?.includes(handleId)
const handleOpenChange = useCallback((v: boolean) => {
setOpen(v)
@ -142,10 +152,11 @@ export const NodeSourceHandle = memo(({
${!connected && 'after:opacity-0'}
${handleClassName}
`}
isConnectable={isConnectable}
onClick={handleHandleClick}
>
{
!connected && (
!connected && isConnectable && (
<BlockSelector
open={open}
onOpenChange={handleOpenChange}
@ -157,6 +168,7 @@ export const NodeSourceHandle = memo(({
group-hover:flex
${open && '!flex'}
`}
availableBlocksTypes={availableNextNodes}
/>
)
}

View File

@ -3,20 +3,32 @@ import {
useCallback,
} from 'react'
import { useTranslation } from 'react-i18next'
import { union } from 'lodash-es'
import BlockSelector from '@/app/components/workflow/block-selector'
import { useNodesInteractions } from '@/app/components/workflow/hooks'
import type { OnSelectBlock } from '@/app/components/workflow/types'
import {
useNodesExtraData,
useNodesInteractions,
} from '@/app/components/workflow/hooks'
import type {
BlockEnum,
OnSelectBlock,
} from '@/app/components/workflow/types'
type ChangeBlockProps = {
nodeId: string
nodeType: BlockEnum
sourceHandle: string
}
const ChangeBlock = ({
nodeId,
nodeType,
sourceHandle,
}: ChangeBlockProps) => {
const { t } = useTranslation()
const { handleNodeChange } = useNodesInteractions()
const nodesExtraData = useNodesExtraData()
const availablePrevNodes = nodesExtraData[nodeType].availablePrevNodes
const availableNextNodes = nodesExtraData[nodeType].availableNextNodes
const handleSelect = useCallback<OnSelectBlock>((type, toolDefaultValue) => {
handleNodeChange(nodeId, type, sourceHandle, toolDefaultValue)
@ -39,6 +51,7 @@ const ChangeBlock = ({
}}
onSelect={handleSelect}
trigger={renderTrigger}
availableBlocksTypes={union(availablePrevNodes, availableNextNodes)}
/>
)
}

View File

@ -129,6 +129,7 @@ const PanelOperator = ({
data.type !== BlockEnum.Start && (
<ChangeBlock
nodeId={id}
nodeType={data.type}
sourceHandle={edge?.sourceHandle || 'source'}
/>
)

View File

@ -20,6 +20,7 @@ import {
import BlockIcon from '@/app/components/workflow/block-icon'
import {
useNodeDataUpdate,
useNodesExtraData,
useNodesInteractions,
} from '@/app/components/workflow/hooks'
import { canRunBySingle } from '@/app/components/workflow/utils'
@ -27,7 +28,6 @@ import { GitBranch01 } from '@/app/components/base/icons/src/vender/line/develop
import { Play } from '@/app/components/base/icons/src/vender/line/mediaAndDevices'
import TooltipPlus from '@/app/components/base/tooltip-plus'
import type { Node } from '@/app/components/workflow/types'
import { BlockEnum } from '@/app/components/workflow/types'
type BasePanelProps = {
children: ReactElement
@ -40,6 +40,9 @@ const BasePanel: FC<BasePanelProps> = ({
}) => {
const { t } = useTranslation()
const { handleNodeSelect } = useNodesInteractions()
const nodesExtraData = useNodesExtraData()
const availableNextNodes = nodesExtraData[data.type].availableNextNodes
const {
handleNodeDataUpdate,
handleNodeDataUpdateWithSyncDraft,
@ -102,7 +105,7 @@ const BasePanel: FC<BasePanelProps> = ({
{cloneElement(children, { id, data })}
</div>
{
data.type !== BlockEnum.End && (
!!availableNextNodes.length && (
<div className='p-4 border-t-[0.5px] border-t-black/5'>
<div className='flex items-center mb-1 text-gray-700 text-[13px] font-semibold'>
<GitBranch01 className='mr-1 w-4 h-4' />

View File

@ -1,4 +1,4 @@
import type { NodeDefault } from '../../types'
import { BlockEnum, type NodeDefault } from '../../types'
import { type IfElseNodeType, LogicalOperator } from './types'
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/constants'
@ -23,7 +23,7 @@ const nodeDefault: NodeDefault<IfElseNodeType> = {
},
getAvailableNextNodes(isChatMode: boolean) {
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
return nodes
return nodes.filter(type => type !== BlockEnum.VariableAssigner)
},
checkValid(payload: IfElseNodeType) {
let isValid = true

View File

@ -1,4 +1,5 @@
import type { NodeDefault } from '../../types'
import { BlockEnum } from '../../types'
import type { QuestionClassifierNodeType } from './types'
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/constants'
@ -21,7 +22,7 @@ const nodeDefault: NodeDefault<QuestionClassifierNodeType> = {
},
getAvailableNextNodes(isChatMode: boolean) {
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
return nodes
return nodes.filter(type => type !== BlockEnum.VariableAssigner)
},
checkValid(payload: QuestionClassifierNodeType) {
let isValid = true

View File

@ -1,4 +1,5 @@
import { type NodeDefault, VarType } from '../../types'
import { BlockEnum } from '../../types'
import type { VariableAssignerNodeType } from './types'
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/constants'
@ -9,7 +10,7 @@ const nodeDefault: NodeDefault<VariableAssignerNodeType> = {
},
getAvailablePrevNodes(isChatMode: boolean) {
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
return nodes
return nodes.filter(type => type !== BlockEnum.IfElse && type !== BlockEnum.QuestionClassifier)
},
getAvailableNextNodes(isChatMode: boolean) {
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS