updated simulation dashboard

This commit is contained in:
2025-11-28 17:25:15 +05:30
parent b6eb2a9598
commit 1e5cbf4aa3
6 changed files with 338 additions and 169 deletions

View File

@@ -1,95 +1,3 @@
<<<<<<< HEAD
{
"name": "aalai-beta",
"version": "0.1.0",
"private": true,
"dependencies": {
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@fingerprintjs/fingerprintjs": "^4.6.2",
"@fingerprintjs/fingerprintjs-pro-react": "^2.6.3",
"@react-three/csg": "^3.2.0",
"@react-three/drei": "^9.113.0",
"@react-three/fiber": "^8.17.7",
"@react-three/postprocessing": "^2.16.3",
"@recast-navigation/core": "^0.39.0",
"@recast-navigation/three": "^0.39.0",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"@turf/helpers": "^7.2.0",
"@turf/turf": "^7.2.0",
"@types/jest": "^27.5.2",
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"@use-gesture/react": "^10.3.1",
"buffer": "^6.0.3",
"chart.js": "^4.4.8",
"chartjs-plugin-annotation": "^3.1.0",
"clsx": "^2.1.1",
"dxf-parser": "^1.1.2",
"glob": "^11.0.0",
"gsap": "^3.12.5",
"html2canvas": "^1.4.1",
"immer": "^9.0.21",
"leva": "^0.10.0",
"mqtt": "^5.10.4",
"postprocessing": "^6.36.4",
"prompt-sync": "^4.2.0",
"r3f-perf": "^7.2.3",
"react": "^18.3.1",
"react-chartjs-2": "^5.3.0",
"react-dom": "^18.3.1",
"react-router-dom": "^7.4.0",
"react-scripts": "5.0.1",
"react-toastify": "^10.0.5",
"recharts": "^3.2.1",
"sass": "^1.78.0",
"socket.io-client": "^4.8.1",
"three": "^0.168.0",
"three-custom-shader-material": "^6.3.7",
"three-viewport-gizmo": "^2.2.0",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4",
"zustand": "^5.0.0-rc.2"
},
"scripts": {
"prepare": "husky",
"prestart": "tsc scripts/git-prompt.ts && node scripts/git-prompt.js",
"start": "react-scripts start",
"build": "GENERATE_SOURCEMAP=false react-scripts build",
"test": "jest"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@types/html2canvas": "^1.0.0",
"@types/node": "^22.9.1",
"@types/three": "^0.169.0",
"axios": "^1.8.4",
"cypress": "^13.14.2",
"dotenv": "^16.4.5",
"husky": "^9.1.6",
"ts-node": "^10.9.2"
}
}
=======
{ {
"name": "aalai-beta", "name": "aalai-beta",
"version": "0.1.0", "version": "0.1.0",
@@ -177,4 +85,3 @@
"ts-node": "^10.9.2" "ts-node": "^10.9.2"
} }
} }
>>>>>>> origin/main

View File

