mirror of
https://github.com/langgenius/dify.git
synced 2026-04-23 20:36:14 +08:00
- Add right-click context menu and '...' more button for files - Files now support Rename and Delete operations - Created file-node-menu.tsx for file-specific menu - Refactor component naming for consistency - file-item-menu.tsx -> file-node-menu.tsx (unify 'node' terminology) - file-operations-menu.tsx -> folder-node-menu.tsx (clarify folder menu) - file-tree-context-menu.tsx -> tree-context-menu.tsx (simplify) - file-tree-node.tsx -> tree-node.tsx (simplify) - files.tsx -> file-tree.tsx (more descriptive) - Renamed internal components: FileTreeNode -> TreeNode, Files -> FileTree - Add context menu node highlight - When right-clicking a node, it now shows hover highlight - Subscribed to contextMenu.nodeId in TreeNode component
77 lines
2.1 KiB
TypeScript
77 lines
2.1 KiB
TypeScript
'use client'
|
|
|
|
import type { FC } from 'react'
|
|
import type { TreeApi } from 'react-arborist'
|
|
import type { TreeNodeData } from './type'
|
|
import { useClickAway } from 'ahooks'
|
|
import * as React from 'react'
|
|
import { useCallback, useMemo, useRef } from 'react'
|
|
import { useStore as useAppStore } from '@/app/components/app/store'
|
|
import { useGetAppAssetTree } from '@/service/use-app-asset'
|
|
import FileNodeMenu from './file-node-menu'
|
|
import FolderNodeMenu from './folder-node-menu'
|
|
import { useSkillEditorStore, useSkillEditorStoreApi } from './store'
|
|
import { findNodeById } from './utils/tree-utils'
|
|
|
|
type TreeContextMenuProps = {
|
|
treeRef: React.RefObject<TreeApi<TreeNodeData> | null>
|
|
}
|
|
|
|
const TreeContextMenu: FC<TreeContextMenuProps> = ({ treeRef }) => {
|
|
const ref = useRef<HTMLDivElement>(null)
|
|
const contextMenu = useSkillEditorStore(s => s.contextMenu)
|
|
const storeApi = useSkillEditorStoreApi()
|
|
|
|
const appDetail = useAppStore(s => s.appDetail)
|
|
const appId = appDetail?.id || ''
|
|
const { data: treeData } = useGetAppAssetTree(appId)
|
|
|
|
const handleClose = useCallback(() => {
|
|
storeApi.getState().setContextMenu(null)
|
|
}, [storeApi])
|
|
|
|
useClickAway(() => {
|
|
handleClose()
|
|
}, ref)
|
|
|
|
const targetNode = useMemo(() => {
|
|
if (!contextMenu?.nodeId || !treeData?.children)
|
|
return null
|
|
return findNodeById(treeData.children, contextMenu.nodeId)
|
|
}, [contextMenu?.nodeId, treeData?.children])
|
|
|
|
const isFolder = targetNode?.node_type === 'folder'
|
|
|
|
if (!contextMenu)
|
|
return null
|
|
|
|
return (
|
|
<div
|
|
ref={ref}
|
|
className="fixed z-[100]"
|
|
style={{
|
|
top: contextMenu.top,
|
|
left: contextMenu.left,
|
|
}}
|
|
>
|
|
{isFolder
|
|
? (
|
|
<FolderNodeMenu
|
|
nodeId={contextMenu.nodeId}
|
|
onClose={handleClose}
|
|
treeRef={treeRef}
|
|
/>
|
|
)
|
|
: (
|
|
<FileNodeMenu
|
|
nodeId={contextMenu.nodeId}
|
|
onClose={handleClose}
|
|
treeRef={treeRef}
|
|
/>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default React.memo(TreeContextMenu)
|