Files
cameleer-server/ui
hsiegeln 09b49f096c feat(alerting): per-severity breakdown on unread-count DTO
Spec §13 calls for the notification bell to colour-code by highest
unread severity (CRITICAL → error, WARNING → amber, INFO → muted).
The old { count } DTO forced the UI to pick one static colour, so
NotificationBell shipped with a TODO. Grow the contract instead:

  UnreadCountResponse = { total, bySeverity: { CRITICAL, WARNING, INFO } }

Guarantees:
- every severity is always present with a >=0 value (no undefined
  keys on the wire), so the UI can branch without defaults.
- total = sum of bySeverity values — kept explicit on the wire for
  cheap top-line display, not recomputed client-side.

Backend
- AlertInstanceRepository: replaces countUnreadForUser(long) with
  countUnreadBySeverityForUser returning Map<AlertSeverity, Long>.
  One SQL round-trip per (env, user) — GROUP BY ai.severity over the
  same NOT EXISTS(alert_reads) filter.
- UnreadCountResponse.from(Map) normalises and defensively copies;
  missing severities default to 0.
- InAppInboxQuery.countUnread now returns the DTO, caches the full
  response (still 5s TTL) so severity breakdown gets the same
  hit-rate as the total did before.
- AlertController just hands the DTO back.

Breaking change — no backwards-compat shim: the `count` field is
gone. UI and tests updated in the same commit; there are no other
API consumers in the tree.

Frontend
- Regenerated openapi.json + schema.d.ts against a fresh build of
  the new backend.
- NotificationBell branches badge colour on the highest unread
  severity (CRITICAL > WARNING > INFO) via new CSS variants.
- Tests cover all four paths: zero, critical-present, warning-only,
  info-only.

Tests: 7 unit tests + 12 ITs (incl. new grouping + empty-map)
       + 49 vitest (was 46; +3 severity-branch assertions).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 18:15:56 +02:00
..
2026-04-15 15:28:42 +02:00
2026-04-15 15:28:42 +02:00
2026-04-15 15:28:42 +02:00

Cameleer UI

React SPA built with @cameleer/design-system v0.1.28, TanStack Query, and Zustand.

Development

npm install
npm run dev

By default the dev server proxies /api/* to http://localhost:8081. To proxy to a remote server instead:

VITE_API_TARGET=http://192.168.50.86:30081 npm run dev

No CORS issues — Vite's proxy makes API calls server-side.

Build

npm run build

API Types

Regenerate TypeScript types from a running backend:

npm run generate-api   # Requires backend running on :8081

Key Features

  • Composable sidebar with accordion behavior (Applications / Starred / Admin sections)
  • Context-aware cmd-k search: shows apps/routes/exchanges on operational pages, users/groups/roles on admin pages
  • LIVE mode toggle: when ON, queries poll at intervals (5s-30s); when OFF, sidebar clicks trigger manual refresh
  • Route control bar with state-aware buttons (start/stop/suspend/resume) and confirmation dialogs
  • Event-type icons in agent timeline with severity-based coloring