@@ -9,7 +9,15 @@ import DataModelPanel from "./components/models/DataModelPanel";
import { useSceneContext } from "../../modules/scene/sceneContext"; import { useSceneContext } from "../../modules/scene/sceneContext";
import useModuleStore from "../../store/ui/useModuleStore"; import useModuleStore from "../../store/ui/useModuleStore";
import { calculateMinBlockSize } from "./functions/block/calculateMinBlockSize"; import { calculateMinBlockSize } from "./functions/block/calculateMinBlockSize";
import { handleElementDragStart, handleElementResizeStart, handleBlockResizeStart, handleSwapStart, handleSwapTarget, handleBlockClick, handleElementClick } from "./functions/eventHandlers"; import {
handleElementDragStart,
handleElementResizeStart,
handleBlockResizeStart,
handleSwapStart,
handleSwapTarget,
handleBlockClick,
handleElementClick,
} from "./functions/eventHandlers";
import BlockGrid from "./components/block/BlockGrid"; import BlockGrid from "./components/block/BlockGrid";
import BlockEditor from "./components/block/BlockEditor"; import BlockEditor from "./components/block/BlockEditor";
import ElementEditor from "./components/element/ElementEditor"; import ElementEditor from "./components/element/ElementEditor";
@@ -18,6 +26,7 @@ import { handleBlockDragStart } from "./functions/block/handleBlockDragStart";
import { getDashBoardBlocksApi } from "../../services/visulization/dashBoard/getDashBoardBlocks"; import { getDashBoardBlocksApi } from "../../services/visulization/dashBoard/getDashBoardBlocks";
import { upsetDashBoardBlocksApi } from "../../services/visulization/dashBoard/upsertDashBoardBlocks"; import { upsetDashBoardBlocksApi } from "../../services/visulization/dashBoard/upsertDashBoardBlocks";
import { deleteDashBoardBlocksApi } from "../../services/visulization/dashBoard/deleteDashBoardBlocks";
const DashboardEditor: React.FC = () => { const DashboardEditor: React.FC = () => {
const { simulationDashBoardStore, versionStore } = useSceneContext(); const { simulationDashBoardStore, versionStore } = useSceneContext();
@@ -44,6 +53,7 @@ const DashboardEditor: React.FC = () => {
updateGraphType, updateGraphType,
swapElements, swapElements,
subscribe, subscribe,
removeBlock,
} = simulationDashBoardStore(); } = simulationDashBoardStore();
const [selectedBlock, setSelectedBlock] = useState<string | null>(null); const [selectedBlock, setSelectedBlock] = useState<string | null>(null);
@@ -92,11 +102,13 @@ const DashboardEditor: React.FC = () => {
const updateBackend = (blocks: Block[]) => { const updateBackend = (blocks: Block[]) => {
if (!projectId || !selectedVersion) return; if (!projectId || !selectedVersion) return;
upsetDashBoardBlocksApi({ projectId, versionId: selectedVersion.versionId, blocks }).then((data) => { upsetDashBoardBlocksApi({ projectId, versionId: selectedVersion.versionId, blocks }).then(
(data) => {
if (data.data?.blocks) { if (data.data?.blocks) {
setBlocks(data.data.blocks); setBlocks(data.data.blocks);
} }
}); }
);
}; };
useEffect(() => { useEffect(() => {
@@ -170,7 +182,12 @@ const DashboardEditor: React.FC = () => {
return; return;
} }
if (isInsideEditor && !isInsideBlockEditor && !isInsideElementEditor && !isInsideDropdown) { if (
isInsideEditor &&
!isInsideBlockEditor &&
!isInsideElementEditor &&
!isInsideDropdown
) {
const clickedElement = event.target as HTMLElement; const clickedElement = event.target as HTMLElement;
const isBlock = clickedElement.closest("[data-block-id]"); const isBlock = clickedElement.closest("[data-block-id]");
const isElement = clickedElement.closest("[data-element-id]"); const isElement = clickedElement.closest("[data-element-id]");
@@ -197,8 +214,12 @@ const DashboardEditor: React.FC = () => {
const handleMouseMove = (e: MouseEvent): void => { const handleMouseMove = (e: MouseEvent): void => {
// Element dragging - direct DOM manipulation // Element dragging - direct DOM manipulation
if (draggingElement && selectedBlock && currentElement?.positionType === "absolute") { if (draggingElement && selectedBlock && currentElement?.positionType === "absolute") {
const blockElement = document.querySelector(`[data-block-id="${selectedBlock}"]`) as HTMLElement; const blockElement = document.querySelector(
const elementToDrag = document.querySelector(`[data-element-id="${draggingElement}"]`) as HTMLElement; `[data-block-id="${selectedBlock}"]`
) as HTMLElement;
const elementToDrag = document.querySelector(
`[data-element-id="${draggingElement}"]`
) as HTMLElement;
if (blockElement && elementToDrag) { if (blockElement && elementToDrag) {
const blockRect = blockElement.getBoundingClientRect(); const blockRect = blockElement.getBoundingClientRect();
@@ -206,15 +227,27 @@ const DashboardEditor: React.FC = () => {
const newY = e.clientY - blockRect.top - elementDragOffset.y; const newY = e.clientY - blockRect.top - elementDragOffset.y;
// Direct DOM manipulation // Direct DOM manipulation
elementToDrag.style.left = `${Math.max(0, Math.min(blockRect.width - 50, newX))}px`; elementToDrag.style.left = `${Math.max(
elementToDrag.style.top = `${Math.max(0, Math.min(blockRect.height - 30, newY))}px`; 0,
Math.min(blockRect.width - 50, newX)
)}px`;
elementToDrag.style.top = `${Math.max(
0,
Math.min(blockRect.height - 30, newY)
)}px`;
} }
} }
// Block dragging - direct DOM manipulation // Block dragging - direct DOM manipulation
if (draggingBlock && currentBlock?.positionType && (currentBlock.positionType === "absolute" || currentBlock.positionType === "fixed")) { if (
draggingBlock &&
currentBlock?.positionType &&
(currentBlock.positionType === "absolute" || currentBlock.positionType === "fixed")
) {
const editorElement = editorRef.current; const editorElement = editorRef.current;
const blockToDrag = document.querySelector(`[data-block-id="${draggingBlock}"]`) as HTMLElement; const blockToDrag = document.querySelector(
`[data-block-id="${draggingBlock}"]`
) as HTMLElement;
if (editorElement && blockToDrag) { if (editorElement && blockToDrag) {
const editorRect = editorElement.getBoundingClientRect(); const editorRect = editorElement.getBoundingClientRect();
@@ -222,15 +255,23 @@ const DashboardEditor: React.FC = () => {
const newY = e.clientY - editorRect.top - blockDragOffset.y; const newY = e.clientY - editorRect.top - blockDragOffset.y;
// Direct DOM manipulation // Direct DOM manipulation
blockToDrag.style.left = `${Math.max(0, Math.min(editorRect.width - (currentBlock.size?.width || 400), newX))}px`; blockToDrag.style.left = `${Math.max(
blockToDrag.style.top = `${Math.max(0, Math.min(editorRect.height - (currentBlock.size?.height || 300), newY))}px`; 0,
Math.min(editorRect.width - (currentBlock.size?.width || 400), newX)
)}px`;
blockToDrag.style.top = `${Math.max(
0,
Math.min(editorRect.height - (currentBlock.size?.height || 300), newY)
)}px`;
} }
} }
// Resizing - direct DOM manipulation // Resizing - direct DOM manipulation
if ((resizingElement || resizingBlock) && resizeStart) { if ((resizingElement || resizingBlock) && resizeStart) {
if (resizingElement && selectedBlock) { if (resizingElement && selectedBlock) {
const elementToResize = document.querySelector(`[data-element-id="${resizingElement}"]`) as HTMLElement; const elementToResize = document.querySelector(
`[data-element-id="${resizingElement}"]`
) as HTMLElement;
if (elementToResize) { if (elementToResize) {
const deltaX = e.clientX - resizeStart.x; const deltaX = e.clientX - resizeStart.x;
const deltaY = e.clientY - resizeStart.y; const deltaY = e.clientY - resizeStart.y;
@@ -243,13 +284,17 @@ const DashboardEditor: React.FC = () => {
elementToResize.style.height = `${newHeight}px`; elementToResize.style.height = `${newHeight}px`;
} }
} else if (resizingBlock) { } else if (resizingBlock) {
const blockToResize = document.querySelector(`[data-block-id="${resizingBlock}"]`) as HTMLElement; const blockToResize = document.querySelector(
`[data-block-id="${resizingBlock}"]`
) as HTMLElement;
if (blockToResize) { if (blockToResize) {
const deltaX = e.clientX - resizeStart.x; const deltaX = e.clientX - resizeStart.x;
const deltaY = e.clientY - resizeStart.y; const deltaY = e.clientY - resizeStart.y;
const currentBlock = blocks.find((b) => b.blockUuid === resizingBlock); const currentBlock = blocks.find((b) => b.blockUuid === resizingBlock);
const minSize = currentBlock ? calculateMinBlockSize(currentBlock) : { width: 100, height: 50 }; const minSize = currentBlock
? calculateMinBlockSize(currentBlock)
: { width: 100, height: 50 };
const newWidth = Math.max(minSize.width, resizeStart.width + deltaX); const newWidth = Math.max(minSize.width, resizeStart.width + deltaX);
const newHeight = Math.max(minSize.height, resizeStart.height + deltaY); const newHeight = Math.max(minSize.height, resizeStart.height + deltaY);
@@ -265,8 +310,12 @@ const DashboardEditor: React.FC = () => {
const handleMouseUp = (): void => { const handleMouseUp = (): void => {
// Update state only on mouse up for elements // Update state only on mouse up for elements
if (draggingElement && selectedBlock && currentElement?.positionType === "absolute") { if (draggingElement && selectedBlock && currentElement?.positionType === "absolute") {
const blockElement = document.querySelector(`[data-block-id="${selectedBlock}"]`) as HTMLElement; const blockElement = document.querySelector(
const elementToDrag = document.querySelector(`[data-element-id="${draggingElement}"]`) as HTMLElement; `[data-block-id="${selectedBlock}"]`
) as HTMLElement;
const elementToDrag = document.querySelector(
`[data-element-id="${draggingElement}"]`
) as HTMLElement;
if (blockElement && elementToDrag) { if (blockElement && elementToDrag) {
const computedStyle = window.getComputedStyle(elementToDrag); const computedStyle = window.getComputedStyle(elementToDrag);
@@ -278,8 +327,14 @@ const DashboardEditor: React.FC = () => {
} }
// Update state only on mouse up for blocks // Update state only on mouse up for blocks
if (draggingBlock && currentBlock?.positionType && (currentBlock.positionType === "absolute" || currentBlock.positionType === "fixed")) { if (
const blockToDrag = document.querySelector(`[data-block-id="${draggingBlock}"]`) as HTMLElement; draggingBlock &&
currentBlock?.positionType &&
(currentBlock.positionType === "absolute" || currentBlock.positionType === "fixed")
) {
const blockToDrag = document.querySelector(
`[data-block-id="${draggingBlock}"]`
) as HTMLElement;
if (blockToDrag) { if (blockToDrag) {
const computedStyle = window.getComputedStyle(blockToDrag); const computedStyle = window.getComputedStyle(blockToDrag);
@@ -292,7 +347,9 @@ const DashboardEditor: React.FC = () => {
// Update state only on mouse up for resizing // Update state only on mouse up for resizing
if (resizingElement && selectedBlock) { if (resizingElement && selectedBlock) {
const elementToResize = document.querySelector(`[data-element-id="${resizingElement}"]`) as HTMLElement; const elementToResize = document.querySelector(
`[data-element-id="${resizingElement}"]`
) as HTMLElement;
if (elementToResize) { if (elementToResize) {
const computedStyle = window.getComputedStyle(elementToResize); const computedStyle = window.getComputedStyle(elementToResize);
const width = parseFloat(computedStyle.width); const width = parseFloat(computedStyle.width);
@@ -303,7 +360,9 @@ const DashboardEditor: React.FC = () => {
} }
if (resizingBlock) { if (resizingBlock) {
const blockToResize = document.querySelector(`[data-block-id="${resizingBlock}"]`) as HTMLElement; const blockToResize = document.querySelector(
`[data-block-id="${resizingBlock}"]`
) as HTMLElement;
if (blockToResize) { if (blockToResize) {
const computedStyle = window.getComputedStyle(blockToResize); const computedStyle = window.getComputedStyle(blockToResize);
const width = parseFloat(computedStyle.width); const width = parseFloat(computedStyle.width);
@@ -330,12 +389,41 @@ const DashboardEditor: React.FC = () => {
document.removeEventListener("mousemove", handleMouseMove); document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp); document.removeEventListener("mouseup", handleMouseUp);
}; };
}, [draggingElement, resizingElement, draggingBlock, resizingBlock, elementDragOffset, blockDragOffset, selectedBlock, currentElement, resizeStart, currentBlock, blocks]); }, [
draggingElement,
resizingElement,
draggingBlock,
resizingBlock,
elementDragOffset,
blockDragOffset,
selectedBlock,
currentElement,
resizeStart,
currentBlock,
blocks,
]);
const handleDelteBlock = (blocks: Block[] | Block) => {
if (!projectId || !selectedVersion) return;
deleteDashBoardBlocksApi({ blocks, projectId, versionId: selectedVersion.versionId }).then(
(data) => {
if (data.blocks[0].message === "Block deleted successfully") {
removeBlock(data.blocks[0].blockUuid);
}
}
);
};
return ( return (
<div ref={editorRef} className="dashboard-editor"> <div ref={editorRef} className="dashboard-editor">
{activeModule === "visualization" && ( {activeModule === "visualization" && (
<ControlPanel editMode={editMode} setEditMode={setEditMode} addBlock={() => addBlock()} showDataModelPanel={showDataModelPanel} setShowDataModelPanel={setShowDataModelPanel} /> <ControlPanel
editMode={editMode}
setEditMode={setEditMode}
addBlock={() => addBlock()}
showDataModelPanel={showDataModelPanel}
setShowDataModelPanel={setShowDataModelPanel}
/>
)} )}
{/* BlockGrid */} {/* BlockGrid */}
@@ -349,16 +437,57 @@ const DashboardEditor: React.FC = () => {
showSwapUI={showSwapUI} showSwapUI={showSwapUI}
swapSource={swapSource} swapSource={swapSource}
calculateMinBlockSize={calculateMinBlockSize} calculateMinBlockSize={calculateMinBlockSize}
handleBlockClick={(blockId, event) => handleBlockClick(blockId, event, editMode, setSelectedBlock, setSelectedElement, setShowSwapUI)} handleBlockClick={(blockId, event) =>
handleElementClick={(blockId, elementId, event) => handleBlockClick(
handleElementClick(blockId, elementId, event, editMode, setSelectedElement, setSelectedBlock, setShowSwapUI, setShowElementDropdown) blockId,
event,
editMode,
setSelectedBlock,
setSelectedElement,
setShowSwapUI
)
}
handleElementClick={(blockId, elementId, event) =>
handleElementClick(
blockId,
elementId,
event,
editMode,
setSelectedElement,
setSelectedBlock,
setShowSwapUI,
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={(elementId, event) =>
handleSwapTarget(elementId, event, swapSource, selectedBlock, swapElements)
}
handleBlockDragStart={(blockId, event) =>
handleBlockDragStart(blockId, event, setDraggingBlock, setBlockDragOffset)
} }
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={(elementId, event) => handleSwapTarget(elementId, event, swapSource, selectedBlock, swapElements)}
handleBlockDragStart={(blockId, event) => handleBlockDragStart(blockId, event, setDraggingBlock, setBlockDragOffset)}
setShowElementDropdown={setShowElementDropdown} setShowElementDropdown={setShowElementDropdown}
showElementDropdown={showElementDropdown} showElementDropdown={showElementDropdown}
blockRef={blockRef} blockRef={blockRef}
@@ -371,9 +500,16 @@ const DashboardEditor: React.FC = () => {
selectedBlock={selectedBlock} selectedBlock={selectedBlock}
updateBlockStyle={(blockId, style) => updateBlockStyle(blockId, style)} updateBlockStyle={(blockId, style) => updateBlockStyle(blockId, style)}
updateBlockSize={(blockId, size) => updateBlockSize(blockId, size)} updateBlockSize={(blockId, size) => updateBlockSize(blockId, size)}
updateBlockPosition={(blockId, position) => updateBlockPosition(blockId, position)} updateBlockPosition={(blockId, position) =>
updateBlockPositionType={(blockId, positionType) => updateBlockPositionType(blockId, positionType)} updateBlockPosition(blockId, position)
}
updateBlockPositionType={(blockId, positionType) =>
updateBlockPositionType(blockId, positionType)
}
updateBlockZIndex={(blockId, zIndex) => updateBlockZIndex(blockId, zIndex)} updateBlockZIndex={(blockId, zIndex) => updateBlockZIndex(blockId, zIndex)}
removeBlock={(block) => {
handleDelteBlock(block);
}}
/> />
)} )}
{selectedElement && editMode && selectedBlock && currentElement && ( {selectedElement && editMode && selectedBlock && currentElement && (
@@ -382,15 +518,33 @@ const DashboardEditor: React.FC = () => {
currentElement={currentElement} currentElement={currentElement}
selectedBlock={selectedBlock} selectedBlock={selectedBlock}
selectedElement={selectedElement} selectedElement={selectedElement}
updateElementStyle={(blockId, elementId, style) => updateElementStyle(blockId, elementId, style)} updateElementStyle={(blockId, elementId, style) =>
updateElementSize={(blockId, elementId, size) => updateElementSize(blockId, elementId, size)} updateElementStyle(blockId, elementId, style)
updateElementPosition={(blockId, elementId, position) => updateElementPosition(blockId, elementId, position)} }
updateElementPositionType={(blockId, elementId, positionType) => updateElementPositionType(blockId, elementId, positionType)} updateElementSize={(blockId, elementId, size) =>
updateElementZIndex={(blockId, elementId, zIndex) => updateElementZIndex(blockId, elementId, zIndex)} updateElementSize(blockId, elementId, size)
updateElementData={(blockId, elementId, updates) => updateElementData(blockId, elementId, updates)} }
updateGraphData={(blockId, elementId, newData) => updateGraphData(blockId, elementId, newData)} updateElementPosition={(blockId, elementId, position) =>
updateGraphTitle={(blockId, elementId, title) => updateGraphTitle(blockId, elementId, title)} updateElementPosition(blockId, elementId, position)
updateGraphType={(blockId, elementId, type) => updateGraphType(blockId, elementId, type)} }
updateElementPositionType={(blockId, elementId, positionType) =>
updateElementPositionType(blockId, elementId, positionType)
}
updateElementZIndex={(blockId, elementId, zIndex) =>
updateElementZIndex(blockId, elementId, zIndex)
}
updateElementData={(blockId, elementId, updates) =>
updateElementData(blockId, elementId, updates)
}
updateGraphData={(blockId, elementId, newData) =>
updateGraphData(blockId, elementId, newData)
}
updateGraphTitle={(blockId, elementId, title) =>
updateGraphTitle(blockId, elementId, title)
}
updateGraphType={(blockId, elementId, type) =>
updateGraphType(blockId, elementId, type)
}
setSwapSource={setSwapSource} setSwapSource={setSwapSource}
setShowSwapUI={setShowSwapUI} setShowSwapUI={setShowSwapUI}
dataModelManager={dataModelManager} dataModelManager={dataModelManager}
@@ -398,9 +552,13 @@ const DashboardEditor: React.FC = () => {
)} )}
</div> </div>
{showDataModelPanel && editMode && <DataModelPanel dataModel={dataModel} dataModelManager={dataModelManager} />} {showDataModelPanel && editMode && (
<DataModelPanel dataModel={dataModel} dataModelManager={dataModelManager} />
)}
{showSwapUI && <SwapModal setShowSwapUI={setShowSwapUI} setSwapSource={setSwapSource} />} {showSwapUI && (
<SwapModal setShowSwapUI={setShowSwapUI} setSwapSource={setSwapSource} />
)}
</div> </div>
); );
}; };

View File

@@ -1,4 +1,4 @@
import { useRef, type RefObject } from "react"; import { useRef, useState, type RefObject } from "react";
import { Block } from "../../../../types/exportedTypes"; import { Block } from "../../../../types/exportedTypes";
import ElementComponent from "../element/ElementComponent"; import ElementComponent from "../element/ElementComponent";
import { ResizeIcon } from "../../../icons/ExportToolsIcons"; import { ResizeIcon } from "../../../icons/ExportToolsIcons";
@@ -47,13 +47,13 @@ const BlockComponent: React.FC<BlockComponentProps> = ({
handleBlockDragStart, handleBlockDragStart,
}) => { }) => {
const { simulationDashBoardStore } = useSceneContext(); const { simulationDashBoardStore } = useSceneContext();
const { addElement } = simulationDashBoardStore() const { addElement } = simulationDashBoardStore();
const dropdownRef = useRef<HTMLDivElement>(null); const dropdownRef = useRef<HTMLDivElement>(null);
const minSize = calculateMinBlockSize(block); const minSize = calculateMinBlockSize(block);
const isSelected = selectedBlock === block.blockUuid; const isSelected = selectedBlock === block.blockUuid;
const isDraggable = editMode && (block.positionType === "absolute" || block.positionType === "fixed"); const isDraggable =
editMode && (block.positionType === "absolute" || block.positionType === "fixed");
const handleMouseDown = (event: React.MouseEvent) => { const handleMouseDown = (event: React.MouseEvent) => {
if (isDraggable) { if (isDraggable) {
@@ -67,12 +67,20 @@ const BlockComponent: React.FC<BlockComponentProps> = ({
key={block.blockUuid} key={block.blockUuid}
data-block-id={block.blockUuid} data-block-id={block.blockUuid}
ref={isSelected ? blockRef : null} ref={isSelected ? blockRef : null}
className={`block ${isSelected ? "selected" : ""} ${editMode ? "edit-mode" : ""} ${isDraggable ? "draggable" : ""}`} className={`block ${isSelected ? "selected" : ""} ${editMode ? "edit-mode" : ""} ${
isDraggable ? "draggable" : ""
}`}
style={{ style={{
...block.style, ...block.style,
position: block.positionType || "relative", position: block.positionType || "relative",
left: block.positionType === "absolute" || block.positionType === "fixed" ? `${block.position?.x || 0}px` : "auto", left:
top: block.positionType === "absolute" || block.positionType === "fixed" ? `${block.position?.y || 0}px` : "auto", block.positionType === "absolute" || block.positionType === "fixed"
? `${block.position?.x || 0}px`
: "auto",
top:
block.positionType === "absolute" || block.positionType === "fixed"
? `${block.position?.y || 0}px`
: "auto",
width: block.size?.width || 400, width: block.size?.width || 400,
height: block.size?.height || 300, height: block.size?.height || 300,
minWidth: minSize.width, minWidth: minSize.width,
@@ -88,7 +96,9 @@ const BlockComponent: React.FC<BlockComponentProps> = ({
<button <button
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
setShowElementDropdown(showElementDropdown === block.blockUuid ? null : block.blockUuid); setShowElementDropdown(
showElementDropdown === block.blockUuid ? null : block.blockUuid
);
}} }}
className="add-element-button" className="add-element-button"
> >
@@ -97,7 +107,9 @@ const BlockComponent: React.FC<BlockComponentProps> = ({
<ElementDropdown <ElementDropdown
showElementDropdown={showElementDropdown} showElementDropdown={showElementDropdown}
addElement={(blockId, type, graphType) => addElement(blockId, type as UIType, graphType as GraphTypes)} addElement={(blockId, type, graphType) =>
addElement(blockId, type as UIType, graphType as GraphTypes)
}
dropdownRef={dropdownRef} dropdownRef={dropdownRef}
/> />
</div> </div>
@@ -122,10 +134,14 @@ const BlockComponent: React.FC<BlockComponentProps> = ({
))} ))}
{/* Block resize handle */} {/* Block resize handle */}
{editMode && isSelected && {editMode && isSelected && (
<div className="resize-handle" onMouseDown={(e) => handleBlockResizeStart(block.blockUuid, e)}> <div
className="resize-handle"
onMouseDown={(e) => handleBlockResizeStart(block.blockUuid, e)}
>
<ResizeIcon /> <ResizeIcon />
</div>} </div>
)}
{/* Drag handle indicator for absolute/fixed blocks */} {/* Drag handle indicator for absolute/fixed blocks */}
{isDraggable && editMode && ( {isDraggable && editMode && (
@@ -152,9 +168,6 @@ const BlockComponent: React.FC<BlockComponentProps> = ({
</div> </div>
)} )}
</div> </div>
); );
}; };

View File

@@ -14,9 +14,13 @@ interface BlockEditorProps {
currentBlock: Block; currentBlock: Block;
selectedBlock: string; selectedBlock: string;
updateBlockStyle: (blockId: string, style: React.CSSProperties) => void; updateBlockStyle: (blockId: string, style: React.CSSProperties) => void;
removeBlock: (block: Block | Block[]) => void;
updateBlockSize: (blockId: string, size: { width: number; height: number }) => void; updateBlockSize: (blockId: string, size: { width: number; height: number }) => void;
updateBlockPosition: (blockId: string, position: { x: number; y: number }) => void; updateBlockPosition: (blockId: string, position: { x: number; y: number }) => void;
updateBlockPositionType: (blockId: string, positionType: "relative" | "absolute" | "fixed") => void; updateBlockPositionType: (
blockId: string,
positionType: "relative" | "absolute" | "fixed"
) => void;
updateBlockZIndex: (blockId: string, zIndex: number) => void; updateBlockZIndex: (blockId: string, zIndex: number) => void;
} }
@@ -29,12 +33,13 @@ const BlockEditor: React.FC<BlockEditorProps> = ({
updateBlockPosition, updateBlockPosition,
updateBlockPositionType, updateBlockPositionType,
updateBlockZIndex, updateBlockZIndex,
removeBlock,
}) => { }) => {
return ( return (
<div ref={blockEditorRef} className="panel block-editor-panel"> <div ref={blockEditorRef} className="panel block-editor-panel">
<div className="header"> <div className="header">
<h4>Block Style</h4> <h4>Block Style</h4>
<div className="delete icon"> <div className="delete icon" onClick={() => removeBlock([currentBlock])}>
<DeleteIcon /> <DeleteIcon />
</div> </div>
</div> </div>
@@ -42,7 +47,12 @@ const BlockEditor: React.FC<BlockEditorProps> = ({
<label className="form-label">Position Type: </label> <label className="form-label">Position Type: </label>
<select <select
value={currentBlock.positionType || "relative"} value={currentBlock.positionType || "relative"}
onChange={(e) => updateBlockPositionType(selectedBlock, e.target.value as "relative" | "absolute" | "fixed")} onChange={(e) =>
updateBlockPositionType(
selectedBlock,
e.target.value as "relative" | "absolute" | "fixed"
)
}
className="form-select" className="form-select"
> >
<option value="relative">Relative</option> <option value="relative">Relative</option>
@@ -101,7 +111,14 @@ const BlockEditor: React.FC<BlockEditorProps> = ({
<input <input
type="color" type="color"
value={rgbaToHex(getCurrentBlockStyleValue(currentBlock, "backgroundColor"))} value={rgbaToHex(getCurrentBlockStyleValue(currentBlock, "backgroundColor"))}
onChange={(e) => handleBackgroundColorChange(currentBlock, selectedBlock, updateBlockStyle, e.target.value)} onChange={(e) =>
handleBackgroundColorChange(
currentBlock,
selectedBlock,
updateBlockStyle,
e.target.value
)
}
className="color-input" className="color-input"
/> />
</div> </div>
@@ -139,10 +156,21 @@ const BlockEditor: React.FC<BlockEditorProps> = ({
<InputRange <InputRange
label="Background Opacity" label="Background Opacity"
disabled={false} disabled={false}
value={Math.round(getAlphaFromRgba(getCurrentBlockStyleValue(currentBlock, "backgroundColor")) * 100)} value={Math.round(
getAlphaFromRgba(
getCurrentBlockStyleValue(currentBlock, "backgroundColor")
) * 100
)}
min={0} min={0}
max={100} max={100}
onChange={(value: number) => handleBackgroundAlphaChange(currentBlock, selectedBlock, updateBlockStyle, Number(value))} onChange={(value: number) =>
handleBackgroundAlphaChange(
currentBlock,
selectedBlock,
updateBlockStyle,
Number(value)
)
}
// onPointerUp={updatedDist} // onPointerUp={updatedDist}
key={"6"} key={"6"}
/> />
@@ -180,10 +208,16 @@ const BlockEditor: React.FC<BlockEditorProps> = ({
<InputRange <InputRange
label="Blur Amount" label="Blur Amount"
disabled={false} disabled={false}
value={parseInt(getCurrentBlockStyleValue(currentBlock, "backdropFilter")?.match(/\d+/)?.[0] || "10")} value={parseInt(
getCurrentBlockStyleValue(currentBlock, "backdropFilter")?.match(
/\d+/
)?.[0] || "10"
)}
min={0} min={0}
max={50} max={50}
onChange={(value: number) => handleBlurAmountChange(selectedBlock, updateBlockStyle, Number(value))} onChange={(value: number) =>
handleBlurAmountChange(selectedBlock, updateBlockStyle, Number(value))
}
// onPointerUp={updatedDist} // onPointerUp={updatedDist}
key={"6"} key={"6"}
/> />
@@ -223,7 +257,13 @@ const BlockEditor: React.FC<BlockEditorProps> = ({
<div className="form-group"> <div className="form-group">
<label className="form-label">Z-Index: </label> <label className="form-label">Z-Index: </label>
<input type="number" placeholder="Z-Index" value={currentBlock.zIndex || 1} onChange={(e) => updateBlockZIndex(selectedBlock, Number(e.target.value))} className="form-input" /> <input
type="number"
placeholder="Z-Index"
value={currentBlock.zIndex || 1}
onChange={(e) => updateBlockZIndex(selectedBlock, Number(e.target.value))}
className="form-input"
/>
</div> </div>
<div className="form-group"> <div className="form-group">
@@ -232,7 +272,9 @@ const BlockEditor: React.FC<BlockEditorProps> = ({
type="number" type="number"
placeholder="Padding" placeholder="Padding"
value={parseInt(getCurrentBlockStyleValue(currentBlock, "padding")) || 10} value={parseInt(getCurrentBlockStyleValue(currentBlock, "padding")) || 10}
onChange={(e) => updateBlockStyle(selectedBlock, { padding: Number(e.target.value) })} onChange={(e) =>
updateBlockStyle(selectedBlock, { padding: Number(e.target.value) })
}
className="form-input" className="form-input"
/> />
</div> </div>

View File

@@ -0,0 +1,40 @@
import { Block } from "../../../types/exportedTypes";
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
export const deleteDashBoardBlocksApi = async ({
projectId,
versionId,
blocks,
}: {
projectId: string;
versionId: string;
blocks: Block[] | Block;
}) => {
console.log("blocks, projectId, versionId: ", blocks, projectId, versionId);
try {
const response = await fetch(`${url_Backend_dwinzo}/api/V1/simulation/blocks`, {
method: "PATCH",
headers: {
Authorization: "Bearer <access_token>",
"Content-Type": "application/json",
token: localStorage.getItem("token") || "",
refresh_token: localStorage.getItem("refreshToken") || "",
},
body: JSON.stringify({ blocks, projectId, versionId }),
});
const newAccessToken = response.headers.get("x-access-token");
if (newAccessToken) {
localStorage.setItem("token", newAccessToken);
}
if (!response.ok) {
echo.error("Failed to delete block");
}
const result = await response.json();
console.log('result: ', result);
return result;
} catch {
echo.error("Failed to delete block");
}
};

View File

@@ -2,7 +2,16 @@ import { Block } from "../../../types/exportedTypes";
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
export const upsetDashBoardBlocksApi = async ({ projectId, versionId, blocks }: { projectId: string; versionId: string; blocks: Block[] }) => { export const upsetDashBoardBlocksApi = async ({
projectId,
versionId,
blocks,
}: {
projectId: string;
versionId: string;
blocks: Block[];
}) => {
console.log("blocks: ", blocks);
try { try {
const response = await fetch(`${url_Backend_dwinzo}/api/V1/simulation/blocks/upsert`, { const response = await fetch(`${url_Backend_dwinzo}/api/V1/simulation/blocks/upsert`, {
method: "POST", method: "POST",
@@ -22,8 +31,8 @@ export const upsetDashBoardBlocksApi = async ({ projectId, versionId, blocks }:
if (!response.ok) { if (!response.ok) {
echo.error("Failed to upsert dashBoardBlocks"); echo.error("Failed to upsert dashBoardBlocks");
} }
const data = await response.clone().json();
return await response.json(); return data;
} catch { } catch {
echo.error("Failed to upsert dashBoardBlocks"); echo.error("Failed to upsert dashBoardBlocks");
} }