BranchMenu

tcmts.studio.BranchMenu · #a3r4zqcl · term · runs in the browser

handles onAction

The branch the studio shows, as a menu in its header: the codebase's own first, then the other branches, then agents' sessions (those an agent is working on now marked, and those changed in the last day; the rest under Older), each with when it last changed. Choosing one reads it in this browser from then on (readBranch), its code, history and traces; nothing changes it.

import { refresh } from "#codebase/tcmts/react";
import { Chevron, toasts } from "#codebase/tcmts/share";
import { readBranch } from "#codebase/tcmts/studio";
import {
  Button, Header, Menu, MenuItem, MenuSection, MenuTrigger, Popover, SubmenuTrigger,
} from "react-aria-components";

export function BranchMenu({
  current,
  own,
  sections,
  older = [],
}: {
  current: string;
  own: string;
  sections: { label: string; items: { name: string; detail: string; live?: boolean }[] }[];
  older?: { name: string; detail: string }[];
}) {
  const read = (k: unknown) =>
    void readBranch(String(k)).then(
      () => refresh(),
      (e: Error) =>
        toasts.add(
          { title: "Couldn't read it", description: e.message, tone: "bad" },
          { timeout: 6000 },
        ),
    );
  return (
    <MenuTrigger>
      <Button className="btn small select-btn branchbtn" aria-label={`Branch: ${current}`}>
        <span>
          ⑂ {current}
          {current !== own && <span className="muted"> · read only</span>}
        </span>
        <Chevron />
      </Button>
      <Popover className="menu-pop branchpop" placement="bottom start" offset={4}>
        <Menu
          className="menu"
          aria-label="Branches"
          selectionMode="single"
          selectedKeys={[current]}
          onAction={(k) => k !== "older" && read(k)}
        >
          {sections.map((s) => (
            <MenuSection key={s.label}>
              <Header className="menu-head">{s.label}</Header>
              {s.items.map((i) => (
                <MenuItem key={i.name} id={i.name} textValue={i.name} className="opt">
                  {i.live && <span className="live busy" title="an agent is working on it" />}
                  <span className="mono">{i.name}</span>
                  <span className="muted branchago">{i.detail}</span>
                </MenuItem>
              ))}
            </MenuSection>
          ))}
          {older.length > 0 && (
            <MenuSection>
              <SubmenuTrigger>
                <MenuItem id="older" textValue="Older sessions" className="opt">
                  <span className="mono">Older sessions</span>
                  <span className="muted branchago">{older.length} ›</span>
                </MenuItem>
                <Popover className="menu-pop branchpop" offset={-4}>
                  <Menu className="menu" aria-label="Older sessions" onAction={read}>
                    {older.map((i) => (
                      <MenuItem key={i.name} id={i.name} textValue={i.name} className="opt">
                        <span className="mono">{i.name}</span>
                        <span className="muted branchago">{i.detail}</span>
                      </MenuItem>
                    ))}
                  </Menu>
                </Popover>
              </SubmenuTrigger>
            </MenuSection>
          )}
        </Menu>
      </Popover>
    </MenuTrigger>
  );
}

uses

used by