Refactor canvas element references to use "work-space-three-d-canvas"; update tooltip keyboard shortcut; clean up unused imports and comments; enhance keyboard shortcut handling for module switching and tool selection.
This commit is contained in:
@@ -28,7 +28,7 @@ const Header: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="tooltip">{toggleUI ? "Hide" : "Show"} sidebar (ctrl + .)</div>
|
<div className="tooltip">{toggleUI ? "Hide" : "Show"} sidebar (ctrl + \)</div>
|
||||||
<ToggleSidebarIcon />
|
<ToggleSidebarIcon />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect } from "react";
|
import React from "react";
|
||||||
import useModuleStore from "../../store/useModuleStore";
|
import useModuleStore from "../../store/useModuleStore";
|
||||||
import {
|
import {
|
||||||
BuilderIcon,
|
BuilderIcon,
|
||||||
@@ -14,45 +14,60 @@ const ModuleToggle: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="module-toggle-container">
|
<div className="module-toggle-container">
|
||||||
<div
|
<button
|
||||||
className={`module-list ${activeModule === "builder" && "active"}`}
|
className={`module-list ${activeModule === "builder" ? "active" : ""}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActiveModule("builder");
|
setActiveModule("builder");
|
||||||
setToggleUI(localStorage.getItem('navBarUi') ? localStorage.getItem('navBarUi') === 'true' : true)
|
setToggleUI(
|
||||||
|
localStorage.getItem("navBarUi")
|
||||||
|
? localStorage.getItem("navBarUi") === "true"
|
||||||
|
: true
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="icon">
|
<div className="icon">
|
||||||
<BuilderIcon isActive={activeModule === "builder"} />
|
<BuilderIcon isActive={activeModule === "builder"} />
|
||||||
</div>
|
</div>
|
||||||
<div className="module">Builder</div>
|
<div className="module">Builder</div>
|
||||||
</div>
|
</button>
|
||||||
<div
|
<button
|
||||||
className={`module-list ${activeModule === "simulation" && "active"}`}
|
className={`module-list ${
|
||||||
|
activeModule === "simulation" ? "active" : ""
|
||||||
|
}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActiveModule("simulation");
|
setActiveModule("simulation");
|
||||||
setToggleUI(localStorage.getItem('navBarUi') ? localStorage.getItem('navBarUi') === 'true' : true)
|
setToggleUI(
|
||||||
|
localStorage.getItem("navBarUi")
|
||||||
|
? localStorage.getItem("navBarUi") === "true"
|
||||||
|
: true
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="icon">
|
<div className="icon">
|
||||||
<SimulationIcon isActive={activeModule === "simulation"} />
|
<SimulationIcon isActive={activeModule === "simulation"} />
|
||||||
</div>
|
</div>
|
||||||
<div className="module">Simulation</div>
|
<div className="module">Simulation</div>
|
||||||
</div>
|
</button>
|
||||||
<div
|
<button
|
||||||
className={`module-list ${activeModule === "visualization" && "active"
|
className={`module-list ${
|
||||||
}`}
|
activeModule === "visualization" ? "active" : ""
|
||||||
|
}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActiveModule("visualization");
|
setActiveModule("visualization");
|
||||||
setToggleUI(localStorage.getItem('navBarUi') ? localStorage.getItem('navBarUi') === 'true' : true)
|
setToggleUI(
|
||||||
|
localStorage.getItem("navBarUi")
|
||||||
|
? localStorage.getItem("navBarUi") === "true"
|
||||||
|
: true
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="icon">
|
<div className="icon">
|
||||||
<VisualizationIcon isActive={activeModule === "visualization"} />
|
<VisualizationIcon isActive={activeModule === "visualization"} />
|
||||||
</div>
|
</div>
|
||||||
<div className="module">Visualization</div>
|
<div className="module">Visualization</div>
|
||||||
</div>
|
</button>
|
||||||
<div
|
<button
|
||||||
className={`module-list ${activeModule === "market" && "active"}`}
|
className={`module-list ${activeModule === "market" ? "active" : ""}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActiveModule("market");
|
setActiveModule("market");
|
||||||
setToggleUI(false);
|
setToggleUI(false);
|
||||||
@@ -62,7 +77,7 @@ const ModuleToggle: React.FC = () => {
|
|||||||
<CartIcon isActive={activeModule === "market"} />
|
<CartIcon isActive={activeModule === "market"} />
|
||||||
</div>
|
</div>
|
||||||
<div className="module">Market Place</div>
|
<div className="module">Market Place</div>
|
||||||
</div>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -103,10 +103,9 @@ const DropDownList: React.FC<DropDownListProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="dropdown-list-container">
|
<div className="dropdown-list-container">
|
||||||
<div className="head">
|
{/* eslint-disable-next-line */}
|
||||||
<button className="value" onClick={handleToggle}>
|
<div className="head" onClick={handleToggle}>
|
||||||
{value}
|
<div className="value">{value}</div>
|
||||||
</button>
|
|
||||||
<div className="options">
|
<div className="options">
|
||||||
{showFocusIcon && (
|
{showFocusIcon && (
|
||||||
<div className="focus option">
|
<div className="focus option">
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const SimulationPlayer: React.FC = () => {
|
|||||||
setReset(false);
|
setReset(false);
|
||||||
}, 0)
|
}, 0)
|
||||||
}
|
}
|
||||||
}, [isReset])
|
}, [isReset, setReset])
|
||||||
|
|
||||||
// Button functions
|
// Button functions
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ const CamModelsGroup = () => {
|
|||||||
socket.off("userDisConnectResponse");
|
socket.off("userDisConnectResponse");
|
||||||
socket.off("cameraUpdateResponse");
|
socket.off("cameraUpdateResponse");
|
||||||
};
|
};
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [email, loader, navigate, setActiveUsers, socket]);
|
}, [email, loader, navigate, setActiveUsers, socket]);
|
||||||
|
|
||||||
useFrame(() => {
|
useFrame(() => {
|
||||||
@@ -231,30 +232,9 @@ const CamModelsGroup = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// collide validate
|
|
||||||
const collisionThreshold = 0.001;
|
|
||||||
|
|
||||||
const collidedCamUUIDs = new Set<string>();
|
|
||||||
|
|
||||||
for (let i = 0; i < cams.length; i++) {
|
|
||||||
for (let j = i + 1; j < cams.length; j++) {
|
|
||||||
const posA = cams[i].position;
|
|
||||||
const posB = cams[j].position;
|
|
||||||
|
|
||||||
const distSquared =
|
|
||||||
Math.pow(posA.x - posB.x, 2) +
|
|
||||||
Math.pow(posA.y - posB.y, 2) +
|
|
||||||
Math.pow(posA.z - posB.z, 2);
|
|
||||||
|
|
||||||
if (distSquared < collisionThreshold ** 2) {
|
|
||||||
collidedCamUUIDs.add(cams[i].uuid);
|
|
||||||
collidedCamUUIDs.add(cams[j].uuid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group ref={groupRef} name="Cam-Model-Group">
|
<group ref={groupRef} name="Cam-Model-Group">
|
||||||
{cams.map((cam, index) => (
|
{cams.map((cam, index) => (
|
||||||
@@ -277,6 +257,10 @@ const CamModelsGroup = () => {
|
|||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
fontFamily: "Arial, sans-serif",
|
fontFamily: "Arial, sans-serif",
|
||||||
display: `${activeModule !== "visualization" ? "" : "none"}`,
|
display: `${activeModule !== "visualization" ? "" : "none"}`,
|
||||||
|
opacity: `${
|
||||||
|
selectedUser?.name !== cam.userData.userName ? 1 : 0
|
||||||
|
}`,
|
||||||
|
transition: "opacity .2s ease",
|
||||||
}}
|
}}
|
||||||
position={[-0.015, 0, 0.7]}
|
position={[-0.015, 0, 0.7]}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -19,12 +19,10 @@ const CamMode: React.FC = () => {
|
|||||||
const handlePointerLockChange = async () => {
|
const handlePointerLockChange = async () => {
|
||||||
if (document.pointerLockElement && !toggleView) {
|
if (document.pointerLockElement && !toggleView) {
|
||||||
// Pointer is locked
|
// Pointer is locked
|
||||||
} else {
|
} else if (camMode === "FirstPerson" && !toggleView) {
|
||||||
// Pointer is unlocked
|
// Pointer is unlocked
|
||||||
if (camMode === "FirstPerson" && !toggleView) {
|
setCamMode("ThirdPerson");
|
||||||
setCamMode("ThirdPerson");
|
await switchToThirdPerson(state.controls, state.camera);
|
||||||
await switchToThirdPerson(state.controls, state.camera);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ const RealTimeVisulization: React.FC = () => {
|
|||||||
height: 0,
|
height: 0,
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const canvas = document.getElementById("real-time-vis-canvas");
|
const canvas = document.getElementById("work-space-three-d-canvas");
|
||||||
if (!canvas) return;
|
if (!canvas) return;
|
||||||
|
|
||||||
const updateCanvasDimensions = () => {
|
const updateCanvasDimensions = () => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import html2canvas from "html2canvas";
|
import html2canvas from "html2canvas";
|
||||||
|
|
||||||
export const captureVisualization = async (): Promise<string | null> => {
|
export const captureVisualization = async (): Promise<string | null> => {
|
||||||
const container = document.getElementById("real-time-vis-canvas");
|
const container = document.getElementById("work-space-three-d-canvas");
|
||||||
if (!container) {
|
if (!container) {
|
||||||
console.error("Container element not found");
|
console.error("Container element not found");
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export const createHandleDrop = ({
|
|||||||
if (!data || selectedZone.zoneName === "") return;
|
if (!data || selectedZone.zoneName === "") return;
|
||||||
|
|
||||||
const droppedData = JSON.parse(data);
|
const droppedData = JSON.parse(data);
|
||||||
const canvasElement = document.getElementById("real-time-vis-canvas");
|
const canvasElement = document.getElementById("work-space-three-d-canvas");
|
||||||
if (!canvasElement) throw new Error("Canvas element not found");
|
if (!canvasElement) throw new Error("Canvas element not found");
|
||||||
|
|
||||||
const rect = canvasElement.getBoundingClientRect();
|
const rect = canvasElement.getBoundingClientRect();
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ export const DraggableWidget = ({
|
|||||||
// Current: Two identical useEffect hooks for canvas dimensions
|
// Current: Two identical useEffect hooks for canvas dimensions
|
||||||
// Remove the duplicate and keep only one
|
// Remove the duplicate and keep only one
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const canvas = document.getElementById("real-time-vis-canvas");
|
const canvas = document.getElementById("work-space-three-d-canvas");
|
||||||
if (!canvas) return;
|
if (!canvas) return;
|
||||||
|
|
||||||
const updateCanvasDimensions = () => {
|
const updateCanvasDimensions = () => {
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ export default function Dropped3dWidgets() {
|
|||||||
if (widgetSubOption === "Floating" || widgetSubOption === "2D") return;
|
if (widgetSubOption === "Floating" || widgetSubOption === "2D") return;
|
||||||
if (selectedZone.zoneName === "") return;
|
if (selectedZone.zoneName === "") return;
|
||||||
|
|
||||||
const canvasElement = document.getElementById("real-time-vis-canvas");
|
const canvasElement = document.getElementById("work-space-three-d-canvas");
|
||||||
|
|
||||||
if (!canvasElement) return;
|
if (!canvasElement) return;
|
||||||
|
|
||||||
@@ -601,7 +601,7 @@ export default function Dropped3dWidgets() {
|
|||||||
const handleRightClick3d = (event: React.MouseEvent, id: string) => {
|
const handleRightClick3d = (event: React.MouseEvent, id: string) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
const canvasElement = document.getElementById("real-time-vis-canvas");
|
const canvasElement = document.getElementById("work-space-three-d-canvas");
|
||||||
if (!canvasElement) throw new Error("Canvas element not found");
|
if (!canvasElement) throw new Error("Canvas element not found");
|
||||||
|
|
||||||
const canvasRect = canvasElement.getBoundingClientRect();
|
const canvasRect = canvasElement.getBoundingClientRect();
|
||||||
@@ -654,7 +654,7 @@ export default function Dropped3dWidgets() {
|
|||||||
setSelectedChartId({ id: id, type: type })
|
setSelectedChartId({ id: id, type: type })
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const canvasElement = document.getElementById(
|
const canvasElement = document.getElementById(
|
||||||
"real-time-vis-canvas"
|
"work-space-three-d-canvas"
|
||||||
);
|
);
|
||||||
if (!canvasElement) throw new Error("Canvas element not found");
|
if (!canvasElement) throw new Error("Canvas element not found");
|
||||||
const canvasRect = canvasElement.getBoundingClientRect();
|
const canvasRect = canvasElement.getBoundingClientRect();
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { WalletIcon } from "../../../../components/icons/3dChartIcons";
|
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
useDroppedObjectsStore,
|
useDroppedObjectsStore,
|
||||||
Zones,
|
|
||||||
} from "../../../../store/visualization/useDroppedObjectsStore";
|
} from "../../../../store/visualization/useDroppedObjectsStore";
|
||||||
import useModuleStore from "../../../../store/useModuleStore";
|
import useModuleStore from "../../../../store/useModuleStore";
|
||||||
import { determinePosition } from "../../functions/determinePosition";
|
import { determinePosition } from "../../functions/determinePosition";
|
||||||
@@ -14,14 +12,12 @@ import {
|
|||||||
DeleteIcon,
|
DeleteIcon,
|
||||||
} from "../../../../components/icons/ExportCommonIcons";
|
} from "../../../../components/icons/ExportCommonIcons";
|
||||||
import DistanceLines from "./DistanceLines"; // Import the DistanceLines component
|
import DistanceLines from "./DistanceLines"; // Import the DistanceLines component
|
||||||
import { deleteFloatingWidgetApi } from "../../../../services/visulization/zone/deleteFloatingWidget";
|
|
||||||
|
|
||||||
import TotalCardComponent from "./cards/TotalCardComponent";
|
import TotalCardComponent from "./cards/TotalCardComponent";
|
||||||
import WarehouseThroughputComponent from "./cards/WarehouseThroughputComponent";
|
import WarehouseThroughputComponent from "./cards/WarehouseThroughputComponent";
|
||||||
import FleetEfficiencyComponent from "./cards/FleetEfficiencyComponent";
|
import FleetEfficiencyComponent from "./cards/FleetEfficiencyComponent";
|
||||||
import { useWidgetStore } from "../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../store/useWidgetStore";
|
||||||
import { useSocketStore } from "../../../../store/store";
|
import { useSocketStore } from "../../../../store/store";
|
||||||
import { useClickOutside } from "../../functions/handleWidgetsOuterClick";
|
|
||||||
import { usePlayButtonStore } from "../../../../store/usePlayButtonStore";
|
import { usePlayButtonStore } from "../../../../store/usePlayButtonStore";
|
||||||
import { useSelectedZoneStore } from "../../../../store/visualization/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../store/visualization/useZoneStore";
|
||||||
interface DraggingState {
|
interface DraggingState {
|
||||||
@@ -54,7 +50,7 @@ const DroppedObjects: React.FC = () => {
|
|||||||
const updateObjectPosition = useDroppedObjectsStore(
|
const updateObjectPosition = useDroppedObjectsStore(
|
||||||
(state) => state.updateObjectPosition
|
(state) => state.updateObjectPosition
|
||||||
);
|
);
|
||||||
const { setSelectedZone, selectedZone } = useSelectedZoneStore();
|
const { selectedZone } = useSelectedZoneStore();
|
||||||
|
|
||||||
const deleteObject = useDroppedObjectsStore((state) => state.deleteObject);
|
const deleteObject = useDroppedObjectsStore((state) => state.deleteObject);
|
||||||
|
|
||||||
@@ -79,12 +75,8 @@ const DroppedObjects: React.FC = () => {
|
|||||||
bottom: number | "auto";
|
bottom: number | "auto";
|
||||||
} | null>(null); // State to track the current position during drag
|
} | null>(null); // State to track the current position during drag
|
||||||
const animationRef = useRef<number | null>(null);
|
const animationRef = useRef<number | null>(null);
|
||||||
const { activeModule } = useModuleStore();
|
|
||||||
const chartWidget = useRef<HTMLDivElement>(null);
|
const chartWidget = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
// useClickOutside(chartWidget, () => {
|
|
||||||
// setSelectedChartId(null);
|
|
||||||
// });
|
|
||||||
const kebabRef = useRef<HTMLDivElement>(null);
|
const kebabRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
// Clean up animation frame on unmount
|
// Clean up animation frame on unmount
|
||||||
@@ -141,12 +133,6 @@ const DroppedObjects: React.FC = () => {
|
|||||||
}
|
}
|
||||||
deleteObject(zoneName, id);
|
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) {}
|
} catch (error) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +146,7 @@ const DroppedObjects: React.FC = () => {
|
|||||||
const obj = zone.objects[index];
|
const obj = zone.objects[index];
|
||||||
const element = event.currentTarget as HTMLElement;
|
const element = event.currentTarget as HTMLElement;
|
||||||
element.setPointerCapture(event.pointerId);
|
element.setPointerCapture(event.pointerId);
|
||||||
const container = document.getElementById("real-time-vis-canvas");
|
const container = document.getElementById("work-space-three-d-canvas");
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
const rect = container.getBoundingClientRect();
|
const rect = container.getBoundingClientRect();
|
||||||
@@ -322,6 +308,7 @@ const DroppedObjects: React.FC = () => {
|
|||||||
updateObjectPosition(zoneName, draggingIndex.index, boundedPosition);
|
updateObjectPosition(zoneName, draggingIndex.index, boundedPosition);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
} finally {
|
} finally {
|
||||||
setDraggingIndex(null);
|
setDraggingIndex(null);
|
||||||
setOffset(null);
|
setOffset(null);
|
||||||
@@ -343,7 +330,7 @@ const DroppedObjects: React.FC = () => {
|
|||||||
const handlePointerMove = (event: React.PointerEvent) => {
|
const handlePointerMove = (event: React.PointerEvent) => {
|
||||||
if (!draggingIndex || !offset) return;
|
if (!draggingIndex || !offset) return;
|
||||||
if (isPlaying === true) return;
|
if (isPlaying === true) return;
|
||||||
const container = document.getElementById("real-time-vis-canvas");
|
const container = document.getElementById("work-space-three-d-canvas");
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
const rect = container.getBoundingClientRect();
|
const rect = container.getBoundingClientRect();
|
||||||
@@ -394,12 +381,6 @@ const DroppedObjects: React.FC = () => {
|
|||||||
// Update position immediately without animation frame
|
// Update position immediately without animation frame
|
||||||
updateObjectPosition(zoneName, draggingIndex.index, newPosition);
|
updateObjectPosition(zoneName, draggingIndex.index, newPosition);
|
||||||
|
|
||||||
// if (!animationRef.current) {
|
|
||||||
// animationRef.current = requestAnimationFrame(() => {
|
|
||||||
// updateObjectPosition(zoneName, draggingIndex.index, newPosition);
|
|
||||||
// animationRef.current = null;
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePointerUp = async (event: React.PointerEvent<HTMLDivElement>) => {
|
const handlePointerUp = async (event: React.PointerEvent<HTMLDivElement>) => {
|
||||||
@@ -407,7 +388,7 @@ const DroppedObjects: React.FC = () => {
|
|||||||
if (!draggingIndex || !offset) return;
|
if (!draggingIndex || !offset) return;
|
||||||
if (isPlaying === true) return;
|
if (isPlaying === true) return;
|
||||||
|
|
||||||
const container = document.getElementById("real-time-vis-canvas");
|
const container = document.getElementById("work-space-three-d-canvas");
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
const rect = container.getBoundingClientRect();
|
const rect = container.getBoundingClientRect();
|
||||||
@@ -450,11 +431,6 @@ const DroppedObjects: React.FC = () => {
|
|||||||
// Save to backend
|
// Save to backend
|
||||||
const email = localStorage.getItem("email") || "";
|
const email = localStorage.getItem("email") || "";
|
||||||
const organization = email?.split("@")[1]?.split(".")[0];
|
const organization = email?.split("@")[1]?.split(".")[0];
|
||||||
// const response = await addingFloatingWidgets(zone.zoneId, organization, {
|
|
||||||
// ...zone.objects[draggingIndex.index],
|
|
||||||
// position: boundedPosition,
|
|
||||||
// });
|
|
||||||
|
|
||||||
let updateFloatingWidget = {
|
let updateFloatingWidget = {
|
||||||
organization: organization,
|
organization: organization,
|
||||||
widget: {
|
widget: {
|
||||||
@@ -468,21 +444,9 @@ const DroppedObjects: React.FC = () => {
|
|||||||
visualizationSocket.emit("v2:viz-float:add", updateFloatingWidget);
|
visualizationSocket.emit("v2:viz-float:add", updateFloatingWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (response.message === "Widget updated successfully") {
|
|
||||||
|
|
||||||
updateObjectPosition(zoneName, draggingIndex.index, boundedPosition);
|
updateObjectPosition(zoneName, draggingIndex.index, boundedPosition);
|
||||||
// }
|
|
||||||
|
|
||||||
// // Clean up
|
|
||||||
// setDraggingIndex(null);
|
|
||||||
// setOffset(null);
|
|
||||||
// setActiveEdges(null); // Clear active edges
|
|
||||||
// setCurrentPosition(null); // Reset current position
|
|
||||||
// if (animationRef.current) {
|
|
||||||
// cancelAnimationFrame(animationRef.current);
|
|
||||||
// animationRef.current = null;
|
|
||||||
// }
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
} finally {
|
} finally {
|
||||||
// Clean up regardless of success or failure
|
// Clean up regardless of success or failure
|
||||||
setDraggingIndex(null);
|
setDraggingIndex(null);
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ const Panel: React.FC<PanelProps> = ({
|
|||||||
setZonesData,
|
setZonesData,
|
||||||
waitingPanels,
|
waitingPanels,
|
||||||
}) => {
|
}) => {
|
||||||
const { widgetSelect, setWidgetSelect } = useAsset3dWidget();
|
|
||||||
const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({});
|
const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({});
|
||||||
const [panelDimensions, setPanelDimensions] = useState<{
|
const [panelDimensions, setPanelDimensions] = useState<{
|
||||||
[side in Side]?: { width: number; height: number };
|
[side in Side]?: { width: number; height: number };
|
||||||
@@ -74,7 +73,7 @@ const Panel: React.FC<PanelProps> = ({
|
|||||||
|
|
||||||
// Track canvas dimensions
|
// Track canvas dimensions
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const canvas = document.getElementById("real-time-vis-canvas");
|
const canvas = document.getElementById("work-space-three-d-canvas");
|
||||||
if (!canvas) return;
|
if (!canvas) return;
|
||||||
|
|
||||||
const updateCanvasDimensions = () => {
|
const updateCanvasDimensions = () => {
|
||||||
@@ -186,7 +185,7 @@ const Panel: React.FC<PanelProps> = ({
|
|||||||
|
|
||||||
// Add widget to panel
|
// Add widget to panel
|
||||||
const addWidgetToPanel = async (asset: any, panel: Side) => {
|
const addWidgetToPanel = async (asset: any, panel: Side) => {
|
||||||
const email = localStorage.getItem("email") || "";
|
const email = localStorage.getItem("email") ?? "";
|
||||||
const organization = email?.split("@")[1]?.split(".")[0];
|
const organization = email?.split("@")[1]?.split(".")[0];
|
||||||
|
|
||||||
const newWidget = {
|
const newWidget = {
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ const Project: React.FC = () => {
|
|||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
className="scene-container"
|
className="scene-container"
|
||||||
id="real-time-vis-canvas"
|
id="work-space-three-d-canvas"
|
||||||
style={{
|
style={{
|
||||||
height: isPlaying || activeModule !== "visualization" ? "100vh" : "",
|
height: isPlaying || activeModule !== "visualization" ? "100vh" : "",
|
||||||
width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
|
width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
|
||||||
@@ -130,7 +130,7 @@ const Project: React.FC = () => {
|
|||||||
<LogList />
|
<LogList />
|
||||||
</RenderOverlay>
|
</RenderOverlay>
|
||||||
)}
|
)}
|
||||||
{activeModule != "market" && <Footer />}
|
{activeModule !== "market" && !selectedUser && <Footer />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
outline: 8px solid var(--user-color);
|
outline: 8px solid var(--user-color);
|
||||||
outline-offset: -3px;
|
outline-offset: -4px;
|
||||||
border-radius: #{$border-radius-xlarge};
|
border-radius: #{$border-radius-xlarge};
|
||||||
|
|
||||||
.follower-name {
|
.follower-name {
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
// Importing React and useEffect from React library
|
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
|
|
||||||
// Importing the necessary hooks and types from the application's state management stores
|
|
||||||
import useModuleStore, { useThreeDStore } from "../../store/useModuleStore";
|
import useModuleStore, { useThreeDStore } from "../../store/useModuleStore";
|
||||||
import useToggleStore from "../../store/useUIToggleStore";
|
import useToggleStore from "../../store/useUIToggleStore";
|
||||||
import {
|
import {
|
||||||
@@ -14,185 +11,141 @@ import {
|
|||||||
useToolMode,
|
useToolMode,
|
||||||
} from "../../store/store";
|
} from "../../store/store";
|
||||||
import { usePlayButtonStore } from "../../store/usePlayButtonStore";
|
import { usePlayButtonStore } from "../../store/usePlayButtonStore";
|
||||||
|
|
||||||
// Utility function to detect modifier keys (Ctrl, Alt, Shift) and key combinations
|
|
||||||
import { detectModifierKeys } from "./detectModifierKeys";
|
import { detectModifierKeys } from "./detectModifierKeys";
|
||||||
|
|
||||||
// KeyPressListener component to handle global keyboard shortcuts
|
|
||||||
const KeyPressListener: React.FC = () => {
|
const KeyPressListener: React.FC = () => {
|
||||||
// Accessing state and actions from different stores
|
const { activeModule, setActiveModule } = useModuleStore();
|
||||||
const { activeModule, setActiveModule } = useModuleStore(); // Module management (e.g., builder, simulation, visualization)
|
const { setActiveSubTool } = useActiveSubTool();
|
||||||
const { setActiveSubTool } = useActiveSubTool(); // Sub-tool management
|
const { toggleUI, setToggleUI } = useToggleStore();
|
||||||
const { toggleUI, setToggleUI } = useToggleStore(); // UI visibility toggle
|
const { setToggleThreeD } = useThreeDStore();
|
||||||
const { setToggleThreeD } = useThreeDStore(); // 3D view toggle
|
const { setToolMode } = useToolMode();
|
||||||
const { setToolMode } = useToolMode(); // Tool mode management
|
const { setIsPlaying } = usePlayButtonStore();
|
||||||
const { setIsPlaying } = usePlayButtonStore(); // Play button state management
|
const { toggleView, setToggleView } = useToggleView();
|
||||||
|
const { setDeleteTool } = useDeleteTool();
|
||||||
|
const { setAddAction } = useAddAction();
|
||||||
|
const { setSelectedWallItem } = useSelectedWallItem();
|
||||||
|
const { setActiveTool } = useActiveTool();
|
||||||
|
|
||||||
// Wall and tool-related actions
|
const isTextInput = (element: Element | null): boolean =>
|
||||||
const { toggleView, setToggleView } = useToggleView(); // 2D/3D toggle state
|
element instanceof HTMLInputElement ||
|
||||||
const { setDeleteTool } = useDeleteTool(); // Delete tool action
|
element instanceof HTMLTextAreaElement ||
|
||||||
const { setAddAction } = useAddAction(); // Add action management
|
element?.getAttribute("contenteditable") === "true";
|
||||||
const { setSelectedWallItem } = useSelectedWallItem(); // Selected wall item management
|
|
||||||
const { setActiveTool } = useActiveTool(); // Active tool management
|
const handleModuleSwitch = (keyCombination: string) => {
|
||||||
|
const modules: Record<string, string> = {
|
||||||
|
"1": "builder",
|
||||||
|
"2": "simulation",
|
||||||
|
"3": "visualization",
|
||||||
|
"4": "market",
|
||||||
|
};
|
||||||
|
const module = modules[keyCombination];
|
||||||
|
if (module && !toggleView) {
|
||||||
|
setActiveTool("cursor");
|
||||||
|
setActiveSubTool("cursor");
|
||||||
|
if (module === "market") setToggleUI(false);
|
||||||
|
setActiveModule(module);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePrimaryTools = (key: string) => {
|
||||||
|
const toolMap: Record<string, string> = {
|
||||||
|
V: "cursor",
|
||||||
|
X: "delete",
|
||||||
|
H: "free-hand",
|
||||||
|
};
|
||||||
|
const tool = toolMap[key];
|
||||||
|
if (tool) {
|
||||||
|
setActiveTool(tool);
|
||||||
|
setActiveSubTool(tool);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBuilderShortcuts = (key: string) => {
|
||||||
|
if (activeModule !== "builder") return;
|
||||||
|
|
||||||
|
if (key === "TAB") {
|
||||||
|
const toggleTo2D = toggleView;
|
||||||
|
setToggleView(!toggleTo2D);
|
||||||
|
setToggleThreeD(toggleTo2D);
|
||||||
|
if (toggleTo2D) {
|
||||||
|
setSelectedWallItem(null);
|
||||||
|
setDeleteTool(false);
|
||||||
|
setAddAction(null);
|
||||||
|
}
|
||||||
|
setActiveTool("cursor");
|
||||||
|
setActiveSubTool("cursor");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// These should only apply in 2D view
|
||||||
|
const twoDToolConfigs: Record<string, { tool: string; mode: string }> = {
|
||||||
|
Q: { tool: "draw-wall", mode: "Wall" },
|
||||||
|
"6": { tool: "draw-wall", mode: "Wall" },
|
||||||
|
R: { tool: "draw-aisle", mode: "Aisle" },
|
||||||
|
"7": { tool: "draw-aisle", mode: "Aisle" },
|
||||||
|
E: { tool: "draw-zone", mode: "Zone" },
|
||||||
|
"8": { tool: "draw-zone", mode: "Zone" },
|
||||||
|
T: { tool: "draw-floor", mode: "Floor" },
|
||||||
|
"9": { tool: "draw-floor", mode: "Floor" },
|
||||||
|
};
|
||||||
|
|
||||||
|
const config = twoDToolConfigs[key];
|
||||||
|
if (toggleView && config) {
|
||||||
|
setActiveTool(config.tool);
|
||||||
|
setToolMode(config.mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Measurement tool should work in both 2D and 3D
|
||||||
|
if (key === "M") {
|
||||||
|
setActiveTool("measure");
|
||||||
|
setToolMode("MeasurementScale");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const handleKeyPress = (event: KeyboardEvent) => {
|
||||||
|
if (isTextInput(document.activeElement)) return;
|
||||||
|
|
||||||
|
const keyCombination = detectModifierKeys(event);
|
||||||
|
if (!keyCombination || ["F5", "F11", "F12"].includes(event.key) || keyCombination === "Ctrl+R") return;
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (keyCombination === "Ctrl+\\") {
|
||||||
|
if (activeModule !== "market") setToggleUI(!toggleUI);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Active module selection (builder, simulation, etc.)
|
||||||
|
handleModuleSwitch(keyCombination);
|
||||||
|
// Common editing tools: cursor | delete | free-hand
|
||||||
|
handlePrimaryTools(keyCombination);
|
||||||
|
// Shortcuts specific to the builder module (e.g., drawing and measurement tools)
|
||||||
|
handleBuilderShortcuts(keyCombination);
|
||||||
|
|
||||||
|
// Shortcut to enter play mode
|
||||||
|
if (keyCombination === "Ctrl+P" && !toggleView) {
|
||||||
|
setIsPlaying(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyCombination === "ESCAPE") {
|
||||||
|
setActiveTool("cursor");
|
||||||
|
setIsPlaying(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Placeholder for future implementation
|
||||||
|
if (["Ctrl+Z", "Ctrl+Y", "Ctrl+Shift+Z", "Ctrl+H", "Ctrl+F", "Ctrl+?"].includes(keyCombination)) {
|
||||||
|
// Implement undo/redo/help/find/shortcuts
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// useEffect to manage global keyboard shortcuts
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Function to handle keydown events
|
|
||||||
const handleKeyPress = (event: KeyboardEvent) => {
|
|
||||||
// Identify the currently focused element
|
|
||||||
const activeElement = document.activeElement;
|
|
||||||
|
|
||||||
// Check if the user is typing in an input field, textarea, or contenteditable element
|
|
||||||
const isTyping =
|
|
||||||
activeElement instanceof HTMLInputElement ||
|
|
||||||
activeElement instanceof HTMLTextAreaElement ||
|
|
||||||
(activeElement && activeElement.getAttribute("contenteditable") === "true");
|
|
||||||
|
|
||||||
if (isTyping) {
|
|
||||||
return; // Skip shortcut handling while typing
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect the combination of keys pressed
|
|
||||||
const keyCombination = detectModifierKeys(event);
|
|
||||||
|
|
||||||
// Allow browser default behavior for specific keys (e.g., F5 for refresh)
|
|
||||||
if (["F5", "F11", "F12"].includes(event.key) || keyCombination === "Ctrl+R") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prevent the default browser action for other handled key presses
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
if (keyCombination) {
|
|
||||||
// Switch between different modules (e.g., builder, simulation)
|
|
||||||
if (keyCombination === "1" && !toggleView) {
|
|
||||||
setActiveTool("cursor");
|
|
||||||
setActiveSubTool("cursor");
|
|
||||||
setActiveModule("builder");
|
|
||||||
}
|
|
||||||
if (keyCombination === "2" && !toggleView) {
|
|
||||||
setActiveTool("cursor");
|
|
||||||
setActiveSubTool("cursor");
|
|
||||||
setActiveModule("simulation");
|
|
||||||
}
|
|
||||||
if (keyCombination === "3" && !toggleView) {
|
|
||||||
setActiveTool("cursor");
|
|
||||||
setActiveSubTool("cursor");
|
|
||||||
setActiveModule("visualization");
|
|
||||||
}
|
|
||||||
if (keyCombination === "4" && !toggleView) {
|
|
||||||
setActiveTool("cursor");
|
|
||||||
setActiveSubTool("cursor");
|
|
||||||
setToggleUI(false);
|
|
||||||
setActiveModule("market");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toggle UI visibility
|
|
||||||
if (keyCombination === "Ctrl+." && activeModule !== "market") {
|
|
||||||
setToggleUI(!toggleUI);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tool selection shortcuts
|
|
||||||
if (keyCombination === "V") {
|
|
||||||
setActiveTool("cursor");
|
|
||||||
setActiveSubTool("cursor");
|
|
||||||
}
|
|
||||||
if (keyCombination === "X") {
|
|
||||||
setActiveTool("delete");
|
|
||||||
setActiveSubTool("delete");
|
|
||||||
}
|
|
||||||
if (keyCombination === "H") {
|
|
||||||
setActiveTool("free-hand");
|
|
||||||
setActiveSubTool("free-hand");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toggle play mode
|
|
||||||
if (keyCombination === "Ctrl+P" && !toggleView) {
|
|
||||||
setIsPlaying(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Builder-specific shortcuts
|
|
||||||
if (activeModule === "builder") {
|
|
||||||
if (keyCombination === "TAB") {
|
|
||||||
// Switch between 2D and 3D views
|
|
||||||
if (toggleView) {
|
|
||||||
setToggleView(false);
|
|
||||||
setToggleThreeD(true);
|
|
||||||
setActiveTool("cursor");
|
|
||||||
} else {
|
|
||||||
setSelectedWallItem(null);
|
|
||||||
setDeleteTool(false);
|
|
||||||
setAddAction(null);
|
|
||||||
setToggleView(true);
|
|
||||||
setToggleThreeD(false);
|
|
||||||
setActiveTool("cursor");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wall-related tools
|
|
||||||
if (toggleView) {
|
|
||||||
if (keyCombination === "Q" || keyCombination === "6") {
|
|
||||||
setActiveTool("draw-wall");
|
|
||||||
setToolMode("Wall");
|
|
||||||
}
|
|
||||||
if (keyCombination === "R" || keyCombination === "7") {
|
|
||||||
setActiveTool("draw-aisle");
|
|
||||||
setToolMode("Aisle");
|
|
||||||
}
|
|
||||||
if (keyCombination === "E" || keyCombination === "8") {
|
|
||||||
setActiveTool("draw-zone");
|
|
||||||
setToolMode("Zone");
|
|
||||||
}
|
|
||||||
if (keyCombination === "T" || keyCombination === "9") {
|
|
||||||
setActiveTool("draw-floor");
|
|
||||||
setToolMode("Floor");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Measurement tool
|
|
||||||
if (keyCombination === "M") {
|
|
||||||
setActiveTool("measure");
|
|
||||||
setToolMode("MeasurementScale");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Undo and redo actions
|
|
||||||
if (keyCombination === "Ctrl+Z") {
|
|
||||||
// Handle undo action
|
|
||||||
}
|
|
||||||
if (keyCombination === "Ctrl+Y" || keyCombination === "Ctrl+Shift+Z") {
|
|
||||||
// Handle redo action
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper actions
|
|
||||||
if (keyCombination === "Ctrl+H") {
|
|
||||||
// Open help
|
|
||||||
}
|
|
||||||
if (keyCombination === "Ctrl+F") {
|
|
||||||
// Open find functionality
|
|
||||||
}
|
|
||||||
if (keyCombination === "Ctrl+?") {
|
|
||||||
// Show shortcuts info
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset to cursor tool and stop play mode
|
|
||||||
if (keyCombination === "ESCAPE") {
|
|
||||||
setActiveTool("cursor");
|
|
||||||
setIsPlaying(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add keydown event listener
|
|
||||||
window.addEventListener("keydown", handleKeyPress);
|
window.addEventListener("keydown", handleKeyPress);
|
||||||
|
return () => window.removeEventListener("keydown", handleKeyPress);
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [activeModule, toggleUI, toggleView]);
|
||||||
|
|
||||||
// Cleanup function to remove the event listener
|
return null;
|
||||||
return () => {
|
|
||||||
window.removeEventListener("keydown", handleKeyPress);
|
|
||||||
};
|
|
||||||
}, [activeModule, setActiveModule, setActiveSubTool, setActiveTool, setAddAction, setDeleteTool, setIsPlaying, setSelectedWallItem, setToggleThreeD, setToggleUI, setToggleView, setToolMode, toggleUI, toggleView]); // Dependencies to reapply effect if these values change
|
|
||||||
|
|
||||||
return null; // This component does not render any UI
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default KeyPressListener;
|
export default KeyPressListener;
|
||||||
|
|||||||
Reference in New Issue
Block a user