diff --git a/rsconcept/frontend/src/features/help/items/ui/help-oss-graph.tsx b/rsconcept/frontend/src/features/help/items/ui/help-oss-graph.tsx
index a9dba114..bb916b6d 100644
--- a/rsconcept/frontend/src/features/help/items/ui/help-oss-graph.tsx
+++ b/rsconcept/frontend/src/features/help/items/ui/help-oss-graph.tsx
@@ -107,7 +107,7 @@ export function HelpOssGraph() {
Space – перемещение экрана
- Shift – перемещение выделенных элементов в границах родителя
+ Shift – перемещение в границах блока
diff --git a/rsconcept/frontend/src/features/oss/pages/oss-page/editor-oss-graph/graph/node-core.tsx b/rsconcept/frontend/src/features/oss/pages/oss-page/editor-oss-graph/graph/node-core.tsx
index de087696..6be90695 100644
--- a/rsconcept/frontend/src/features/oss/pages/oss-page/editor-oss-graph/graph/node-core.tsx
+++ b/rsconcept/frontend/src/features/oss/pages/oss-page/editor-oss-graph/graph/node-core.tsx
@@ -31,10 +31,6 @@ export function NodeCore({ node }: NodeCoreProps) {
const hasFile = !!node.data.operation.result;
const longLabel = node.data.label.length > LONG_LABEL_CHARS;
- function handleTouchStart(event: React.TouchEvent) {
- console.log('handleTouchStart', event);
- }
-
return (
(null);
- const longPressTarget = useRef(null);
-
function handleSavePositions() {
void updateLayout({ itemID: schema.id, data: getLayout() });
}
@@ -193,62 +189,23 @@ export function OssFlow() {
openContextMenu(node, event.clientX, event.clientY);
}
- function handleTouchStart(event: React.TouchEvent) {
- if (!isIOS() || event.touches.length !== 1) {
- return;
- }
-
- // Long-press support for iOS/iPadOS
- const touch = event.touches[0];
- longPressTarget.current = touch.target;
- longPressTimeout.current = setTimeout(() => {
- let targetID = null;
- let element = touch.target as HTMLElement | null;
- while (element) {
- if (element?.getAttribute?.('data-id')) {
- targetID = element.getAttribute('data-id');
- break;
- }
- element = element.parentElement;
- }
- if (targetID) {
- const targetNode = nodes.find(node => node.id === targetID);
- if (targetNode) {
- openContextMenu(targetNode, touch.clientX, touch.clientY);
- }
- }
- }, PARAMETER.ossContextMenuDuration);
- }
-
- function handleTouchEnd() {
- if (!isIOS()) return;
- if (longPressTimeout.current) {
- clearTimeout(longPressTimeout.current);
- longPressTimeout.current = null;
- }
- }
-
- function handleTouchMove() {
- if (!isIOS()) return;
- if (longPressTimeout.current) {
- clearTimeout(longPressTimeout.current);
- longPressTimeout.current = null;
- }
- }
-
return (
{showCoordinates ? : null}
+
+
+
-
-
);
diff --git a/rsconcept/frontend/src/features/oss/pages/oss-page/editor-oss-graph/toolbar-oss-graph.tsx b/rsconcept/frontend/src/features/oss/pages/oss-page/editor-oss-graph/toolbar-oss-graph.tsx
index 8748213e..c74202e1 100644
--- a/rsconcept/frontend/src/features/oss/pages/oss-page/editor-oss-graph/toolbar-oss-graph.tsx
+++ b/rsconcept/frontend/src/features/oss/pages/oss-page/editor-oss-graph/toolbar-oss-graph.tsx
@@ -1,14 +1,16 @@
'use client';
+import React from 'react';
+
import { HelpTopic } from '@/features/help';
import { BadgeHelp } from '@/features/help/components';
+import { type OssNode } from '@/features/oss/models/oss-layout';
import { MiniButton } from '@/components/control';
import {
IconConceptBlock,
IconDestroy,
IconEdit2,
- IconExecute,
IconFitImage,
IconNewItem,
IconReset,
@@ -18,14 +20,11 @@ import {
import { type Styling } from '@/components/props';
import { cn } from '@/components/utils';
import { useDialogsStore } from '@/stores/dialogs';
-import { prepareTooltip } from '@/utils/utils';
+import { isIOS, prepareTooltip } from '@/utils/utils';
-import { OperationType } from '../../../backend/types';
-import { useExecuteOperation } from '../../../backend/use-execute-operation';
import { useMutatingOss } from '../../../backend/use-mutating-oss';
import { useUpdateLayout } from '../../../backend/use-update-layout';
import { NodeType } from '../../../models/oss';
-import { LayoutManager } from '../../../models/oss-layout-api';
import { useOssEdit } from '../oss-edit-context';
import { useOssFlow } from './oss-flow-context';
@@ -36,6 +35,10 @@ interface ToolbarOssGraphProps extends Styling {
onCreateBlock: () => void;
onDelete: () => void;
onResetPositions: () => void;
+
+ isContextMenuOpen: boolean;
+ openContextMenu: (node: OssNode, clientX: number, clientY: number) => void;
+ hideContextMenu: () => void;
}
export function ToolbarOssGraph({
@@ -43,12 +46,16 @@ export function ToolbarOssGraph({
onCreateBlock,
onDelete,
onResetPositions,
+
+ isContextMenuOpen,
+ openContextMenu,
+ hideContextMenu,
className,
...restProps
}: ToolbarOssGraphProps) {
const { schema, selectedItems, isMutable, canDeleteOperation: canDelete } = useOssEdit();
const isProcessing = useMutatingOss();
- const { resetView } = useOssFlow();
+ const { resetView, nodes } = useOssFlow();
const selectedOperation =
selectedItems.length === 1 && selectedItems[0].nodeType === NodeType.OPERATION ? selectedItems[0] : null;
const selectedBlock =
@@ -56,33 +63,9 @@ export function ToolbarOssGraph({
const getLayout = useGetLayout();
const { updateLayout } = useUpdateLayout();
- const { executeOperation } = useExecuteOperation();
- const showEditOperation = useDialogsStore(state => state.showEditOperation);
- const showEditBlock = useDialogsStore(state => state.showEditBlock);
const showOssOptions = useDialogsStore(state => state.showOssOptions);
- const readyForSynthesis = (() => {
- if (!selectedOperation || selectedOperation.operation_type !== OperationType.SYNTHESIS) {
- return false;
- }
- if (selectedOperation.result) {
- return false;
- }
-
- const argumentIDs = schema.graph.expandInputs([selectedOperation.id]);
- if (!argumentIDs || argumentIDs.length < 1) {
- return false;
- }
-
- const argumentOperations = argumentIDs.map(id => schema.operationByID.get(id)!);
- if (argumentOperations.some(item => item.result === null)) {
- return false;
- }
-
- return true;
- })();
-
function handleShowOptions() {
showOssOptions();
}
@@ -91,27 +74,18 @@ export function ToolbarOssGraph({
void updateLayout({ itemID: schema.id, data: getLayout() });
}
- function handleOperationExecute() {
- if (!readyForSynthesis || !selectedOperation) {
+ function handleEditItem(event: React.MouseEvent) {
+ if (isContextMenuOpen) {
+ hideContextMenu();
return;
}
- void executeOperation({
- itemID: schema.id, //
- data: { target: selectedOperation.id, layout: getLayout() }
- });
- }
-
- function handleEditItem() {
- if (selectedOperation) {
- showEditOperation({
- manager: new LayoutManager(schema, getLayout()),
- target: selectedOperation
- });
- } else if (selectedBlock) {
- showEditBlock({
- manager: new LayoutManager(schema, getLayout()),
- target: selectedBlock
- });
+ const nodeID = selectedOperation?.nodeID ?? selectedBlock?.nodeID;
+ if (!nodeID) {
+ return;
+ }
+ const node = nodes.find(node => node.id === nodeID);
+ if (node) {
+ openContextMenu(node, event.clientX, event.clientY);
}
}
@@ -153,11 +127,12 @@ export function ToolbarOssGraph({
disabled={isProcessing}
/>
}
- onClick={onCreateBlock}
- disabled={isProcessing}
+ titleHtml={prepareTooltip('Редактировать выбранную', isIOS() ? '' : 'Правый клик')}
+ hideTitle={isContextMenuOpen}
+ aria-label='Редактировать выбранную'
+ icon={}
+ onClick={handleEditItem}
+ disabled={selectedItems.length !== 1 || isProcessing}
/>
}
- onClick={handleOperationExecute}
- disabled={isProcessing || selectedItems.length !== 1 || !readyForSynthesis}
- />
- }
- onClick={handleEditItem}
- disabled={selectedItems.length !== 1 || isProcessing}
+ titleHtml={prepareTooltip('Новый блок', 'Ctrl + Shift + Q')}
+ aria-label='Новый блок'
+ icon={}
+ onClick={onCreateBlock}
+ disabled={isProcessing}
/>
+
state.showRelocateConstituents);
-
- function handleRelocate() {
- menu.hide();
- showRelocateConstituents({
- oss: schema,
- initialTarget: undefined
- });
- }
-
- if (isAnonymous) {
- return null;
- }
-
- return (
-
- }
- onClick={menu.toggle}
- />
-
- }
- disabled={isProcessing || !isMutable}
- onClick={handleRelocate}
- />
-
-
- );
-}
diff --git a/rsconcept/frontend/src/features/oss/pages/oss-page/menu-main.tsx b/rsconcept/frontend/src/features/oss/pages/oss-page/menu-main.tsx
index af206779..0748e607 100644
--- a/rsconcept/frontend/src/features/oss/pages/oss-page/menu-main.tsx
+++ b/rsconcept/frontend/src/features/oss/pages/oss-page/menu-main.tsx
@@ -53,7 +53,7 @@ export function MenuMain() {
title='Меню'
hideTitle={menu.isOpen}
icon={}
- className='h-full pl-2 text-muted-foreground hover:text-primary cc-animate-color'
+ className='h-full px-2 text-muted-foreground hover:text-primary cc-animate-color'
onClick={menu.toggle}
/>
diff --git a/rsconcept/frontend/src/features/oss/pages/oss-page/menu-oss-tabs.tsx b/rsconcept/frontend/src/features/oss/pages/oss-page/menu-oss-tabs.tsx
index d207dc12..e5ad4899 100644
--- a/rsconcept/frontend/src/features/oss/pages/oss-page/menu-oss-tabs.tsx
+++ b/rsconcept/frontend/src/features/oss/pages/oss-page/menu-oss-tabs.tsx
@@ -3,7 +3,6 @@
import { useAuthSuspense } from '@/features/auth';
import { MenuRole } from '@/features/library/components';
-import { MenuEditOss } from './menu-edit-oss';
import { MenuMain } from './menu-main';
import { useOssEdit } from './oss-edit-context';
@@ -14,8 +13,6 @@ export function MenuOssTabs() {
-
-
);
diff --git a/rsconcept/frontend/src/utils/constants.ts b/rsconcept/frontend/src/utils/constants.ts
index 09871961..16b543d0 100644
--- a/rsconcept/frontend/src/utils/constants.ts
+++ b/rsconcept/frontend/src/utils/constants.ts
@@ -11,7 +11,6 @@ export const PARAMETER = {
notificationDelay: 300, // milliseconds delay for notifications
zoomDuration: 500, // milliseconds animation duration
navigationPopupDelay: 300, // milliseconds delay for navigation popup
- ossContextMenuDuration: 500, // milliseconds - duration of long-press to trigger context menu on iOS/iPadOS
moveDuration: 500, // milliseconds - duration of move animation