F: Fix forms that are subject to react compiler problems
This commit is contained in:
parent
ddc5c7e767
commit
9b0cc3107b
|
@ -72,8 +72,20 @@ export type ICreateLibraryItemDTO = z.infer<typeof CreateLibraryItemSchema>;
|
|||
/**
|
||||
* Represents update data for editing {@link ILibraryItem}.
|
||||
*/
|
||||
export interface IUpdateLibraryItemDTO
|
||||
extends Omit<ILibraryItem, 'time_create' | 'time_update' | 'access_policy' | 'location' | 'owner'> {}
|
||||
export const UpdateLibraryItemSchema = z.object({
|
||||
id: z.number(),
|
||||
item_type: z.nativeEnum(LibraryItemType),
|
||||
title: z.string().nonempty(errors.requiredField),
|
||||
alias: z.string().nonempty(errors.requiredField),
|
||||
comment: z.string(),
|
||||
visible: z.boolean(),
|
||||
read_only: z.boolean()
|
||||
});
|
||||
|
||||
/**
|
||||
* Represents update data for editing {@link ILibraryItem}.
|
||||
*/
|
||||
export type IUpdateLibraryItemDTO = z.infer<typeof UpdateLibraryItemSchema>;
|
||||
|
||||
/**
|
||||
* Create version metadata in persistent storage.
|
||||
|
|
|
@ -32,6 +32,6 @@ export const useUpdateItem = () => {
|
|||
}
|
||||
});
|
||||
return {
|
||||
updateItem: (data: IUpdateLibraryItemDTO) => mutation.mutate(data)
|
||||
updateItem: (data: IUpdateLibraryItemDTO, onSuccess?: () => void) => mutation.mutate(data, { onSuccess })
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
'use no memo'; // TODO: remove when react hook forms are compliant with react compiler
|
||||
'use client';
|
||||
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { useEffect, useLayoutEffect, useState } from 'react';
|
||||
import { useEffect, useLayoutEffect, useMemo, useState } from 'react';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
|
@ -50,19 +51,26 @@ function FormConstituenta({ disabled, id, toggleReset, schema, activeCst, onOpen
|
|||
|
||||
const [localParse, setLocalParse] = useState<IExpressionParse | undefined>(undefined);
|
||||
|
||||
const typification = localParse
|
||||
const typification = useMemo(
|
||||
() =>
|
||||
localParse
|
||||
? labelTypification({
|
||||
isValid: localParse.parseResult,
|
||||
resultType: localParse.typification,
|
||||
args: localParse.args
|
||||
})
|
||||
: labelCstTypification(activeCst);
|
||||
: labelCstTypification(activeCst),
|
||||
[localParse, activeCst]
|
||||
);
|
||||
|
||||
const typeInfo = {
|
||||
const typeInfo = useMemo(
|
||||
() => ({
|
||||
alias: activeCst.alias,
|
||||
result: localParse ? localParse.typification : activeCst.parse.typification,
|
||||
args: localParse ? localParse.args : activeCst.parse.args
|
||||
};
|
||||
}),
|
||||
[activeCst, localParse]
|
||||
);
|
||||
|
||||
const [forceComment, setForceComment] = useState(false);
|
||||
const isBasic = isBasicConcept(activeCst.cst_type);
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
'use no memo'; // TODO: remove when react hook forms are compliant with react compiler
|
||||
'use client';
|
||||
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import clsx from 'clsx';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { useForm, useWatch } from 'react-hook-form';
|
||||
|
||||
import { useConceptNavigation } from '@/app/Navigation/NavigationContext';
|
||||
import { urls } from '@/app/urls';
|
||||
import { IUpdateLibraryItemDTO } from '@/backend/library/api';
|
||||
import { IUpdateLibraryItemDTO, UpdateLibraryItemSchema } from '@/backend/library/api';
|
||||
import { useUpdateItem } from '@/backend/library/useUpdateItem';
|
||||
import { useMutatingRSForm } from '@/backend/rsform/useMutatingRSForm';
|
||||
import { IconSave } from '@/components/Icons';
|
||||
|
@ -28,106 +31,82 @@ interface FormRSFormProps {
|
|||
function FormRSForm({ id }: FormRSFormProps) {
|
||||
const controller = useRSEdit();
|
||||
const router = useConceptNavigation();
|
||||
const schema = controller.schema;
|
||||
const { updateItem: update } = useUpdateItem();
|
||||
const { isModified, setIsModified } = useModificationStore();
|
||||
const { updateItem: updateSchema } = useUpdateItem();
|
||||
const { setIsModified } = useModificationStore();
|
||||
const isProcessing = useMutatingRSForm();
|
||||
|
||||
const [title, setTitle] = useState(schema.title);
|
||||
const [alias, setAlias] = useState(schema.alias);
|
||||
const [comment, setComment] = useState(schema.comment);
|
||||
const [visible, setVisible] = useState(schema.visible);
|
||||
const [readOnly, setReadOnly] = useState(schema.read_only);
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
control,
|
||||
setValue,
|
||||
reset,
|
||||
formState: { isDirty, errors }
|
||||
} = useForm<IUpdateLibraryItemDTO>({
|
||||
resolver: zodResolver(UpdateLibraryItemSchema),
|
||||
defaultValues: {
|
||||
id: controller.schema.id,
|
||||
item_type: LibraryItemType.RSFORM,
|
||||
title: controller.schema.title,
|
||||
alias: controller.schema.alias,
|
||||
comment: controller.schema.comment,
|
||||
visible: controller.schema.visible,
|
||||
read_only: controller.schema.read_only
|
||||
}
|
||||
});
|
||||
const visible = useWatch({ control, name: 'visible' });
|
||||
const readOnly = useWatch({ control, name: 'read_only' });
|
||||
|
||||
useEffect(() => {
|
||||
setIsModified(isDirty);
|
||||
}, [isDirty, controller.schema, setIsModified]);
|
||||
|
||||
function handleSelectVersion(version?: VersionID) {
|
||||
router.push(urls.schema(schema.id, version));
|
||||
router.push(urls.schema(controller.schema.id, version));
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (schema) {
|
||||
setTitle(schema.title);
|
||||
setAlias(schema.alias);
|
||||
setComment(schema.comment);
|
||||
setVisible(schema.visible);
|
||||
setReadOnly(schema.read_only);
|
||||
function onSubmit(data: IUpdateLibraryItemDTO) {
|
||||
updateSchema(data, () => reset({ ...data }));
|
||||
}
|
||||
}, [schema]);
|
||||
|
||||
useEffect(() => {
|
||||
setIsModified(
|
||||
schema.title !== title ||
|
||||
schema.alias !== alias ||
|
||||
schema.comment !== comment ||
|
||||
schema.visible !== visible ||
|
||||
schema.read_only !== readOnly
|
||||
);
|
||||
return () => setIsModified(false);
|
||||
}, [
|
||||
schema.title,
|
||||
schema.alias,
|
||||
schema.comment,
|
||||
schema.visible,
|
||||
schema.read_only,
|
||||
title,
|
||||
alias,
|
||||
comment,
|
||||
visible,
|
||||
readOnly,
|
||||
setIsModified
|
||||
]);
|
||||
|
||||
const handleSubmit = (event?: React.FormEvent<HTMLFormElement>) => {
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
const data: IUpdateLibraryItemDTO = {
|
||||
id: schema.id,
|
||||
item_type: LibraryItemType.RSFORM,
|
||||
title: title,
|
||||
alias: alias,
|
||||
comment: comment,
|
||||
visible: visible,
|
||||
read_only: readOnly
|
||||
};
|
||||
update(data);
|
||||
};
|
||||
|
||||
return (
|
||||
<form id={id} className={clsx('mt-1 min-w-[22rem] sm:w-[30rem]', 'flex flex-col pt-1')} onSubmit={handleSubmit}>
|
||||
<form
|
||||
id={id}
|
||||
className={clsx('mt-1 min-w-[22rem] sm:w-[30rem]', 'flex flex-col pt-1')}
|
||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||
>
|
||||
<TextInput
|
||||
id='schema_title'
|
||||
required
|
||||
{...register('title')}
|
||||
label='Полное название'
|
||||
className='mb-3'
|
||||
value={title}
|
||||
disabled={!controller.isContentEditable}
|
||||
onChange={event => setTitle(event.target.value)}
|
||||
error={errors.title}
|
||||
/>
|
||||
<div className='flex justify-between gap-3 mb-3'>
|
||||
<TextInput
|
||||
id='schema_alias'
|
||||
required
|
||||
{...register('alias')}
|
||||
label='Сокращение'
|
||||
className='w-[16rem]'
|
||||
disabled={!controller.isContentEditable}
|
||||
value={alias}
|
||||
onChange={event => setAlias(event.target.value)}
|
||||
error={errors.alias}
|
||||
/>
|
||||
<div className='flex flex-col'>
|
||||
<ToolbarVersioning blockReload={schema.oss.length > 0} />
|
||||
<ToolbarVersioning blockReload={controller.schema.oss.length > 0} />
|
||||
<ToolbarItemAccess
|
||||
visible={visible}
|
||||
toggleVisible={() => setVisible(prev => !prev)}
|
||||
toggleVisible={() => setValue('visible', !visible, { shouldDirty: true })}
|
||||
readOnly={readOnly}
|
||||
toggleReadOnly={() => setReadOnly(prev => !prev)}
|
||||
toggleReadOnly={() => setValue('read_only', !readOnly, { shouldDirty: true })}
|
||||
controller={controller}
|
||||
/>
|
||||
<Label text='Версия' className='mb-2 select-none' />
|
||||
<SelectVersion
|
||||
id='schema_version'
|
||||
className='select-none'
|
||||
value={schema.version} //
|
||||
items={schema.versions}
|
||||
value={controller.schema.version} //
|
||||
items={controller.schema.versions}
|
||||
onChange={handleSelectVersion}
|
||||
/>
|
||||
</div>
|
||||
|
@ -135,18 +114,18 @@ function FormRSForm({ id }: FormRSFormProps) {
|
|||
|
||||
<TextArea
|
||||
id='schema_comment'
|
||||
{...register('comment')}
|
||||
label='Описание'
|
||||
rows={3}
|
||||
value={comment}
|
||||
disabled={!controller.isContentEditable || isProcessing}
|
||||
onChange={event => setComment(event.target.value)}
|
||||
error={errors.comment}
|
||||
/>
|
||||
{controller.isContentEditable || isModified ? (
|
||||
{controller.isContentEditable || isDirty ? (
|
||||
<SubmitButton
|
||||
text='Сохранить изменения'
|
||||
className='self-center mt-4'
|
||||
loading={isProcessing}
|
||||
disabled={!isModified}
|
||||
disabled={!isDirty}
|
||||
icon={<IconSave size='1.25rem' />}
|
||||
/>
|
||||
) : null}
|
||||
|
|
|
@ -66,12 +66,6 @@ function FormSignup() {
|
|||
>
|
||||
<h1>
|
||||
<span>Новый пользователь</span>
|
||||
<Overlay id={globals.password_tooltip} position='top-[5.4rem] left-[3.5rem]'>
|
||||
<IconHelp size='1.25rem' className='icon-primary' />
|
||||
</Overlay>
|
||||
<Tooltip anchorSelect={`#${globals.password_tooltip}`} offset={6}>
|
||||
используйте уникальный пароль для каждого сайта
|
||||
</Tooltip>
|
||||
<Overlay id={globals.email_tooltip} position='top-[0.5rem] right-[1.75rem]'>
|
||||
<IconHelp size='1.25rem' className='icon-primary' />
|
||||
</Overlay>
|
||||
|
@ -120,7 +114,7 @@ function FormSignup() {
|
|||
required
|
||||
spellCheck={false}
|
||||
label='Электронная почта (email)'
|
||||
title='электронная почта в корректном формате, например: i.petrov@mycompany.ru.com'
|
||||
title='электронная почта в корректном формате'
|
||||
error={errors.email}
|
||||
/>
|
||||
<TextInput
|
||||
|
|
|
@ -110,7 +110,6 @@ export const globals = {
|
|||
tooltip: 'global_tooltip',
|
||||
value_tooltip: 'value_tooltip',
|
||||
constituenta_tooltip: 'cst_tooltip',
|
||||
password_tooltip: 'password_tooltip',
|
||||
email_tooltip: 'email_tooltip',
|
||||
main_scroll: 'main_scroll',
|
||||
library_item_editor: 'library_item_editor',
|
||||
|
|
Loading…
Reference in New Issue
Block a user