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
{{ message }}
Repository navigation
feat(dashboards): let users choose which Arc instance a dashboard and its panels query #86
A dashboard created today is unusable and there is no way out of it from the UI.
"New dashboard" creates with instanceId: null (dashboards/+page.svelte, createDashboard({ title, instanceId: null }))
There is no instance control anywhere — not on /d/[uid], not in the panel editor
So: create → add a panel → write SQL → every panel renders "This dashboard does not have an Arc instance selected." (queryRunner's unresolvedError) and the user cannot fix it
The model has supported this the whole time. resolveInstanceRef does target → panel → dashboard precedence with $variable dereference, and listInstances(orgId) exists in cloudApi. Only the UI is missing.
Scope
1. At creation. The "New dashboard" flow asks which instance, so a dashboard is never created in the unusable state. Needs an empty state when the org has no instances — a link to create one, not a blank dropdown.
2. Dashboard settings drawer. The dashboard-level default, alongside title, description and tags. This is the half that rescues dashboards that already exist and dashboards that arrive through import (#57), and it is the only way to change the instance later. Already listed in #35's scope.
3. Panel editor override. Per-target, beside the query tabs, since Target.instanceId is the most specific level. This is what makes a cross-instance dashboard possible — prod and staging side by side in one view. Already implied by #43's "options sidebar".
Things to get right
Changing the dashboard instance is a MODEL edit. It dirties the dashboard and must re-run every panel. Changing a panel/target override dirties it too and re-runs that panel.
The picker offers only instances from listInstances(orgId), so a user cannot type an arbitrary id — but that is convenience, not security: instanceId is untrusted per model.ts invariant 3, and the proxy re-checks instance.org_id === orgId on every request regardless.
Leave the seam for instance variables. The model has type: 'instance' variables precisely so one dashboard can template across instances, and resolveInstanceRef already dereferences $name. Until feat(viz): add the dashboard variable engine #31 lands the picker offers concrete instances only, but the control should be shaped so adding "…or a variable" later is not a rewrite.
Inherit must be expressible. A panel with no override inherits the dashboard's; the control needs a distinct "inherit" state, not an empty string, or clearing an override becomes impossible.
An instance that no longer exists. A dashboard can name an instance that was deleted since. The picker should show it as missing rather than silently selecting nothing — the query already fails with a clear 404 from the proxy, but the settings UI should say why.
Acceptance criteria
Creating a dashboard offers an instance, and says so when the org has none
The settings drawer sets and changes the dashboard's instance, and the change re-runs every panel
A panel target can override the dashboard instance, and can be set back to inherit
A dashboard naming a deleted instance shows that in settings rather than appearing unset
Closing: the dashboards feature has been dropped from Launchpad. The implemented work was removed in #87 and this work will not be picked up. Recoverable from git tag pre-dashboards-removal-backup if the feature is ever revived.
The dead end
A dashboard created today is unusable and there is no way out of it from the UI.
instanceId: null(dashboards/+page.svelte,createDashboard({ title, instanceId: null }))/d/[uid], not in the panel editorqueryRunner'sunresolvedError) and the user cannot fix itThe model has supported this the whole time.
resolveInstanceRefdoestarget → panel → dashboardprecedence with$variabledereference, andlistInstances(orgId)exists incloudApi. Only the UI is missing.Scope
1. At creation. The "New dashboard" flow asks which instance, so a dashboard is never created in the unusable state. Needs an empty state when the org has no instances — a link to create one, not a blank dropdown.
2. Dashboard settings drawer. The dashboard-level default, alongside title, description and tags. This is the half that rescues dashboards that already exist and dashboards that arrive through import (#57), and it is the only way to change the instance later. Already listed in #35's scope.
3. Panel editor override. Per-target, beside the query tabs, since
Target.instanceIdis the most specific level. This is what makes a cross-instance dashboard possible — prod and staging side by side in one view. Already implied by #43's "options sidebar".Things to get right
listInstances(orgId), so a user cannot type an arbitrary id — but that is convenience, not security:instanceIdis untrusted permodel.tsinvariant 3, and the proxy re-checksinstance.org_id === orgIdon every request regardless.type: 'instance'variables precisely so one dashboard can template across instances, andresolveInstanceRefalready dereferences$name. Until feat(viz): add the dashboard variable engine #31 lands the picker offers concrete instances only, but the control should be shaped so adding "…or a variable" later is not a rewrite.Acceptance criteria