Files
dc-observatio/services/pcp-tgu-ui-service
Дмитрий Соловьев c402f376c5 feat(tgu-ui): степпер по прохождениям и подсветка конфликтов выбора слотов
Степпер прохождений (виток как проход над районом):
- slotPasses.ts: группировка слотов в проходы (КА·cycle·revolution·sign) в
  хронологии по всем КА + юнит-тесты;
- PassStepper.tsx: ◀/▶ листают проходы, окно суток следует за курсором,
  таблица скроллится к проходу, карта не прыгает; выбранный проход
  изолирует отображение, «Все» — назад ко всему набору;
- дата/время прохождения отдельной строкой во всю ширину (видно целиком).

Подсветка конфликтов выбора (мягкая подсказка «станет недоступным»):
- slotConflicts.ts: тот же КА + недостаточный зазор на манёвр — 10 с при том
  же крене, 30 с при смене крена (ROLL_EPSILON); конфликтные слоты гаснут в
  таблице и на карте, остаются выбираемыми (жёсткая выполнимость — за бэком);
- производительность: оконный поиск по времени (~O(N·logM)), кандидаты —
  только видимые, выбор через useDeferredValue (не молотит во время drag);
- чекбокс «Гасить конфликты» в строке выбора: выключает и слой, и расчёт;
- юнит-тесты на правило зазора и оконный поиск.

Карта: проп dimmedObjectIds — серый «налёт» поверх конфликтных слотов в SVG
overlay (без изменения canvas).
2026-06-17 13:31:28 +03:00
..

pcp-tgu-ui-service

Фронтенд «ТГУ — Операции». Сервис собран с нуля на чистой базе исходного pcp-tgu-ops-ui (React + Vite, своя тёмная тема), в которую добавлены только две вещи с платформы NStart:

  1. Авторизация — headless-ядро @nstart/auth (New Start ID / Keycloak): токен, login, logout, refresh. Без @nstart/ui — UI-компоненты библиотеки (ProfilePage/UserPanel) намеренно не подключены, экраны ТГУ остаются на своём UI.
  2. Сборка и деплой — платформенный контракт: hardened Dockerfile (non-root, healthcheck), runtime-config (config.js из APP_*), docker-bake.hcl, .gitlab-ci.yml (build → trivy/semgrep → push в registry), nginx.conf.

В отличие от pcp-tgu-ops-ui-template, здесь нет демо-страниц шаблона, @nstart/ui, Tailwind, i18n и борьбы тем — только рабочий ТГУ + auth + контур сборки/деплоя.

Авторизация (headless)

  • Режим выбирается переменной authMode (anonymous | new-start-id).
  • anonymous (дефолт): приложение открывается сразу, токена нет, заголовок Authorization не добавляется — поведение как у исходного сервиса.
  • new-start-id: вход редиректом на New Start ID; токен подставляется в каждый запрос src/api/* через мост apiFetch + AuthTokenBridge. В шапке появляется кнопка «Выйти».
  • Конфиг входа берётся из src/config/env.ts (runtime APP_* имеют приоритет над build VITE_*).

Конфигурация окружения

Назначение DEV (npm run dev) PROD (Docker)
источник .env (VITE_*) APP_* контейнера → config.js
api VITE_API_URL APP_API_URL
режим auth VITE_AUTH_MODE APP_AUTH_MODE
New Start ID VITE_NEW_START_ID_* APP_NEW_START_ID_*

Доступ к приватному реестру @nstart/*: scope @nstart:registry=... должен быть в ~/.npmrc (или в конфиге CI-раннера). Проектный .npmrc задаёт только min-release-age=7.

Запуск

cp .env.example .env     # режим anonymous, открывается сразу
npm install              # нужен доступ к repo.nstart.cloud (scope @nstart)
npm run dev              # http://localhost:5174
npm run build            # tsc -b + vite build
npm run test             # vitest

Прод-прокси (осталось настроить)

В nginx.conf активный /api/ — заглушка (127.0.0.1:8000), а блоки pcp-* закомментированы (зеркало server.proxy из vite.config.ts). Подставьте реальные UPSTREAM_* кластера и раскомментируйте, либо вынесите маршрутизацию на gateway/ingress.