From 578f10dfdb8ccdd59ba316b8fb4e8cf088d56c1d Mon Sep 17 00:00:00 2001 From: Vishnu Date: Sat, 20 Dec 2025 14:05:27 +0530 Subject: [PATCH] feat: Add simulation dashboard with interactive block and element editing capabilities. --- .../SimulationDashboard/DashboardEditor.tsx | 37 ++++------------ .../SimulationDashboard/SwapModal.tsx | 26 ------------ .../components/block/BlockComponent.tsx | 12 ------ .../components/block/BlockGrid.tsx | 12 ------ .../components/element/ElementComponent.tsx | 17 +------- .../components/element/ElementDesign.tsx | 6 +-- .../components/element/ElementEditor.tsx | 34 +++++++-------- .../functions/eventHandlers/index.ts | 42 +------------------ 8 files changed, 27 insertions(+), 159 deletions(-) delete mode 100644 app/src/components/SimulationDashboard/SwapModal.tsx diff --git a/app/src/components/SimulationDashboard/DashboardEditor.tsx b/app/src/components/SimulationDashboard/DashboardEditor.tsx index 7759646..3c470d9 100644 --- a/app/src/components/SimulationDashboard/DashboardEditor.tsx +++ b/app/src/components/SimulationDashboard/DashboardEditor.tsx @@ -1,7 +1,6 @@ import { useParams } from "react-router-dom"; import React, { useState, useRef, useEffect } from "react"; import ControlPanel from "./ControlPanel"; -import SwapModal from "./SwapModal"; import { Block } from "../../types/exportedTypes"; import AnalyzerManager from "./AnalyzerManager"; @@ -9,7 +8,7 @@ import { useSceneContext } from "../../modules/scene/sceneContext"; import useModuleStore from "../../store/ui/useModuleStore"; import { usePlayButtonStore } from "../../store/ui/usePlayButtonStore"; import { calculateMinBlockSize } from "./functions/block/calculateMinBlockSize"; -import { handleElementDragStart, handleElementResizeStart, handleBlockResizeStart, handleSwapStart, handleSwapTarget, handleBlockClick, handleElementClick } from "./functions/eventHandlers"; +import { handleElementDragStart, handleElementResizeStart, handleBlockResizeStart, handleBlockClick, handleElementClick } from "./functions/eventHandlers"; import BlockGrid from "./components/block/BlockGrid"; import BlockEditor from "./components/block/BlockEditor"; import ElementEditor from "./components/element/ElementEditor"; @@ -60,7 +59,7 @@ const DashboardEditor: React.FC = () => { peekUpdateCommonValue, peekUpdateDataValue, peekUpdateDataSource, - peekSwapElements, + } = simulationDashBoardStore(); const [editMode, setEditMode] = useState(false); @@ -73,8 +72,7 @@ const DashboardEditor: React.FC = () => { width: number; height: number; } | null>(null); - const [showSwapUI, setShowSwapUI] = useState(false); - const [swapSource, setSwapSource] = useState(null); + const [showElementDropdown, setShowElementDropdown] = useState(null); const [draggingBlock, setDraggingBlock] = useState(null); const [elementDragOffset, setElementDragOffset] = useState({ x: 0, y: 0 }); @@ -89,12 +87,12 @@ const DashboardEditor: React.FC = () => { const currentBlock = blocks.find((b) => b.blockUuid === selectedBlock); const currentElement = currentBlock?.elements.find((el) => el.elementUuid === selectedElement); - useEffect(()=>{ + useEffect(() => { if (!editMode) { setSelectedBlock(null); setSelectedElement(null); } - },[editMode]) + }, [editMode]) // Helper function to send updates to backend - only sends the specific block that changed const updateBackend = async (updatedBlock: Block) => { @@ -176,7 +174,7 @@ const DashboardEditor: React.FC = () => { if (!isInsideEditor) { setSelectedBlock(null); setSelectedElement(null); - setShowSwapUI(false); + setSelectedElement(null); return; } @@ -190,7 +188,7 @@ const DashboardEditor: React.FC = () => { if (!isBlock && !isElement && !isButton && !isResizeHandle) { setSelectedBlock(null); setSelectedElement(null); - setShowSwapUI(false); + setSelectedElement(null); setShowElementDropdown(null); } } @@ -396,28 +394,14 @@ const DashboardEditor: React.FC = () => { editMode={editMode} selectedBlock={selectedBlock} selectedElement={selectedElement} - showSwapUI={showSwapUI} - swapSource={swapSource} calculateMinBlockSize={calculateMinBlockSize} - handleBlockClick={(blockId, event) => handleBlockClick(blockId, event, editMode, setSelectedBlock, setSelectedElement, setShowSwapUI, setShowElementDropdown, showElementDropdown)} + handleBlockClick={(blockId, event) => handleBlockClick(blockId, event, editMode, setSelectedBlock, setSelectedElement, setShowElementDropdown, showElementDropdown)} handleElementClick={(blockId, elementId, event) => { - handleBlockClick(blockId, event, editMode, setSelectedBlock, setSelectedElement, setShowSwapUI, setShowElementDropdown, showElementDropdown); - handleElementClick(blockId, elementId, event, editMode, setSelectedElement, setSelectedBlock, setShowSwapUI, setShowElementDropdown); + handleElementClick(blockId, elementId, event, editMode, setSelectedElement, setSelectedBlock, setShowElementDropdown); }} handleElementDragStart={(elementId, event) => handleElementDragStart(elementId, event, currentElement, setDraggingElement, setElementDragOffset)} handleElementResizeStart={(elementId, event) => handleElementResizeStart(elementId, event, setResizingElement, setResizeStart)} handleBlockResizeStart={(blockId, event) => handleBlockResizeStart(blockId, event, setResizingBlock, setResizeStart)} - handleSwapStart={(elementId, event) => handleSwapStart(elementId, event, setSwapSource, setShowSwapUI)} - handleSwapTarget={async (elementId, event) => { - if (!selectedBlock) return; - handleSwapTarget(elementId, event, swapSource, selectedBlock, async (blockId, el1, el2) => { - const updatedBlocks = peekSwapElements(blockId, el1, el2); - const updatedBlock = getBlockFromPeekedBlocks(updatedBlocks, blockId); - if (updatedBlock) { - await updateBackend(updatedBlock); - } - }); - }} handleBlockDragStart={(blockId, event) => handleBlockDragStart(blockId, event, setDraggingBlock, setBlockDragOffset)} setShowElementDropdown={setShowElementDropdown} showElementDropdown={showElementDropdown} @@ -607,13 +591,10 @@ const DashboardEditor: React.FC = () => { console.error("Failed to delete element:", error); } }} - setSwapSource={setSwapSource} - setShowSwapUI={setShowSwapUI} /> )} - {showSwapUI && } ); }; diff --git a/app/src/components/SimulationDashboard/SwapModal.tsx b/app/src/components/SimulationDashboard/SwapModal.tsx deleted file mode 100644 index 879b765..0000000 --- a/app/src/components/SimulationDashboard/SwapModal.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from "react"; - -interface SwapModalProps { - setShowSwapUI: (show: boolean) => void; - setSwapSource: (source: string | null) => void; -} - -const SwapModal: React.FC = ({ setShowSwapUI, setSwapSource }) => { - return ( -
-

Swap Elements

-

Click on another element to swap positions with the selected element

- -
- ); -}; - -export default SwapModal; diff --git a/app/src/components/SimulationDashboard/components/block/BlockComponent.tsx b/app/src/components/SimulationDashboard/components/block/BlockComponent.tsx index a4dab05..203ec67 100644 --- a/app/src/components/SimulationDashboard/components/block/BlockComponent.tsx +++ b/app/src/components/SimulationDashboard/components/block/BlockComponent.tsx @@ -10,16 +10,12 @@ interface BlockComponentProps { editMode: boolean; selectedBlock: string | null; selectedElement: string | null; - showSwapUI: boolean; - swapSource: string | null; calculateMinBlockSize: (block: Block) => { width: number; height: number }; handleBlockClick: (blockId: string, event: React.MouseEvent) => void; handleElementClick: (blockId: string, elementId: string, event: React.MouseEvent) => void; handleElementDragStart: (elementId: string, event: React.MouseEvent) => void; handleElementResizeStart: (elementId: string, event: React.MouseEvent) => void; handleBlockResizeStart: (blockId: string, event: React.MouseEvent) => void; - handleSwapStart: (elementId: string, event: React.MouseEvent) => void; - handleSwapTarget: (elementId: string, event: React.MouseEvent) => void; setShowElementDropdown: (blockId: string | null) => void; showElementDropdown: string | null; blockRef: RefObject; @@ -32,16 +28,12 @@ const BlockComponent: React.FC = ({ editMode, selectedBlock, selectedElement, - showSwapUI, - swapSource, calculateMinBlockSize, handleBlockClick, handleElementClick, handleElementDragStart, handleElementResizeStart, handleBlockResizeStart, - handleSwapStart, - handleSwapTarget, setShowElementDropdown, showElementDropdown, blockRef, @@ -109,13 +101,9 @@ const BlockComponent: React.FC = ({ blockId={block.blockUuid} editMode={editMode} selectedElement={selectedElement} - showSwapUI={showSwapUI} - swapSource={swapSource} handleElementClick={handleElementClick} handleElementDragStart={handleElementDragStart} handleElementResizeStart={handleElementResizeStart} - handleSwapStart={handleSwapStart} - handleSwapTarget={handleSwapTarget} /> ))} diff --git a/app/src/components/SimulationDashboard/components/block/BlockGrid.tsx b/app/src/components/SimulationDashboard/components/block/BlockGrid.tsx index 51f6e4c..ff07552 100644 --- a/app/src/components/SimulationDashboard/components/block/BlockGrid.tsx +++ b/app/src/components/SimulationDashboard/components/block/BlockGrid.tsx @@ -9,16 +9,12 @@ interface BlockGridProps { editMode: boolean; selectedBlock: string | null; selectedElement: string | null; - showSwapUI: boolean; - swapSource: string | null; calculateMinBlockSize: (block: Block) => { width: number; height: number }; handleBlockClick: (blockId: string, event: React.MouseEvent) => void; handleElementClick: (blockId: string, elementId: string, event: React.MouseEvent) => void; handleElementDragStart: (elementId: string, event: React.MouseEvent) => void; handleElementResizeStart: (elementId: string, event: React.MouseEvent) => void; handleBlockResizeStart: (blockId: string, event: React.MouseEvent) => void; - handleSwapStart: (elementId: string, event: React.MouseEvent) => void; - handleSwapTarget: (elementId: string, event: React.MouseEvent) => void; handleBlockDragStart: (blockId: string, event: React.MouseEvent) => void; setShowElementDropdown: (blockId: string | null) => void; showElementDropdown: string | null; @@ -31,16 +27,12 @@ const BlockGrid: React.FC = ({ editMode, selectedBlock, selectedElement, - showSwapUI, - swapSource, calculateMinBlockSize, handleBlockClick, handleElementClick, handleElementDragStart, handleElementResizeStart, handleBlockResizeStart, - handleSwapStart, - handleSwapTarget, setShowElementDropdown, handleBlockDragStart, showElementDropdown, @@ -58,16 +50,12 @@ const BlockGrid: React.FC = ({ editMode={editMode} selectedBlock={selectedBlock} selectedElement={selectedElement} - showSwapUI={showSwapUI} - swapSource={swapSource} calculateMinBlockSize={calculateMinBlockSize} handleBlockClick={handleBlockClick} handleElementClick={handleElementClick} handleElementDragStart={handleElementDragStart} handleElementResizeStart={handleElementResizeStart} handleBlockResizeStart={handleBlockResizeStart} - handleSwapStart={handleSwapStart} - handleSwapTarget={handleSwapTarget} handleBlockDragStart={handleBlockDragStart} setShowElementDropdown={setShowElementDropdown} showElementDropdown={showElementDropdown} diff --git a/app/src/components/SimulationDashboard/components/element/ElementComponent.tsx b/app/src/components/SimulationDashboard/components/element/ElementComponent.tsx index e3767c8..28ec04d 100644 --- a/app/src/components/SimulationDashboard/components/element/ElementComponent.tsx +++ b/app/src/components/SimulationDashboard/components/element/ElementComponent.tsx @@ -9,13 +9,9 @@ interface ElementComponentProps { blockId: string; editMode: boolean; selectedElement: string | null; - showSwapUI: boolean; - swapSource: string | null; handleElementClick: (blockId: string, elementId: string, event: React.MouseEvent) => void; handleElementDragStart: (elementId: string, event: React.MouseEvent) => void; handleElementResizeStart: (elementId: string, event: React.MouseEvent) => void; - handleSwapStart: (elementId: string, event: React.MouseEvent) => void; - handleSwapTarget: (elementId: string, event: React.MouseEvent) => void; } const ElementComponent: React.FC = ({ @@ -23,16 +19,11 @@ const ElementComponent: React.FC = ({ blockId, editMode, selectedElement, - showSwapUI, - swapSource, handleElementClick, handleElementDragStart, handleElementResizeStart, - handleSwapStart, - handleSwapTarget, }) => { const isSelected = selectedElement === element.elementUuid; - const isSwapSource = swapSource === element.elementUuid; const elementClasses = [ "element", @@ -40,8 +31,6 @@ const ElementComponent: React.FC = ({ element.type === "graph" ? "graph" : "", editMode ? "edit-mode" : "", isSelected ? "selected" : "", - isSwapSource ? "swap-source" : "", - showSwapUI && !isSwapSource ? "swap-target" : "", ] .filter(Boolean) .join(" "); @@ -64,11 +53,7 @@ const ElementComponent: React.FC = ({ onClick={(e) => { e.preventDefault(); e.stopPropagation(); - if (showSwapUI && swapSource !== element.elementUuid) { - handleSwapTarget(element.elementUuid, e); - } else { - handleElementClick(blockId, element.elementUuid, e); - } + handleElementClick(blockId, element.elementUuid, e); }} onMouseDown={(e) => handleElementDragStart(element.elementUuid, e)} > diff --git a/app/src/components/SimulationDashboard/components/element/ElementDesign.tsx b/app/src/components/SimulationDashboard/components/element/ElementDesign.tsx index ddbc066..1696481 100644 --- a/app/src/components/SimulationDashboard/components/element/ElementDesign.tsx +++ b/app/src/components/SimulationDashboard/components/element/ElementDesign.tsx @@ -57,8 +57,6 @@ interface ElementDesignProps { updateDataValue: (blockId: string, elementId: string, dataValue: string | string[]) => void; updateDataSource: (blockId: string, elementId: string, dataSource: string | string[]) => void; handleRemoveElement: (blockId: string, elementId: string) => void; - setSwapSource: (source: string | null) => void; - setShowSwapUI: (show: boolean) => void; } const ElementDesign: React.FC = ({ @@ -74,8 +72,6 @@ const ElementDesign: React.FC = ({ updateElementZIndex, updateGraphTitle, updateGraphType, - setSwapSource, - setShowSwapUI, }) => { const [color, setColor] = useState("#000000"); @@ -396,7 +392,7 @@ const ElementDesign: React.FC = ({ value={color} onChange={(e) => { updateElementStyle(selectedBlock, selectedElement, { - backgroundColor: color, + backgroundColor: hexToRgba(e.target.value), }); setColor(e.target.value); }} diff --git a/app/src/components/SimulationDashboard/components/element/ElementEditor.tsx b/app/src/components/SimulationDashboard/components/element/ElementEditor.tsx index e3ad828..0a73603 100644 --- a/app/src/components/SimulationDashboard/components/element/ElementEditor.tsx +++ b/app/src/components/SimulationDashboard/components/element/ElementEditor.tsx @@ -30,8 +30,6 @@ interface ElementEditorProps { updateDataValue: (blockId: string, elementId: string, dataValue: string | string[]) => void; updateDataSource: (blockId: string, elementId: string, dataSource: string | string[]) => void; handleRemoveElement: (blockId: string, elementId: string) => void; - setSwapSource: (source: string | null) => void; - setShowSwapUI: (show: boolean) => void; } const ElementEditor: React.FC = ({ @@ -53,8 +51,6 @@ const ElementEditor: React.FC = ({ updateDataValue, updateDataSource, handleRemoveElement, - setSwapSource, - setShowSwapUI, }) => { const { simulationDashBoardStore, productStore } = useSceneContext(); const { selectedProduct, getProductById, getEventByModelUuid } = productStore(); @@ -160,7 +156,7 @@ const ElementEditor: React.FC = ({ window.removeEventListener("pointerup", onPointerUp); try { (panel as Element).releasePointerCapture?.((e as any).pointerId); - } catch (err) {} + } catch (err) { } }; window.addEventListener("pointermove", onPointerMove); @@ -519,8 +515,6 @@ const ElementEditor: React.FC = ({ updateDataValue={updateDataValue} updateDataSource={updateDataSource} handleRemoveElement={handleRemoveElement} - setSwapSource={setSwapSource} - setShowSwapUI={setShowSwapUI} /> )} {selectType === "data" && ( @@ -553,12 +547,12 @@ const ElementEditor: React.FC = ({ value={ element.dataBinding?.dataSource ? { - id: element.dataBinding.dataSource as string, - label: - getEventByModelUuid(selectedProduct.productUuid, element.dataBinding.dataSource as string)?.modelName ?? - (element.dataBinding.dataSource === "global" ? "Global" : ""), - icon: , - } + id: element.dataBinding.dataSource as string, + label: + getEventByModelUuid(selectedProduct.productUuid, element.dataBinding.dataSource as string)?.modelName ?? + (element.dataBinding.dataSource === "global" ? "Global" : ""), + icon: , + } : null } onChange={(value) => { @@ -577,13 +571,13 @@ const ElementEditor: React.FC = ({ value={ element.dataBinding?.dataValue ? { - id: element.dataBinding.dataValue as string, - label: - getLableValueDropdownItems(element.dataBinding?.dataSource as string | undefined) - .flatMap((section) => section.items) - .find((item) => item.id === element.dataBinding?.dataValue)?.label ?? "", - icon: , - } + id: element.dataBinding.dataValue as string, + label: + getLableValueDropdownItems(element.dataBinding?.dataSource as string | undefined) + .flatMap((section) => section.items) + .find((item) => item.id === element.dataBinding?.dataValue)?.label ?? "", + icon: , + } : null } onChange={(value) => { diff --git a/app/src/components/SimulationDashboard/functions/eventHandlers/index.ts b/app/src/components/SimulationDashboard/functions/eventHandlers/index.ts index 3836dac..514a4ca 100644 --- a/app/src/components/SimulationDashboard/functions/eventHandlers/index.ts +++ b/app/src/components/SimulationDashboard/functions/eventHandlers/index.ts @@ -24,23 +24,6 @@ export const handleElementDragStart = ( } }; -export const handleBlockDragStart = ( - blockId: string, - event: React.MouseEvent, - setDraggingBlock: (blockId: string | null) => void, - setBlockDragOffset: (offset: Position) => void // Change to specific offset -): void => { - setDraggingBlock(blockId); - const element = event.currentTarget as HTMLElement; - const rect = element.getBoundingClientRect(); - setBlockDragOffset({ - x: event.clientX - rect.left, - y: event.clientY - rect.top, - }); - event.preventDefault(); - event.stopPropagation(); -}; - export const handleElementResizeStart = ( elementId: string, event: React.MouseEvent, @@ -81,24 +64,7 @@ export const handleBlockResizeStart = ( } }; -export const handleSwapStart = (elementId: string, event: React.MouseEvent, setSwapSource: (source: string | null) => void, setShowSwapUI: (show: boolean) => void): void => { - event.stopPropagation(); - setSwapSource(elementId); - setShowSwapUI(true); -}; -export const handleSwapTarget = ( - elementId: string, - event: React.MouseEvent, - swapSource: string | null, - selectedBlock: string | null, - swapElements: (blockId: string, elementId1: string, elementId2: string) => void -): void => { - event.stopPropagation(); - if (swapSource && swapSource !== elementId && selectedBlock) { - swapElements(selectedBlock, swapSource, elementId); - } -}; export const handleBlockClick = ( blockId: string, @@ -106,7 +72,6 @@ export const handleBlockClick = ( editMode: boolean, setSelectedBlock: (blockId: string | null) => void, setSelectedElement: (elementId: string | null) => void, - setShowSwapUI: (show: boolean) => void, setShowElementDropdown: (blockId: string | null) => void, showElementDropdown: string | null ): void => { @@ -114,7 +79,6 @@ export const handleBlockClick = ( if (editMode) { setSelectedBlock(blockId); setSelectedElement(null); - setShowSwapUI(false); if (showElementDropdown && showElementDropdown !== blockId) { setShowElementDropdown(blockId); } @@ -128,14 +92,12 @@ export const handleElementClick = ( editMode: boolean, setSelectedElement: (elementId: string | null) => void, setSelectedBlock: (blockId: string | null) => void, - setShowSwapUI: (show: boolean) => void, setShowElementDropdown: (blockId: string | null) => void ): void => { event.stopPropagation(); if (editMode) { + setSelectedBlock(blockId); setSelectedElement(elementId); - // setSelectedBlock(blockId); - // setShowSwapUI(false); - // setShowElementDropdown(null); + setShowElementDropdown(null); } };