diff --git a/app/src/components/layout/3D-cards/cards/ProductionCapacity.tsx b/app/src/components/layout/3D-cards/cards/ProductionCapacity.tsx index 0d239b4..a719023 100644 --- a/app/src/components/layout/3D-cards/cards/ProductionCapacity.tsx +++ b/app/src/components/layout/3D-cards/cards/ProductionCapacity.tsx @@ -157,10 +157,10 @@ const ProductionCapacity: React.FC = ({ id, type, posit setDuration(response.data.Data.duration) setName(response.data.widgetName) } else { - console.log("Unexpected response:", response); + } } catch (error) { - console.error("There was an error!", error); + } } } @@ -178,7 +178,7 @@ const ProductionCapacity: React.FC = ({ id, type, posit useEffect(() => { - console.log('rotation: ', rotation); + }, [rotation]) const rotationDegrees = { x: (rotation[0] * 180) / Math.PI, @@ -202,7 +202,6 @@ const ProductionCapacity: React.FC = ({ id, type, posit transform: transformStyle.transform, transformStyle: 'preserve-3d', transition: 'transform 0.1s ease-out' - }}>
setSelectedChartId({ id: id, type: type })} diff --git a/app/src/components/layout/3D-cards/cards/ReturnOfInvestment.tsx b/app/src/components/layout/3D-cards/cards/ReturnOfInvestment.tsx index 96fc305..8e6c707 100644 --- a/app/src/components/layout/3D-cards/cards/ReturnOfInvestment.tsx +++ b/app/src/components/layout/3D-cards/cards/ReturnOfInvestment.tsx @@ -43,9 +43,10 @@ interface ReturnOfInvestmentProps { id: string; type: string; position: [number, number, number]; + rotation: [number, number, number]; onContextMenu?: (event: React.MouseEvent) => void; } -const ReturnOfInvestment: React.FC = ({ id, type, position, onContextMenu }) => { +const ReturnOfInvestment: React.FC = ({ id, type, position, rotation, onContextMenu }) => { const { selectedChartId, setSelectedChartId } = useWidgetStore(); const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore(); @@ -203,13 +204,29 @@ const ReturnOfInvestment: React.FC = ({ id, type, posit } } , [chartMeasurements, chartDuration, widgetName]) + const rotationDegrees = { + x: (rotation[0] * 180) / Math.PI, + y: (rotation[1] * 180) / Math.PI, + z: (rotation[2] * 180) / Math.PI, + }; + + const transformStyle = { + transform: `rotateX(${rotationDegrees.x}deg) rotateY(${rotationDegrees.y}deg) rotateZ(${rotationDegrees.z}deg)`, + }; return ( + sprite + style={{ + transform: transformStyle.transform, + transformStyle: 'preserve-3d', + transition: 'transform 0.1s ease-out' + + }} + >
setSelectedChartId({ id: id, type: type })} onContextMenu={onContextMenu} diff --git a/app/src/components/layout/3D-cards/cards/StateWorking.tsx b/app/src/components/layout/3D-cards/cards/StateWorking.tsx index efd4e7d..287bc15 100644 --- a/app/src/components/layout/3D-cards/cards/StateWorking.tsx +++ b/app/src/components/layout/3D-cards/cards/StateWorking.tsx @@ -10,9 +10,10 @@ interface StateWorkingProps { id: string; type: string; position: [number, number, number]; + rotation: [number, number, number]; onContextMenu?: (event: React.MouseEvent) => void; } -const StateWorking: React.FC = ({ id, type, position, onContextMenu }) => { +const StateWorking: React.FC = ({ id, type, position, rotation, onContextMenu }) => { const { selectedChartId, setSelectedChartId } = useWidgetStore(); const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore(); const [measurements, setmeasurements] = useState({}); @@ -89,13 +90,28 @@ const StateWorking: React.FC = ({ id, type, position, onConte } , [chartMeasurements, chartDuration, widgetName]) + const rotationDegrees = { + x: (rotation[0] * 180) / Math.PI, + y: (rotation[1] * 180) / Math.PI, + z: (rotation[2] * 180) / Math.PI, + }; + const transformStyle = { + transform: `rotateX(${rotationDegrees.x}deg) rotateY(${rotationDegrees.y}deg) rotateZ(${rotationDegrees.z}deg)`, + }; return ( + sprite + style={{ + transform: transformStyle.transform, + transformStyle: 'preserve-3d', + transition: 'transform 0.1s ease-out' + + }} + >
setSelectedChartId({ id: id, type: type })} onContextMenu={onContextMenu} diff --git a/app/src/components/layout/3D-cards/cards/Throughput.tsx b/app/src/components/layout/3D-cards/cards/Throughput.tsx index 5d6fab9..de3109b 100644 --- a/app/src/components/layout/3D-cards/cards/Throughput.tsx +++ b/app/src/components/layout/3D-cards/cards/Throughput.tsx @@ -45,10 +45,11 @@ interface ThroughputProps { id: string; type: string; position: [number, number, number]; + rotation: [number, number, number]; onContextMenu?: (event: React.MouseEvent) => void; } -const Throughput: React.FC = ({ id, type, position, onContextMenu }) => { +const Throughput: React.FC = ({ id, type, position, rotation, onContextMenu }) => { const { selectedChartId, setSelectedChartId } = useWidgetStore(); const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore(); @@ -183,13 +184,29 @@ const Throughput: React.FC = ({ id, type, position, onContextMe } } , [chartMeasurements, chartDuration, widgetName]) + const rotationDegrees = { + x: (rotation[0] * 180) / Math.PI, + y: (rotation[1] * 180) / Math.PI, + z: (rotation[2] * 180) / Math.PI, + }; + + const transformStyle = { + transform: `rotateX(${rotationDegrees.x}deg) rotateY(${rotationDegrees.y}deg) rotateZ(${rotationDegrees.z}deg)`, + }; return ( + sprite + style={{ + transform: transformStyle.transform, + transformStyle: 'preserve-3d', + transition: 'transform 0.1s ease-out' + + }} + >
setSelectedChartId({ id: id, type: type })} onContextMenu={onContextMenu} diff --git a/app/src/components/layout/sidebarLeft/visualization/widgets/Widgets2D.tsx b/app/src/components/layout/sidebarLeft/visualization/widgets/Widgets2D.tsx index 561c82b..9f71423 100644 --- a/app/src/components/layout/sidebarLeft/visualization/widgets/Widgets2D.tsx +++ b/app/src/components/layout/sidebarLeft/visualization/widgets/Widgets2D.tsx @@ -101,7 +101,7 @@ const ProgressBarWidget = ({
); }; -console.log(chartTypes, "chartTypes"); + const Widgets2D = () => { return ( diff --git a/app/src/components/layout/sidebarRight/properties/GlobalProperties.tsx b/app/src/components/layout/sidebarRight/properties/GlobalProperties.tsx index 4e6a537..4ffea3b 100644 --- a/app/src/components/layout/sidebarRight/properties/GlobalProperties.tsx +++ b/app/src/components/layout/sidebarRight/properties/GlobalProperties.tsx @@ -33,7 +33,7 @@ const GlobalProperties: React.FC = () => { const { setPlaneValue, setGridValue, planeValue, gridValue } = useTileDistance(); useEffect(() => { - console.log(gridValue, planeValue, "values"); + }, [gridValue, planeValue]); const { socket } = useSocketStore(); const { limitDistance, setLimitDistance } = useLimitDistance(); diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/FleetEfficiencyInputComponent.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/FleetEfficiencyInputComponent.tsx index cd60d24..55ae422 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/FleetEfficiencyInputComponent.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/FleetEfficiencyInputComponent.tsx @@ -45,7 +45,7 @@ const FleetEfficiencyInputComponent = (props: Props) => { try { const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/A_floatWidget/${selectedChartId.id}/${organization}`); if (response.status === 200) { - console.log(response.data); + setSelections(response.data.Data.measurements) setDuration(response.data.Data.duration) diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/FlotingWidgetInput.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/FlotingWidgetInput.tsx index e389802..1164a84 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/FlotingWidgetInput.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/FlotingWidgetInput.tsx @@ -45,7 +45,7 @@ const FlotingWidgetInput = (props: Props) => { try { const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/A_floatWidget/${selectedChartId.id}/${organization}`); if (response.status === 200) { - console.log(response.data); + setSelections(response.data.Data.measurements) setDuration(response.data.Data.duration) diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/WarehouseThroughputInputComponent.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/WarehouseThroughputInputComponent.tsx index c35211e..d3ed377 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/WarehouseThroughputInputComponent.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/WarehouseThroughputInputComponent.tsx @@ -45,7 +45,7 @@ const WarehouseThroughputInputComponent = (props: Props) => { try { const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/A_floatWidget/${selectedChartId.id}/${organization}`); if (response.status === 200) { - console.log(response.data); + setSelections(response.data.Data.measurements) setDuration(response.data.Data.duration) diff --git a/app/src/components/ui/componets/Dropped3dWidget.tsx b/app/src/components/ui/componets/Dropped3dWidget.tsx index 7885275..567aa7a 100644 --- a/app/src/components/ui/componets/Dropped3dWidget.tsx +++ b/app/src/components/ui/componets/Dropped3dWidget.tsx @@ -1,10 +1,6 @@ import { useThree } from "@react-three/fiber"; import React, { useEffect, useRef } from "react"; -import { - useAsset3dWidget, - useSocketStore, - useWidgetSubOption, -} from "../../../store/store"; +import { useAsset3dWidget, useSocketStore, useWidgetSubOption } from "../../../store/store"; import useModuleStore from "../../../store/useModuleStore"; import { ThreeState } from "../../../types/world/worldTypes"; import * as THREE from "three"; @@ -17,391 +13,413 @@ import { generateUniqueId } from "../../../functions/generateUniqueId"; import { adding3dWidgets } from "../../../services/realTimeVisulization/zoneData/add3dWidget"; import { get3dWidgetZoneData } from "../../../services/realTimeVisulization/zoneData/get3dWidgetData"; import { use3DWidget } from "../../../store/useDroppedObjectsStore"; -import { - useEditWidgetOptionsStore, - useLeftData, - useRightClickSelected, - useRightSelected, - useTopData, - useZoneWidgetStore, -} from "../../../store/useZone3DWidgetStore"; +import { useEditWidgetOptionsStore, useLeftData, useRightClickSelected, useRightSelected, useTopData, useZoneWidgetStore } from "../../../store/useZone3DWidgetStore"; import { useWidgetStore } from "../../../store/useWidgetStore"; import EditWidgetOption from "../menu/EditWidgetOption"; +import { delete3dWidgetApi } from "../../../services/realTimeVisulization/zoneData/delete3dWidget"; +import { update3dWidget, update3dWidgetRotation } from "../../../services/realTimeVisulization/zoneData/update3dWidget"; type WidgetData = { - id: string; - type: string; - position: [number, number, number]; - rotation?: [number, number, number]; - tempPosition?: [number, number, number]; + id: string; + type: string; + position: [number, number, number]; + rotation?: [number, number, number]; + tempPosition?: [number, number, number]; }; + export default function Dropped3dWidgets() { - const { widgetSelect } = useAsset3dWidget(); - const { activeModule } = useModuleStore(); - const { raycaster, gl, scene, mouse, camera }: ThreeState = useThree(); - const { widgetSubOption } = useWidgetSubOption(); - const { selectedZone } = useSelectedZoneStore(); - const { top, setTop } = useTopData(); - const { left, setLeft } = useLeftData(); - const { rightSelect, setRightSelect } = useRightSelected(); - const { setEditWidgetOptions } = useEditWidgetOptionsStore(); + const { widgetSelect } = useAsset3dWidget(); + const { activeModule } = useModuleStore(); + const { raycaster, gl, scene, mouse, camera }: ThreeState = useThree(); + const { widgetSubOption } = useWidgetSubOption(); + const { selectedZone } = useSelectedZoneStore(); + const { top, setTop } = useTopData(); + const { left, setLeft } = useLeftData(); + const { rightSelect, setRightSelect } = useRightSelected(); + const { editWidgetOptions, setEditWidgetOptions } = useEditWidgetOptionsStore() + const { zoneWidgetData, setZoneWidgetData, addWidget, updateWidgetPosition, updateWidgetRotation } = useZoneWidgetStore(); + const { setWidgets3D } = use3DWidget(); + const { visualizationSocket } = useSocketStore(); + const { rightClickSelected, setRightClickSelected } = useRightClickSelected(); + const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)); // Floor plane for horizontal move + const verticalPlane = useRef(new THREE.Plane(new THREE.Vector3(0, 0, 1), 0)); // Vertical plane for vertical move + const planeIntersect = useRef(new THREE.Vector3()); + // const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0); + // const verticalPlane = useRef(new THREE.Plane(new THREE.Vector3(0, 0, 1), 0); + // const planeIntersect = useRef(new THREE.Vector3()); + const rotationStartRef = useRef<[number, number, number]>([0, 0, 0]); + const mouseStartRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 }); - const { - zoneWidgetData, - setZoneWidgetData, - addWidget, - updateWidgetPosition, - updateWidgetRotation, - } = useZoneWidgetStore(); - const { setWidgets3D } = use3DWidget(); - const { visualizationSocket } = useSocketStore(); - const { rightClickSelected, setRightClickSelected } = useRightClickSelected(); - const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)); // Floor plane for horizontal move - const verticalPlane = useRef(new THREE.Plane(new THREE.Vector3(0, 0, 1), 0)); // Vertical plane for vertical move - const planeIntersect = useRef(new THREE.Vector3()); - // const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0); - // const verticalPlane = useRef(new THREE.Plane(new THREE.Vector3(0, 0, 1), 0); - // const planeIntersect = useRef(new THREE.Vector3()); - const rotationStartRef = useRef<[number, number, number]>([0, 0, 0]); - const mouseStartRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 }); + useEffect(() => { + if (activeModule !== "visualization") return; + if (!selectedZone.zoneId) return; - useEffect(() => { - if (activeModule !== "visualization") return; - if (!selectedZone.zoneId) return; + const email = localStorage.getItem("email") || ""; + const organization = email?.split("@")[1]?.split(".")[0]; - const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0]; + async function get3dWidgetData() { + const result = await get3dWidgetZoneData(selectedZone.zoneId, organization); + console.log('result: ', result); + setWidgets3D(result); - async function get3dWidgetData() { - const result = await get3dWidgetZoneData( - selectedZone.zoneId, - organization - ); - setWidgets3D(result); + const formattedWidgets = result.map((widget: WidgetData) => ({ + id: widget.id, + type: widget.type, + position: widget.position, + rotation: widget.rotation || [0, 0, 0], + })); - const formattedWidgets = result.map((widget: WidgetData) => ({ - id: widget.id, - type: widget.type, - position: widget.position, - rotation: widget.rotation || [0, 0, 0], - })); - setZoneWidgetData(selectedZone.zoneId, formattedWidgets); - } - - get3dWidgetData(); - }, [selectedZone.zoneId, activeModule]); - - useEffect(() => { - if (activeModule !== "visualization") return; - if (widgetSubOption === "Floating" || widgetSubOption === "2D") return; - if (selectedZone.zoneName === "") return; - - const canvasElement = gl.domElement; - - const onDrop = async (event: DragEvent) => { - event.preventDefault(); - - const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0]; - if (!widgetSelect.startsWith("ui")) return; - const group1 = scene.getObjectByName("itemsGroup"); - if (!group1) return; - - const intersects = raycaster - .intersectObjects(scene.children, true) - .filter( - (intersect) => - !intersect.object.name.includes("Roof") && - !intersect.object.name.includes("agv-collider") && - !intersect.object.name.includes("MeasurementReference") && - !intersect.object.userData.isPathObject && - !(intersect.object.type === "GridHelper") - ); - - if (intersects.length > 0) { - const { x, y, z } = intersects[0].point; - const newWidget: WidgetData = { - id: generateUniqueId(), - type: widgetSelect, - position: [x, y, z], - rotation: [0, 0, 0], - }; - - const add3dWidget = { - organization: organization, - widget: newWidget, - zoneId: selectedZone.zoneId, - }; - - if (visualizationSocket) { - visualizationSocket.emit("v2:viz-3D-widget:add", add3dWidget); + setZoneWidgetData(selectedZone.zoneId, formattedWidgets); } - addWidget(selectedZone.zoneId, newWidget); - } - }; + get3dWidgetData(); + }, [selectedZone.zoneId, activeModule]); - canvasElement.addEventListener("drop", onDrop); - return () => { - canvasElement.removeEventListener("drop", onDrop); - }; - }, [widgetSelect, activeModule, selectedZone.zoneId, widgetSubOption]); + useEffect(() => { + if (activeModule !== "visualization") return; + if (widgetSubOption === "Floating" || widgetSubOption === "2D") return; + if (selectedZone.zoneName === "") return; - const activeZoneWidgets = zoneWidgetData[selectedZone.zoneId] || []; + const canvasElement = gl.domElement; - useEffect(() => { - if (!rightClickSelected) return; - const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0]; - - if (rightSelect === "Duplicate") { - const widgetToDuplicate = activeZoneWidgets.find( - (w: WidgetData) => w.id === rightClickSelected - ); - if (!widgetToDuplicate) return; - const newWidget: WidgetData = { - id: generateUniqueId(), - type: widgetToDuplicate.type, - position: [ - widgetToDuplicate.position[0] + 0.5, - widgetToDuplicate.position[1], - widgetToDuplicate.position[2] + 0.5, - ], - rotation: widgetToDuplicate.rotation || [0, 0, 0], - }; - - const add3dWidget = { - organization, - widget: newWidget, - zoneId: selectedZone.zoneId, - }; - - addWidget(selectedZone.zoneId, newWidget); - setRightSelect(null); - setRightClickSelected(null); - } - - if (rightSelect === "Delete") { - const deleteWidget = { - organization, - widgetId: rightClickSelected, - zoneId: selectedZone.zoneId, - }; - - setZoneWidgetData( - selectedZone.zoneId, - activeZoneWidgets.filter((w: WidgetData) => w.id !== rightClickSelected) - ); - setRightClickSelected(null); - setRightSelect(null); - } - }, [rightSelect, rightClickSelected]); - - useEffect(() => { - const handleMouseDown = (event: MouseEvent) => { - if (!rightClickSelected || !rightSelect) return; - - if (rightSelect === "RotateX" || rightSelect === "RotateY") { - mouseStartRef.current = { x: event.clientX, y: event.clientY }; - - const selectedZone = Object.keys(zoneWidgetData).find( - (zoneId: string) => - zoneWidgetData[zoneId].some( - (widget: WidgetData) => widget.id === rightClickSelected - ) - ); - - if (!selectedZone) return; - - const selectedWidget = zoneWidgetData[selectedZone].find( - (widget: WidgetData) => widget.id === rightClickSelected - ); - if (selectedWidget) { - rotationStartRef.current = selectedWidget.rotation || [0, 0, 0]; - } - } - }; - - const handleMouseMove = (event: MouseEvent) => { - if (!rightClickSelected || !rightSelect) return; - const selectedZone = Object.keys(zoneWidgetData).find((zoneId: string) => - zoneWidgetData[zoneId].some( - (widget: WidgetData) => widget.id === rightClickSelected - ) - ); - if (!selectedZone) return; - - const selectedWidget = zoneWidgetData[selectedZone].find( - (widget: WidgetData) => widget.id === rightClickSelected - ); - if (!selectedWidget) return; - - const rect = gl.domElement.getBoundingClientRect(); - mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; - mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; - - raycaster.setFromCamera(mouse, camera); - - if ( - rightSelect === "Horizontal Move" && - raycaster.ray.intersectPlane(plane.current, planeIntersect.current) - ) { - const newPosition: [number, number, number] = [ - planeIntersect.current.x, - selectedWidget.position[1], - planeIntersect.current.z, - ]; - updateWidgetPosition(selectedZone, rightClickSelected, newPosition); - console.log("Horizontal Move - Final Position:", newPosition); - } - - if (rightSelect === "Vertical Move") { - if ( - raycaster.ray.intersectPlane( - verticalPlane.current, - planeIntersect.current - ) - ) { - updateWidgetPosition(selectedZone, rightClickSelected, [ - selectedWidget.position[0], - planeIntersect.current.y, - selectedWidget.position[2], - ]); - } - } - - if (rightSelect === "RotateX") { - const deltaX = event.clientX - mouseStartRef.current.x; - const rotationSpeed = 0.03; - const newRotation: [number, number, number] = [ - rotationStartRef.current[0] + deltaX * rotationSpeed, - rotationStartRef.current[1], - rotationStartRef.current[2], - ]; - updateWidgetRotation(selectedZone, rightClickSelected, newRotation); - } - - if (rightSelect === "RotateY") { - const deltaY = event.clientY - mouseStartRef.current.y; - const rotationSpeed = 0.03; - const newRotation: [number, number, number] = [ - rotationStartRef.current[0], - rotationStartRef.current[1] + deltaY * rotationSpeed, - rotationStartRef.current[2], - ]; - updateWidgetRotation(selectedZone, rightClickSelected, newRotation); - } - if (rightSelect === "RotateZ") { - const deltaX = event.movementX; - const rotationSpeed = 0.03; - const currentRotation = selectedWidget.rotation || [0, 0, 0]; - const newRotation: [number, number, number] = [ - currentRotation[0], - currentRotation[1], - currentRotation[2] + deltaX * rotationSpeed, - ]; - updateWidgetRotation(selectedZone, rightClickSelected, newRotation); - } - }; - - const handleMouseUp = () => { - if ( - rightClickSelected && - (rightSelect === "Horizontal Move" || - rightSelect === "Vertical Move" || - rightSelect === "RotateX" || - rightSelect === "RotateY" || - rightSelect === "RotateZ") - ) { - setTimeout(() => { - setRightClickSelected(null); - setRightSelect(null); - }, 50); - } - }; - - window.addEventListener("mousedown", handleMouseDown); - window.addEventListener("mousemove", handleMouseMove); - window.addEventListener("mouseup", handleMouseUp); - - return () => { - window.removeEventListener("mousedown", handleMouseDown); - window.removeEventListener("mousemove", handleMouseMove); - window.removeEventListener("mouseup", handleMouseUp); - }; - }, [rightClickSelected, rightSelect, zoneWidgetData, gl]); - - return ( - <> - {activeZoneWidgets.map( - ({ id, type, position, rotation = [0, 0, 0] }: WidgetData) => { - const handleRightClick = (event: React.MouseEvent, id: string) => { + const onDrop = async (event: DragEvent) => { event.preventDefault(); - const canvasElement = document.getElementById( - "real-time-vis-canvas" + + const email = localStorage.getItem("email") || ""; + const organization = email?.split("@")[1]?.split(".")[0]; + if (!widgetSelect.startsWith("ui")) return; + const group1 = scene.getObjectByName("itemsGroup"); + if (!group1) return; + + const intersects = raycaster.intersectObjects(scene.children, true).filter( + (intersect) => + !intersect.object.name.includes("Roof") && + !intersect.object.name.includes("agv-collider") && + !intersect.object.name.includes("MeasurementReference") && + !intersect.object.userData.isPathObject && + !(intersect.object.type === "GridHelper") ); - if (!canvasElement) throw new Error("Canvas element not found"); - const canvasRect = canvasElement.getBoundingClientRect(); - const relativeX = event.clientX - canvasRect.left; - const relativeY = event.clientY - canvasRect.top; - setEditWidgetOptions(true); - setRightClickSelected(id); - setTop(relativeY); - setLeft(relativeX); - }; + if (intersects.length > 0) { + const { x, y, z } = intersects[0].point; + const newWidget: WidgetData = { + id: generateUniqueId(), + type: widgetSelect, + position: [x, y, z], + rotation: [0, 0, 0], + }; - switch (type) { - case "ui-Widget 1": - return ( - handleRightClick(e, id)} - /> - ); - case "ui-Widget 2": - return ( - handleRightClick(e, id)} - /> - ); - case "ui-Widget 3": - return ( - handleRightClick(e, id)} - /> - ); - case "ui-Widget 4": - return ( - handleRightClick(e, id)} - /> - ); - default: - return null; - } + const add3dWidget = { + organization: organization, + widget: newWidget, + zoneId: selectedZone.zoneId + }; + + if (visualizationSocket) { + visualizationSocket.emit("v2:viz-3D-widget:add", add3dWidget); + } + + addWidget(selectedZone.zoneId, newWidget); + } + }; + + canvasElement.addEventListener("drop", onDrop); + return () => { + canvasElement.removeEventListener("drop", onDrop); + }; + }, [widgetSelect, activeModule, selectedZone.zoneId, widgetSubOption]); + + const activeZoneWidgets = zoneWidgetData[selectedZone.zoneId] || []; + + useEffect(() => { + if (!rightClickSelected) return; + const email = localStorage.getItem("email") || ""; + const organization = email?.split("@")[1]?.split(".")[0]; + + if (rightSelect === "Duplicate") { + async function duplicateWidget() { + + + const widgetToDuplicate = activeZoneWidgets.find((w: WidgetData) => w.id === rightClickSelected); + if (!widgetToDuplicate) return; + const newWidget: WidgetData = { + id: generateUniqueId(), + type: widgetToDuplicate.type, + position: [ + widgetToDuplicate.position[0] + 0.5, + widgetToDuplicate.position[1], + widgetToDuplicate.position[2] + 0.5, + ], + rotation: widgetToDuplicate.rotation || [0, 0, 0], + }; + const adding3dWidget = { + organization, + widget: newWidget, + zoneId: selectedZone.zoneId + }; + let response = await adding3dWidgets(selectedZone.zoneId, organization, newWidget) + console.log('response: ', response); + + addWidget(selectedZone.zoneId, newWidget); + setRightSelect(null); + setRightClickSelected(null); + } + duplicateWidget() } - )} - - ); -} + + if (rightSelect === "Delete") { + const deleteWidgetApi = async () => { + try { + const deleteWidget = { + organization, + widgetId: rightClickSelected, + zoneId: selectedZone.zoneId, + }; + + // Call the API to delete the widget + const response = await delete3dWidgetApi(selectedZone.zoneId, organization, rightClickSelected); + + + // if (response?.success) { + // Remove from state only if API call succeeds + setZoneWidgetData( + selectedZone.zoneId, + activeZoneWidgets.filter((w: WidgetData) => w.id !== rightClickSelected) + ); + // } else { + // console.error("Failed to delete widget:", response?.message); + // } + } catch (error) { + console.error("Error deleting widget:", error); + } finally { + setRightClickSelected(null); + setRightSelect(null); + } + }; + + deleteWidgetApi(); + } + }, [rightSelect, rightClickSelected]); + + useEffect(() => { + + const email = localStorage.getItem("email") || ""; + const organization = email?.split("@")[1]?.split(".")[0]; + const handleMouseDown = (event: MouseEvent) => { + if (!rightClickSelected || !rightSelect) return; + + if (rightSelect === "RotateX" || rightSelect === "RotateY") { + mouseStartRef.current = { x: event.clientX, y: event.clientY }; + + const selectedZone = Object.keys(zoneWidgetData).find((zoneId: string) => + zoneWidgetData[zoneId].some((widget: WidgetData) => widget.id === rightClickSelected) + ); + + if (!selectedZone) return; + + const selectedWidget = zoneWidgetData[selectedZone].find((widget: WidgetData) => widget.id === rightClickSelected); + if (selectedWidget) { + rotationStartRef.current = selectedWidget.rotation || [0, 0, 0]; + } + } + }; + + const handleMouseMove = (event: MouseEvent) => { + if (!rightClickSelected || !rightSelect) return; + const selectedZone = Object.keys(zoneWidgetData).find((zoneId: string) => + zoneWidgetData[zoneId].some((widget: WidgetData) => widget.id === rightClickSelected) + ); + if (!selectedZone) return; + + const selectedWidget = zoneWidgetData[selectedZone].find((widget: WidgetData) => widget.id === rightClickSelected); + if (!selectedWidget) return; + + const rect = gl.domElement.getBoundingClientRect(); + mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; + mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; + + raycaster.setFromCamera(mouse, camera); + + if (rightSelect === "Horizontal Move" && raycaster.ray.intersectPlane(plane.current, planeIntersect.current)) { + const newPosition: [number, number, number] = [ + planeIntersect.current.x, + selectedWidget.position[1], + planeIntersect.current.z + ]; + updateWidgetPosition(selectedZone, rightClickSelected, newPosition); + + } + + if (rightSelect === "Vertical Move") { + if (raycaster.ray.intersectPlane(verticalPlane.current, planeIntersect.current)) { + updateWidgetPosition(selectedZone, rightClickSelected, [ + selectedWidget.position[0], + planeIntersect.current.y, + selectedWidget.position[2] + ]); + } + } + + if (rightSelect === "RotateX") { + const deltaX = event.clientX - mouseStartRef.current.x; + const rotationSpeed = 0.03; + const newRotation: [number, number, number] = [ + rotationStartRef.current[0] + deltaX * rotationSpeed, + rotationStartRef.current[1], + rotationStartRef.current[2] + ]; + updateWidgetRotation(selectedZone, rightClickSelected, newRotation); + } + + if (rightSelect === "RotateY") { + const deltaY = event.clientY - mouseStartRef.current.y; + const rotationSpeed = 0.03; + const newRotation: [number, number, number] = [ + rotationStartRef.current[0], + rotationStartRef.current[1] + deltaY * rotationSpeed, + rotationStartRef.current[2] + ]; + updateWidgetRotation(selectedZone, rightClickSelected, newRotation); + } + if (rightSelect === "RotateZ") { + const deltaX = event.movementX; + const rotationSpeed = 0.03; + const currentRotation = selectedWidget.rotation || [0, 0, 0]; + const newRotation: [number, number, number] = [ + currentRotation[0], + currentRotation[1], + currentRotation[2] + deltaX * rotationSpeed + ]; + updateWidgetRotation(selectedZone, rightClickSelected, newRotation); + } + + }; + + const handleMouseUp = () => { + if (!rightClickSelected || !rightSelect) return; + + const selectedZone = Object.keys(zoneWidgetData).find(zoneId => + zoneWidgetData[zoneId].some(widget => widget.id === rightClickSelected) + ); + + if (!selectedZone) return; + + const selectedWidget = zoneWidgetData[selectedZone].find(widget => widget.id === rightClickSelected); + if (!selectedWidget) return; + + // Format values to 2 decimal places + const formatValues = (vals: number[]) => vals.map(val => parseFloat(val.toFixed(2))); + + if (rightSelect === "Horizontal Move" || rightSelect === "Vertical Move") { + console.log(`${rightSelect} Completed - Full Position:`, formatValues(selectedWidget.position)); + let lastPosition = formatValues(selectedWidget.position) as [number, number, number]; + + (async () => { + let response = await update3dWidget(selectedZone, organization, rightClickSelected, lastPosition); + console.log('response: ', response); + if (response) { + console.log("Widget position updated in API:", response); + } + })(); + } + else if (rightSelect.includes("Rotate")) { + const rotation = selectedWidget.rotation || [0, 0, 0]; + console.log(`${rightSelect} Completed - Full Rotation:`, formatValues(rotation)); + let lastPosition = formatValues(rotation) as [number, number, number]; + console.log('lastPosition: ', lastPosition); + + (async () => { + let response = await update3dWidgetRotation(selectedZone, organization, rightClickSelected, lastPosition); + console.log('response: ', response); + if (response) { + console.log("Widget position updated in API:", response); + } + })(); + } + + // Reset selection + setTimeout(() => { + setRightClickSelected(null); + setRightSelect(null); + }, 50); + }; + window.addEventListener("mousedown", handleMouseDown); + window.addEventListener("mousemove", handleMouseMove); + window.addEventListener("mouseup", handleMouseUp); + + return () => { + window.removeEventListener("mousedown", handleMouseDown); + window.removeEventListener("mousemove", handleMouseMove); + window.removeEventListener("mouseup", handleMouseUp); + }; + }, [rightClickSelected, rightSelect, zoneWidgetData, gl]); + + return ( + <> + {activeZoneWidgets.map(({ id, type, position, rotation = [0, 0, 0] }: WidgetData) => { + const handleRightClick = (event: React.MouseEvent, id: string) => { + event.preventDefault(); + const canvasElement = document.getElementById("real-time-vis-canvas"); + if (!canvasElement) throw new Error("Canvas element not found"); + const canvasRect = canvasElement.getBoundingClientRect(); + const relativeX = event.clientX - canvasRect.left; + const relativeY = event.clientY - canvasRect.top; + setEditWidgetOptions(true); + setRightClickSelected(id); + setTop(relativeY); + setLeft(relativeX); + }; + + switch (type) { + case "ui-Widget 1": + return ( + handleRightClick(e, id)} + /> + ); + case "ui-Widget 2": + return ( + handleRightClick(e, id)} + /> + ); + case "ui-Widget 3": + return ( + handleRightClick(e, id)} + /> + ); + case "ui-Widget 4": + return ( + handleRightClick(e, id)} + /> + ); + default: + return null; + } + })} + + ); +} \ No newline at end of file diff --git a/app/src/components/ui/componets/DroppedFloatingWidgets.tsx b/app/src/components/ui/componets/DroppedFloatingWidgets.tsx index 8cf1f86..465e8e4 100644 --- a/app/src/components/ui/componets/DroppedFloatingWidgets.tsx +++ b/app/src/components/ui/componets/DroppedFloatingWidgets.tsx @@ -112,7 +112,7 @@ const DroppedObjects: React.FC = () => { const zoneEntries = Object.entries(zones); if (zoneEntries.length === 0) return null; const [zoneName, zone] = zoneEntries[0]; - + function handleDuplicate(zoneName: string, index: number) { setOpenKebabId(null); @@ -123,14 +123,14 @@ const DroppedObjects: React.FC = () => { try { const email = localStorage.getItem("email") || ""; const organization = email?.split("@")[1]?.split(".")[0]; - - + + let deleteFloatingWidget = { floatWidgetID: id, organization: organization, zoneId: zone.zoneId } - + if (visualizationSocket) { visualizationSocket.emit("v2:viz-float:delete", deleteFloatingWidget) } @@ -143,7 +143,7 @@ const DroppedObjects: React.FC = () => { // deleteObject(zoneName, id, index); // Call the deleteObject method from the store // } } catch (error) { - + } } @@ -448,7 +448,7 @@ const DroppedObjects: React.FC = () => { // ...zone.objects[draggingIndex.index], // position: boundedPosition, // }); - + let updateFloatingWidget = { organization: organization, @@ -456,7 +456,7 @@ const DroppedObjects: React.FC = () => { ...zone.objects[draggingIndex.index], position: boundedPosition, }, - index:draggingIndex.index, + index: draggingIndex.index, zoneId: zone.zoneId } if (visualizationSocket) { @@ -464,7 +464,7 @@ const DroppedObjects: React.FC = () => { } // if (response.message === "Widget updated successfully") { - + console.log('boundedPosition: ', boundedPosition); updateObjectPosition(zoneName, draggingIndex.index, boundedPosition); // } @@ -479,7 +479,7 @@ const DroppedObjects: React.FC = () => { // animationRef.current = null; // } } catch (error) { - + } finally { // Clean up regardless of success or failure setDraggingIndex(null); @@ -509,43 +509,37 @@ const DroppedObjects: React.FC = () => { {zone.objects.map((obj, index) => (
{ @@ -559,7 +553,7 @@ const DroppedObjects: React.FC = () => { ) : obj.className === "warehouseThroughput floating" ? ( <> - + ) : obj.className === "fleetEfficiency floating" ? ( <> diff --git a/app/src/components/ui/componets/RealTimeVisulization.tsx b/app/src/components/ui/componets/RealTimeVisulization.tsx index 4b8d7c8..5a47964 100644 --- a/app/src/components/ui/componets/RealTimeVisulization.tsx +++ b/app/src/components/ui/componets/RealTimeVisulization.tsx @@ -23,11 +23,8 @@ import RenderOverlay from "../../templates/Overlay"; import ConfirmationPopup from "../../layout/confirmationPopup/ConfirmationPopup"; import DroppedObjects from "./DroppedFloatingWidgets"; import EditWidgetOption from "../menu/EditWidgetOption"; -import { - useRightClickSelected, - useRightSelected, - useEditWidgetOptionsStore, -} from "../../../store/useZone3DWidgetStore"; +import { useEditWidgetOptionsStore, useRightClickSelected, useRightSelected } from "../../../store/useZone3DWidgetStore"; + type Side = "top" | "bottom" | "left" | "right"; @@ -60,9 +57,11 @@ const RealTimeVisulization: React.FC = () => { const [droppedObjects, setDroppedObjects] = useState([]); const [zonesData, setZonesData] = useState({}); const { selectedZone, setSelectedZone } = useSelectedZoneStore(); - - const { editWidgetOptions, setEditWidgetOptions } = useEditWidgetOptionsStore(); - const { rightClickSelected, setRightClickSelected } = useRightClickSelected(); + + + const { rightSelect, setRightSelect } = useRightSelected() + const { editWidgetOptions, setEditWidgetOptions } = useEditWidgetOptionsStore() + const { rightClickSelected, setRightClickSelected } = useRightClickSelected() const [openConfirmationPopup, setOpenConfirmationPopup] = useState(false); const [floatingWidgets, setFloatingWidgets] = useState< @@ -71,7 +70,7 @@ const RealTimeVisulization: React.FC = () => { const { widgetSelect, setWidgetSelect } = useAsset3dWidget(); const { widgetSubOption, setWidgetSubOption } = useWidgetSubOption(); const { visualizationSocket } = useSocketStore(); - const { setRightSelect } = useRightSelected(); + useEffect(() => { async function GetZoneData() { @@ -100,7 +99,7 @@ const RealTimeVisulization: React.FC = () => { {} ); setZonesData(formattedData); - } catch (error) {} + } catch (error) { } } GetZoneData(); @@ -198,8 +197,27 @@ const RealTimeVisulization: React.FC = () => { ], }, })); - } catch (error) {} + } catch (error) { } }; + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + const editWidgetOptions = document.querySelector( + ".editWidgetOptions-wrapper" + ); + if ( + editWidgetOptions && + !editWidgetOptions.contains(event.target as Node) + ) { + setRightClickSelected(null); + setRightSelect(null); + } + }; + + document.addEventListener("mousedown", handleClickOutside); + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, [setRightClickSelected]); // Add this useEffect hook to your component useEffect(() => { @@ -264,14 +282,12 @@ const RealTimeVisulization: React.FC = () => { editWidgetOptions && rightClickSelected && ( diff --git a/app/src/components/ui/menu/EditWidgetOption.tsx b/app/src/components/ui/menu/EditWidgetOption.tsx index f1d6263..1c1fa2e 100644 --- a/app/src/components/ui/menu/EditWidgetOption.tsx +++ b/app/src/components/ui/menu/EditWidgetOption.tsx @@ -8,22 +8,19 @@ import { } from "../../../store/useZone3DWidgetStore"; interface EditWidgetOptionProps { - setWidgetSelect: any; options: string[]; } const EditWidgetOption: React.FC = ({ - setWidgetSelect, options, }) => { - const { top, setTop } = useTopData(); - const { left, setLeft } = useLeftData(); - const { rightSelect, setRightSelect } = useRightSelected(); + const { top } = useTopData(); + const { left } = useLeftData(); + const { setRightSelect } = useRightSelected(); const { setEditWidgetOptions } = useEditWidgetOptionsStore(); useEffect(() => { - console.log("left: ", left); - console.log("top: ", top); + }, [top, left]); return ( diff --git a/app/src/components/ui/realTimeVis/charts/BarGraphComponent.tsx b/app/src/components/ui/realTimeVis/charts/BarGraphComponent.tsx index 4876fe4..f6589a2 100644 --- a/app/src/components/ui/realTimeVis/charts/BarGraphComponent.tsx +++ b/app/src/components/ui/realTimeVis/charts/BarGraphComponent.tsx @@ -238,7 +238,7 @@ const BarGraphComponent = ({ }; useEffect(() => { - console.log("titleeeeeeeeeeeeeeeeeee",title); + },[]) // Memoize Theme Colors diff --git a/app/src/components/ui/realTimeVis/charts/DoughnutGraphComponent.tsx b/app/src/components/ui/realTimeVis/charts/DoughnutGraphComponent.tsx index 6eec49e..93c2960 100644 --- a/app/src/components/ui/realTimeVis/charts/DoughnutGraphComponent.tsx +++ b/app/src/components/ui/realTimeVis/charts/DoughnutGraphComponent.tsx @@ -51,7 +51,7 @@ const DoughnutGraphComponent = ({ }; useEffect(() => { - console.log("titleeeeeeeeeeeeeeeeeee",title); + },[]) // Memoize Theme Colors diff --git a/app/src/components/ui/realTimeVis/charts/LineGraphComponent.tsx b/app/src/components/ui/realTimeVis/charts/LineGraphComponent.tsx index bf76add..c7f7252 100644 --- a/app/src/components/ui/realTimeVis/charts/LineGraphComponent.tsx +++ b/app/src/components/ui/realTimeVis/charts/LineGraphComponent.tsx @@ -51,7 +51,7 @@ const LineGraphComponent = ({ }; useEffect(() => { - console.log("titleeeeeeeeeeeeeeeeeee",title); + },[]) // Memoize Theme Colors diff --git a/app/src/components/ui/realTimeVis/charts/PieGraphComponent.tsx b/app/src/components/ui/realTimeVis/charts/PieGraphComponent.tsx index 094b9e7..d7cc0da 100644 --- a/app/src/components/ui/realTimeVis/charts/PieGraphComponent.tsx +++ b/app/src/components/ui/realTimeVis/charts/PieGraphComponent.tsx @@ -237,7 +237,7 @@ const PieChartComponent = ({ }; useEffect(() => { - console.log("titleeeeeeeeeeeeeeeeeee",title); + },[]) // Memoize Theme Colors diff --git a/app/src/components/ui/realTimeVis/charts/PolarAreaGraphComponent.tsx b/app/src/components/ui/realTimeVis/charts/PolarAreaGraphComponent.tsx index 92581c0..fb87080 100644 --- a/app/src/components/ui/realTimeVis/charts/PolarAreaGraphComponent.tsx +++ b/app/src/components/ui/realTimeVis/charts/PolarAreaGraphComponent.tsx @@ -51,7 +51,7 @@ const PolarAreaGraphComponent = ({ }; useEffect(() => { - console.log("titleeeeeeeeeeeeeeeeeee",title); + },[]) // Memoize Theme Colors diff --git a/app/src/services/realTimeVisulization/zoneData/add3dWidget.ts b/app/src/services/realTimeVisulization/zoneData/add3dWidget.ts index 82562b7..401a5bf 100644 --- a/app/src/services/realTimeVisulization/zoneData/add3dWidget.ts +++ b/app/src/services/realTimeVisulization/zoneData/add3dWidget.ts @@ -5,9 +5,6 @@ export const adding3dWidgets = async ( organization: string, widget: {} ) => { - console.log('widget: ', widget); - console.log('organization: ', organization); - console.log('zoneId: ', zoneId); try { const response = await fetch( `${url_Backend_dwinzo}/api/v2/3dwidget/save`, diff --git a/app/src/services/realTimeVisulization/zoneData/delete3dWidget.ts b/app/src/services/realTimeVisulization/zoneData/delete3dWidget.ts new file mode 100644 index 0000000..fe868f1 --- /dev/null +++ b/app/src/services/realTimeVisulization/zoneData/delete3dWidget.ts @@ -0,0 +1,38 @@ +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; +// let url_Backend_dwinzo = `http://192.168.0.102:5000`; + +export const delete3dWidgetApi = async ( + zoneId: string, + organization: string, + id: string +) => { + console.log("zoneId: ", zoneId); + console.log("organization: ", organization); + console.log("id: ", id); + + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v2/widget3D/delete`, + { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, zoneId, id }), + } + ); + + if (!response.ok) { + throw new Error("Failed to delete floating widget in the zone"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/realTimeVisulization/zoneData/update3dWidget.ts b/app/src/services/realTimeVisulization/zoneData/update3dWidget.ts new file mode 100644 index 0000000..553fc68 --- /dev/null +++ b/app/src/services/realTimeVisulization/zoneData/update3dWidget.ts @@ -0,0 +1,81 @@ +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; +// let url_Backend_dwinzo = `http://192.168.0.102:5000`; +export const update3dWidget = async ( + zoneId: string, + organization: string, + id: string, + position?: [number, number, number] +) => { + console.log("organization: ", organization); + console.log("zoneId: ", zoneId); + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v2/modifyPR/widget3D`, + { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + organization, + zoneId, + id, + position, + }), + } + ); + + if (!response.ok) { + throw new Error("Failed to add 3dwidget in the zone"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; + +export const update3dWidgetRotation = async ( + zoneId: string, + organization: string, + id: string, + rotation?: [number, number, number] +) => { + console.log("organization: ", organization); + console.log("zoneId: ", zoneId); + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v2/modifyPR/widget3D`, + { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + organization, + zoneId, + id, + rotation, + }), + } + ); + + if (!response.ok) { + throw new Error("Failed to add 3dwidget in the zone"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/store/useZone3DWidgetStore.ts b/app/src/store/useZone3DWidgetStore.ts index 425674f..7dcaaeb 100644 --- a/app/src/store/useZone3DWidgetStore.ts +++ b/app/src/store/useZone3DWidgetStore.ts @@ -97,7 +97,6 @@ export const useRightSelected = create((set) => ({ setRightSelect: (x) => set({ rightSelect: x }), })); - interface EditWidgetOptionsStore { editWidgetOptions: boolean; setEditWidgetOptions: (value: boolean) => void;