Skip to content

feat(ui): wire Export/Import job cards to tenant-scoped counts (#554) - #565

Merged
smunini merged 4 commits into
mainfrom
feat/554-dashboard-job-cards
Aug 19, 2026
Merged

feat(ui): wire Export/Import job cards to tenant-scoped counts (#554)#565
smunini merged 4 commits into
mainfrom
feat/554-dashboard-job-cards

Conversation

@andyguz17

Copy link
Copy Markdown
Contributor

Closes #554.

What

  • The Export jobs card now shows the tenant's real running / queued bulk-export counts (it was a hardcoded "13 / 1 queued").
  • New Import jobs card with the tenant's active bulk-submit count, linking to /ui/bulk-import.
  • Both cards render an explicit "unavailable" state (em dash + aria-label) when the running backend has no job store or the count cannot be read — never a fabricated zero.
  • Both cards are links (<a class="card stat stat--link">): Export → /ui/bulk-export, Import → /ui/bulk-import.
  • Stat grid gets a stat-grid--5 modifier (5 cols on desktop, 3 ≤1100px, existing 2-col rule ≤900px).

How

  • persistence: BulkExportStorage::count_exports_by_status(tenant, status) (SQLite + Postgres, additive). count_active_exports is untouched — it still backs the concurrency cap.
  • observability: DashboardSnapshot gains export_jobs: Option<ExportJobCounts { running, queued }> and import_jobs_active: Option<u64>; None means unavailable.
  • rest: StorageDashboardProvider::with_job_stores(..) receives the optional bulk-export / bulk-submit job stores already built in build_app and fills the two fields. running = in-progress, queued = accepted. A read error logs a warning and yields None; no store wired yields None silently.
  • ui: DashboardMetrics carries Options, template + CSS + i18n (en/es/de) + HTTP test; e2e page object and spec cover both cards (stat-card count 4 → 5).

Decisions (as requested by the issue)

  • Per-tenant job counts come from the authenticated dashboard snapshot, not /metrics; nothing per-tenant is added to /metrics.
  • Process-wide export/import Prometheus metrics: not added here — recorded decision; happy to file a follow-up issue if wanted (would instrument the workers, no tenant label).
  • The running/queued split is backed by real data (in-progress / accepted); the card copy is unchanged.
  • Uptime is untouched (UI Home Page: wire the Uptime stat to Prometheus metrics (implement the metric if missing) #540, @angela-helios); only the placeholder comment next to it was reworded to cover uptime alone.
  • 5-column grid kept after a visual check at 1440/1200/1000/800px (dark + light); the es labels wrap to two lines around 1200px but stay within the card.

Coordination

Testing

  • cargo fmt --all -- --check, workspace cargo clippy --all-targets --all-features -D warnings (CI allow-list), cargo test -p helios-persistence bulk_export (SQLite unit + Postgres via testcontainers), cargo test -p helios-observability -p helios-rest -p helios-ui, cargo build -p helios-hfs --features ui.
  • Manual: hfs on SQLite → /ui shows Export "0 / running (0 queued)" and Import "0 / active".
  • Playwright: spec compiles and is discovered (--list); the full browser run relies on CI (ui-tests.yml) — Chromium could not be downloaded on the dev box.

…snapshot

DashboardSnapshot gains export_jobs (running/queued) and import_jobs_active as Options; None means unavailable, never a fabricated zero. StorageDashboardProvider receives the optional bulk-export / bulk-submit job stores from build_app and fills them; read errors log a warning and yield None. Existing exhaustive DashboardSnapshot literals in the UI crate get the two new fields as None.
The Export card shows the tenant's running/queued bulk-export counts and links to /ui/bulk-export; a new Import card shows active bulk-submit jobs and links to /ui/bulk-import. Both render an explicit unavailable state when the snapshot carries None. Adds the stat-grid--5 modifier (5 cols, 3 at <=1100px, existing 2-col rule at <=900px), en/es/de keys, and an HTTP test. Uptime stays a placeholder (#540).
@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.75000% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...s/persistence/src/backends/postgres/bulk_export.rs 66.66% 1 Missing ⚠️
...tes/persistence/src/backends/sqlite/bulk_export.rs 98.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@smunini
smunini merged commit 016a16b into main Aug 19, 2026
141 of 149 checks passed
@smunini
smunini deleted the feat/554-dashboard-job-cards branch August 19, 2026 12:24
smunini added a commit that referenced this pull request Aug 19, 2026
Conflicts were the dashboard data path (#565 job cards + #537 bulk export
landing on main while this branch reworked the chart) and the UI's CSS/class
vocabulary refactor.

Resolution:
- DashboardSnapshot carries both sides: `available`/`TypeCount` (#555) and
  `export_jobs`/`import_jobs_active` (#565). The provider keeps this branch's
  `distinct_types` (derived from `available`) instead of main's second
  `count_all_types` read, and gains main's job-store counts.
- Rest dashboard tests updated for the three-argument `snapshot(window,
  tenant, types)` signature.
- app.css: main's new rules folded into this branch's `@layer` structure.
- Main's new templates moved onto the renamed vocabulary this branch
  introduced (`.button` -> `.btn`, `.page-title` -> `.page-head__title`).
- Bulk-export status chips renamed `.chip*` -> `.status-chip*`: `.chip` is
  already the filter affordance on the search/registry pages, and the
  duplicate definition both collided visually and tripped the new
  design-system guard. The dead duplicate `.notice` block from #537 is
  dropped (the registry-viewer `.notice` won the cascade anyway).
- Dashboard e2e expects five stat cards (main's job cards) and keeps this
  branch's `waitForSeries()`.

Claude-Session: https://claude.ai/code/session_019E74WX1whW1NaT1SjUqXJG
angela-helios added a commit that referenced this pull request Aug 19, 2026
Main brought Bulk Export (#538), the dashboard job cards (#565), and the menu
close behaviors (#566). The vocabulary work carries over both export pages,
which predate #543: canonical title/button classes, the job-status chips move
onto the .tag status-pill family (main's new .chip block collided with the
facet-chip component — exactly the duplicate this branch exists to kill), the
typegrid joins the pages layer, the job-card additions join the components
layer, and both export routes join the shared guard list.

Also makes the design-system guard read app.css and the shipped scripts over
HTTP from the server under test instead of the source tree: the CI runner
drives a packaged binary with no checkout alongside it (the ENOENT on every
merge-ref run), and in HFS_E2E_BASE_URL mode the running server is the only
truth worth checking anyway.
angela-helios added a commit that referenced this pull request Aug 19, 2026
…ashboard-chart

Combines the multi-series chart with main's #565 job cards: the snapshot
carries both the picker's available types and the job counts, the metrics
render real export/import figures inside the rewritten build_dashboard, and
the stat-card spec expects five cards with the chart's series wait.
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.

Home dashboard: hook up Export jobs, add Import jobs, and settle the data source

2 participants