B: Fix contextmenu animations
This commit is contained in:
parent
751d73a880
commit
7792a82bf7
|
@ -1,6 +1,6 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useRef } from 'react';
|
||||||
|
|
||||||
import { useMutatingOss } from '@/backend/oss/useMutatingOss';
|
import { useMutatingOss } from '@/backend/oss/useMutatingOss';
|
||||||
import {
|
import {
|
||||||
|
@ -22,12 +22,13 @@ import { prepareTooltip } from '@/utils/labels';
|
||||||
import { useOssEdit } from '../OssEditContext';
|
import { useOssEdit } from '../OssEditContext';
|
||||||
|
|
||||||
export interface ContextMenuData {
|
export interface ContextMenuData {
|
||||||
operation: IOperation;
|
operation?: IOperation;
|
||||||
cursorX: number;
|
cursorX: number;
|
||||||
cursorY: number;
|
cursorY: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NodeContextMenuProps extends ContextMenuData {
|
interface NodeContextMenuProps extends ContextMenuData {
|
||||||
|
isOpen: boolean;
|
||||||
onHide: () => void;
|
onHide: () => void;
|
||||||
onDelete: (target: OperationID) => void;
|
onDelete: (target: OperationID) => void;
|
||||||
onCreateInput: (target: OperationID) => void;
|
onCreateInput: (target: OperationID) => void;
|
||||||
|
@ -38,6 +39,7 @@ interface NodeContextMenuProps extends ContextMenuData {
|
||||||
}
|
}
|
||||||
|
|
||||||
function NodeContextMenu({
|
function NodeContextMenu({
|
||||||
|
isOpen,
|
||||||
operation,
|
operation,
|
||||||
cursorX,
|
cursorX,
|
||||||
cursorY,
|
cursorY,
|
||||||
|
@ -52,10 +54,9 @@ function NodeContextMenu({
|
||||||
const controller = useOssEdit();
|
const controller = useOssEdit();
|
||||||
const isProcessing = useMutatingOss();
|
const isProcessing = useMutatingOss();
|
||||||
|
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
const readyForSynthesis = (() => {
|
const readyForSynthesis = (() => {
|
||||||
if (operation.operation_type !== OperationType.SYNTHESIS) {
|
if (operation?.operation_type !== OperationType.SYNTHESIS) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (operation.result) {
|
if (operation.result) {
|
||||||
|
@ -75,47 +76,40 @@ function NodeContextMenu({
|
||||||
return true;
|
return true;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
function handleHide() {
|
useClickedOutside(isOpen, ref, onHide);
|
||||||
setIsOpen(false);
|
|
||||||
onHide();
|
|
||||||
}
|
|
||||||
|
|
||||||
useClickedOutside(isOpen, ref, handleHide);
|
|
||||||
|
|
||||||
useEffect(() => setIsOpen(true), []);
|
|
||||||
|
|
||||||
function handleOpenSchema() {
|
function handleOpenSchema() {
|
||||||
controller.navigateOperationSchema(operation.id);
|
if (operation) controller.navigateOperationSchema(operation.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleEditSchema() {
|
function handleEditSchema() {
|
||||||
handleHide();
|
onHide();
|
||||||
onEditSchema(operation.id);
|
if (operation) onEditSchema(operation.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleEditOperation() {
|
function handleEditOperation() {
|
||||||
handleHide();
|
onHide();
|
||||||
onEditOperation(operation.id);
|
if (operation) onEditOperation(operation.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDeleteOperation() {
|
function handleDeleteOperation() {
|
||||||
handleHide();
|
onHide();
|
||||||
onDelete(operation.id);
|
if (operation) onDelete(operation.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCreateSchema() {
|
function handleCreateSchema() {
|
||||||
handleHide();
|
onHide();
|
||||||
onCreateInput(operation.id);
|
if (operation) onCreateInput(operation.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleRunSynthesis() {
|
function handleRunSynthesis() {
|
||||||
handleHide();
|
onHide();
|
||||||
onExecuteOperation(operation.id);
|
if (operation) onExecuteOperation(operation.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleRelocateConstituents() {
|
function handleRelocateConstituents() {
|
||||||
handleHide();
|
onHide();
|
||||||
onRelocateConstituents(operation.id);
|
if (operation) onRelocateConstituents(operation.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -133,7 +127,7 @@ function NodeContextMenu({
|
||||||
onClick={handleEditOperation}
|
onClick={handleEditOperation}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{operation.result ? (
|
{operation?.result ? (
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
text='Открыть схему'
|
text='Открыть схему'
|
||||||
titleHtml={prepareTooltip('Открыть привязанную КС', 'Двойной клик')}
|
titleHtml={prepareTooltip('Открыть привязанную КС', 'Двойной клик')}
|
||||||
|
@ -142,7 +136,7 @@ function NodeContextMenu({
|
||||||
onClick={handleOpenSchema}
|
onClick={handleOpenSchema}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{controller.isMutable && !operation.result && operation.operation_type === OperationType.INPUT ? (
|
{controller.isMutable && !operation?.result && operation?.operation_type === OperationType.INPUT ? (
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
text='Создать схему'
|
text='Создать схему'
|
||||||
title='Создать пустую схему для загрузки'
|
title='Создать пустую схему для загрузки'
|
||||||
|
@ -151,16 +145,16 @@ function NodeContextMenu({
|
||||||
onClick={handleCreateSchema}
|
onClick={handleCreateSchema}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{controller.isMutable && operation.operation_type === OperationType.INPUT ? (
|
{controller.isMutable && operation?.operation_type === OperationType.INPUT ? (
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
text={!operation.result ? 'Загрузить схему' : 'Изменить схему'}
|
text={!operation?.result ? 'Загрузить схему' : 'Изменить схему'}
|
||||||
title='Выбрать схему для загрузки'
|
title='Выбрать схему для загрузки'
|
||||||
icon={<IconConnect size='1rem' className='icon-primary' />}
|
icon={<IconConnect size='1rem' className='icon-primary' />}
|
||||||
disabled={isProcessing}
|
disabled={isProcessing}
|
||||||
onClick={handleEditSchema}
|
onClick={handleEditSchema}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{controller.isMutable && !operation.result && operation.operation_type === OperationType.SYNTHESIS ? (
|
{controller.isMutable && !operation?.result && operation?.operation_type === OperationType.SYNTHESIS ? (
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
text='Активировать синтез'
|
text='Активировать синтез'
|
||||||
titleHtml={
|
titleHtml={
|
||||||
|
@ -174,7 +168,7 @@ function NodeContextMenu({
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{controller.isMutable && operation.result ? (
|
{controller.isMutable && operation?.result ? (
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
text='Конституенты'
|
text='Конституенты'
|
||||||
titleHtml='Перенос конституент</br>между схемами'
|
titleHtml='Перенос конституент</br>между схемами'
|
||||||
|
@ -187,7 +181,7 @@ function NodeContextMenu({
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
text='Удалить операцию'
|
text='Удалить операцию'
|
||||||
icon={<IconDestroy size='1rem' className='icon-red' />}
|
icon={<IconDestroy size='1rem' className='icon-red' />}
|
||||||
disabled={!controller.isMutable || isProcessing || !controller.canDelete(operation.id)}
|
disabled={!controller.isMutable || isProcessing || !operation || !controller.canDelete(operation.id)}
|
||||||
onClick={handleDeleteOperation}
|
onClick={handleDeleteOperation}
|
||||||
/>
|
/>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
|
|
@ -63,7 +63,8 @@ function OssFlow() {
|
||||||
const [nodes, setNodes, onNodesChange] = useNodesState([]);
|
const [nodes, setNodes, onNodesChange] = useNodesState([]);
|
||||||
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
||||||
const [toggleReset, setToggleReset] = useState(false);
|
const [toggleReset, setToggleReset] = useState(false);
|
||||||
const [menuProps, setMenuProps] = useState<ContextMenuData | undefined>(undefined);
|
const [menuProps, setMenuProps] = useState<ContextMenuData>({ operation: undefined, cursorX: 0, cursorY: 0 });
|
||||||
|
const [isContextMenuOpen, setIsContextMenuOpen] = useState(false);
|
||||||
|
|
||||||
function onSelectionChange({ nodes }: { nodes: Node[] }) {
|
function onSelectionChange({ nodes }: { nodes: Node[] }) {
|
||||||
const ids = nodes.map(node => Number(node.id));
|
const ids = nodes.map(node => Number(node.id));
|
||||||
|
@ -243,12 +244,13 @@ function OssFlow() {
|
||||||
cursorX: event.clientX,
|
cursorX: event.clientX,
|
||||||
cursorY: event.clientY
|
cursorY: event.clientY
|
||||||
});
|
});
|
||||||
|
setIsContextMenuOpen(true);
|
||||||
controller.setShowTooltip(false);
|
controller.setShowTooltip(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleContextMenuHide() {
|
function handleContextMenuHide() {
|
||||||
controller.setShowTooltip(true);
|
controller.setShowTooltip(true);
|
||||||
setMenuProps(undefined);
|
setIsContextMenuOpen(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCanvasClick() {
|
function handleCanvasClick() {
|
||||||
|
@ -308,6 +310,7 @@ function OssFlow() {
|
||||||
</Overlay>
|
</Overlay>
|
||||||
{menuProps ? (
|
{menuProps ? (
|
||||||
<NodeContextMenu
|
<NodeContextMenu
|
||||||
|
isOpen={isContextMenuOpen}
|
||||||
onHide={handleContextMenuHide}
|
onHide={handleContextMenuHide}
|
||||||
onDelete={handleDeleteOperation}
|
onDelete={handleDeleteOperation}
|
||||||
onCreateInput={handleInputCreate}
|
onCreateInput={handleInputCreate}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user