Fix: add persisted project folder deletion
This commit is contained in:
@@ -658,28 +658,65 @@ export const ProjectSelector = (props: ProjectSelectorProps): JSX.Element => {
|
||||
}
|
||||
};
|
||||
|
||||
const deletePersistedFolder = async (folderId: string): Promise<void> => {
|
||||
const projectId = selectedProject().id;
|
||||
if (!folderId || !isUuidString(projectId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${resolveAPIBase()}/projects/${projectId}/folders?folderId=${encodeURIComponent(folderId)}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const body = (await response.json()) as ProjectFoldersResponse;
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(body.message || "Failed to delete project folder.");
|
||||
}
|
||||
|
||||
setPersistedFolders(readPersistedFolders(body));
|
||||
setCollapsedFolderIds((current) => current.filter((id) => id !== folderId));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const cancelPendingFolder = (): void => {
|
||||
setPendingFolderDraft(null);
|
||||
setPendingFolderName("");
|
||||
};
|
||||
|
||||
const handleContextActionSelect = (action: { id: string; label: string }, target: ProjectMenuTarget): void => {
|
||||
if (action.id !== "new-folder") {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (target.kind) {
|
||||
case "surface":
|
||||
beginFolderDraft(null, 0);
|
||||
switch (action.id) {
|
||||
case "new-folder":
|
||||
switch (target.kind) {
|
||||
case "surface":
|
||||
beginFolderDraft(null, 0);
|
||||
return;
|
||||
case "folder":
|
||||
beginFolderDraft(target.id, (findTreeNodeDepth(projectTreeNodes(), target.id, projectTreeAdapter) ?? 0) + 1);
|
||||
return;
|
||||
case "project": {
|
||||
const parentId = findTreeNodeLocation(projectTreeNodes(), target.id, projectTreeAdapter)?.parentId ?? null;
|
||||
beginFolderDraft(parentId, parentId ? (findTreeNodeDepth(projectTreeNodes(), parentId, projectTreeAdapter) ?? 0) + 1 : 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
case "folder":
|
||||
beginFolderDraft(target.id, (findTreeNodeDepth(projectTreeNodes(), target.id, projectTreeAdapter) ?? 0) + 1);
|
||||
case "delete-folder":
|
||||
if (target.kind === "folder") {
|
||||
void deletePersistedFolder(target.id);
|
||||
}
|
||||
return;
|
||||
case "project": {
|
||||
const parentId = findTreeNodeLocation(projectTreeNodes(), target.id, projectTreeAdapter)?.parentId ?? null;
|
||||
beginFolderDraft(parentId, parentId ? (findTreeNodeDepth(projectTreeNodes(), parentId, projectTreeAdapter) ?? 0) + 1 : 0);
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -581,6 +581,36 @@ export const WorkspaceSidebar = (props: WorkspaceSidebarProps): JSX.Element => {
|
||||
}
|
||||
};
|
||||
|
||||
const deletePersistedFolder = async (folderId: string): Promise<void> => {
|
||||
const projectId = activeProject()?.id ?? "";
|
||||
if (!folderId || !projectId || !isUuidString(projectId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${resolveAPIBase()}/projects/${projectId}/tree/folders?folderId=${encodeURIComponent(folderId)}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const body = (await response.json()) as WorkspaceFoldersResponse;
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(body.message || "Failed to delete project tree folder.");
|
||||
}
|
||||
|
||||
setPersistedFolders(readPersistedWorkspaceFolders(body));
|
||||
setCollapsedFolderIds((current) => current.filter((id) => id !== folderId));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const cancelPendingFolder = (): void => {
|
||||
setPendingFolderDraft(null);
|
||||
setPendingFolderName("");
|
||||
@@ -639,20 +669,27 @@ export const WorkspaceSidebar = (props: WorkspaceSidebarProps): JSX.Element => {
|
||||
};
|
||||
|
||||
const handleContextActionSelect = (action: WorkspaceContextMenuAction, target: WorkspaceContextMenuTarget): void => {
|
||||
if (action.id !== "new-folder") {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (target.kind) {
|
||||
case "workspace":
|
||||
case "home":
|
||||
beginFolderDraft(null, 0);
|
||||
switch (action.id) {
|
||||
case "new-folder":
|
||||
switch (target.kind) {
|
||||
case "workspace":
|
||||
case "home":
|
||||
beginFolderDraft(null, 0);
|
||||
return;
|
||||
case "folder":
|
||||
beginFolderDraft(target.id, (findTreeNodeDepth(workspaceTreeNodes(), target.id, workspaceTreeAdapter) ?? 0) + 1);
|
||||
return;
|
||||
case "settings":
|
||||
case "item":
|
||||
return;
|
||||
}
|
||||
return;
|
||||
case "folder":
|
||||
beginFolderDraft(target.id, (findTreeNodeDepth(workspaceTreeNodes(), target.id, workspaceTreeAdapter) ?? 0) + 1);
|
||||
case "delete-folder":
|
||||
if (target.kind === "folder") {
|
||||
void deletePersistedFolder(target.id);
|
||||
}
|
||||
return;
|
||||
case "settings":
|
||||
case "item":
|
||||
default:
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -597,6 +597,11 @@ const getProjectCreateActions = (): readonly ProjectContextMenuAction[] =>
|
||||
{ id: "new-folder", label: "New folder" },
|
||||
] as const;
|
||||
|
||||
const getProjectFolderDangerActions = (): readonly ProjectContextMenuAction[] =>
|
||||
[
|
||||
{ id: "delete-folder", label: "Delete", shortcut: { modifiers: ["meta"], key: "delete" }, tone: "danger" },
|
||||
] as const;
|
||||
|
||||
export const createProjectSurfaceTarget = (label = "Projects"): ProjectMenuTarget => ({
|
||||
id: "project-surface",
|
||||
label,
|
||||
@@ -643,6 +648,10 @@ export const getProjectContextMenuSections = (target: ProjectMenuTarget): readon
|
||||
id: "create",
|
||||
items: createActions,
|
||||
},
|
||||
{
|
||||
id: "organize",
|
||||
items: getProjectFolderDangerActions(),
|
||||
},
|
||||
] as const;
|
||||
case "project":
|
||||
return [
|
||||
|
||||
Reference in New Issue
Block a user