feat: project workspace clear/update UX and creation docs

Add granular workspace management — clear local folder or repo URL
independently instead of deleting the whole workspace. Fix project
create route typing. Document inline workspace creation in API docs
and skill references.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dotta
2026-03-02 14:21:03 -06:00
parent f54f30cb90
commit ff472af343
5 changed files with 135 additions and 20 deletions

View File

@@ -83,6 +83,11 @@ export function ProjectProperties({ project, onUpdate }: ProjectPropertiesProps)
mutationFn: (workspaceId: string) => projectsApi.removeWorkspace(project.id, workspaceId),
onSuccess: invalidateProject,
});
const updateWorkspace = useMutation({
mutationFn: ({ workspaceId, data }: { workspaceId: string; data: Record<string, unknown> }) =>
projectsApi.updateWorkspace(project.id, workspaceId, data),
onSuccess: invalidateProject,
});
const removeGoal = (goalId: string) => {
if (!onUpdate) return;
@@ -167,6 +172,41 @@ export function ProjectProperties({ project, onUpdate }: ProjectPropertiesProps)
});
};
const clearLocalWorkspace = (workspace: Project["workspaces"][number]) => {
const confirmed = window.confirm(
workspace.repoUrl
? "Clear local folder from this workspace?"
: "Delete this workspace local folder?",
);
if (!confirmed) return;
if (workspace.repoUrl) {
updateWorkspace.mutate({
workspaceId: workspace.id,
data: { cwd: null },
});
return;
}
removeWorkspace.mutate(workspace.id);
};
const clearRepoWorkspace = (workspace: Project["workspaces"][number]) => {
const hasLocalFolder = Boolean(workspace.cwd && workspace.cwd !== REPO_ONLY_CWD_SENTINEL);
const confirmed = window.confirm(
hasLocalFolder
? "Clear GitHub repo from this workspace?"
: "Delete this workspace repo?",
);
if (!confirmed) return;
if (hasLocalFolder) {
updateWorkspace.mutate({
workspaceId: workspace.id,
data: { repoUrl: null, repoRef: null },
});
return;
}
removeWorkspace.mutate(workspace.id);
};
return (
<div className="space-y-4">
<div className="space-y-1">
@@ -285,13 +325,8 @@ export function ProjectProperties({ project, onUpdate }: ProjectPropertiesProps)
<Button
variant="ghost"
size="icon-xs"
onClick={() => {
const confirmed = window.confirm("Delete this workspace?");
if (confirmed) {
removeWorkspace.mutate(workspace.id);
}
}}
aria-label="Delete workspace"
onClick={() => clearLocalWorkspace(workspace)}
aria-label="Delete local folder"
>
<Trash2 className="h-3 w-3" />
</Button>
@@ -312,13 +347,8 @@ export function ProjectProperties({ project, onUpdate }: ProjectPropertiesProps)
<Button
variant="ghost"
size="icon-xs"
onClick={() => {
const confirmed = window.confirm("Delete this workspace?");
if (confirmed) {
removeWorkspace.mutate(workspace.id);
}
}}
aria-label="Delete workspace"
onClick={() => clearRepoWorkspace(workspace)}
aria-label="Delete workspace repo"
>
<Trash2 className="h-3 w-3" />
</Button>
@@ -427,6 +457,9 @@ export function ProjectProperties({ project, onUpdate }: ProjectPropertiesProps)
{removeWorkspace.isError && (
<p className="text-xs text-destructive">Failed to delete workspace.</p>
)}
{updateWorkspace.isError && (
<p className="text-xs text-destructive">Failed to update workspace.</p>
)}
</div>
<Separator />