Merge branch 'feat/webhook-schema-draft-events' into 'main'

feat(webhooks): event-type multi-select + schema draft events (E)

See merge request 2-6/2-6-4/terravault/ordinis!134
This commit is contained in:
Александр Зимин
2026-05-12 11:48:34 +00:00
2 changed files with 39 additions and 11 deletions
+4 -4
View File
@@ -159,8 +159,8 @@ i18n
'webhooks.field.scopeFilterHint': 'Пусто = все scope',
'webhooks.field.dictionaryFilter': 'Справочники (CSV)',
'webhooks.field.dictionaryFilterHint': 'Через запятую: spacecraft, satellite_type. Пусто = все',
'webhooks.field.eventTypeFilter': 'Типы событий (CSV)',
'webhooks.field.eventTypeFilterHint': 'record.created, record.updated, record.closed. Пусто = все',
'webhooks.field.eventTypeFilter': 'Типы событий',
'webhooks.field.eventTypeFilterHint': 'Record*, Definition*, SchemaDraft*. Пусто = все события.',
'webhooks.field.description': 'Описание',
'webhooks.field.createdBy': 'Создатель',
'webhooks.error.nameUrlRequired': 'Имя и URL обязательны',
@@ -799,8 +799,8 @@ i18n
'webhooks.field.scopeFilterHint': 'Empty = all scopes',
'webhooks.field.dictionaryFilter': 'Dictionaries (CSV)',
'webhooks.field.dictionaryFilterHint': 'Comma-separated: spacecraft, satellite_type. Empty = all',
'webhooks.field.eventTypeFilter': 'Event types (CSV)',
'webhooks.field.eventTypeFilterHint': 'record.created, record.updated, record.closed. Empty = all',
'webhooks.field.eventTypeFilter': 'Event types',
'webhooks.field.eventTypeFilterHint': 'Record*, Definition*, SchemaDraft*. Empty = all events.',
'webhooks.field.description': 'Description',
'webhooks.field.createdBy': 'Created by',
'webhooks.error.nameUrlRequired': 'Name and URL are required',
+35 -7
View File
@@ -49,6 +49,34 @@ const SCOPE_OPTIONS: SelectOption[] = [
{ id: 'RESTRICTED', label: 'RESTRICTED' },
]
/**
* Known outbox event types в порядке от самых частых (record CRUD) до
* реже встречающихся (schema workflow). Backend emit'ит PascalCase
* (см. DictionaryRecordService, DictionaryDefinitionService,
* SchemaDraftService). При новых событиях — добавлять сюда.
*
* <p>Pre-v2.4: hint текст в форме фигурировал dot-case формат
* `record.created` — это был docs bug, backend такие не emit'ит.
* Multi-select закрывает дыру и не даёт пользователю ввести неверное
* строковое имя.
*/
const EVENT_TYPE_OPTIONS: SelectOption[] = [
// Record CRUD
{ id: 'RecordCreated', label: 'RecordCreated' },
{ id: 'RecordUpdated', label: 'RecordUpdated' },
{ id: 'RecordDeleted', label: 'RecordDeleted' },
// Dict definition / schema
{ id: 'DefinitionCreated', label: 'DefinitionCreated' },
{ id: 'DefinitionUpdated', label: 'DefinitionUpdated' },
// Schema workflow (v2.2.0+)
{ id: 'SchemaDraftCreated', label: 'SchemaDraftCreated' },
{ id: 'SchemaDraftUpdated', label: 'SchemaDraftUpdated' },
{ id: 'SchemaDraftReviewRequested', label: 'SchemaDraftReviewRequested' },
{ id: 'SchemaDraftDecided', label: 'SchemaDraftDecided' },
{ id: 'SchemaDraftPublished', label: 'SchemaDraftPublished' },
{ id: 'SchemaDraftWithdrawn', label: 'SchemaDraftWithdrawn' },
]
function WebhooksPage() {
const { t } = useTranslation()
const { data, isLoading, error } = useWebhookSubscriptions()
@@ -206,7 +234,7 @@ function CreateWebhookDialog({ open, onClose, onSuccess }: CreateDialogProps) {
const [url, setUrl] = useState('')
const [scopeFilter, setScopeFilter] = useState<string[]>([])
const [dictionaryFilterCsv, setDictionaryFilterCsv] = useState('')
const [eventTypeFilterCsv, setEventTypeFilterCsv] = useState('')
const [eventTypeFilter, setEventTypeFilter] = useState<string[]>([])
const [description, setDescription] = useState('')
const [errorMsg, setErrorMsg] = useState<string | null>(null)
@@ -215,7 +243,7 @@ function CreateWebhookDialog({ open, onClose, onSuccess }: CreateDialogProps) {
setUrl('')
setScopeFilter([])
setDictionaryFilterCsv('')
setEventTypeFilterCsv('')
setEventTypeFilter([])
setDescription('')
setErrorMsg(null)
}
@@ -243,7 +271,7 @@ function CreateWebhookDialog({ open, onClose, onSuccess }: CreateDialogProps) {
url: url.trim(),
scopeFilter: scopeFilter.length > 0 ? (scopeFilter as DataScope[]) : undefined,
dictionaryFilter: csvToArray(dictionaryFilterCsv),
eventTypeFilter: csvToArray(eventTypeFilterCsv),
eventTypeFilter: eventTypeFilter.length > 0 ? eventTypeFilter : undefined,
active: true,
description: description.trim() || undefined,
}
@@ -297,12 +325,12 @@ function CreateWebhookDialog({ open, onClose, onSuccess }: CreateDialogProps) {
value={dictionaryFilterCsv}
onChange={(e) => setDictionaryFilterCsv(e.target.value)}
/>
<TextInput
<MultiSelect
label={t('webhooks.field.eventTypeFilter')}
placeholder="record.created, record.updated"
options={EVENT_TYPE_OPTIONS}
value={eventTypeFilter}
onChange={(ids) => setEventTypeFilter(ids as string[])}
hint={t('webhooks.field.eventTypeFilterHint')}
value={eventTypeFilterCsv}
onChange={(e) => setEventTypeFilterCsv(e.target.value)}
/>
<TextArea
label={t('webhooks.field.description')}