feat(admin-ui,cuod): array-FK picker для instrument

Три массива в instrument были comma-separated текстом с подсказкой
«businessKey'и из X». Пользователь не знал что туда вписать — справочника
доступных значений рядом нет.

UI: добавлен ReferenceMultiSelectField — array-аналог ReferenceSelectField.
Триггер — `items["x-references"]` на string-массиве. Под капотом — готовый
MultiSelect (popover + cmdk-поиск). Fallback на comma-separated TextInput
сохраняется когда target dict недоступен (scope-hide / 403 / 404), сервер
всё равно валидирует FK через ReferenceValidator.

Schema:
- spacecraft_codes      → items.x-references: spacecraft.designator
- supported_format_codes → items.x-references: data_format.code
- supported_level_codes  → items.x-references: processing_level.code

instrument schemaVersion 1.0.0 → 1.1.0, bundle 1.3.2 → 1.3.3 —
CuodBundleImporter перепишет schema_json в БД на старте writer'а,
admin-ui подхватит свежую схему через /api/v1/dictionaries/instrument.

Tests: 2 новых кейса в SchemaDrivenForm.test.tsx — happy path (MultiSelect
рендерится, запрос ушёл на правильный dict) + fallback (comma-separated
с подсказкой «список недоступен»). 171/171 passed.
This commit is contained in:
Zimin A.N.
2026-05-25 13:28:03 +03:00
parent 1ea402e7ec
commit 1cb0d868c8
4 changed files with 231 additions and 9 deletions
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://ordinis.nstart.cloud/schemas/cuod/instrument/1.0.0",
"$id": "https://ordinis.nstart.cloud/schemas/cuod/instrument/1.1.0",
"title": "Instrument (бортовой сенсор)",
"description": "Конкретный сенсор/полезная нагрузка на борту КА. Один прибор может летать на нескольких бортах (many-to-many со spacecraft).",
"type": "object",
@@ -32,8 +32,8 @@
},
"spacecraft_codes": {
"type": "array",
"description": "businessKey'и КА с этим прибором (many-to-many)",
"items": { "type": "string" },
"description": "КА с этим прибором (many-to-many) — FK на spacecraft.designator",
"items": { "type": "string", "x-references": "spacecraft.designator" },
"uniqueItems": true
},
"type": {
@@ -59,14 +59,14 @@
},
"supported_format_codes": {
"type": "array",
"description": "businessKey'и из data_format — какие форматы поддерживает выгрузка",
"items": { "type": "string" },
"description": "Форматы выгрузки — FK на data_format.code",
"items": { "type": "string", "x-references": "data_format.code" },
"uniqueItems": true
},
"supported_level_codes": {
"type": "array",
"description": "businessKey'и из processing_level — какие уровни обработки доступны",
"items": { "type": "string" },
"description": "Уровни обработки — FK на processing_level.code",
"items": { "type": "string", "x-references": "processing_level.code" },
"uniqueItems": true
},
"status": {
@@ -2,7 +2,7 @@
"bundle": "cuod",
"displayName": "ЦУОД ДЗЗ",
"description": "Bundle справочников для Центра Управления Обработкой Данных ДЗЗ. Anchor v1.",
"version": "1.3.2",
"version": "1.3.3",
"supportedLocales": ["ru-RU", "en-US"],
"defaultLocale": "ru-RU",
"dictionaries": [
@@ -12,7 +12,7 @@
{ "name": "ground_station", "displayName": "Наземные станции", "description": "Каталог наземных пунктов приёма и управления", "scope": "PUBLIC", "schemaResource": "ground_station.schema.json", "schemaVersion": "1.0.0", "approvalRequired": true },
{ "name": "antenna", "displayName": "Антенны", "description": "Антенны наземных станций с G/T и поддерживаемыми диапазонами.", "scope": "PUBLIC", "schemaResource": "antenna.schema.json", "schemaVersion": "1.0.0" },
{ "name": "mission", "displayName": "Миссии / программы", "description": "Программы ДЗЗ — Ресурс-П, Канопус-В, Sentinel и т.д. Группируют семейства КА.", "scope": "PUBLIC", "schemaResource": "mission.schema.json", "schemaVersion": "1.0.0" },
{ "name": "instrument", "displayName": "Инструменты съёмки", "description": "Полезная нагрузка / сенсоры на борту КА (Геотон-Л1, MODIS, C-SAR, ...)", "scope": "PUBLIC", "schemaResource": "instrument.schema.json", "schemaVersion": "1.0.0", "approvalRequired": true },
{ "name": "instrument", "displayName": "Инструменты съёмки", "description": "Полезная нагрузка / сенсоры на борту КА (Геотон-Л1, MODIS, C-SAR, ...)", "scope": "PUBLIC", "schemaResource": "instrument.schema.json", "schemaVersion": "1.1.0", "approvalRequired": true },
{ "name": "sensor_type", "displayName": "Типы сенсоров", "description": "Класс полезной нагрузки: optical/SAR/hyperspectral/lidar/thermal.", "scope": "PUBLIC", "schemaResource": "sensor_type.schema.json", "schemaVersion": "1.0.0" },
{ "name": "spectral_band", "displayName": "Спектральные каналы", "description": "Стандартные оптические/ИК каналы (PAN/R/G/B/NIR/SWIR/TIR).", "scope": "PUBLIC", "schemaResource": "spectral_band.schema.json", "schemaVersion": "1.0.0" },
{ "name": "frequency_band", "displayName": "Радиочастотные диапазоны", "description": "IEEE-диапазоны (L/S/C/X/Ku/Ka) для SAR и связи.", "scope": "PUBLIC", "schemaResource": "frequency_band.schema.json", "schemaVersion": "1.0.0" },