socket added for 3d and floating Widget
This commit is contained in:
@@ -5,11 +5,13 @@ import { useSelectedZoneStore } from "../../../../store/useZoneStore";
|
||||
import { getTemplateData } from "../../../../services/realTimeVisulization/zoneData/getTemplate";
|
||||
import { deleteTemplateApi } from "../../../../services/realTimeVisulization/zoneData/deleteTemplate";
|
||||
import { loadTempleteApi } from "../../../../services/realTimeVisulization/zoneData/loadTemplate";
|
||||
import { useSocketStore } from "../../../../store/store";
|
||||
|
||||
const Templates = () => {
|
||||
const { templates, removeTemplate } = useTemplateStore();
|
||||
const { setTemplates } = useTemplateStore();
|
||||
const { setSelectedZone, selectedZone } = useSelectedZoneStore();
|
||||
const { visualizationSocket } = useSocketStore();
|
||||
|
||||
useEffect(() => {
|
||||
async function templateData() {
|
||||
@@ -30,12 +32,18 @@ const Templates = () => {
|
||||
try {
|
||||
const email = localStorage.getItem("email") || "";
|
||||
const organization = email?.split("@")[1]?.split(".")[0];
|
||||
|
||||
let response = await deleteTemplateApi(id, organization);
|
||||
|
||||
if (response.message === "Template deleted successfully") {
|
||||
removeTemplate(id);
|
||||
let deleteTemplate = {
|
||||
organization: organization,
|
||||
templateID: id,
|
||||
}
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit("v2:viz-template:deleteTemplate", deleteTemplate)
|
||||
}
|
||||
removeTemplate(id);
|
||||
// let response = await deleteTemplateApi(id, organization);
|
||||
|
||||
// if (response.message === "Template deleted successfully") {
|
||||
// }
|
||||
} catch (error) {
|
||||
console.error("Error deleting template:", error);
|
||||
}
|
||||
@@ -48,9 +56,20 @@ const Templates = () => {
|
||||
const email = localStorage.getItem("email") || "";
|
||||
const organization = email?.split("@")[1]?.split(".")[0];
|
||||
|
||||
let response = await loadTempleteApi(template.id, selectedZone.zoneId, organization);
|
||||
let loadingTemplate = {
|
||||
organization: organization,
|
||||
zoneId: selectedZone.zoneId,
|
||||
templateID: template.id,
|
||||
}
|
||||
console.log('template: ', template);
|
||||
console.log('loadingTemplate: ', loadingTemplate);
|
||||
|
||||
if (response.message === "Template placed in Zone") {
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit("v2:viz-template:addToZone", loadingTemplate)
|
||||
}
|
||||
// let response = await loadTempleteApi(template.id, selectedZone.zoneId, organization);
|
||||
|
||||
// if (response.message === "Template placed in Zone") {
|
||||
setSelectedZone({
|
||||
panelOrder: template.panelOrder,
|
||||
activeSides: Array.from(new Set(template.panelOrder)), // No merging with previous `activeSides`
|
||||
@@ -64,7 +83,7 @@ const Templates = () => {
|
||||
useDroppedObjectsStore.getState().addObject(selectedZone.zoneName, val);
|
||||
});
|
||||
}
|
||||
}
|
||||
// }
|
||||
} catch (error) {
|
||||
console.error("Error loading template:", error);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
useMovePoint,
|
||||
useRefTextUpdate,
|
||||
useSelectedWallItem,
|
||||
useSocketStore,
|
||||
useToggleView,
|
||||
useToolMode,
|
||||
useTransformMode,
|
||||
@@ -42,7 +43,7 @@ const Tools: React.FC = () => {
|
||||
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
const [openDrop, setOpenDrop] = useState(false);
|
||||
|
||||
const { visualizationSocket } = useSocketStore();
|
||||
const { activeModule } = useModuleStore();
|
||||
const { isPlaying, setIsPlaying } = usePlayButtonStore();
|
||||
const { addTemplate } = useTemplateStore();
|
||||
@@ -397,6 +398,7 @@ const Tools: React.FC = () => {
|
||||
widgets3D,
|
||||
selectedZone,
|
||||
templates,
|
||||
visualizationSocket
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +92,7 @@ export const DraggableWidget = ({
|
||||
widgetID: widget.id,
|
||||
organization: organization
|
||||
}
|
||||
console.log('deleteWidget: ', deleteWidget);
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit("v2:viz-widget:delete", deleteWidget)
|
||||
}
|
||||
@@ -160,14 +161,27 @@ export const DraggableWidget = ({
|
||||
id: `${widget.id}-copy-${Date.now()}`,
|
||||
};
|
||||
|
||||
const response = await duplicateWidgetApi(selectedZone.zoneId, organization, duplicatedWidget);
|
||||
|
||||
if (response?.message === "Widget created successfully") {
|
||||
setSelectedZone((prevZone: any) => ({
|
||||
...prevZone,
|
||||
widgets: [...prevZone.widgets, duplicatedWidget],
|
||||
}));
|
||||
let duplicateWidget = {
|
||||
organization: organization,
|
||||
zoneId: selectedZone.zoneId,
|
||||
widget: duplicatedWidget
|
||||
}
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit("v2:viz-widget:add", duplicateWidget)
|
||||
}
|
||||
setSelectedZone((prevZone: any) => ({
|
||||
...prevZone,
|
||||
widgets: [...prevZone.widgets, duplicatedWidget],
|
||||
}));
|
||||
|
||||
// const response = await duplicateWidgetApi(selectedZone.zoneId, organization, duplicatedWidget);
|
||||
|
||||
// if (response?.message === "Widget created successfully") {
|
||||
// setSelectedZone((prevZone: any) => ({
|
||||
// ...prevZone,
|
||||
// widgets: [...prevZone.widgets, duplicatedWidget],
|
||||
// }));
|
||||
// }
|
||||
} catch (error) {
|
||||
|
||||
} finally {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
import { useThree } from "@react-three/fiber";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useAsset3dWidget, 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";
|
||||
@@ -14,21 +14,23 @@ 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 { useZoneWidgetStore } from "../../../store/useZone3DWidgetStore";
|
||||
|
||||
export default function Dropped3dWidgets() {
|
||||
const { widgetSelect } = useAsset3dWidget();
|
||||
const { activeModule } = useModuleStore();
|
||||
const { raycaster, gl, scene }: ThreeState = useThree();
|
||||
const { widgetSubOption, setWidgetSubOption } = useWidgetSubOption();
|
||||
const { selectedZone } = useSelectedZoneStore(); // Get the currently active zone
|
||||
// 🔥 Store widget data (id, type, position) based on the selected zone
|
||||
const [zoneWidgetData, setZoneWidgetData] = useState<
|
||||
Record<string, { id: string; type: string; position: [number, number, number] }[]>
|
||||
>({});
|
||||
const { setWidgets3D } = use3DWidget()
|
||||
const { widgetSubOption } = useWidgetSubOption();
|
||||
const { selectedZone } = useSelectedZoneStore();
|
||||
|
||||
// ✅ Use Zustand Store instead of useState
|
||||
const { zoneWidgetData, setZoneWidgetData, addWidget } = useZoneWidgetStore();
|
||||
const { setWidgets3D } = use3DWidget();
|
||||
const { visualizationSocket } = useSocketStore();
|
||||
|
||||
useEffect(() => {
|
||||
if (activeModule !== "visualization") return
|
||||
if (selectedZone.zoneName === "") return;
|
||||
if (activeModule !== "visualization") return;
|
||||
if (!selectedZone.zoneId) return;
|
||||
|
||||
const email = localStorage.getItem("email") || "";
|
||||
const organization = email?.split("@")[1]?.split(".")[0];
|
||||
@@ -36,37 +38,36 @@ export default function Dropped3dWidgets() {
|
||||
async function get3dWidgetData() {
|
||||
let result = await get3dWidgetZoneData(selectedZone.zoneId, organization);
|
||||
console.log('result: ', result);
|
||||
setWidgets3D(result)
|
||||
// Ensure the extracted data has id, type, and position correctly mapped
|
||||
setWidgets3D(result);
|
||||
|
||||
const formattedWidgets = result.map((widget: any) => ({
|
||||
id: widget.id,
|
||||
type: widget.type,
|
||||
position: widget.position,
|
||||
}));
|
||||
|
||||
setZoneWidgetData((prev) => ({
|
||||
...prev,
|
||||
[selectedZone.zoneId]: formattedWidgets,
|
||||
}));
|
||||
setZoneWidgetData(selectedZone.zoneId, formattedWidgets);
|
||||
}
|
||||
|
||||
get3dWidgetData();
|
||||
|
||||
}, [selectedZone.zoneId, activeModule]);
|
||||
|
||||
useEffect(() => {
|
||||
if (activeModule !== "visualization") return;
|
||||
if (widgetSubOption === "Floating") return;
|
||||
if (widgetSubOption === "2D") return;
|
||||
if (selectedZone.zoneName === "") return
|
||||
if (widgetSubOption === "Floating" || widgetSubOption === "2D") return;
|
||||
if (selectedZone.zoneName === "") return;
|
||||
|
||||
const canvasElement = gl.domElement;
|
||||
|
||||
const onDrop = async (event: DragEvent) => {
|
||||
event.preventDefault(); // Prevent default browser behavior
|
||||
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") &&
|
||||
@@ -75,40 +76,41 @@ export default function Dropped3dWidgets() {
|
||||
!intersect.object.userData.isPathObject &&
|
||||
!(intersect.object.type === "GridHelper")
|
||||
);
|
||||
|
||||
if (intersects.length > 0) {
|
||||
const { x, y, z } = intersects[0].point;
|
||||
|
||||
// ✅ Explicitly define position as a tuple
|
||||
const newWidget: { id: string; type: string; position: [number, number, number] } = {
|
||||
const newWidget = {
|
||||
id: generateUniqueId(),
|
||||
type: widgetSelect,
|
||||
position: [x, y, z], // Ensures TypeScript recognizes it as a tuple
|
||||
position: [x, y, z] as [number, number, number],
|
||||
};
|
||||
|
||||
|
||||
let response = await adding3dWidgets(selectedZone.zoneId, organization, newWidget)
|
||||
console.log('response: ', response);
|
||||
|
||||
if (response.message === "Widget created successfully") {
|
||||
// ✅ Store widgets uniquely for each zone
|
||||
setZoneWidgetData((prev) => ({
|
||||
...prev,
|
||||
[selectedZone.zoneId]: [...(prev[selectedZone.zoneId] || []), newWidget],
|
||||
}));
|
||||
let add3dWidget = {
|
||||
organization: organization,
|
||||
widget: newWidget,
|
||||
zoneId: selectedZone.zoneId
|
||||
}
|
||||
console.log('add3dWidget: ', add3dWidget);
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit("v2:viz-3D-widget:add", add3dWidget)
|
||||
}
|
||||
|
||||
// let response = await adding3dWidgets(selectedZone.zoneId, organization, newWidget);
|
||||
// console.log('response: ', response);
|
||||
|
||||
// if (response.message === "Widget created successfully") {
|
||||
addWidget(selectedZone.zoneId, newWidget);
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
canvasElement.addEventListener("drop", onDrop);
|
||||
return () => {
|
||||
canvasElement.removeEventListener("drop", onDrop);
|
||||
};
|
||||
}, [widgetSelect, activeModule, selectedZone.zoneId, widgetSubOption]);
|
||||
|
||||
// Get widgets for the currently active zone
|
||||
const activeZoneWidgets = zoneWidgetData[selectedZone.zoneId] || [];
|
||||
console.log('activeZoneWidgets: ', activeZoneWidgets);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -130,5 +132,3 @@ export default function Dropped3dWidgets() {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import TotalCardComponent from "../realTimeVis/floating/TotalCardComponent";
|
||||
import WarehouseThroughputComponent from "../realTimeVis/floating/WarehouseThroughputComponent";
|
||||
import FleetEfficiencyComponent from "../realTimeVis/floating/FleetEfficiencyComponent";
|
||||
import { useWidgetStore } from "../../../store/useWidgetStore";
|
||||
import { useSocketStore } from "../../../store/store";
|
||||
interface DraggingState {
|
||||
zone: string;
|
||||
index: number;
|
||||
@@ -43,6 +44,7 @@ interface DraggingState {
|
||||
};
|
||||
}
|
||||
const DroppedObjects: React.FC = () => {
|
||||
const { visualizationSocket } = useSocketStore();
|
||||
const zones = useDroppedObjectsStore((state) => state.zones);
|
||||
const [openKebabId, setOpenKebabId] = useState<string | null>(null);
|
||||
const updateObjectPosition = useDroppedObjectsStore(
|
||||
@@ -98,29 +100,41 @@ 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)
|
||||
duplicateObject(zoneName, index); // Call the duplicateObject method from the store
|
||||
}
|
||||
|
||||
async function handleDelete(zoneName: string, id: string, index: number) {
|
||||
async function handleDelete(zoneName: string, id: string) {
|
||||
try {
|
||||
const email = localStorage.getItem("email") || "";
|
||||
const organization = email?.split("@")[1]?.split(".")[0];
|
||||
|
||||
let res = await deleteFloatingWidgetApi(id, organization);
|
||||
console.log('res: ', res);
|
||||
|
||||
if (res.message === "FloatingWidget deleted successfully") {
|
||||
deleteObject(zoneName, id, index); // Call the deleteObject method from the store
|
||||
|
||||
|
||||
let deleteFloatingWidget = {
|
||||
floatWidgetID: id,
|
||||
organization: organization,
|
||||
zoneId: zone.zoneId
|
||||
}
|
||||
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit("v2:viz-float:delete", deleteFloatingWidget)
|
||||
}
|
||||
deleteObject(zoneName, id);
|
||||
|
||||
// let res = await deleteFloatingWidgetApi(id, organization);
|
||||
// s
|
||||
|
||||
// if (res.message === "FloatingWidget deleted successfully") {
|
||||
// deleteObject(zoneName, id, index); // Call the deleteObject method from the store
|
||||
// }
|
||||
} catch (error) {
|
||||
console.error("Error deleting floating widget:", error);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const handlePointerDown = (event: React.PointerEvent, index: number) => {
|
||||
if ((event.target as HTMLElement).closest(".kebab-options") || (event.target as HTMLElement).closest(".kebab")) {
|
||||
return; // Prevent dragging when clicking on the kebab menu or its options
|
||||
@@ -278,15 +292,30 @@ const DroppedObjects: React.FC = () => {
|
||||
// Save to backend
|
||||
const email = localStorage.getItem("email") || "";
|
||||
const organization = email?.split("@")[1]?.split(".")[0];
|
||||
const response = await addingFloatingWidgets(zone.zoneId, organization, {
|
||||
...zone.objects[draggingIndex.index],
|
||||
position: boundedPosition,
|
||||
});
|
||||
console.log('response: ', response);
|
||||
// const response = await addingFloatingWidgets(zone.zoneId, organization, {
|
||||
// ...zone.objects[draggingIndex.index],
|
||||
// position: boundedPosition,
|
||||
// });
|
||||
|
||||
|
||||
if (response.message === "Widget updated successfully") {
|
||||
updateObjectPosition(zoneName, draggingIndex.index, boundedPosition);
|
||||
let updateFloatingWidget = {
|
||||
organization: organization,
|
||||
widget: {
|
||||
...zone.objects[draggingIndex.index],
|
||||
position: boundedPosition,
|
||||
},
|
||||
index:draggingIndex.index,
|
||||
zoneId: zone.zoneId
|
||||
}
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit("v2:viz-float:add", updateFloatingWidget)
|
||||
}
|
||||
|
||||
// if (response.message === "Widget updated successfully") {
|
||||
|
||||
console.log('boundedPosition: ', boundedPosition);
|
||||
updateObjectPosition(zoneName, draggingIndex.index, boundedPosition);
|
||||
// }
|
||||
|
||||
// // Clean up
|
||||
// setDraggingIndex(null);
|
||||
@@ -298,7 +327,7 @@ const DroppedObjects: React.FC = () => {
|
||||
// animationRef.current = null;
|
||||
// }
|
||||
} catch (error) {
|
||||
console.error("Error in handlePointerUp:", error);
|
||||
|
||||
} finally {
|
||||
// Clean up regardless of success or failure
|
||||
setDraggingIndex(null);
|
||||
@@ -390,7 +419,7 @@ const DroppedObjects: React.FC = () => {
|
||||
</div>
|
||||
<div className="edit btn" onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
handleDelete(zoneName, obj.id, index); // Call the delete handler
|
||||
handleDelete(zoneName, obj.id); // Call the delete handler
|
||||
}}>
|
||||
<div className="icon">
|
||||
<DeleteIcon />
|
||||
|
||||
@@ -153,8 +153,6 @@ const Panel: React.FC<PanelProps> = ({
|
||||
zoneId: selectedZone.zoneId,
|
||||
widget: newWidget
|
||||
}
|
||||
console.log('newWidget: ', newWidget);
|
||||
console.log('addWidget: ', addWidget);
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit("v2:viz-widget:add", addWidget)
|
||||
}
|
||||
@@ -163,18 +161,18 @@ const Panel: React.FC<PanelProps> = ({
|
||||
widgets: [...prev.widgets, newWidget],
|
||||
}));
|
||||
|
||||
// try {
|
||||
// let response = await addingWidgets(selectedZone.zoneId, organization, newWidget);
|
||||
try {
|
||||
// let response = await addingWidgets(selectedZone.zoneId, organization, newWidget);
|
||||
|
||||
// if (response.message === "Widget created successfully") {
|
||||
// setSelectedZone((prev) => ({
|
||||
// ...prev,
|
||||
// widgets: [...prev.widgets, newWidget],
|
||||
// }));
|
||||
// }
|
||||
// } catch (error) {
|
||||
// console.error("Error adding widget:", error);
|
||||
// }
|
||||
// if (response.message === "Widget created successfully") {
|
||||
// setSelectedZone((prev) => ({
|
||||
// ...prev,
|
||||
// widgets: [...prev.widgets, newWidget],
|
||||
// }));
|
||||
// }
|
||||
} catch (error) {
|
||||
console.error("Error adding widget:", error);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -144,12 +144,6 @@ const RealTimeVisulization: React.FC = () => {
|
||||
};
|
||||
console.log('newObject: ', newObject);
|
||||
|
||||
let response = await addingFloatingWidgets(
|
||||
selectedZone.zoneId,
|
||||
organization,
|
||||
newObject
|
||||
);
|
||||
|
||||
// Only set zone if it’s not already in the store (prevents overwriting objects)
|
||||
const existingZone =
|
||||
useDroppedObjectsStore.getState().zones[selectedZone.zoneName];
|
||||
@@ -159,12 +153,28 @@ const RealTimeVisulization: React.FC = () => {
|
||||
.setZone(selectedZone.zoneName, selectedZone.zoneId);
|
||||
}
|
||||
|
||||
// Add the dropped object to the zone if the API call is successful
|
||||
if (response.message === "FloatWidget created successfully") {
|
||||
useDroppedObjectsStore
|
||||
.getState()
|
||||
.addObject(selectedZone.zoneName, newObject);
|
||||
let addFloatingWidget = {
|
||||
organization: organization,
|
||||
widget: newObject,
|
||||
zoneId: selectedZone.zoneId
|
||||
}
|
||||
console.log('newObject: ', newObject);
|
||||
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit("v2:viz-float:add", addFloatingWidget)
|
||||
}
|
||||
|
||||
// let response = await addingFloatingWidgets(
|
||||
// selectedZone.zoneId,
|
||||
// organization,
|
||||
// newObject
|
||||
// );
|
||||
// Add the dropped object to the zone if the API call is successful
|
||||
// if (response.message === "FloatWidget created successfully") {
|
||||
useDroppedObjectsStore
|
||||
.getState()
|
||||
.addObject(selectedZone.zoneName, newObject);
|
||||
// }
|
||||
|
||||
// Update floating widgets state
|
||||
setFloatingWidgets((prevWidgets) => ({
|
||||
@@ -209,6 +219,11 @@ const RealTimeVisulization: React.FC = () => {
|
||||
{activeModule === "visualization" && selectedZone.zoneName !== "" && <DroppedObjects />}
|
||||
{activeModule === "visualization" && <SocketRealTimeViz />}
|
||||
{/* <DroppedObjects /> */}
|
||||
{/* <RenderOverlay>
|
||||
<EditWidgetOption
|
||||
options={["Dublicate", "Vertical Move", "Horizontal Move", "Delete"]}
|
||||
/>
|
||||
</RenderOverlay> */}
|
||||
{activeModule === "visualization" && (
|
||||
<>
|
||||
<DisplayZone
|
||||
|
||||
Reference in New Issue
Block a user