Commit Graph

544 Commits

Author SHA1 Message Date
Александр Зимин 87b4f319d9 Merge branch 'feat/brand-logo-update' into 'main'
feat(brand): adopt official Ordinis logo assets

See merge request 2-6/2-6-4/terravault/ordinis!100
2026-05-11 20:20:26 +00:00
Zimin A.N. e6fe9c3da8 feat(brand): adopt official Ordinis logo assets
Делёные design team 2026-05-11 в Downloads/files:
  - ordinis-mark.svg — двойные орбиты + 6 dots + gradient core
    (DeepBlue #185FA5 → SkyBlue #378ADD), brand spec
  - ordinis-favicon.svg — minimal 32px variant
  - ordinis-appicon.svg — 1024px PWA icon с dark rounded tile
  - ordinis-lockup-light/dark.svg — horizontal lockup с wordmark
    (для landing/splash/marketing — пока не используется но
    хранится в public для future use)

Changes:
- public/favicon.svg → minimal 32px variant
- Sidebar logo block: inline ordinis-mark с двойными орбитами +
  gradient core. Wordmark 'ORDINIS MDM' остаётся в Tektur.
- index.html: theme-color #185FA5 (был #120a8f), apple-touch-icon
  link на appicon, mask-icon color match.

Note: SVG colors hardcoded в Sidebar inline для full design fidelity
(brand assets specifically defined gradient). currentColor не подходит
т.к. brand требует точные DeepBlue/SkyBlue/LightBlue tokens.
2026-05-11 23:19:33 +03:00
Александр Зимин 3119e8c81c Merge branch 'docs/backend-status-update' into 'main'
docs(api): mark 4/5 pending endpoints shipped, workflow API deferred

See merge request 2-6/2-6-4/terravault/ordinis!99
2026-05-11 20:16:46 +00:00
semantic-release-bot 1b577393d6 chore(release): v1.7.0 [skip ci]
## [1.7.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v1.6.1...v1.7.0) (2026-05-11)

###  Features

* **api:** GET /dictionaries/graph/outgoing — batch outgoing FK summary ([ff05ef9](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/ff05ef9a9fcc0df55c0da2cb16c2d7d75f9e9db4))
* **loader:** real Natural Earth globe via d3-geo + topojson + world-atlas ([acde4e1](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/acde4e134dc7d7610e108e155e2b57426190be08))

### 🐛 Fixes

* **a11y:** add sr-only DialogTitle/Description to record/export/timetravel modals ([7429cff](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/7429cff0096918fb0fe9dc2a55506a93ee5ee89e))
* **form:** break drawer counter/dirty infinite-loop + add GlobeLoader + AppErrorBoundary ([ca53322](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/ca53322b14265c26b94db73c5fed7cb7cdf1f343))
* **loader:** remove transform-box fill-box — orbits rotated around offset bbox ([82b754b](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/82b754b3abafc8383c95aecf28a81c116e843512))
* **ui:** block route render with centered GlobeLoader until queries resolve ([e165a55](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/e165a552aae42a05a2ad4b0f1187ad684b376fa6))

### 📝 Docs

* **api:** pending-endpoints brief for backend team ([a4add24](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/a4add2402aea8620d071e48ea8e598e8f62c8249))
2026-05-11 20:16:26 +00:00
Zimin A.N. 6c8cc21204 docs(api): mark 4/5 pending endpoints shipped, workflow API deferred
Status table в pending-endpoints.md обновлён: endpoints #1, #2, #4, #5
landed в MR !95-!98 в session 2026-05-11. Workflow API (#3) deferred —
требует отдельной design discussion + sprint (state machine + RBAC pool
model parallel to record-level DraftController architecture).
2026-05-11 23:15:41 +03:00
Zimin A.N. db4f859ef6 feat(api): PATCH /dictionaries/{name}/schema — inline non-breaking field edit (backend #4)
Backend #4 из pending-endpoints brief. Frontend Fields tab inline edit:
кликаешь field row → form показывает только allowed (non-breaking) changes
→ submit → patch component bumps (1.4.0 → 1.4.1) без full DictionaryEditorDialog.

Body:
```json
{
  "expectedHeadVersion": "1.4.0",
  "field": "altitude",
  "changes": { "description": {"ru":"Высота орбиты"}, "minimum": 0 }
}
```

Allowed change keys: description / title / minimum / maximum / enum.
Breaking keys (type/format/x-references/etc) → 422 breaking_change_requires_draft.

Validation:
- minimum tighter than current → 422 validation_failed (могло бы invalidate existing)
- maximum tighter than current → 422 validation_failed
- enum removing existing values → 422 (only additions allowed inline)
- expectedHeadVersion != actual → 409 version_mismatch (optimistic lock)

Implementation:
- PatchSchemaRequest DTO (record).
- SchemaPatchService: gates dict/scope/version, applies whitelisted changes
  on deep-copied JsonNode, bumps patch component via bumpPatchVersion helper
  (semver-safe + fallback для non-semver).
- DictionaryDefinitionController новый @PatchMapping.
- OrdinisException.unprocessableEntity helper (422).

Audit: hooks через existing AuditLogger.definitionUpdated после save.

Tests +10: 4xx scenarios, description update bumps version, enum add ok,
enum remove blocked, minimum expand ok / tighten blocked, version bump
helpers (semver + non-semver fallback).
2026-05-11 23:13:04 +03:00
Zimin A.N. e02e684cca feat(api): GET /dictionaries/{name}/snapshots — record-change buckets (backend #2)
Backend #2 из pending-endpoints brief. Frontend TimeTravelModal использует
этот endpoint для slider marks — каждая точка = bucket где минимум одна
запись validFrom попадает.

GET /api/v1/dictionaries/{name}/snapshots?from=...&to=...&granularity=day

Implementation:
- DictionaryRecordRepository.findSnapshotBuckets — native SQL date_trunc
  GROUP BY bucket, ORDER BY bucket DESC. scope filter через text[] из CSV.
- SnapshotsService — gates dict existence/scope, validates granularity
  (hour/day/week) + window, formats RU label (1 апр / сейчас), reverses
  список чтобы oldest first (UI читает слева-направо).
- DictionaryChangelogController новый endpoint /snapshots.

Errors:
- 404 dictionary_not_found
- 400 invalid_granularity (not in {hour,day,week})
- 400 invalid_window (from >= to)

Frontend impact: TimeTravelModal slider marks переходит с recordTimestamps
derived data на реальный API. ~1h frontend swap.
2026-05-11 23:08:07 +03:00
Zimin A.N. ebc90d76e9 feat(api): GET /dictionaries/{name}/changelog — schema versions timeline (backend #1)
Backend #1 из pending-endpoints brief. Frontend HistoryTabContent +
TimeTravelModal используют этот endpoint для отображения версий схемы
во времени с per-version property-level diff summary.

Implementation:
- AuditLogger.definitionCreated / definitionUpdated — пишет в audit_log
  с event_type DEFINITION_CREATED / DEFINITION_UPDATED. payload_before/
  after = JsonNode schema. record_id / business_key — NULL (dict-level event).
- DictionaryDefinitionService.create / updateSchema hook в audit logger
  (autowired, null-safe для tests).
- AuditLogRepository.findByDictionaryIdAndEventTypes — query by dict_id +
  event_type IN (...), ORDER BY event_time DESC, paginated.
- ChangelogService.findChangelog — собирает entries, computes top-level
  property-key diff (added/removed/changed). Первая entry (newest) =
  isCurrent + schemaVersion из DictionaryDefinition; старые entries
  возвращают version=null (semver-в-аудит backfill — separate migration).
- DictionaryChangelogController — GET /dictionaries/{name}/changelog?limit=50

Errors:
- 404 dictionary_not_found когда dict missing OR scope hidden (consistent
  с другими endpoints).

Tests +9: dict-not-found, scope-hidden, empty-audit, first-is-current,
diff-added/removed/changed/null-before/identical.
2026-05-11 23:04:09 +03:00
Александр Зимин b4a9f09e5e Merge branch 'feat/graph-outgoing-batch' into 'main'
feat(api): GET /dictionaries/graph/outgoing — batch outgoing FK summary (backend #5)

See merge request 2-6/2-6-4/terravault/ordinis!95
2026-05-11 19:56:59 +00:00
Zimin A.N. ff05ef9a9f feat(api): GET /dictionaries/graph/outgoing — batch outgoing FK summary
Frontend admin-UI catalog list (`→` column) парсил schemaJson per-row
для подсчёта outgoing FK refs. Этот endpoint возвращает batch:

  GET /api/v1/dictionaries/graph/outgoing?dicts=satellites,operators

  → { "outgoing": {
      "satellites": { "fkCount": 3, "targets": ["launch_sites", "missions", "operators"] },
      "operators":  { "fkCount": 0, "targets": [] }
    } }

Implementation:
- LineageIndexService.findOutgoingFkSummary — обходит DictionaryDefinitionRepo.findAll()
  + ScopeContext filter, парсит x-references через ReferenceValidator.parseRef,
  dedup target dict names, sort alphabetically.
- LineageController новый endpoint + OutgoingGraphResponse wrapper record
  (extensible — sibling fields в будущем без breaking).

Errors: scope hide (тихо skip — same pattern что и GET /dictionaries).
Malformed x-references логируются WARN + skip (не падают на одной плохой
schema).

Tests +6 cases: empty, basic counts, scope hide, whitelist filter, dedup
repeated target, malformed-not-fatal.
2026-05-11 22:54:43 +03:00
Александр Зимин 848eb2243a Merge branch 'fix/loop-globeloader-error-boundary' into 'main'
fix(ui): infinite-loop + GlobeLoader + AppErrorBoundary + a11y modals

See merge request 2-6/2-6-4/terravault/ordinis!94
2026-05-11 19:48:59 +00:00
Zimin A.N. a4add2402a docs(api): pending-endpoints brief for backend team
5 endpoints нужны admin-UI для завершения UI-фич:
  1. GET /dictionaries/{name}/changelog — History tab + TimeTravel
  2. GET /dictionaries/{name}/snapshots — TimeTravel slider marks
  3. POST drafts/.../{review,decision,publish} — workflow state machine
  4. PATCH /dictionaries/{name}/schema — Fields tab inline edit
  5. GET /dictionaries/graph/outgoing — catalog → FK count column

Каждый endpoint содержит: purpose, route, query/body, response example,
errors, frontend integration estimate. Total frontend work after backend
ship — ~14h (1.5 sprint day).
2026-05-11 22:47:24 +03:00
Zimin A.N. 82b754b3ab fix(loader): remove transform-box fill-box — orbits rotated around offset bbox
CSS transform-box default для SVG = view-box (transform-origin в viewBox
user coords). С transform-box: fill-box origin становится относительным
bounding-box каждой группы (whirl + whirl-rev — arc bbox смещён). Арки
летали по неправильной траектории. Прототип HTML rely on default — copy.
2026-05-11 22:43:32 +03:00
Zimin A.N. acde4e134d feat(loader): real Natural Earth globe via d3-geo + topojson + world-atlas
Per user — GlobeLoader должен показывать реальные континенты (Asia/Africa/
Australia outline) с rotating orthographic projection, как в прототипе
Downloads/Globe loader/Globe Loader.html. Прошлая версия использовала
faked ellipses graticule — выглядело как абстрактные кольца, не как глобус.

Implementation:
- d3-geo.geoOrthographic + d3.geoPath для projection math
- topojson-client.feature для распаковки world-atlas land-110m
- dynamic import обоих deps + JSON — не блокирует main bundle, lazy chunk
- requestAnimationFrame loop пересчитывает d-attr на каждом кадре
  (8s per revolution per прототип, tilt -15° lean)
- LAND_CACHE module-level — повторные mount'ы не re-fetch
- CSS .globe-sphere rotation удалена — d3 projection делает работу,
  CSS transform distort'ила бы land mass (нет projection math)

Bundle hit: ~55kb (land-110m.json) + ~15kb gzipped (d3-geo + topojson) —
lazy chunk, fetched один раз и cached.
2026-05-11 22:39:58 +03:00
Zimin A.N. e165a552aa fix(ui): block route render with centered GlobeLoader until queries resolve
Per user feedback ('вот такого не должно быть, лучше лоадер'):
- /dictionaries — full-page LoadingBlock (size lg, centered min-h 60vh)
  пока useDictionaries query loading. Раньше size=md без centering
  показывался в углу — а на пустой странице это смотрелось куце.
- /dictionaries/$name — same gate на detailQuery.isLoading. Без этого
  юзер видел partial render: пустую sidebar info panel, узкую records
  колонку (extra columns ещё не computed из schema), битую табличную
  toolbar. Теперь — централизованный GlobeLoader пока схема не дойдёт.
2026-05-11 22:37:22 +03:00
Zimin A.N. ca53322b14 fix(form): break drawer counter/dirty infinite-loop + add GlobeLoader + AppErrorBoundary
Maximum update depth exceeded showed на /dictionaries/$name когда RecordDrawer
открывался в create mode. Root cause:
  1. SchemaDrivenForm useEffect deps включал onCounterChange/onDirtyChange.
  2. Parent route передавал inline arrow (() => setDrawerCount({...})) —
     новая identity каждый render.
  3. setDrawerCount({visible, total}) создавал новый object literal даже
     при тех же значениях → React re-render → effect fires → loop.

Fix:
- SchemaDrivenForm: ref-pattern для callback. useEffect subscribed только
  на value deps (visibleFieldCount/totalFieldCount/dirtyCount), latest
  callback хранится в ref.
- dataValues — useMemo с frozen EMPTY_DATA default чтобы не invalidate'ить
  isFieldVisible memo каждый render.

Plus:
- GlobeLoader component — orbital globe spinner per Downloads/Globe loader
  prototype. Pure SVG + CSS animations, без d3/topojson.
- LoadingBlock переключен с Loader2 на GlobeLoader (все usage обновляется
  автоматически: RecordHistoryDrawer, dictionaries.$name editor loading,
  search results, webhooks list, etc).
- AppErrorBoundary — friendly fallback вместо TanStack DefaultErrorComponent.
  GlobeLoader (paused/dimmed) + 'Что-то пошло не так' + [Обновить][На главную].
  Dev-only collapsible с raw stack trace.
2026-05-11 22:31:57 +03:00
semantic-release-bot a0bc784754 chore(release): v1.6.1 [skip ci]
## [1.6.1](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v1.6.0...v1.6.1) (2026-05-11)

### 🐛 Fixes

* **ui:** remove TopBar search (final) + add clear X to catalog input ([7f32416](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/7f3241686c9896d33e4a6add5806a0fd587fd046))
* **ui:** restore TopBar search + add notifications bell + theme to sidebar ([7e44df3](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/7e44df34931f56235fff6bebd62e4ac3be010032))
* **ui:** TopBar right cluster + catalog toolbar h-8 align ([24f04ef](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/24f04ef3efbfe71ed8cc19a519dff6370beb0741))
2026-05-11 19:30:09 +00:00
Zimin A.N. 7429cff009 fix(a11y): add sr-only DialogTitle/Description to record/export/timetravel modals
Radix Dialog warns when DialogContent отсутствует accessible name/description.
RecordDrawer (Sheet) уже имел Title, добавили sr-only Description.
ConflictDiffModal/ExportModal/TimeTravelModal — кастомные visible headers,
теперь имеют sr-only Title + Description для screen readers + чтобы
заглушить dev warnings.
2026-05-11 22:25:06 +03:00
Александр Зимин 399efb48b1 Merge branch 'fix/topbar-right-align-toolbar-h8' into 'main'
fix(ui): TopBar right align + catalog toolbar h-8

See merge request 2-6/2-6-4/terravault/ordinis!93
2026-05-11 19:21:05 +00:00
Александр Зимин 89c66b0aa0 Merge branch 'fix/topbar-remove-search-catalog-clear-x' into 'main'
fix(ui): remove TopBar search + add clear X to catalog input

See merge request 2-6/2-6-4/terravault/ordinis!92
2026-05-11 19:13:37 +00:00
Zimin A.N. 24f04ef3ef fix(ui): TopBar right cluster + catalog toolbar h-8 align
- TopBar: right cluster `md:ml-0 ml-auto` → `ml-auto` always. Без TopBar
  search в центре уже нечего push'ить вправо через form, right cluster
  должен сам прижиматься к правому краю. User: "в топбаре руководство
  и далее по правой стороне".
- Catalog toolbar: scope chips / bundle pills / Граф button — все на
  h-8 (было py-1 + inline text variable height). + inline-flex
  items-center чтобы baseline консистентный с input/Граф/+Создать.
  User: "высоту элементов в баре таблиц выровняй".
2026-05-11 22:11:24 +03:00
Александр Зимин 5365170de2 Merge branch 'fix/topbar-restore-search-single-x' into 'main'
fix(ui): restore TopBar search + notifications bell + theme to sidebar

See merge request 2-6/2-6-4/terravault/ordinis!91
2026-05-11 19:09:15 +00:00
Zimin A.N. 7f3241686c fix(ui): remove TopBar search (final) + add clear X to catalog input
User clarification after MR !91:
- "Search из TopBar убран — все верно" — TopBar search должен быть удалён.
- "TopBar search вернулся. убери его" — MR !91 ошибочно его вернул.
- "два крестика баг в топбаре был а ты и в таблице убрал его" — двойной X
  was в TopBar (native + custom); в catalog был только custom X на
  старом input. После refactor catalog input получился без X совсем —
  fix: добавил кастомный clear button когда q непустой.

Changes:
- TopBar: removed form + SearchInput + handlers (handleSearchInput /
  Submit / Clear / inputRef / useState). Removed useEffect ⌘K shortcut
  (без search input nothing to focus). Right cluster: Docs +
  VersionBadge + NotificationsBell. ml-auto на right cluster чтобы
  push'ить вправо без search в центре.
- Catalog input: добавлен absolute-positioned X (✕) справа input'а
  когда `search.q` непустой. `pr-7` на input чтобы текст не наезжал.
  Clear → `setSearch({ q: undefined })`. Single X confirmed visually.
2026-05-11 22:07:00 +03:00
Zimin A.N. 7e44df3493 fix(ui): restore TopBar search + add notifications bell + theme to sidebar
Follow-up к MR !90 per user feedback iterations:

1) "в поиске по справочникам два крестика" — fixed в SearchInput:
   `type="search"` (native browser X) → `type="text"`. Custom onClear X
   остаётся единственным. Catalog input тоже type="text".

2) "блин два крестика было на топбар поиске а тут норм все. верни" —
   restore TopBar search input. Context-aware behavior сохранён:
   - На /dictionaries → live filter каталога через URL ?q=
   - На остальных routes → submit (Enter) → /search records search
   Single X confirmed by visual test.

3) "свитч темы можно тоже в профиль перенести" — ThemeSwitch переехал в
   Sidebar footer (рядом с RU/EN button). Right row в footer: lang button
   слева, theme switch (3 icons sun/moon/monitor) справа через ml-auto.

4) "руководство и версию оставить в топбар чтобы подсвечивать новинки" —
   Docs + VersionBadge stays in TopBar. Туда же добавлена
   NotificationsBell (placeholder Bell icon) — broadcast slot для
   webhook errors / draft reviews / system notices когда backend
   notifications stream появится.
2026-05-11 22:03:12 +03:00
semantic-release-bot ffdf942344 chore(release): v1.6.0 [skip ci]
## [1.6.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v1.5.0...v1.6.0) (2026-05-11)

###  Features

* **ui:** batch UI polish — auth/lang to sidebar, search h-7, info overflow, graph zoom ([d9df2fc](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/d9df2fc359856dedc7a4f6a0aea8728dc508a706))
2026-05-11 19:01:38 +00:00
Александр Зимин ce2768d1d9 Merge branch 'feat/ui-polish-batch' into 'main'
feat(ui): batch UI polish — auth/lang to sidebar, search h-7, info overflow, graph zoom

See merge request 2-6/2-6-4/terravault/ordinis!90
2026-05-11 18:55:48 +00:00
Zimin A.N. d9df2fc359 feat(ui): batch UI polish — auth/lang to sidebar, search h-7, info overflow, graph zoom
User feedback batch — multiple iterations of UX refinement.

Layout shifts:
- TopBar right cluster: AuthBadge + LanguageSwitch переехали в Sidebar
  footer per user ("вход в сайдбар перенесем", "ru/en тоже в сайд баре").
  TopBar теперь: breadcrumb + search + Docs + VersionBadge + ThemeSwitch
  only. Освобождает место + concentrates user/lang controls в одном месте.
- Sidebar footer: новая структура — Lang toggle (Язык [RU/EN]) + Auth block
  (avatar+name+logout authed, Sign-in CTA anonymous) + collapse button.
  Refactored из inline JSX в named subcomponents (AuthedUserBlock,
  SignInCta, SidebarFooter).

Sizing / spacing:
- TopBar SearchInput: h-9 → h-7 to match LangSwitch/ThemeSwitch (+ Sign-in
  кнопка). User: "поиск по справочникам высоту выровняй". Override via
  `!h-7 text-cell` className на SearchInput.
- TopBar: h-14 → h-11 (slimmer). Sidebar logo block matches h-11.

Catalog search:
- Catalog page input в toolbar — restored для on-page filter ("Catalog
  search никак не работает" → проверил, работает; добавил TopBar context-
  aware behavior где TopBar input на /dictionaries route синхронизируется
  с URL ?q= live).
- TopBar search context-aware: catalog mode = live filter; else = submit
  → /search (records JSONB search).

InfoPanel:
- Description: `text-body text-ink-2 leading-relaxed` → +
  `break-words overflow-hidden`. Long slash-separated values
  (LZW/Deflate/JPEG2000/ZSTD/LERC) теперь wrap'ятся внутри panel вместо
  overflow за границы (user: "описание убежало за границы панели").
- Container: + `min-w-0 overflow-hidden` для proper flex shrinking.

Graph:
- Zoom controls overlay (+/-/1:1/N%) + mouse wheel zoom toward cursor +
  drag pan по empty space. Per user: "Граф связей еще не зумируется".

WorkflowBanner:
- Moved в InfoPanel banner slot (compact flex-col layout) — free
  horizontal space выше editor + concentrates status info в left rail.

Auth:
- AuthBadge: primary Button → compact h-7 outline button. Matches
  TopBar toolbar control style.
- RequireAuth: убран visible amber error banner "Авторизация недоступна:
  Failed to fetch" — silent fall-through к anonymous mode (user feedback).
- routes/index.tsx: beforeLoad skip redirect если есть `?code=` в URL
  (OIDC callback fix). HomeIndex компонент рендерит null + redirect на
  /dictionaries после auth complete.

LanguageSwitch:
- h-8 + items-stretch + inner items-center — matches ThemeSwitch height.
- Later moved entirely в Sidebar footer (h-7 button only) per user.
2026-05-11 21:50:21 +03:00
semantic-release-bot 1bee41e2cf chore(release): v1.5.0 [skip ci]
## [1.5.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v1.4.0...v1.5.0) (2026-05-11)

###  Features

* **editor:** restore 3-col HubView + hide AOI on non-geo dicts ([b0e1995](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/b0e19951b30773545fdaf296e398ffe3ec4b5cae))
2026-05-11 17:55:39 +00:00
Александр Зимин 4b14749ec0 Merge branch 'feat/restore-hub-view-hide-aoi-non-geo' into 'main'
feat(editor): restore 3-col HubView + hide AOI on non-geo dicts

See merge request 2-6/2-6-4/terravault/ordinis!89
2026-05-11 17:49:44 +00:00
semantic-release-bot c3ae1a7ecc chore(release): v1.4.0 [skip ci]
## [1.4.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v1.3.0...v1.4.0) (2026-05-11)

###  Features

* **catalog:** scope-colored row stripes + filter pills + chips ([bc73782](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/bc737820d6a74755494987bf7c45cc2674ab2365))
* **catalog:** toolbar layout per redesign prototype ([ad7c51d](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/ad7c51d93fe73c8af4c91464637992ef758d9b48))
* **editor:** Fields / Events / History tabs match redesign prototype ([cbe21db](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/cbe21dbc52026998ceb91205a491b531f201c0c1))
* **editor:** scope-colored InfoPanel badge + Time-travel label ([e580a04](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/e580a04007e2a0658b3cfcedc73f240bd81978ac))
* **editor:** wrap InfoPanel + main content in bordered panels per prototype ([ce1f40c](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/ce1f40c5d1771166a7ba59785d8b2a4623c0ed9a))
* **editor:** Связи tab 2-col split per redesign prototype ([180a592](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/180a5920fe79b2144396bc3fb6ff6a90337e3a3e))
* **layout:** catalog relative time + chevron + flat sidebar per redesign (4) ([7e33456](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/7e33456d70875ad70e8748517cb668b0abd6fec2)), closes [#faf9f5](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/issues/faf9f5)
* **record:** conflict diff modal на 409 save (handoff line 444) ([16da694](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/16da694d8ca9acb1a3014f0d2947ea2421c57401))
* **records:** accent businessKey + remove redundant Export CSV from bulk bar ([3e4d789](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/3e4d78906d4ebb976ec9382defd6c7c502add794))
* **topbar:** match redesign prototype — breadcrumb back-arrow + cleaner right cluster ([ac1ca8d](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/ac1ca8d035d928bfd90ab36650cd38a196a73ebc))

### 🐛 Fixes

* **catalog:** title→TopBar + toolbar→tinted bar + table white + font fix ([d77f040](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/d77f040a5c2ba7b566cd94d50f1776d695988278))
* **table:** white row bg + stronger hover per user feedback ([a27e9ec](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/a27e9ec901d609afea150d1272c2be5b4bee8adb)), closes [#faf9f5](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/issues/faf9f5)
* **topbar:** restore full right cluster per user preference ([38f7dce](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/38f7dcee3ec7ba645ecbbaa8e278fb060f2b7c6c))
* **topbar:** revert ThemeSwitch to 3-icon original + shorten create button ([6627fd9](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/6627fd918d382f338bc4ee2667df70dfae604191))
2026-05-11 17:47:48 +00:00
Zimin A.N. b0e19951b3 feat(editor): restore 3-col HubView + hide AOI on non-geo dicts
Per user feedback:
- "hub view" — restore старый 3-col layout с central focused dict card +
  outgoing FK rail слева + refBy rail справа. Был simpler 2-col split,
  но user previously сказал "Связи и вкладка связи была удобнее" (старый
  hub более информативный + центральная карта показывает context).
  Revert к версии 5007e0f (pre-2-col-redesign).
- "aoi там где нет полей гео лишний" — InfoPanel AOI button теперь скрыт
  если schema dict не имеет geo properties. Heuristic: property name
  matches /geom|location|bbox|polygon|coordinates|geo/i OR format=geojson|wkt.
  Edge case: если active aoi уже set → button показывается чтобы clear.
2026-05-11 20:19:27 +03:00
Александр Зимин ff0a8b25cc Merge branch 'feat/business-key-accent-bulk-bar-export-removed' into 'main'
feat(records): accent businessKey + remove Export from bulk bar

See merge request 2-6/2-6-4/terravault/ordinis!88
2026-05-11 17:14:49 +00:00
Zimin A.N. 3e4d78906d feat(records): accent businessKey + remove redundant Export CSV from bulk bar
Per user feedback:
- "поле Бизнес-ключ выделен цветом" — businessKey column TableCell теперь
  `text-mono text-accent` (было plain text-mono). Matches prototype 03 где
  RES-P-1, KAN-V-3, SNT-1A показаны в accent orange — primary identifier
  для каждой row.
- "Экспорт CSV в bulk bar лишний как повтор Экспорт кнопки в InfoPanel" —
  убрал Export button из BulkSelectionToolbar. ExportModal pre-picks
  scope=selected когда selection.size > 0, поэтому workflow:
  select rows → click "↓ Экспорт..." в InfoPanel → modal с pre-selected
  scope. Бэк endpoint тот же, UX cleaner — один путь к export'у.
- Removed handleBulkExport callback + DownloadSimpleIcon import (теперь
  unused).
2026-05-11 20:14:43 +03:00
Александр Зимин 3da788c5da Merge branch 'feat/editor-bordered-panels' into 'main'
feat(editor): wrap InfoPanel + main content in bordered panels

See merge request 2-6/2-6-4/terravault/ordinis!87
2026-05-11 17:11:10 +00:00
Zimin A.N. ce1f40c5d1 feat(editor): wrap InfoPanel + main content in bordered panels per prototype
Per user feedback: "словари в своих панелях то как у нас было ранее".

Per redesign prototype editor view (Ordinis(4) compact.html):
- InfoPanel: was floating sidebar aside без borders → теперь
  `rounded-lg border border-line bg-surface p-4` — visible bordered card
  containing PUBLIC chip + meta + Связи + actions.
- Main editor area: tabs + toolbar + tab content (records/relations/
  fields/json/events/history) обёрнуты в `rounded-lg border border-line
  bg-surface overflow-hidden` panel.
- WorkflowBanner и AOI banner остаются outside panels (status chrome).

Visual containment отделяет editor chrome от page background, делает
очевидным где info ends / table starts. Matches prototype Screen 03-08.
2026-05-11 20:11:04 +03:00
Александр Зимин ea729dc901 Merge branch 'fix/catalog-toolbar-bar-topbar-count' into 'main'
fix(catalog): title→TopBar + toolbar→tinted bar + table white + font fix

See merge request 2-6/2-6-4/terravault/ordinis!86
2026-05-11 17:06:23 +00:00
Zimin A.N. d77f040a5c fix(catalog): title→TopBar + toolbar→tinted bar + table white + font fix
Per user feedback:
- "Справочники 37 шт. эта надпись в топбаре" — title с inline count
  переехал в TopBar breadcrumb (новый Crumb.caption field, text-cap mute).
  Catalog page больше не имеет h1 — start straight from toolbar.
- "фильтры и кнопки в баре таблицы. бар цветом" — toolbar (scope/bundle
  pills + counter + Граф + + Создать) обёрнут в tinted `bg-surface-2`
  rounded bar с border. Визуально отделяет controls от table chrome.
- "заголовки таблицы белый фон" — table thead was `bg-surface-2` (cream),
  сливалось с toolbar bar. Стало `bg-surface` (white) — clean visual
  separation toolbar (tinted) → table (white).
- "→ ссылается шрифт не тот" — InfoPanel section subhead "→ ссылается"
  / "← используют" был `text-cap` (Tektur uppercase 10.5px bold).
  Прототип использует regular body Inter lowercase mute. Заменил на
  `text-body text-mute`.

TopBar useBreadcrumb extended: для catalog route добавляет inline `caption`
field из useDictionaries() count. Editor route остаётся с mono `subtitle`
("name · v1.0.0"). Different fields rendered с different styles.
2026-05-11 20:06:18 +03:00
Александр Зимин d4348d4d26 Merge branch 'fix/table-rows-white-stronger-hover' into 'main'
fix(table): white row bg + stronger hover

See merge request 2-6/2-6-4/terravault/ordinis!85
2026-05-11 17:00:45 +00:00
Zimin A.N. a27e9ec901 fix(table): white row bg + stronger hover per user feedback
User: "строки таблиц белые / ховер на них более чёткий а то еле видно".

Прошлый hover был bg-surface-2/40 (40% opacity на cream/yellow page bg) —
почти неотличим от default. Под page bg #faf9f5 + 40% opacity surface-2
тёмное пятно еле проступало. На long тяжело отследить какая row под cursor.

Изменения:
- DictRow (catalog table): убран subtle scope-color bg tint (был
  warn-bg/30, pink-bg/30 — еле виден на page bg). Row всегда `bg-surface`
  (white). Scope visually conveyed через 3px left-stripe + colored SCOPE
  chip. Hover full strength `bg-surface-2` (no /40 opacity).
- FieldsTabContent + EventsTabContent rows: same change — bg-surface +
  hover:bg-surface-2.
- Shared TableRow component (ui/components/table.tsx): bg-surface +
  hover:bg-surface-2 — applies к records table, audit, и любым другим
  TableRow callsites.
2026-05-11 20:00:40 +03:00
Александр Зимин 1b382cb338 Merge branch 'fix/topbar-restore-full-cluster' into 'main'
fix(topbar): restore full right cluster (Docs/VersionBadge/LangSwitch)

See merge request 2-6/2-6-4/terravault/ordinis!84
2026-05-11 16:56:06 +00:00
Zimin A.N. 38f7dcee3e fix(topbar): restore full right cluster per user preference
User explicitly: "Руководство · dev · 19a3731b · ☀️🌙🖥 · RU EN · zimin.an · ↩
это оставь". Revert MR !81 cluster-minimization — diagnostic info нужна
для prod debugging.

Restored:
- Docs link (/docs/) — opens admin docs portal
- VersionBadge (channel + commit short SHA) — shows local/dev/v1.x.x · hash
- LanguageSwitch (dual RU | EN radio) — keeps both visible vs single-toggle
- (ThemeSwitch + AuthBadge остаются как были)
2026-05-11 19:55:52 +03:00
Zimin A.N. 6627fd918d fix(topbar): revert ThemeSwitch to 3-icon original + shorten create button
User explicitly: "ThemeSwitch не трогай". Реверт my 2-button Earth|Dark
переделку обратно на 3-icon Sun/Moon/Monitor segmented control (по
original 3bfa7ca).

Также:
- schema.action.create RU: "Создать справочник" → "Создать"
- schema.action.create EN: "Create dictionary" → "Create"
  (per prototype catalog button — короче чтобы не растягивать toolbar)
2026-05-11 19:50:41 +03:00
Александр Зимин 1102e7b8ec Merge branch 'feat/scope-badge-timetravel-label' into 'main'
feat(editor): scope-colored InfoPanel badge + Time-travel label

See merge request 2-6/2-6-4/terravault/ordinis!82
2026-05-11 16:46:52 +00:00
Zimin A.N. e580a04007 feat(editor): scope-colored InfoPanel badge + Time-travel label
Per redesign (4) prototype.

- InfoPanel scope badge: было `<Badge variant="info">` (generic light bg).
  Стало scope-color filled chip: PUBLIC→accent-bg, INTERNAL→warn-bg,
  RESTRICTED→pink-bg. Matches table SCOPE col + filter pills.
- i18n: timeTravel.button RU "Просмотр на дату" → "Time-travel…"; EN
  "View as of date" → "Time-travel…". User confirmed: "Time-travel label
  оставь" — единый label везде, без локализации (бренд-слово как редизайн).
2026-05-11 19:46:33 +03:00
Александр Зимин a9394ea363 Merge branch 'feat/topbar-cleanup-infopanel-order' into 'main'
feat(topbar): breadcrumb back-arrow + cleaner right cluster + InfoPanel order

See merge request 2-6/2-6-4/terravault/ordinis!81
2026-05-11 16:43:21 +00:00
Zimin A.N. ac1ca8d035 feat(topbar): match redesign prototype — breadcrumb back-arrow + cleaner right cluster
Per /Users/zimin/Downloads/Ordinis (4)/redesign/compact.html.

TopBar breadcrumb:
- Detail routes теперь показывают `← Справочники / Космические аппараты`
  с back-arrow prefix на parent crumb (caption text, mute). Bold title +
  inline mono subtitle "satellites · v1.0.0".
- Catalog route: simple "Dictionaries" title.

TopBar right cluster cleanup:
- Removed `Docs` link — diagnostic, не critical UX, моя кноп не нужна
  для UI flow.
- Removed `VersionBadge` (commit + tag) — был noise рядом с продакшн
  features. Build info всё ещё доступна в browser console / Docs.
- ThemeSwitch: tri-state (Light/Dark/System icons 3×24px) заменён на
  2-button `Earth | Dark` с text labels (per prototype). `system`
  preference остаётся в localStorage для existing users, но новый UI
  не выставляет.
- LanguageSwitch: dual radio `RU | EN` заменён на single toggle button —
  показывает текущий язык как label, click переключает на следующий.
  Saves ~60px горизонтально, matches prototype.

EditorInfoPanel order:
- Action buttons (Экспорт / Time-travel / AOI) переехали из середины
  panel (между metadata и Relations) в bottom (после Relations) —
  per prototype. Info → meta → relations → actions flow.
- Action order: Экспорт первым (frequent), затем Time-travel, AOI последним
  (rare для most dicts).
2026-05-11 19:43:05 +03:00
Александр Зимин 4219a6f96d Merge branch 'feat/catalog-scope-color-rows' into 'main'
feat(catalog): scope-colored row stripes + filter pills + chips

See merge request 2-6/2-6-4/terravault/ordinis!80
2026-05-11 16:35:57 +00:00
Zimin A.N. bc737820d6 feat(catalog): scope-colored row stripes + filter pills + chips
Per redesign prototype screenshot: каждая row имеет 3px цветной strip слева
по scope + filter chips заполняются scope-color когда active.

- DictRow: добавлен absolute-positioned `<span>` шириной 3px на левом краю
  первой td (relative wrapper), background = SCOPE_DOT (PUBLIC=accent,
  INTERNAL=warn, RESTRICTED=pink). pl-1 на контенте чтобы не наезжал.
- Row bg tint: для INTERNAL/RESTRICTED rows — subtle SCOPE_BG_TINT/30,
  PUBLIC = plain white (default).
- SCOPE col chip: использует SCOPE_BG_TINT + SCOPE_TEXT вместо generic
  Badge info — теперь PUBLIC chip orange, INTERNAL amber, RESTRICTED pink.
- Toolbar scope filter pills: active state = SCOPE_BG_TINT + SCOPE_TEXT +
  border-transparent (filled in scope color). Inactive = outline.
2026-05-11 19:35:43 +03:00
Zimin A.N. 180a5920fe feat(editor): Связи tab 2-col split per redesign prototype
Per /Users/zimin/Downloads/Ordinis (4)/redesign/screens/04-editor-links.png.

Replaced 3-col hub view (left rail + center dict card + right rail) с simple
2-col grid. Central dict card стал избыточен — все его info уже в InfoPanel
слева, дублирование тратило место и attention.

New layout:
┌────────────────────────────┬────────────────────────────┐
│ → ССЫЛАЕТСЯ НА (N)         │ ← ССЫЛАЮТСЯ НА НАС (M)     │
│ ┌──────────────────────┐   │ ┌──────────────────────┐   │
│ │ {target} {count}     │   │ │ {source} {count}     │   │
│ │ {req|opt} {.field}   │   │ │ {крит} {.field}      │   │
│ └──────────────────────┘   │ ├──────────────────────┤   │
│                            │ │ Warning N ссылок     │   │
│                            │ └──────────────────────┘   │
└────────────────────────────┴────────────────────────────┘

Each outgoing row: target_dict (link accent) | recordCount | required/optional
chip | source_field (mono right).
Each incoming row: source_dict (link) | activeRecordsInSourceDict | onClose
policy chip (BLOCK=критично pink, CASCADE=warn amber) | .source_field.

Footer warning в incoming panel когда totalDeps > 100 — "удаление сложно".
2026-05-11 19:29:37 +03:00
Александр Зимин 19a3731ba9 Merge branch 'feat/catalog-relative-time-flat-sidebar' into 'main'
feat(layout): catalog relative time + chevron + flat sidebar per redesign (4)

See merge request 2-6/2-6-4/terravault/ordinis!78
2026-05-11 16:27:18 +00:00