mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 04:50:36 +03:00
F: Rework create operation dialog
Some checks are pending
Frontend CI / build (22.x) (push) Waiting to run
Some checks are pending
Frontend CI / build (22.x) (push) Waiting to run
This commit is contained in:
parent
c5b73612f3
commit
f31acfc817
|
@ -15,7 +15,7 @@ import { Label, TextArea, TextInput } from '@/components/Input';
|
|||
import { useAuthSuspense } from '@/features/auth/backend/useAuth';
|
||||
import { EXTEOR_TRS_FILE } from '@/utils/constants';
|
||||
|
||||
import { schemaCreateLibraryItem, ICreateLibraryItemDTO } from '../../backend/api';
|
||||
import { ICreateLibraryItemDTO, schemaCreateLibraryItem } from '../../backend/api';
|
||||
import { useCreateItem } from '../../backend/useCreateItem';
|
||||
import SelectAccessPolicy from '../../components/SelectAccessPolicy';
|
||||
import SelectItemType from '../../components/SelectItemType';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { queryOptions } from '@tanstack/react-query';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { axiosDelete, axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport';
|
||||
import { axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport';
|
||||
import { DELAYS } from '@/backend/configuration';
|
||||
import { ILibraryItem, ILibraryItemData, LibraryItemID } from '@/features/library/models/library';
|
||||
import {
|
||||
|
@ -46,20 +46,25 @@ export type IOperationPosition = z.infer<typeof schemaOperationPosition>;
|
|||
/**
|
||||
* Represents {@link IOperation} data, used in creation process.
|
||||
*/
|
||||
export interface IOperationCreateDTO {
|
||||
positions: IOperationPosition[];
|
||||
item_data: {
|
||||
alias: string;
|
||||
operation_type: OperationType;
|
||||
title: string;
|
||||
comment: string;
|
||||
position_x: number;
|
||||
position_y: number;
|
||||
result: LibraryItemID | null;
|
||||
};
|
||||
arguments: OperationID[] | undefined;
|
||||
create_schema: boolean;
|
||||
}
|
||||
export const schemaOperationCreate = z.object({
|
||||
positions: z.array(schemaOperationPosition),
|
||||
item_data: z.object({
|
||||
alias: z.string().nonempty(),
|
||||
operation_type: z.nativeEnum(OperationType),
|
||||
title: z.string(),
|
||||
comment: z.string(),
|
||||
position_x: z.number(),
|
||||
position_y: z.number(),
|
||||
result: z.number().nullable()
|
||||
}),
|
||||
arguments: z.array(z.number()),
|
||||
create_schema: z.boolean()
|
||||
});
|
||||
|
||||
/**
|
||||
* Represents {@link IOperation} data, used in creation process.
|
||||
*/
|
||||
export type IOperationCreateDTO = z.infer<typeof schemaOperationCreate>;
|
||||
|
||||
/**
|
||||
* Represents data response when creating {@link IOperation}.
|
||||
|
@ -183,7 +188,7 @@ export const ossApi = {
|
|||
}
|
||||
}),
|
||||
operationDelete: ({ itemID, data }: { itemID: LibraryItemID; data: IOperationDeleteDTO }) =>
|
||||
axiosDelete<IOperationDeleteDTO, IOperationSchemaDTO>({
|
||||
axiosPatch<IOperationDeleteDTO, IOperationSchemaDTO>({
|
||||
endpoint: `/api/oss/${itemID}/delete-operation`,
|
||||
request: {
|
||||
data: data,
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { DataCallback } from '@/backend/apiTransport';
|
||||
import { useUpdateTimestamp } from '@/features/library/backend/useUpdateTimestamp';
|
||||
import { LibraryItemID } from '@/features/library/models/library';
|
||||
|
||||
import { IOperationCreateDTO, IOperationDTO, ossApi } from './api';
|
||||
import { IOperationCreateDTO, ossApi } from './api';
|
||||
|
||||
export const useOperationCreate = () => {
|
||||
const client = useQueryClient();
|
||||
|
@ -12,18 +11,12 @@ export const useOperationCreate = () => {
|
|||
const mutation = useMutation({
|
||||
mutationKey: [ossApi.baseKey, 'operation-create'],
|
||||
mutationFn: ossApi.operationCreate,
|
||||
onSuccess: data => {
|
||||
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.oss.id }).queryKey, data.oss);
|
||||
updateTimestamp(data.oss.id);
|
||||
onSuccess: response => {
|
||||
client.setQueryData(ossApi.getOssQueryOptions({ itemID: response.oss.id }).queryKey, response.oss);
|
||||
updateTimestamp(response.oss.id);
|
||||
}
|
||||
});
|
||||
return {
|
||||
operationCreate: (
|
||||
data: {
|
||||
itemID: LibraryItemID; //
|
||||
data: IOperationCreateDTO;
|
||||
},
|
||||
onSuccess?: DataCallback<IOperationDTO>
|
||||
) => mutation.mutate(data, { onSuccess: response => onSuccess?.(response.new_operation) })
|
||||
operationCreate: (data: { itemID: LibraryItemID; data: IOperationCreateDTO }) => mutation.mutateAsync(data)
|
||||
};
|
||||
};
|
||||
|
|
|
@ -14,8 +14,7 @@ import SelectOperation from './SelectOperation';
|
|||
|
||||
interface PickMultiOperationProps extends CProps.Styling {
|
||||
value: OperationID[];
|
||||
onChange: React.Dispatch<React.SetStateAction<OperationID[]>>;
|
||||
|
||||
onChange: (newValue: OperationID[]) => void;
|
||||
items: IOperation[];
|
||||
rows?: number;
|
||||
}
|
||||
|
@ -28,13 +27,13 @@ function PickMultiOperation({ rows, items, value, onChange, className, ...restPr
|
|||
const [lastSelected, setLastSelected] = useState<IOperation | undefined>(undefined);
|
||||
|
||||
function handleDelete(operation: OperationID) {
|
||||
onChange(prev => prev.filter(item => item !== operation));
|
||||
onChange(value.filter(item => item !== operation));
|
||||
}
|
||||
|
||||
function handleSelect(operation?: IOperation) {
|
||||
if (operation) {
|
||||
setLastSelected(operation);
|
||||
onChange(prev => [...prev, operation.id]);
|
||||
onChange([...value, operation.id]);
|
||||
setTimeout(() => setLastSelected(undefined), 1000);
|
||||
}
|
||||
}
|
||||
|
@ -42,24 +41,20 @@ function PickMultiOperation({ rows, items, value, onChange, className, ...restPr
|
|||
function handleMoveUp(operation: OperationID) {
|
||||
const index = value.indexOf(operation);
|
||||
if (index > 0) {
|
||||
onChange(prev => {
|
||||
const newSelected = [...prev];
|
||||
newSelected[index] = newSelected[index - 1];
|
||||
newSelected[index - 1] = operation;
|
||||
return newSelected;
|
||||
});
|
||||
const newSelected = [...value];
|
||||
newSelected[index] = newSelected[index - 1];
|
||||
newSelected[index - 1] = operation;
|
||||
onChange(newSelected);
|
||||
}
|
||||
}
|
||||
|
||||
function handleMoveDown(operation: OperationID) {
|
||||
const index = value.indexOf(operation);
|
||||
if (index < value.length - 1) {
|
||||
onChange(prev => {
|
||||
const newSelected = [...prev];
|
||||
newSelected[index] = newSelected[index + 1];
|
||||
newSelected[index + 1] = operation;
|
||||
return newSelected;
|
||||
});
|
||||
const newSelected = [...value];
|
||||
newSelected[index] = newSelected[index + 1];
|
||||
newSelected[index + 1] = operation;
|
||||
onChange(newSelected);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,25 +1,30 @@
|
|||
'use client';
|
||||
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import clsx from 'clsx';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { FormProvider, useForm, useWatch } from 'react-hook-form';
|
||||
|
||||
import { ModalForm } from '@/components/Modal';
|
||||
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/Tabs';
|
||||
import { HelpTopic } from '@/features/help/models/helpTopic';
|
||||
import { useLibrary } from '@/features/library/backend/useLibrary';
|
||||
import { LibraryItemID } from '@/features/library/models/library';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { describeOperationType, labelOperationType } from '@/utils/labels';
|
||||
|
||||
import { IOperationCreateDTO } from '../../backend/api';
|
||||
import { IOperationCreateDTO, IOperationPosition, schemaOperationCreate } from '../../backend/api';
|
||||
import { useOperationCreate } from '../../backend/useOperationCreate';
|
||||
import { IOperationSchema, OperationID, OperationType } from '../../models/oss';
|
||||
import { calculateInsertPosition } from '../../models/ossAPI';
|
||||
import TabInputOperation from './TabInputOperation';
|
||||
import TabSynthesisOperation from './TabSynthesisOperation';
|
||||
|
||||
export interface DlgCreateOperationProps {
|
||||
oss: IOperationSchema;
|
||||
onCreate: (data: IOperationCreateDTO) => void;
|
||||
positions: IOperationPosition[];
|
||||
initialInputs: OperationID[];
|
||||
defaultX: number;
|
||||
defaultY: number;
|
||||
onCreate?: (newID: OperationID) => void;
|
||||
}
|
||||
|
||||
export enum TabID {
|
||||
|
@ -28,70 +33,57 @@ export enum TabID {
|
|||
}
|
||||
|
||||
function DlgCreateOperation() {
|
||||
const { items: libraryItems } = useLibrary();
|
||||
const { operationCreate } = useOperationCreate();
|
||||
|
||||
const { oss, onCreate, initialInputs } = useDialogsStore(state => state.props as DlgCreateOperationProps);
|
||||
const [activeTab, setActiveTab] = useState(initialInputs.length > 0 ? TabID.SYNTHESIS : TabID.INPUT);
|
||||
const { oss, positions, initialInputs, onCreate, defaultX, defaultY } = useDialogsStore(
|
||||
state => state.props as DlgCreateOperationProps
|
||||
);
|
||||
|
||||
const [alias, setAlias] = useState('');
|
||||
const [title, setTitle] = useState('');
|
||||
const [comment, setComment] = useState('');
|
||||
const [inputs, setInputs] = useState<OperationID[]>(initialInputs);
|
||||
const [attachedID, setAttachedID] = useState<LibraryItemID | undefined>(undefined);
|
||||
const [createSchema, setCreateSchema] = useState(false);
|
||||
|
||||
const isValid = (() => {
|
||||
if (alias === '') {
|
||||
return false;
|
||||
}
|
||||
if (activeTab === TabID.SYNTHESIS && inputs.length === 0) {
|
||||
return false;
|
||||
}
|
||||
if (activeTab === TabID.INPUT && !attachedID) {
|
||||
if (oss.items.some(operation => operation.alias === alias)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
})();
|
||||
|
||||
useEffect(() => {
|
||||
if (attachedID) {
|
||||
const schema = libraryItems.find(value => value.id === attachedID);
|
||||
if (schema) {
|
||||
setAlias(schema.alias);
|
||||
setTitle(schema.title);
|
||||
setComment(schema.comment);
|
||||
}
|
||||
}
|
||||
}, [attachedID, libraryItems]);
|
||||
|
||||
const handleSubmit = () => {
|
||||
onCreate({
|
||||
const methods = useForm<IOperationCreateDTO>({
|
||||
resolver: zodResolver(schemaOperationCreate),
|
||||
defaultValues: {
|
||||
item_data: {
|
||||
position_x: 0,
|
||||
position_y: 0,
|
||||
alias: alias,
|
||||
title: title,
|
||||
comment: comment,
|
||||
operation_type: activeTab === TabID.INPUT ? OperationType.INPUT : OperationType.SYNTHESIS,
|
||||
result: activeTab === TabID.INPUT ? attachedID ?? null : null
|
||||
operation_type: initialInputs.length === 0 ? OperationType.INPUT : OperationType.SYNTHESIS,
|
||||
result: null,
|
||||
position_x: defaultX,
|
||||
position_y: defaultY,
|
||||
alias: '',
|
||||
title: '',
|
||||
comment: ''
|
||||
},
|
||||
positions: [],
|
||||
arguments: activeTab === TabID.INPUT ? undefined : inputs.length > 0 ? inputs : undefined,
|
||||
create_schema: createSchema
|
||||
arguments: initialInputs,
|
||||
create_schema: false,
|
||||
positions: positions
|
||||
},
|
||||
mode: 'onChange'
|
||||
});
|
||||
const alias = useWatch({ control: methods.control, name: 'item_data.alias' });
|
||||
const [activeTab, setActiveTab] = useState(initialInputs.length === 0 ? TabID.INPUT : TabID.SYNTHESIS);
|
||||
const isValid = !!alias && !oss.items.some(operation => operation.alias === alias);
|
||||
|
||||
function onSubmit(data: IOperationCreateDTO) {
|
||||
const target = calculateInsertPosition(oss, data.item_data.operation_type, data.arguments, positions, {
|
||||
x: defaultX,
|
||||
y: defaultY
|
||||
});
|
||||
return true;
|
||||
};
|
||||
data.item_data.position_x = target.x;
|
||||
data.item_data.position_y = target.y;
|
||||
operationCreate({ itemID: oss.id, data: data })
|
||||
.then(response => onCreate?.(response.new_operation.id))
|
||||
.catch(console.error);
|
||||
}
|
||||
|
||||
function handleSelectTab(newTab: TabID, last: TabID) {
|
||||
if (last === newTab) {
|
||||
return;
|
||||
}
|
||||
if (newTab === TabID.INPUT) {
|
||||
setAttachedID(undefined);
|
||||
methods.setValue('item_data.operation_type', OperationType.INPUT);
|
||||
methods.setValue('item_data.result', null);
|
||||
methods.setValue('arguments', []);
|
||||
} else {
|
||||
setInputs(initialInputs);
|
||||
methods.setValue('item_data.operation_type', OperationType.SYNTHESIS);
|
||||
methods.setValue('arguments', initialInputs);
|
||||
}
|
||||
setActiveTab(newTab);
|
||||
}
|
||||
|
@ -101,7 +93,7 @@ function DlgCreateOperation() {
|
|||
header='Создание операции'
|
||||
submitText='Создать'
|
||||
canSubmit={isValid}
|
||||
onSubmit={handleSubmit}
|
||||
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
|
||||
className='w-[40rem] px-6 h-[32rem]'
|
||||
helpTopic={HelpTopic.CC_OSS}
|
||||
>
|
||||
|
@ -123,36 +115,15 @@ function DlgCreateOperation() {
|
|||
label={labelOperationType(OperationType.SYNTHESIS)}
|
||||
/>
|
||||
</TabList>
|
||||
<FormProvider {...methods}>
|
||||
<TabPanel>
|
||||
<TabInputOperation oss={oss} />
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel>
|
||||
<TabInputOperation
|
||||
oss={oss}
|
||||
alias={alias}
|
||||
onChangeAlias={setAlias}
|
||||
comment={comment}
|
||||
onChangeComment={setComment}
|
||||
title={title}
|
||||
onChangeTitle={setTitle}
|
||||
attachedID={attachedID}
|
||||
onChangeAttachedID={setAttachedID}
|
||||
createSchema={createSchema}
|
||||
onChangeCreateSchema={setCreateSchema}
|
||||
/>
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel>
|
||||
<TabSynthesisOperation
|
||||
oss={oss}
|
||||
alias={alias}
|
||||
onChangeAlias={setAlias}
|
||||
comment={comment}
|
||||
onChangeComment={setComment}
|
||||
title={title}
|
||||
onChangeTitle={setTitle}
|
||||
inputs={inputs}
|
||||
setInputs={setInputs}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
<TabSynthesisOperation oss={oss} />
|
||||
</TabPanel>
|
||||
</FormProvider>
|
||||
</Tabs>
|
||||
</ModalForm>
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import { Controller, useFormContext, useWatch } from 'react-hook-form';
|
||||
|
||||
import { MiniButton } from '@/components/Control';
|
||||
import { IconReset } from '@/components/Icons';
|
||||
|
@ -11,73 +11,70 @@ import { IOperationSchema } from '@/features/oss/models/oss';
|
|||
import { sortItemsForOSS } from '@/features/oss/models/ossAPI';
|
||||
import PickSchema from '@/features/rsform/components/PickSchema';
|
||||
|
||||
import { IOperationCreateDTO } from '../../backend/api';
|
||||
|
||||
interface TabInputOperationProps {
|
||||
oss: IOperationSchema;
|
||||
alias: string;
|
||||
onChangeAlias: (newValue: string) => void;
|
||||
title: string;
|
||||
onChangeTitle: (newValue: string) => void;
|
||||
comment: string;
|
||||
onChangeComment: (newValue: string) => void;
|
||||
attachedID: LibraryItemID | undefined;
|
||||
onChangeAttachedID: (newValue: LibraryItemID | undefined) => void;
|
||||
createSchema: boolean;
|
||||
onChangeCreateSchema: (newValue: boolean) => void;
|
||||
}
|
||||
|
||||
function TabInputOperation({
|
||||
oss,
|
||||
alias,
|
||||
onChangeAlias,
|
||||
title,
|
||||
onChangeTitle,
|
||||
comment,
|
||||
onChangeComment,
|
||||
attachedID,
|
||||
onChangeAttachedID,
|
||||
createSchema,
|
||||
onChangeCreateSchema
|
||||
}: TabInputOperationProps) {
|
||||
function TabInputOperation({ oss }: TabInputOperationProps) {
|
||||
const { items: libraryItems } = useLibrary();
|
||||
const sortedItems = sortItemsForOSS(oss, libraryItems);
|
||||
|
||||
const {
|
||||
register,
|
||||
control,
|
||||
setValue,
|
||||
formState: { errors }
|
||||
} = useFormContext<IOperationCreateDTO>();
|
||||
const createSchema = useWatch({ control, name: 'create_schema' });
|
||||
|
||||
function baseFilter(item: ILibraryItem) {
|
||||
return !oss.schemas.includes(item.id);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (createSchema) {
|
||||
onChangeAttachedID(undefined);
|
||||
function handleChangeCreateSchema(value: boolean) {
|
||||
if (value) {
|
||||
setValue('item_data.result', null);
|
||||
}
|
||||
}, [createSchema, onChangeAttachedID]);
|
||||
setValue('create_schema', value);
|
||||
}
|
||||
|
||||
function handleSetInput(value: LibraryItemID) {
|
||||
const schema = libraryItems.find(item => item.id === value);
|
||||
if (!schema) {
|
||||
return;
|
||||
}
|
||||
setValue('item_data.result', value);
|
||||
setValue('create_schema', false);
|
||||
setValue('item_data.alias', schema.alias);
|
||||
setValue('item_data.title', schema.title);
|
||||
setValue('item_data.comment', schema.comment);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='cc-fade-in cc-column'>
|
||||
<TextInput
|
||||
id='operation_title'
|
||||
id='operation_title' //
|
||||
label='Полное название'
|
||||
value={title}
|
||||
onChange={event => onChangeTitle(event.target.value)}
|
||||
disabled={attachedID !== undefined}
|
||||
{...register('item_data.title')}
|
||||
error={errors.item_data?.title}
|
||||
/>
|
||||
<div className='flex gap-6'>
|
||||
<TextInput
|
||||
id='operation_alias'
|
||||
id='operation_alias' //
|
||||
label='Сокращение'
|
||||
className='w-[16rem]'
|
||||
value={alias}
|
||||
onChange={event => onChangeAlias(event.target.value)}
|
||||
disabled={attachedID !== undefined}
|
||||
{...register('item_data.alias')}
|
||||
error={errors.item_data?.alias}
|
||||
/>
|
||||
|
||||
<TextArea
|
||||
id='operation_comment'
|
||||
id='operation_comment' //
|
||||
label='Описание'
|
||||
noResize
|
||||
rows={3}
|
||||
value={comment}
|
||||
onChange={event => onChangeComment(event.target.value)}
|
||||
disabled={attachedID !== undefined}
|
||||
{...register('item_data.comment')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
@ -89,25 +86,29 @@ function TabInputOperation({
|
|||
noHover
|
||||
noPadding
|
||||
icon={<IconReset size='1.25rem' className='icon-primary' />}
|
||||
onClick={() => onChangeAttachedID(undefined)}
|
||||
disabled={attachedID == undefined}
|
||||
onClick={() => setValue('item_data.result', null)}
|
||||
/>
|
||||
</div>
|
||||
<Checkbox
|
||||
value={createSchema}
|
||||
onChange={onChangeCreateSchema}
|
||||
value={createSchema} //
|
||||
onChange={handleChangeCreateSchema}
|
||||
label='Создать новую схему'
|
||||
titleHtml='Создать пустую схему для загрузки'
|
||||
/>
|
||||
</div>
|
||||
{!createSchema ? (
|
||||
<PickSchema
|
||||
items={sortedItems}
|
||||
value={attachedID ?? null}
|
||||
itemType={LibraryItemType.RSFORM}
|
||||
onChange={onChangeAttachedID}
|
||||
rows={8}
|
||||
baseFilter={baseFilter}
|
||||
<Controller
|
||||
control={control}
|
||||
name='item_data.result'
|
||||
render={({ field }) => (
|
||||
<PickSchema
|
||||
items={sortedItems}
|
||||
value={field.value}
|
||||
itemType={LibraryItemType.RSFORM}
|
||||
onChange={handleSetInput}
|
||||
rows={8}
|
||||
baseFilter={baseFilter}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
|
@ -1,47 +1,39 @@
|
|||
import { Controller, useFormContext, useWatch } from 'react-hook-form';
|
||||
|
||||
import { FlexColumn } from '@/components/Container';
|
||||
import { Label, TextArea, TextInput } from '@/components/Input';
|
||||
|
||||
import { IOperationCreateDTO } from '../../backend/api';
|
||||
import PickMultiOperation from '../../components/PickMultiOperation';
|
||||
import { IOperationSchema, OperationID } from '../../models/oss';
|
||||
import { IOperationSchema } from '../../models/oss';
|
||||
|
||||
interface TabSynthesisOperationProps {
|
||||
oss: IOperationSchema;
|
||||
alias: string;
|
||||
onChangeAlias: (newValue: string) => void;
|
||||
title: string;
|
||||
onChangeTitle: (newValue: string) => void;
|
||||
comment: string;
|
||||
onChangeComment: (newValue: string) => void;
|
||||
inputs: OperationID[];
|
||||
setInputs: React.Dispatch<React.SetStateAction<OperationID[]>>;
|
||||
}
|
||||
|
||||
function TabSynthesisOperation({
|
||||
oss,
|
||||
alias,
|
||||
onChangeAlias,
|
||||
title,
|
||||
onChangeTitle,
|
||||
comment,
|
||||
onChangeComment,
|
||||
inputs,
|
||||
setInputs
|
||||
}: TabSynthesisOperationProps) {
|
||||
function TabSynthesisOperation({ oss }: TabSynthesisOperationProps) {
|
||||
const {
|
||||
register,
|
||||
control,
|
||||
formState: { errors }
|
||||
} = useFormContext<IOperationCreateDTO>();
|
||||
const inputs = useWatch({ control, name: 'arguments' });
|
||||
|
||||
return (
|
||||
<div className='cc-fade-in cc-column'>
|
||||
<TextInput
|
||||
id='operation_title'
|
||||
label='Полное название'
|
||||
value={title}
|
||||
onChange={event => onChangeTitle(event.target.value)}
|
||||
{...register('item_data.title')}
|
||||
error={errors.item_data?.title}
|
||||
/>
|
||||
<div className='flex gap-6'>
|
||||
<TextInput
|
||||
id='operation_alias'
|
||||
label='Сокращение'
|
||||
className='w-[16rem]'
|
||||
value={alias}
|
||||
onChange={event => onChangeAlias(event.target.value)}
|
||||
{...register('item_data.alias')}
|
||||
error={errors.item_data?.alias}
|
||||
/>
|
||||
|
||||
<TextArea
|
||||
|
@ -49,14 +41,21 @@ function TabSynthesisOperation({
|
|||
label='Описание'
|
||||
noResize
|
||||
rows={3}
|
||||
value={comment}
|
||||
onChange={event => onChangeComment(event.target.value)}
|
||||
{...register('item_data.comment')}
|
||||
error={errors.item_data?.comment}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<FlexColumn>
|
||||
<Label text={`Выбор аргументов: [ ${inputs.length} ]`} />
|
||||
<PickMultiOperation items={oss.items} value={inputs} onChange={setInputs} rows={6} />
|
||||
<Controller
|
||||
name='arguments'
|
||||
control={control}
|
||||
defaultValue={[]}
|
||||
render={({ field }) => (
|
||||
<PickMultiOperation items={oss.items} value={field.value} onChange={field.onChange} rows={6} />
|
||||
)}
|
||||
/>
|
||||
</FlexColumn>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -56,8 +56,6 @@ function DlgRelocateConstituents() {
|
|||
libraryItems.find(item => item.id === initialTarget?.result)
|
||||
);
|
||||
|
||||
console.log(isValid);
|
||||
|
||||
const operation = oss.items.find(item => item.result === source?.id);
|
||||
const sourceSchemas = libraryItems.filter(item => oss.schemas.includes(item.id));
|
||||
const destinationSchemas = (() => {
|
||||
|
|
|
@ -488,7 +488,7 @@ export function calculateInsertPosition(
|
|||
return result;
|
||||
}
|
||||
|
||||
if (operationType === OperationType.INPUT) {
|
||||
if (operationType === OperationType.INPUT || argumentsOps.length === 0) {
|
||||
let inputsNodes = positions.filter(pos =>
|
||||
oss.items.find(operation => operation.operation_type === OperationType.INPUT && operation.id === pos.id)
|
||||
);
|
||||
|
|
|
@ -143,7 +143,7 @@ function OssFlow() {
|
|||
defaultY: target.y,
|
||||
inputs: inputs,
|
||||
positions: positions,
|
||||
callback: () => flow.fitView({ duration: PARAMETER.zoomDuration })
|
||||
callback: () => setTimeout(() => flow.fitView({ duration: PARAMETER.zoomDuration }), PARAMETER.refreshTimeout)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -12,15 +12,12 @@ import { UserRole } from '@/features/users/models/user';
|
|||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { usePreferencesStore } from '@/stores/preferences';
|
||||
import { useRoleStore } from '@/stores/role';
|
||||
import { PARAMETER } from '@/utils/constants';
|
||||
import { prompts } from '@/utils/labels';
|
||||
|
||||
import { IOperationPosition } from '../../backend/api';
|
||||
import { useOperationCreate } from '../../backend/useOperationCreate';
|
||||
import { useOperationUpdate } from '../../backend/useOperationUpdate';
|
||||
import { useOssSuspense } from '../../backend/useOSS';
|
||||
import { IOperationSchema, OperationID, OperationType } from '../../models/oss';
|
||||
import { calculateInsertPosition } from '../../models/ossAPI';
|
||||
|
||||
export enum OssTabID {
|
||||
CARD = 0,
|
||||
|
@ -98,7 +95,6 @@ export const OssEditState = ({ itemID, children }: React.PropsWithChildren<OssEd
|
|||
const showCreateOperation = useDialogsStore(state => state.showCreateOperation);
|
||||
|
||||
const { deleteItem } = useDeleteItem();
|
||||
const { operationCreate } = useOperationCreate();
|
||||
const { operationUpdate } = useOperationUpdate();
|
||||
|
||||
useEffect(
|
||||
|
@ -143,21 +139,11 @@ export const OssEditState = ({ itemID, children }: React.PropsWithChildren<OssEd
|
|||
function promptCreateOperation({ defaultX, defaultY, inputs, positions, callback }: ICreateOperationPrompt) {
|
||||
showCreateOperation({
|
||||
oss: schema,
|
||||
onCreate: data => {
|
||||
const target = calculateInsertPosition(schema, data.item_data.operation_type, data.arguments ?? [], positions, {
|
||||
x: defaultX,
|
||||
y: defaultY
|
||||
});
|
||||
data.positions = positions;
|
||||
data.item_data.position_x = target.x;
|
||||
data.item_data.position_y = target.y;
|
||||
operationCreate({ itemID: schema.id, data }, operation => {
|
||||
if (callback) {
|
||||
setTimeout(() => callback(operation.id), PARAMETER.refreshTimeout);
|
||||
}
|
||||
});
|
||||
},
|
||||
initialInputs: inputs
|
||||
defaultX: defaultX,
|
||||
defaultY: defaultY,
|
||||
positions: positions,
|
||||
initialInputs: inputs,
|
||||
onCreate: callback
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import { VisibilityIcon } from '@/components/DomainIcons';
|
|||
import { Checkbox, Label, TextArea, TextInput } from '@/components/Input';
|
||||
import { ModalForm } from '@/components/Modal';
|
||||
import { useAuthSuspense } from '@/features/auth/backend/useAuth';
|
||||
import { schemaCloneLibraryItem, ICloneLibraryItemDTO } from '@/features/library/backend/api';
|
||||
import { ICloneLibraryItemDTO, schemaCloneLibraryItem } from '@/features/library/backend/api';
|
||||
import { useCloneItem } from '@/features/library/backend/useCloneItem';
|
||||
import SelectAccessPolicy from '@/features/library/components/SelectAccessPolicy';
|
||||
import SelectLocationContext from '@/features/library/components/SelectLocationContext';
|
||||
|
|
Loading…
Reference in New Issue
Block a user