mirror of
https://github.com/langgenius/dify.git
synced 2026-05-05 18:08:07 +08:00
refactor(skill): migrate skill editor store to workflow store slice injection
Refactor the skill editor state management from a standalone Zustand store with Context provider pattern to a slice injection pattern that integrates with the existing workflow store. This aligns with how rag-pipeline already injects its slice. - Remove SkillEditorProvider and SkillEditorContext - Export createSkillEditorSlice for injection into workflow store - Update all components to use useStore/useWorkflowStore from workflow store - Add SkillEditorSliceShape to SliceFromInjection union type - Use type-safe slice creator args without any types
This commit is contained in:
@ -13,10 +13,10 @@ import { useTranslation } from 'react-i18next'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { useStore, useWorkflowStore } from '@/app/components/workflow/store'
|
||||
import { useRenameAppAssetNode } from '@/service/use-app-asset'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { useSkillAssetTreeData } from '../hooks/use-skill-asset-tree'
|
||||
import { useSkillEditorStore, useSkillEditorStoreApi } from '../store'
|
||||
import { getAncestorIds } from '../utils/tree-utils'
|
||||
import TreeContextMenu from './tree-context-menu'
|
||||
import TreeNode from './tree-node'
|
||||
@ -49,9 +49,9 @@ const FileTree: React.FC<FileTreeProps> = ({ className }) => {
|
||||
const { data: treeData, isLoading, error } = useSkillAssetTreeData()
|
||||
const isMutating = useIsMutating() > 0
|
||||
|
||||
const expandedFolderIds = useSkillEditorStore(s => s.expandedFolderIds)
|
||||
const activeTabId = useSkillEditorStore(s => s.activeTabId)
|
||||
const storeApi = useSkillEditorStoreApi()
|
||||
const expandedFolderIds = useStore(s => s.expandedFolderIds!)
|
||||
const activeTabId = useStore(s => s.activeTabId!)
|
||||
const storeApi = useWorkflowStore()
|
||||
|
||||
const renameNode = useRenameAppAssetNode()
|
||||
|
||||
@ -62,12 +62,12 @@ const FileTree: React.FC<FileTreeProps> = ({ className }) => {
|
||||
}, [expandedFolderIds])
|
||||
|
||||
const handleToggle = useCallback((id: string) => {
|
||||
storeApi.getState().toggleFolder(id)
|
||||
storeApi.getState().toggleFolder?.(id)
|
||||
}, [storeApi])
|
||||
|
||||
const handleActivate = useCallback((node: NodeApi<TreeNodeData>) => {
|
||||
if (node.data.node_type === 'file')
|
||||
storeApi.getState().openTab(node.data.id, { pinned: true })
|
||||
storeApi.getState().openTab?.(node.data.id, { pinned: true })
|
||||
else
|
||||
node.toggle()
|
||||
}, [storeApi])
|
||||
@ -95,7 +95,7 @@ const FileTree: React.FC<FileTreeProps> = ({ className }) => {
|
||||
|
||||
const ancestors = getAncestorIds(activeTabId, treeData.children)
|
||||
if (ancestors.length > 0)
|
||||
storeApi.getState().revealFile(ancestors)
|
||||
storeApi.getState().revealFile?.(ancestors)
|
||||
requestAnimationFrame(() => {
|
||||
const node = tree.get(activeTabId)
|
||||
if (node) {
|
||||
|
||||
@ -6,8 +6,8 @@ import type { TreeNodeData } from '../type'
|
||||
import { useClickAway } from 'ahooks'
|
||||
import * as React from 'react'
|
||||
import { useCallback, useMemo, useRef } from 'react'
|
||||
import { useStore, useWorkflowStore } from '@/app/components/workflow/store'
|
||||
import { useSkillAssetTreeData } from '../hooks/use-skill-asset-tree'
|
||||
import { useSkillEditorStore, useSkillEditorStoreApi } from '../store'
|
||||
import { findNodeById } from '../utils/tree-utils'
|
||||
import NodeMenu from './node-menu'
|
||||
|
||||
@ -17,12 +17,12 @@ type TreeContextMenuProps = {
|
||||
|
||||
const TreeContextMenu: FC<TreeContextMenuProps> = ({ treeRef }) => {
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const contextMenu = useSkillEditorStore(s => s.contextMenu)
|
||||
const storeApi = useSkillEditorStoreApi()
|
||||
const contextMenu = useStore(s => s.contextMenu)
|
||||
const storeApi = useWorkflowStore()
|
||||
const { data: treeData } = useSkillAssetTreeData()
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
storeApi.getState().setContextMenu(null)
|
||||
storeApi.getState().setContextMenu?.(null)
|
||||
}, [storeApi])
|
||||
|
||||
useClickAway(() => {
|
||||
|
||||
@ -14,9 +14,9 @@ import {
|
||||
PortalToFollowElemContent,
|
||||
PortalToFollowElemTrigger,
|
||||
} from '@/app/components/base/portal-to-follow-elem'
|
||||
import { useStore, useWorkflowStore } from '@/app/components/workflow/store'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { useDelayedClick } from '../hooks/use-delayed-click'
|
||||
import { useSkillEditorStore, useSkillEditorStoreApi } from '../store'
|
||||
import { getFileIconType } from '../utils/file-utils'
|
||||
import NodeMenu from './node-menu'
|
||||
import TreeEditInput from './tree-edit-input'
|
||||
@ -26,10 +26,10 @@ const TreeNode = ({ node, style, dragHandle }: NodeRendererProps<TreeNodeData>)
|
||||
const { t } = useTranslation('workflow')
|
||||
const isFolder = node.data.node_type === 'folder'
|
||||
const isSelected = node.isSelected
|
||||
const isDirty = useSkillEditorStore(s => s.dirtyContents.has(node.data.id))
|
||||
const contextMenuNodeId = useSkillEditorStore(s => s.contextMenu?.nodeId)
|
||||
const isDirty = useStore(s => s.dirtyContents?.has(node.data.id) ?? false)
|
||||
const contextMenuNodeId = useStore(s => s.contextMenu?.nodeId)
|
||||
const hasContextMenu = contextMenuNodeId === node.data.id
|
||||
const storeApi = useSkillEditorStoreApi()
|
||||
const storeApi = useWorkflowStore()
|
||||
|
||||
const [showDropdown, setShowDropdown] = useState(false)
|
||||
|
||||
@ -41,11 +41,11 @@ const TreeNode = ({ node, style, dragHandle }: NodeRendererProps<TreeNodeData>)
|
||||
)
|
||||
|
||||
const openFilePreview = useCallback(() => {
|
||||
storeApi.getState().openTab(node.data.id, { pinned: false })
|
||||
storeApi.getState().openTab?.(node.data.id, { pinned: false })
|
||||
}, [node.data.id, storeApi])
|
||||
|
||||
const openFilePinned = useCallback(() => {
|
||||
storeApi.getState().openTab(node.data.id, { pinned: true })
|
||||
storeApi.getState().openTab?.(node.data.id, { pinned: true })
|
||||
}, [node.data.id, storeApi])
|
||||
|
||||
const { handleClick: handleFileClick, handleDoubleClick: handleFileDoubleClick } = useDelayedClick({
|
||||
@ -79,7 +79,7 @@ const TreeNode = ({ node, style, dragHandle }: NodeRendererProps<TreeNodeData>)
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
storeApi.getState().setContextMenu({
|
||||
storeApi.getState().setContextMenu?.({
|
||||
top: e.clientY,
|
||||
left: e.clientX,
|
||||
nodeId: node.data.id,
|
||||
@ -97,7 +97,7 @@ const TreeNode = ({ node, style, dragHandle }: NodeRendererProps<TreeNodeData>)
|
||||
if (isFolder)
|
||||
node.toggle()
|
||||
else
|
||||
storeApi.getState().openTab(node.data.id, { pinned: true })
|
||||
storeApi.getState().openTab?.(node.data.id, { pinned: true })
|
||||
}
|
||||
}, [isFolder, node, storeApi])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user