From c5bf72f8895f271bff26d0409e5ec02ac9d94f70 Mon Sep 17 00:00:00 2001 From: Ivan <8611739+IRBorisov@users.noreply.github.com> Date: Mon, 10 Feb 2025 13:29:28 +0300 Subject: [PATCH] F: Rework ChangeInputSchema dialog --- .../frontend/src/features/oss/backend/api.ts | 29 +++++++-- .../oss/backend/useUpdatePositions.tsx | 3 +- .../oss/dialogs/DlgChangeInputSchema.tsx | 63 +++++++++++-------- .../frontend/src/features/oss/models/oss.ts | 12 ---- .../src/features/oss/models/ossAPI.ts | 11 +--- .../oss/pages/OssPage/OssEditContext.tsx | 16 +---- .../features/rsform/components/PickSchema.tsx | 2 +- .../features/rsform/dialogs/DlgRenameCst.tsx | 6 +- 8 files changed, 71 insertions(+), 71 deletions(-) diff --git a/rsconcept/frontend/src/features/oss/backend/api.ts b/rsconcept/frontend/src/features/oss/backend/api.ts index 70e42c6c..35257f5e 100644 --- a/rsconcept/frontend/src/features/oss/backend/api.ts +++ b/rsconcept/frontend/src/features/oss/backend/api.ts @@ -1,4 +1,5 @@ import { queryOptions } from '@tanstack/react-query'; +import { z } from 'zod'; import { axiosDelete, axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport'; import { DELAYS } from '@/backend/configuration'; @@ -8,7 +9,6 @@ import { ICstSubstitute, ICstSubstituteEx, IOperation, - IOperationPosition, OperationID, OperationType } from '@/features/oss/models/oss'; @@ -79,12 +79,33 @@ export interface IInputCreatedResponse { oss: IOperationSchemaDTO; } +/** + * Represents {@link IOperation} position. + */ +export const OperationPositionSchema = z.object({ + id: z.number(), + position_x: z.number(), + position_y: z.number() +}); + +/** + * Represents {@link IOperation} position. + */ +export type IOperationPosition = z.infer; + /** * Represents {@link IOperation} data, used in setInput process. */ -export interface IInputUpdateDTO extends ITargetOperation { - input: LibraryItemID | null; -} +export const InputUpdateSchema = z.object({ + target: z.number(), + positions: z.array(OperationPositionSchema), + input: z.number().nullable() +}); + +/** + * Represents {@link IOperation} data, used in setInput process. + */ +export type IInputUpdateDTO = z.infer; /** * Represents {@link IOperation} data, used in update process. diff --git a/rsconcept/frontend/src/features/oss/backend/useUpdatePositions.tsx b/rsconcept/frontend/src/features/oss/backend/useUpdatePositions.tsx index 125c96b5..a850cd04 100644 --- a/rsconcept/frontend/src/features/oss/backend/useUpdatePositions.tsx +++ b/rsconcept/frontend/src/features/oss/backend/useUpdatePositions.tsx @@ -2,9 +2,8 @@ import { useMutation } from '@tanstack/react-query'; import { useUpdateTimestamp } from '@/features/library/backend/useUpdateTimestamp'; import { LibraryItemID } from '@/features/library/models/library'; -import { IOperationPosition } from '@/features/oss/models/oss'; -import { ossApi } from './api'; +import { IOperationPosition, ossApi } from './api'; export const useUpdatePositions = () => { const { updateTimestamp } = useUpdateTimestamp(); diff --git a/rsconcept/frontend/src/features/oss/dialogs/DlgChangeInputSchema.tsx b/rsconcept/frontend/src/features/oss/dialogs/DlgChangeInputSchema.tsx index 7b71aa98..fafc4498 100644 --- a/rsconcept/frontend/src/features/oss/dialogs/DlgChangeInputSchema.tsx +++ b/rsconcept/frontend/src/features/oss/dialogs/DlgChangeInputSchema.tsx @@ -1,44 +1,51 @@ 'use client'; +import { zodResolver } from '@hookform/resolvers/zod'; import clsx from 'clsx'; -import { useState } from 'react'; +import { Controller, useForm } from 'react-hook-form'; import { MiniButton } from '@/components/Control'; import { IconReset } from '@/components/Icons'; import { Label } from '@/components/Input'; import { ModalForm } from '@/components/Modal'; import { useLibrary } from '@/features/library/backend/useLibrary'; -import { ILibraryItem, LibraryItemID, LibraryItemType } from '@/features/library/models/library'; +import { ILibraryItem, LibraryItemType } from '@/features/library/models/library'; import PickSchema from '@/features/rsform/components/PickSchema'; import { useDialogsStore } from '@/stores/dialogs'; -import { IOperation, IOperationSchema, OperationID } from '../models/oss'; +import { IInputUpdateDTO, InputUpdateSchema, IOperationPosition } from '../backend/api'; +import { useInputUpdate } from '../backend/useInputUpdate'; +import { IOperation, IOperationSchema } from '../models/oss'; import { sortItemsForOSS } from '../models/ossAPI'; export interface DlgChangeInputSchemaProps { oss: IOperationSchema; target: IOperation; - onSubmit: (target: OperationID, newSchema: LibraryItemID | undefined) => void; + positions: IOperationPosition[]; } function DlgChangeInputSchema() { - const { oss, target, onSubmit } = useDialogsStore(state => state.props as DlgChangeInputSchemaProps); - const [selected, setSelected] = useState(target.result ?? undefined); + const { oss, target, positions } = useDialogsStore(state => state.props as DlgChangeInputSchemaProps); + const { inputUpdate } = useInputUpdate(); + + const { setValue, handleSubmit, control } = useForm({ + resolver: zodResolver(InputUpdateSchema), + defaultValues: { + target: target.id, + positions: positions, + input: target.result + } + }); + const { items } = useLibrary(); const sortedItems = sortItemsForOSS(oss, items); - const isValid = target.result !== selected; function baseFilter(item: ILibraryItem) { - return !oss.schemas.includes(item.id) || item.id === selected || item.id === target.result; + return !oss.schemas.includes(item.id) || item.id === target.result; } - function handleSelectLocation(newValue: LibraryItemID) { - setSelected(newValue); - } - - function handleSubmit() { - onSubmit(target.id, selected); - return true; + function onSubmit(data: IInputUpdateDTO) { + inputUpdate({ itemID: oss.id, data: data }); } return ( @@ -46,8 +53,7 @@ function DlgChangeInputSchema() { overflowVisible header='Выбор концептуальной схемы' submitText='Подтвердить выбор' - canSubmit={isValid} - onSubmit={handleSubmit} + onSubmit={event => void handleSubmit(onSubmit)(event)} className={clsx('w-[35rem]', 'pb-3 px-6 cc-column')} >
@@ -58,18 +64,23 @@ function DlgChangeInputSchema() { noHover noPadding icon={} - onClick={() => setSelected(undefined)} - disabled={selected == undefined} + onClick={() => setValue('input', null)} />
- ( + + )} /> ); diff --git a/rsconcept/frontend/src/features/oss/models/oss.ts b/rsconcept/frontend/src/features/oss/models/oss.ts index b57900c8..f6cefb82 100644 --- a/rsconcept/frontend/src/features/oss/models/oss.ts +++ b/rsconcept/frontend/src/features/oss/models/oss.ts @@ -43,18 +43,6 @@ export interface IOperation { arguments: OperationID[]; } -/** - * Represents {@link IOperation} position. - */ -export interface IOperationPosition extends Pick {} - -/** - * Represents all {@link IOperation} positions in {@link IOperationSchema}. - */ -export interface IPositions { - positions: IOperationPosition[]; -} - /** * Represents {@link IOperation} Argument. */ diff --git a/rsconcept/frontend/src/features/oss/models/ossAPI.ts b/rsconcept/frontend/src/features/oss/models/ossAPI.ts index 2fd28839..ddaeb534 100644 --- a/rsconcept/frontend/src/features/oss/models/ossAPI.ts +++ b/rsconcept/frontend/src/features/oss/models/ossAPI.ts @@ -16,15 +16,8 @@ import { describeSubstitutionError, information } from '@/utils/labels'; import { TextMatcher } from '@/utils/utils'; import { Graph } from '../../../models/Graph'; -import { - ICstSubstitute, - IOperation, - IOperationPosition, - IOperationSchema, - OperationID, - OperationType, - SubstitutionErrorType -} from './oss'; +import { IOperationPosition } from '../backend/api'; +import { ICstSubstitute, IOperation, IOperationSchema, OperationID, OperationType, SubstitutionErrorType } from './oss'; import { Position2D } from './ossLayout'; /** diff --git a/rsconcept/frontend/src/features/oss/pages/OssPage/OssEditContext.tsx b/rsconcept/frontend/src/features/oss/pages/OssPage/OssEditContext.tsx index 57e6561d..4cbfe463 100644 --- a/rsconcept/frontend/src/features/oss/pages/OssPage/OssEditContext.tsx +++ b/rsconcept/frontend/src/features/oss/pages/OssPage/OssEditContext.tsx @@ -15,14 +15,14 @@ import { useRoleStore } from '@/stores/role'; import { PARAMETER } from '@/utils/constants'; import { prompts } from '@/utils/labels'; -import { useInputUpdate } from '../../backend/useInputUpdate'; +import { IOperationPosition } from '../../backend/api'; import { useOperationCreate } from '../../backend/useOperationCreate'; import { useOperationDelete } from '../../backend/useOperationDelete'; import { useOperationUpdate } from '../../backend/useOperationUpdate'; import { useOssSuspense } from '../../backend/useOSS'; import { useRelocateConstituents } from '../../backend/useRelocateConstituents'; import { useUpdatePositions } from '../../backend/useUpdatePositions'; -import { IOperationPosition, IOperationSchema, OperationID, OperationType } from '../../models/oss'; +import { IOperationSchema, OperationID, OperationType } from '../../models/oss'; import { calculateInsertPosition } from '../../models/ossAPI'; export enum OssTabID { @@ -106,7 +106,6 @@ export const OssEditState = ({ itemID, children }: React.PropsWithChildren @@ -223,16 +222,7 @@ export const OssEditState = ({ itemID, children }: React.PropsWithChildren { - inputUpdate({ - itemID: schema.id, - data: { - target: target, - positions: positions, - input: newInput ?? null - } - }); - } + positions: positions }); } diff --git a/rsconcept/frontend/src/features/rsform/components/PickSchema.tsx b/rsconcept/frontend/src/features/rsform/components/PickSchema.tsx index bae4b858..0035a233 100644 --- a/rsconcept/frontend/src/features/rsform/components/PickSchema.tsx +++ b/rsconcept/frontend/src/features/rsform/components/PickSchema.tsx @@ -18,7 +18,7 @@ import SelectLocation from '../../library/components/SelectLocation'; interface PickSchemaProps extends CProps.Styling { id?: string; - value?: LibraryItemID; + value: LibraryItemID | null; onChange: (newValue: LibraryItemID) => void; initialFilter?: string; diff --git a/rsconcept/frontend/src/features/rsform/dialogs/DlgRenameCst.tsx b/rsconcept/frontend/src/features/rsform/dialogs/DlgRenameCst.tsx index bafc0ef0..22251714 100644 --- a/rsconcept/frontend/src/features/rsform/dialogs/DlgRenameCst.tsx +++ b/rsconcept/frontend/src/features/rsform/dialogs/DlgRenameCst.tsx @@ -34,9 +34,7 @@ function DlgRenameCst() { }); const alias = useWatch({ control, name: 'alias' }); const cst_type = useWatch({ control, name: 'cst_type' }); - - // TODO: validate in ZOD - const validated = alias !== target.alias && validateNewAlias(alias, cst_type, schema); + const isValid = alias !== target.alias && validateNewAlias(alias, cst_type, schema); function onSubmit(data: ICstRenameDTO) { cstRename({ itemID: schema.id, data: data }); @@ -52,7 +50,7 @@ function DlgRenameCst() { header='Переименование конституенты' submitText='Переименовать' submitInvalidTooltip='Введите незанятое имя, соответствующее типу' - canSubmit={validated} + canSubmit={isValid} onSubmit={event => void handleSubmit(onSubmit)(event)} className={clsx('w-[30rem]', 'py-6 pr-3 pl-6 flex gap-3 justify-center items-center ')} helpTopic={HelpTopic.CC_CONSTITUENTA}