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:
@@ -71,13 +71,11 @@ export async function updateWorkspace(
|
||||
}
|
||||
|
||||
export async function deleteWorkspace(
|
||||
projectId: string,
|
||||
repoId: string,
|
||||
workspaceId: string,
|
||||
force = false,
|
||||
): Promise<{ status: string }> {
|
||||
const response = await apiClient.delete<{ status: string }>(
|
||||
`${workspaceUrl(projectId, repoId, workspaceId)}?force=${force}`,
|
||||
`/workspaces/${workspaceId}/?force=${force}`,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@ export interface UseWorkspaceActionsResult {
|
||||
data: CreateWorkspaceRequest,
|
||||
) => Promise<Workspace>;
|
||||
delete: (
|
||||
projectId: string,
|
||||
repoId: string,
|
||||
workspace: Workspace,
|
||||
onRefresh: () => Promise<void>,
|
||||
) => Promise<void>;
|
||||
@@ -61,14 +59,12 @@ export function useWorkspaceActions(): UseWorkspaceActionsResult {
|
||||
|
||||
const deleteAction = useCallback(
|
||||
async (
|
||||
projectId: string,
|
||||
repoId: string,
|
||||
workspace: Workspace,
|
||||
onRefresh: () => Promise<void>,
|
||||
) => {
|
||||
setLoadingId(workspace.id);
|
||||
try {
|
||||
await deleteWorkspace(projectId, repoId, workspace.id);
|
||||
await deleteWorkspace(workspace.id);
|
||||
await onRefresh();
|
||||
} catch (err) {
|
||||
const error = err as ApiError;
|
||||
@@ -81,7 +77,7 @@ export function useWorkspaceActions(): UseWorkspaceActionsResult {
|
||||
`\n\nDelete workspace and all instances?`,
|
||||
);
|
||||
if (confirmed) {
|
||||
await deleteWorkspace(projectId, repoId, workspace.id, true);
|
||||
await deleteWorkspace(workspace.id, true);
|
||||
await onRefresh();
|
||||
}
|
||||
} else {
|
||||
@@ -118,7 +114,7 @@ export function useWorkspaceActions(): UseWorkspaceActionsResult {
|
||||
`${message}\n\nDelete this workspace?`,
|
||||
);
|
||||
if (confirmed) {
|
||||
await deleteWorkspace(projectId, repoId, workspace.id, true);
|
||||
await deleteWorkspace(workspace.id, true);
|
||||
await onRefresh();
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
Reference in New Issue
Block a user