mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 04:50:36 +03:00
R: Refactor layout management
This commit is contained in:
parent
6fa25b51fe
commit
309c1ba323
|
@ -10,18 +10,16 @@ import { ModalForm } from '@/components/modal';
|
||||||
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
|
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
import { type ICreateBlockDTO, type IOssLayout, schemaCreateBlock } from '../../backend/types';
|
import { type ICreateBlockDTO, schemaCreateBlock } from '../../backend/types';
|
||||||
import { useCreateBlock } from '../../backend/use-create-block';
|
import { useCreateBlock } from '../../backend/use-create-block';
|
||||||
import { type IOperationSchema } from '../../models/oss';
|
import { type LayoutManager } from '../../models/oss-layout-api';
|
||||||
import { calculateNewBlockPosition } from '../../models/oss-api';
|
|
||||||
import { BLOCK_NODE_MIN_HEIGHT, BLOCK_NODE_MIN_WIDTH } from '../../pages/oss-page/editor-oss-graph/graph/block-node';
|
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 { TabBlockCard } from './tab-block-card';
|
||||||
import { TabBlockChildren } from './tab-block-children';
|
import { TabBlockChildren } from './tab-block-children';
|
||||||
|
|
||||||
export interface DlgCreateBlockProps {
|
export interface DlgCreateBlockProps {
|
||||||
oss: IOperationSchema;
|
manager: LayoutManager;
|
||||||
layout: IOssLayout;
|
|
||||||
initialInputs: number[];
|
initialInputs: number[];
|
||||||
defaultX: number;
|
defaultX: number;
|
||||||
defaultY: number;
|
defaultY: number;
|
||||||
|
@ -37,7 +35,7 @@ export type TabID = (typeof TabID)[keyof typeof TabID];
|
||||||
export function DlgCreateBlock() {
|
export function DlgCreateBlock() {
|
||||||
const { createBlock } = useCreateBlock();
|
const { createBlock } = useCreateBlock();
|
||||||
|
|
||||||
const { oss, layout, initialInputs, onCreate, defaultX, defaultY } = useDialogsStore(
|
const { manager, initialInputs, onCreate, defaultX, defaultY } = useDialogsStore(
|
||||||
state => state.props as DlgCreateBlockProps
|
state => state.props as DlgCreateBlockProps
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -55,21 +53,21 @@ export function DlgCreateBlock() {
|
||||||
height: BLOCK_NODE_MIN_HEIGHT,
|
height: BLOCK_NODE_MIN_HEIGHT,
|
||||||
children_blocks: initialInputs.filter(id => id < 0).map(id => -id),
|
children_blocks: initialInputs.filter(id => id < 0).map(id => -id),
|
||||||
children_operations: initialInputs.filter(id => id > 0),
|
children_operations: initialInputs.filter(id => id > 0),
|
||||||
layout: layout
|
layout: manager.layout
|
||||||
},
|
},
|
||||||
mode: 'onChange'
|
mode: 'onChange'
|
||||||
});
|
});
|
||||||
const title = useWatch({ control: methods.control, name: 'item_data.title' });
|
const title = useWatch({ control: methods.control, name: 'item_data.title' });
|
||||||
const [activeTab, setActiveTab] = useState<TabID>(TabID.CARD);
|
const [activeTab, setActiveTab] = useState<TabID>(TabID.CARD);
|
||||||
const isValid = !!title && !oss.blocks.some(block => block.title === title);
|
const isValid = !!title && !manager.oss.blocks.some(block => block.title === title);
|
||||||
|
|
||||||
function onSubmit(data: ICreateBlockDTO) {
|
function onSubmit(data: ICreateBlockDTO) {
|
||||||
const rectangle = calculateNewBlockPosition(data, layout);
|
const rectangle = manager.calculateNewBlockPosition(data);
|
||||||
data.position_x = rectangle.x;
|
data.position_x = rectangle.x;
|
||||||
data.position_y = rectangle.y;
|
data.position_y = rectangle.y;
|
||||||
data.width = rectangle.width;
|
data.width = rectangle.width;
|
||||||
data.height = rectangle.height;
|
data.height = rectangle.height;
|
||||||
void createBlock({ itemID: oss.id, data: data }).then(response => onCreate?.(response.new_block.id));
|
void createBlock({ itemID: manager.oss.id, data: data }).then(response => onCreate?.(response.new_block.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { SelectParent } from '../../components/select-parent';
|
||||||
import { type DlgCreateBlockProps } from './dlg-create-block';
|
import { type DlgCreateBlockProps } from './dlg-create-block';
|
||||||
|
|
||||||
export function TabBlockCard() {
|
export function TabBlockCard() {
|
||||||
const { oss } = useDialogsStore(state => state.props as DlgCreateBlockProps);
|
const { manager } = useDialogsStore(state => state.props as DlgCreateBlockProps);
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
control,
|
control,
|
||||||
|
@ -31,8 +31,8 @@ export function TabBlockCard() {
|
||||||
control={control}
|
control={control}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<SelectParent
|
<SelectParent
|
||||||
items={oss.blocks}
|
items={manager.oss.blocks}
|
||||||
value={field.value ? oss.blockByID.get(field.value) ?? null : null}
|
value={field.value ? manager.oss.blockByID.get(field.value) ?? null : null}
|
||||||
placeholder='Блок содержания не выбран'
|
placeholder='Блок содержания не выбран'
|
||||||
onChange={value => field.onChange(value ? value.id : null)}
|
onChange={value => field.onChange(value ? value.id : null)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { type DlgCreateBlockProps } from './dlg-create-block';
|
||||||
|
|
||||||
export function TabBlockChildren() {
|
export function TabBlockChildren() {
|
||||||
const { setValue, control } = useFormContext<ICreateBlockDTO>();
|
const { setValue, control } = useFormContext<ICreateBlockDTO>();
|
||||||
const { oss } = useDialogsStore(state => state.props as DlgCreateBlockProps);
|
const { manager } = useDialogsStore(state => state.props as DlgCreateBlockProps);
|
||||||
const children_blocks = useWatch({ control, name: 'children_blocks' });
|
const children_blocks = useWatch({ control, name: 'children_blocks' });
|
||||||
const children_operations = useWatch({ control, name: 'children_operations' });
|
const children_operations = useWatch({ control, name: 'children_operations' });
|
||||||
|
|
||||||
|
@ -33,7 +33,12 @@ export function TabBlockChildren() {
|
||||||
return (
|
return (
|
||||||
<div className='cc-fade-in cc-column'>
|
<div className='cc-fade-in cc-column'>
|
||||||
<Label text={`Выбор содержания: [ ${value.length} ]`} />
|
<Label text={`Выбор содержания: [ ${value.length} ]`} />
|
||||||
<PickContents schema={oss} value={value} onChange={newValue => handleChangeSelected(newValue)} rows={10} />
|
<PickContents
|
||||||
|
schema={manager.oss}
|
||||||
|
value={value}
|
||||||
|
onChange={newValue => handleChangeSelected(newValue)}
|
||||||
|
rows={10}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,18 +10,16 @@ import { ModalForm } from '@/components/modal';
|
||||||
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
|
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
import { type ICreateOperationDTO, type IOssLayout, OperationType, schemaCreateOperation } from '../../backend/types';
|
import { type ICreateOperationDTO, OperationType, schemaCreateOperation } from '../../backend/types';
|
||||||
import { useCreateOperation } from '../../backend/use-create-operation';
|
import { useCreateOperation } from '../../backend/use-create-operation';
|
||||||
import { describeOperationType, labelOperationType } from '../../labels';
|
import { describeOperationType, labelOperationType } from '../../labels';
|
||||||
import { type IOperationSchema } from '../../models/oss';
|
import { type LayoutManager } from '../../models/oss-layout-api';
|
||||||
import { calculateNewOperationPosition } from '../../models/oss-api';
|
|
||||||
|
|
||||||
import { TabInputOperation } from './tab-input-operation';
|
import { TabInputOperation } from './tab-input-operation';
|
||||||
import { TabSynthesisOperation } from './tab-synthesis-operation';
|
import { TabSynthesisOperation } from './tab-synthesis-operation';
|
||||||
|
|
||||||
export interface DlgCreateOperationProps {
|
export interface DlgCreateOperationProps {
|
||||||
oss: IOperationSchema;
|
manager: LayoutManager;
|
||||||
layout: IOssLayout;
|
|
||||||
initialParent: number | null;
|
initialParent: number | null;
|
||||||
initialInputs: number[];
|
initialInputs: number[];
|
||||||
defaultX: number;
|
defaultX: number;
|
||||||
|
@ -38,7 +36,7 @@ export type TabID = (typeof TabID)[keyof typeof TabID];
|
||||||
export function DlgCreateOperation() {
|
export function DlgCreateOperation() {
|
||||||
const { createOperation } = useCreateOperation();
|
const { createOperation } = useCreateOperation();
|
||||||
|
|
||||||
const { oss, layout, initialInputs, initialParent, onCreate, defaultX, defaultY } = useDialogsStore(
|
const { manager, initialInputs, initialParent, onCreate, defaultX, defaultY } = useDialogsStore(
|
||||||
state => state.props as DlgCreateOperationProps
|
state => state.props as DlgCreateOperationProps
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -57,19 +55,21 @@ export function DlgCreateOperation() {
|
||||||
position_y: defaultY,
|
position_y: defaultY,
|
||||||
arguments: initialInputs,
|
arguments: initialInputs,
|
||||||
create_schema: false,
|
create_schema: false,
|
||||||
layout: layout
|
layout: manager.layout
|
||||||
},
|
},
|
||||||
mode: 'onChange'
|
mode: 'onChange'
|
||||||
});
|
});
|
||||||
const alias = useWatch({ control: methods.control, name: 'item_data.alias' });
|
const alias = useWatch({ control: methods.control, name: 'item_data.alias' });
|
||||||
const [activeTab, setActiveTab] = useState(initialInputs.length === 0 ? TabID.INPUT : TabID.SYNTHESIS);
|
const [activeTab, setActiveTab] = useState(initialInputs.length === 0 ? TabID.INPUT : TabID.SYNTHESIS);
|
||||||
const isValid = !!alias && !oss.operations.some(operation => operation.alias === alias);
|
const isValid = !!alias && !manager.oss.operations.some(operation => operation.alias === alias);
|
||||||
|
|
||||||
function onSubmit(data: ICreateOperationDTO) {
|
function onSubmit(data: ICreateOperationDTO) {
|
||||||
const target = calculateNewOperationPosition(oss, data, layout);
|
const target = manager.calculateNewOperationPosition(data);
|
||||||
data.position_x = target.x;
|
data.position_x = target.x;
|
||||||
data.position_y = target.y;
|
data.position_y = target.y;
|
||||||
void createOperation({ itemID: oss.id, data: data }).then(response => onCreate?.(response.new_operation.id));
|
void createOperation({ itemID: manager.oss.id, data: data }).then(response =>
|
||||||
|
onCreate?.(response.new_operation.id)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSelectTab(newTab: TabID, last: TabID) {
|
function handleSelectTab(newTab: TabID, last: TabID) {
|
||||||
|
|
|
@ -18,9 +18,9 @@ import { sortItemsForOSS } from '../../models/oss-api';
|
||||||
import { type DlgCreateOperationProps } from './dlg-create-operation';
|
import { type DlgCreateOperationProps } from './dlg-create-operation';
|
||||||
|
|
||||||
export function TabInputOperation() {
|
export function TabInputOperation() {
|
||||||
const { oss } = useDialogsStore(state => state.props as DlgCreateOperationProps);
|
const { manager } = useDialogsStore(state => state.props as DlgCreateOperationProps);
|
||||||
const { items: libraryItems } = useLibrary();
|
const { items: libraryItems } = useLibrary();
|
||||||
const sortedItems = sortItemsForOSS(oss, libraryItems);
|
const sortedItems = sortItemsForOSS(manager.oss, libraryItems);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
|
@ -31,7 +31,7 @@ export function TabInputOperation() {
|
||||||
const createSchema = useWatch({ control, name: 'create_schema' });
|
const createSchema = useWatch({ control, name: 'create_schema' });
|
||||||
|
|
||||||
function baseFilter(item: ILibraryItem) {
|
function baseFilter(item: ILibraryItem) {
|
||||||
return !oss.schemas.includes(item.id);
|
return !manager.oss.schemas.includes(item.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleChangeCreateSchema(value: boolean) {
|
function handleChangeCreateSchema(value: boolean) {
|
||||||
|
@ -75,8 +75,8 @@ export function TabInputOperation() {
|
||||||
control={control}
|
control={control}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<SelectParent
|
<SelectParent
|
||||||
items={oss.blocks}
|
items={manager.oss.blocks}
|
||||||
value={field.value ? oss.blockByID.get(field.value) ?? null : null}
|
value={field.value ? manager.oss.blockByID.get(field.value) ?? null : null}
|
||||||
placeholder='Блок содержания'
|
placeholder='Блок содержания'
|
||||||
onChange={value => field.onChange(value ? value.id : null)}
|
onChange={value => field.onChange(value ? value.id : null)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { SelectParent } from '../../components/select-parent';
|
||||||
import { type DlgCreateOperationProps } from './dlg-create-operation';
|
import { type DlgCreateOperationProps } from './dlg-create-operation';
|
||||||
|
|
||||||
export function TabSynthesisOperation() {
|
export function TabSynthesisOperation() {
|
||||||
const { oss } = useDialogsStore(state => state.props as DlgCreateOperationProps);
|
const { manager } = useDialogsStore(state => state.props as DlgCreateOperationProps);
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
control,
|
control,
|
||||||
|
@ -40,8 +40,8 @@ export function TabSynthesisOperation() {
|
||||||
control={control}
|
control={control}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<SelectParent
|
<SelectParent
|
||||||
items={oss.blocks}
|
items={manager.oss.blocks}
|
||||||
value={field.value ? oss.blockByID.get(field.value) ?? null : null}
|
value={field.value ? manager.oss.blockByID.get(field.value) ?? null : null}
|
||||||
placeholder='Блок содержания'
|
placeholder='Блок содержания'
|
||||||
onChange={value => field.onChange(value ? value.id : null)}
|
onChange={value => field.onChange(value ? value.id : null)}
|
||||||
/>
|
/>
|
||||||
|
@ -64,7 +64,7 @@ export function TabSynthesisOperation() {
|
||||||
name='arguments'
|
name='arguments'
|
||||||
control={control}
|
control={control}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<PickMultiOperation items={oss.operations} value={field.value} onChange={field.onChange} rows={6} />
|
<PickMultiOperation items={manager.oss.operations} value={field.value} onChange={field.onChange} rows={6} />
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,19 +7,19 @@ import { TextArea, TextInput } from '@/components/input';
|
||||||
import { ModalForm } from '@/components/modal';
|
import { ModalForm } from '@/components/modal';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
import { type IOssLayout, type IUpdateBlockDTO, schemaUpdateBlock } from '../backend/types';
|
import { type IUpdateBlockDTO, schemaUpdateBlock } from '../backend/types';
|
||||||
import { useUpdateBlock } from '../backend/use-update-block';
|
import { useUpdateBlock } from '../backend/use-update-block';
|
||||||
import { SelectParent } from '../components/select-parent';
|
import { SelectParent } from '../components/select-parent';
|
||||||
import { type IBlock, type IOperationSchema } from '../models/oss';
|
import { type IBlock } from '../models/oss';
|
||||||
|
import { type LayoutManager } from '../models/oss-layout-api';
|
||||||
|
|
||||||
export interface DlgEditBlockProps {
|
export interface DlgEditBlockProps {
|
||||||
oss: IOperationSchema;
|
manager: LayoutManager;
|
||||||
target: IBlock;
|
target: IBlock;
|
||||||
layout: IOssLayout;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DlgEditBlock() {
|
export function DlgEditBlock() {
|
||||||
const { oss, target, layout } = useDialogsStore(state => state.props as DlgEditBlockProps);
|
const { manager, target } = useDialogsStore(state => state.props as DlgEditBlockProps);
|
||||||
const { updateBlock } = useUpdateBlock();
|
const { updateBlock } = useUpdateBlock();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -36,13 +36,13 @@ export function DlgEditBlock() {
|
||||||
description: target.description,
|
description: target.description,
|
||||||
parent: target.parent
|
parent: target.parent
|
||||||
},
|
},
|
||||||
layout: layout
|
layout: manager.layout
|
||||||
},
|
},
|
||||||
mode: 'onChange'
|
mode: 'onChange'
|
||||||
});
|
});
|
||||||
|
|
||||||
function onSubmit(data: IUpdateBlockDTO) {
|
function onSubmit(data: IUpdateBlockDTO) {
|
||||||
return updateBlock({ itemID: oss.id, data });
|
return updateBlock({ itemID: manager.oss.id, data });
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -64,8 +64,8 @@ export function DlgEditBlock() {
|
||||||
control={control}
|
control={control}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<SelectParent
|
<SelectParent
|
||||||
items={oss.blocks.filter(block => block.id !== target.id)}
|
items={manager.oss.blocks.filter(block => block.id !== target.id)}
|
||||||
value={field.value ? oss.blockByID.get(field.value) ?? null : null}
|
value={field.value ? manager.oss.blockByID.get(field.value) ?? null : null}
|
||||||
placeholder='Блок содержания не выбран'
|
placeholder='Блок содержания не выбран'
|
||||||
onChange={value => field.onChange(value ? value.id : null)}
|
onChange={value => field.onChange(value ? value.id : null)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -11,18 +11,18 @@ import { ModalForm } from '@/components/modal';
|
||||||
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
|
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
import { type IOssLayout, type IUpdateOperationDTO, OperationType, schemaUpdateOperation } from '../../backend/types';
|
import { type IUpdateOperationDTO, OperationType, schemaUpdateOperation } from '../../backend/types';
|
||||||
import { useUpdateOperation } from '../../backend/use-update-operation';
|
import { useUpdateOperation } from '../../backend/use-update-operation';
|
||||||
import { type IOperation, type IOperationSchema } from '../../models/oss';
|
import { type IOperation } from '../../models/oss';
|
||||||
|
import { type LayoutManager } from '../../models/oss-layout-api';
|
||||||
|
|
||||||
import { TabArguments } from './tab-arguments';
|
import { TabArguments } from './tab-arguments';
|
||||||
import { TabOperation } from './tab-operation';
|
import { TabOperation } from './tab-operation';
|
||||||
import { TabSynthesis } from './tab-synthesis';
|
import { TabSynthesis } from './tab-synthesis';
|
||||||
|
|
||||||
export interface DlgEditOperationProps {
|
export interface DlgEditOperationProps {
|
||||||
oss: IOperationSchema;
|
manager: LayoutManager;
|
||||||
target: IOperation;
|
target: IOperation;
|
||||||
layout: IOssLayout;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TabID = {
|
export const TabID = {
|
||||||
|
@ -33,7 +33,7 @@ export const TabID = {
|
||||||
export type TabID = (typeof TabID)[keyof typeof TabID];
|
export type TabID = (typeof TabID)[keyof typeof TabID];
|
||||||
|
|
||||||
export function DlgEditOperation() {
|
export function DlgEditOperation() {
|
||||||
const { oss, target, layout } = useDialogsStore(state => state.props as DlgEditOperationProps);
|
const { manager, target } = useDialogsStore(state => state.props as DlgEditOperationProps);
|
||||||
const { updateOperation } = useUpdateOperation();
|
const { updateOperation } = useUpdateOperation();
|
||||||
|
|
||||||
const methods = useForm<IUpdateOperationDTO>({
|
const methods = useForm<IUpdateOperationDTO>({
|
||||||
|
@ -51,14 +51,17 @@ export function DlgEditOperation() {
|
||||||
original: sub.original,
|
original: sub.original,
|
||||||
substitution: sub.substitution
|
substitution: sub.substitution
|
||||||
})),
|
})),
|
||||||
layout: layout
|
layout: manager.layout
|
||||||
},
|
},
|
||||||
mode: 'onChange'
|
mode: 'onChange'
|
||||||
});
|
});
|
||||||
const [activeTab, setActiveTab] = useState<TabID>(TabID.CARD);
|
const [activeTab, setActiveTab] = useState<TabID>(TabID.CARD);
|
||||||
|
|
||||||
function onSubmit(data: IUpdateOperationDTO) {
|
function onSubmit(data: IUpdateOperationDTO) {
|
||||||
return updateOperation({ itemID: oss.id, data });
|
// if (data.item_data.parent !== target.parent) {
|
||||||
|
// data.layout = updateLayoutOnOperationChange(data.target, data.item_data.parent, data.layout);
|
||||||
|
// }
|
||||||
|
return updateOperation({ itemID: manager.oss.id, data });
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -11,9 +11,9 @@ import { type DlgEditOperationProps } from './dlg-edit-operation';
|
||||||
|
|
||||||
export function TabArguments() {
|
export function TabArguments() {
|
||||||
const { control, setValue } = useFormContext<IUpdateOperationDTO>();
|
const { control, setValue } = useFormContext<IUpdateOperationDTO>();
|
||||||
const { oss, target } = useDialogsStore(state => state.props as DlgEditOperationProps);
|
const { manager, target } = useDialogsStore(state => state.props as DlgEditOperationProps);
|
||||||
const potentialCycle = [target.id, ...oss.graph.expandAllOutputs([target.id])];
|
const potentialCycle = [target.id, ...manager.oss.graph.expandAllOutputs([target.id])];
|
||||||
const filtered = oss.operations.filter(item => !potentialCycle.includes(item.id));
|
const filtered = manager.oss.operations.filter(item => !potentialCycle.includes(item.id));
|
||||||
|
|
||||||
function handleChangeArguments(prev: number[], newValue: number[]) {
|
function handleChangeArguments(prev: number[], newValue: number[]) {
|
||||||
setValue('arguments', newValue, { shouldValidate: true });
|
setValue('arguments', newValue, { shouldValidate: true });
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { SelectParent } from '../../components/select-parent';
|
||||||
import { type DlgEditOperationProps } from './dlg-edit-operation';
|
import { type DlgEditOperationProps } from './dlg-edit-operation';
|
||||||
|
|
||||||
export function TabOperation() {
|
export function TabOperation() {
|
||||||
const { oss } = useDialogsStore(state => state.props as DlgEditOperationProps);
|
const { manager } = useDialogsStore(state => state.props as DlgEditOperationProps);
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
control,
|
control,
|
||||||
|
@ -37,8 +37,8 @@ export function TabOperation() {
|
||||||
control={control}
|
control={control}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<SelectParent
|
<SelectParent
|
||||||
items={oss.blocks}
|
items={manager.oss.blocks}
|
||||||
value={field.value ? oss.blockByID.get(field.value) ?? null : null}
|
value={field.value ? manager.oss.blockByID.get(field.value) ?? null : null}
|
||||||
placeholder='Блок содержания'
|
placeholder='Блок содержания'
|
||||||
onChange={value => field.onChange(value ? value.id : null)}
|
onChange={value => field.onChange(value ? value.id : null)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -14,13 +14,13 @@ import { SubstitutionValidator } from '../../models/oss-api';
|
||||||
import { type DlgEditOperationProps } from './dlg-edit-operation';
|
import { type DlgEditOperationProps } from './dlg-edit-operation';
|
||||||
|
|
||||||
export function TabSynthesis() {
|
export function TabSynthesis() {
|
||||||
const { oss } = useDialogsStore(state => state.props as DlgEditOperationProps);
|
const { manager } = useDialogsStore(state => state.props as DlgEditOperationProps);
|
||||||
const { control } = useFormContext<IUpdateOperationDTO>();
|
const { control } = useFormContext<IUpdateOperationDTO>();
|
||||||
const inputs = useWatch({ control, name: 'arguments' });
|
const inputs = useWatch({ control, name: 'arguments' });
|
||||||
const substitutions = useWatch({ control, name: 'substitutions' });
|
const substitutions = useWatch({ control, name: 'substitutions' });
|
||||||
|
|
||||||
const schemasIDs = inputs
|
const schemasIDs = inputs
|
||||||
.map(id => oss.operationByID.get(id)!)
|
.map(id => manager.oss.operationByID.get(id)!)
|
||||||
.map(operation => operation.result)
|
.map(operation => operation.result)
|
||||||
.filter(id => id !== null);
|
.filter(id => id !== null);
|
||||||
const schemas = useRSForms(schemasIDs);
|
const schemas = useRSForms(schemasIDs);
|
||||||
|
|
|
@ -22,17 +22,9 @@ import {
|
||||||
import { infoMsg } from '@/utils/labels';
|
import { infoMsg } from '@/utils/labels';
|
||||||
|
|
||||||
import { Graph } from '../../../models/graph';
|
import { Graph } from '../../../models/graph';
|
||||||
import { type ICreateBlockDTO, type ICreateOperationDTO, type IOssLayout } from '../backend/types';
|
|
||||||
import { describeSubstitutionError } from '../labels';
|
import { describeSubstitutionError } from '../labels';
|
||||||
import { OPERATION_NODE_HEIGHT, OPERATION_NODE_WIDTH } from '../pages/oss-page/editor-oss-graph/graph/node-core';
|
|
||||||
|
|
||||||
import { type IOperationSchema, type IOssItem, SubstitutionErrorType } from './oss';
|
import { type IOperationSchema, type IOssItem, SubstitutionErrorType } from './oss';
|
||||||
import { type Position2D, type Rectangle2D } from './oss-layout';
|
|
||||||
|
|
||||||
export const GRID_SIZE = 10; // pixels - size of OSS grid
|
|
||||||
const MIN_DISTANCE = 2 * GRID_SIZE; // pixels - minimum distance between nodes
|
|
||||||
const DISTANCE_X = 180; // pixels - insert x-distance between node centers
|
|
||||||
const DISTANCE_Y = 100; // pixels - insert y-distance between node centers
|
|
||||||
|
|
||||||
const STARTING_SUB_INDEX = 900; // max semantic index for starting substitution
|
const STARTING_SUB_INDEX = 900; // max semantic index for starting substitution
|
||||||
|
|
||||||
|
@ -477,100 +469,3 @@ export function getRelocateCandidates(
|
||||||
const unreachable = schema.graph.expandAllOutputs(unreachableBases);
|
const unreachable = schema.graph.expandAllOutputs(unreachableBases);
|
||||||
return addedCst.filter(cst => !unreachable.includes(cst.id));
|
return addedCst.filter(cst => !unreachable.includes(cst.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Calculate insert position for a new {@link IOperation} */
|
|
||||||
export function calculateNewOperationPosition(
|
|
||||||
oss: IOperationSchema,
|
|
||||||
data: ICreateOperationDTO,
|
|
||||||
layout: IOssLayout
|
|
||||||
): Position2D {
|
|
||||||
// TODO: check parent node
|
|
||||||
|
|
||||||
const result = { x: data.position_x, y: data.position_y };
|
|
||||||
const operations = layout.operations;
|
|
||||||
if (operations.length === 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.arguments.length === 0) {
|
|
||||||
let inputsPositions = operations.filter(pos =>
|
|
||||||
oss.operations.find(operation => operation.arguments.length === 0 && operation.id === pos.id)
|
|
||||||
);
|
|
||||||
if (inputsPositions.length === 0) {
|
|
||||||
inputsPositions = operations;
|
|
||||||
}
|
|
||||||
const maxX = Math.max(...inputsPositions.map(node => node.x));
|
|
||||||
const minY = Math.min(...inputsPositions.map(node => node.y));
|
|
||||||
result.x = maxX + DISTANCE_X;
|
|
||||||
result.y = minY;
|
|
||||||
} else {
|
|
||||||
const argNodes = operations.filter(pos => data.arguments.includes(pos.id));
|
|
||||||
const maxY = Math.max(...argNodes.map(node => node.y));
|
|
||||||
const minX = Math.min(...argNodes.map(node => node.x));
|
|
||||||
const maxX = Math.max(...argNodes.map(node => node.x));
|
|
||||||
result.x = Math.ceil((maxX + minX) / 2 / GRID_SIZE) * GRID_SIZE;
|
|
||||||
result.y = maxY + DISTANCE_Y;
|
|
||||||
}
|
|
||||||
|
|
||||||
let flagIntersect = false;
|
|
||||||
do {
|
|
||||||
flagIntersect = operations.some(
|
|
||||||
position => Math.abs(position.x - result.x) < MIN_DISTANCE && Math.abs(position.y - result.y) < MIN_DISTANCE
|
|
||||||
);
|
|
||||||
if (flagIntersect) {
|
|
||||||
result.x += MIN_DISTANCE;
|
|
||||||
result.y += MIN_DISTANCE;
|
|
||||||
}
|
|
||||||
} while (flagIntersect);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Calculate insert position for a new {@link IBlock} */
|
|
||||||
export function calculateNewBlockPosition(data: ICreateBlockDTO, layout: IOssLayout): Rectangle2D {
|
|
||||||
const block_nodes = data.children_blocks
|
|
||||||
.map(id => layout.blocks.find(block => block.id === id))
|
|
||||||
.filter(node => !!node);
|
|
||||||
const operation_nodes = data.children_operations
|
|
||||||
.map(id => layout.operations.find(operation => operation.id === id))
|
|
||||||
.filter(node => !!node);
|
|
||||||
|
|
||||||
if (block_nodes.length === 0 && operation_nodes.length === 0) {
|
|
||||||
return { x: data.position_x, y: data.position_y, width: data.width, height: data.height };
|
|
||||||
}
|
|
||||||
|
|
||||||
let left = undefined;
|
|
||||||
let top = undefined;
|
|
||||||
let right = undefined;
|
|
||||||
let bottom = undefined;
|
|
||||||
|
|
||||||
for (const block of block_nodes) {
|
|
||||||
left = !left ? block.x - MIN_DISTANCE : Math.min(left, block.x - MIN_DISTANCE);
|
|
||||||
top = !top ? block.y - MIN_DISTANCE : Math.min(top, block.y - MIN_DISTANCE);
|
|
||||||
right = !right
|
|
||||||
? Math.max(left + data.width, block.x + block.width + MIN_DISTANCE)
|
|
||||||
: Math.max(right, block.x + block.width + MIN_DISTANCE);
|
|
||||||
bottom = !bottom
|
|
||||||
? Math.max(top + data.height, block.y + block.height + MIN_DISTANCE)
|
|
||||||
: Math.max(bottom, block.y + block.height + MIN_DISTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('left, top, right, bottom', left, top, right, bottom);
|
|
||||||
|
|
||||||
for (const operation of operation_nodes) {
|
|
||||||
left = !left ? operation.x - MIN_DISTANCE : Math.min(left, operation.x - MIN_DISTANCE);
|
|
||||||
top = !top ? operation.y - MIN_DISTANCE : Math.min(top, operation.y - MIN_DISTANCE);
|
|
||||||
right = !right
|
|
||||||
? Math.max(left + data.width, operation.x + OPERATION_NODE_WIDTH + MIN_DISTANCE)
|
|
||||||
: Math.max(right, operation.x + OPERATION_NODE_WIDTH + MIN_DISTANCE);
|
|
||||||
bottom = !bottom
|
|
||||||
? Math.max(top + data.height, operation.y + OPERATION_NODE_HEIGHT + MIN_DISTANCE)
|
|
||||||
: Math.max(bottom, operation.y + OPERATION_NODE_HEIGHT + MIN_DISTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
x: left ?? data.position_x,
|
|
||||||
y: top ?? data.position_y,
|
|
||||||
width: right && left ? right - left : data.width,
|
|
||||||
height: bottom && top ? bottom - top : data.height
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
120
rsconcept/frontend/src/features/oss/models/oss-layout-api.ts
Normal file
120
rsconcept/frontend/src/features/oss/models/oss-layout-api.ts
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
import { type ICreateBlockDTO, type ICreateOperationDTO, type IOssLayout } from '../backend/types';
|
||||||
|
|
||||||
|
import { type IOperationSchema } from './oss';
|
||||||
|
import { type Position2D, type Rectangle2D } from './oss-layout';
|
||||||
|
|
||||||
|
export const GRID_SIZE = 10; // pixels - size of OSS grid
|
||||||
|
const MIN_DISTANCE = 2 * GRID_SIZE; // pixels - minimum distance between nodes
|
||||||
|
const DISTANCE_X = 180; // pixels - insert x-distance between node centers
|
||||||
|
const DISTANCE_Y = 100; // pixels - insert y-distance between node centers
|
||||||
|
|
||||||
|
const OPERATION_NODE_WIDTH = 150;
|
||||||
|
const OPERATION_NODE_HEIGHT = 40;
|
||||||
|
|
||||||
|
/** Layout manipulations for {@link IOperationSchema}. */
|
||||||
|
export class LayoutManager {
|
||||||
|
public oss: IOperationSchema;
|
||||||
|
public layout: IOssLayout;
|
||||||
|
|
||||||
|
constructor(oss: IOperationSchema, layout?: IOssLayout) {
|
||||||
|
this.oss = oss;
|
||||||
|
if (layout) {
|
||||||
|
this.layout = layout;
|
||||||
|
} else {
|
||||||
|
this.layout = this.oss.layout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Calculate insert position for a new {@link IOperation} */
|
||||||
|
calculateNewOperationPosition(data: ICreateOperationDTO): Position2D {
|
||||||
|
// TODO: check parent node
|
||||||
|
|
||||||
|
const result = { x: data.position_x, y: data.position_y };
|
||||||
|
const operations = this.layout.operations;
|
||||||
|
if (operations.length === 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.arguments.length === 0) {
|
||||||
|
let inputsPositions = operations.filter(pos =>
|
||||||
|
this.oss.operations.find(operation => operation.arguments.length === 0 && operation.id === pos.id)
|
||||||
|
);
|
||||||
|
if (inputsPositions.length === 0) {
|
||||||
|
inputsPositions = operations;
|
||||||
|
}
|
||||||
|
const maxX = Math.max(...inputsPositions.map(node => node.x));
|
||||||
|
const minY = Math.min(...inputsPositions.map(node => node.y));
|
||||||
|
result.x = maxX + DISTANCE_X;
|
||||||
|
result.y = minY;
|
||||||
|
} else {
|
||||||
|
const argNodes = operations.filter(pos => data.arguments.includes(pos.id));
|
||||||
|
const maxY = Math.max(...argNodes.map(node => node.y));
|
||||||
|
const minX = Math.min(...argNodes.map(node => node.x));
|
||||||
|
const maxX = Math.max(...argNodes.map(node => node.x));
|
||||||
|
result.x = Math.ceil((maxX + minX) / 2 / GRID_SIZE) * GRID_SIZE;
|
||||||
|
result.y = maxY + DISTANCE_Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
let flagIntersect = false;
|
||||||
|
do {
|
||||||
|
flagIntersect = operations.some(
|
||||||
|
position => Math.abs(position.x - result.x) < MIN_DISTANCE && Math.abs(position.y - result.y) < MIN_DISTANCE
|
||||||
|
);
|
||||||
|
if (flagIntersect) {
|
||||||
|
result.x += MIN_DISTANCE;
|
||||||
|
result.y += MIN_DISTANCE;
|
||||||
|
}
|
||||||
|
} while (flagIntersect);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Calculate insert position for a new {@link IBlock} */
|
||||||
|
calculateNewBlockPosition(data: ICreateBlockDTO): Rectangle2D {
|
||||||
|
const block_nodes = data.children_blocks
|
||||||
|
.map(id => this.layout.blocks.find(block => block.id === id))
|
||||||
|
.filter(node => !!node);
|
||||||
|
const operation_nodes = data.children_operations
|
||||||
|
.map(id => this.layout.operations.find(operation => operation.id === id))
|
||||||
|
.filter(node => !!node);
|
||||||
|
|
||||||
|
if (block_nodes.length === 0 && operation_nodes.length === 0) {
|
||||||
|
return { x: data.position_x, y: data.position_y, width: data.width, height: data.height };
|
||||||
|
}
|
||||||
|
|
||||||
|
let left = undefined;
|
||||||
|
let top = undefined;
|
||||||
|
let right = undefined;
|
||||||
|
let bottom = undefined;
|
||||||
|
|
||||||
|
for (const block of block_nodes) {
|
||||||
|
left = !left ? block.x - MIN_DISTANCE : Math.min(left, block.x - MIN_DISTANCE);
|
||||||
|
top = !top ? block.y - MIN_DISTANCE : Math.min(top, block.y - MIN_DISTANCE);
|
||||||
|
right = !right
|
||||||
|
? Math.max(left + data.width, block.x + block.width + MIN_DISTANCE)
|
||||||
|
: Math.max(right, block.x + block.width + MIN_DISTANCE);
|
||||||
|
bottom = !bottom
|
||||||
|
? Math.max(top + data.height, block.y + block.height + MIN_DISTANCE)
|
||||||
|
: Math.max(bottom, block.y + block.height + MIN_DISTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('left, top, right, bottom', left, top, right, bottom);
|
||||||
|
|
||||||
|
for (const operation of operation_nodes) {
|
||||||
|
left = !left ? operation.x - MIN_DISTANCE : Math.min(left, operation.x - MIN_DISTANCE);
|
||||||
|
top = !top ? operation.y - MIN_DISTANCE : Math.min(top, operation.y - MIN_DISTANCE);
|
||||||
|
right = !right
|
||||||
|
? Math.max(left + data.width, operation.x + OPERATION_NODE_WIDTH + MIN_DISTANCE)
|
||||||
|
: Math.max(right, operation.x + OPERATION_NODE_WIDTH + MIN_DISTANCE);
|
||||||
|
bottom = !bottom
|
||||||
|
? Math.max(top + data.height, operation.y + OPERATION_NODE_HEIGHT + MIN_DISTANCE)
|
||||||
|
: Math.max(bottom, operation.y + OPERATION_NODE_HEIGHT + MIN_DISTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: left ?? data.position_x,
|
||||||
|
y: top ?? data.position_y,
|
||||||
|
width: right && left ? right - left : data.width,
|
||||||
|
height: bottom && top ? bottom - top : data.height
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,11 +2,10 @@
|
||||||
|
|
||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
|
|
||||||
import { isOperation } from '@/features/oss/models/oss-api';
|
|
||||||
|
|
||||||
import { Dropdown } from '@/components/dropdown';
|
import { Dropdown } from '@/components/dropdown';
|
||||||
|
|
||||||
import { type IBlock, type IOperation, type IOssItem } from '../../../../models/oss';
|
import { type IBlock, type IOperation, type IOssItem } from '../../../../models/oss';
|
||||||
|
import { isOperation } from '../../../../models/oss-api';
|
||||||
|
|
||||||
import { MenuBlock } from './menu-block';
|
import { MenuBlock } from './menu-block';
|
||||||
import { MenuOperation } from './menu-operation';
|
import { MenuOperation } from './menu-operation';
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useDeleteBlock } from '@/features/oss/backend/use-delete-block';
|
|
||||||
|
|
||||||
import { DropdownButton } from '@/components/dropdown';
|
import { DropdownButton } from '@/components/dropdown';
|
||||||
import { IconDestroy, IconEdit2 } from '@/components/icons';
|
import { IconDestroy, IconEdit2 } from '@/components/icons';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
|
import { useDeleteBlock } from '../../../../backend/use-delete-block';
|
||||||
import { useMutatingOss } from '../../../../backend/use-mutating-oss';
|
import { useMutatingOss } from '../../../../backend/use-mutating-oss';
|
||||||
import { type IBlock } from '../../../../models/oss';
|
import { type IBlock } from '../../../../models/oss';
|
||||||
|
import { LayoutManager } from '../../../../models/oss-layout-api';
|
||||||
import { useOssEdit } from '../../oss-edit-context';
|
import { useOssEdit } from '../../oss-edit-context';
|
||||||
import { useGetLayout } from '../use-get-layout';
|
import { useGetLayout } from '../use-get-layout';
|
||||||
|
|
||||||
|
@ -30,9 +30,8 @@ export function MenuBlock({ block, onHide }: MenuBlockProps) {
|
||||||
}
|
}
|
||||||
onHide();
|
onHide();
|
||||||
showEditBlock({
|
showEditBlock({
|
||||||
oss: schema,
|
manager: new LayoutManager(schema, getLayout()),
|
||||||
target: block,
|
target: block
|
||||||
layout: getLayout()
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@ import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import { urls, useConceptNavigation } from '@/app';
|
import { urls, useConceptNavigation } from '@/app';
|
||||||
import { useLibrary } from '@/features/library/backend/use-library';
|
import { useLibrary } from '@/features/library/backend/use-library';
|
||||||
import { useCreateInput } from '@/features/oss/backend/use-create-input';
|
|
||||||
import { useExecuteOperation } from '@/features/oss/backend/use-execute-operation';
|
|
||||||
|
|
||||||
import { DropdownButton } from '@/components/dropdown';
|
import { DropdownButton } from '@/components/dropdown';
|
||||||
import {
|
import {
|
||||||
|
@ -21,8 +19,11 @@ import { errorMsg } from '@/utils/labels';
|
||||||
import { prepareTooltip } from '@/utils/utils';
|
import { prepareTooltip } from '@/utils/utils';
|
||||||
|
|
||||||
import { OperationType } from '../../../../backend/types';
|
import { OperationType } from '../../../../backend/types';
|
||||||
|
import { useCreateInput } from '../../../../backend/use-create-input';
|
||||||
|
import { useExecuteOperation } from '../../../../backend/use-execute-operation';
|
||||||
import { useMutatingOss } from '../../../../backend/use-mutating-oss';
|
import { useMutatingOss } from '../../../../backend/use-mutating-oss';
|
||||||
import { type IOperation } from '../../../../models/oss';
|
import { type IOperation } from '../../../../models/oss';
|
||||||
|
import { LayoutManager } from '../../../../models/oss-layout-api';
|
||||||
import { useOssEdit } from '../../oss-edit-context';
|
import { useOssEdit } from '../../oss-edit-context';
|
||||||
import { useGetLayout } from '../use-get-layout';
|
import { useGetLayout } from '../use-get-layout';
|
||||||
|
|
||||||
|
@ -93,9 +94,8 @@ export function MenuOperation({ operation, onHide }: MenuOperationProps) {
|
||||||
}
|
}
|
||||||
onHide();
|
onHide();
|
||||||
showEditOperation({
|
showEditOperation({
|
||||||
oss: schema,
|
manager: new LayoutManager(schema, getLayout()),
|
||||||
target: operation,
|
target: operation
|
||||||
layout: getLayout()
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,12 @@
|
||||||
import { NodeResizeControl } from 'reactflow';
|
import { NodeResizeControl } from 'reactflow';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import { useOperationTooltipStore } from '@/features/oss/stores/operation-tooltip';
|
|
||||||
import { useOSSGraphStore } from '@/features/oss/stores/oss-graph';
|
|
||||||
|
|
||||||
import { IconResize } from '@/components/icons';
|
import { IconResize } from '@/components/icons';
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globalIDs } from '@/utils/constants';
|
||||||
|
|
||||||
import { type BlockInternalNode } from '../../../../models/oss-layout';
|
import { type BlockInternalNode } from '../../../../models/oss-layout';
|
||||||
|
import { useOperationTooltipStore } from '../../../../stores/operation-tooltip';
|
||||||
|
import { useOSSGraphStore } from '../../../../stores/oss-graph';
|
||||||
import { useOssEdit } from '../../oss-edit-context';
|
import { useOssEdit } from '../../oss-edit-context';
|
||||||
import { useOssFlow } from '../oss-flow-context';
|
import { useOssFlow } from '../oss-flow-context';
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import { useOSSGraphStore } from '@/features/oss/stores/oss-graph';
|
|
||||||
|
|
||||||
import { IconConsolidation, IconRSForm } from '@/components/icons';
|
import { IconConsolidation, IconRSForm } from '@/components/icons';
|
||||||
import { cn } from '@/components/utils';
|
import { cn } from '@/components/utils';
|
||||||
import { Indicator } from '@/components/view';
|
import { Indicator } from '@/components/view';
|
||||||
|
@ -12,11 +10,9 @@ import { globalIDs } from '@/utils/constants';
|
||||||
import { OperationType } from '../../../../backend/types';
|
import { OperationType } from '../../../../backend/types';
|
||||||
import { type OperationInternalNode } from '../../../../models/oss-layout';
|
import { type OperationInternalNode } from '../../../../models/oss-layout';
|
||||||
import { useOperationTooltipStore } from '../../../../stores/operation-tooltip';
|
import { useOperationTooltipStore } from '../../../../stores/operation-tooltip';
|
||||||
|
import { useOSSGraphStore } from '../../../../stores/oss-graph';
|
||||||
import { useOssEdit } from '../../oss-edit-context';
|
import { useOssEdit } from '../../oss-edit-context';
|
||||||
|
|
||||||
export const OPERATION_NODE_WIDTH = 150;
|
|
||||||
export const OPERATION_NODE_HEIGHT = 40;
|
|
||||||
|
|
||||||
// characters - threshold for long labels - small font
|
// characters - threshold for long labels - small font
|
||||||
const LONG_LABEL_CHARS = 14;
|
const LONG_LABEL_CHARS = 14;
|
||||||
|
|
||||||
|
|
|
@ -13,20 +13,19 @@ import {
|
||||||
} from 'reactflow';
|
} from 'reactflow';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import { useDeleteBlock } from '@/features/oss/backend/use-delete-block';
|
|
||||||
import { useMoveItems } from '@/features/oss/backend/use-move-items';
|
|
||||||
import { type IOperationSchema } from '@/features/oss/models/oss';
|
|
||||||
|
|
||||||
import { useThrottleCallback } from '@/hooks/use-throttle-callback';
|
import { useThrottleCallback } from '@/hooks/use-throttle-callback';
|
||||||
import { useMainHeight } from '@/stores/app-layout';
|
import { useMainHeight } from '@/stores/app-layout';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
import { PARAMETER } from '@/utils/constants';
|
import { PARAMETER } from '@/utils/constants';
|
||||||
import { promptText } from '@/utils/labels';
|
import { promptText } from '@/utils/labels';
|
||||||
|
|
||||||
|
import { useDeleteBlock } from '../../../backend/use-delete-block';
|
||||||
|
import { useMoveItems } from '../../../backend/use-move-items';
|
||||||
import { useMutatingOss } from '../../../backend/use-mutating-oss';
|
import { useMutatingOss } from '../../../backend/use-mutating-oss';
|
||||||
import { useUpdateLayout } from '../../../backend/use-update-layout';
|
import { useUpdateLayout } from '../../../backend/use-update-layout';
|
||||||
import { GRID_SIZE } from '../../../models/oss-api';
|
import { type IOperationSchema } from '../../../models/oss';
|
||||||
import { type OssNode, type Position2D } from '../../../models/oss-layout';
|
import { type OssNode, type Position2D } from '../../../models/oss-layout';
|
||||||
|
import { GRID_SIZE, LayoutManager } from '../../../models/oss-layout-api';
|
||||||
import { useOperationTooltipStore } from '../../../stores/operation-tooltip';
|
import { useOperationTooltipStore } from '../../../stores/operation-tooltip';
|
||||||
import { useOSSGraphStore } from '../../../stores/oss-graph';
|
import { useOSSGraphStore } from '../../../stores/oss-graph';
|
||||||
import { useOssEdit } from '../oss-edit-context';
|
import { useOssEdit } from '../oss-edit-context';
|
||||||
|
@ -153,10 +152,9 @@ export function OssFlow() {
|
||||||
function handleCreateOperation() {
|
function handleCreateOperation() {
|
||||||
const targetPosition = screenToFlowPosition({ x: window.innerWidth / 2, y: window.innerHeight / 2 });
|
const targetPosition = screenToFlowPosition({ x: window.innerWidth / 2, y: window.innerHeight / 2 });
|
||||||
showCreateOperation({
|
showCreateOperation({
|
||||||
oss: schema,
|
manager: new LayoutManager(schema, getLayout()),
|
||||||
defaultX: targetPosition.x,
|
defaultX: targetPosition.x,
|
||||||
defaultY: targetPosition.y,
|
defaultY: targetPosition.y,
|
||||||
layout: getLayout(),
|
|
||||||
initialInputs: selected.filter(id => id > 0),
|
initialInputs: selected.filter(id => id > 0),
|
||||||
initialParent: extractSingleBlock(selected),
|
initialParent: extractSingleBlock(selected),
|
||||||
onCreate: () =>
|
onCreate: () =>
|
||||||
|
@ -167,10 +165,9 @@ export function OssFlow() {
|
||||||
function handleCreateBlock() {
|
function handleCreateBlock() {
|
||||||
const targetPosition = screenToFlowPosition({ x: window.innerWidth / 2, y: window.innerHeight / 2 });
|
const targetPosition = screenToFlowPosition({ x: window.innerWidth / 2, y: window.innerHeight / 2 });
|
||||||
showCreateBlock({
|
showCreateBlock({
|
||||||
oss: schema,
|
manager: new LayoutManager(schema, getLayout()),
|
||||||
defaultX: targetPosition.x,
|
defaultX: targetPosition.x,
|
||||||
defaultY: targetPosition.y,
|
defaultY: targetPosition.y,
|
||||||
layout: getLayout(),
|
|
||||||
initialInputs: selected,
|
initialInputs: selected,
|
||||||
onCreate: () =>
|
onCreate: () =>
|
||||||
setTimeout(() => fitView({ duration: PARAMETER.zoomDuration, padding: VIEW_PADDING }), PARAMETER.refreshTimeout)
|
setTimeout(() => fitView({ duration: PARAMETER.zoomDuration, padding: VIEW_PADDING }), PARAMETER.refreshTimeout)
|
||||||
|
@ -226,9 +223,8 @@ export function OssFlow() {
|
||||||
const block = schema.blockByID.get(-Number(node.id));
|
const block = schema.blockByID.get(-Number(node.id));
|
||||||
if (block) {
|
if (block) {
|
||||||
showEditBlock({
|
showEditBlock({
|
||||||
oss: schema,
|
manager: new LayoutManager(schema, getLayout()),
|
||||||
target: block,
|
target: block
|
||||||
layout: getLayout()
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -5,8 +5,6 @@ import { useReactFlow } from 'reactflow';
|
||||||
|
|
||||||
import { HelpTopic } from '@/features/help';
|
import { HelpTopic } from '@/features/help';
|
||||||
import { BadgeHelp } from '@/features/help/components';
|
import { BadgeHelp } from '@/features/help/components';
|
||||||
import { useExecuteOperation } from '@/features/oss/backend/use-execute-operation';
|
|
||||||
import { useUpdateLayout } from '@/features/oss/backend/use-update-layout';
|
|
||||||
|
|
||||||
import { MiniButton } from '@/components/control';
|
import { MiniButton } from '@/components/control';
|
||||||
import {
|
import {
|
||||||
|
@ -28,7 +26,10 @@ import { PARAMETER } from '@/utils/constants';
|
||||||
import { prepareTooltip } from '@/utils/utils';
|
import { prepareTooltip } from '@/utils/utils';
|
||||||
|
|
||||||
import { OperationType } from '../../../backend/types';
|
import { OperationType } from '../../../backend/types';
|
||||||
|
import { useExecuteOperation } from '../../../backend/use-execute-operation';
|
||||||
import { useMutatingOss } from '../../../backend/use-mutating-oss';
|
import { useMutatingOss } from '../../../backend/use-mutating-oss';
|
||||||
|
import { useUpdateLayout } from '../../../backend/use-update-layout';
|
||||||
|
import { LayoutManager } from '../../../models/oss-layout-api';
|
||||||
import { useOssEdit } from '../oss-edit-context';
|
import { useOssEdit } from '../oss-edit-context';
|
||||||
|
|
||||||
import { VIEW_PADDING } from './oss-flow';
|
import { VIEW_PADDING } from './oss-flow';
|
||||||
|
@ -114,15 +115,13 @@ export function ToolbarOssGraph({
|
||||||
function handleEditItem() {
|
function handleEditItem() {
|
||||||
if (selectedOperation) {
|
if (selectedOperation) {
|
||||||
showEditOperation({
|
showEditOperation({
|
||||||
oss: schema,
|
manager: new LayoutManager(schema, getLayout()),
|
||||||
target: selectedOperation,
|
target: selectedOperation
|
||||||
layout: getLayout()
|
|
||||||
});
|
});
|
||||||
} else if (selectedBlock) {
|
} else if (selectedBlock) {
|
||||||
showEditBlock({
|
showEditBlock({
|
||||||
oss: schema,
|
manager: new LayoutManager(schema, getLayout()),
|
||||||
target: selectedBlock,
|
target: selectedBlock
|
||||||
layout: getLayout()
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import { type Node, useReactFlow } from 'reactflow';
|
import { type Node, useReactFlow } from 'reactflow';
|
||||||
|
|
||||||
import { type IOssLayout } from '@/features/oss/backend/types';
|
import { type IOssLayout } from '../../../backend/types';
|
||||||
import { type IOperationSchema } from '@/features/oss/models/oss';
|
import { type IOperationSchema } from '../../../models/oss';
|
||||||
import { type Position2D } from '@/features/oss/models/oss-layout';
|
import { type Position2D } from '../../../models/oss-layout';
|
||||||
|
|
||||||
import { useOssEdit } from '../oss-edit-context';
|
import { useOssEdit } from '../oss-edit-context';
|
||||||
|
|
||||||
import { BLOCK_NODE_MIN_HEIGHT, BLOCK_NODE_MIN_WIDTH } from './graph/block-node';
|
import { BLOCK_NODE_MIN_HEIGHT, BLOCK_NODE_MIN_WIDTH } from './graph/block-node';
|
||||||
|
|
|
@ -3,7 +3,6 @@ import clsx from 'clsx';
|
||||||
import { HelpTopic } from '@/features/help';
|
import { HelpTopic } from '@/features/help';
|
||||||
import { BadgeHelp } from '@/features/help/components';
|
import { BadgeHelp } from '@/features/help/components';
|
||||||
import { MiniSelectorOSS } from '@/features/library/components';
|
import { MiniSelectorOSS } from '@/features/library/components';
|
||||||
import { CstType } from '@/features/rsform';
|
|
||||||
|
|
||||||
import { MiniButton } from '@/components/control';
|
import { MiniButton } from '@/components/control';
|
||||||
import { Dropdown, DropdownButton, useDropdown } from '@/components/dropdown';
|
import { Dropdown, DropdownButton, useDropdown } from '@/components/dropdown';
|
||||||
|
@ -19,6 +18,7 @@ import {
|
||||||
import { prefixes } from '@/utils/constants';
|
import { prefixes } from '@/utils/constants';
|
||||||
import { prepareTooltip } from '@/utils/utils';
|
import { prepareTooltip } from '@/utils/utils';
|
||||||
|
|
||||||
|
import { CstType } from '../../../backend/types';
|
||||||
import { useMutatingRSForm } from '../../../backend/use-mutating-rsform';
|
import { useMutatingRSForm } from '../../../backend/use-mutating-rsform';
|
||||||
import { IconCstType } from '../../../components/icon-cst-type';
|
import { IconCstType } from '../../../components/icon-cst-type';
|
||||||
import { getCstTypeShortcut, labelCstType } from '../../../labels';
|
import { getCstTypeShortcut, labelCstType } from '../../../labels';
|
||||||
|
|
|
@ -3,12 +3,11 @@
|
||||||
import { Handle, Position } from 'reactflow';
|
import { Handle, Position } from 'reactflow';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import { labelCstTypification } from '@/features/rsform/labels';
|
|
||||||
|
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
import { APP_COLORS } from '@/styling/colors';
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globalIDs } from '@/utils/constants';
|
||||||
|
|
||||||
import { colorBgGraphNode } from '../../../../colors';
|
import { colorBgGraphNode } from '../../../../colors';
|
||||||
|
import { labelCstTypification } from '../../../../labels';
|
||||||
import { type IConstituenta } from '../../../../models/rsform';
|
import { type IConstituenta } from '../../../../models/rsform';
|
||||||
import { useTermGraphStore } from '../../../../stores/term-graph';
|
import { useTermGraphStore } from '../../../../stores/term-graph';
|
||||||
import { useRSEdit } from '../../rsedit-context';
|
import { useRSEdit } from '../../rsedit-context';
|
||||||
|
|
Loading…
Reference in New Issue
Block a user