fix: workspace delete mixed-content error via top-level endpoint

- Add top-level DELETE /workspaces/{workspace_id} endpoint (avoids nested path)
- Frontend deleteWorkspace now uses /workspaces/{id}/?force=... (no project/repo needed)
- Update useWorkspaceActions, ProjectsPage, WorkspacesPage to match new signature

Quality gates: ruff clean, tsc --noEmit clean, pytest workspaces API (9 passed, 1 skipped)
This commit is contained in:
2026-06-01 20:03:24 +02:00
parent 9a036f1968
commit 95efa5d029
6 changed files with 46 additions and 24 deletions
+3 -7
View File
@@ -124,15 +124,11 @@ export const ProjectsPage = () => {
}
};
const handleDeleteWorkspace = async (
projectId: string,
repoId: string,
workspace: WorkspaceSummary,
) => {
const handleDeleteWorkspace = async (workspace: WorkspaceSummary) => {
if (!confirm(`Delete workspace "${workspace.name}"?`)) return;
setWorkspaceLoading(workspace.id);
try {
await deleteWorkspace(projectId, repoId, workspace.id);
await deleteWorkspace(workspace.id);
reload();
} catch (err) {
alert(err instanceof Error ? err.message : "Failed to delete workspace");
@@ -187,7 +183,7 @@ export const ProjectsPage = () => {
if (action === "sync") {
void handleSyncWorkspace(project.id, repoId, workspace);
} else if (action === "delete") {
void handleDeleteWorkspace(project.id, repoId, workspace);
void handleDeleteWorkspace(workspace);
}
}}
workspaceLoading={workspaceLoading}
+1 -6
View File
@@ -18,12 +18,7 @@ export function WorkspacesPage() {
const actions = useWorkspaceActions();
const handleDelete = async (workspace: Workspace) => {
await actions.delete(
workspace.project_id,
workspace.repo_id,
workspace,
refresh,
);
await actions.delete(workspace, refresh);
};
const handleSync = async (workspace: Workspace) => {