mirror of
https://github.com/langgenius/dify.git
synced 2025-12-20 06:32:45 +00:00
Compare commits
2 Commits
test/build
...
chore/work
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf20f3aa8b | ||
|
|
c90e564d99 |
@@ -3,7 +3,7 @@ import {
|
||||
useCallback,
|
||||
useMemo,
|
||||
} from 'react'
|
||||
import { useEdges, useNodes, useStore as useReactflowStore } from 'reactflow'
|
||||
import { useStore as useReactflowStore } from 'reactflow'
|
||||
import { RiApps2AddLine } from '@remixicon/react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
useWorkflowStore,
|
||||
} from '@/app/components/workflow/store'
|
||||
import {
|
||||
useChecklist,
|
||||
useChecklistBeforePublish,
|
||||
useNodesReadOnly,
|
||||
useNodesSyncDraft,
|
||||
@@ -19,10 +18,6 @@ import {
|
||||
import Button from '@/app/components/base/button'
|
||||
import AppPublisher from '@/app/components/app/app-publisher'
|
||||
import { useFeatures } from '@/app/components/base/features/hooks'
|
||||
import type {
|
||||
CommonEdgeType,
|
||||
CommonNodeType,
|
||||
} from '@/app/components/workflow/types'
|
||||
import {
|
||||
BlockEnum,
|
||||
InputVarType,
|
||||
@@ -97,18 +92,9 @@ const FeaturesTrigger = () => {
|
||||
}
|
||||
}, [appID, setAppDetail])
|
||||
const { mutateAsync: publishWorkflow } = usePublishWorkflow()
|
||||
const nodes = useNodes<CommonNodeType>()
|
||||
const edges = useEdges<CommonEdgeType>()
|
||||
const needWarningNodes = useChecklist(nodes, edges)
|
||||
|
||||
const updatePublishedWorkflow = useInvalidateAppWorkflow()
|
||||
const onPublish = useCallback(async (params?: PublishWorkflowParams) => {
|
||||
// First check if there are any items in the checklist
|
||||
if (needWarningNodes.length > 0) {
|
||||
notify({ type: 'error', message: t('workflow.panel.checklistTip') })
|
||||
throw new Error('Checklist has unresolved items')
|
||||
}
|
||||
|
||||
// Then perform the detailed validation
|
||||
if (await handleCheckBeforePublish()) {
|
||||
const res = await publishWorkflow({
|
||||
@@ -128,7 +114,7 @@ const FeaturesTrigger = () => {
|
||||
else {
|
||||
throw new Error('Checklist failed')
|
||||
}
|
||||
}, [needWarningNodes, handleCheckBeforePublish, publishWorkflow, notify, appID, t, updatePublishedWorkflow, updateAppDetail, workflowStore, resetWorkflowVersionHistory])
|
||||
}, [handleCheckBeforePublish, publishWorkflow, notify, appID, t, updatePublishedWorkflow, updateAppDetail, workflowStore, resetWorkflowVersionHistory])
|
||||
|
||||
const onPublisherToggle = useCallback((state: boolean) => {
|
||||
if (state)
|
||||
|
||||
@@ -2,27 +2,25 @@ import {
|
||||
memo,
|
||||
useCallback,
|
||||
} from 'react'
|
||||
import { useNodes } from 'reactflow'
|
||||
import { useStore } from './store'
|
||||
import {
|
||||
useIsChatMode,
|
||||
useNodesReadOnly,
|
||||
useNodesSyncDraft,
|
||||
} from './hooks'
|
||||
import { type CommonNodeType, type InputVar, InputVarType, type Node } from './types'
|
||||
import { type InputVar, InputVarType, type Node } from './types'
|
||||
import useConfig from './nodes/start/use-config'
|
||||
import type { StartNodeType } from './nodes/start/types'
|
||||
import type { PromptVariable } from '@/models/debug'
|
||||
import NewFeaturePanel from '@/app/components/base/features/new-feature-panel'
|
||||
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
|
||||
|
||||
const Features = () => {
|
||||
const setShowFeaturesPanel = useStore(s => s.setShowFeaturesPanel)
|
||||
const isChatMode = useIsChatMode()
|
||||
const { nodesReadOnly } = useNodesReadOnly()
|
||||
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
||||
const nodes = useNodes<CommonNodeType>()
|
||||
|
||||
const startNode = nodes.find(node => node.data.type === 'start')
|
||||
const startNode = useFindNode(['sys'])
|
||||
const { id, data } = startNode as Node<StartNodeType>
|
||||
const { handleAddVariable } = useConfig(id, data)
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import {
|
||||
useCallback,
|
||||
} from 'react'
|
||||
import { useNodes } from 'reactflow'
|
||||
import { useStore as useReactFlowStore } from 'reactflow'
|
||||
import {
|
||||
useStore,
|
||||
useWorkflowStore,
|
||||
} from '../store'
|
||||
import type { StartNodeType } from '../nodes/start/types'
|
||||
import {
|
||||
useNodesInteractions,
|
||||
useNodesReadOnly,
|
||||
@@ -39,8 +38,7 @@ const HeaderInNormal = ({
|
||||
const setShowDebugAndPreviewPanel = useStore(s => s.setShowDebugAndPreviewPanel)
|
||||
const setShowVariableInspectPanel = useStore(s => s.setShowVariableInspectPanel)
|
||||
const setShowChatVariablePanel = useStore(s => s.setShowChatVariablePanel)
|
||||
const nodes = useNodes<StartNodeType>()
|
||||
const selectedNode = nodes.find(node => node.data.selected)
|
||||
const selectedNode = useReactFlowStore(s => s.getNodes().find(node => node.data.selected))
|
||||
const { handleBackupDraft } = useWorkflowRun()
|
||||
const { closeAllInputFieldPanels } = useInputFieldPanel()
|
||||
|
||||
|
||||
36
web/app/components/workflow/hooks/use-find-node.ts
Normal file
36
web/app/components/workflow/hooks/use-find-node.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { useMemo } from 'react'
|
||||
import { useStore } from 'reactflow'
|
||||
import { useShallow } from 'zustand/react/shallow'
|
||||
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import type { Node, ValueSelector } from '@/app/components/workflow/types'
|
||||
|
||||
export const useFindNode = (valueSelector: ValueSelector = [], nodes: Node[] = []) => {
|
||||
const nodeFromOuterNodes = nodes.find(node => node.id === valueSelector[0])
|
||||
const node = useStore(useShallow((s) => {
|
||||
if (isSystemVar(valueSelector)) {
|
||||
for (const n of s.nodeInternals.values()) {
|
||||
if (n?.data?.type === BlockEnum.Start) {
|
||||
return {
|
||||
id: n.id,
|
||||
data: n.data,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!!valueSelector.length) {
|
||||
const id = s.nodeInternals.get(valueSelector[0])?.id
|
||||
const data = s.nodeInternals.get(valueSelector[0])?.data
|
||||
if (id && data) {
|
||||
return {
|
||||
id,
|
||||
data,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
return useMemo(() => nodeFromOuterNodes || node, [nodeFromOuterNodes, node])
|
||||
}
|
||||
@@ -4,18 +4,16 @@ import {
|
||||
useRef,
|
||||
} from 'react'
|
||||
import { useClickAway } from 'ahooks'
|
||||
import { useNodes } from 'reactflow'
|
||||
import PanelOperatorPopup from './nodes/_base/components/panel-operator/panel-operator-popup'
|
||||
import type { Node } from './types'
|
||||
import { useStore } from './store'
|
||||
import { usePanelInteractions } from './hooks'
|
||||
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
|
||||
|
||||
const NodeContextmenu = () => {
|
||||
const ref = useRef(null)
|
||||
const nodes = useNodes()
|
||||
const { handleNodeContextmenuCancel, handlePaneContextmenuCancel } = usePanelInteractions()
|
||||
const nodeMenu = useStore(s => s.nodeMenu)
|
||||
const currentNode = nodes.find(node => node.id === nodeMenu?.nodeId) as Node
|
||||
const currentNode = useFindNode(nodeMenu?.nodeId ? [nodeMenu.nodeId] : [])
|
||||
|
||||
useEffect(() => {
|
||||
if (nodeMenu)
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useNodes, useReactFlow, useStoreApi } from 'reactflow'
|
||||
import { useReactFlow, useStoreApi } from 'reactflow'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type {
|
||||
CommonNodeType,
|
||||
Node,
|
||||
ValueSelector,
|
||||
VarType,
|
||||
} from '@/app/components/workflow/types'
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import { getNodeInfoById, isConversationVar, isENV, isRagVariableVar, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
|
||||
import { isConversationVar, isENV, isRagVariableVar, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
|
||||
import { isExceptionVariable } from '@/app/components/workflow/utils'
|
||||
import {
|
||||
VariableLabelInSelect,
|
||||
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
|
||||
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
|
||||
|
||||
type VariableTagProps = {
|
||||
valueSelector: ValueSelector
|
||||
@@ -26,16 +26,16 @@ const VariableTag = ({
|
||||
isShort,
|
||||
availableNodes,
|
||||
}: VariableTagProps) => {
|
||||
const nodes = useNodes<CommonNodeType>()
|
||||
const isRagVar = isRagVariableVar(valueSelector)
|
||||
const nodeFromAvailableNodes = useFindNode(isRagVar ? [valueSelector[1]] : [valueSelector[0]], availableNodes)
|
||||
const node = useMemo(() => {
|
||||
if (isSystemVar(valueSelector)) {
|
||||
const startNode = availableNodes?.find(n => n.data.type === BlockEnum.Start)
|
||||
if (startNode)
|
||||
return startNode
|
||||
}
|
||||
return getNodeInfoById(availableNodes || nodes, isRagVar ? valueSelector[1] : valueSelector[0])
|
||||
}, [nodes, valueSelector, availableNodes, isRagVar])
|
||||
return nodeFromAvailableNodes
|
||||
}, [valueSelector, availableNodes, isRagVar, nodeFromAvailableNodes]) as Node
|
||||
|
||||
const isEnv = isENV(valueSelector)
|
||||
const isChatVar = isConversationVar(valueSelector)
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { memo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { AssignerNodeOperation } from '../types'
|
||||
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
|
||||
import {
|
||||
VariableLabelInNode,
|
||||
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
|
||||
type OperationItemProps = {
|
||||
value: AssignerNodeOperation
|
||||
}
|
||||
|
||||
const i18nPrefix = 'workflow.nodes.assigner'
|
||||
|
||||
const OperationItem = ({ value }: OperationItemProps) => {
|
||||
const { t } = useTranslation()
|
||||
const variable = value.variable_selector
|
||||
const node = useFindNode(variable)
|
||||
if (!variable || variable.length === 0)
|
||||
return null
|
||||
|
||||
return (
|
||||
<VariableLabelInNode
|
||||
variables={variable}
|
||||
nodeType={node?.data.type}
|
||||
nodeTitle={node?.data.title}
|
||||
rightSlot={
|
||||
value.operation && <Badge className='!ml-auto shrink-0' text={t(`${i18nPrefix}.operations.${value.operation}`)} />
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(OperationItem)
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useCallback } from 'react'
|
||||
import {
|
||||
useNodes,
|
||||
useStoreApi,
|
||||
} from 'reactflow'
|
||||
import { uniqBy } from 'lodash-es'
|
||||
import {
|
||||
@@ -15,12 +15,14 @@ import type {
|
||||
import { AssignerNodeInputType, WriteMode } from './types'
|
||||
|
||||
export const useGetAvailableVars = () => {
|
||||
const nodes: Node[] = useNodes()
|
||||
const store = useStoreApi()
|
||||
const { getBeforeNodesInSameBranchIncludeParent } = useWorkflow()
|
||||
const { getNodeAvailableVars } = useWorkflowVariables()
|
||||
const isChatMode = useIsChatMode()
|
||||
const getAvailableVars = useCallback((nodeId: string, handleId: string, filterVar: (v: Var) => boolean, hideEnv = false) => {
|
||||
const availableNodes: Node[] = []
|
||||
const { getNodes } = store.getState()
|
||||
const nodes = getNodes()
|
||||
const currentNode = nodes.find(node => node.id === nodeId)!
|
||||
|
||||
if (!currentNode)
|
||||
@@ -52,7 +54,7 @@ export const useGetAvailableVars = () => {
|
||||
isChatMode,
|
||||
filterVar,
|
||||
})
|
||||
}, [nodes, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode])
|
||||
}, [store, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode])
|
||||
|
||||
return getAvailableVars
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useNodes } from 'reactflow'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { AssignerNodeType } from './types'
|
||||
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
|
||||
import { BlockEnum, type Node, type NodeProps } from '@/app/components/workflow/types'
|
||||
import type { NodeProps } from '@/app/components/workflow/types'
|
||||
import {
|
||||
VariableLabelInNode,
|
||||
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import OperationItem from './components/operation-item'
|
||||
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
|
||||
|
||||
const i18nPrefix = 'workflow.nodes.assigner'
|
||||
|
||||
@@ -16,7 +16,7 @@ const NodeComponent: FC<NodeProps<AssignerNodeType>> = ({
|
||||
data,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const nodes: Node[] = useNodes()
|
||||
const node = useFindNode((data as any).assigned_variable_selector)
|
||||
if (data.version === '2') {
|
||||
const { items: operationItems } = data
|
||||
const validOperationItems = operationItems?.filter(item =>
|
||||
@@ -37,22 +37,7 @@ const NodeComponent: FC<NodeProps<AssignerNodeType>> = ({
|
||||
return (
|
||||
<div className='relative flex flex-col items-start gap-0.5 self-stretch px-3 py-1'>
|
||||
{operationItems.map((value, index) => {
|
||||
const variable = value.variable_selector
|
||||
if (!variable || variable.length === 0)
|
||||
return null
|
||||
const isSystem = isSystemVar(variable)
|
||||
const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0])
|
||||
return (
|
||||
<VariableLabelInNode
|
||||
key={index}
|
||||
variables={variable}
|
||||
nodeType={node?.data.type}
|
||||
nodeTitle={node?.data.title}
|
||||
rightSlot={
|
||||
value.operation && <Badge className='!ml-auto shrink-0' text={t(`${i18nPrefix}.operations.${value.operation}`)} />
|
||||
}
|
||||
/>
|
||||
)
|
||||
return <OperationItem key={index} value={value} />
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
@@ -62,8 +47,6 @@ const NodeComponent: FC<NodeProps<AssignerNodeType>> = ({
|
||||
|
||||
if (!variable || variable.length === 0)
|
||||
return null
|
||||
const isSystem = isSystemVar(variable)
|
||||
const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0])
|
||||
|
||||
return (
|
||||
<div className='relative flex flex-col items-start gap-0.5 self-stretch px-3 py-1'>
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useNodes } from 'reactflow'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { DocExtractorNodeType } from './types'
|
||||
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
|
||||
import { BlockEnum, type Node, type NodeProps } from '@/app/components/workflow/types'
|
||||
import type { NodeProps } from '@/app/components/workflow/types'
|
||||
import {
|
||||
VariableLabelInNode,
|
||||
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
|
||||
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
|
||||
|
||||
const i18nPrefix = 'workflow.nodes.docExtractor'
|
||||
|
||||
@@ -15,15 +14,12 @@ const NodeComponent: FC<NodeProps<DocExtractorNodeType>> = ({
|
||||
data,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const nodes: Node[] = useNodes()
|
||||
const { variable_selector: variable } = data
|
||||
const node = useFindNode(variable)
|
||||
|
||||
if (!variable || variable.length === 0)
|
||||
return null
|
||||
|
||||
const isSystem = isSystemVar(variable)
|
||||
const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0])
|
||||
return (
|
||||
<div className='relative px-3'>
|
||||
<div className='system-2xs-medium-uppercase mb-1 text-text-tertiary'>{t(`${i18nPrefix}.inputVar`)}</div>
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
useMemo,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNodes } from 'reactflow'
|
||||
import { ComparisonOperator } from '../types'
|
||||
import {
|
||||
comparisonOperatorNotRequireValue,
|
||||
@@ -12,13 +11,10 @@ import {
|
||||
import { FILE_TYPE_OPTIONS, TRANSFER_METHOD } from '../../constants'
|
||||
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
|
||||
import { isExceptionVariable } from '@/app/components/workflow/utils'
|
||||
import type {
|
||||
CommonNodeType,
|
||||
Node,
|
||||
} from '@/app/components/workflow/types'
|
||||
import {
|
||||
VariableLabelInText,
|
||||
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
|
||||
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
|
||||
|
||||
type ConditionValueProps = {
|
||||
variableSelector: string[]
|
||||
@@ -33,11 +29,10 @@ const ConditionValue = ({
|
||||
value,
|
||||
}: ConditionValueProps) => {
|
||||
const { t } = useTranslation()
|
||||
const nodes = useNodes()
|
||||
const node = useFindNode(variableSelector)
|
||||
const variableName = labelName || (isSystemVar(variableSelector) ? variableSelector.slice(0).join('.') : variableSelector.slice(1).join('.'))
|
||||
const operatorName = isComparisonOperatorNeedTranslate(operator) ? t(`workflow.nodes.ifElse.comparisonOperator.${operator}`) : operator
|
||||
const notHasValue = comparisonOperatorNotRequireValue(operator)
|
||||
const node: Node<CommonNodeType> | undefined = nodes.find(n => n.id === variableSelector[0]) as Node<CommonNodeType>
|
||||
const isException = isExceptionVariable(variableName, node?.data.type)
|
||||
const formatValue = useMemo(() => {
|
||||
if (notHasValue)
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useNodes } from 'reactflow'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { ListFilterNodeType } from './types'
|
||||
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
|
||||
import { BlockEnum, type Node, type NodeProps } from '@/app/components/workflow/types'
|
||||
import type { NodeProps } from '@/app/components/workflow/types'
|
||||
import {
|
||||
VariableLabelInNode,
|
||||
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
|
||||
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
|
||||
|
||||
const i18nPrefix = 'workflow.nodes.listFilter'
|
||||
|
||||
@@ -15,15 +14,12 @@ const NodeComponent: FC<NodeProps<ListFilterNodeType>> = ({
|
||||
data,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const nodes: Node[] = useNodes()
|
||||
const { variable } = data
|
||||
const node = useFindNode(variable)
|
||||
|
||||
if (!variable || variable.length === 0)
|
||||
return null
|
||||
|
||||
const isSystem = isSystemVar(variable)
|
||||
const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0])
|
||||
return (
|
||||
<div className='relative px-3'>
|
||||
<div className='system-2xs-medium-uppercase mb-1 text-text-tertiary'>{t(`${i18nPrefix}.inputVar`)}</div>
|
||||
|
||||
@@ -3,11 +3,8 @@ import {
|
||||
useMemo,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNodes } from 'reactflow'
|
||||
import { useStore } from '../../../store'
|
||||
import { BlockEnum } from '../../../types'
|
||||
import type {
|
||||
Node,
|
||||
ValueSelector,
|
||||
VarType,
|
||||
} from '../../../types'
|
||||
@@ -18,12 +15,8 @@ import {
|
||||
} from '../hooks'
|
||||
import { filterVar } from '../utils'
|
||||
import AddVariable from './add-variable'
|
||||
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
|
||||
import cn from '@/utils/classnames'
|
||||
import { isExceptionVariable } from '@/app/components/workflow/utils'
|
||||
import {
|
||||
VariableLabelInNode,
|
||||
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
|
||||
import VariableLabelItem from './variable-label-item'
|
||||
|
||||
const i18nPrefix = 'workflow.nodes.variableAssigner'
|
||||
type GroupItem = {
|
||||
@@ -44,7 +37,6 @@ const NodeGroupItem = ({
|
||||
const { t } = useTranslation()
|
||||
const enteringNodePayload = useStore(s => s.enteringNodePayload)
|
||||
const hoveringAssignVariableGroupId = useStore(s => s.hoveringAssignVariableGroupId)
|
||||
const nodes: Node[] = useNodes()
|
||||
const {
|
||||
handleGroupItemMouseEnter,
|
||||
handleGroupItemMouseLeave,
|
||||
@@ -128,21 +120,7 @@ const NodeGroupItem = ({
|
||||
<div className='space-y-0.5'>
|
||||
{
|
||||
item.variables.map((variable = [], index) => {
|
||||
const isSystem = isSystemVar(variable)
|
||||
|
||||
const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0])
|
||||
const varName = isSystem ? `sys.${variable[variable.length - 1]}` : variable.slice(1).join('.')
|
||||
const isException = isExceptionVariable(varName, node?.data.type)
|
||||
|
||||
return (
|
||||
<VariableLabelInNode
|
||||
key={index}
|
||||
variables={variable}
|
||||
nodeType={node?.data.type}
|
||||
nodeTitle={node?.data.title}
|
||||
isExceptionVariable={isException}
|
||||
/>
|
||||
)
|
||||
return <VariableLabelItem key={index} variable={variable} />
|
||||
})
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { memo } from 'react'
|
||||
import type { ValueSelector } from '@/app/components/workflow/types'
|
||||
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
|
||||
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
|
||||
import { isExceptionVariable } from '@/app/components/workflow/utils'
|
||||
import {
|
||||
VariableLabelInNode,
|
||||
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
|
||||
|
||||
type VariableLabelItemProps = {
|
||||
variable: ValueSelector
|
||||
}
|
||||
const VariableLabelItem = ({ variable }: VariableLabelItemProps) => {
|
||||
const isSystem = isSystemVar(variable)
|
||||
const node = useFindNode(variable)
|
||||
const varName = isSystem ? `sys.${variable[variable.length - 1]}` : variable.slice(1).join('.')
|
||||
const isException = isExceptionVariable(varName, node?.data.type)
|
||||
|
||||
return (
|
||||
<VariableLabelInNode
|
||||
variables={variable}
|
||||
nodeType={node?.data.type}
|
||||
nodeTitle={node?.data.title}
|
||||
isExceptionVariable={isException}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(VariableLabelItem)
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useCallback } from 'react'
|
||||
import {
|
||||
useNodes,
|
||||
useStoreApi,
|
||||
} from 'reactflow'
|
||||
import { uniqBy } from 'lodash-es'
|
||||
@@ -122,12 +121,14 @@ export const useVariableAssigner = () => {
|
||||
}
|
||||
|
||||
export const useGetAvailableVars = () => {
|
||||
const nodes: Node[] = useNodes()
|
||||
const store = useStoreApi()
|
||||
const { getBeforeNodesInSameBranchIncludeParent } = useWorkflow()
|
||||
const { getNodeAvailableVars } = useWorkflowVariables()
|
||||
const isChatMode = useIsChatMode()
|
||||
const getAvailableVars = useCallback((nodeId: string, handleId: string, filterVar: (v: Var) => boolean, hideEnv = false) => {
|
||||
const availableNodes: Node[] = []
|
||||
const { getNodes } = store.getState()
|
||||
const nodes = getNodes()
|
||||
const currentNode = nodes.find(node => node.id === nodeId)!
|
||||
|
||||
if (!currentNode)
|
||||
@@ -158,7 +159,7 @@ export const useGetAvailableVars = () => {
|
||||
isChatMode,
|
||||
filterVar,
|
||||
})
|
||||
}, [nodes, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode])
|
||||
}, [store, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode])
|
||||
|
||||
return getAvailableVars
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { memo, useCallback, useEffect, useImperativeHandle, useMemo } from 'react'
|
||||
import { useNodes } from 'reactflow'
|
||||
import { BlockEnum } from '../../types'
|
||||
import type { Node } from '../../types'
|
||||
import {
|
||||
useStore,
|
||||
useWorkflowStore,
|
||||
@@ -23,6 +22,7 @@ import { getLastAnswer, isValidGeneratedAnswer } from '@/app/components/base/cha
|
||||
import type { FileEntity } from '@/app/components/base/file-uploader/types'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import { EVENT_WORKFLOW_STOP } from '@/app/components/workflow/variable-inspect/types'
|
||||
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
|
||||
|
||||
type ChatWrapperProps = {
|
||||
showConversationVariableModal: boolean
|
||||
@@ -42,8 +42,7 @@ const ChatWrapper = (
|
||||
ref: React.RefObject<ChatWrapperRefType>;
|
||||
},
|
||||
) => {
|
||||
const nodes = useNodes<StartNodeType>()
|
||||
const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
|
||||
const startNode = useFindNode(['sys']) as Node<StartNodeType>
|
||||
const startVariables = startNode?.data.variables
|
||||
const appDetail = useAppStore(s => s.appDetail)
|
||||
const workflowStore = useWorkflowStore()
|
||||
|
||||
@@ -8,13 +8,13 @@ import {
|
||||
|
||||
import { RiCloseLine, RiEqualizer2Line } from '@remixicon/react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNodes } from 'reactflow'
|
||||
import { useStore as useReactFlowStore } from 'reactflow'
|
||||
import {
|
||||
useWorkflowInteractions,
|
||||
} from '../../hooks'
|
||||
import { useEdgesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-edges-interactions-without-sync'
|
||||
import { useNodesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-nodes-interactions-without-sync'
|
||||
import { BlockEnum } from '../../types'
|
||||
import type { Node } from '../../types'
|
||||
import type { StartNodeType } from '../../nodes/start/types'
|
||||
import { useResizePanel } from '../../nodes/_base/hooks/use-resize-panel'
|
||||
import ChatWrapper from './chat-wrapper'
|
||||
@@ -24,6 +24,7 @@ import Tooltip from '@/app/components/base/tooltip'
|
||||
import ActionButton, { ActionButtonState } from '@/app/components/base/action-button'
|
||||
import { useStore } from '@/app/components/workflow/store'
|
||||
import { debounce, noop } from 'lodash-es'
|
||||
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
|
||||
|
||||
export type ChatWrapperRefType = {
|
||||
handleRestart: () => void
|
||||
@@ -35,9 +36,8 @@ const DebugAndPreview = () => {
|
||||
const { handleNodeCancelRunningStatus } = useNodesInteractionsWithoutSync()
|
||||
const { handleEdgeCancelRunningStatus } = useEdgesInteractionsWithoutSync()
|
||||
const [expanded, setExpanded] = useState(true)
|
||||
const nodes = useNodes<StartNodeType>()
|
||||
const selectedNode = nodes.find(node => node.data.selected)
|
||||
const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
|
||||
const startNode = useFindNode(['sys']) as Node<StartNodeType>
|
||||
const selectedNode = useReactFlowStore(s => s.getNodes().find(node => node.data.selected))
|
||||
const variables = startNode?.data.variables || []
|
||||
const visibleVariables = variables.filter(v => v.hide !== true)
|
||||
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
import {
|
||||
memo,
|
||||
} from 'react'
|
||||
import { useNodes } from 'reactflow'
|
||||
import FormItem from '../../nodes/_base/components/before-run-form/form-item'
|
||||
import { BlockEnum } from '../../types'
|
||||
import type { Node } from '../../types'
|
||||
import {
|
||||
useStore,
|
||||
useWorkflowStore,
|
||||
} from '../../store'
|
||||
import type { StartNodeType } from '../../nodes/start/types'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
|
||||
|
||||
const UserInput = () => {
|
||||
const workflowStore = useWorkflowStore()
|
||||
const inputs = useStore(s => s.inputs)
|
||||
const nodes = useNodes<StartNodeType>()
|
||||
const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
|
||||
const startNode = useFindNode(['sys']) as Node<StartNodeType>
|
||||
const variables = startNode?.data.variables || []
|
||||
const visibleVariables = variables.filter(v => v.hide !== true)
|
||||
|
||||
|
||||
@@ -4,10 +4,8 @@ import {
|
||||
useMemo,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNodes } from 'reactflow'
|
||||
import FormItem from '../nodes/_base/components/before-run-form/form-item'
|
||||
import {
|
||||
BlockEnum,
|
||||
InputVarType,
|
||||
WorkflowRunningStatus,
|
||||
} from '../types'
|
||||
@@ -16,7 +14,6 @@ import {
|
||||
useWorkflowStore,
|
||||
} from '../store'
|
||||
import { useWorkflowRun } from '../hooks'
|
||||
import type { StartNodeType } from '../nodes/start/types'
|
||||
import { TransferMethod } from '../../base/text-generation/types'
|
||||
import Button from '@/app/components/base/button'
|
||||
import {
|
||||
@@ -24,6 +21,7 @@ import {
|
||||
} from '@/app/components/base/chat/chat/utils'
|
||||
import { useCheckInputsForms } from '@/app/components/base/chat/chat/check-input-forms-hooks'
|
||||
import { useHooksStore } from '../hooks-store'
|
||||
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
|
||||
|
||||
type Props = {
|
||||
onRun: () => void
|
||||
@@ -37,19 +35,18 @@ const InputsPanel = ({ onRun }: Props) => {
|
||||
setInputs: s.setInputs,
|
||||
}))
|
||||
const fileSettings = useHooksStore(s => s.configsMap?.fileSettings)
|
||||
const nodes = useNodes<StartNodeType>()
|
||||
const startNode = useFindNode(['sys'])
|
||||
const files = useStore(s => s.files)
|
||||
const workflowRunningData = useStore(s => s.workflowRunningData)
|
||||
const {
|
||||
handleRun,
|
||||
} = useWorkflowRun()
|
||||
const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
|
||||
const startVariables = startNode?.data.variables
|
||||
const { checkInputsForm } = useCheckInputsForms()
|
||||
|
||||
const initialInputs = { ...inputs }
|
||||
if (startVariables) {
|
||||
startVariables.forEach((variable) => {
|
||||
startVariables.forEach((variable: any) => {
|
||||
if (variable.default)
|
||||
initialInputs[variable.variable] = variable.default
|
||||
if (inputs[variable.variable] !== undefined)
|
||||
@@ -110,7 +107,7 @@ const InputsPanel = ({ onRun }: Props) => {
|
||||
<>
|
||||
<div className='px-4 pb-2 pt-3'>
|
||||
{
|
||||
variables.map((variable, index) => (
|
||||
variables.map((variable: any, index: number) => (
|
||||
<div
|
||||
key={variable.variable}
|
||||
className='mb-2 last-of-type:mb-0'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { FC } from 'react'
|
||||
import { useMemo } from 'react'
|
||||
import { useNodes } from 'reactflow'
|
||||
import { useStore as useReactFlowStore } from 'reactflow'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiLoader2Line, RiStopCircleFill } from '@remixicon/react'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
@@ -8,7 +8,6 @@ import { useStore } from '../store'
|
||||
import useCurrentVars from '../hooks/use-inspect-vars-crud'
|
||||
import { WorkflowRunningStatus } from '@/app/components/workflow/types'
|
||||
import { NodeRunningStatus } from '@/app/components/workflow/types'
|
||||
import type { CommonNodeType } from '@/app/components/workflow/types'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import { EVENT_WORKFLOW_STOP } from '@/app/components/workflow/variable-inspect/types'
|
||||
import cn from '@/utils/classnames'
|
||||
@@ -38,8 +37,7 @@ const VariableInspectTrigger: FC = () => {
|
||||
getNodesReadOnly,
|
||||
} = useNodesReadOnly()
|
||||
const workflowRunningData = useStore(s => s.workflowRunningData)
|
||||
const nodes = useNodes<CommonNodeType>()
|
||||
const isStepRunning = useMemo(() => nodes.some(node => node.data._singleRunningStatus === NodeRunningStatus.Running), [nodes])
|
||||
const isStepRunning = useReactFlowStore(s => s.getNodes().some(node => node.data._singleRunningStatus === NodeRunningStatus.Running))
|
||||
const isPreviewRunning = useMemo(() => {
|
||||
if (!workflowRunningData)
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user