feat(admin-ui): visual schema builder для создания/редактирования справочников
Новый функционал — заводить свои справочники через UI без code deploy:
API:
- CreateDictionaryRequest type в client.ts
- useCreateDictionary / useUpdateDictionary mutations с invalidate
['dictionaries'] и ['dictionary', name]
Компоненты (src/components/schema/):
- types.ts: PropertyDef + buildSchemaJson() (Draft-07) + parseSchemaJson()
для двусторонней конвертации между UI state и schema_json
- PropertyEditor: name + kind select + required + description + type-specific
опции (minLength/maxLength/pattern для string; minimum/maximum для number;
enum values; uniqueItems для array). Up/Down/Trash icon buttons
- SchemaBuilder: список property cards + кнопка «добавить» + EmptyState
- DictionaryEditorDialog: модалка с 3 табами:
* Метаданные (name/displayName/description/scope/bundle/version/locales)
* Поля (SchemaBuilder)
* JSON (readonly preview сгенерированной schema_json)
Поддерживаемые типы полей: string, integer, number, boolean, enum,
localized (i18n object с patternProperties), date (format=date),
datetime (format=date-time), array_string (с опц. enum + uniqueItems).
Wiring:
- /dictionaries: PageHeader actions = «+ Создать справочник» → Dialog в режиме create
→ onSuccess navigate на /dictionaries/{name}
- /dictionaries/$name: PageHeader actions расширен «Схема» (secondary) +
«Создать запись» (primary). Dialog в edit-режиме prefilled из
detailQuery.data + parseSchemaJson()
i18n: 30+ новых ключей в schema.* / scope.* (RU/EN)
This commit is contained in:
@@ -43,6 +43,47 @@ i18n
|
||||
'form.save': 'Сохранить',
|
||||
'form.saving': 'Сохранение...',
|
||||
'form.error.required': 'Обязательное поле',
|
||||
'scope.PUBLIC': 'PUBLIC — публичный',
|
||||
'scope.INTERNAL': 'INTERNAL — внутренний',
|
||||
'scope.RESTRICTED': 'RESTRICTED — ограниченный',
|
||||
'schema.action.create': 'Создать справочник',
|
||||
'schema.action.edit': 'Изменить справочник',
|
||||
'schema.action.editSchema': 'Схема',
|
||||
'schema.tabs.metadata': 'Метаданные',
|
||||
'schema.tabs.schema': 'Поля',
|
||||
'schema.tabs.preview': 'JSON',
|
||||
'schema.name': 'Имя',
|
||||
'schema.nameHint': 'snake_case, начинается с буквы (например my_dictionary)',
|
||||
'schema.nameInvalid': 'Только snake_case: a-z, 0-9, _; начинается с буквы',
|
||||
'schema.displayName': 'Отображаемое имя',
|
||||
'schema.description': 'Описание',
|
||||
'schema.scope': 'Scope',
|
||||
'schema.bundle': 'Bundle',
|
||||
'schema.bundleHint': 'Обычно cuod',
|
||||
'schema.version': 'Версия схемы',
|
||||
'schema.supportedLocales': 'Поддерживаемые локали',
|
||||
'schema.defaultLocale': 'Локаль по умолчанию',
|
||||
'schema.property': 'Поле',
|
||||
'schema.required': 'Обязательное',
|
||||
'schema.pattern': 'Pattern (regex)',
|
||||
'schema.enumValues': 'Значения enum (через запятую)',
|
||||
'schema.enumValuesHint': 'Например: ACTIVE, INACTIVE, RETIRED',
|
||||
'schema.arrayEnumOptional': 'Допустимые значения (опц., через запятую)',
|
||||
'schema.empty': 'Полей нет — добавь первое',
|
||||
'schema.addProperty': 'Добавить поле',
|
||||
'schema.delete': 'Удалить',
|
||||
'schema.moveUp': 'Выше',
|
||||
'schema.moveDown': 'Ниже',
|
||||
'schema.kind.label': 'Тип',
|
||||
'schema.kind.string': 'Строка',
|
||||
'schema.kind.integer': 'Целое',
|
||||
'schema.kind.number': 'Число',
|
||||
'schema.kind.boolean': 'Логическое',
|
||||
'schema.kind.enum': 'Enum (выбор из списка)',
|
||||
'schema.kind.localized': 'I18N строка (ru-RU/en-US/...)',
|
||||
'schema.kind.date': 'Дата',
|
||||
'schema.kind.datetime': 'Дата+время',
|
||||
'schema.kind.array_string': 'Массив строк',
|
||||
'field.name': 'Наименование',
|
||||
'field.designator': 'Designator (COSPAR)',
|
||||
'field.norad_id': 'NORAD ID',
|
||||
@@ -98,6 +139,47 @@ i18n
|
||||
'form.save': 'Save',
|
||||
'form.saving': 'Saving...',
|
||||
'form.error.required': 'Required field',
|
||||
'scope.PUBLIC': 'PUBLIC',
|
||||
'scope.INTERNAL': 'INTERNAL',
|
||||
'scope.RESTRICTED': 'RESTRICTED',
|
||||
'schema.action.create': 'Create dictionary',
|
||||
'schema.action.edit': 'Edit dictionary',
|
||||
'schema.action.editSchema': 'Schema',
|
||||
'schema.tabs.metadata': 'Metadata',
|
||||
'schema.tabs.schema': 'Fields',
|
||||
'schema.tabs.preview': 'JSON',
|
||||
'schema.name': 'Name',
|
||||
'schema.nameHint': 'snake_case, starts with letter (e.g. my_dictionary)',
|
||||
'schema.nameInvalid': 'Only snake_case: a-z, 0-9, _; must start with letter',
|
||||
'schema.displayName': 'Display name',
|
||||
'schema.description': 'Description',
|
||||
'schema.scope': 'Scope',
|
||||
'schema.bundle': 'Bundle',
|
||||
'schema.bundleHint': 'Usually cuod',
|
||||
'schema.version': 'Schema version',
|
||||
'schema.supportedLocales': 'Supported locales',
|
||||
'schema.defaultLocale': 'Default locale',
|
||||
'schema.property': 'Field',
|
||||
'schema.required': 'Required',
|
||||
'schema.pattern': 'Pattern (regex)',
|
||||
'schema.enumValues': 'Enum values (comma-separated)',
|
||||
'schema.enumValuesHint': 'E.g.: ACTIVE, INACTIVE, RETIRED',
|
||||
'schema.arrayEnumOptional': 'Allowed values (optional, comma-separated)',
|
||||
'schema.empty': 'No fields yet — add the first one',
|
||||
'schema.addProperty': 'Add field',
|
||||
'schema.delete': 'Delete',
|
||||
'schema.moveUp': 'Move up',
|
||||
'schema.moveDown': 'Move down',
|
||||
'schema.kind.label': 'Type',
|
||||
'schema.kind.string': 'String',
|
||||
'schema.kind.integer': 'Integer',
|
||||
'schema.kind.number': 'Number',
|
||||
'schema.kind.boolean': 'Boolean',
|
||||
'schema.kind.enum': 'Enum (pick from list)',
|
||||
'schema.kind.localized': 'I18N string (ru-RU/en-US/...)',
|
||||
'schema.kind.date': 'Date',
|
||||
'schema.kind.datetime': 'Date+time',
|
||||
'schema.kind.array_string': 'Array of strings',
|
||||
'field.name': 'Name',
|
||||
'field.designator': 'Designator (COSPAR)',
|
||||
'field.norad_id': 'NORAD ID',
|
||||
|
||||
Reference in New Issue
Block a user