sidebar: click-to-rename org/company/team + strip synthetics from world viz
ci / gates (push) Successful in 7s
ci / frontend (push) Successful in 25s
ci / rust (push) Successful in 3m51s
ci / e2e (push) Has been skipped
ci / publish (push) Successful in 2m43s

Two related pieces of the "kill My Workspace" cleanup, landed
together because they share the same file:

Backend

- Three tiny inline-rename endpoints:
    PATCH /api/orgs/{id}/name
    PATCH /api/companies/{id}/name
    PATCH /api/teams/{id}/name
  Each takes { name: string }, trims + rejects empty, returns 204.
  Backed by rename_org / rename_company / rename_team in cm-db —
  single-row UPDATEs scoped to the caller's workspace, NotFound if
  the id isn't visible.
- Registered next to the existing PATCH /:id (topology) routes so
  they don't collide.

Frontend

- StructureTree accepts an optional onRename and canRename.
  TreeRow: click on the label text of a renamable node → the span
  becomes an <input>, focus + select-all, save on Enter or blur,
  cancel on Escape. The rest of the row (row chevron / row body)
  still navigates + selects as before, so single-click behaviour
  is preserved for everything except the name text itself.
  react-hooks/set-state-in-effect avoided by resetting the draft
  in the enterEdit() click handler instead of inside a useEffect.

- Dashboard passes canRename={item.level !== "claw" && !synthetic}
  (claws don't have a rename endpoint yet; synthetic scaffolding
  gets reified into real rows in the next commit — the wizard
  auto-materialize + orphan-migration dialog).
  onRename fires the corresponding PATCH and calls router.refresh()
  so the label lands in every consumer of the tree.

- World viz seed: new stripSynthetics(roots) helper walks the tree
  and lifts children of any synthetic container up to their
  grandparent's level. worldCanvasRoots feeds through this before
  narrowRoots(). Result: the Live viz no longer shows "My Workspace"
  or "Teams" nodes — real agents orbit the world root directly
  (which is what you were asking for). Sidebar tree still shows
  them so orphaned agents remain visible until the migration lands.
This commit is contained in:
Omar Sobh
2026-07-09 11:18:52 -07:00
parent a7cb895099
commit 99e5207e69
9 changed files with 251 additions and 17 deletions
+21
View File
@@ -152,6 +152,27 @@ pub struct OrgDetail {
}
/// `GET /api/orgs/{id}` — an org's graph + node→company bindings.
/// `PATCH /api/orgs/{id}/name` — inline rename from the sidebar. Trims the
/// input and rejects empty; returns 204 on success, 404 if the id isn't
/// visible in the caller's workspace.
#[derive(Deserialize)]
pub struct RenameOrgRequest {
pub name: String,
}
pub async fn rename_org(
State(state): State<AppState>,
Authed(user): Authed,
Path(id): Path<Uuid>,
Json(body): Json<RenameOrgRequest>,
) -> Result<StatusCode, ApiError> {
let name = body.name.trim();
if name.is_empty() {
return Err(ApiError::BadRequest);
}
cm_db::repo::orgs::rename_org(&state.pool, id, user.workspace_id, name).await?;
Ok(StatusCode::NO_CONTENT)
}
/// `DELETE /api/orgs/{id}` — remove the org (structural: companies survive, just
/// ungrouped from it).
pub async fn delete_org(