code structure updated

This commit is contained in:
2025-04-24 16:58:15 +05:30
parent 967f1741b0
commit 9b9f61369c
8 changed files with 169 additions and 608 deletions

View File

@@ -45,7 +45,8 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
const [expandedZones, setExpandedZones] = useState<Record<string, boolean>>( const [expandedZones, setExpandedZones] = useState<Record<string, boolean>>(
{} {}
); );
const { floorItems, setFloorItems } = useFloorItems(); const { setFloorItems } = useFloorItems();
useEffect(() => { useEffect(() => {
useSelectedZoneStore.getState().setSelectedZone({ useSelectedZoneStore.getState().setSelectedZone({
@@ -143,6 +144,7 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
); );
} }
console.log('newName: ', newName); console.log('newName: ', newName);
} }

View File

@@ -1,5 +1,5 @@
import { useFrame, useThree } from "@react-three/fiber"; import { useFrame, useThree } from "@react-three/fiber";
import { useActiveTool, useAsset3dWidget, useCamMode, useDeletableFloorItem, useDeleteTool, useFloorItems, useLoadingProgress, useRenderDistance, useSelectedFloorItem, useSelectedItem, useSimulationStates, useSocketStore, useToggleView, useTransformMode, } from "../../../store/store"; import { useActiveTool, useAsset3dWidget, useCamMode, useDeletableFloorItem, useDeleteTool, useFloorItems, useLoadingProgress, useRenderDistance, useSelectedFloorItem, useSelectedItem, useSimulationStates, useSocketStore, useToggleView, useTransformMode, useZoneAssetId, } from "../../../store/store";
import assetVisibility from "../geomentries/assets/assetVisibility"; import assetVisibility from "../geomentries/assets/assetVisibility";
import { useEffect } from "react"; import { useEffect } from "react";
import * as THREE from "three"; import * as THREE from "three";
@@ -32,12 +32,13 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
const { setSelectedFloorItem } = useSelectedFloorItem(); const { setSelectedFloorItem } = useSelectedFloorItem();
const { activeTool } = useActiveTool(); const { activeTool } = useActiveTool();
const { selectedItem, setSelectedItem } = useSelectedItem(); const { selectedItem, setSelectedItem } = useSelectedItem();
const { simulationStates, setSimulationStates } = useSimulationStates(); const { setSimulationStates } = useSimulationStates();
const { setLoadingProgress } = useLoadingProgress(); const { setLoadingProgress } = useLoadingProgress();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { socket } = useSocketStore(); const { socket } = useSocketStore();
const loader = new GLTFLoader(); const loader = new GLTFLoader();
const dracoLoader = new DRACOLoader(); const dracoLoader = new DRACOLoader();
const { setZoneAssetId } = useZoneAssetId();
dracoLoader.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/"); dracoLoader.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/");
loader.setDRACOLoader(dracoLoader); loader.setDRACOLoader(dracoLoader);
@@ -220,6 +221,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
const target = controls.getTarget(new THREE.Vector3()); const target = controls.getTarget(new THREE.Vector3());
await controls.setTarget(target.x, 0, target.z, true); await controls.setTarget(target.x, 0, target.z, true);
setSelectedFloorItem(null); setSelectedFloorItem(null);
setZoneAssetId(null)
} }
} }
} }

View File

@@ -795,7 +795,7 @@ export default function SocketResponses({
return return
} }
if (data.message === "zone deleted") { if (data.message === "zone deleted") {
const updatedZones = zones.filter((zone: any) => zone.zoneId !== data.data.zoneId); const updatedZones = zones?.filter((zone: any) => zone.zoneId !== data.data.zoneId);
setZones(updatedZones); setZones(updatedZones);
const zoneIndex = zones.findIndex((zone: any) => zone.zoneId === data.data.zoneId); const zoneIndex = zones.findIndex((zone: any) => zone.zoneId === data.data.zoneId);

View File

@@ -1,18 +1,11 @@
import React, { useEffect, useRef, useState, useCallback } from "react"; import React, { useEffect, useRef, useState, useCallback } from "react";
import { useWidgetStore, Widget } from "../../store/useWidgetStore"; import { Widget } from "../../store/useWidgetStore";
import {useDroppedObjectsStore, useFloatingWidget,} from "../../store/useDroppedObjectsStore";
import {
useDroppedObjectsStore,
useFloatingWidget,
} from "../../store/useDroppedObjectsStore";
import { getSelect2dZoneData } from "../../services/realTimeVisulization/zoneData/getSelect2dZoneData"; import { getSelect2dZoneData } from "../../services/realTimeVisulization/zoneData/getSelect2dZoneData";
import { getFloatingZoneData } from "../../services/realTimeVisulization/zoneData/getFloatingData"; import { getFloatingZoneData } from "../../services/realTimeVisulization/zoneData/getFloatingData";
import { get3dWidgetZoneData } from "../../services/realTimeVisulization/zoneData/get3dWidgetData"; import {MoveArrowLeft, MoveArrowRight,} from "../../components/icons/SimulationIcons";
import {
MoveArrowLeft,
MoveArrowRight,
} from "../../components/icons/SimulationIcons";
import { InfoIcon } from "../../components/icons/ExportCommonIcons"; import { InfoIcon } from "../../components/icons/ExportCommonIcons";
import { useSelectedZoneStore } from "../../store/useZoneStore";
// Define the type for `Side` // Define the type for `Side`
type Side = "top" | "bottom" | "left" | "right"; type Side = "top" | "bottom" | "left" | "right";
@@ -34,62 +27,20 @@ interface DisplayZoneProps {
zoneViewPortPosition: number[]; zoneViewPortPosition: number[];
}; };
}; };
selectedZone: {
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
zoneId: string;
points: [];
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
widgets: {
id: string;
type: string;
title: string;
panel: Side;
data: any;
}[];
};
setSelectedZone: React.Dispatch<
React.SetStateAction<{
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
points: [];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
widgets: {
id: string;
type: string;
title: string;
panel: Side;
data: any;
}[];
}>
>;
hiddenPanels: HiddenPanels; // Updated prop type hiddenPanels: HiddenPanels; // Updated prop type
setHiddenPanels: React.Dispatch<React.SetStateAction<HiddenPanels>>; // Updated prop type setHiddenPanels: React.Dispatch<React.SetStateAction<HiddenPanels>>; // Updated prop type
} }
const DisplayZone: React.FC<DisplayZoneProps> = ({ const DisplayZone: React.FC<DisplayZoneProps> = ({ zonesData, hiddenPanels }) => {
zonesData,
selectedZone, const [showLeftArrow, setShowLeftArrow] = useState(false);
setSelectedZone, const [showRightArrow, setShowRightArrow] = useState(false);
hiddenPanels,
}) => {
// Ref for the container element // Ref for the container element
const containerRef = useRef<HTMLDivElement | null>(null); const containerRef = useRef<HTMLDivElement | null>(null);
const scrollContainerRef = useRef<HTMLDivElement | null>(null); const scrollContainerRef = useRef<HTMLDivElement | null>(null);
//zustand
// State to track overflow visibility const { setFloatingWidget } = useFloatingWidget();
const [showLeftArrow, setShowLeftArrow] = useState(false); const { selectedZone, setSelectedZone } = useSelectedZoneStore();
const [showRightArrow, setShowRightArrow] = useState(false);
const { floatingWidget, setFloatingWidget } = useFloatingWidget();
const { setSelectedChartId } = useWidgetStore();
// Function to calculate overflow state // Function to calculate overflow state
const updateOverflowState = useCallback(() => { const updateOverflowState = useCallback(() => {
@@ -97,16 +48,9 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
if (container) { if (container) {
const isOverflowing = container.scrollWidth > container.clientWidth; const isOverflowing = container.scrollWidth > container.clientWidth;
const canScrollLeft = container.scrollLeft > 0; const canScrollLeft = container.scrollLeft > 0;
const canScrollRight = container.scrollLeft + container.clientWidth + 1 < container.scrollWidth;
const canScrollRight =
container.scrollLeft + container.clientWidth + 1 <
container.scrollWidth;
setShowLeftArrow(isOverflowing && canScrollLeft); setShowLeftArrow(isOverflowing && canScrollLeft);
setShowRightArrow(isOverflowing && canScrollRight); setShowRightArrow(isOverflowing && canScrollRight);
// console.log('canScrollRight: ', canScrollRight);
// console.log('isOverflowing: ', isOverflowing);
} }
}, []); }, []);
@@ -126,10 +70,7 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
const handleWheel = (event: WheelEvent) => { const handleWheel = (event: WheelEvent) => {
if (Math.abs(event.deltaY) > Math.abs(event.deltaX)) { if (Math.abs(event.deltaY) > Math.abs(event.deltaX)) {
event.preventDefault(); event.preventDefault();
container.scrollBy({ container.scrollBy({ left: event.deltaY * 2, behavior: "smooth", });
left: event.deltaY * 2,
behavior: "smooth",
});
} }
}; };
@@ -171,23 +112,11 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
if (selectedZone?.zoneId === zoneId) { if (selectedZone?.zoneId === zoneId) {
return; return;
} }
// setSelectedChartId(null);
const email = localStorage.getItem("email") || ""; const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0]; const organization = email?.split("@")[1]?.split(".")[0];
//api for getting 2d widget Data
let response = await getSelect2dZoneData(zoneId, organization); let response = await getSelect2dZoneData(zoneId, organization);
console.log("response: ", response);
let res = await getFloatingZoneData(zoneId, organization);
console.log("res: ", res);
setFloatingWidget(res);
// Set the selected zone in the store
useDroppedObjectsStore.getState().setZone(zoneName, zoneId);
if (Array.isArray(res)) {
res.forEach((val) => {
useDroppedObjectsStore.getState().addObject(zoneName, val);
});
}
setSelectedZone({ setSelectedZone({
zoneName, zoneName,
activeSides: response.activeSides || [], activeSides: response.activeSides || [],
@@ -199,62 +128,42 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
zoneViewPortTarget: response.viewPortCenter || {}, zoneViewPortTarget: response.viewPortCenter || {},
zoneViewPortPosition: response.viewPortposition || {}, zoneViewPortPosition: response.viewPortposition || {},
}); });
} catch (error) {}
//api for getting floating widget Data
let res = await getFloatingZoneData(zoneId, organization);
setFloatingWidget(res);
useDroppedObjectsStore.getState().setZone(zoneName, zoneId);
if (Array.isArray(res)) {
res.forEach((val) => {
useDroppedObjectsStore.getState().addObject(zoneName, val);
});
}
} catch (error) { }
} }
return ( return (
<div <div ref={containerRef} className={`zone-wrapper ${selectedZone?.activeSides?.includes("bottom") && !hiddenPanels[selectedZone.zoneId]?.includes("bottom") ? "bottom" : ""}`}>
ref={containerRef}
className={`zone-wrapper ${
selectedZone?.activeSides?.includes("bottom") &&
!hiddenPanels[selectedZone.zoneId]?.includes("bottom")
? "bottom"
: ""
}`}
>
{/* Left Arrow */} {/* Left Arrow */}
{showLeftArrow && ( {showLeftArrow && (<button className="arrow left-arrow" onClick={handleScrollLeft}><MoveArrowLeft /></button>)}
<button className="arrow left-arrow" onClick={handleScrollLeft}>
<MoveArrowLeft />
</button>
)}
{/* Scrollable Zones Container */} {/* Scrollable Zones Container */}
<div <div ref={scrollContainerRef} className="zones-wrapper" style={{ overflowX: "auto", whiteSpace: "nowrap" }}>
ref={scrollContainerRef}
className="zones-wrapper"
style={{ overflowX: "auto", whiteSpace: "nowrap" }}
>
{Object.keys(zonesData).length !== 0 ? ( {Object.keys(zonesData).length !== 0 ? (
<> <>
{Object.keys(zonesData).map((zoneName, index) => ( {Object.keys(zonesData).map((zoneName, index) => (
<div <div key={index} className={`zone ${selectedZone.zoneName === zoneName ? "active" : ""}`}
key={index} onClick={() => handleSelect2dZoneData(zonesData[zoneName]?.zoneId, zoneName)}
className={`zone ${
selectedZone.zoneName === zoneName ? "active" : ""
}`}
onClick={() =>
handleSelect2dZoneData(zonesData[zoneName]?.zoneId, zoneName)
}
> >
{zoneName} {zoneName}
</div> </div>
))} ))}
</> </>
) : ( ) : (
<div className="no-zone"> <div className="no-zone"><InfoIcon />No zones? Create one!</div>
<InfoIcon />
No zones? Create one!
</div>
)} )}
</div> </div>
{/* Right Arrow */} {/* Right Arrow */}
{showRightArrow && ( {showRightArrow && (<button className="arrow right-arrow" onClick={handleScrollRight}><MoveArrowRight /></button>)}
<button className="arrow right-arrow" onClick={handleScrollRight}>
<MoveArrowRight />
</button>
)}
</div> </div>
); );
}; };

View File

