fix(ui): clicking "My Workforce" offered to rebuild the hierarchy it replaced
Clicking the root opened the orphan-migration dialog: "You have some entities that never got parented into a real org → company → team chain. Naming the three below will materialize the chain and move everything under it in one transaction." which is an offer to reconstruct exactly the structure that root exists to replace. `SYNTHETIC_TREE_IDS` was doing three jobs at once — "not a database row, so cannot be renamed or selected for reap" AND "is a placeholder for unparented entities, so clicking it offers the migration" — and adding `my-workforce` to it inherited the second along with the first. Split by what each set is FOR. `ORPHAN_CONTAINER_IDS` are the placeholders the migration applies to and the nodes the world visualisation strips; `SYNTHETIC_TREE_IDS` is that set plus the workforce root, and still guards rename and reap. Clicking the root now just toggles the branch, which the row handler in `StructureTree` was already doing before `onSelectNode` ran. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
fe2451fd60
commit
e417247e7e
@@ -78,14 +78,27 @@ const mono = "'JetBrains Mono', ui-monospace, monospace";
|
|||||||
// dashboard-data.ts fabricates a few org/company/team nodes so an empty
|
// dashboard-data.ts fabricates a few org/company/team nodes so an empty
|
||||||
// workspace still has something to render. These ids aren't UUIDs and
|
// workspace still has something to render. These ids aren't UUIDs and
|
||||||
// don't exist in the DB — treat them as non-selectable for reap.
|
// don't exist in the DB — treat them as non-selectable for reap.
|
||||||
const SYNTHETIC_TREE_IDS = new Set([
|
// Placeholder containers `dashboard-data.ts` fabricates for entities that were
|
||||||
"my-workforce",
|
// never parented into a real org → company → team chain. Clicking one offers to
|
||||||
|
// materialise that chain, because that is the only thing you can do with it.
|
||||||
|
// They exist only in the World tree.
|
||||||
|
const ORPHAN_CONTAINER_IDS = new Set([
|
||||||
"my-workspace",
|
"my-workspace",
|
||||||
"ws-teams",
|
"ws-teams",
|
||||||
"ungrouped-co",
|
"ungrouped-co",
|
||||||
"ungrouped-team",
|
"ungrouped-team",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Every id in the tree that is NOT a database row, orphan containers plus the
|
||||||
|
// "My Workforce" root. These cannot be renamed or selected for reap — the
|
||||||
|
// backend would 422 on the non-UUID id.
|
||||||
|
//
|
||||||
|
// Kept separate from the set above on purpose: they answer different questions.
|
||||||
|
// Folding the workforce root into the orphan set made clicking "My Workforce"
|
||||||
|
// offer to parent everything into an org → company → team chain — the exact
|
||||||
|
// hierarchy that root exists to replace.
|
||||||
|
const SYNTHETIC_TREE_IDS = new Set([...ORPHAN_CONTAINER_IDS, "my-workforce"]);
|
||||||
|
|
||||||
// Gradient palette for structure nodes that don't carry their own (companies,
|
// Gradient palette for structure nodes that don't carry their own (companies,
|
||||||
// teams). Agents bring their own grad/ink.
|
// teams). Agents bring their own grad/ink.
|
||||||
const NODE_GRADS: [string, string][] = [
|
const NODE_GRADS: [string, string][] = [
|
||||||
@@ -444,14 +457,21 @@ export function Dashboard({ user, orgs, claws }: { user?: { display_name?: strin
|
|||||||
};
|
};
|
||||||
// Clicking a synthetic scaffolding node ("my-workspace" / "ws-teams" /
|
// Clicking a synthetic scaffolding node ("my-workspace" / "ws-teams" /
|
||||||
// "ungrouped-co" / "ungrouped-team") opens the migration dialog instead of
|
// "ungrouped-co" / "ungrouped-team") opens the migration dialog instead of
|
||||||
// navigating — those nodes have no real DB row to select. Real nodes fall
|
// navigating — those nodes have no real DB row to select. The "My Workforce"
|
||||||
// through to the normal selection path below.
|
// root is synthetic too but is NOT one of those: it is the flat tree's
|
||||||
|
// heading, and offering to parent everything into an org chain from it would
|
||||||
|
// rebuild the hierarchy it replaced. Real nodes fall through to the normal
|
||||||
|
// selection path below.
|
||||||
const [orphanDialogOpen, setOrphanDialogOpen] = useState(false);
|
const [orphanDialogOpen, setOrphanDialogOpen] = useState(false);
|
||||||
|
|
||||||
// The tree's unified node handler (world tree + the flat agents list). On the
|
// The tree's unified node handler (world tree + the flat agents list). On the
|
||||||
// flat agents page a claw click opens the agent; in the World tree it selects.
|
// flat agents page a claw click opens the agent; in the World tree it selects.
|
||||||
const onTreeSelect = (item: TreeItem) => {
|
const onTreeSelect = (item: TreeItem) => {
|
||||||
if (SYNTHETIC_TREE_IDS.has(item.id)) { setOrphanDialogOpen(true); return; }
|
// Only an orphan container offers the migration. The workforce root is a
|
||||||
|
// heading: the row click above it has already toggled the branch, and there
|
||||||
|
// is nothing else to do with it.
|
||||||
|
if (ORPHAN_CONTAINER_IDS.has(item.id)) { setOrphanDialogOpen(true); return; }
|
||||||
|
if (SYNTHETIC_TREE_IDS.has(item.id)) return;
|
||||||
if (isClaw && item.level === "claw") { openClaw(item.id); return; }
|
if (isClaw && item.level === "claw") { openClaw(item.id); return; }
|
||||||
onWorldSelect(item.id);
|
onWorldSelect(item.id);
|
||||||
expandPathTo(item.id);
|
expandPathTo(item.id);
|
||||||
@@ -560,7 +580,7 @@ export function Dashboard({ user, orgs, claws }: { user?: { display_name?: strin
|
|||||||
const stripSynthetics = (roots: TreeItem[]): TreeItem[] => {
|
const stripSynthetics = (roots: TreeItem[]): TreeItem[] => {
|
||||||
const walk = (items: TreeItem[]): TreeItem[] =>
|
const walk = (items: TreeItem[]): TreeItem[] =>
|
||||||
items.flatMap((n) =>
|
items.flatMap((n) =>
|
||||||
SYNTHETIC_TREE_IDS.has(n.id)
|
ORPHAN_CONTAINER_IDS.has(n.id)
|
||||||
? walk(n.children ?? [])
|
? walk(n.children ?? [])
|
||||||
: [{ ...n, children: walk(n.children ?? []) }],
|
: [{ ...n, children: walk(n.children ?? []) }],
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user