openova/products/catalyst/bootstrap/ui/package.json
hatiyildiz e066509cc3 feat(ui): dashboard with Recharts treemap (cpu/memory utilization)
Adds the Sovereign Dashboard surface at
/sovereign/provision/$deploymentId/dashboard rendering a Recharts
<Treemap> where box AREA tracks the selected resource limit and box
COLOR is a continuous gradient (blue -> green -> red) over a
selectable utilisation/health/age metric. Toolbar lets the operator
pick Size, Color, and up to 4 nested Layer dimensions
(sovereign/cluster/family/namespace/application). Capacity size
metrics auto-lock the colour scale to utilisation. Drill-down walks
the in-memory tree (no refetch); breadcrumb chips pop back. Hover
yields a viewport-clamped tooltip with a deep link to AppDetail.

Architecture notes baked into the code:
- Module-level callback refs (_onCellHover/_onCellClick/_activeColorFn
  /_itemsByName) are required because Recharts clones the cell content
  component without preserving React closures or hooks.
- Parent-bounds Map clips child labels under the 24px nested header
  strip so a tall narrow child can't render under its parent's title.
- Cell renderers gate label visibility on width >= 50px / height >= 24px
  to avoid noisy text on tiny cells.
- isAnimationActive=false for perf on 500+ cells.

Backend (catalyst-api):
- New GET /api/v1/dashboard/treemap?group_by=A,B&color_by=C&size_by=D
  returning the nested TreemapItem[] shape the UI consumes.
- v1 emits a static placeholder shape derived from the canonical
  Catalyst-Zero family list (20 cells across 6 families). The HTTP
  schema is the target schema; only the data SOURCE is a placeholder.
  Replacing it with metrics-server integration is a follow-up.

Tests:
- 30 colour-gradient + drill-walk unit tests in
  src/lib/treemap.types.test.ts (0%->blue, 50%->green, 100%->red,
  interpolation, walk, query string).
- 9 controller toolbar tests (add/remove layer caps, capacity-metric
  auto-lock, dimension exclusion).
- 6 Dashboard render tests (toolbar, empty state, total count,
  breadcrumb root chip).
- 6 Go handler tests (default/nested response shape, dimension/colour/
  size validation, percentage-in-range invariant).

Sidebar gets a Dashboard nav entry. Sidebar.test updated to reflect.

Vite dev proxy gains a /sovereign/api passthrough (rewrites to /api)
so dev mirrors the production traefik prefix-strip.

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

73 lines
2.2 KiB
JSON

{
"name": "ui",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"build:catalog": "node scripts/build-catalog.mjs",
"predev": "npm run build:catalog",
"prebuild": "npm run build:catalog",
"dev": "vite",
"build": "tsc -b && vite build",
"typecheck": "tsc -b --noEmit",
"test": "vitest run",
"test:watch": "vitest",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"@hookform/resolvers": "^5.2.2",
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-alert-dialog": "^1.1.15",
"@radix-ui/react-avatar": "^1.1.11",
"@radix-ui/react-checkbox": "^1.3.3",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.8",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-progress": "^1.1.8",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-tooltip": "^1.2.8",
"@tailwindcss/vite": "^4.2.2",
"@tanstack/react-query": "^5.91.2",
"@tanstack/react-query-devtools": "^5.91.3",
"@tanstack/react-router": "^1.167.5",
"@tanstack/router-devtools": "^1.166.9",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"framer-motion": "^12.38.0",
"lucide-react": "^0.577.0",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-hook-form": "^7.71.2",
"recharts": "^3.8.1",
"tailwind-merge": "^3.5.0",
"tailwindcss": "^4.2.2",
"zod": "^4.3.6",
"zustand": "^5.0.12"
},
"devDependencies": {
"@eslint/js": "^9.39.4",
"@playwright/test": "^1.59.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@types/node": "^24.12.0",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^6.0.1",
"eslint": "^9.39.4",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.5.2",
"globals": "^17.4.0",
"jsdom": "^29.1.0",
"typescript": "~5.9.3",
"typescript-eslint": "^8.57.0",
"vite": "^8.0.1",
"vitest": "^4.1.5"
}
}