Files
cameleer-server/.claude/rules/ui.md
hsiegeln 0cd0a27452 docs(alerts): rules + CLAUDE.md — inbox redesign, V17 migration
- .claude/rules/ui.md: rewrite Alerts section — sidebar trims to
  Inbox/Rules/Silences, InboxPage description updated (4 filters, row
  actions, bulk toolbar, soft-delete undo), SilenceRuleMenu documented,
  SilencesPage ?ruleId= prefill noted.
- CLAUDE.md: V17 migration entry describing enum/column/table/index
  changes for the inbox redesign.
- .claude/rules/app-classes.md AlertController bullet already updated
  in the T6 drive-by.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 19:21:27 +02:00

7.6 KiB

paths
paths
ui/**

UI Structure

The UI has 4 main tabs: Exchanges, Dashboard, Runtime, Deployments.

  • Exchanges — route execution search and detail (ui/src/pages/Exchanges/)
  • Dashboard — metrics and stats with L1/L2/L3 drill-down (ui/src/pages/DashboardTab/)
  • Runtime — live agent status, logs, commands (ui/src/pages/RuntimeTab/). AgentHealth supports compact view (dense health-tinted cards) and expanded view (full GroupCard+DataTable per app). View mode persisted to localStorage.
  • Deployments — app management, JAR upload, deployment lifecycle (ui/src/pages/AppsTab/)
    • Config sub-tabs: Monitoring | Resources | Variables | Traces & Taps | Route Recording
    • Create app: full page at /apps/new (not a modal)
    • Deployment progress: ui/src/components/DeploymentProgress.tsx (7-stage step indicator)

Admin pages (ADMIN-only, under /admin/):

  • Sensitive Keys (ui/src/pages/Admin/SensitiveKeysPage.tsx) — global sensitive key masking config. Shows agent built-in defaults as outlined Badge reference, editable Tag pills for custom keys, amber-highlighted push-to-agents toggle. Keys add to (not replace) agent defaults. Per-app sensitive key additions managed via ApplicationConfigController API. Note: AppConfigDetailPage.tsx exists but is not routed in router.tsx.

Key UI Files

  • ui/src/router.tsx — React Router v6 routes
  • ui/src/config.ts — apiBaseUrl, basePath
  • ui/src/auth/auth-store.ts — Zustand: accessToken, user, roles, login/logout
  • ui/src/api/environment-store.ts — Zustand: selected environment (localStorage)
  • ui/src/components/ContentTabs.tsx — main tab switcher
  • ui/src/components/ExecutionDiagram/ — interactive trace view (canvas)
  • ui/src/components/ProcessDiagram/ — ELK-rendered route diagram
  • ui/src/hooks/useScope.ts — TabKey type, scope inference
  • ui/src/components/StartupLogPanel.tsx — deployment startup log viewer (container logs from ClickHouse, polls 3s while STARTING)
  • ui/src/api/queries/logs.tsuseStartupLogs hook for container startup log polling, useLogs/useApplicationLogs for bounded log search (single page), useInfiniteApplicationLogs for streaming log views (cursor-paginated, server-side source/level filters)
  • ui/src/api/queries/agents.tsuseAgents for agent list, useInfiniteAgentEvents for cursor-paginated timeline stream
  • ui/src/hooks/useInfiniteStream.ts — tanstack useInfiniteQuery wrapper with top-gated auto-refetch, flattened items[], and refresh() invalidator
  • ui/src/components/InfiniteScrollArea.tsx — scrollable container with IntersectionObserver top/bottom sentinels. Streaming log/event views use this + useInfiniteStream. Bounded views (LogTab, StartupLogPanel) keep useLogs/useStartupLogs

Alerts

  • Sidebar section (buildAlertsTreeNodes in ui/src/components/sidebar-utils.ts) — Inbox, Rules, Silences.
  • Routes in ui/src/router.tsx: /alerts (redirect to inbox), /alerts/inbox, /alerts/rules, /alerts/rules/new, /alerts/rules/:id, /alerts/silences. No redirects for the retired /alerts/all and /alerts/history — stale URLs 404 per the clean-break policy.
  • Pages under ui/src/pages/Alerts/:
    • InboxPage.tsx — single filterable inbox. Filters: severity (multi), state (PENDING/FIRING/RESOLVED, default FIRING), Hide acked toggle (default on), Hide read toggle (default on). Row actions: Acknowledge, Mark read, Silence rule… (duration quick menu), Delete (OPERATOR+, soft-delete with undo toast wired to useRestoreAlert). Bulk toolbar (selection-driven): Acknowledge N · Mark N read · Silence rules · Delete N (ConfirmDialog; OPERATOR+).
    • SilenceRuleMenu.tsx — DS Dropdown-based duration picker (1h / 8h / 24h / Custom…). Used by the row-level and bulk silence actions. "Custom…" navigates to /alerts/silences?ruleId=<id>.
    • RulesListPage.tsx — CRUD + enable/disable toggle + env-promotion dropdown (pure UI prefill, no new endpoint).
    • RuleEditor/RuleEditorWizard.tsx — 5-step wizard (Scope / Condition / Trigger / Notify / Review). form-state.ts is the single source of truth (initialForm / toRequest / validateStep). Seven condition-form subcomponents under RuleEditor/condition-forms/ — including AgentLifecycleForm.tsx (multi-select event-type chips for the six-entry AgentLifecycleEventType allowlist + lookback-window input).
    • SilencesPage.tsx — matcher-based create + end-early. Reads ?ruleId= search param to prefill the Rule ID field (driven by InboxPage's "Silence rule… → Custom…" flow).
    • AlertRow.tsx shared list row; alerts-page.module.css shared styling.
  • Components:
    • NotificationBell.tsx — polls /alerts/unread-count every 30 s (paused when tab hidden via TanStack Query refetchIntervalInBackground: false).
    • AlertStateChip.tsx, SeverityBadge.tsx — shared state/severity indicators.
    • MustacheEditor/ — CodeMirror 6 editor with variable autocomplete + inline linter. Shared between rule title/message, webhook body/header overrides, and (future) Admin Outbound Connection editor (reduced-context mode for URL).
    • MustacheEditor/alert-variables.ts — variable registry aligned with NotificationContextBuilder.java. Add new leaves here whenever the backend context grows.
  • API queries under ui/src/api/queries/: alerts.ts, alertRules.ts, alertSilences.ts, alertNotifications.ts, alertMeta.ts. All env-scoped via useSelectedEnv from alertMeta.
  • CMD-K: buildAlertSearchData in LayoutShell.tsx registers alert and alertRule result categories. Badges convey severity + state. Palette navigates directly to the deep-link path — no sidebar-reveal state for alerts.
  • Sidebar accordion: entering /alerts/* collapses Applications + Admin + Starred (mirrors Admin accordion).
  • Top-nav: <NotificationBell /> is the first child of <TopBar>, sitting alongside SearchTrigger + status ButtonGroup + TimeRangeDropdown + AutoRefreshToggle.

UI Styling

  • Always use @cameleer/design-system CSS variables for colors (var(--amber), var(--error), var(--success), etc.) — never hardcode hex values. This applies to CSS modules, inline styles, and SVG fill/stroke attributes. SVG presentation attributes resolve var() correctly. All colors use CSS variables (no hardcoded hex).
  • Shared CSS modules in ui/src/styles/ (table-section, log-panel, rate-colors, refresh-indicator, chart-card, section-card) — import these instead of duplicating patterns.
  • Shared PageLoader component replaces copy-pasted spinner patterns.
  • Design system components used consistently: Select, Tabs, Toggle, Button, LogViewer, Label — prefer DS components over raw HTML elements. LogViewer renders optional source badges (container, app, agent) via LogEntry.source field (DS v0.1.49+).
  • Environment slugs are auto-computed from display name (read-only in UI).
  • Brand assets: @cameleer/design-system/assets/ provides camel-logo.svg (currentColor), cameleer-{16,32,48,192,512}.png, and cameleer-logo.png. Copied to ui/public/ for use as favicon (favicon-16.png, favicon-32.png) and logo (camel-logo.svg — login dialog 36px, sidebar 28x24px).
  • Sidebar generates /exchanges/ paths directly (no legacy /apps/ redirects). basePath is centralized in ui/src/config.ts; router.tsx imports it instead of re-reading <base> tag.
  • Global user preferences (environment selection) use Zustand stores with localStorage persistence — never URL search params. URL params are for page-specific state only (e.g. ?text= search query). Switching environment resets all filters and remounts pages.