You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
do not show a Library query chooser;
do not select, copy, or modify a Library query;
do not create a temporary Library entry and then assign it;
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:
Add panel — plus icon;
Edit dashboard — pencil;
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:
Resolve exactly one target Dashboard by id; abort on missing or ambiguous targets.
Re-check the 100-tile limit against the latest committed Dashboard.
Reject query-id or Dashboard-local tile-id collisions.
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.
Append the query to workspace.queries.
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.
Store the tile as { id, queryId } only; do not duplicate the name or description as tile overrides.
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:
Close the dialog.
Open Dashboards tree and position to the just-added panel.
Switch to the Query surface.
Open the newly committed owned query through the existing saved-query tab-opening path.
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.
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:
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:
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.
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
mutateWorkspacetransform:id: the minted query id;sql:"";specVersion;spec.dashboard.role: "panel";favoriteand no Library-specific state.workspace.queries.add-query-instancecommand, not by hand-writingtiles.push, so placement, size-hint defaults, layout normalization, and fallback regeneration follow the existing add path.{ id, queryId }only; do not duplicate the name or description as tile overrides.The whole candidate must validate and commit atomically: no orphan query and no dangling tile may be observable on failure.
After a successful commit:
The opened tab must be linked to the new query (
savedIdand 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
add-query-instance/layout path is reused.CHANGELOG.mdand relevant Dashboard authoring documentation are updated.Related: #427, #483, #494.