From 8d611d5471fde1bde6c53f072dae2f1566a6871b Mon Sep 17 00:00:00 2001 From: Ivan <8611739+IRBorisov@users.noreply.github.com> Date: Sat, 8 Feb 2025 19:07:43 +0300 Subject: [PATCH] F: rework CloneLibraryItem dialog --- rsconcept/frontend/src/backend/library/api.ts | 28 ++- .../src/dialogs/DlgCloneLibraryItem.tsx | 170 +++++++++++------- .../pages/CreateItemPage/FormCreateItem.tsx | 5 +- 3 files changed, 124 insertions(+), 79 deletions(-) diff --git a/rsconcept/frontend/src/backend/library/api.ts b/rsconcept/frontend/src/backend/library/api.ts index 4e9e5623..119ffed1 100644 --- a/rsconcept/frontend/src/backend/library/api.ts +++ b/rsconcept/frontend/src/backend/library/api.ts @@ -7,7 +7,6 @@ import { ossApi } from '@/backend/oss/api'; import { IRSFormDTO, rsformsApi } from '@/backend/rsform/api'; import { AccessPolicy, ILibraryItem, IVersionInfo, LibraryItemID, LibraryItemType, VersionID } from '@/models/library'; import { validateLocation } from '@/models/libraryAPI'; -import { ConstituentaID } from '@/models/rsform'; import { UserID } from '@/models/user'; import { errors, information } from '@/utils/labels'; @@ -22,9 +21,24 @@ export interface IRenameLocationDTO { /** * Represents data, used for cloning {@link IRSForm}. */ -export interface ICloneLibraryItemDTO extends Omit { - items?: ConstituentaID[]; -} +export const CloneLibraryItemSchema = 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(), + location: z.string().refine(data => validateLocation(data), { message: errors.invalidLocation }), + access_policy: z.nativeEnum(AccessPolicy), + + items: z.array(z.number()).optional() +}); + +/** + * Represents data, used for cloning {@link IRSForm}. + */ +export type ICloneLibraryItemDTO = z.infer; /** * Represents data, used for creating {@link IRSForm}. @@ -37,16 +51,12 @@ export const CreateLibraryItemSchema = z comment: z.string(), visible: z.boolean(), read_only: z.boolean(), - location: z.string(), + location: z.string().refine(data => validateLocation(data), { message: errors.invalidLocation }), access_policy: z.nativeEnum(AccessPolicy), file: z.instanceof(File).optional(), fileName: z.string().optional() }) - .refine(data => validateLocation(data.location), { - path: ['location'], - message: errors.invalidLocation - }) .refine(data => !!data.file || !!data.title, { path: ['title'], message: errors.requiredField diff --git a/rsconcept/frontend/src/dialogs/DlgCloneLibraryItem.tsx b/rsconcept/frontend/src/dialogs/DlgCloneLibraryItem.tsx index dcd15d8b..46319326 100644 --- a/rsconcept/frontend/src/dialogs/DlgCloneLibraryItem.tsx +++ b/rsconcept/frontend/src/dialogs/DlgCloneLibraryItem.tsx @@ -1,12 +1,13 @@ 'use client'; +import { zodResolver } from '@hookform/resolvers/zod'; import clsx from 'clsx'; -import { useState } from 'react'; +import { Controller, useForm } from 'react-hook-form'; import { useConceptNavigation } from '@/app/Navigation/NavigationContext'; import { urls } from '@/app/urls'; import { useAuthSuspense } from '@/backend/auth/useAuth'; -import { ICloneLibraryItemDTO } from '@/backend/library/api'; +import { CloneLibraryItemSchema, ICloneLibraryItemDTO } from '@/backend/library/api'; import { useCloneItem } from '@/backend/library/useCloneItem'; import { VisibilityIcon } from '@/components/DomainIcons'; import SelectAccessPolicy from '@/components/select/SelectAccessPolicy'; @@ -16,7 +17,7 @@ import { MiniButton } from '@/components/ui/Control'; import { Checkbox, Label, TextArea, TextInput } from '@/components/ui/Input'; import { ModalForm } from '@/components/ui/Modal'; import { AccessPolicy, ILibraryItem, LocationHead } from '@/models/library'; -import { cloneTitle, combineLocation, validateLocation } from '@/models/libraryAPI'; +import { cloneTitle, combineLocation } from '@/models/libraryAPI'; import { ConstituentaID } from '@/models/rsform'; import { useDialogsStore } from '@/stores/dialogs'; @@ -33,82 +34,81 @@ function DlgCloneLibraryItem() { ); const router = useConceptNavigation(); const { user } = useAuthSuspense(); - - const [title, setTitle] = useState(cloneTitle(base)); - const [alias, setAlias] = useState(base.alias); - const [comment, setComment] = useState(base.comment); - const [visible, setVisible] = useState(true); - const [policy, setPolicy] = useState(AccessPolicy.PUBLIC); - - const [onlySelected, setOnlySelected] = useState(false); - - const [head, setHead] = useState(initialLocation.substring(0, 2) as LocationHead); - const [body, setBody] = useState(initialLocation.substring(3)); - const location = combineLocation(head, body); - const { cloneItem } = useCloneItem(); - const canSubmit = title !== '' && alias !== '' && validateLocation(location); - - function handleSelectLocation(newValue: string) { - setHead(newValue.substring(0, 2) as LocationHead); - setBody(newValue.length > 3 ? newValue.substring(3) : ''); - } - - function handleSubmit() { - const data: ICloneLibraryItemDTO = { + const { + register, + handleSubmit, + control, + formState: { errors, isValid } + } = useForm({ + resolver: zodResolver(CloneLibraryItemSchema), + defaultValues: { id: base.id, item_type: base.item_type, - title: title, - alias: alias, - comment: comment, + title: cloneTitle(base), + alias: base.alias, + comment: base.comment, + visible: true, read_only: false, - visible: visible, - access_policy: policy, - location: location - }; - if (onlySelected) { - data.items = selected; - } + access_policy: AccessPolicy.PUBLIC, + location: initialLocation, + items: undefined + }, + mode: 'onChange', + reValidateMode: 'onChange' + }); + + function onSubmit(data: ICloneLibraryItemDTO) { cloneItem(data, newSchema => router.push(urls.schema(newSchema.id))); - return true; } return ( void handleSubmit(onSubmit)(event)} className={clsx('px-6 py-2', 'cc-column', 'max-h-full w-[30rem]')} > setTitle(event.target.value)} + {...register('title')} + error={errors.title} />
setAlias(event.target.value)} + className='w-[16rem]' + {...register('alias')} + error={errors.alias} />
@@ -117,26 +117,60 @@ function DlgCloneLibraryItem() {
- -