diff --git a/app/src/components/SimulationDashboard/DashboardEditor.tsx b/app/src/components/SimulationDashboard/DashboardEditor.tsx index 3c24a57..10e8453 100644 --- a/app/src/components/SimulationDashboard/DashboardEditor.tsx +++ b/app/src/components/SimulationDashboard/DashboardEditor.tsx @@ -418,7 +418,7 @@ const DashboardEditor: React.FC = () => { {/* BlockGrid */} -
+
{ diff --git a/app/src/components/SimulationDashboard/components/block/BlockEditor.tsx b/app/src/components/SimulationDashboard/components/block/BlockEditor.tsx index 986914d..3ed46df 100644 --- a/app/src/components/SimulationDashboard/components/block/BlockEditor.tsx +++ b/app/src/components/SimulationDashboard/components/block/BlockEditor.tsx @@ -13,6 +13,7 @@ import { AddIcon, DeviceIcon, ParametersIcon, ResizeHeightIcon } from "../../../ import DataDetailedDropdown from "../../../ui/inputs/DataDetailedDropdown"; import RenameInput from "../../../ui/inputs/RenameInput"; import DataSourceSelector from "../../../ui/inputs/DataSourceSelector"; +import { useVisualizationStore } from "../../../../store/visualization/useVisualizationStore"; interface BlockEditorProps { blockEditorRef: RefObject; @@ -38,15 +39,10 @@ const BlockEditor: React.FC = ({ handleRemoveBlock, }) => { const [color, setColor] = useState("#000000"); - // Dragging for block editor + + // Use position from VisualizationStore + const { editorPosition, setEditorPosition } = useVisualizationStore(); const panelRef = useRef(null); - const [position, setPosition] = useState<{ x: number; y: number }>(() => { - if (typeof window !== "undefined") { - // approximate initial left using a default panel width of 300 - return { x: Math.max(0, window.innerWidth - 300 - 40), y: 80 }; - } - return { x: 120, y: 80 }; - }); const initialPositionRef = useRef<{ x: number; y: number } | null>(null); const draggingRef = useRef(false); const startXRef = useRef(0); @@ -54,14 +50,21 @@ const BlockEditor: React.FC = ({ const startLeftRef = useRef(0); const startTopRef = useRef(0); + const position = editorPosition || { x: 100, y: 80 }; + const setPosition = (newPosition: { x: number; y: number }) => { + setEditorPosition(newPosition); + }; + // compute exact initial position once we have panel dimensions useEffect(() => { - const panelEl = panelRef.current || (blockEditorRef && (blockEditorRef as any).current); - const width = panelEl?.offsetWidth || 300; - const nx = Math.max(0, window.innerWidth - width - 40); - const ny = 80; - initialPositionRef.current = { x: nx, y: ny }; - setPosition({ x: nx, y: ny }); + if (!editorPosition) { + const panelEl = panelRef.current || (blockEditorRef && (blockEditorRef as any).current); + const width = panelEl?.offsetWidth || 300; + const nx = Math.max(0, window.innerWidth - width - 40); + const ny = 80; + initialPositionRef.current = { x: nx, y: ny }; + setPosition({ x: nx, y: ny }); + } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); @@ -73,7 +76,6 @@ const BlockEditor: React.FC = ({ }, []); const startDrag = (ev: React.PointerEvent) => { - if (ev.detail > 1) return; const panel = panelRef.current || (blockEditorRef && (blockEditorRef as any).current); @@ -120,8 +122,6 @@ const BlockEditor: React.FC = ({ }; const resetPosition = () => { - - console.log("adsasdasdadasd"); if (initialPositionRef.current) { setPosition(initialPositionRef.current); return; @@ -143,11 +143,7 @@ const BlockEditor: React.FC = ({ className="panel block-editor-panel" style={{ position: "fixed", left: position.x, top: position.y, zIndex: 999 }} > -
+
diff --git a/app/src/components/SimulationDashboard/components/element/ElementEditor.tsx b/app/src/components/SimulationDashboard/components/element/ElementEditor.tsx index 28991e3..1492cd8 100644 --- a/app/src/components/SimulationDashboard/components/element/ElementEditor.tsx +++ b/app/src/components/SimulationDashboard/components/element/ElementEditor.tsx @@ -9,6 +9,7 @@ import { AddIcon, DeviceIcon, ParametersIcon, ResizeHeightIcon } from "../../../ import DataDetailedDropdown from "../../../ui/inputs/DataDetailedDropdown"; import { useSceneContext } from "../../../../modules/scene/sceneContext"; import ElementDesign from "./ElementDesign"; +import { useVisualizationStore } from "../../../../store/visualization/useVisualizationStore"; interface ElementEditorProps { elementEditorRef: RefObject; @@ -64,27 +65,30 @@ const ElementEditor: React.FC = ({ const [selectType, setSelectType] = useState("design"); const [selectDataMapping, setSelectDataMapping] = useState(element?.type === "graph" && element.dataBinding?.dataType === "multiple-machine" ? "multipleMachine" : "singleMachine"); - // Dragging state for the panel + // Use shared position from VisualizationStore + const { editorPosition, setEditorPosition } = useVisualizationStore(); const panelRef = useRef(null); - const [position, setPosition] = useState<{ x: number; y: number }>(() => { - if (typeof window !== "undefined") { - // approximate initial left using a default panel width of 300 - return { x: Math.max(0, window.innerWidth - 300 - 40), y: 80 }; - } - return { x: 100, y: 80 }; - }); const initialPositionRef = useRef<{ x: number; y: number } | null>(null); + // Compute position from store or initialize + const position = editorPosition || { x: 100, y: 80 }; + const setPosition = (newPosition: { x: number; y: number }) => { + setEditorPosition(newPosition); + }; + // On mount, compute exact initial position based on panel width and store it useEffect(() => { - const panelEl = panelRef.current || (elementEditorRef && (elementEditorRef as any).current); - const width = panelEl?.offsetWidth || 300; - const nx = Math.max(0, window.innerWidth - width - 40); - const ny = 80; - initialPositionRef.current = { x: nx, y: ny }; - setPosition({ x: nx, y: ny }); + if (!editorPosition) { + const panelEl = panelRef.current || (elementEditorRef && (elementEditorRef as any).current); + const width = panelEl?.offsetWidth || 300; + const nx = Math.max(0, window.innerWidth - width - 40); + const ny = 80; + initialPositionRef.current = { x: nx, y: ny }; + setPosition({ x: nx, y: ny }); + } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + const draggingRef = useRef(false); const startXRef = useRef(0); const startYRef = useRef(0); @@ -157,7 +161,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); diff --git a/app/src/modules/simulation/analyzer/analyzer.tsx b/app/src/modules/simulation/analyzer/analyzer.tsx index f9d6334..b5c6544 100644 --- a/app/src/modules/simulation/analyzer/analyzer.tsx +++ b/app/src/modules/simulation/analyzer/analyzer.tsx @@ -1376,17 +1376,18 @@ function Analyzer() { // Occupancy trends const timestamp = new Date().toISOString(); - if (!historicalDataRef.current[storage.modelUuid]) { - historicalDataRef.current[storage.modelUuid] = []; - } - historicalDataRef.current[storage.modelUuid].push({ - timestamp, - currentLoad, - utilizationRate, - operation: storeOps > retrieveOps ? "store" : "retrieve", - totalOps, - state: storage.state, - }); + const currentData = historicalDataRef.current[storage.modelUuid] || []; + historicalDataRef.current[storage.modelUuid] = [ + ...currentData, + { + timestamp, + currentLoad, + utilizationRate, + operation: storeOps > retrieveOps ? "store" : "retrieve", + totalOps, + state: storage.state, + }, + ].slice(-100); // Calculate peak occupancy from historical data const occupancyData = historicalDataRef.current[storage.modelUuid] || []; diff --git a/app/src/store/visualization/useVisualizationStore.ts b/app/src/store/visualization/useVisualizationStore.ts index 4b18f49..0ccdc85 100644 --- a/app/src/store/visualization/useVisualizationStore.ts +++ b/app/src/store/visualization/useVisualizationStore.ts @@ -1,13 +1,22 @@ import { create } from "zustand"; import { immer } from "zustand/middleware/immer"; +interface PanelPosition { + x: number; + y: number; +} + interface VisualizationState { - // blocks: Block[] + editorPosition: PanelPosition | null; + setEditorPosition: (position: PanelPosition) => void; } export const useVisualizationStore = create()( immer((set) => ({ - // blocks: [], - + editorPosition: null, + setEditorPosition: (position) => + set((state) => { + state.editorPosition = position; + }), })) ); diff --git a/app/src/styles/components/simulationDashboard/_simulationDashBoard.scss b/app/src/styles/components/simulationDashboard/_simulationDashBoard.scss index af2a618..1f171fd 100644 --- a/app/src/styles/components/simulationDashboard/_simulationDashBoard.scss +++ b/app/src/styles/components/simulationDashboard/_simulationDashBoard.scss @@ -12,7 +12,7 @@ left: 0; pointer-events: none; - *> { + * > { pointer-events: auto; } @@ -256,8 +256,12 @@ width: 100%; display: flex; justify-content: space-between; + width: fit-content !important; + pointer-events: none; + } - pointer-events: auto; + .block-grid-container.editable { + pointer-events: all; } .panel { @@ -272,7 +276,6 @@ box-shadow: 0px 4px 8px rgba(60, 60, 67, 0.1019607843); z-index: 3; - display: flex; flex-direction: column; gap: 11px; @@ -321,7 +324,6 @@ } .design-section { - padding: 4px; outline: 1px solid var(--border-color); outline-offset: -1px; @@ -356,7 +358,7 @@ } .position-canvas { - background: #8D70AD33; + background: #8d70ad33; height: 110px; border-radius: 17px; @@ -369,7 +371,7 @@ .canvas { width: 60%; height: 27px; - background: #E0DFFF80; + background: #e0dfff80; // position: relative; .value { @@ -420,7 +422,6 @@ display: flex; gap: 10px; width: fit-content; - } .icon { @@ -511,11 +512,9 @@ .datas__label, .datas__class { flex: 1; - } } - .type-switch { display: flex; padding: 6px 12px; @@ -548,22 +547,16 @@ } } - &.block-editor-panel { // h4 { // color: #4caf50; // } - - .design-section-wrapper { display: flex; flex-direction: column; gap: 6px; - - } - } .data-details { @@ -620,7 +613,8 @@ text-align: center; } - .type-switch {} + .type-switch { + } .fields-wrapper { display: flex; @@ -653,7 +647,6 @@ border-radius: 2px; &.active { - background: var(--background-color-button); } } @@ -673,11 +666,11 @@ cursor: pointer; svg path { - stroke: #CCACFF !important; + stroke: #ccacff !important; } .label { - color: #CCACFF; + color: #ccacff; } } } @@ -698,7 +691,6 @@ right: 40px; .appearance { .design-datas-wrapper { - display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px 16px; @@ -708,14 +700,13 @@ width: 80%; text-wrap: nowrap; } - } } } .footer { text-align: center; - color: #CCACFF; + color: #ccacff; } } } @@ -926,12 +917,6 @@ } } - - - - - - // DataDetailedDropdown .data-detailed-dropdown { display: flex; @@ -973,7 +958,6 @@ } .input-wrapper { - outline: 1px solid var(--input-border-color); outline-offset: -1px; border: none; @@ -1011,7 +995,6 @@ gap: 8px; .search { - outline: 1px solid var(--border-color); outline-offset: -1px; border-radius: 12px; @@ -1063,11 +1046,11 @@ &.active { span { - color: #CCACFF; + color: #ccacff; } } } } } } -} \ No newline at end of file +}