diff --git a/web/app/components/workflow/store.ts b/web/app/components/workflow/store.ts deleted file mode 100644 index a71454ffff..0000000000 --- a/web/app/components/workflow/store.ts +++ /dev/null @@ -1,323 +0,0 @@ -import { useContext } from 'react' -import { - useStore as useZustandStore, -} from 'zustand' -import { createStore } from 'zustand/vanilla' -import { debounce } from 'lodash-es' -import type { Viewport } from 'reactflow' -import type { - HelpLineHorizontalPosition, - HelpLineVerticalPosition, -} from './help-line/types' -import type { VariableAssignerNodeType } from './nodes/variable-assigner/types' -import type { - ConversationVariable, - Edge, - EnvironmentVariable, - HistoryWorkflowData, - Node, - RunFile, - ToolWithProvider, - WorkflowRunningData, -} from './types' -import { WorkflowContext } from './context' -import type { NodeTracing, VersionHistory } from '@/types/workflow' - -// #TODO chatVar# -// const MOCK_DATA = [ -// { -// id: 'fjlaksdjflkjg-dfjlajfl0dnfkafjk-djfdkafj-djfak', -// name: 'chat_history', -// value_type: 'array[message]', -// value: [], -// description: 'The chat history of the conversation', -// }, -// { -// id: 'fljdaklfjl-dfjlafj0-dklajglje-eknglh', -// name: 'order_id', -// value: '123456', -// value_type: 'string', -// description: '', -// }, -// ] - -type PreviewRunningData = WorkflowRunningData & { - resultTabActive?: boolean - resultText?: string -} - -type Shape = { - appId: string - panelWidth: number - showSingleRunPanel: boolean - setShowSingleRunPanel: (showSingleRunPanel: boolean) => void - workflowRunningData?: PreviewRunningData - setWorkflowRunningData: (workflowData: PreviewRunningData) => void - historyWorkflowData?: HistoryWorkflowData - setHistoryWorkflowData: (historyWorkflowData?: HistoryWorkflowData) => void - showRunHistory: boolean - setShowRunHistory: (showRunHistory: boolean) => void - showFeaturesPanel: boolean - setShowFeaturesPanel: (showFeaturesPanel: boolean) => void - helpLineHorizontal?: HelpLineHorizontalPosition - setHelpLineHorizontal: (helpLineHorizontal?: HelpLineHorizontalPosition) => void - helpLineVertical?: HelpLineVerticalPosition - setHelpLineVertical: (helpLineVertical?: HelpLineVerticalPosition) => void - draftUpdatedAt: number - setDraftUpdatedAt: (draftUpdatedAt: number) => void - publishedAt: number - setPublishedAt: (publishedAt: number) => void - currentVersion: VersionHistory | null - setCurrentVersion: (currentVersion: VersionHistory) => void - showWorkflowVersionHistoryPanel: boolean - setShowWorkflowVersionHistoryPanel: (showWorkflowVersionHistoryPanel: boolean) => void - showInputsPanel: boolean - setShowInputsPanel: (showInputsPanel: boolean) => void - inputs: Record - setInputs: (inputs: Record) => void - toolPublished: boolean - setToolPublished: (toolPublished: boolean) => void - files: RunFile[] - setFiles: (files: RunFile[]) => void - backupDraft?: { - nodes: Node[] - edges: Edge[] - viewport: Viewport - features: Record - environmentVariables: EnvironmentVariable[] - } - setBackupDraft: (backupDraft?: Shape['backupDraft']) => void - notInitialWorkflow: boolean - setNotInitialWorkflow: (notInitialWorkflow: boolean) => void - nodesDefaultConfigs: Record - setNodesDefaultConfigs: (nodesDefaultConfigs: Record) => void - nodeAnimation: boolean - setNodeAnimation: (nodeAnimation: boolean) => void - isRestoring: boolean - setIsRestoring: (isRestoring: boolean) => void - debouncedSyncWorkflowDraft: (fn: () => void) => void - buildInTools: ToolWithProvider[] - setBuildInTools: (tools: ToolWithProvider[]) => void - customTools: ToolWithProvider[] - setCustomTools: (tools: ToolWithProvider[]) => void - workflowTools: ToolWithProvider[] - setWorkflowTools: (tools: ToolWithProvider[]) => void - clipboardElements: Node[] - setClipboardElements: (clipboardElements: Node[]) => void - showDebugAndPreviewPanel: boolean - setShowDebugAndPreviewPanel: (showDebugAndPreviewPanel: boolean) => void - showEnvPanel: boolean - setShowEnvPanel: (showEnvPanel: boolean) => void - environmentVariables: EnvironmentVariable[] - setEnvironmentVariables: (environmentVariables: EnvironmentVariable[]) => void - envSecrets: Record - setEnvSecrets: (envSecrets: Record) => void - showChatVariablePanel: boolean - setShowChatVariablePanel: (showChatVariablePanel: boolean) => void - showGlobalVariablePanel: boolean - setShowGlobalVariablePanel: (showGlobalVariablePanel: boolean) => void - conversationVariables: ConversationVariable[] - setConversationVariables: (conversationVariables: ConversationVariable[]) => void - selection: null | { x1: number; y1: number; x2: number; y2: number } - setSelection: (selection: Shape['selection']) => void - bundleNodeSize: { width: number; height: number } | null - setBundleNodeSize: (bundleNodeSize: Shape['bundleNodeSize']) => void - controlMode: 'pointer' | 'hand' - setControlMode: (controlMode: Shape['controlMode']) => void - candidateNode?: Node - setCandidateNode: (candidateNode?: Node) => void - panelMenu?: { - top: number - left: number - } - setPanelMenu: (panelMenu: Shape['panelMenu']) => void - nodeMenu?: { - top: number - left: number - nodeId: string - } - setNodeMenu: (nodeMenu: Shape['nodeMenu']) => void - mousePosition: { pageX: number; pageY: number; elementX: number; elementY: number } - setMousePosition: (mousePosition: Shape['mousePosition']) => void - syncWorkflowDraftHash: string - setSyncWorkflowDraftHash: (hash: string) => void - showConfirm?: { title: string; desc?: string; onConfirm: () => void } - setShowConfirm: (showConfirm: Shape['showConfirm']) => void - showAssignVariablePopup?: { - nodeId: string - nodeData: Node['data'] - variableAssignerNodeId: string - variableAssignerNodeData: VariableAssignerNodeType - variableAssignerNodeHandleId: string - parentNode?: Node - x: number - y: number - } - setShowAssignVariablePopup: (showAssignVariablePopup: Shape['showAssignVariablePopup']) => void - hoveringAssignVariableGroupId?: string - setHoveringAssignVariableGroupId: (hoveringAssignVariableGroupId?: string) => void - connectingNodePayload?: { nodeId: string; nodeType: string; handleType: string; handleId: string | null } - setConnectingNodePayload: (startConnectingPayload?: Shape['connectingNodePayload']) => void - enteringNodePayload?: { - nodeId: string - nodeData: VariableAssignerNodeType - } - setEnteringNodePayload: (enteringNodePayload?: Shape['enteringNodePayload']) => void - isSyncingWorkflowDraft: boolean - setIsSyncingWorkflowDraft: (isSyncingWorkflowDraft: boolean) => void - controlPromptEditorRerenderKey: number - setControlPromptEditorRerenderKey: (controlPromptEditorRerenderKey: number) => void - showImportDSLModal: boolean - setShowImportDSLModal: (showImportDSLModal: boolean) => void - showTips: string - setShowTips: (showTips: string) => void - iterTimes: number - setIterTimes: (iterTimes: number) => void - loopTimes: number - setLoopTimes: (loopTimes: number) => void - iterParallelLogMap: Map> - setIterParallelLogMap: (iterParallelLogMap: Map>) => void - versionHistory: VersionHistory[] - setVersionHistory: (versionHistory: VersionHistory[]) => void -} - -export const createWorkflowStore = () => { - const hideAllPanel = { - showDebugAndPreviewPanel: false, - showEnvPanel: false, - showChatVariablePanel: false, - showGlobalVariablePanel: false, - } - return createStore(set => ({ - appId: '', - panelWidth: localStorage.getItem('workflow-node-panel-width') ? Number.parseFloat(localStorage.getItem('workflow-node-panel-width')!) : 420, - showSingleRunPanel: false, - setShowSingleRunPanel: showSingleRunPanel => set(() => ({ showSingleRunPanel })), - workflowRunningData: undefined, - setWorkflowRunningData: workflowRunningData => set(() => ({ workflowRunningData })), - historyWorkflowData: undefined, - setHistoryWorkflowData: historyWorkflowData => set(() => ({ historyWorkflowData })), - showRunHistory: false, - setShowRunHistory: showRunHistory => set(() => ({ showRunHistory })), - showFeaturesPanel: false, - setShowFeaturesPanel: showFeaturesPanel => set(() => ({ showFeaturesPanel })), - helpLineHorizontal: undefined, - setHelpLineHorizontal: helpLineHorizontal => set(() => ({ helpLineHorizontal })), - helpLineVertical: undefined, - setHelpLineVertical: helpLineVertical => set(() => ({ helpLineVertical })), - draftUpdatedAt: 0, - setDraftUpdatedAt: draftUpdatedAt => set(() => ({ draftUpdatedAt: draftUpdatedAt ? draftUpdatedAt * 1000 : 0 })), - publishedAt: 0, - setPublishedAt: publishedAt => set(() => ({ publishedAt: publishedAt ? publishedAt * 1000 : 0 })), - currentVersion: null, - setCurrentVersion: currentVersion => set(() => ({ currentVersion })), - showWorkflowVersionHistoryPanel: false, - setShowWorkflowVersionHistoryPanel: showWorkflowVersionHistoryPanel => set(() => ({ showWorkflowVersionHistoryPanel })), - showInputsPanel: false, - setShowInputsPanel: showInputsPanel => set(() => ({ showInputsPanel })), - inputs: {}, - setInputs: inputs => set(() => ({ inputs })), - toolPublished: false, - setToolPublished: toolPublished => set(() => ({ toolPublished })), - files: [], - setFiles: files => set(() => ({ files })), - backupDraft: undefined, - setBackupDraft: backupDraft => set(() => ({ backupDraft })), - notInitialWorkflow: false, - setNotInitialWorkflow: notInitialWorkflow => set(() => ({ notInitialWorkflow })), - nodesDefaultConfigs: {}, - setNodesDefaultConfigs: nodesDefaultConfigs => set(() => ({ nodesDefaultConfigs })), - nodeAnimation: false, - setNodeAnimation: nodeAnimation => set(() => ({ nodeAnimation })), - isRestoring: false, - setIsRestoring: isRestoring => set(() => ({ isRestoring })), - debouncedSyncWorkflowDraft: debounce((syncWorkflowDraft) => { - syncWorkflowDraft() - }, 5000), - buildInTools: [], - setBuildInTools: buildInTools => set(() => ({ buildInTools })), - customTools: [], - setCustomTools: customTools => set(() => ({ customTools })), - workflowTools: [], - setWorkflowTools: workflowTools => set(() => ({ workflowTools })), - clipboardElements: [], - setClipboardElements: clipboardElements => set(() => ({ clipboardElements })), - showDebugAndPreviewPanel: false, - setShowDebugAndPreviewPanel: showDebugAndPreviewPanel => set(() => ({ showDebugAndPreviewPanel })), - showEnvPanel: false, - setShowEnvPanel: showEnvPanel => set(() => ({ showEnvPanel })), - environmentVariables: [], - setEnvironmentVariables: environmentVariables => set(() => ({ environmentVariables })), - envSecrets: {}, - setEnvSecrets: envSecrets => set(() => ({ envSecrets })), - showChatVariablePanel: false, - setShowChatVariablePanel: showChatVariablePanel => set(() => ({ showChatVariablePanel })), - showGlobalVariablePanel: false, - setShowGlobalVariablePanel: showGlobalVariablePanel => set(() => { - if (showGlobalVariablePanel) - return { ...hideAllPanel, showGlobalVariablePanel: true } - else - return { showGlobalVariablePanel: false } - }), - conversationVariables: [], - setConversationVariables: conversationVariables => set(() => ({ conversationVariables })), - selection: null, - setSelection: selection => set(() => ({ selection })), - bundleNodeSize: null, - setBundleNodeSize: bundleNodeSize => set(() => ({ bundleNodeSize })), - controlMode: localStorage.getItem('workflow-operation-mode') === 'pointer' ? 'pointer' : 'hand', - setControlMode: (controlMode) => { - set(() => ({ controlMode })) - localStorage.setItem('workflow-operation-mode', controlMode) - }, - candidateNode: undefined, - setCandidateNode: candidateNode => set(() => ({ candidateNode })), - panelMenu: undefined, - setPanelMenu: panelMenu => set(() => ({ panelMenu })), - nodeMenu: undefined, - setNodeMenu: nodeMenu => set(() => ({ nodeMenu })), - mousePosition: { pageX: 0, pageY: 0, elementX: 0, elementY: 0 }, - setMousePosition: mousePosition => set(() => ({ mousePosition })), - syncWorkflowDraftHash: '', - setSyncWorkflowDraftHash: syncWorkflowDraftHash => set(() => ({ syncWorkflowDraftHash })), - showConfirm: undefined, - setShowConfirm: showConfirm => set(() => ({ showConfirm })), - showAssignVariablePopup: undefined, - setShowAssignVariablePopup: showAssignVariablePopup => set(() => ({ showAssignVariablePopup })), - hoveringAssignVariableGroupId: undefined, - setHoveringAssignVariableGroupId: hoveringAssignVariableGroupId => set(() => ({ hoveringAssignVariableGroupId })), - connectingNodePayload: undefined, - setConnectingNodePayload: connectingNodePayload => set(() => ({ connectingNodePayload })), - enteringNodePayload: undefined, - setEnteringNodePayload: enteringNodePayload => set(() => ({ enteringNodePayload })), - isSyncingWorkflowDraft: false, - setIsSyncingWorkflowDraft: isSyncingWorkflowDraft => set(() => ({ isSyncingWorkflowDraft })), - controlPromptEditorRerenderKey: 0, - setControlPromptEditorRerenderKey: controlPromptEditorRerenderKey => set(() => ({ controlPromptEditorRerenderKey })), - showImportDSLModal: false, - setShowImportDSLModal: showImportDSLModal => set(() => ({ showImportDSLModal })), - showTips: '', - setShowTips: showTips => set(() => ({ showTips })), - iterTimes: 1, - setIterTimes: iterTimes => set(() => ({ iterTimes })), - loopTimes: 1, - setLoopTimes: loopTimes => set(() => ({ loopTimes })), - iterParallelLogMap: new Map>(), - setIterParallelLogMap: iterParallelLogMap => set(() => ({ iterParallelLogMap })), - - versionHistory: [], - setVersionHistory: versionHistory => set(() => ({ versionHistory })), - })) -} - -export function useStore(selector: (state: Shape) => T): T { - const store = useContext(WorkflowContext) - if (!store) - throw new Error('Missing WorkflowContext.Provider in the tree') - - return useZustandStore(store, selector) -} - -export const useWorkflowStore = () => { - return useContext(WorkflowContext)! -} diff --git a/web/app/components/workflow/store/index.ts b/web/app/components/workflow/store/index.ts new file mode 100644 index 0000000000..61cd5773ce --- /dev/null +++ b/web/app/components/workflow/store/index.ts @@ -0,0 +1 @@ +export * from './workflow' diff --git a/web/app/components/workflow/store/workflow/chat-variable-slice.ts b/web/app/components/workflow/store/workflow/chat-variable-slice.ts new file mode 100644 index 0000000000..0d81446005 --- /dev/null +++ b/web/app/components/workflow/store/workflow/chat-variable-slice.ts @@ -0,0 +1,34 @@ +import type { StateCreator } from 'zustand' +import type { ConversationVariable } from '@/app/components/workflow/types' + +export type ChatVariableSliceShape = { + showChatVariablePanel: boolean + setShowChatVariablePanel: (showChatVariablePanel: boolean) => void + showGlobalVariablePanel: boolean + setShowGlobalVariablePanel: (showGlobalVariablePanel: boolean) => void + conversationVariables: ConversationVariable[] + setConversationVariables: (conversationVariables: ConversationVariable[]) => void +} + +export const createChatVariableSlice: StateCreator = (set) => { + const hideAllPanel = { + showDebugAndPreviewPanel: false, + showEnvPanel: false, + showChatVariablePanel: false, + showGlobalVariablePanel: false, + } + + return ({ + showChatVariablePanel: false, + setShowChatVariablePanel: showChatVariablePanel => set(() => ({ showChatVariablePanel })), + showGlobalVariablePanel: false, + setShowGlobalVariablePanel: showGlobalVariablePanel => set(() => { + if (showGlobalVariablePanel) + return { ...hideAllPanel, showGlobalVariablePanel: true } + else + return { showGlobalVariablePanel: false } + }), + conversationVariables: [], + setConversationVariables: conversationVariables => set(() => ({ conversationVariables })), + }) +} diff --git a/web/app/components/workflow/store/workflow/env-variable-slice.ts b/web/app/components/workflow/store/workflow/env-variable-slice.ts new file mode 100644 index 0000000000..de60e7dd5f --- /dev/null +++ b/web/app/components/workflow/store/workflow/env-variable-slice.ts @@ -0,0 +1,20 @@ +import type { StateCreator } from 'zustand' +import type { EnvironmentVariable } from '@/app/components/workflow/types' + +export type EnvVariableSliceShape = { + showEnvPanel: boolean + setShowEnvPanel: (showEnvPanel: boolean) => void + environmentVariables: EnvironmentVariable[] + setEnvironmentVariables: (environmentVariables: EnvironmentVariable[]) => void + envSecrets: Record + setEnvSecrets: (envSecrets: Record) => void +} + +export const createEnvVariableSlice: StateCreator = set => ({ + showEnvPanel: false, + setShowEnvPanel: showEnvPanel => set(() => ({ showEnvPanel })), + environmentVariables: [], + setEnvironmentVariables: environmentVariables => set(() => ({ environmentVariables })), + envSecrets: {}, + setEnvSecrets: envSecrets => set(() => ({ envSecrets })), +}) diff --git a/web/app/components/workflow/store/workflow/form-slice.ts b/web/app/components/workflow/store/workflow/form-slice.ts new file mode 100644 index 0000000000..a6c607d2af --- /dev/null +++ b/web/app/components/workflow/store/workflow/form-slice.ts @@ -0,0 +1,18 @@ +import type { StateCreator } from 'zustand' +import type { + RunFile, +} from '@/app/components/workflow/types' + +export type FormSliceShape = { + inputs: Record + setInputs: (inputs: Record) => void + files: RunFile[] + setFiles: (files: RunFile[]) => void +} + +export const createFormSlice: StateCreator = set => ({ + inputs: {}, + setInputs: inputs => set(() => ({ inputs })), + files: [], + setFiles: files => set(() => ({ files })), +}) diff --git a/web/app/components/workflow/store/workflow/help-line-slice.ts b/web/app/components/workflow/store/workflow/help-line-slice.ts new file mode 100644 index 0000000000..7d9aeac14a --- /dev/null +++ b/web/app/components/workflow/store/workflow/help-line-slice.ts @@ -0,0 +1,19 @@ +import type { StateCreator } from 'zustand' +import type { + HelpLineHorizontalPosition, + HelpLineVerticalPosition, +} from '@/app/components/workflow/help-line/types' + +export type HelpLineSliceShape = { + helpLineHorizontal?: HelpLineHorizontalPosition + setHelpLineHorizontal: (helpLineHorizontal?: HelpLineHorizontalPosition) => void + helpLineVertical?: HelpLineVerticalPosition + setHelpLineVertical: (helpLineVertical?: HelpLineVerticalPosition) => void +} + +export const createHelpLineSlice: StateCreator = set => ({ + helpLineHorizontal: undefined, + setHelpLineHorizontal: helpLineHorizontal => set(() => ({ helpLineHorizontal })), + helpLineVertical: undefined, + setHelpLineVertical: helpLineVertical => set(() => ({ helpLineVertical })), +}) diff --git a/web/app/components/workflow/store/workflow/history-slice.ts b/web/app/components/workflow/store/workflow/history-slice.ts new file mode 100644 index 0000000000..47d1b8ad42 --- /dev/null +++ b/web/app/components/workflow/store/workflow/history-slice.ts @@ -0,0 +1,25 @@ +import type { StateCreator } from 'zustand' +import type { + HistoryWorkflowData, +} from '@/app/components/workflow/types' +import type { + VersionHistory, +} from '@/types/workflow' + +export type HistorySliceShape = { + historyWorkflowData?: HistoryWorkflowData + setHistoryWorkflowData: (historyWorkflowData?: HistoryWorkflowData) => void + showRunHistory: boolean + setShowRunHistory: (showRunHistory: boolean) => void + versionHistory: VersionHistory[] + setVersionHistory: (versionHistory: VersionHistory[]) => void +} + +export const createHistorySlice: StateCreator = set => ({ + historyWorkflowData: undefined, + setHistoryWorkflowData: historyWorkflowData => set(() => ({ historyWorkflowData })), + showRunHistory: false, + setShowRunHistory: showRunHistory => set(() => ({ showRunHistory })), + versionHistory: [], + setVersionHistory: versionHistory => set(() => ({ versionHistory })), +}) diff --git a/web/app/components/workflow/store/workflow/index.ts b/web/app/components/workflow/store/workflow/index.ts new file mode 100644 index 0000000000..769b986606 --- /dev/null +++ b/web/app/components/workflow/store/workflow/index.ts @@ -0,0 +1,69 @@ +import { useContext } from 'react' +import { + useStore as useZustandStore, +} from 'zustand' +import { createStore } from 'zustand/vanilla' +import type { ChatVariableSliceShape } from './chat-variable-slice' +import { createChatVariableSlice } from './chat-variable-slice' +import type { EnvVariableSliceShape } from './env-variable-slice' +import { createEnvVariableSlice } from './env-variable-slice' +import type { FormSliceShape } from './form-slice' +import { createFormSlice } from './form-slice' +import type { HelpLineSliceShape } from './help-line-slice' +import { createHelpLineSlice } from './help-line-slice' +import type { HistorySliceShape } from './history-slice' +import { createHistorySlice } from './history-slice' +import type { NodeSliceShape } from './node-slice' +import { createNodeSlice } from './node-slice' +import type { PanelSliceShape } from './panel-slice' +import { createPanelSlice } from './panel-slice' +import type { ToolSliceShape } from './tool-slice' +import { createToolSlice } from './tool-slice' +import type { VersionSliceShape } from './version-slice' +import { createVersionSlice } from './version-slice' +import type { WorkflowDraftSliceShape } from './workflow-draft-slice' +import { createWorkflowDraftSlice } from './workflow-draft-slice' +import type { WorkflowSliceShape } from './workflow-slice' +import { createWorkflowSlice } from './workflow-slice' +import { WorkflowContext } from '@/app/components/workflow/context' + +export type Shape = + ChatVariableSliceShape & + EnvVariableSliceShape & + FormSliceShape & + HelpLineSliceShape & + HistorySliceShape & + NodeSliceShape & + PanelSliceShape & + ToolSliceShape & + VersionSliceShape & + WorkflowDraftSliceShape & + WorkflowSliceShape + +export const createWorkflowStore = () => { + return createStore((...args) => ({ + ...createChatVariableSlice(...args), + ...createEnvVariableSlice(...args), + ...createFormSlice(...args), + ...createHelpLineSlice(...args), + ...createHistorySlice(...args), + ...createNodeSlice(...args), + ...createPanelSlice(...args), + ...createToolSlice(...args), + ...createVersionSlice(...args), + ...createWorkflowDraftSlice(...args), + ...createWorkflowSlice(...args), + })) +} + +export function useStore(selector: (state: Shape) => T): T { + const store = useContext(WorkflowContext) + if (!store) + throw new Error('Missing WorkflowContext.Provider in the tree') + + return useZustandStore(store, selector) +} + +export const useWorkflowStore = () => { + return useContext(WorkflowContext)! +} diff --git a/web/app/components/workflow/store/workflow/node-slice.ts b/web/app/components/workflow/store/workflow/node-slice.ts new file mode 100644 index 0000000000..d937dc2099 --- /dev/null +++ b/web/app/components/workflow/store/workflow/node-slice.ts @@ -0,0 +1,80 @@ +import type { StateCreator } from 'zustand' +import type { + Node, +} from '@/app/components/workflow/types' +import type { + VariableAssignerNodeType, +} from '@/app/components/workflow/nodes/variable-assigner/types' +import type { + NodeTracing, +} from '@/types/workflow' + +export type NodeSliceShape = { + showSingleRunPanel: boolean + setShowSingleRunPanel: (showSingleRunPanel: boolean) => void + nodesDefaultConfigs: Record + setNodesDefaultConfigs: (nodesDefaultConfigs: Record) => void + nodeAnimation: boolean + setNodeAnimation: (nodeAnimation: boolean) => void + candidateNode?: Node + setCandidateNode: (candidateNode?: Node) => void + nodeMenu?: { + top: number + left: number + nodeId: string + } + setNodeMenu: (nodeMenu: NodeSliceShape['nodeMenu']) => void + showAssignVariablePopup?: { + nodeId: string + nodeData: Node['data'] + variableAssignerNodeId: string + variableAssignerNodeData: VariableAssignerNodeType + variableAssignerNodeHandleId: string + parentNode?: Node + x: number + y: number + } + setShowAssignVariablePopup: (showAssignVariablePopup: NodeSliceShape['showAssignVariablePopup']) => void + hoveringAssignVariableGroupId?: string + setHoveringAssignVariableGroupId: (hoveringAssignVariableGroupId?: string) => void + connectingNodePayload?: { nodeId: string; nodeType: string; handleType: string; handleId: string | null } + setConnectingNodePayload: (startConnectingPayload?: NodeSliceShape['connectingNodePayload']) => void + enteringNodePayload?: { + nodeId: string + nodeData: VariableAssignerNodeType + } + setEnteringNodePayload: (enteringNodePayload?: NodeSliceShape['enteringNodePayload']) => void + iterTimes: number + setIterTimes: (iterTimes: number) => void + loopTimes: number + setLoopTimes: (loopTimes: number) => void + iterParallelLogMap: Map> + setIterParallelLogMap: (iterParallelLogMap: Map>) => void +} + +export const createNodeSlice: StateCreator = set => ({ + showSingleRunPanel: false, + setShowSingleRunPanel: showSingleRunPanel => set(() => ({ showSingleRunPanel })), + nodesDefaultConfigs: {}, + setNodesDefaultConfigs: nodesDefaultConfigs => set(() => ({ nodesDefaultConfigs })), + nodeAnimation: false, + setNodeAnimation: nodeAnimation => set(() => ({ nodeAnimation })), + candidateNode: undefined, + setCandidateNode: candidateNode => set(() => ({ candidateNode })), + nodeMenu: undefined, + setNodeMenu: nodeMenu => set(() => ({ nodeMenu })), + showAssignVariablePopup: undefined, + setShowAssignVariablePopup: showAssignVariablePopup => set(() => ({ showAssignVariablePopup })), + hoveringAssignVariableGroupId: undefined, + setHoveringAssignVariableGroupId: hoveringAssignVariableGroupId => set(() => ({ hoveringAssignVariableGroupId })), + connectingNodePayload: undefined, + setConnectingNodePayload: connectingNodePayload => set(() => ({ connectingNodePayload })), + enteringNodePayload: undefined, + setEnteringNodePayload: enteringNodePayload => set(() => ({ enteringNodePayload })), + iterTimes: 1, + setIterTimes: iterTimes => set(() => ({ iterTimes })), + loopTimes: 1, + setLoopTimes: loopTimes => set(() => ({ loopTimes })), + iterParallelLogMap: new Map>(), + setIterParallelLogMap: iterParallelLogMap => set(() => ({ iterParallelLogMap })), +}) diff --git a/web/app/components/workflow/store/workflow/panel-slice.ts b/web/app/components/workflow/store/workflow/panel-slice.ts new file mode 100644 index 0000000000..06a5f45e11 --- /dev/null +++ b/web/app/components/workflow/store/workflow/panel-slice.ts @@ -0,0 +1,32 @@ +import type { StateCreator } from 'zustand' + +export type PanelSliceShape = { + panelWidth: number + showFeaturesPanel: boolean + setShowFeaturesPanel: (showFeaturesPanel: boolean) => void + showWorkflowVersionHistoryPanel: boolean + setShowWorkflowVersionHistoryPanel: (showWorkflowVersionHistoryPanel: boolean) => void + showInputsPanel: boolean + setShowInputsPanel: (showInputsPanel: boolean) => void + showDebugAndPreviewPanel: boolean + setShowDebugAndPreviewPanel: (showDebugAndPreviewPanel: boolean) => void + panelMenu?: { + top: number + left: number + } + setPanelMenu: (panelMenu: PanelSliceShape['panelMenu']) => void +} + +export const createPanelSlice: StateCreator = set => ({ + panelWidth: localStorage.getItem('workflow-node-panel-width') ? Number.parseFloat(localStorage.getItem('workflow-node-panel-width')!) : 420, + showFeaturesPanel: false, + setShowFeaturesPanel: showFeaturesPanel => set(() => ({ showFeaturesPanel })), + showWorkflowVersionHistoryPanel: false, + setShowWorkflowVersionHistoryPanel: showWorkflowVersionHistoryPanel => set(() => ({ showWorkflowVersionHistoryPanel })), + showInputsPanel: false, + setShowInputsPanel: showInputsPanel => set(() => ({ showInputsPanel })), + showDebugAndPreviewPanel: false, + setShowDebugAndPreviewPanel: showDebugAndPreviewPanel => set(() => ({ showDebugAndPreviewPanel })), + panelMenu: undefined, + setPanelMenu: panelMenu => set(() => ({ panelMenu })), +}) diff --git a/web/app/components/workflow/store/workflow/tool-slice.ts b/web/app/components/workflow/store/workflow/tool-slice.ts new file mode 100644 index 0000000000..2d54bbd925 --- /dev/null +++ b/web/app/components/workflow/store/workflow/tool-slice.ts @@ -0,0 +1,26 @@ +import type { StateCreator } from 'zustand' +import type { + ToolWithProvider, +} from '@/app/components/workflow/types' + +export type ToolSliceShape = { + buildInTools: ToolWithProvider[] + setBuildInTools: (tools: ToolWithProvider[]) => void + customTools: ToolWithProvider[] + setCustomTools: (tools: ToolWithProvider[]) => void + workflowTools: ToolWithProvider[] + setWorkflowTools: (tools: ToolWithProvider[]) => void + toolPublished: boolean + setToolPublished: (toolPublished: boolean) => void +} + +export const createToolSlice: StateCreator = set => ({ + buildInTools: [], + setBuildInTools: buildInTools => set(() => ({ buildInTools })), + customTools: [], + setCustomTools: customTools => set(() => ({ customTools })), + workflowTools: [], + setWorkflowTools: workflowTools => set(() => ({ workflowTools })), + toolPublished: false, + setToolPublished: toolPublished => set(() => ({ toolPublished })), +}) diff --git a/web/app/components/workflow/store/workflow/version-slice.ts b/web/app/components/workflow/store/workflow/version-slice.ts new file mode 100644 index 0000000000..df19218786 --- /dev/null +++ b/web/app/components/workflow/store/workflow/version-slice.ts @@ -0,0 +1,26 @@ +import type { StateCreator } from 'zustand' +import type { + VersionHistory, +} from '@/types/workflow' + +export type VersionSliceShape = { + draftUpdatedAt: number + setDraftUpdatedAt: (draftUpdatedAt: number) => void + publishedAt: number + setPublishedAt: (publishedAt: number) => void + currentVersion: VersionHistory | null + setCurrentVersion: (currentVersion: VersionHistory) => void + isRestoring: boolean + setIsRestoring: (isRestoring: boolean) => void +} + +export const createVersionSlice: StateCreator = set => ({ + draftUpdatedAt: 0, + setDraftUpdatedAt: draftUpdatedAt => set(() => ({ draftUpdatedAt: draftUpdatedAt ? draftUpdatedAt * 1000 : 0 })), + publishedAt: 0, + setPublishedAt: publishedAt => set(() => ({ publishedAt: publishedAt ? publishedAt * 1000 : 0 })), + currentVersion: null, + setCurrentVersion: currentVersion => set(() => ({ currentVersion })), + isRestoring: false, + setIsRestoring: isRestoring => set(() => ({ isRestoring })), +}) diff --git a/web/app/components/workflow/store/workflow/workflow-draft-slice.ts b/web/app/components/workflow/store/workflow/workflow-draft-slice.ts new file mode 100644 index 0000000000..ec28debee2 --- /dev/null +++ b/web/app/components/workflow/store/workflow/workflow-draft-slice.ts @@ -0,0 +1,36 @@ +import type { StateCreator } from 'zustand' +import { debounce } from 'lodash-es' +import type { Viewport } from 'reactflow' +import type { + Edge, + EnvironmentVariable, + Node, +} from '@/app/components/workflow/types' + +export type WorkflowDraftSliceShape = { + backupDraft?: { + nodes: Node[] + edges: Edge[] + viewport: Viewport + features: Record + environmentVariables: EnvironmentVariable[] + } + setBackupDraft: (backupDraft?: WorkflowDraftSliceShape['backupDraft']) => void + debouncedSyncWorkflowDraft: (fn: () => void) => void + syncWorkflowDraftHash: string + setSyncWorkflowDraftHash: (hash: string) => void + isSyncingWorkflowDraft: boolean + setIsSyncingWorkflowDraft: (isSyncingWorkflowDraft: boolean) => void +} + +export const createWorkflowDraftSlice: StateCreator = set => ({ + backupDraft: undefined, + setBackupDraft: backupDraft => set(() => ({ backupDraft })), + debouncedSyncWorkflowDraft: debounce((syncWorkflowDraft) => { + syncWorkflowDraft() + }, 5000), + syncWorkflowDraftHash: '', + setSyncWorkflowDraftHash: syncWorkflowDraftHash => set(() => ({ syncWorkflowDraftHash })), + isSyncingWorkflowDraft: false, + setIsSyncingWorkflowDraft: isSyncingWorkflowDraft => set(() => ({ isSyncingWorkflowDraft })), +}) diff --git a/web/app/components/workflow/store/workflow/workflow-slice.ts b/web/app/components/workflow/store/workflow/workflow-slice.ts new file mode 100644 index 0000000000..19248161d2 --- /dev/null +++ b/web/app/components/workflow/store/workflow/workflow-slice.ts @@ -0,0 +1,65 @@ +import type { StateCreator } from 'zustand' +import type { + Node, + WorkflowRunningData, +} from '@/app/components/workflow/types' + +type PreviewRunningData = WorkflowRunningData & { + resultTabActive?: boolean + resultText?: string +} + +export type WorkflowSliceShape = { + appId: string + workflowRunningData?: PreviewRunningData + setWorkflowRunningData: (workflowData: PreviewRunningData) => void + notInitialWorkflow: boolean + setNotInitialWorkflow: (notInitialWorkflow: boolean) => void + clipboardElements: Node[] + setClipboardElements: (clipboardElements: Node[]) => void + selection: null | { x1: number; y1: number; x2: number; y2: number } + setSelection: (selection: WorkflowSliceShape['selection']) => void + bundleNodeSize: { width: number; height: number } | null + setBundleNodeSize: (bundleNodeSize: WorkflowSliceShape['bundleNodeSize']) => void + controlMode: 'pointer' | 'hand' + setControlMode: (controlMode: WorkflowSliceShape['controlMode']) => void + mousePosition: { pageX: number; pageY: number; elementX: number; elementY: number } + setMousePosition: (mousePosition: WorkflowSliceShape['mousePosition']) => void + showConfirm?: { title: string; desc?: string; onConfirm: () => void } + setShowConfirm: (showConfirm: WorkflowSliceShape['showConfirm']) => void + controlPromptEditorRerenderKey: number + setControlPromptEditorRerenderKey: (controlPromptEditorRerenderKey: number) => void + showImportDSLModal: boolean + setShowImportDSLModal: (showImportDSLModal: boolean) => void + showTips: string + setShowTips: (showTips: string) => void +} + +export const createWorkflowSlice: StateCreator = set => ({ + appId: '', + workflowRunningData: undefined, + setWorkflowRunningData: workflowRunningData => set(() => ({ workflowRunningData })), + notInitialWorkflow: false, + setNotInitialWorkflow: notInitialWorkflow => set(() => ({ notInitialWorkflow })), + clipboardElements: [], + setClipboardElements: clipboardElements => set(() => ({ clipboardElements })), + selection: null, + setSelection: selection => set(() => ({ selection })), + bundleNodeSize: null, + setBundleNodeSize: bundleNodeSize => set(() => ({ bundleNodeSize })), + controlMode: localStorage.getItem('workflow-operation-mode') === 'pointer' ? 'pointer' : 'hand', + setControlMode: (controlMode) => { + set(() => ({ controlMode })) + localStorage.setItem('workflow-operation-mode', controlMode) + }, + mousePosition: { pageX: 0, pageY: 0, elementX: 0, elementY: 0 }, + setMousePosition: mousePosition => set(() => ({ mousePosition })), + showConfirm: undefined, + setShowConfirm: showConfirm => set(() => ({ showConfirm })), + controlPromptEditorRerenderKey: 0, + setControlPromptEditorRerenderKey: controlPromptEditorRerenderKey => set(() => ({ controlPromptEditorRerenderKey })), + showImportDSLModal: false, + setShowImportDSLModal: showImportDSLModal => set(() => ({ showImportDSLModal })), + showTips: '', + setShowTips: showTips => set(() => ({ showTips })), +})