R: Improve dialogs persistence when data is invalidated
Some checks are pending
Frontend CI / build (22.x) (push) Waiting to run
Frontend CI / notify-failure (push) Blocked by required conditions

This commit is contained in:
Ivan 2025-08-13 22:08:03 +03:00
parent 2ecdbd1719
commit 9420729a96
20 changed files with 220 additions and 142 deletions

View File

@ -10,18 +10,20 @@ import { ModalForm } from '@/components/modal';
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
import { useDialogsStore } from '@/stores/dialogs';
import { type ICreateBlockDTO, schemaCreateBlock } from '../../backend/types';
import { type ICreateBlockDTO, type IOssLayout, schemaCreateBlock } from '../../backend/types';
import { useCreateBlock } from '../../backend/use-create-block';
import { type IOssItem, NodeType } from '../../models/oss';
import { type LayoutManager } from '../../models/oss-layout-api';
import { useOssSuspense } from '../../backend/use-oss';
import { LayoutManager } from '../../models/oss-layout-api';
import { BLOCK_NODE_MIN_HEIGHT, BLOCK_NODE_MIN_WIDTH } from '../../pages/oss-page/editor-oss-graph/graph/block-node';
import { TabBlockCard } from './tab-block-card';
import { TabBlockChildren } from './tab-block-children';
export interface DlgCreateBlockProps {
manager: LayoutManager;
initialChildren: IOssItem[];
ossID: number;
layout: IOssLayout;
childrenBlocks: number[];
childrenOperations: number[];
initialParent: number | null;
defaultX: number;
defaultY: number;
@ -37,9 +39,19 @@ export type TabID = (typeof TabID)[keyof typeof TabID];
export function DlgCreateBlock() {
const { createBlock } = useCreateBlock();
const { manager, initialChildren, initialParent, onCreate, defaultX, defaultY } = useDialogsStore(
state => state.props as DlgCreateBlockProps
);
const {
ossID, //
layout,
childrenBlocks,
childrenOperations,
initialParent,
onCreate,
defaultX,
defaultY
} = useDialogsStore(state => state.props as DlgCreateBlockProps);
const { schema } = useOssSuspense({ itemID: ossID });
const manager = new LayoutManager(schema, layout);
const methods = useForm<ICreateBlockDTO>({
resolver: zodResolver(schemaCreateBlock),
@ -55,8 +67,8 @@ export function DlgCreateBlock() {
width: BLOCK_NODE_MIN_WIDTH,
height: BLOCK_NODE_MIN_HEIGHT
},
children_blocks: initialChildren.filter(item => item.nodeType === NodeType.BLOCK).map(item => item.id),
children_operations: initialChildren.filter(item => item.nodeType === NodeType.OPERATION).map(item => item.id),
children_blocks: childrenBlocks,
children_operations: childrenOperations,
layout: manager.layout
},
mode: 'onChange'
@ -93,11 +105,11 @@ export function DlgCreateBlock() {
<FormProvider {...methods}>
<TabPanel>
<TabBlockCard />
<TabBlockCard oss={schema} />
</TabPanel>
<TabPanel>
<TabBlockChildren />
<TabBlockChildren oss={schema} />
</TabPanel>
</FormProvider>
</Tabs>

View File

@ -3,17 +3,17 @@
import { Controller, useFormContext, useWatch } from 'react-hook-form';
import { TextArea, TextInput } from '@/components/input';
import { useDialogsStore } from '@/stores/dialogs';
import { type ICreateBlockDTO } from '../../backend/types';
import { SelectParent } from '../../components/select-parent';
import { NodeType } from '../../models/oss';
import { type IOperationSchema, NodeType } from '../../models/oss';
import { constructNodeID } from '../../models/oss-api';
import { type DlgCreateBlockProps } from './dlg-create-block';
interface TabBlockCardProps {
oss: IOperationSchema;
}
export function TabBlockCard() {
const { manager } = useDialogsStore(state => state.props as DlgCreateBlockProps);
export function TabBlockCard({ oss }: TabBlockCardProps) {
const {
register,
control,
@ -21,7 +21,7 @@ export function TabBlockCard() {
} = useFormContext<ICreateBlockDTO>();
const children_blocks = useWatch({ control, name: 'children_blocks' });
const block_ids = children_blocks.map(id => constructNodeID(NodeType.BLOCK, id));
const all_children = [...block_ids, ...manager.oss.hierarchy.expandAllOutputs(block_ids)];
const all_children = [...block_ids, ...oss.hierarchy.expandAllOutputs(block_ids)];
return (
<div className='cc-fade-in cc-column'>
@ -36,8 +36,8 @@ export function TabBlockCard() {
control={control}
render={({ field }) => (
<SelectParent
items={manager.oss.blocks.filter(block => !all_children.includes(block.nodeID))}
value={field.value ? manager.oss.blockByID.get(field.value) ?? null : null}
items={oss.blocks.filter(block => !all_children.includes(block.nodeID))}
value={field.value ? oss.blockByID.get(field.value) ?? null : null}
placeholder='Родительский блок'
onChange={value => field.onChange(value ? value.id : null)}
/>

View File

@ -3,34 +3,34 @@
import { useFormContext, useWatch } from 'react-hook-form';
import { Label } from '@/components/input';
import { useDialogsStore } from '@/stores/dialogs';
import { type ICreateBlockDTO } from '../../backend/types';
import { PickContents } from '../../components/pick-contents';
import { type IOssItem, NodeType } from '../../models/oss';
import { type IOperationSchema, type IOssItem, NodeType } from '../../models/oss';
import { type DlgCreateBlockProps } from './dlg-create-block';
interface TabBlockChildrenProps {
oss: IOperationSchema;
}
export function TabBlockChildren() {
export function TabBlockChildren({ oss }: TabBlockChildrenProps) {
const { setValue, control } = useFormContext<ICreateBlockDTO>();
const { manager } = useDialogsStore(state => state.props as DlgCreateBlockProps);
const parent = useWatch({ control, name: 'item_data.parent' });
const children_blocks = useWatch({ control, name: 'children_blocks' });
const children_operations = useWatch({ control, name: 'children_operations' });
const parentItem = parent ? manager.oss.blockByID.get(parent) : null;
const parentItem = parent ? oss.blockByID.get(parent) : null;
const internalBlocks = parentItem
? manager.oss.hierarchy
? oss.hierarchy
.expandAllInputs([parentItem.nodeID])
.map(id => manager.oss.itemByNodeID.get(id))
.map(id => oss.itemByNodeID.get(id))
.filter(item => item !== null && item?.nodeType === NodeType.BLOCK)
: [];
const exclude = parentItem ? [parentItem, ...internalBlocks] : [];
const value = [
...children_blocks.map(id => manager.oss.blockByID.get(id)!),
...children_operations.map(id => manager.oss.operationByID.get(id)!)
...children_blocks.map(id => oss.blockByID.get(id)!),
...children_operations.map(id => oss.operationByID.get(id)!)
];
function handleChangeSelected(newValue: IOssItem[]) {
@ -50,7 +50,7 @@ export function TabBlockChildren() {
<div className='cc-fade-in cc-column'>
<Label text={`Выбор содержания: [ ${value.length} ]`} />
<PickContents
schema={manager.oss}
schema={oss}
exclude={exclude}
value={value}
onChange={newValue => handleChangeSelected(newValue)}

View File

@ -9,13 +9,15 @@ import { TextArea, TextInput } from '@/components/input';
import { ModalForm } from '@/components/modal';
import { useDialogsStore } from '@/stores/dialogs';
import { type ICreateSchemaDTO, schemaCreateSchema } from '../backend/types';
import { type ICreateSchemaDTO, type IOssLayout, schemaCreateSchema } from '../backend/types';
import { useCreateSchema } from '../backend/use-create-schema';
import { useOssSuspense } from '../backend/use-oss';
import { SelectParent } from '../components/select-parent';
import { type LayoutManager, OPERATION_NODE_HEIGHT, OPERATION_NODE_WIDTH } from '../models/oss-layout-api';
import { LayoutManager, OPERATION_NODE_HEIGHT, OPERATION_NODE_WIDTH } from '../models/oss-layout-api';
export interface DlgCreateSchemaProps {
manager: LayoutManager;
ossID: number;
layout: IOssLayout;
defaultX: number;
defaultY: number;
initialParent: number | null;
@ -25,9 +27,17 @@ export interface DlgCreateSchemaProps {
export function DlgCreateSchema() {
const { createSchema } = useCreateSchema();
const { manager, initialParent, onCreate, defaultX, defaultY } = useDialogsStore(
state => state.props as DlgCreateSchemaProps
);
const {
ossID, //
layout,
initialParent,
onCreate,
defaultX,
defaultY
} = useDialogsStore(state => state.props as DlgCreateSchemaProps);
const { schema } = useOssSuspense({ itemID: ossID });
const manager = new LayoutManager(schema, layout);
const {
control,

View File

@ -11,15 +11,17 @@ import { ModalForm } from '@/components/modal';
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
import { useDialogsStore } from '@/stores/dialogs';
import { type ICreateSynthesisDTO, schemaCreateSynthesis } from '../../backend/types';
import { type ICreateSynthesisDTO, type IOssLayout, schemaCreateSynthesis } from '../../backend/types';
import { useCreateSynthesis } from '../../backend/use-create-synthesis';
import { type LayoutManager, OPERATION_NODE_HEIGHT, OPERATION_NODE_WIDTH } from '../../models/oss-layout-api';
import { useOssSuspense } from '../../backend/use-oss';
import { LayoutManager, OPERATION_NODE_HEIGHT, OPERATION_NODE_WIDTH } from '../../models/oss-layout-api';
import { TabArguments } from './tab-arguments';
import { TabSubstitutions } from './tab-substitutions';
export interface DlgCreateSynthesisProps {
manager: LayoutManager;
ossID: number;
layout: IOssLayout;
initialParent: number | null;
initialInputs: number[];
defaultX: number;
@ -36,9 +38,17 @@ export type TabID = (typeof TabID)[keyof typeof TabID];
export function DlgCreateSynthesis() {
const { createSynthesis } = useCreateSynthesis();
const { manager, initialInputs, initialParent, onCreate, defaultX, defaultY } = useDialogsStore(
state => state.props as DlgCreateSynthesisProps
);
const {
ossID, //
layout,
initialInputs,
initialParent,
onCreate,
defaultX,
defaultY
} = useDialogsStore(state => state.props as DlgCreateSynthesisProps);
const { schema } = useOssSuspense({ itemID: ossID });
const manager = new LayoutManager(schema, layout);
const methods = useForm<ICreateSynthesisDTO>({
resolver: zodResolver(schemaCreateSynthesis),
@ -87,7 +97,7 @@ export function DlgCreateSynthesis() {
</TabList>
<FormProvider {...methods}>
<TabPanel>
<TabArguments />
<TabArguments oss={schema} />
</TabPanel>
<TabPanel>
<Suspense
@ -97,7 +107,7 @@ export function DlgCreateSynthesis() {
</div>
}
>
<TabSubstitutions />
<TabSubstitutions oss={schema} />
</Suspense>
</TabPanel>
</FormProvider>

View File

@ -3,16 +3,17 @@
import { Controller, useFormContext, useWatch } from 'react-hook-form';
import { Label, TextArea, TextInput } from '@/components/input';
import { useDialogsStore } from '@/stores/dialogs';
import { type ICreateSynthesisDTO } from '../../backend/types';
import { PickMultiOperation } from '../../components/pick-multi-operation';
import { SelectParent } from '../../components/select-parent';
import { type IOperationSchema } from '../../models/oss';
import { type DlgCreateSynthesisProps } from './dlg-create-synthesis';
interface TabArgumentsProps {
oss: IOperationSchema;
}
export function TabArguments() {
const { manager } = useDialogsStore(state => state.props as DlgCreateSynthesisProps);
export function TabArguments({ oss }: TabArgumentsProps) {
const {
register,
control,
@ -20,11 +21,11 @@ export function TabArguments() {
} = useFormContext<ICreateSynthesisDTO>();
const inputs = useWatch({ control, name: 'arguments' });
const replicas = manager.oss.replicas
const replicas = oss.replicas
.filter(item => inputs.includes(item.original))
.map(item => item.replica)
.concat(manager.oss.replicas.filter(item => inputs.includes(item.replica)).map(item => item.original));
const filtered = manager.oss.operations.filter(item => !replicas.includes(item.id));
.concat(oss.replicas.filter(item => inputs.includes(item.replica)).map(item => item.original));
const filtered = oss.operations.filter(item => !replicas.includes(item.id));
return (
<div className='cc-fade-in cc-column'>
@ -48,8 +49,8 @@ export function TabArguments() {
control={control}
render={({ field }) => (
<SelectParent
items={manager.oss.blocks}
value={field.value ? manager.oss.blockByID.get(field.value) ?? null : null}
items={oss.blocks}
value={field.value ? oss.blockByID.get(field.value) ?? null : null}
placeholder='Родительский блок'
onChange={value => field.onChange(value ? value.id : null)}
/>

View File

@ -6,21 +6,22 @@ import { useRSForms } from '@/features/rsform/backend/use-rsforms';
import { PickSubstitutions } from '@/features/rsform/components/pick-substitutions';
import { TextArea } from '@/components/input';
import { useDialogsStore } from '@/stores/dialogs';
import { type ICreateSynthesisDTO } from '../../backend/types';
import { type IOperationSchema } from '../../models/oss';
import { SubstitutionValidator } from '../../models/oss-api';
import { type DlgCreateSynthesisProps } from './dlg-create-synthesis';
interface TabSubstitutionsProps {
oss: IOperationSchema;
}
export function TabSubstitutions() {
const { manager } = useDialogsStore(state => state.props as DlgCreateSynthesisProps);
export function TabSubstitutions({ oss }: TabSubstitutionsProps) {
const { control } = useFormContext<ICreateSynthesisDTO>();
const inputs = useWatch({ control, name: 'arguments' });
const substitutions = useWatch({ control, name: 'substitutions' });
const schemasIDs = inputs
.map(id => manager.oss.operationByID.get(id)!)
.map(id => oss.operationByID.get(id)!)
.map(operation => operation.result)
.filter(id => id !== null);
const schemas = useRSForms(schemasIDs);

View File

@ -11,23 +11,26 @@ import { useDialogsStore } from '@/stores/dialogs';
import { type IDeleteOperationDTO, type IOssLayout, OperationType, schemaDeleteOperation } from '../backend/types';
import { useDeleteOperation } from '../backend/use-delete-operation';
import { type IOperationInput, type IOperationSchema, type IOperationSynthesis } from '../models/oss';
import { useOssSuspense } from '../backend/use-oss';
export interface DlgDeleteOperationProps {
oss: IOperationSchema;
target: IOperationInput | IOperationSynthesis;
ossID: number;
targetID: number;
layout: IOssLayout;
beforeDelete?: () => void;
}
export function DlgDeleteOperation() {
const { oss, target, layout, beforeDelete } = useDialogsStore(state => state.props as DlgDeleteOperationProps);
const { ossID, targetID, layout, beforeDelete } = useDialogsStore(state => state.props as DlgDeleteOperationProps);
const { deleteOperation } = useDeleteOperation();
const { schema } = useOssSuspense({ itemID: ossID });
const target = schema.operationByID.get(targetID)!;
const { handleSubmit, control } = useForm<IDeleteOperationDTO>({
resolver: zodResolver(schemaDeleteOperation),
defaultValues: {
target: target.id,
target: targetID,
layout: layout,
keep_constituents: false,
delete_schema: true
@ -35,7 +38,7 @@ export function DlgDeleteOperation() {
});
function onSubmit(data: IDeleteOperationDTO) {
return deleteOperation({ itemID: oss.id, data: data, beforeUpdate: beforeDelete });
return deleteOperation({ itemID: ossID, data: data, beforeUpdate: beforeDelete });
}
return (

View File

@ -11,23 +11,26 @@ import { useDialogsStore } from '@/stores/dialogs';
import { type IDeleteReplicaDTO, type IOssLayout, schemaDeleteReplica } from '../backend/types';
import { useDeleteReplica } from '../backend/use-delete-replica';
import { type IOperationReplica, type IOperationSchema } from '../models/oss';
import { useOssSuspense } from '../backend/use-oss';
export interface DlgDeleteReplicaProps {
oss: IOperationSchema;
target: IOperationReplica;
ossID: number;
targetID: number;
layout: IOssLayout;
beforeDelete?: () => void;
}
export function DlgDeleteReplica() {
const { oss, target, layout, beforeDelete } = useDialogsStore(state => state.props as DlgDeleteReplicaProps);
const { ossID, targetID, layout, beforeDelete } = useDialogsStore(state => state.props as DlgDeleteReplicaProps);
const { deleteReplica: deleteReference } = useDeleteReplica();
const { schema } = useOssSuspense({ itemID: ossID });
const target = schema.operationByID.get(targetID)!;
const { handleSubmit, control } = useForm<IDeleteReplicaDTO>({
resolver: zodResolver(schemaDeleteReplica),
defaultValues: {
target: target.id,
target: targetID,
layout: layout,
keep_constituents: false,
keep_connections: false
@ -36,7 +39,7 @@ export function DlgDeleteReplica() {
const keep_connections = useWatch({ control, name: 'keep_connections' });
function onSubmit(data: IDeleteReplicaDTO) {
return deleteReference({ itemID: oss.id, data: data, beforeUpdate: beforeDelete });
return deleteReference({ itemID: ossID, data: data, beforeUpdate: beforeDelete });
}
return (

View File

@ -9,20 +9,24 @@ import { TextArea, TextInput } from '@/components/input';
import { ModalForm } from '@/components/modal';
import { useDialogsStore } from '@/stores/dialogs';
import { type IUpdateBlockDTO, schemaUpdateBlock } from '../backend/types';
import { type IOssLayout, type IUpdateBlockDTO, schemaUpdateBlock } from '../backend/types';
import { useOssSuspense } from '../backend/use-oss';
import { useUpdateBlock } from '../backend/use-update-block';
import { SelectParent } from '../components/select-parent';
import { type IBlock } from '../models/oss';
import { type LayoutManager } from '../models/oss-layout-api';
import { LayoutManager } from '../models/oss-layout-api';
export interface DlgEditBlockProps {
manager: LayoutManager;
target: IBlock;
ossID: number;
layout: IOssLayout;
targetID: number;
}
export function DlgEditBlock() {
const { manager, target } = useDialogsStore(state => state.props as DlgEditBlockProps);
const { ossID, targetID, layout } = useDialogsStore(state => state.props as DlgEditBlockProps);
const { updateBlock } = useUpdateBlock();
const { schema } = useOssSuspense({ itemID: ossID });
const manager = new LayoutManager(schema, layout);
const target = manager.oss.blockByID.get(targetID)!;
const {
handleSubmit,

View File

@ -11,18 +11,19 @@ import { ModalForm } from '@/components/modal';
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
import { useDialogsStore } from '@/stores/dialogs';
import { type IUpdateOperationDTO, OperationType, schemaUpdateOperation } from '../../backend/types';
import { type IOssLayout, type IUpdateOperationDTO, OperationType, schemaUpdateOperation } from '../../backend/types';
import { useOssSuspense } from '../../backend/use-oss';
import { useUpdateOperation } from '../../backend/use-update-operation';
import { type IOperationInput, type IOperationSynthesis } from '../../models/oss';
import { type LayoutManager } from '../../models/oss-layout-api';
import { LayoutManager } from '../../models/oss-layout-api';
import { TabArguments } from './tab-arguments';
import { TabOperation } from './tab-operation';
import { TabSubstitutions } from './tab-substitutions';
export interface DlgEditOperationProps {
manager: LayoutManager;
target: IOperationInput | IOperationSynthesis;
ossID: number;
layout: IOssLayout;
targetID: number;
}
export const TabID = {
@ -33,13 +34,17 @@ export const TabID = {
export type TabID = (typeof TabID)[keyof typeof TabID];
export function DlgEditOperation() {
const { manager, target } = useDialogsStore(state => state.props as DlgEditOperationProps);
const { ossID, layout, targetID } = useDialogsStore(state => state.props as DlgEditOperationProps);
const { updateOperation } = useUpdateOperation();
const { schema } = useOssSuspense({ itemID: ossID });
const manager = new LayoutManager(schema, layout);
const target = manager.oss.operationByID.get(targetID)!;
const methods = useForm<IUpdateOperationDTO>({
resolver: zodResolver(schemaUpdateOperation),
defaultValues: {
target: target.id,
target: targetID,
item_data: {
alias: target.alias,
title: target.title,
@ -101,15 +106,17 @@ export function DlgEditOperation() {
<FormProvider {...methods}>
<TabPanel>
<TabOperation />
<TabOperation oss={schema} />
</TabPanel>
<TabPanel>{target.operation_type === OperationType.SYNTHESIS ? <TabArguments /> : null}</TabPanel>
<TabPanel>
{target.operation_type === OperationType.SYNTHESIS ? <TabArguments oss={schema} target={target} /> : null}
</TabPanel>
<TabPanel>
{target.operation_type === OperationType.SYNTHESIS ? (
<Suspense fallback={<Loader />}>
<TabSubstitutions />
<TabSubstitutions oss={schema} />
</Suspense>
) : null}
</TabPanel>

View File

@ -3,24 +3,26 @@
import { Controller, useFormContext, useWatch } from 'react-hook-form';
import { Label } from '@/components/input';
import { useDialogsStore } from '@/stores/dialogs';
import { type IUpdateOperationDTO } from '../../backend/types';
import { PickMultiOperation } from '../../components/pick-multi-operation';
import { type IOperationInput, type IOperationSchema, type IOperationSynthesis } from '../../models/oss';
import { type DlgEditOperationProps } from './dlg-edit-operation';
interface TabArgumentsProps {
oss: IOperationSchema;
target: IOperationInput | IOperationSynthesis;
}
export function TabArguments() {
export function TabArguments({ oss, target }: TabArgumentsProps) {
const { control, setValue } = useFormContext<IUpdateOperationDTO>();
const { manager, target } = useDialogsStore(state => state.props as DlgEditOperationProps);
const args = useWatch({ control, name: 'arguments' });
const replicas = manager.oss.replicas
const replicas = oss.replicas
.filter(item => args.includes(item.original) || item.original === target.id)
.map(item => item.replica)
.concat(manager.oss.replicas.filter(item => args.includes(item.replica)).map(item => item.original));
const potentialCycle = [target.id, ...replicas, ...manager.oss.graph.expandAllOutputs([target.id])];
const filtered = manager.oss.operations.filter(item => !potentialCycle.includes(item.id));
.concat(oss.replicas.filter(item => args.includes(item.replica)).map(item => item.original));
const potentialCycle = [target.id, ...replicas, ...oss.graph.expandAllOutputs([target.id])];
const filtered = oss.operations.filter(item => !potentialCycle.includes(item.id));
function handleChangeArguments(prev: number[], newValue: number[]) {
setValue('arguments', newValue, { shouldValidate: true });

View File

@ -1,15 +1,16 @@
import { Controller, useFormContext } from 'react-hook-form';
import { TextArea, TextInput } from '@/components/input';
import { useDialogsStore } from '@/stores/dialogs';
import { type IUpdateOperationDTO } from '../../backend/types';
import { SelectParent } from '../../components/select-parent';
import { type IOperationSchema } from '../../models/oss';
import { type DlgEditOperationProps } from './dlg-edit-operation';
interface TabOperationProps {
oss: IOperationSchema;
}
export function TabOperation() {
const { manager } = useDialogsStore(state => state.props as DlgEditOperationProps);
export function TabOperation({ oss }: TabOperationProps) {
const {
register,
control,
@ -37,8 +38,8 @@ export function TabOperation() {
control={control}
render={({ field }) => (
<SelectParent
items={manager.oss.blocks}
value={field.value ? manager.oss.blockByID.get(field.value) ?? null : null}
items={oss.blocks}
value={field.value ? oss.blockByID.get(field.value) ?? null : null}
placeholder='Родительский блок'
onChange={value => field.onChange(value ? value.id : null)}
/>

View File

@ -6,21 +6,22 @@ import { useRSForms } from '@/features/rsform/backend/use-rsforms';
import { PickSubstitutions } from '@/features/rsform/components/pick-substitutions';
import { TextArea } from '@/components/input';
import { useDialogsStore } from '@/stores/dialogs';
import { type IUpdateOperationDTO } from '../../backend/types';
import { type IOperationSchema } from '../../models/oss';
import { SubstitutionValidator } from '../../models/oss-api';
import { type DlgEditOperationProps } from './dlg-edit-operation';
interface TabSubstitutionsProps {
oss: IOperationSchema;
}
export function TabSubstitutions() {
const { manager } = useDialogsStore(state => state.props as DlgEditOperationProps);
export function TabSubstitutions({ oss }: TabSubstitutionsProps) {
const { control } = useFormContext<IUpdateOperationDTO>();
const inputs = useWatch({ control, name: 'arguments' });
const substitutions = useWatch({ control, name: 'substitutions' });
const schemasIDs = inputs
.map(id => manager.oss.operationByID.get(id)!)
.map(id => oss.operationByID.get(id)!)
.map(operation => operation.result)
.filter(id => id !== null);
const schemas = useRSForms(schemasIDs);

View File

@ -12,14 +12,16 @@ import { Checkbox, TextArea, TextInput } from '@/components/input';
import { ModalForm } from '@/components/modal';
import { useDialogsStore } from '@/stores/dialogs';
import { type IImportSchemaDTO, schemaImportSchema } from '../backend/types';
import { type IImportSchemaDTO, type IOssLayout, schemaImportSchema } from '../backend/types';
import { useImportSchema } from '../backend/use-import-schema';
import { useOssSuspense } from '../backend/use-oss';
import { SelectParent } from '../components/select-parent';
import { sortItemsForOSS } from '../models/oss-api';
import { type LayoutManager, OPERATION_NODE_HEIGHT, OPERATION_NODE_WIDTH } from '../models/oss-layout-api';
import { LayoutManager, OPERATION_NODE_HEIGHT, OPERATION_NODE_WIDTH } from '../models/oss-layout-api';
export interface DlgImportSchemaProps {
manager: LayoutManager;
ossID: number;
layout: IOssLayout;
defaultX: number;
defaultY: number;
initialParent: number | null;
@ -29,9 +31,16 @@ export interface DlgImportSchemaProps {
export function DlgImportSchema() {
const { importSchema } = useImportSchema();
const { manager, initialParent, onCreate, defaultX, defaultY } = useDialogsStore(
state => state.props as DlgImportSchemaProps
);
const {
ossID, //
layout,
initialParent,
onCreate,
defaultX,
defaultY
} = useDialogsStore(state => state.props as DlgImportSchemaProps);
const { schema } = useOssSuspense({ itemID: ossID });
const manager = new LayoutManager(schema, layout);
const { items: libraryItems } = useLibrary();
const sortedItems = sortItemsForOSS(manager.oss, libraryItems);

View File

@ -17,24 +17,27 @@ import { ModalForm } from '@/components/modal';
import { useDialogsStore } from '@/stores/dialogs';
import { type IOssLayout, type IRelocateConstituentsDTO, schemaRelocateConstituents } from '../backend/types';
import { useOssSuspense } from '../backend/use-oss';
import { useRelocateConstituents } from '../backend/use-relocate-constituents';
import { useUpdateLayout } from '../backend/use-update-layout';
import { IconRelocationUp } from '../components/icon-relocation-up';
import { type IOperation, type IOperationSchema } from '../models/oss';
import { getRelocateCandidates } from '../models/oss-api';
export interface DlgRelocateConstituentsProps {
oss: IOperationSchema;
initialTarget?: IOperation;
ossID: number;
targetID?: number;
layout?: IOssLayout;
}
export function DlgRelocateConstituents() {
const { oss, initialTarget, layout } = useDialogsStore(state => state.props as DlgRelocateConstituentsProps);
const { ossID, targetID, layout } = useDialogsStore(state => state.props as DlgRelocateConstituentsProps);
const { items: libraryItems } = useLibrary();
const { updateLayout: updatePositions } = useUpdateLayout();
const { relocateConstituents } = useRelocateConstituents();
const { schema: oss } = useOssSuspense({ itemID: ossID });
const initialTarget = targetID ? oss.operationByID.get(targetID)! : undefined;
const { handleSubmit, control, setValue } = useForm<IRelocateConstituentsDTO>({
resolver: zodResolver(schemaRelocateConstituents),
defaultValues: {

View File

@ -7,7 +7,6 @@ import { useDialogsStore } from '@/stores/dialogs';
import { useDeleteBlock } from '../../../../backend/use-delete-block';
import { useMutatingOss } from '../../../../backend/use-mutating-oss';
import { type IBlock } from '../../../../models/oss';
import { LayoutManager } from '../../../../models/oss-layout-api';
import { useOssEdit } from '../../oss-edit-context';
import { useGetLayout } from '../use-get-layout';
@ -30,8 +29,9 @@ export function MenuBlock({ block, onHide }: MenuBlockProps) {
}
onHide();
showEditBlock({
manager: new LayoutManager(schema, getLayout()),
target: block
layout: getLayout(),
ossID: schema.id,
targetID: block.id
});
}

View File

@ -101,8 +101,9 @@ export function MenuOperation({ operation, onHide }: MenuOperationProps) {
}
onHide();
showEditOperation({
manager: new LayoutManager(schema, getLayout()),
target: operation
layout: getLayout(),
ossID: schema.id,
targetID: operation.id
});
}
@ -114,8 +115,8 @@ export function MenuOperation({ operation, onHide }: MenuOperationProps) {
switch (operation.operation_type) {
case OperationType.REPLICA:
showDeleteReference({
oss: schema,
target: operation,
ossID: schema.id,
targetID: operation.id,
layout: getLayout(),
beforeDelete: deselectAll
});
@ -123,8 +124,8 @@ export function MenuOperation({ operation, onHide }: MenuOperationProps) {
case OperationType.INPUT:
case OperationType.SYNTHESIS:
showDeleteOperation({
oss: schema,
target: operation,
ossID: schema.id,
targetID: operation.id,
layout: getLayout(),
beforeDelete: deselectAll
});
@ -163,8 +164,8 @@ export function MenuOperation({ operation, onHide }: MenuOperationProps) {
}
onHide();
showRelocateConstituents({
oss: schema,
initialTarget: operation,
ossID: schema.id,
targetID: operation.id,
layout: getLayout()
});
}

View File

@ -73,7 +73,7 @@ export function OssFlow() {
const [mouseCoords, setMouseCoords] = useState<Position2D>({ x: 0, y: 0 });
const showCreateOperation = useDialogsStore(state => state.showCreateOperation);
const showCreateOperation = useDialogsStore(state => state.showCreateSynthesis);
const showCreateBlock = useDialogsStore(state => state.showCreateBlock);
const showCreateSchema = useDialogsStore(state => state.showCreateSchema);
const showDeleteOperation = useDialogsStore(state => state.showDeleteOperation);
@ -91,7 +91,8 @@ export function OssFlow() {
function handleCreateSynthesis() {
const targetPosition = screenToFlowPosition({ x: window.innerWidth / 2, y: window.innerHeight / 2 });
showCreateOperation({
manager: new LayoutManager(schema, getLayout()),
ossID: schema.id,
layout: getLayout(),
defaultX: targetPosition.x,
defaultY: targetPosition.y,
initialInputs: selectedItems.filter(item => item?.nodeType === NodeType.OPERATION).map(item => item.id),
@ -106,12 +107,18 @@ export function OssFlow() {
function handleCreateBlock() {
const targetPosition = screenToFlowPosition({ x: window.innerWidth / 2, y: window.innerHeight / 2 });
const parent = extractBlockParent(selectedItems);
const needChildren = parent === null || selectedItems.length !== 1 || parent !== selectedItems[0].id;
showCreateBlock({
manager: new LayoutManager(schema, getLayout()),
ossID: schema.id,
layout: getLayout(),
defaultX: targetPosition.x,
defaultY: targetPosition.y,
initialChildren:
parent !== null && selectedItems.length === 1 && parent === selectedItems[0].id ? [] : selectedItems,
childrenBlocks: !needChildren
? []
: selectedItems.filter(item => item.nodeType === NodeType.BLOCK).map(item => item.id),
childrenOperations: !needChildren
? []
: selectedItems.filter(item => item.nodeType === NodeType.OPERATION).map(item => item.id),
initialParent: parent,
onCreate: newID => {
resetView();
@ -123,7 +130,8 @@ export function OssFlow() {
function handleCreateSchema() {
const targetPosition = screenToFlowPosition({ x: window.innerWidth / 2, y: window.innerHeight / 2 });
showCreateSchema({
manager: new LayoutManager(schema, getLayout()),
ossID: schema.id,
layout: getLayout(),
defaultX: targetPosition.x,
defaultY: targetPosition.y,
initialParent: extractBlockParent(selectedItems),
@ -137,7 +145,8 @@ export function OssFlow() {
function handleImportSchema() {
const targetPosition = screenToFlowPosition({ x: window.innerWidth / 2, y: window.innerHeight / 2 });
showImportSchema({
manager: new LayoutManager(schema, getLayout()),
ossID: schema.id,
layout: getLayout(),
defaultX: targetPosition.x,
defaultY: targetPosition.y,
initialParent: extractBlockParent(selectedItems),
@ -163,8 +172,8 @@ export function OssFlow() {
switch (item.operation_type) {
case OperationType.REPLICA:
showDeleteReference({
oss: schema,
target: item,
ossID: schema.id,
targetID: item.id,
layout: getLayout(),
beforeDelete: deselectAll
});
@ -172,8 +181,8 @@ export function OssFlow() {
case OperationType.INPUT:
case OperationType.SYNTHESIS:
showDeleteOperation({
oss: schema,
target: item,
ossID: schema.id,
targetID: item.id,
layout: getLayout(),
beforeDelete: deselectAll
});
@ -198,8 +207,9 @@ export function OssFlow() {
const block = schema.blockByID.get(-Number(node.id));
if (block) {
showEditBlock({
manager: new LayoutManager(schema, getLayout()),
target: block
ossID: schema.id,
layout: getLayout(),
targetID: block.id
});
}
} else {

View File

@ -93,7 +93,7 @@ interface DialogsStore {
showCstTemplate: (props: DlgCstTemplateProps) => void;
showCreateCst: (props: DlgCreateCstProps) => void;
showCreateBlock: (props: DlgCreateBlockProps) => void;
showCreateOperation: (props: DlgCreateSynthesisProps) => void;
showCreateSynthesis: (props: DlgCreateSynthesisProps) => void;
showDeleteCst: (props: DlgDeleteCstProps) => void;
showEditEditors: (props: DlgEditEditorsProps) => void;
showEditOperation: (props: DlgEditOperationProps) => void;
@ -138,7 +138,7 @@ export const useDialogsStore = create<DialogsStore>()(set => ({
showVideo: props => set({ active: DialogType.SHOW_VIDEO, props: props }),
showCstTemplate: props => set({ active: DialogType.CONSTITUENTA_TEMPLATE, props: props }),
showCreateCst: props => set({ active: DialogType.CREATE_CONSTITUENTA, props: props }),
showCreateOperation: props => set({ active: DialogType.CREATE_SYNTHESIS, props: props }),
showCreateSynthesis: props => set({ active: DialogType.CREATE_SYNTHESIS, props: props }),
showCreateBlock: props => set({ active: DialogType.CREATE_BLOCK, props: props }),
showDeleteCst: props => set({ active: DialogType.DELETE_CONSTITUENTA, props: props }),
showEditEditors: props => set({ active: DialogType.EDIT_EDITORS, props: props }),