update: dir tree
This commit is contained in:
@@ -19,6 +19,7 @@ type TreeContextMenuProps = {
|
|||||||
onChooseUpload: (parentPath: string) => void;
|
onChooseUpload: (parentPath: string) => void;
|
||||||
onRemoveDirectory: (path: string) => void;
|
onRemoveDirectory: (path: string) => void;
|
||||||
onCopyResourcePath?: (jupyterPath: string) => void;
|
onCopyResourcePath?: (jupyterPath: string) => void;
|
||||||
|
onRemoveResource?: (resourceId: string) => void;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -32,6 +33,7 @@ export function TreeContextMenu({
|
|||||||
onChooseUpload,
|
onChooseUpload,
|
||||||
onRemoveDirectory,
|
onRemoveDirectory,
|
||||||
onCopyResourcePath,
|
onCopyResourcePath,
|
||||||
|
onRemoveResource,
|
||||||
onClose,
|
onClose,
|
||||||
}: TreeContextMenuProps) {
|
}: TreeContextMenuProps) {
|
||||||
if (!contextMenu) return null;
|
if (!contextMenu) return null;
|
||||||
@@ -55,6 +57,7 @@ export function TreeContextMenu({
|
|||||||
{contextMenu.kind === "file" && contextMenu.script ? (
|
{contextMenu.kind === "file" && contextMenu.script ? (
|
||||||
<>
|
<>
|
||||||
{isDataResource ? (
|
{isDataResource ? (
|
||||||
|
<>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
role="menuitem"
|
role="menuitem"
|
||||||
@@ -68,6 +71,22 @@ export function TreeContextMenu({
|
|||||||
<Icon name="database" size={16} />
|
<Icon name="database" size={16} />
|
||||||
复制 Jupyter 路径
|
复制 Jupyter 路径
|
||||||
</button>
|
</button>
|
||||||
|
{onRemoveResource && (
|
||||||
|
<button
|
||||||
|
className="is-danger"
|
||||||
|
type="button"
|
||||||
|
role="menuitem"
|
||||||
|
onClick={() => {
|
||||||
|
const id = contextMenu.script!.script_id.replace(/^data:/, "");
|
||||||
|
onRemoveResource(id);
|
||||||
|
onClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon name="close" size={16} />
|
||||||
|
删除资源
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -232,6 +232,8 @@ export function useApi(): WorkspaceBoundApi {
|
|||||||
rawApi.uploadResourceBytes(workspaceId, uploadId, fileBytes, contentType),
|
rawApi.uploadResourceBytes(workspaceId, uploadId, fileBytes, contentType),
|
||||||
bindResourceUpload: (uploadId, body) =>
|
bindResourceUpload: (uploadId, body) =>
|
||||||
rawApi.bindResourceUpload(workspaceId, uploadId, body),
|
rawApi.bindResourceUpload(workspaceId, uploadId, body),
|
||||||
|
deleteResource: (resourceId) =>
|
||||||
|
rawApi.deleteResource(workspaceId, resourceId),
|
||||||
updateScript: (scriptId, input) =>
|
updateScript: (scriptId, input) =>
|
||||||
rawApi.updateScript(workspaceId, scriptId, input),
|
rawApi.updateScript(workspaceId, scriptId, input),
|
||||||
deleteScript: (scriptId) => rawApi.deleteScript(workspaceId, scriptId),
|
deleteScript: (scriptId) => rawApi.deleteScript(workspaceId, scriptId),
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ export default function ScriptsPage() {
|
|||||||
const uploadDataResource = useScriptWorkspaceStore((s) => s.uploadDataResource);
|
const uploadDataResource = useScriptWorkspaceStore((s) => s.uploadDataResource);
|
||||||
const createFolder = useScriptWorkspaceStore((s) => s.createFolder);
|
const createFolder = useScriptWorkspaceStore((s) => s.createFolder);
|
||||||
const deleteScript = useScriptWorkspaceStore((s) => s.deleteScript);
|
const deleteScript = useScriptWorkspaceStore((s) => s.deleteScript);
|
||||||
|
const deleteDataResource = useScriptWorkspaceStore((s) => s.deleteDataResource);
|
||||||
const deleteDirectory = useScriptWorkspaceStore((s) => s.deleteDirectory);
|
const deleteDirectory = useScriptWorkspaceStore((s) => s.deleteDirectory);
|
||||||
const toggleScriptLock = useScriptWorkspaceStore((s) => s.toggleScriptLock);
|
const toggleScriptLock = useScriptWorkspaceStore((s) => s.toggleScriptLock);
|
||||||
const openPublishDialog = useScriptWorkspaceStore((s) => s.openPublishDialog);
|
const openPublishDialog = useScriptWorkspaceStore((s) => s.openPublishDialog);
|
||||||
@@ -421,6 +422,7 @@ export default function ScriptsPage() {
|
|||||||
onChooseUpload={(parentPath) => triggerUpload(parentPath ?? "")}
|
onChooseUpload={(parentPath) => triggerUpload(parentPath ?? "")}
|
||||||
onRemoveDirectory={(p) => void deleteDirectory(p)}
|
onRemoveDirectory={(p) => void deleteDirectory(p)}
|
||||||
onCopyResourcePath={(p) => void handleCopyResourcePath(p)}
|
onCopyResourcePath={(p) => void handleCopyResourcePath(p)}
|
||||||
|
onRemoveResource={(id) => void deleteDataResource(id)}
|
||||||
onClose={closeContextMenu}
|
onClose={closeContextMenu}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
bindScriptWorkspaceApi,
|
|
||||||
editSessionHandle,
|
editSessionHandle,
|
||||||
useScriptWorkspaceStore,
|
useScriptWorkspaceStore,
|
||||||
} from "../state/scriptWorkspaceStore";
|
} from "../state/scriptWorkspaceStore";
|
||||||
@@ -61,11 +60,4 @@ export function useEditSessionLifecycle({
|
|||||||
window.addEventListener("beforeunload", handleUnload);
|
window.addEventListener("beforeunload", handleUnload);
|
||||||
return () => window.removeEventListener("beforeunload", handleUnload);
|
return () => window.removeEventListener("beforeunload", handleUnload);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// 4) layout 卸载时解绑 api
|
|
||||||
useEffect(() => {
|
|
||||||
return () => {
|
|
||||||
bindScriptWorkspaceApi(null);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ type State = {
|
|||||||
}) => Promise<ResourceItem | null>;
|
}) => Promise<ResourceItem | null>;
|
||||||
createFolder: (name: string, parentPath: string) => Promise<void>;
|
createFolder: (name: string, parentPath: string) => Promise<void>;
|
||||||
deleteScript: (script: ScriptItem) => Promise<void>;
|
deleteScript: (script: ScriptItem) => Promise<void>;
|
||||||
|
deleteDataResource: (resourceId: string) => Promise<void>;
|
||||||
deleteDirectory: (path: string) => Promise<void>;
|
deleteDirectory: (path: string) => Promise<void>;
|
||||||
toggleExpanded: (path: string, loadPath?: string) => Promise<void>;
|
toggleExpanded: (path: string, loadPath?: string) => Promise<void>;
|
||||||
loadChildren: (parentPath: string) => Promise<void>;
|
loadChildren: (parentPath: string) => Promise<void>;
|
||||||
@@ -856,6 +857,28 @@ export const useScriptWorkspaceStore = create<State>((set, get) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
deleteDataResource: async (resourceId) => {
|
||||||
|
const api = requireApi();
|
||||||
|
useUiStore.getState().closeContextMenu();
|
||||||
|
if (!window.confirm(`确定删除数据资源吗?稳定版本会保留。`)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await api.deleteResource(resourceId);
|
||||||
|
set((state) => ({
|
||||||
|
dataResources: state.dataResources.filter(
|
||||||
|
(r) => r.resource_id !== resourceId,
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
pushToast("success", "数据资源已删除");
|
||||||
|
} catch (error) {
|
||||||
|
pushToast(
|
||||||
|
"error",
|
||||||
|
error instanceof Error ? error.message : "数据资源删除失败",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
createFolder: async (name, parentPath) => {
|
createFolder: async (name, parentPath) => {
|
||||||
const api = requireApi();
|
const api = requireApi();
|
||||||
const trimmed = name.trim();
|
const trimmed = name.trim();
|
||||||
|
|||||||
@@ -428,6 +428,17 @@ export async function listResources(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function deleteResource(
|
||||||
|
workspaceId: string,
|
||||||
|
resourceId: string,
|
||||||
|
): Promise<{ resource_id: string; status: string }> {
|
||||||
|
return apiRequest<{ resource_id: string; status: string }>(
|
||||||
|
`/api/v1/data-resources/${encodeURIComponent(resourceId)}`,
|
||||||
|
{ method: "DELETE" },
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export async function createResourceUpload(
|
export async function createResourceUpload(
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
body: {
|
body: {
|
||||||
@@ -1462,6 +1473,9 @@ export type WorkspaceBoundApi = {
|
|||||||
uploadId: string,
|
uploadId: string,
|
||||||
body: Parameters<typeof bindResourceUpload>[2],
|
body: Parameters<typeof bindResourceUpload>[2],
|
||||||
) => Promise<ResourceItem>;
|
) => Promise<ResourceItem>;
|
||||||
|
deleteResource: (
|
||||||
|
resourceId: string,
|
||||||
|
) => Promise<{ resource_id: string; status: string }>;
|
||||||
updateScript: (
|
updateScript: (
|
||||||
scriptId: string,
|
scriptId: string,
|
||||||
input: Parameters<typeof updateScript>[2],
|
input: Parameters<typeof updateScript>[2],
|
||||||
|
|||||||
Reference in New Issue
Block a user