Skip to content

feat(#429): unify Dashboard creation and add the metadata rename pencil (phase 3) - #495

Merged
BorisTyshkevich merged 1 commit into
mainfrom
feat/dashboard-metadata-429p3
Jul 27, 2026
Merged

feat(#429): unify Dashboard creation and add the metadata rename pencil (phase 3)#495
BorisTyshkevich merged 1 commit into
mainfrom
feat/dashboard-metadata-429p3

Conversation

@BorisTyshkevich

Copy link
Copy Markdown
Collaborator

What & why

Part of #429phase 3, absorbing #481: Dashboard-document metadata gets
exactly one create path and its first rename affordance.

One Dashboard-creation path (#481)

File ▸ New dashboard… and the empty-workspace placeholder's Create button
disagreed: the File menu prompted for a name and committed through
appendDashboard; the placeholder applied createEmptyDashboard's default
title silently and wrote through withCompatibilityDashboard/dashboards[0].
Both now prompt through the same openNameDialog (seeded with the same
DEFAULT_DASHBOARD_TITLE) and commit through appendDashboard — no caller
reaches the compatibility slot to create any more. The placeholder's dead
"collection already non-empty" guard is deleted rather than ported: once the
write is unconditionally additive, checking it first serves no purpose.

Dashboard-level metadata pencil

Each Dashboard row's new pencil (revealed on hover/:focus-within, beside the
existing ) opens a two-field dialog — title and description — prefilled
from the current committed document. Cancel/Escape commit nothing; a blank
title disables Save; a real commit bumps only that Dashboard's revision and
refreshes the tree/any open Dashboard surface. There is still no Dashboard
trash action (non-goal, unchanged).

Implementation notes

  • openDialogShell/openNameDialog are promoted out of file-menu.ts into a
    new src/ui/dialog-shell.ts, so the Dashboard tree's pencil can reuse them
    with no behavior change for File-menu's own dialogs. The hardcoded
    app.dom.fileBtn!.focus() restore becomes an explicit returnFocusTo
    param (File-menu's own wrapper still supplies fileBtn); the dialogClosers
    WeakMap + app.dom.fileDialog bookkeeping (now-dead field removed from
    AppDom) becomes a single module-local "current open dialog" slot with its
    own staleness guard, so a dialog opened from the tree — which, unlike
    File-menu's own overlays, persists across Query/Dashboard surface switches —
    is force-closed on a surface transition too.
  • renameDashboard (pure planner, workspace-dashboards.ts, modeled on
    withVariableConfig) trims the title and refuses (commits nothing) on a
    blank-after-trim result — defense in depth alongside the dialog's own
    disabled-confirm, since the schema itself carries no minLength floor on a
    Dashboard's title. description: undefined (omitted) leaves the stored
    value untouched; an explicit string trims and omits the field once empty,
    matching renameSaved's convention. commitDashboardRename
    (src/application/dashboard-title.ts) wraps it exactly like
    commitVariableConfig wraps withVariableConfig.
  • A real-browser-only bug caught by e2e, not the unit suite: the pencil is
    display: none except on hover/:focus-within, like the it sits beside.
    By the time its own dialog closes, the pointer has typically moved onto the
    dialog's controls, so neither still holds on the row — and focus() on an
    already-hidden element is a silent no-op in a real browser (happy-dom
    enforces no CSS layout at all, so the equivalent unit test passed regardless).
    Fixed the same way buildMenuButton already does it: the trigger's own
    aria-expanded stays "true" for the dialog's whole lifetime, reveals it
    through the openDialogShell's returnFocusTo.focus() call, and only resets
    to "false" afterward — by which point :focus-within covers it
    independently. dialog-shell.ts gained an onClose hook for this.
  • The pencil sits before the (Library-row icon-order convention), gated by
    a new DashboardTreeRow.renamable field (true for the Dashboard row only) —
    keeping the row at two trailing controls, not three, so phase 5's "third icon
    on a narrow row" concern isn't triggered here.

Acceptance criteria claimed

Deferred by design: panel-row edit/delete (phases 4/5), the repair planner
decision (phase 6), and every Dashboard-trash/deletion path (non-goal,
unchanged).

Verification

  • npm test179 files / 5877 tests passed, per-file coverage gate held;
    tsc --noEmit clean; npm run build clean.
  • npm run test:e2e (dashboard-tree.spec.js) — full spec green on
    chromium, webkit and firefox; the real-browser focus-restore bug above
    was caught here first and is now pinned by a dedicated e2e test plus a unit
    test on the aria-expanded toggle.
  • Full test:e2e suite green on chromium (152/152); webkit clean; a handful
    of unrelated Firefox specs (dashboard-kpi-move, dashboard-membership,
    tile-open-workbench, variable-tab — none touched by this change) flaked
    under full parallel load and passed individually on retry, matching known
    sandbox Firefox flakiness.
  • An independent read-only review pass against the diff (dialog-shell
    staleness guard, renameDashboard/commitDashboardRename correctness,
    boundary rules, coverage-gate honesty, scope) came back with no defects.
  • Driven against the real served app with a live ClickHouse (local
    ch-26.6): created a Dashboard via File ▸ New dashboard…, renamed it via the
    pencil (title + description), confirmed the tree label updates, the toast
    fires, and no console errors — including moving the mouse away right after
    Save, to exercise the focus-restore fix above.

Checklist

  • npm test passes (the per-file coverage gate is non-negotiable)
  • Tests added/updated in the same change as the code
  • npm run build succeeds (single-file dist/sql.html)
  • Layers kept honest: pure logic in src/core/, network in src/net/ (injected fetch), DOM in src/ui/
  • No new runtime dependency (or it's a deliberate, justified addition — see CONTRIBUTING)
  • README / CHANGELOG.md ([Unreleased]) updated if behavior or the deployed surface changed
  • Reconciled affected tracked work (roadmap Roadmap to 1.0.0 #68, the issue body, ADR/CHANGELOG) if this change reshaped it

🤖 Generated with Claude Code

https://claude.ai/code/session_018mujm1kW7jDGpTEfscndcU

…il (phase 3)

Absorbs #481. `openNameDialog`/`openDialogShell` move out of file-menu.ts into
a shared src/ui/dialog-shell.ts (generalized returnFocusTo + a single-slot
staleness-guarded teardown) so the Dashboard tree's new rename pencil can
reuse them. File > New dashboard... and the empty-workspace placeholder now
both prompt and commit through appendDashboard, never the compatibility slot.
A new renameDashboard planner + commitDashboardRename wrapper back a
two-field title/description dialog on each Dashboard row's pencil.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018mujm1kW7jDGpTEfscndcU
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant