feat(admin-ui): D-pack — history, breaking-change detection, x-unique, x-id-source, datetime
History:
- Drawer на детальной странице записи (timeline всех версий через GET /records/{key}/history)
- Иконка ClockCounterClockwise в actions колонке таблицы записей
- Каждая версия показывает v(version), validFrom/To, updatedBy + expand JSON
Schema diff (breaking detection):
- Util diffSchemas() сравнивает старую/новую схему и классифицирует изменения:
breaking (removed/typeChanged/becameRequired/enumRemoved/maxLengthTightened/
patternChanged/newRequiredField), compatible (added optional/enumAdded/
becameOptional), metadata (description)
- В DictionaryEditorDialog при breaking → Alert с детальным списком + Save заблокирован
- При compatible → Alert info со списком
- suggestVersionBump: major для breaking, minor для compatible field changes,
patch для metadata-only
x-unique:
- Чекбокс «Уникальное» на PropertyEditor → emit x-unique: true в schema
- Backend enforcement позже — отдельный PR с partial unique index
x-id-source:
- SingleSelect в Метаданных «Использовать как ID» → emit x-id-source на schema root
- В SchemaDrivenForm если установлен — businessKey input скрывается, на submit
derived из data[idSource]
- Подсказка с именем поля
DateTime для validFrom/validTo:
- Заменил DatePicker (date-only) на DateTimeField компонент: DatePicker + TextInput
type=time рядом
- Default time: validFrom=00:00, validTo=23:59 (запись действует до конца дня
иначе зануляется в полночь)
- Поддерживает 2-часовые интервалы (запуск КА в 14:30 → сход в 02:15 etc.)
Bug fix:
- parseSchemaJson изменил сигнатуру с PropertyDef[] на {properties, idSource},
старый код в DictionaryEditorDialog падал "{} is not iterable". Поправлено
через destructuring const parsed = parseSchemaJson(...).
i18n: 25+ новых ключей (RU/EN) — schema.unique, schema.idSource, schema.diff.*,
history.*, form.idSourceNote.
This commit is contained in:
@@ -20,12 +20,13 @@ import {
|
||||
TableRow,
|
||||
TextInput,
|
||||
} from '@nstart/ui'
|
||||
import { PlusIcon, PencilSimpleIcon, XCircleIcon, GearIcon } from '@phosphor-icons/react'
|
||||
import { PlusIcon, PencilSimpleIcon, XCircleIcon, GearIcon, ClockCounterClockwiseIcon } from '@phosphor-icons/react'
|
||||
import { useDictionaryDetail, useRecordRaw, useRecords } from '@/api/queries'
|
||||
import { useCreateRecord, useUpdateRecord, useCloseRecord } from '@/api/mutations'
|
||||
import type { CreateRecordRequest, FlattenedRecord } from '@/api/client'
|
||||
import { SchemaDrivenForm } from '@/components/form/SchemaDrivenForm'
|
||||
import { DictionaryEditorDialog } from '@/components/schema/DictionaryEditorDialog'
|
||||
import { RecordHistoryDrawer } from '@/components/record/RecordHistoryDrawer'
|
||||
|
||||
export const Route = createFileRoute('/dictionaries/$name')({
|
||||
component: DictionaryDetail,
|
||||
@@ -49,6 +50,7 @@ function DictionaryDetail() {
|
||||
const [edit, setEdit] = useState<EditState>({ kind: 'closed' })
|
||||
const [closeReason, setCloseReason] = useState('')
|
||||
const [schemaEditOpen, setSchemaEditOpen] = useState(false)
|
||||
const [historyKey, setHistoryKey] = useState<string | undefined>(undefined)
|
||||
|
||||
const editingKey = edit.kind === 'edit' ? edit.record.businessKey : undefined
|
||||
const rawRecordQuery = useRecordRaw(name, editingKey)
|
||||
@@ -168,6 +170,12 @@ function DictionaryDetail() {
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<div className="flex items-center justify-end gap-1">
|
||||
<IconButton
|
||||
label={t('history.title')}
|
||||
variant="default"
|
||||
icon={<ClockCounterClockwiseIcon weight="regular" />}
|
||||
onClick={() => setHistoryKey(r.businessKey)}
|
||||
/>
|
||||
<IconButton
|
||||
label={t('dict.action.edit')}
|
||||
variant="default"
|
||||
@@ -299,6 +307,13 @@ function DictionaryDetail() {
|
||||
onSuccess={() => setSchemaEditOpen(false)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<RecordHistoryDrawer
|
||||
open={Boolean(historyKey)}
|
||||
onClose={() => setHistoryKey(undefined)}
|
||||
dictionaryName={name}
|
||||
businessKey={historyKey}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user