Make a workspace page a dashboard and drop its coordinator from the rail

The workspace rail now lists only the bots attached to the workspace, with the back link returning to the workspace page from a bot's conversation. /admin/workspaces/<id> becomes a read-only dashboard (picture, context, latest activity, bots, computers) that links into the editable settings page.
This commit is contained in:
2026-10-19 13:40:59 +01:00
parent 7b1ccfeb62
commit e5747effa8
16 changed files with 425 additions and 63 deletions
@@ -2,7 +2,6 @@ import Divider from "@moduletrace/twui/layout/Divider";
import { useContext } from "react";
import { AddFlowContext } from "../(data)/add-flow-context";
import type { BotWithLastMessage, WorkspaceWithActivity } from "@/src/types";
import CoordinatorRow from "./coordinator-row";
import RailBackLink from "./rail-back-link";
import RailBotsSection from "./rail-bots-section";
import RailSectionAddButton from "./rail-section-add-button";
@@ -11,7 +10,8 @@ import WorkspaceRow from "./workspace-row";
type Props = {
workspace: WorkspaceWithActivity;
/**
* The workspace's crew: the coordinator and its bots.
* The workspace's crew: the coordinator is left out, only the bots
* attached to the workspace show.
*/
bots: BotWithLastMessage[];
selected_id?: number;
@@ -23,28 +23,22 @@ type Props = {
/**
* The rail inside a workspace: back to all bots, the workspace itself (its
* page), its coordinator conversation, then the workspace's bots. Every
* conversation here runs with the workspace's context.
* page), then the workspace's bots. Every conversation here runs with the
* workspace's context. The coordinator is reached from the main rail.
*/
export default function RailWorkspaceList({ workspace, bots, selected_id, on_workspace_page }: Props) {
const { openForm } = useContext(AddFlowContext);
const coordinator = bots.find((bot) => bot.kind === "coordinator");
const workers = bots.filter((bot) => bot.kind !== "coordinator");
const base = `/admin/workspaces/${workspace.id}`;
return (
<>
<RailBackLink title="All bots" />
<RailBackLink
title={on_workspace_page ? "All bots" : `Back to ${workspace.name}`}
href={on_workspace_page ? undefined : base}
/>
<Divider className="shrink-0 mx-1 lg:mx-3 my-2 w-auto border-hairline dark:border-hairline" />
<WorkspaceRow workspace={{ ...workspace, unread: 0 }} selected={on_workspace_page} />
{coordinator ? (
<CoordinatorRow
bot={coordinator}
bots={bots}
href={`${base}/bots/${coordinator.id}`}
selected={!on_workspace_page && coordinator.id === selected_id}
/>
) : null}
<RailBotsSection
action={<RailSectionAddButton title="Add a bot to this workspace" onClick={() => openForm({ kind: "bot" })} />}
title="Workspace bots"