fix(ui): DictionaryEditorDialog disables Save when draft workflow needed

This commit is contained in:
Александр Зимин
2026-05-14 12:33:43 +00:00
parent ce3b495561
commit 898cb345ec
3 changed files with 95 additions and 7 deletions
@@ -138,6 +138,24 @@ export const DictionaryEditorDialog = ({ open, mode, onClose, onSuccess }: Props
[isEdit, initial, changes, schemaVersion],
)
// Approval-aware Save: when editing an approval-required dict, any schema
// change OR toggling approvalRequired off OR changing approvalMinRole has
// to route through the schema-draft workflow. The backend will reject with
// 422 approval_required, but it's much better UX to disable Save up front
// and tell the user to open a draft instead. Mirror the three backend
// gate clauses exactly so the UX matches the server contract.
const wasApprovalRequired =
Boolean((initial as { approvalRequired?: boolean } | null)?.approvalRequired)
const initialMinRole =
((initial as { approvalMinRole?: string } | null)?.approvalMinRole ?? '') || null
const currentMinRole = approvalMinRole.trim() === '' ? null : approvalMinRole.trim()
const schemaChangedFromInitial = isEdit && changes.length > 0
const approvalToggledOff = isEdit && wasApprovalRequired && !approvalRequired
const minRoleChanged = isEdit && wasApprovalRequired && initialMinRole !== currentMinRole
const requiresDraftFlow =
isEdit && wasApprovalRequired
&& (schemaChangedFromInitial || approvalToggledOff || minRoleChanged)
const activeMutation = isEdit ? updateMut : createMut
const serverError = serverErrorMessage(activeMutation.error)
@@ -412,6 +430,17 @@ export const DictionaryEditorDialog = ({ open, mode, onClose, onSuccess }: Props
{serverError && <Alert variant="error">{serverError}</Alert>}
{requiresDraftFlow && (
<Alert variant="warning">
{t('schema.approvalRequired.editorBlock', {
defaultValue:
'Этот словарь требует ревью изменений. Закройте редактор и нажмите ' +
'«Создать черновик схемы» на странице справочника — там вы сможете ' +
'отправить эти изменения на согласование.',
})}
</Alert>
)}
<FormActions align="end">
<Button type="button" variant="ghost" onClick={onClose} disabled={activeMutation.isPending}>
{t('form.cancel')}
@@ -420,7 +449,7 @@ export const DictionaryEditorDialog = ({ open, mode, onClose, onSuccess }: Props
type="button"
variant="primary"
loading={activeMutation.isPending}
disabled={isEdit && breaking}
disabled={(isEdit && breaking) || requiresDraftFlow}
onClick={handleSubmit}
>
{activeMutation.isPending ? t('form.saving') : t('form.save')}