2024-07-26 17:30:37 +03:00
|
|
|
|
'use client';
|
|
|
|
|
|
|
|
|
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
|
|
|
import { toast } from 'react-toastify';
|
|
|
|
|
|
2024-07-28 01:30:00 +03:00
|
|
|
|
import { IconConnect, IconDestroy, IconEdit2, IconExecute, IconNewItem, IconRSForm } from '@/components/Icons';
|
2024-07-26 17:30:37 +03:00
|
|
|
|
import Dropdown from '@/components/ui/Dropdown';
|
|
|
|
|
import DropdownButton from '@/components/ui/DropdownButton';
|
|
|
|
|
import useClickedOutside from '@/hooks/useClickedOutside';
|
|
|
|
|
import { IOperation, OperationID, OperationType } from '@/models/oss';
|
|
|
|
|
import { PARAMETER } from '@/utils/constants';
|
|
|
|
|
import { prepareTooltip } from '@/utils/labels';
|
|
|
|
|
|
|
|
|
|
import { useOssEdit } from '../OssEditContext';
|
|
|
|
|
|
|
|
|
|
export interface ContextMenuData {
|
|
|
|
|
operation: IOperation;
|
|
|
|
|
cursorX: number;
|
|
|
|
|
cursorY: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface NodeContextMenuProps extends ContextMenuData {
|
|
|
|
|
onHide: () => void;
|
|
|
|
|
onDelete: (target: OperationID) => void;
|
2024-07-28 00:37:33 +03:00
|
|
|
|
onCreateInput: (target: OperationID) => void;
|
2024-07-26 17:30:37 +03:00
|
|
|
|
}
|
|
|
|
|
|
2024-07-28 00:37:33 +03:00
|
|
|
|
function NodeContextMenu({ operation, cursorX, cursorY, onHide, onDelete, onCreateInput }: NodeContextMenuProps) {
|
2024-07-26 17:30:37 +03:00
|
|
|
|
const controller = useOssEdit();
|
|
|
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
|
|
|
const ref = useRef(null);
|
|
|
|
|
|
|
|
|
|
const handleHide = useCallback(() => {
|
|
|
|
|
setIsOpen(false);
|
|
|
|
|
onHide();
|
|
|
|
|
}, [onHide]);
|
|
|
|
|
|
|
|
|
|
useClickedOutside({ ref, callback: handleHide });
|
|
|
|
|
|
|
|
|
|
useEffect(() => setIsOpen(true), []);
|
|
|
|
|
|
|
|
|
|
const handleOpenSchema = () => {
|
|
|
|
|
controller.openOperationSchema(operation.id);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleEditSchema = () => {
|
|
|
|
|
toast.error('Not implemented');
|
|
|
|
|
handleHide();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleEditOperation = () => {
|
|
|
|
|
toast.error('Not implemented');
|
|
|
|
|
handleHide();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleDeleteOperation = () => {
|
|
|
|
|
handleHide();
|
|
|
|
|
onDelete(operation.id);
|
|
|
|
|
};
|
|
|
|
|
|
2024-07-28 00:37:33 +03:00
|
|
|
|
const handleCreateSchema = () => {
|
|
|
|
|
handleHide();
|
|
|
|
|
onCreateInput(operation.id);
|
|
|
|
|
};
|
|
|
|
|
|
2024-07-28 01:30:00 +03:00
|
|
|
|
const handleRunSynthesis = () => {
|
|
|
|
|
toast.error('Not implemented');
|
|
|
|
|
handleHide();
|
|
|
|
|
};
|
|
|
|
|
|
2024-07-26 17:30:37 +03:00
|
|
|
|
return (
|
|
|
|
|
<div ref={ref} className='absolute' style={{ top: cursorY, left: cursorX, width: 10, height: 10 }}>
|
|
|
|
|
<Dropdown isOpen={isOpen} stretchLeft={cursorX >= window.innerWidth - PARAMETER.ossContextMenuWidth}>
|
|
|
|
|
<DropdownButton
|
2024-07-28 01:30:00 +03:00
|
|
|
|
text='Редактировать'
|
2024-07-26 17:30:37 +03:00
|
|
|
|
titleHtml={prepareTooltip('Редактировать операцию', 'Ctrl + клик')}
|
|
|
|
|
icon={<IconEdit2 size='1rem' className='icon-primary' />}
|
|
|
|
|
disabled={controller.isProcessing}
|
|
|
|
|
onClick={handleEditOperation}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
{operation.result ? (
|
|
|
|
|
<DropdownButton
|
|
|
|
|
text='Открыть схему'
|
|
|
|
|
title='Открыть привязанную КС'
|
|
|
|
|
icon={<IconRSForm size='1rem' className='icon-green' />}
|
|
|
|
|
disabled={controller.isProcessing}
|
|
|
|
|
onClick={handleOpenSchema}
|
|
|
|
|
/>
|
|
|
|
|
) : null}
|
|
|
|
|
{controller.isMutable && !operation.result && operation.operation_type === OperationType.INPUT ? (
|
|
|
|
|
<DropdownButton
|
|
|
|
|
text='Создать схему'
|
|
|
|
|
title='Создать пустую схему для загрузки'
|
|
|
|
|
icon={<IconNewItem size='1rem' className='icon-green' />}
|
|
|
|
|
disabled={controller.isProcessing}
|
2024-07-28 00:37:33 +03:00
|
|
|
|
onClick={handleCreateSchema}
|
2024-07-26 17:30:37 +03:00
|
|
|
|
/>
|
|
|
|
|
) : null}
|
2024-07-28 01:30:00 +03:00
|
|
|
|
{controller.isMutable && !operation.result && operation.operation_type === OperationType.INPUT ? (
|
2024-07-26 17:30:37 +03:00
|
|
|
|
<DropdownButton
|
2024-07-28 01:30:00 +03:00
|
|
|
|
text='Загрузить схему'
|
2024-07-26 17:30:37 +03:00
|
|
|
|
title='Выбрать схему для загрузки'
|
2024-07-28 01:30:00 +03:00
|
|
|
|
icon={<IconConnect size='1rem' className='icon-primary' />}
|
2024-07-26 17:30:37 +03:00
|
|
|
|
disabled={controller.isProcessing}
|
|
|
|
|
onClick={handleEditSchema}
|
|
|
|
|
/>
|
|
|
|
|
) : null}
|
2024-07-28 01:30:00 +03:00
|
|
|
|
{controller.isMutable && !operation.result && operation.operation_type === OperationType.SYNTHESIS ? (
|
|
|
|
|
<DropdownButton
|
|
|
|
|
text='Выполнить синтез'
|
|
|
|
|
title='Выполнить операцию и получить синтезированную КС'
|
|
|
|
|
icon={<IconExecute size='1rem' className='icon-green' />}
|
|
|
|
|
disabled={controller.isProcessing}
|
|
|
|
|
onClick={handleRunSynthesis}
|
|
|
|
|
/>
|
|
|
|
|
) : null}
|
2024-07-26 17:30:37 +03:00
|
|
|
|
|
|
|
|
|
<DropdownButton
|
|
|
|
|
text='Удалить операцию'
|
|
|
|
|
icon={<IconDestroy size='1rem' className='icon-red' />}
|
|
|
|
|
disabled={!controller.isMutable || controller.isProcessing}
|
|
|
|
|
onClick={handleDeleteOperation}
|
|
|
|
|
/>
|
|
|
|
|
</Dropdown>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default NodeContextMenu;
|