import { type MouseEvent as ReactMouseEvent, useState } from "react"; import Icon from "../../components/common/Icon"; import type { ScriptItem, WorkspaceDirectory, } from "~/services/api"; export type WorkspaceTreeTarget = { kind: "root" | "directory" | "file"; path: string; script?: ScriptItem; }; type WorkspaceTreeProps = { title: string; scripts: ScriptItem[]; directories: WorkspaceDirectory[]; selectedId: string | null; onSelect: (id: string) => void; onContextMenu?: ( event: ReactMouseEvent, target: WorkspaceTreeTarget, ) => void; readOnly?: boolean; }; type WorkspaceTreeItemsProps = Omit & { path: string; depth: number; }; function formatTime(value: string) { return new Intl.DateTimeFormat("zh-CN", { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", hour12: false, }).format(new Date(value)); } export function scriptIcon(item: ScriptItem) { return item.script_type === "notebook" ? "notebook" : "python"; } function ownedScriptPath(item: ScriptItem) { return item.relative_path.replaceAll("\\", "/").split("/").slice(2).join("/"); } function parentOf(path: string) { const parts = path.split("/"); parts.pop(); return parts.join("/"); } export function WorkspaceTreeGroup({ title, scripts, directories, selectedId, onSelect, onContextMenu, readOnly = false, }: WorkspaceTreeProps) { const [open, setOpen] = useState(true); return (
{open && (
{scripts.length === 0 && directories.length === 0 && (

{readOnly ? "暂无文件" : "右键此目录即可新建或上传"}

)}
)}
); } function WorkspaceTreeItems({ path, depth, scripts, directories, selectedId, onSelect, onContextMenu, }: WorkspaceTreeItemsProps) { const childDirectories = directories.filter( (item) => item.parent_path === path, ); const childScripts = scripts.filter( (item) => parentOf(ownedScriptPath(item)) === path, ); return ( <> {childDirectories.map((directory) => ( ))} {childScripts.map((item) => ( ))} ); } function DirectoryBranch({ directory, depth, scripts, directories, selectedId, onSelect, onContextMenu, }: Omit & { directory: WorkspaceDirectory; }) { const [open, setOpen] = useState(true); return (
{open && ( )}
); }