Skip to content

feat(dashboards): visual previews + tech marks on template cards#160

Merged
Makisuo merged 1 commit into
mainfrom
feat/dashboard-template-previews
Jul 1, 2026
Merged

feat(dashboards): visual previews + tech marks on template cards#160
Makisuo merged 1 commit into
mainfrom
feat/dashboard-template-previews

Conversation

@Makisuo

@Makisuo Makisuo commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

What

The dashboard template picker (/dashboards/templates) rendered every template as a text-only card. Each card now shows:

  • A miniature wireframe of the actual dashboard — widget rectangles at their real 12-col grid positions, with a glyph per visualization type: smoothed sparkline (line), filled area, bars, big-number stat block, table/list rows. The blank template gets a dashed empty-grid placeholder.
  • A technology mark next to the name — Postgres/MongoDB/Redis/MySQL/Kubernetes marks reused from the existing icon set; new simple-icons components for Kafka, NATS, RabbitMQ, Node.js, and OpenJDK; category-icon fallback for future templates.
  • A composition line (4 stats · 3 charts) in mono for quick scanning.

How

The preview geometry is derived from the template definitions, not hand-drawn: DashboardTemplateMetadata gains a preview: DashboardTemplatePreviewWidget[] field (x/y/w/h + kind + title), computed once per template from its build({}) output in listTemplateMetadata(). Chart kind comes from display.chartId (-area/-bar/default line); unknown visualizations fall back to the table glyph. Previews therefore can't drift from what instantiating the template actually creates.

Client-side, TemplatePreview renders a small SVG: series points come from a seeded random walk (FNV-1a + mulberry32 over template id), normalized to the glyph height and drawn as midpoint-smoothed quadratic curves — deterministic, SSR-stable, no data fetching, no charting library. Widget titles are exposed as native <title> tooltips and the SVG carries role="img" + aria-label.

Also fixes the template parameter dialog composition: the form fields were placed directly inside DialogContent, skipping DialogPanel (the design system's padded body slot), which left labels/inputs flush against the popup edge. Now composed DialogHeader → DialogPanel → DialogFooter like the other dialogs, with Enter-to-submit.

Notes for review

  • New vitest (apps/api/src/dashboard-templates/index.test.ts) asserts every template's preview matches its built widget list, kinds stay within the literal set, and blank stays empty.
  • Verified in the browser end-to-end: all 20 cards render previews matching their layouts, and template instantiation (dialog → create → navigate) works.
  • The preview metadata field is additive; the MCP create-dashboard tool reads DASHBOARD_TEMPLATES directly and is unaffected.

🤖 Generated with Claude Code


Open in Devin Review

Template cards were text-only (name, description, badges), so telling
templates apart meant reading every card. Each card now renders a
miniature wireframe of the actual dashboard it creates — widget rects at
their real grid positions with per-type glyphs (smoothed sparkline/area,
bars, stat block, table rows) — plus a technology mark (Postgres, Redis,
Kafka, K8s, Node.js, OpenJDK, …) and a widget-composition line
("4 stats · 3 charts").

The preview geometry is data-derived, not hand-drawn: template metadata
now carries a `preview` field (DashboardTemplatePreviewWidget[]) computed
once per template from its build({}) output, so previews can never drift
from what instantiation produces. Glyph series are seeded from the
template id (deterministic, SSR-stable). The blank template renders a
dashed empty-grid placeholder.

Also fixes the parameter dialog composition: form fields were placed
directly in DialogContent, skipping DialogPanel (the padded body slot),
leaving the fields flush against the popup edge.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pullfrog

pullfrog Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Your LLM provider API key was rejected. Rotate the key in your provider dashboard, then update the matching GitHub Actions secret.

Update repo secret → · Model settings → · Setup docs → · Ask in Discord →

Pullfrog  | ⚠️ this action is pinned to a commit SHA, which freezes the cleanup step — switch to @v0 or keep the SHA fresh with Dependabot | Rerun failed job ➔View workflow run | via Pullfrog | Using Claude Opus𝕏

@Makisuo Makisuo merged commit adfef1b into main Jul 1, 2026
5 of 8 checks passed
@Makisuo Makisuo deleted the feat/dashboard-template-previews branch July 1, 2026 22:19

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

Open in Devin Review

"description_changed",
"tags_changed",
"time_range_changed",
"variables_changed",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Dashboard variable changes are silently ignored in version history, showing "No changes"

The new "variables_changed" change kind is declared (packages/domain/src/http/dashboards.ts:351) and variables is added to the document schema (packages/domain/src/http/dashboards.ts:295), but the change-detection function that produces version history entries never compares the variables field, so a variables-only edit is recorded as "No changes."

Impact: Users editing dashboard variables see a misleading "No changes" label in the version history timeline.

Change-detection function never inspects the new variables field

The summarizeDashboardChange function in apps/api/src/services/dashboard-changes.ts:26-119 checks name, description, tags, timeRange, and widgets for differences between the previous and next dashboard documents. It does not compare the new variables field added to DashboardDocument at packages/domain/src/http/dashboards.ts:305.

When only variables change, no kind is added to the kinds set, so the function falls through to the kinds.size === 0 branch at apps/api/src/services/dashboard-changes.ts:110-111 and returns { kind: "multiple", summary: "No changes" }. The version record is still persisted with the correct snapshot, so there is no data loss, but the change kind and summary shown in the UI are wrong.

A block like the following is needed between the timeRange and widget checks:

if (!sameJson(prev.variables ?? [], next.variables ?? [])) {
    kinds.add("variables_changed")
    detail = detail ?? "Variables updated"
}
Prompt for agents
The PR adds a 'variables' optional field to DashboardDocument and PortableDashboardDocument (packages/domain/src/http/dashboards.ts lines 295 and 305), and adds 'variables_changed' as a new DashboardVersionChangeKind literal (line 351). However, the change-detection function summarizeDashboardChange in apps/api/src/services/dashboard-changes.ts does not compare the variables field between the previous and next dashboard documents. When only variables change, the function returns kind 'multiple' with summary 'No changes', producing a misleading version history entry. To fix this, add a variables comparison block (similar to the existing tags or timeRange checks) in summarizeDashboardChange, between the timeRange check and the widget diffing, using sameJson(prev.variables ?? [], next.variables ?? []) and adding 'variables_changed' to the kinds set when they differ.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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