From 9050e2427e0fe85f84ca38f1bbe67f1cd9344acf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=97=D0=B8=D0=BC=D0=B8=D0=BD?= Date: Thu, 14 May 2026 14:40:35 +0000 Subject: [PATCH] =?UTF-8?q?feat(notifications):=20TODO=207=20=E2=80=94=20d?= =?UTF-8?q?raft=20decision=20toast=20+=20email=20+=20bell=20badge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + DESIGN.md | 353 +++++++++++++++++ TODOS.md | 162 ++++---- ordinis-admin-ui/src/api/client.ts | 32 ++ ordinis-admin-ui/src/api/mutations.ts | 36 ++ ordinis-admin-ui/src/api/queries.ts | 34 ++ .../src/components/layout/TopBar.tsx | 76 +++- .../notifications/NotificationsDrawer.tsx | 225 +++++++++++ ordinis-admin-ui/src/i18n.ts | 30 ++ ordinis-app/pom.xml | 4 + .../NotificationsUserDisplayBridge.java | 29 ++ .../src/main/resources/application.yml | 15 + .../changes/0024-notification-read-state.xml | 56 +++ .../main/resources/db/changelog/master.xml | 1 + .../dispatcher/NotificationsDispatcher.java | 375 ++++++++++++++++++ .../dispatcher/RecipientResolver.java | 27 ++ .../dispatcher/UserDisplayPort.java | 17 + .../UserDisplayRecipientResolver.java | 50 +++ .../NotificationsDispatcherTest.java | 337 ++++++++++++++++ .../org.mockito.plugins.MockMaker | 1 + .../web/MeNotificationsController.java | 213 ++++++++++ 21 files changed, 1992 insertions(+), 82 deletions(-) create mode 100644 DESIGN.md create mode 100644 ordinis-admin-ui/src/components/notifications/NotificationsDrawer.tsx create mode 100644 ordinis-app/src/main/java/cloud/nstart/terravault/ordinis/app/config/NotificationsUserDisplayBridge.java create mode 100644 ordinis-migrations/src/main/resources/db/changelog/changes/0024-notification-read-state.xml create mode 100644 ordinis-notifications/src/main/java/cloud/nstart/terravault/ordinis/notifications/dispatcher/NotificationsDispatcher.java create mode 100644 ordinis-notifications/src/main/java/cloud/nstart/terravault/ordinis/notifications/dispatcher/RecipientResolver.java create mode 100644 ordinis-notifications/src/main/java/cloud/nstart/terravault/ordinis/notifications/dispatcher/UserDisplayPort.java create mode 100644 ordinis-notifications/src/main/java/cloud/nstart/terravault/ordinis/notifications/dispatcher/UserDisplayRecipientResolver.java create mode 100644 ordinis-notifications/src/test/java/cloud/nstart/terravault/ordinis/notifications/dispatcher/NotificationsDispatcherTest.java create mode 100644 ordinis-notifications/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker create mode 100644 ordinis-rest-api/src/main/java/cloud/nstart/terravault/ordinis/restapi/web/MeNotificationsController.java diff --git a/.gitignore b/.gitignore index ec6bf16..93f9a1d 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ HELP.md *.pem *.key .gstack/ +.claude/ diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..a4d5b54 --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,353 @@ +# DESIGN.md — Ordinis Admin UI Design System + +**Status:** v0 baseline (2026-05-14). Captured from observed patterns в +codebase after approval workflow saga (MR !179–!190). To be refined через +`/design-consultation` skill in a dedicated sprint. + +**Goal:** Lock the implicit design system как source of truth для будущих +features (Phase 4 webhook approvals, notifications surfaces, MDM expansion). +Document invariants (tokens, primitives, semantic rules) — NOT specific +components. + +--- + +## 1. Voice & Tone + +- **Russian-first.** UI primary language ru-RU; en-US is parallel mirror. + Every user-facing string registered in `src/i18n.ts`. +- **Operational, not aspirational.** Copy describes what user sees / does + ("Очередь чистая", "Reject требует comment") — no marketing-speak. +- **Domain-precise.** Use exact role names (maker / reviewer / publisher) + and operation codes (CREATE / UPDATE / CLOSE) — no generic "user". +- **Apologize on failure.** Empty states + error messages name what went + wrong и what to do next ("Refresh page + retry", "Укажите причину"). + +--- + +## 2. Color Tokens + +CSS variables defined в `src/styles.css`. Three themes: `default` (light +Anthropic warm), `nstart` (medium contrast brand), `dark` (Anthropic dark). + +### Semantic roles + +| Token | Light | Dark | Use | +|---|---|---|---| +| `--color-ink` | `#1a1714` | `#f0ece4` | Primary text | +| `--color-ink-2` | `#52483d` | `#c8c1b3` | Secondary text | +| `--color-mute` | `#8c8276` | `#8a8474` | Tertiary text / placeholders | +| `--color-bg` | `#faf9f5` | `#1c1a17` | App background | +| `--color-surface` | `#ffffff` | `#262421` | Card / panel surface | +| `--color-surface-2` | `#f5f3ec` | `#2e2b27` | Hover / nested surface | +| `--color-line` | `#e6e1d4` | `#3a3733` | Dividers / borders | +| `--color-line-2` | `#efeae0` | `#2d2a27` | Subtle dividers | +| `--color-accent` | `#b05a2e` | `#d97757` | Primary CTA / links | +| `--color-accent-bg` | accent @ 11% | accent @ 16% | Accent tint | +| `--color-on-accent` | `#ffffff` | `#1c1a17` | Text on accent | +| `--color-green` | `#4f7038` | `#4a7d4f` | Success / APPROVED | +| `--color-green-bg` | `#e4ead0` | `#dde9da` | Success tint | +| `--color-warn` | `#a8762a` | `#b97c2f` | Warning / CHANGES_REQUESTED | +| `--color-warn-bg` | `#f6e8bc` | `#fcecc7` | Warning tint | +| `--color-pink` | `#a64636` | `#b34d6a` | Danger / REJECTED | +| `--color-pink-bg` | `#f4d9cd` | `#f8d8de` | Danger tint | + +### Rules + +- **Never hard-code hex.** Use `bg-line`, `text-mute`, `border-accent` через + Tailwind utilities mapped to these tokens. +- **Status colors are stable across themes.** `success` always green-family; + `danger` always pink-family. +- **Tint backgrounds (`*-bg`) use 11-16% alpha** — for badge backgrounds + and subtle highlights. Never tint at higher opacity (loses contrast). + +--- + +## 3. Typography + +### Font families + +| Token | Stack | Use | +|---|---|---| +| `--font-sans` | `Inter, -apple-system, BlinkMacSystemFont, sans-serif` | Body, UI | +| `--font-mono` | `JetBrains Mono, SF Mono, monospace` | Code, UUIDs, business keys, versions | +| `--font-display` | `Tektur, Inter, sans-serif` | Caps headers, brand mark | + +### Type scale (Tailwind utilities) + +| Utility | Use | +|---|---| +| `text-title-md` | Section headings (Panel title) | +| `text-body` | Body copy | +| `text-cell` | Table cell, dense info | +| `text-cap` | Caps tracking-wide labels (column headers) — uses `--font-display` | +| `text-mono` | Code / monospaced | + +### Rules + +- **Mono для identity:** UUIDs (truncated `slice(0,8)…`), business keys, + version strings (`v1.1.0`). Reads as "this is an exact identifier". +- **Display caps для column headers:** `text-cap text-mute font-display + uppercase tracking-wider` — visual hierarchy через caps, not size. +- **`tabular-nums` для timestamp + count columns** — prevents jitter on + refresh. +- **Never use system-ui / -apple-system as primary display font.** Inter + is fallback only. + +--- + +## 4. Spacing & Layout + +### Base scale + +Tailwind default 4px scale (`gap-1` = 4px, `gap-2` = 8px, `gap-3` = 12px, +`gap-4` = 16px). Avoid arbitrary spacing values (`mt-[13px]`) — use scale +or extend tokens. + +### Layout primitives + +- **Page chrome:** `` for top of every route +- **Content area:** `space-y-4` (16px) between top-level sections +- **Panel:** `` wraps tables / forms with `bg-surface border border-line` +- **Card:** `` для individual content blocks (`bg-surface-2`) +- **Drawer:** Right-side slide-in for detail views (review draft, schema + draft, history) +- **Modal:** Centered overlay для destructive confirmations + create flows + +### Drawer-vs-Modal rules + +| Pattern | Use Drawer | Use Modal | +|---|---|---| +| Review existing entity | ✓ | | +| Read-only history | ✓ | | +| Diff side-by-side | ✓ (max-w-3xl) | | +| Create new entity | | ✓ | +| Destructive confirmation | | ✓ (size=sm) | +| Maker action requiring focus | | ✓ | + +Drawer = "look at this thing, maybe act on it". Modal = "do this thing now, +then dismiss". + +### Width caps + +- Drawer: `max-w-md` (notifications), `max-w-xl` (schema draft), `max-w-3xl` + (record review with diff panes) +- Modal: `size="sm"` (confirm), `"md"` (form), `"xl"` (JSON editor) +- Body copy: implicit via Panel padding; for description text apply + `max-w-prose` если viewport wide + +--- + +## 5. Component Primitives + +Locations: `src/ui/components/*.tsx`. Re-exported via `@/ui`. + +### Stable primitives (use freely) + +- `