Skip to content

Add Panel creation from the Dashboard tree #515

Description

@BorisTyshkevich

Goal

Companion to #483: add the same plus icon to each Dashboard row in the Dashboards tree, immediately before the existing pencil action.

Clicking the plus opens an Add panel dialog with:

  • Panel name — required;
  • Panel description — optional;
  • Add and Cancel buttons.

A successful Add creates a new empty Panel on that Dashboard and opens its empty query in a linked editor tab, ready for the user to type or paste SQL.

No Library interaction

This is not a Library assignment flow:

The new query and tile must be committed atomically. From its first committed state the query is referenced by exactly one Dashboard tile, so it is Dashboard-owned under #427 and does not appear in the Library projection.

Dashboard-row action

Extend the Dashboard row's direct action set and render order to:

  1. Add panel — plus icon;
  2. Edit dashboard — pencil;
  3. Delete dashboard — trash.

The plus is a real button with an accessible name such as Add panel to , aria-haspopup="dialog", native Enter/Space activation, and the same hover/focus visibility rules as the pencil and trash actions.

A Dashboard whose id is ambiguous must render the plus action as unavailable for the same reason its edit/delete actions are unavailable. A Dashboard already at the schema limit of 100 tiles should not open a dialog that can only fail; expose the action as unavailable with an explanatory tooltip/name.

Dialog behaviour

Reuse the shared two-field metadata dialog shell used by Dashboard and Panel editing.

  • Title: Add panel
  • Name label: Panel name
  • Description label: Panel description
  • Confirm label: Add
  • Add is disabled while the trimmed name is empty.
  • Enter in the name field submits; Enter in the description textarea inserts a newline.
  • Cancel, Escape, or backdrop close makes no workspace or tab changes.
  • While the commit is in flight, duplicate submission is prevented.
  • A stale target, validation failure, id collision, or persistence failure keeps the dialog open with the entered values and shows the diagnostic in the dialog.

Creation semantics

Add a dedicated Panel-creation command/service rather than mutating the workspace directly from ui/dashboard-tree.ts.

Mint one query id and one tile id through the injected id generator, once per Add attempt. Inside the normal read-latest-at-dequeue mutateWorkspace transform:

  1. Resolve exactly one target Dashboard by id; abort on missing or ambiguous targets.
  2. Re-check the 100-tile limit against the latest committed Dashboard.
  3. Reject query-id or Dashboard-local tile-id collisions.
  4. Create one blank Dashboard-owned saved query:
    • id: the minted query id;
    • sql: "";
    • current specVersion;
    • Spec name from the trimmed dialog value;
    • optional description from the dialog;
    • spec.dashboard.role: "panel";
    • no favorite and no Library-specific state.
  5. Append the query to workspace.queries.
  6. Add a tile referencing it through the canonical Dashboard add-query-instance command, not by hand-writing tiles.push, so placement, size-hint defaults, layout normalization, and fallback regeneration follow the existing add path.
  7. Store the tile as { id, queryId } only; do not duplicate the name or description as tile overrides.
  8. Increment the target Dashboard revision exactly once and leave all other Dashboards and queries byte-identical.

The whole candidate must validate and commit atomically: no orphan query and no dangling tile may be observable on failure.

After a successful commit:

  1. Close the dialog.
  2. Open Dashboards tree and position to the just-added panel.
  3. Switch to the Query surface.
  4. Open the newly committed owned query through the existing saved-query tab-opening path.
  5. Focus the SQL editor.
    The opened tab must be linked to the new query (savedId and committed-token baseline populated), contain blank SQL, carry the entered name/description in its Spec, and start clean. Typing then makes it dirty through the ordinary editor path, and Save updates the Panel-owned query without moving it into the Library.

Sequence navigation after the dialog has closed so the dialog's return-focus logic cannot steal focus back from the editor. On success, focus belongs in the SQL editor, not on the now-hidden tree trigger.

If the user later closes the untouched empty tab, the empty Panel remains committed. Removing it uses the existing Panel-delete behaviour, which also deletes its dedicated owned query.

Acceptance criteria

  • Every unambiguous Dashboard row exposes a plus button immediately before the pencil.
  • The plus is keyboard accessible and has a Dashboard-specific accessible name.
  • Ambiguous Dashboards and Dashboards at the 100-tile limit expose the action as unavailable with a reason.
  • The dialog asks for required name and optional description and provides Add/Cancel.
  • Cancel, Escape, and backdrop close change neither workspace nor tabs.
  • Add atomically commits one blank panel-role query and one tile referencing it.
  • The canonical add-query-instance/layout path is reused.
  • The tile has no redundant title or description overrides.
  • The new query is Dashboard-owned immediately and never appears in the Library projection.
  • No Library query is selected, copied, modified, or used as a source.
  • On success, the dialog closes and a clean linked tab for the new query opens with SQL-editor focus.
  • The tab contains blank SQL and the entered name/description; typing and Save use the normal linked-query lifecycle.
  • A failed or stale commit keeps the dialog open with its values and reports the error.
  • Duplicate submission and id collisions cannot create duplicate panels.
  • The target Dashboard revision increments exactly once; unrelated workspace content is unchanged.
  • Unit tests cover model action availability/order, pure candidate construction, ownership/Library exclusion, layout placement, limits, stale targets, collisions, and dialog orchestration.
  • E2E coverage creates a Panel from the tree using the keyboard and verifies that the empty linked tab opens with editor focus.
  • CHANGELOG.md and relevant Dashboard authoring documentation are updated.

Related: #427, #483, #494.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions