mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-11-15 17:21:38 +03:00
F: Improve dialogs validation hinting
This commit is contained in:
parent
00f47c4b68
commit
5bf70ed3fa
|
|
@ -5,10 +5,11 @@ import { BadgeHelp } from '@/features/help/components/badge-help';
|
|||
|
||||
import { useEscapeKey } from '@/hooks/use-escape-key';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { globalIDs } from '@/utils/constants';
|
||||
import { prepareTooltip } from '@/utils/utils';
|
||||
|
||||
import { Button, MiniButton, SubmitButton } from '../control';
|
||||
import { IconClose } from '../icons';
|
||||
import { IconAlert, IconClose } from '../icons';
|
||||
import { type Styling } from '../props';
|
||||
import { cn } from '../utils';
|
||||
|
||||
|
|
@ -33,7 +34,7 @@ interface ModalFormProps extends ModalProps {
|
|||
submitText?: string;
|
||||
|
||||
/** Tooltip for the submit button when the form is invalid. */
|
||||
submitInvalidTooltip?: string;
|
||||
validationHint?: string;
|
||||
|
||||
/** Indicates that submit button is enabled. */
|
||||
canSubmit?: boolean;
|
||||
|
|
@ -60,7 +61,7 @@ export function ModalForm({
|
|||
|
||||
canSubmit = true,
|
||||
submitText = 'Продолжить',
|
||||
submitInvalidTooltip,
|
||||
validationHint,
|
||||
beforeSubmit,
|
||||
onSubmit,
|
||||
onCancel,
|
||||
|
|
@ -121,7 +122,7 @@ export function ModalForm({
|
|||
<div
|
||||
className={cn(
|
||||
'@container/modal',
|
||||
'max-h-[calc(100svh-8rem)] max-w-[100svw] xs:max-w-[calc(100svw-2rem)]',
|
||||
'max-h-[calc(100svh-8rem)] max-w-svw xs:max-w-[calc(100svw-2rem)]',
|
||||
'overscroll-contain outline-hidden',
|
||||
overflowVisible ? 'overflow-visible' : 'overflow-auto',
|
||||
className
|
||||
|
|
@ -131,14 +132,18 @@ export function ModalForm({
|
|||
{children}
|
||||
</div>
|
||||
|
||||
<div className='z-pop my-2 flex gap-12 justify-center text-sm'>
|
||||
<SubmitButton
|
||||
autoFocus
|
||||
text={submitText}
|
||||
title={!canSubmit ? submitInvalidTooltip : ''}
|
||||
className='min-w-28'
|
||||
disabled={!canSubmit}
|
||||
/>
|
||||
<div className='z-pop my-2 flex gap-12 justify-center text-sm relative'>
|
||||
{validationHint ? (
|
||||
<div className='absolute top-0.5 text-muted-foreground'>
|
||||
<IconAlert
|
||||
size='1.5rem'
|
||||
className={canSubmit ? 'hover:icon-green' : 'hover:icon-red'}
|
||||
data-tooltip-id={globalIDs.tooltip}
|
||||
data-tooltip-html={validationHint}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
<SubmitButton autoFocus text={submitText} className='min-w-28' disabled={!canSubmit} />
|
||||
<Button text='Отмена' aria-label='Закрыть' className='min-w-28' onClick={handleCancel} />
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ export function DlgCreatePromptTemplate() {
|
|||
submitText='Создать'
|
||||
canSubmit={canSubmit}
|
||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||
submitInvalidTooltip='Введите уникальное название шаблона'
|
||||
validationHint={canSubmit ? '' : 'Введите уникальное название шаблона'}
|
||||
className='cc-column w-140 max-h-120 py-2 px-6'
|
||||
helpTopic={HelpTopic.ASSISTANT}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -47,7 +47,11 @@ export function DlgChangeLocation() {
|
|||
overflowVisible
|
||||
header='Изменение расположения'
|
||||
submitText='Переместить'
|
||||
submitInvalidTooltip={`Допустимы буквы, цифры, подчерк, пробел и "!". Сегмент пути не может начинаться и заканчиваться пробелом. Общая длина (с корнем) не должна превышать ${limits.len_location}`}
|
||||
validationHint={
|
||||
isValid
|
||||
? ''
|
||||
: `Допустимы буквы, цифры, подчерк, пробел и "!". Сегмент пути не может начинаться и заканчиваться пробелом. Общая длина (с корнем) не должна превышать ${limits.len_location}`
|
||||
}
|
||||
canSubmit={isValid && isDirty}
|
||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||
className='w-130 pb-3 px-6 h-36'
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
|||
import { Checkbox, TextArea, TextInput } from '@/components/input';
|
||||
import { ModalForm } from '@/components/modal';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { errorMsg } from '@/utils/labels';
|
||||
import { hintMsg } from '@/utils/labels';
|
||||
|
||||
import { type ICreateVersionDTO, type IVersionInfo, schemaCreateVersion } from '../backend/types';
|
||||
import { useCreateVersion } from '../backend/use-create-version';
|
||||
|
|
@ -41,7 +41,15 @@ export function DlgCreateVersion() {
|
|||
mode: 'onChange'
|
||||
});
|
||||
const version = useWatch({ control, name: 'version' });
|
||||
const canSubmit = !!version && !versions.find(ver => ver.version === version);
|
||||
const { canSubmit, hint } = (() => {
|
||||
if (!version) {
|
||||
return { canSubmit: false, hint: hintMsg.versionEmpty };
|
||||
} else if (versions.find(ver => ver.version === version)) {
|
||||
return { canSubmit: false, hint: hintMsg.versionTaken };
|
||||
} else {
|
||||
return { canSubmit: true, hint: '' };
|
||||
}
|
||||
})();
|
||||
|
||||
function onSubmit(data: ICreateVersionDTO) {
|
||||
return versionCreate({ itemID, data }).then(onCreate);
|
||||
|
|
@ -52,7 +60,7 @@ export function DlgCreateVersion() {
|
|||
header='Создание версии'
|
||||
className='cc-column w-120 py-2 px-6'
|
||||
canSubmit={canSubmit}
|
||||
submitInvalidTooltip={errorMsg.versionTaken}
|
||||
validationHint={hint}
|
||||
submitText='Создать'
|
||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import { IconReset, IconSave } from '@/components/icons';
|
|||
import { TextArea, TextInput } from '@/components/input';
|
||||
import { ModalView } from '@/components/modal';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { errorMsg } from '@/utils/labels';
|
||||
import { hintMsg } from '@/utils/labels';
|
||||
|
||||
import { type IUpdateVersionDTO, schemaUpdateVersion } from '../../backend/types';
|
||||
import { useDeleteVersion } from '../../backend/use-delete-version';
|
||||
|
|
@ -106,7 +106,7 @@ export function DlgEditVersions() {
|
|||
<div className='cc-icons h-fit'>
|
||||
<MiniButton
|
||||
type='submit'
|
||||
title={isValid ? 'Сохранить изменения' : errorMsg.versionTaken}
|
||||
title={isValid ? 'Сохранить изменения' : hintMsg.versionTaken}
|
||||
aria-label='Сохранить изменения'
|
||||
icon={<IconSave size='1.25rem' className='icon-primary' />}
|
||||
disabled={!isDirty || !isValid || isProcessing}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { HelpTopic } from '@/features/help';
|
|||
import { ModalForm } from '@/components/modal';
|
||||
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { hintMsg } from '@/utils/labels';
|
||||
|
||||
import { type ICreateBlockDTO, type IOssLayout, schemaCreateBlock } from '../../backend/types';
|
||||
import { useCreateBlock } from '../../backend/use-create-block';
|
||||
|
|
@ -77,7 +78,17 @@ export function DlgCreateBlock() {
|
|||
const children_blocks = useWatch({ control: methods.control, name: 'children_blocks' });
|
||||
const children_operations = useWatch({ control: methods.control, name: 'children_operations' });
|
||||
const [activeTab, setActiveTab] = useState<TabID>(TabID.CARD);
|
||||
const canSubmit = methods.formState.isValid && !!title && !manager.oss.blocks.some(block => block.title === title);
|
||||
const { canSubmit, hint } = (() => {
|
||||
if (!methods.formState.isValid) {
|
||||
return { canSubmit: false, hint: hintMsg.formInvalid };
|
||||
} else if (!title) {
|
||||
return { canSubmit: false, hint: hintMsg.titleEmpty };
|
||||
} else if (manager.oss.blocks.some(block => block.title === title)) {
|
||||
return { canSubmit: false, hint: hintMsg.blockTitleTaken };
|
||||
} else {
|
||||
return { canSubmit: true, hint: '' };
|
||||
}
|
||||
})();
|
||||
|
||||
function onSubmit(data: ICreateBlockDTO) {
|
||||
data.position = manager.newBlockPosition(data);
|
||||
|
|
@ -90,6 +101,7 @@ export function DlgCreateBlock() {
|
|||
header='Создание блока'
|
||||
submitText='Создать'
|
||||
canSubmit={canSubmit}
|
||||
validationHint={hint}
|
||||
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
|
||||
className='w-160 px-6 h-110'
|
||||
helpTopic={HelpTopic.CC_STRUCTURING}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ export function TabBlockCard({ oss }: TabBlockCardProps) {
|
|||
<TextInput
|
||||
id='operation_title' //
|
||||
label='Название'
|
||||
placeholder='Введите название'
|
||||
{...register('item_data.title')}
|
||||
error={errors.item_data?.title}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { HelpTopic } from '@/features/help';
|
|||
import { TextArea, TextInput } from '@/components/input';
|
||||
import { ModalForm } from '@/components/modal';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { hintMsg } from '@/utils/labels';
|
||||
|
||||
import { type ICreateSchemaDTO, type IOssLayout, schemaCreateSchema } from '../backend/types';
|
||||
import { useCreateSchema } from '../backend/use-create-schema';
|
||||
|
|
@ -64,7 +65,17 @@ export function DlgCreateSchema() {
|
|||
mode: 'onChange'
|
||||
});
|
||||
const alias = useWatch({ control: control, name: 'item_data.alias' });
|
||||
const canSubmit = isValid && !!alias && !manager.oss.operations.some(operation => operation.alias === alias);
|
||||
const { canSubmit, hint } = (() => {
|
||||
if (!isValid) {
|
||||
return { canSubmit: false, hint: hintMsg.formInvalid };
|
||||
} else if (!alias) {
|
||||
return { canSubmit: false, hint: hintMsg.aliasEmpty };
|
||||
} else if (manager.oss.operations.some(operation => operation.alias === alias)) {
|
||||
return { canSubmit: false, hint: hintMsg.schemaAliasTaken };
|
||||
} else {
|
||||
return { canSubmit: true, hint: '' };
|
||||
}
|
||||
})();
|
||||
|
||||
function onSubmit(data: ICreateSchemaDTO) {
|
||||
data.position = manager.newOperationPosition(data);
|
||||
|
|
@ -77,6 +88,7 @@ export function DlgCreateSchema() {
|
|||
header='Создание операции: Новая схема'
|
||||
submitText='Создать'
|
||||
canSubmit={canSubmit}
|
||||
validationHint={hint}
|
||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||
className='w-180 px-6 pb-3 cc-column'
|
||||
helpTopic={HelpTopic.CC_OSS}
|
||||
|
|
@ -84,6 +96,7 @@ export function DlgCreateSchema() {
|
|||
<TextInput
|
||||
id='operation_title' //
|
||||
label='Название'
|
||||
placeholder='Введите название'
|
||||
{...register('item_data.title')}
|
||||
error={errors.item_data?.title}
|
||||
/>
|
||||
|
|
@ -93,6 +106,7 @@ export function DlgCreateSchema() {
|
|||
id='operation_alias' //
|
||||
label='Сокращение'
|
||||
className='w-80'
|
||||
placeholder='Введите сокращение'
|
||||
{...register('item_data.alias')}
|
||||
error={errors.item_data?.alias}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { Loader } from '@/components/loader';
|
|||
import { ModalForm } from '@/components/modal';
|
||||
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { hintMsg } from '@/utils/labels';
|
||||
|
||||
import { type ICreateSynthesisDTO, type IOssLayout, schemaCreateSynthesis } from '../../backend/types';
|
||||
import { useCreateSynthesis } from '../../backend/use-create-synthesis';
|
||||
|
|
@ -73,8 +74,17 @@ export function DlgCreateSynthesis() {
|
|||
});
|
||||
const alias = useWatch({ control: methods.control, name: 'item_data.alias' });
|
||||
const [activeTab, setActiveTab] = useState<TabID>(TabID.ARGUMENTS);
|
||||
const canSubmit =
|
||||
methods.formState.isValid && !!alias && !manager.oss.operations.some(operation => operation.alias === alias);
|
||||
const { canSubmit, hint } = (() => {
|
||||
if (!methods.formState.isValid) {
|
||||
return { canSubmit: false, hint: hintMsg.formInvalid };
|
||||
} else if (!alias) {
|
||||
return { canSubmit: false, hint: hintMsg.aliasEmpty };
|
||||
} else if (manager.oss.operations.some(operation => operation.alias === alias)) {
|
||||
return { canSubmit: false, hint: hintMsg.schemaAliasTaken };
|
||||
} else {
|
||||
return { canSubmit: true, hint: '' };
|
||||
}
|
||||
})();
|
||||
|
||||
function onSubmit(data: ICreateSynthesisDTO) {
|
||||
data.position = manager.newOperationPosition(data);
|
||||
|
|
@ -87,6 +97,7 @@ export function DlgCreateSynthesis() {
|
|||
header='Создание операции синтеза'
|
||||
submitText='Создать'
|
||||
canSubmit={canSubmit}
|
||||
validationHint={hint}
|
||||
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
|
||||
className='w-180 px-6 h-128'
|
||||
helpTopic={HelpTopic.CC_OSS}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ export function TabArguments({ oss }: TabArgumentsProps) {
|
|||
<TextInput
|
||||
id='operation_title'
|
||||
label='Название'
|
||||
placeholder='Введите название'
|
||||
{...register('item_data.title')}
|
||||
error={errors.item_data?.title}
|
||||
/>
|
||||
|
|
@ -40,6 +41,7 @@ export function TabArguments({ oss }: TabArgumentsProps) {
|
|||
<TextInput
|
||||
id='operation_alias' //
|
||||
label='Сокращение'
|
||||
placeholder='Введите сокращение'
|
||||
className='w-80'
|
||||
{...register('item_data.alias')}
|
||||
error={errors.item_data?.alias}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,12 @@ export function TabSubstitutions({ oss }: TabSubstitutionsProps) {
|
|||
)}
|
||||
/>
|
||||
|
||||
<TextArea disabled value={validator.msg} rows={4} className={isCorrect ? '' : 'border-(--acc-fg-red) border-2'} />
|
||||
<TextArea
|
||||
disabled
|
||||
value={validator.msg}
|
||||
rows={4}
|
||||
className={isCorrect ? '' : 'border-accent-red-foreground border-2'}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ export function DlgEditBlock() {
|
|||
<TextInput
|
||||
id='operation_title' //
|
||||
label='Название'
|
||||
placeholder='Введите название'
|
||||
{...register('item_data.title')}
|
||||
error={errors.item_data?.title}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { Loader } from '@/components/loader';
|
|||
import { ModalForm } from '@/components/modal';
|
||||
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { hintMsg } from '@/utils/labels';
|
||||
|
||||
import { type IOssLayout, type IUpdateOperationDTO, OperationType, schemaUpdateOperation } from '../../backend/types';
|
||||
import { useOssSuspense } from '../../backend/use-oss';
|
||||
|
|
@ -79,6 +80,7 @@ export function DlgEditOperation() {
|
|||
header='Редактирование операции'
|
||||
submitText='Сохранить'
|
||||
canSubmit={canSubmit}
|
||||
validationHint={hintMsg.formInvalid}
|
||||
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
|
||||
className='w-160 px-6 h-128'
|
||||
helpTopic={HelpTopic.UI_SUBSTITUTIONS}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ export function TabOperation({ oss }: TabOperationProps) {
|
|||
<TextInput
|
||||
id='operation_title'
|
||||
label='Название'
|
||||
placeholder='Введите название'
|
||||
{...register('item_data.title')}
|
||||
error={errors.item_data?.title}
|
||||
/>
|
||||
|
|
@ -29,6 +30,7 @@ export function TabOperation({ oss }: TabOperationProps) {
|
|||
<TextInput
|
||||
id='operation_alias' //
|
||||
label='Сокращение'
|
||||
placeholder='Введите сокращение'
|
||||
className='w-80'
|
||||
{...register('item_data.alias')}
|
||||
error={errors.item_data?.alias}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,12 @@ export function TabSubstitutions({ oss }: TabSubstitutionsProps) {
|
|||
)}
|
||||
/>
|
||||
|
||||
<TextArea disabled value={validator.msg} rows={4} className={isCorrect ? '' : 'border-(--acc-fg-red) border-2'} />
|
||||
<TextArea
|
||||
disabled
|
||||
value={validator.msg}
|
||||
rows={4}
|
||||
className={isCorrect ? '' : 'border-accent-red-foreground border-2'}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { PickSchema } from '@/features/library/components/pick-schema';
|
|||
import { Checkbox, TextArea, TextInput } from '@/components/input';
|
||||
import { ModalForm } from '@/components/modal';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { hintMsg } from '@/utils/labels';
|
||||
|
||||
import { type IImportSchemaDTO, type IOssLayout, schemaImportSchema } from '../backend/types';
|
||||
import { useImportSchema } from '../backend/use-import-schema';
|
||||
|
|
@ -73,7 +74,17 @@ export function DlgImportSchema() {
|
|||
});
|
||||
const alias = useWatch({ control: control, name: 'item_data.alias' });
|
||||
const clone_source = useWatch({ control: control, name: 'clone_source' });
|
||||
const canSubmit = isValid && !!alias && !manager.oss.operations.some(operation => operation.alias === alias);
|
||||
const { canSubmit, hint } = (() => {
|
||||
if (!isValid) {
|
||||
return { canSubmit: false, hint: hintMsg.formInvalid };
|
||||
} else if (!alias) {
|
||||
return { canSubmit: false, hint: hintMsg.aliasEmpty };
|
||||
} else if (manager.oss.operations.some(operation => operation.alias === alias)) {
|
||||
return { canSubmit: false, hint: hintMsg.schemaAliasTaken };
|
||||
} else {
|
||||
return { canSubmit: true, hint: '' };
|
||||
}
|
||||
})();
|
||||
|
||||
function onSubmit(data: IImportSchemaDTO) {
|
||||
data.position = manager.newOperationPosition(data);
|
||||
|
|
@ -101,6 +112,7 @@ export function DlgImportSchema() {
|
|||
header='Создание операции: Загрузка'
|
||||
submitText='Создать'
|
||||
canSubmit={canSubmit}
|
||||
validationHint={hint}
|
||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||
className='w-180 px-6 pb-3 cc-column'
|
||||
helpTopic={HelpTopic.CC_OSS}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import { MiniButton } from '@/components/control';
|
|||
import { Loader } from '@/components/loader';
|
||||
import { ModalForm } from '@/components/modal';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { hintMsg } from '@/utils/labels';
|
||||
|
||||
import { type IOssLayout, type IRelocateConstituentsDTO, schemaRelocateConstituents } from '../backend/types';
|
||||
import { useOssSuspense } from '../backend/use-oss';
|
||||
|
|
@ -120,7 +121,7 @@ export function DlgRelocateConstituents() {
|
|||
header='Перенос конституент'
|
||||
submitText='Переместить'
|
||||
canSubmit={canSubmit}
|
||||
submitInvalidTooltip='Необходимо выбрать хотя бы одну собственную конституенту'
|
||||
validationHint={canSubmit ? '' : hintMsg.relocateEmpty}
|
||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||
className='w-160 h-132 py-3 px-6'
|
||||
helpTopic={HelpTopic.UI_RELOCATE_CST}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
|||
|
||||
import { ModalForm } from '@/components/modal';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { errorMsg } from '@/utils/labels';
|
||||
import { hintMsg } from '@/utils/labels';
|
||||
import { type RO } from '@/utils/meta';
|
||||
|
||||
import {
|
||||
|
|
@ -37,7 +37,15 @@ export function DlgCreateCst() {
|
|||
});
|
||||
const alias = useWatch({ control: methods.control, name: 'alias' });
|
||||
const cst_type = useWatch({ control: methods.control, name: 'cst_type' });
|
||||
const canSubmit = methods.formState.isValid && validateNewAlias(alias, cst_type, schema);
|
||||
const { canSubmit, hint } = (() => {
|
||||
if (!methods.formState.isValid) {
|
||||
return { canSubmit: false, hint: hintMsg.formInvalid };
|
||||
} else if (!validateNewAlias(alias, cst_type, schema)) {
|
||||
return { canSubmit: false, hint: hintMsg.aliasInvalid };
|
||||
} else {
|
||||
return { canSubmit: true, hint: '' };
|
||||
}
|
||||
})();
|
||||
|
||||
function onSubmit(data: ICreateConstituentaDTO) {
|
||||
return cstCreate({ itemID: schema.id, data }).then(onCreate);
|
||||
|
|
@ -48,7 +56,7 @@ export function DlgCreateCst() {
|
|||
header='Создание конституенты'
|
||||
canSubmit={canSubmit}
|
||||
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
|
||||
submitInvalidTooltip={errorMsg.aliasInvalid}
|
||||
validationHint={hint}
|
||||
submitText='Создать'
|
||||
className='cc-column w-140 max-h-120 py-2 px-6'
|
||||
>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { Loader } from '@/components/loader';
|
|||
import { ModalForm } from '@/components/modal';
|
||||
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { hintMsg } from '@/utils/labels';
|
||||
import { type RO } from '@/utils/meta';
|
||||
|
||||
import {
|
||||
|
|
@ -61,7 +62,17 @@ export function DlgCstTemplate() {
|
|||
});
|
||||
const alias = useWatch({ control: methods.control, name: 'alias' });
|
||||
const cst_type = useWatch({ control: methods.control, name: 'cst_type' });
|
||||
const canSubmit = methods.formState.isValid && validateNewAlias(alias, cst_type, schema);
|
||||
const { canSubmit, hint } = (() => {
|
||||
if (!cst_type) {
|
||||
return { canSubmit: false, hint: hintMsg.templateInvalid };
|
||||
} else if (!methods.formState.isValid) {
|
||||
return { canSubmit: false, hint: hintMsg.formInvalid };
|
||||
} else if (!validateNewAlias(alias, cst_type, schema)) {
|
||||
return { canSubmit: false, hint: hintMsg.aliasInvalid };
|
||||
} else {
|
||||
return { canSubmit: true, hint: '' };
|
||||
}
|
||||
})();
|
||||
|
||||
const [activeTab, setActiveTab] = useState<TabID>(TabID.TEMPLATE);
|
||||
|
||||
|
|
@ -76,6 +87,7 @@ export function DlgCstTemplate() {
|
|||
className='w-172 h-140 px-6'
|
||||
canSubmit={canSubmit}
|
||||
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
|
||||
validationHint={hint}
|
||||
helpTopic={HelpTopic.RSL_TEMPLATES}
|
||||
>
|
||||
<Tabs className='grid' selectedIndex={activeTab} onSelect={index => setActiveTab(index as TabID)}>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { MiniButton } from '@/components/control';
|
|||
import { IconChild, IconRSForm } from '@/components/icons';
|
||||
import { ModalForm } from '@/components/modal';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { errorMsg } from '@/utils/labels';
|
||||
import { hintMsg } from '@/utils/labels';
|
||||
|
||||
import { type IUpdateConstituentaDTO, schemaUpdateConstituenta } from '../../backend/types';
|
||||
import { useRSFormSuspense } from '../../backend/use-rsform';
|
||||
|
|
@ -91,7 +91,7 @@ export function DlgEditCst() {
|
|||
header='Редактирование конституенты'
|
||||
canSubmit={canSubmit}
|
||||
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
|
||||
submitInvalidTooltip={errorMsg.aliasInvalid}
|
||||
validationHint={canSubmit ? '' : hintMsg.aliasInvalid}
|
||||
submitText='Сохранить'
|
||||
className='cc-column w-140 max-h-120 py-2 px-6'
|
||||
>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { HelpTopic } from '@/features/help';
|
|||
import { ModalForm } from '@/components/modal';
|
||||
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { hintMsg } from '@/utils/labels';
|
||||
|
||||
import { labelReferenceType } from '../../labels';
|
||||
import {
|
||||
|
|
@ -116,6 +117,7 @@ export function DlgEditReference() {
|
|||
header='Редактирование ссылки'
|
||||
submitText='Сохранить ссылку'
|
||||
canSubmit={canSubmit}
|
||||
validationHint={canSubmit ? '' : hintMsg.referenceInvalid}
|
||||
onCancel={onCancel}
|
||||
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
|
||||
className='w-160 px-6 h-128'
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { Loader } from '@/components/loader';
|
|||
import { ModalForm } from '@/components/modal';
|
||||
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { hintMsg } from '@/utils/labels';
|
||||
|
||||
import { type IInlineSynthesisDTO, schemaInlineSynthesis } from '../../backend/types';
|
||||
import { useInlineSynthesis } from '../../backend/use-inline-synthesis';
|
||||
|
|
@ -58,6 +59,7 @@ export function DlgInlineSynthesis() {
|
|||
submitText='Добавить конституенты'
|
||||
className='w-160 h-132 px-6'
|
||||
canSubmit={canSubmit}
|
||||
validationHint={canSubmit ? '' : hintMsg.sourceEmpty}
|
||||
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
|
||||
>
|
||||
<Tabs className='grid' selectedIndex={activeTab} onSelect={index => setActiveTab(index as TabID)}>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { HelpTopic } from '@/features/help';
|
|||
import { TextInput } from '@/components/input';
|
||||
import { ModalForm } from '@/components/modal';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { hintMsg } from '@/utils/labels';
|
||||
|
||||
import { type CstType, type IUpdateConstituentaDTO, schemaUpdateConstituenta } from '../backend/types';
|
||||
import { useRSFormSuspense } from '../backend/use-rsform';
|
||||
|
|
@ -60,8 +61,8 @@ export function DlgRenameCst() {
|
|||
<ModalForm
|
||||
header='Переименование конституенты'
|
||||
submitText='Переименовать'
|
||||
submitInvalidTooltip='Введите незанятое имя, соответствующее типу'
|
||||
canSubmit={canSubmit}
|
||||
validationHint={canSubmit ? '' : hintMsg.aliasInvalid}
|
||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||
className='w-120 py-6 pr-3 pl-6 flex gap-3 justify-center items-center'
|
||||
helpTopic={HelpTopic.CC_CONSTITUENTA}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { SubstitutionValidator } from '@/features/oss/models/oss-api';
|
|||
import { ErrorField, TextArea } from '@/components/input';
|
||||
import { ModalForm } from '@/components/modal';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { hintMsg } from '@/utils/labels';
|
||||
|
||||
import { type ISubstitutionsDTO, schemaSubstitutions } from '../backend/types';
|
||||
import { useRSFormSuspense } from '../backend/use-rsform';
|
||||
|
|
@ -50,8 +51,8 @@ export function DlgSubstituteCst() {
|
|||
<ModalForm
|
||||
header='Отождествление'
|
||||
submitText='Отождествить'
|
||||
submitInvalidTooltip='Выберите две различные конституенты'
|
||||
canSubmit={isValid}
|
||||
validationHint={isValid ? '' : hintMsg.substitutionsEmpty}
|
||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||
className='w-160 px-6 pb-3'
|
||||
helpTopic={HelpTopic.UI_SUBSTITUTIONS}
|
||||
|
|
@ -74,7 +75,7 @@ export function DlgSubstituteCst() {
|
|||
disabled
|
||||
value={validator.msg}
|
||||
rows={4}
|
||||
className={clsx('mt-3', isCorrect ? '' : 'border-(--acc-fg-red) border-2')}
|
||||
className={clsx('mt-3', isCorrect ? '' : 'border-accent-red-foreground border-2')}
|
||||
/>
|
||||
</ModalForm>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { Checkbox, FileInput } from '@/components/input';
|
|||
import { ModalForm } from '@/components/modal';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { EXTEOR_TRS_FILE } from '@/utils/constants';
|
||||
import { hintMsg } from '@/utils/labels';
|
||||
|
||||
import { useUploadTRS } from '../backend/use-upload-trs';
|
||||
|
||||
|
|
@ -42,6 +43,7 @@ export function DlgUploadRSForm() {
|
|||
<ModalForm
|
||||
header='Импорт схемы из Экстеора'
|
||||
canSubmit={!!file}
|
||||
validationHint={!!file ? '' : hintMsg.fileEmpty}
|
||||
onSubmit={handleSubmit}
|
||||
submitText='Загрузить'
|
||||
className='w-100 px-6'
|
||||
|
|
|
|||
|
|
@ -68,12 +68,30 @@ export const errorMsg = {
|
|||
privacyNotAccepted: 'Примите политику обработки персональных данных',
|
||||
loginFormat: 'Имя пользователя должно содержать только буквы и цифры',
|
||||
invalidLocation: 'Некорректный формат пути',
|
||||
versionTaken: 'Версия с таким шифром уже существует',
|
||||
emptySubstitutions: 'Выберите хотя бы одно отождествление',
|
||||
aliasInvalid: 'Введите незанятое имя, соответствующее типу',
|
||||
invalidResponse: 'Некорректный ответ сервера'
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* UI hint descriptors.
|
||||
*/
|
||||
export const hintMsg = {
|
||||
templateInvalid: 'Выберите шаблон конституенты',
|
||||
formInvalid: 'Форма заполнена некорректно',
|
||||
aliasInvalid: 'Введите незанятое имя, соответствующее типу',
|
||||
aliasEmpty: 'Введите сокращение',
|
||||
titleEmpty: 'Введите название',
|
||||
blockTitleTaken: 'Блок с таким названием уже существует',
|
||||
schemaAliasTaken: 'Схема с таким именем уже существует',
|
||||
versionEmpty: 'Введите шифр версии',
|
||||
versionTaken: 'Версия с таким шифром уже существует',
|
||||
relocateEmpty: 'Необходимо выбрать хотя бы одну собственную конституенту',
|
||||
substitutionsEmpty: 'Выберите две различные конституенты',
|
||||
sourceEmpty: 'Выберите схему источник',
|
||||
referenceInvalid: 'Выберите тип ссылки и заполните все поля',
|
||||
fileEmpty: 'Выберите файл для загрузки'
|
||||
};
|
||||
|
||||
/**
|
||||
* UI tooltip descriptors.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user