@@ -6,32 +6,17 @@ import { useSelectedZoneStore } from "../../store/useZoneStore";
import DisplayZone from "./DisplayZone"; import DisplayZone from "./DisplayZone";
import Scene from "../scene/scene"; import Scene from "../scene/scene";
import useModuleStore from "../../store/useModuleStore"; import useModuleStore from "../../store/useModuleStore";
import { useDroppedObjectsStore, useFloatingWidget, } from "../../store/useDroppedObjectsStore";
import { import { useAsset3dWidget, useSocketStore, useWidgetSubOption } from "../../store/store";
useDroppedObjectsStore,
useFloatingWidget,
} from "../../store/useDroppedObjectsStore";
import {
useAsset3dWidget,
useSocketStore,
useWidgetSubOption,
useZones,
} from "../../store/store";
import { getZone2dData } from "../../services/realTimeVisulization/zoneData/getZoneData"; import { getZone2dData } from "../../services/realTimeVisulization/zoneData/getZoneData";
import { generateUniqueId } from "../../functions/generateUniqueId"; import { generateUniqueId } from "../../functions/generateUniqueId";
import { determinePosition } from "./functions/determinePosition"; import { determinePosition } from "./functions/determinePosition";
import { addingFloatingWidgets } from "../../services/realTimeVisulization/zoneData/addFloatingWidgets";
import SocketRealTimeViz from "./socket/realTimeVizSocket.dev"; import SocketRealTimeViz from "./socket/realTimeVizSocket.dev";
import RenderOverlay from "../../components/templates/Overlay"; import RenderOverlay from "../../components/templates/Overlay";
import ConfirmationPopup from "../../components/layout/confirmationPopup/ConfirmationPopup"; import ConfirmationPopup from "../../components/layout/confirmationPopup/ConfirmationPopup";
import DroppedObjects from "./widgets/floating/DroppedFloatingWidgets"; import DroppedObjects from "./widgets/floating/DroppedFloatingWidgets";
import EditWidgetOption from "../../components/ui/menu/EditWidgetOption"; import EditWidgetOption from "../../components/ui/menu/EditWidgetOption";
import { import { useEditWidgetOptionsStore, useRightClickSelected, useRightSelected, } from "../../store/useZone3DWidgetStore";
useEditWidgetOptionsStore,
useRightClickSelected,
useRightSelected,
} from "../../store/useZone3DWidgetStore";
import Dropped3dWidgets from "./widgets/3d/Dropped3dWidget";
import OuterClick from "../../utils/outerClick"; import OuterClick from "../../utils/outerClick";
import { useWidgetStore } from "../../store/useWidgetStore"; import { useWidgetStore } from "../../store/useWidgetStore";
import { getActiveProperties } from "./functions/getActiveProperties"; import { getActiveProperties } from "./functions/getActiveProperties";
@@ -65,36 +50,26 @@ interface HiddenPanels {
} }
const RealTimeVisulization: React.FC = () => { const RealTimeVisulization: React.FC = () => {
const [hiddenPanels, setHiddenPanels] = React.useState<HiddenPanels>({}); //zustand
const containerRef = useRef<HTMLDivElement>(null);
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const [droppedObjects, setDroppedObjects] = useState<any[]>([]);
const [zonesData, setZonesData] = useState<FormattedZoneData>({});
const { selectedZone, setSelectedZone } = useSelectedZoneStore(); const { selectedZone, setSelectedZone } = useSelectedZoneStore();
const { setRightSelect } = useRightSelected();
const { rightSelect, setRightSelect } = useRightSelected(); const { editWidgetOptions } = useEditWidgetOptionsStore();
const { editWidgetOptions, setEditWidgetOptions } =
useEditWidgetOptionsStore();
const { rightClickSelected, setRightClickSelected } = useRightClickSelected(); const { rightClickSelected, setRightClickSelected } = useRightClickSelected();
const [openConfirmationPopup, setOpenConfirmationPopup] = useState(false); const { setFloatingWidget } = useFloatingWidget();
const { widgetSubOption } = useWidgetSubOption();
// const [floatingWidgets, setFloatingWidgets] = useState<Record<string, { zoneName: string; zoneId: string; objects: any[] }>>({});
const { floatingWidget, setFloatingWidget } = useFloatingWidget();
const { widgetSelect, setWidgetSelect } = useAsset3dWidget();
const { widgetSubOption, setWidgetSubOption } = useWidgetSubOption();
const { visualizationSocket } = useSocketStore(); const { visualizationSocket } = useSocketStore();
const { setSelectedChartId } = useWidgetStore(); const { setSelectedChartId } = useWidgetStore();
const [hiddenPanels, setHiddenPanels] = React.useState<HiddenPanels>({});
const containerRef = useRef<HTMLDivElement>(null);
const [openConfirmationPopup, setOpenConfirmationPopup] = useState(false);
const [zonesData, setZonesData] = useState<FormattedZoneData>({});
const [canvasDimensions, setCanvasDimensions] = useState({ width: 0, height: 0, });
OuterClick({ OuterClick({
contextClassName: [ contextClassName: ["chart-container","floating","sidebar-right-wrapper","card","dropdown-menu","dropdown-options",],
"chart-container",
"floating",
"sidebar-right-wrapper",
"card",
"dropdown-menu",
"dropdown-options",
],
setMenuVisible: () => setSelectedChartId(null), setMenuVisible: () => setSelectedChartId(null),
}); });
@@ -104,7 +79,6 @@ const RealTimeVisulization: React.FC = () => {
const organization = email?.split("@")[1]?.split(".")[0]; const organization = email?.split("@")[1]?.split(".")[0];
try { try {
const response = await getZone2dData(organization); const response = await getZone2dData(organization);
// console.log('response: ', response);
if (!Array.isArray(response)) { if (!Array.isArray(response)) {
return; return;
@@ -126,11 +100,11 @@ const RealTimeVisulization: React.FC = () => {
{} {}
); );
setZonesData(formattedData); setZonesData(formattedData);
} catch (error) {} } catch (error) { }
} }
GetZoneData(); GetZoneData();
}, [activeModule]); // Removed `zones` from dependencies }, [activeModule]);
useEffect(() => { useEffect(() => {
setZonesData((prev) => { setZonesData((prev) => {
@@ -152,7 +126,6 @@ const RealTimeVisulization: React.FC = () => {
}); });
}, [selectedZone]); }, [selectedZone]);
// useEffect(() => {}, [floatingWidgets]);
const handleDrop = async (event: React.DragEvent<HTMLDivElement>) => { const handleDrop = async (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault(); event.preventDefault();
@@ -251,10 +224,10 @@ const RealTimeVisulization: React.FC = () => {
); );
setFloatingWidget(currentZone.objects); setFloatingWidget(currentZone.objects);
} else { } else {
console.warn("Zone not found or zoneId mismatch");
} }
} catch (error) { } catch (error) {
console.error("Error in handleDrop:", error);
} }
}; };
@@ -278,10 +251,7 @@ const RealTimeVisulization: React.FC = () => {
}; };
}, [setRightClickSelected]); }, [setRightClickSelected]);
const [canvasDimensions, setCanvasDimensions] = useState({
width: 0,
height: 0,
});
useEffect(() => { useEffect(() => {
const canvas = document.getElementById("real-time-vis-canvas"); const canvas = document.getElementById("real-time-vis-canvas");
if (!canvas) return; if (!canvas) return;
@@ -304,14 +274,7 @@ const RealTimeVisulization: React.FC = () => {
return ( return (
<> <>
<style> <style>
{` {`:root {--realTimeViz-container-width: ${canvasDimensions.width}px;--realTimeViz-container-height: ${canvasDimensions.height}px; }`}
:root {
--realTimeViz-container-width: ${canvasDimensions.width}px;
--realTimeViz-container-height: ${canvasDimensions.height}px;
}
`}
</style> </style>
<div <div
ref={containerRef} ref={containerRef}
@@ -326,11 +289,7 @@ const RealTimeVisulization: React.FC = () => {
<div className="realTime-viz-wrapper"> <div className="realTime-viz-wrapper">
{openConfirmationPopup && ( {openConfirmationPopup && (
<RenderOverlay> <RenderOverlay>
<ConfirmationPopup <ConfirmationPopup message={"Are you sure want to delete?"} onConfirm={() => { }} onCancel={() => setOpenConfirmationPopup(false)} />
message={"Are you sure want to delete?"}
onConfirm={() => console.log("Confirmed")}
onCancel={() => setOpenConfirmationPopup(false)}
/>
</RenderOverlay> </RenderOverlay>
)} )}
<div <div
@@ -346,51 +305,15 @@ const RealTimeVisulization: React.FC = () => {
> >
<Scene /> <Scene />
</div> </div>
{activeModule === "visualization" && selectedZone.zoneName !== "" && ( {activeModule === "visualization" && selectedZone.zoneName !== "" && (<DroppedObjects />)}
<DroppedObjects />
)}
{activeModule === "visualization" && <SocketRealTimeViz />} {activeModule === "visualization" && <SocketRealTimeViz />}
{activeModule === "visualization" && editWidgetOptions && rightClickSelected && (<EditWidgetOption options={["Duplicate", "Vertical Move", "Horizontal Move", "RotateX", "RotateY", "Delete",]} />)}
{activeModule === "visualization" &&
editWidgetOptions &&
rightClickSelected && (
<EditWidgetOption
options={[
"Duplicate",
"Vertical Move",
"Horizontal Move",
"RotateX",
"RotateY",
"Delete",
]}
/>
)}
{activeModule === "visualization" && ( {activeModule === "visualization" && (
<> <>
<DisplayZone <DisplayZone zonesData={zonesData} hiddenPanels={hiddenPanels} setHiddenPanels={setHiddenPanels} />
zonesData={zonesData} {!isPlaying && selectedZone?.zoneName !== "" &&
selectedZone={selectedZone} (<AddButtons hiddenPanels={hiddenPanels} setHiddenPanels={setHiddenPanels} />)}
setSelectedZone={setSelectedZone} <Panel hiddenPanels={hiddenPanels} setZonesData={setZonesData} />
hiddenPanels={hiddenPanels}
setHiddenPanels={setHiddenPanels}
/>
{!isPlaying && selectedZone?.zoneName !== "" && (
<AddButtons
hiddenPanels={hiddenPanels}
setHiddenPanels={setHiddenPanels}
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
/>
)}
<Panel
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
hiddenPanels={hiddenPanels}
setZonesData={setZonesData}
/>
</> </>
)} )}
</div> </div>

View File

@@ -6,100 +6,48 @@ import {
} from "../../../../components/icons/RealTimeVisulationIcons"; } from "../../../../components/icons/RealTimeVisulationIcons";
import { AddIcon } from "../../../../components/icons/ExportCommonIcons"; import { AddIcon } from "../../../../components/icons/ExportCommonIcons";
import { useSocketStore } from "../../../../store/store"; import { useSocketStore } from "../../../../store/store";
import { clearPanel } from "../../../../services/realTimeVisulization/zoneData/clearPanel"; import { useSelectedZoneStore } from "../../../../store/useZoneStore";
import { lockPanel } from "../../../../services/realTimeVisulization/zoneData/lockPanel";
// Define the type for `Side` // Define the type for `Side`
type Side = "top" | "bottom" | "left" | "right"; type Side = "top" | "bottom" | "left" | "right";
// Define the type for HiddenPanels, where keys are zone IDs and values are arrays of hidden sides
interface HiddenPanels { interface HiddenPanels {
[zoneId: string]: Side[]; [zoneId: string]: Side[];
} }
// Define the type for the props passed to the Buttons component
interface ButtonsProps { interface ButtonsProps {
selectedZone: {
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
points: [];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
widgets: {
id: string;
type: string;
title: string;
panel: Side;
data: any;
}[];
};
setSelectedZone: React.Dispatch<
React.SetStateAction<{
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
points: [];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
widgets: {
id: string;
type: string;
title: string;
panel: Side;
data: any;
}[];
}>
>;
hiddenPanels: HiddenPanels; // Updated prop type hiddenPanels: HiddenPanels; // Updated prop type
setHiddenPanels: React.Dispatch<React.SetStateAction<HiddenPanels>>; // Updated prop type setHiddenPanels: React.Dispatch<React.SetStateAction<HiddenPanels>>; // Updated prop type
} }
const AddButtons: React.FC<ButtonsProps> = ({ const AddButtons: React.FC<ButtonsProps> = ({ setHiddenPanels, hiddenPanels, }) => {
selectedZone,
setSelectedZone, const { selectedZone, setSelectedZone } = useSelectedZoneStore();
setHiddenPanels,
hiddenPanels,
}) => {
const { visualizationSocket } = useSocketStore(); const { visualizationSocket } = useSocketStore();
// Function to toggle visibility of a panel // Function to toggle visibility of a panel
const toggleVisibility = (side: Side) => { const toggleVisibility = (side: Side) => {
const isHidden = hiddenPanels[selectedZone.zoneId]?.includes(side) ?? false; const isHidden = hiddenPanels[selectedZone.zoneId]?.includes(side) ?? false;
if (isHidden) { if (isHidden) {
// If the panel is already hidden, remove it from the hiddenPanels array for this zone // If the panel is already hidden, remove it from the hiddenPanels array for this zone
setHiddenPanels((prevHiddenPanels) => ({ setHiddenPanels((prevHiddenPanels) => ({
...prevHiddenPanels, ...prevHiddenPanels,
[selectedZone.zoneId]: prevHiddenPanels[selectedZone.zoneId].filter( [selectedZone.zoneId]: prevHiddenPanels[selectedZone.zoneId].filter((panel) => panel !== side),
(panel) => panel !== side
),
})); }));
} else { } else {
// If the panel is visible, add it to the hiddenPanels array for this zone // If the panel is visible, add it to the hiddenPanels array for this zone
setHiddenPanels((prevHiddenPanels) => ({ setHiddenPanels((prevHiddenPanels) => ({
...prevHiddenPanels, ...prevHiddenPanels,
[selectedZone.zoneId]: [ [selectedZone.zoneId]: [...(prevHiddenPanels[selectedZone.zoneId] || []), side,],
...(prevHiddenPanels[selectedZone.zoneId] || []),
side,
],
})); }));
} }
}; };
// Function to toggle lock/unlock a panel // Function to toggle lock/unlock a panel
const toggleLockPanel = async (side: Side) => { const toggleLockPanel = async (side: Side) => {
// console.log('side: ', side);
const email = localStorage.getItem("email") || ""; const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0]; // Fallback value const organization = email?.split("@")[1]?.split(".")[0]; // Fallback value
//add api
const newLockedPanels = selectedZone.lockedPanels.includes(side) const newLockedPanels = selectedZone.lockedPanels.includes(side) ? selectedZone.lockedPanels.filter((panel) => panel !== side) : [...selectedZone.lockedPanels, side];
? selectedZone.lockedPanels.filter((panel) => panel !== side)
: [...selectedZone.lockedPanels, side];
const updatedZone = { const updatedZone = {
...selectedZone, ...selectedZone,
@@ -114,10 +62,9 @@ const AddButtons: React.FC<ButtonsProps> = ({
if (visualizationSocket) { if (visualizationSocket) {
visualizationSocket.emit("v2:viz-panel:locked", lockedPanel); visualizationSocket.emit("v2:viz-panel:locked", lockedPanel);
} }
setSelectedZone(updatedZone); setSelectedZone(updatedZone);
// let response = await lockPanel(selectedZone.zoneId, organization, newLockedPanels) // let response = await lockPanel(selectedZone.zoneId, organization, newLockedPanels)
// console.log('response: ', response); //
// if (response.message === 'locked panel updated successfully') { // if (response.message === 'locked panel updated successfully') {
// // Update the selectedZone state // // Update the selectedZone state
// setSelectedZone(updatedZone); // setSelectedZone(updatedZone);
@@ -126,17 +73,9 @@ const AddButtons: React.FC<ButtonsProps> = ({
// Function to clean all widgets from a panel // Function to clean all widgets from a panel
const cleanPanel = async (side: Side) => { const cleanPanel = async (side: Side) => {
//add api if (hiddenPanels[selectedZone.zoneId]?.includes(side) || selectedZone.lockedPanels.includes(side)) return;
// console.log('side: ', side);
if (
hiddenPanels[selectedZone.zoneId]?.includes(side) ||
selectedZone.lockedPanels.includes(side)
)
return;
const email = localStorage.getItem("email") || ""; const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0]; // Fallback value const organization = email?.split("@")[1]?.split(".")[0]; // Fallback value
let clearPanel = { let clearPanel = {
organization: organization, organization: organization,
panelName: side, panelName: side,
@@ -145,54 +84,33 @@ const AddButtons: React.FC<ButtonsProps> = ({
if (visualizationSocket) { if (visualizationSocket) {
visualizationSocket.emit("v2:viz-panel:clear", clearPanel); visualizationSocket.emit("v2:viz-panel:clear", clearPanel);
} }
const cleanedWidgets = selectedZone.widgets.filter( const cleanedWidgets = selectedZone.widgets.filter((widget) => widget.panel !== side);
(widget) => widget.panel !== side
);
const updatedZone = { const updatedZone = {
...selectedZone, ...selectedZone,
widgets: cleanedWidgets, widgets: cleanedWidgets,
}; };
// Update the selectedZone state // Update the selectedZone state
// console.log('updatedZone: ', updatedZone);
setSelectedZone(updatedZone); setSelectedZone(updatedZone);
// let response = await clearPanel(selectedZone.zoneId, organization, side)
// console.log('response: ', response);
// if (response.message === 'PanelWidgets cleared successfully') {
// const cleanedWidgets = selectedZone.widgets.filter(
// (widget) => widget.panel !== side
// );
// const updatedZone = {
// ...selectedZone,
// widgets: cleanedWidgets,
// };
// // Update the selectedZone state
// setSelectedZone(updatedZone);
// }
}; };
// Function to handle "+" button click // Function to handle "+" button click
const handlePlusButtonClick = async (side: Side) => { const handlePlusButtonClick = async (side: Side) => {
if (selectedZone.activeSides.includes(side)) {
console.log("open"); // Get email and organization safely with a default fallback
// Panel already exists: Remove widgets from that side and update activeSides
const email = localStorage.getItem("email") || ""; const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0]; // Fallback value const organization = email?.split("@")[1]?.split(".")[0];
if (selectedZone.activeSides.includes(side)) {
// Panel already exists: Remove widgets from that side and update activeSides
// Remove all widgets associated with the side and update active sides // Remove all widgets associated with the side and update active sides
const cleanedWidgets = selectedZone.widgets.filter( const cleanedWidgets = selectedZone.widgets.filter((widget) => widget.panel !== side);
(widget) => widget.panel !== side
);
const newActiveSides = selectedZone.activeSides.filter((s) => s !== side); const newActiveSides = selectedZone.activeSides.filter((s) => s !== side);
const updatedZone = { const updatedZone = {
...selectedZone, ...selectedZone,
widgets: cleanedWidgets, widgets: cleanedWidgets,
activeSides: newActiveSides, activeSides: newActiveSides,
panelOrder: newActiveSides, panelOrder: newActiveSides,
}; };
let deletePanel = { let deletePanel = {
organization: organization, organization: organization,
panelName: side, panelName: side,
@@ -202,41 +120,17 @@ const AddButtons: React.FC<ButtonsProps> = ({
visualizationSocket.emit("v2:viz-panel:delete", deletePanel); visualizationSocket.emit("v2:viz-panel:delete", deletePanel);
} }
setSelectedZone(updatedZone); setSelectedZone(updatedZone);
if (hiddenPanels[selectedZone.zoneId]?.includes(side)) { if (hiddenPanels[selectedZone.zoneId]?.includes(side)) {
setHiddenPanels((prev) => ({ setHiddenPanels((prev) => ({
...prev, ...prev,
[selectedZone.zoneId]: prev[selectedZone.zoneId].filter( [selectedZone.zoneId]: prev[selectedZone.zoneId].filter((s) => s !== side),
(s) => s !== side
),
})); }));
} }
// if(hiddenPanels[selectedZone.zoneId].includes(side))
// API call to delete the panel
// try {
// const response = await deletePanelApi(selectedZone.zoneId, side, organization);
//
// if (response.message === "Panel deleted successfully") {
// } else {
//
// }
// } catch (error) {
//
// }
} else { } else {
// Panel does not exist: Create panel // Panel does not exist: Create panel
try { try {
// Get email and organization safely with a default fallback
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0];
// Prevent duplicate side entries // Prevent duplicate side entries
const newActiveSides = selectedZone.activeSides.includes(side) const newActiveSides = selectedZone.activeSides.includes(side)? [...selectedZone.activeSides]: [...selectedZone.activeSides, side];
? [...selectedZone.activeSides]
: [...selectedZone.activeSides, side];
const updatedZone = { const updatedZone = {
...selectedZone, ...selectedZone,
activeSides: newActiveSides, activeSides: newActiveSides,
@@ -251,15 +145,7 @@ const AddButtons: React.FC<ButtonsProps> = ({
visualizationSocket.emit("v2:viz-panel:add", addPanel); visualizationSocket.emit("v2:viz-panel:add", addPanel);
} }
setSelectedZone(updatedZone); setSelectedZone(updatedZone);
// API call to create panels } catch (error) { }
// const response = await panelData(organization, selectedZone.zoneId, newActiveSides);
//
// if (response.message === "Panels created successfully") {
// } else {
//
// }
} catch (error) {}
} }
}; };
return ( return (
@@ -268,20 +154,11 @@ const AddButtons: React.FC<ButtonsProps> = ({
{(["top", "right", "bottom", "left"] as Side[]).map((side) => ( {(["top", "right", "bottom", "left"] as Side[]).map((side) => (
<div key={side} className={`side-button-container ${side}`}> <div key={side} className={`side-button-container ${side}`}>
{/* "+" Button */} {/* "+" Button */}
<button <button className={`side-button ${side}${selectedZone.activeSides.includes(side) ? " active" : ""}`}
className={`side-button ${side}${
selectedZone.activeSides.includes(side) ? " active" : ""
}`}
onClick={() => handlePlusButtonClick(side)} onClick={() => handlePlusButtonClick(side)}
title={ title={selectedZone.activeSides.includes(side) ? `Remove all items and close ${side} panel` : `Activate ${side} panel`}
selectedZone.activeSides.includes(side)
? `Remove all items and close ${side} panel`
: `Activate ${side} panel`
}
> >
<div className="add-icon"> <div className="add-icon"><AddIcon /></div>
<AddIcon />
</div>
</button> </button>
{/* Extra Buttons */} {/* Extra Buttons */}
@@ -289,62 +166,28 @@ const AddButtons: React.FC<ButtonsProps> = ({
<div className="extra-Bs"> <div className="extra-Bs">
{/* Hide Panel */} {/* Hide Panel */}
<div <div
className={`icon ${ className={`icon ${hiddenPanels[selectedZone.zoneId]?.includes(side) ? "active" : ""}`}
hiddenPanels[selectedZone.zoneId]?.includes(side) title={hiddenPanels[selectedZone.zoneId]?.includes(side) ? "Show Panel" : "Hide Panel"}
? "active"
: ""
}`}
title={
hiddenPanels[selectedZone.zoneId]?.includes(side)
? "Show Panel"
: "Hide Panel"
}
onClick={() => toggleVisibility(side)} onClick={() => toggleVisibility(side)}
> >
<EyeIcon <EyeIcon fill={hiddenPanels[selectedZone.zoneId]?.includes(side) ? "var(--primary-color)" : "var(--text-color)"} />
fill={
hiddenPanels[selectedZone.zoneId]?.includes(side)
? "var(--primary-color)"
: "var(--text-color)"
}
/>
</div> </div>
{/* Clean Panel */} {/* Clean Panel */}
<div <div className="icon" title="Clean Panel"
className="icon"
title="Clean Panel"
onClick={() => cleanPanel(side)} onClick={() => cleanPanel(side)}
style={{ style={{ cursor: hiddenPanels[selectedZone.zoneId]?.includes(side) || selectedZone.lockedPanels.includes(side) ? "not-allowed" : "pointer", }}
cursor:
hiddenPanels[selectedZone.zoneId]?.includes(side) ||
selectedZone.lockedPanels.includes(side)
? "not-allowed"
: "pointer",
}}
> >
<CleanPannel /> <CleanPannel />
</div> </div>
{/* Lock/Unlock Panel */} {/* Lock/Unlock Panel */}
<div <div
className={`icon ${ className={`icon ${selectedZone.lockedPanels.includes(side) ? "active" : ""}`}
selectedZone.lockedPanels.includes(side) ? "active" : "" title={selectedZone.lockedPanels.includes(side) ? "Unlock Panel" : "Lock Panel"}
}`}
title={
selectedZone.lockedPanels.includes(side)
? "Unlock Panel"
: "Lock Panel"
}
onClick={() => toggleLockPanel(side)} onClick={() => toggleLockPanel(side)}
> >
<LockIcon <LockIcon fill={selectedZone.lockedPanels.includes(side) ? "var(--primary-color)" : "var(--text-color)"} />
fill={
selectedZone.lockedPanels.includes(side)
? "var(--primary-color)"
: "var(--text-color)"
}
/>
</div> </div>
</div> </div>
)} )}

View File

@@ -5,94 +5,46 @@ import { useAsset3dWidget, useSocketStore } from "../../../../store/store";
import { usePlayButtonStore } from "../../../../store/usePlayButtonStore"; import { usePlayButtonStore } from "../../../../store/usePlayButtonStore";
import { useWidgetStore } from "../../../../store/useWidgetStore"; import { useWidgetStore } from "../../../../store/useWidgetStore";
import { DraggableWidget } from "../2d/DraggableWidget"; import { DraggableWidget } from "../2d/DraggableWidget";
import { useSelectedZoneStore } from "../../../../store/useZoneStore";
type Side = "top" | "bottom" | "left" | "right"; type Side = "top" | "bottom" | "left" | "right";
interface Widget {
id: string;
type: string;
title: string;
panel: Side;
data: any;
}
interface PanelProps { interface PanelProps {
selectedZone: {
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
points: [];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
widgets: Widget[];
};
setSelectedZone: React.Dispatch<
React.SetStateAction<{
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
points: [];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
widgets: Widget[];
}>
>;
hiddenPanels: any; hiddenPanels: any;
setZonesData: React.Dispatch<React.SetStateAction<any>>; setZonesData: React.Dispatch<React.SetStateAction<any>>;
} }
const generateUniqueId = () =>`${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
const generateUniqueId = () => const Panel: React.FC<PanelProps> = ({hiddenPanels,setZonesData,}) => {
`${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; //zustand state
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
const Panel: React.FC<PanelProps> = ({
selectedZone,
setSelectedZone,
hiddenPanels,
setZonesData,
}) => {
const { widgetSelect, setWidgetSelect } = useAsset3dWidget();
const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({});
const [panelDimensions, setPanelDimensions] = useState<{
[side in Side]?: { width: number; height: number };
}>({});
const [openKebabId, setOpenKebabId] = useState<string | null>(null);
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { visualizationSocket } = useSocketStore(); const { visualizationSocket } = useSocketStore();
const [canvasDimensions, setCanvasDimensions] = useState({
width: 0, const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({});
height: 0, const [panelDimensions, setPanelDimensions] = useState<{ [side in Side]?: { width: number; height: number }; }>({});
}); const [openKebabId, setOpenKebabId] = useState<string | null>(null);
const [canvasDimensions, setCanvasDimensions] = useState({ width: 0, height: 0, });
// Track canvas dimensions // Track canvas dimensions
useEffect(() => { useEffect(() => {
const canvas = document.getElementById("real-time-vis-canvas"); const canvas = document.getElementById("real-time-vis-canvas");
if (!canvas) return; if (!canvas) return;
const updateCanvasDimensions = () => { const updateCanvasDimensions = () => {
const rect = canvas.getBoundingClientRect(); const rect = canvas.getBoundingClientRect();
setCanvasDimensions({ setCanvasDimensions({ width: rect.width, height: rect.height, });
width: rect.width,
height: rect.height,
});
}; };
updateCanvasDimensions(); updateCanvasDimensions();
const resizeObserver = new ResizeObserver(updateCanvasDimensions); const resizeObserver = new ResizeObserver(updateCanvasDimensions);
resizeObserver.observe(canvas); resizeObserver.observe(canvas);
return () => resizeObserver.unobserve(canvas); return () => resizeObserver.unobserve(canvas);
}, []); }, []);
// Calculate panel size // Min 170px
// Calculate panel size const panelSize = Math.max(Math.min(canvasDimensions.width * 0.25, canvasDimensions.height * 0.25), 170);
const panelSize = Math.max( // Check if panel is locked
Math.min(canvasDimensions.width * 0.25, canvasDimensions.height * 0.25), const isPanelLocked = (panel: Side) => selectedZone.lockedPanels.includes(panel);
170 // Min 170px // Get current widget count in a panel
); const getCurrentWidgetCount = (panel: Side) => selectedZone.widgets.filter((w) => w.panel === panel).length;
// Define getPanelStyle // Define getPanelStyle
const getPanelStyle = useMemo( const getPanelStyle = useMemo(
() => (side: Side) => { () => (side: Side) => {
@@ -108,8 +60,7 @@ const Panel: React.FC<PanelProps> = ({
case "bottom": case "bottom":
return { return {
minWidth: "170px", minWidth: "170px",
width: `calc(100% - ${(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0) width: `calc(100% - ${(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)}px)`,
}px)`,
minHeight: "170px", minHeight: "170px",
height: `${panelSize}px`, height: `${panelSize}px`,
left: leftActive ? `${panelSize}px` : "0", left: leftActive ? `${panelSize}px` : "0",
@@ -122,8 +73,7 @@ const Panel: React.FC<PanelProps> = ({
minWidth: "170px", minWidth: "170px",
width: `${panelSize}px`, width: `${panelSize}px`,
minHeight: "170px", minHeight: "170px",
height: `calc(100% - ${(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0) height: `calc(100% - ${(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)}px)`,
}px)`,
top: topActive ? `${panelSize}px` : "0", top: topActive ? `${panelSize}px` : "0",
bottom: bottomActive ? `${panelSize}px` : "0", bottom: bottomActive ? `${panelSize}px` : "0",
[side]: "0", [side]: "0",
@@ -134,82 +84,54 @@ const Panel: React.FC<PanelProps> = ({
}, },
[selectedZone.panelOrder, panelSize] [selectedZone.panelOrder, panelSize]
); );
// Handle drop event // Handle drop event
const handleDrop = (e: React.DragEvent, panel: Side) => { const handleDrop = (e: React.DragEvent, panel: Side) => {
e.preventDefault(); e.preventDefault();
const { draggedAsset } = useWidgetStore.getState(); const { draggedAsset } = useWidgetStore.getState();
if ( if (!draggedAsset || isPanelLocked(panel) || hiddenPanels[selectedZone.zoneId]?.includes(panel)) return;
!draggedAsset ||
isPanelLocked(panel) ||
hiddenPanels[selectedZone.zoneId]?.includes(panel)
)
return;
const currentWidgetsCount = getCurrentWidgetCount(panel); const currentWidgetsCount = getCurrentWidgetCount(panel);
const maxCapacity = calculatePanelCapacity(panel); const maxCapacity = calculatePanelCapacity(panel);
if (currentWidgetsCount < maxCapacity) { if (currentWidgetsCount < maxCapacity) {
addWidgetToPanel(draggedAsset, panel); addWidgetToPanel(draggedAsset, panel);
} }
}; };
// Check if panel is locked
const isPanelLocked = (panel: Side) =>
selectedZone.lockedPanels.includes(panel);
// Get current widget count in a panel
const getCurrentWidgetCount = (panel: Side) =>
selectedZone.widgets.filter((w) => w.panel === panel).length;
// Calculate panel capacity // Calculate panel capacity
const calculatePanelCapacity = (panel: Side) => { const calculatePanelCapacity = (panel: Side) => {
const CHART_WIDTH = panelSize - 10; const CHART_WIDTH = panelSize - 10;
const CHART_HEIGHT = panelSize - 10; const CHART_HEIGHT = panelSize - 10;
const dimensions = panelDimensions[panel]; const dimensions = panelDimensions[panel];
if (!dimensions) { if (!dimensions) {
return panel === "top" || panel === "bottom" ? 5 : 3; // Fallback capacities return panel === "top" || panel === "bottom" ? 5 : 3; // Fallback capacities
} }
return panel === "top" || panel === "bottom" ? Math.max(1, Math.floor(dimensions.width / CHART_WIDTH)) : Math.max(1, Math.floor(dimensions.height / CHART_HEIGHT));
return panel === "top" || panel === "bottom"
? Math.max(1, Math.floor(dimensions.width / CHART_WIDTH))
: Math.max(1, Math.floor(dimensions.height / CHART_HEIGHT));
}; };
// 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 = {
...asset, ...asset,
id: generateUniqueId(), id: generateUniqueId(),
panel, panel,
}; };
let addWidget = { let addWidget = {
organization: organization, organization: organization,
zoneId: selectedZone.zoneId, zoneId: selectedZone.zoneId,
widget: newWidget, widget: newWidget,
}; };
if (visualizationSocket) { if (visualizationSocket) {
visualizationSocket.emit("v2:viz-widget:add", addWidget); visualizationSocket.emit("v2:viz-widget:add", addWidget);
} }
setSelectedZone((prev) => ({ setSelectedZone((prev) => ({
...prev, ...prev,
widgets: [...prev.widgets, newWidget], widgets: [...prev.widgets, newWidget],
})); }));
}; };
// Observe panel dimensions // Observe panel dimensions
useEffect(() => { useEffect(() => {
const observers: ResizeObserver[] = []; const observers: ResizeObserver[] = [];
const currentPanelRefs = panelRefs.current; const currentPanelRefs = panelRefs.current;
selectedZone.activeSides.forEach((side) => { selectedZone.activeSides.forEach((side) => {
const element = currentPanelRefs[side]; const element = currentPanelRefs[side];
if (element) { if (element) {
@@ -232,24 +154,18 @@ const Panel: React.FC<PanelProps> = ({
observers.forEach((observer) => observer.disconnect()); observers.forEach((observer) => observer.disconnect());
}; };
}, [selectedZone.activeSides]); }, [selectedZone.activeSides]);
// Handle widget reordering // Handle widget reordering
const handleReorder = (fromIndex: number, toIndex: number, panel: Side) => { const handleReorder = (fromIndex: number, toIndex: number, panel: Side) => {
setSelectedZone((prev) => { setSelectedZone((prev) => {
const widgetsInPanel = prev.widgets.filter((w) => w.panel === panel); const widgetsInPanel = prev.widgets.filter((w) => w.panel === panel);
const reorderedWidgets = arrayMove(widgetsInPanel, fromIndex, toIndex); const reorderedWidgets = arrayMove(widgetsInPanel, fromIndex, toIndex);
const updatedWidgets = prev.widgets.filter((widget) => widget.panel !== panel).concat(reorderedWidgets);
const updatedWidgets = prev.widgets
.filter((widget) => widget.panel !== panel)
.concat(reorderedWidgets);
return { return {
...prev, ...prev,
widgets: updatedWidgets, widgets: updatedWidgets,
}; };
}); });
}; };
// Calculate capacities and dimensions // Calculate capacities and dimensions
const topWidth = getPanelStyle("top").width; const topWidth = getPanelStyle("top").width;
const bottomWidth = getPanelStyle("bottom").height; const bottomWidth = getPanelStyle("bottom").height;
@@ -283,41 +199,29 @@ const Panel: React.FC<PanelProps> = ({
<div <div
key={side} key={side}
id="panel-wrapper" id="panel-wrapper"
className={`panel ${side}-panel absolute ${hiddenPanels[selectedZone.zoneId]?.includes(side) ? "hidePanel" : "" className={`panel ${side}-panel absolute ${hiddenPanels[selectedZone.zoneId]?.includes(side) ? "hidePanel" : ""}`}
}`}
style={getPanelStyle(side)} style={getPanelStyle(side)}
onDrop={(e) => handleDrop(e, side)} onDrop={(e) => handleDrop(e, side)}
onDragOver={(e) => e.preventDefault()} onDragOver={(e) => e.preventDefault()}
ref={(el) => { ref={(el) => {
if (el) { if (el) { panelRefs.current[side] = el; }
panelRefs.current[side] = el; else { delete panelRefs.current[side]; }
} else {
delete panelRefs.current[side];
}
}} }}
> >
<div <div
className={`panel-content ${isPlaying && "fullScreen"}`} className={`panel-content ${isPlaying && "fullScreen"}`}
style={{ style={{
pointerEvents: pointerEvents:selectedZone.lockedPanels.includes(side) || hiddenPanels[selectedZone.zoneId]?.includes(side)? "none": "auto",
selectedZone.lockedPanels.includes(side) ||
hiddenPanels[selectedZone.zoneId]?.includes(side)
? "none"
: "auto",
opacity: selectedZone.lockedPanels.includes(side) ? "0.8" : "1", opacity: selectedZone.lockedPanels.includes(side) ? "0.8" : "1",
}} }}
> >
{selectedZone.widgets {selectedZone.widgets.filter((w) => w.panel === side).map((widget, index) => (
.filter((w) => w.panel === side)
.map((widget, index) => (
<DraggableWidget <DraggableWidget
hiddenPanels={hiddenPanels} hiddenPanels={hiddenPanels}
widget={widget} widget={widget}
key={widget.id} key={widget.id}
index={index} index={index}
onReorder={(fromIndex, toIndex) => onReorder={(fromIndex, toIndex) =>handleReorder(fromIndex, toIndex, side)}
handleReorder(fromIndex, toIndex, side)
}
openKebabId={openKebabId} openKebabId={openKebabId}
setOpenKebabId={setOpenKebabId} setOpenKebabId={setOpenKebabId}
selectedZone={selectedZone} selectedZone={selectedZone}

View File

@@ -1,18 +1,16 @@
import React, { useEffect, useRef } from 'react' import React, { useEffect, useRef } from 'react'
import { useSelectedFloorItem, useZoneAssetId } from '../../store/store'; import { useSelectedFloorItem, useZoneAssetId, useToggleView } from '../../store/store';
import * as THREE from "three"; import * as THREE from "three";
import { useThree } from '@react-three/fiber'; import { useThree } from '@react-three/fiber';
import * as Types from "../../types/world/worldTypes";
export default function ZoneAssets() { export default function ZoneAssets() {
const { zoneAssetId, setZoneAssetId } = useZoneAssetId(); const { zoneAssetId } = useZoneAssetId();
const { setSelectedFloorItem } = useSelectedFloorItem(); const { setSelectedFloorItem } = useSelectedFloorItem();
const { raycaster, controls, scene }: any = useThree(); const { toggleView } = useToggleView();
useEffect(() => { const { controls, scene }: any = useThree();
// console.log('zoneAssetId: ', zoneAssetId);
if (!zoneAssetId) return function focusAsset(AssetMesh: any) {
console.log('zoneAssetId: ', zoneAssetId); console.log('AssetMesh: ', AssetMesh);
let AssetMesh = scene.getObjectByProperty("uuid", zoneAssetId.id); if (toggleView) return;
if (AssetMesh) {
const bbox = new THREE.Box3().setFromObject(AssetMesh); const bbox = new THREE.Box3().setFromObject(AssetMesh);
const size = bbox.getSize(new THREE.Vector3()); const size = bbox.getSize(new THREE.Vector3());
const center = bbox.getCenter(new THREE.Vector3()); const center = bbox.getCenter(new THREE.Vector3());
@@ -29,53 +27,33 @@ export default function ZoneAssets() {
controls.fitToBox(AssetMesh, true, { cover: true, paddingTop: 5, paddingLeft: 5, paddingBottom: 5, paddingRight: 5, }); controls.fitToBox(AssetMesh, true, { cover: true, paddingTop: 5, paddingLeft: 5, paddingBottom: 5, paddingRight: 5, });
setSelectedFloorItem(AssetMesh); setSelectedFloorItem(AssetMesh);
}
useEffect(() => {
if (!zoneAssetId) return
let AssetMesh = scene.getObjectByProperty("uuid", zoneAssetId.id);
if (AssetMesh) {
focusAsset(AssetMesh)
} else { } else {
console.log('zoneAssetId: ', zoneAssetId)
if (Array.isArray(zoneAssetId.position) && zoneAssetId.position.length >= 3) { if (Array.isArray(zoneAssetId.position) && zoneAssetId.position.length >= 3) {
let selectedAssetPosition = [ let selectedAssetPosition = [zoneAssetId.position[0], 10, zoneAssetId.position[2]];
zoneAssetId.position[0], let selectedAssetTarget = [zoneAssetId.position[0], zoneAssetId.position[1], zoneAssetId.position[2]];
10, const setCamera = async () => {
zoneAssetId.position[2]
];
console.log('selectedAssetPosition: ', selectedAssetPosition);
let selectedAssetTarget = [
zoneAssetId.position[0],
zoneAssetId.position[1],
zoneAssetId.position[2]
];
console.log('selectedAssetTarget: ', selectedAssetTarget);
const setCam = async () => {
await controls?.setLookAt(...selectedAssetPosition, ...selectedAssetTarget, true); await controls?.setLookAt(...selectedAssetPosition, ...selectedAssetTarget, true);
setTimeout(() => { setTimeout(() => {
let AssetMesh = scene.getObjectByProperty("uuid", zoneAssetId.id); let AssetMesh = scene.getObjectByProperty("uuid", zoneAssetId.id);
if (AssetMesh) { if (AssetMesh) {
const bbox = new THREE.Box3().setFromObject(AssetMesh); focusAsset(AssetMesh)
const size = bbox.getSize(new THREE.Vector3());
const center = bbox.getCenter(new THREE.Vector3());
const front = new THREE.Vector3(0, 0, 1);
AssetMesh.localToWorld(front);
front.sub(AssetMesh.position).normalize();
const distance = Math.max(size.x, size.y, size.z) * 2;
const newPosition = center.clone().addScaledVector(front, distance);
controls.setPosition(newPosition.x, newPosition.y, newPosition.z, true);
controls.setTarget(center.x, center.y, center.z, true);
controls.fitToBox(AssetMesh, true, { cover: true, paddingTop: 5, paddingLeft: 5, paddingBottom: 5, paddingRight: 5, });
setSelectedFloorItem(AssetMesh);
} }
}, 500) }, 500)
}; };
setCam(); setCamera();
} }
} }
}, [zoneAssetId, scene, controls]) }, [zoneAssetId, scene, controls])
return ( return (
<> <>
</> </>