added pannel hide and EditWidgetOption component
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
// ConfirmationDialog.tsx
|
||||
import React from "react";
|
||||
|
||||
interface ConfirmationPopupProps {
|
||||
message: string;
|
||||
onConfirm: () => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
const ConfirmationPopup: React.FC<ConfirmationPopupProps> = ({
|
||||
message,
|
||||
onConfirm,
|
||||
onCancel,
|
||||
}) => {
|
||||
return (
|
||||
<div className="confirmation-overlay">
|
||||
<div className="confirmation-modal">
|
||||
<p className="message">{message}</p>
|
||||
<div className="buttton-wrapper">
|
||||
<div className="confirmation-button" onClick={onConfirm}>
|
||||
OK
|
||||
</div>
|
||||
<div className="confirmation-button" onClick={onCancel}>
|
||||
Cancel
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConfirmationPopup;
|
||||
@@ -207,10 +207,11 @@ export const DraggableWidget = ({
|
||||
}
|
||||
};
|
||||
|
||||
useClickOutside(chartWidget, () => {
|
||||
setSelectedChartId(null);
|
||||
});
|
||||
// useClickOutside(chartWidget, () => {
|
||||
// setSelectedChartId(null);
|
||||
// });
|
||||
|
||||
console.log('isPanelHidden: ', isPanelHidden);
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
@@ -225,7 +226,6 @@ export const DraggableWidget = ({
|
||||
onDragOver={handleDragOver}
|
||||
onDrop={handleDrop}
|
||||
style={{
|
||||
opacity: isPanelHidden ? 0 : 1,
|
||||
pointerEvents: isPanelHidden ? "none" : "auto",
|
||||
}}
|
||||
ref={chartWidget}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
import { useThree } from "@react-three/fiber";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useAsset3dWidget, useWidgetSubOption } from "../../../store/store";
|
||||
@@ -16,132 +15,141 @@ import { get3dWidgetZoneData } from "../../../services/realTimeVisulization/zone
|
||||
import { use3DWidget } from "../../../store/useDroppedObjectsStore";
|
||||
|
||||
export default function Dropped3dWidgets() {
|
||||
const { widgetSelect } = useAsset3dWidget();
|
||||
const { activeModule } = useModuleStore();
|
||||
const { raycaster, gl, scene }: ThreeState = useThree();
|
||||
const { widgetSubOption, setWidgetSubOption } = useWidgetSubOption();
|
||||
const { selectedZone } = useSelectedZoneStore(); // Get the currently active zone
|
||||
// 🔥 Store widget data (id, type, position) based on the selected zone
|
||||
const [zoneWidgetData, setZoneWidgetData] = useState<
|
||||
Record<string, { id: string; type: string; position: [number, number, number] }[]>
|
||||
>({});
|
||||
const { setWidgets3D } = use3DWidget()
|
||||
useEffect(() => {
|
||||
if (activeModule !== "visualization") return
|
||||
if (selectedZone.zoneName === "") return;
|
||||
const { widgetSelect } = useAsset3dWidget();
|
||||
const { activeModule } = useModuleStore();
|
||||
const { raycaster, gl, scene }: ThreeState = useThree();
|
||||
const { widgetSubOption, setWidgetSubOption } = useWidgetSubOption();
|
||||
const { selectedZone } = useSelectedZoneStore(); // Get the currently active zone
|
||||
// 🔥 Store widget data (id, type, position) based on the selected zone
|
||||
const [zoneWidgetData, setZoneWidgetData] = useState<
|
||||
Record<
|
||||
string,
|
||||
{ id: string; type: string; position: [number, number, number] }[]
|
||||
>
|
||||
>({});
|
||||
const { setWidgets3D } = use3DWidget();
|
||||
useEffect(() => {
|
||||
if (activeModule !== "visualization") return;
|
||||
if (selectedZone.zoneName === "") return;
|
||||
|
||||
const email = localStorage.getItem("email") || "";
|
||||
const organization = email?.split("@")[1]?.split(".")[0];
|
||||
const email = localStorage.getItem("email") || "";
|
||||
const organization = email?.split("@")[1]?.split(".")[0];
|
||||
|
||||
async function get3dWidgetData() {
|
||||
let result = await get3dWidgetZoneData(selectedZone.zoneId, organization);
|
||||
setWidgets3D(result)
|
||||
// Ensure the extracted data has id, type, and position correctly mapped
|
||||
const formattedWidgets = result.map((widget: any) => ({
|
||||
id: widget.id,
|
||||
type: widget.type,
|
||||
position: widget.position,
|
||||
}));
|
||||
async function get3dWidgetData() {
|
||||
let result = await get3dWidgetZoneData(selectedZone.zoneId, organization);
|
||||
setWidgets3D(result);
|
||||
// Ensure the extracted data has id, type, and position correctly mapped
|
||||
const formattedWidgets = result.map((widget: any) => ({
|
||||
id: widget.id,
|
||||
type: widget.type,
|
||||
position: widget.position,
|
||||
}));
|
||||
|
||||
setZoneWidgetData((prev) => ({
|
||||
...prev,
|
||||
[selectedZone.zoneId]: formattedWidgets,
|
||||
}));
|
||||
setZoneWidgetData((prev) => ({
|
||||
...prev,
|
||||
[selectedZone.zoneId]: formattedWidgets,
|
||||
}));
|
||||
}
|
||||
|
||||
get3dWidgetData();
|
||||
}, [selectedZone.zoneId, activeModule]);
|
||||
// useEffect(() => {
|
||||
// // ✅ Set data only for the selected zone, keeping existing state structure
|
||||
// setZoneWidgetData((prev) => ({
|
||||
// ...prev,
|
||||
// [selectedZone.zoneId]: [
|
||||
// {
|
||||
// "id": "1743322674626-50mucpb1c",
|
||||
// "type": "ui-Widget 1",
|
||||
// "position": [120.94655021768133, 4.142360029666558, 124.39283546121099]
|
||||
// },
|
||||
// {
|
||||
// "id": "1743322682086-je2h9x33v",
|
||||
// "type": "ui-Widget 2",
|
||||
// "position": [131.28751045879255, 0.009999999999970264, 133.92059801984362]
|
||||
// }
|
||||
// ]
|
||||
// }));
|
||||
// }, [selectedZone.zoneId]); // ✅ Only update when the zone changes
|
||||
|
||||
useEffect(() => {
|
||||
if (activeModule !== "visualization") return;
|
||||
if (widgetSubOption === "Floating") return;
|
||||
if (selectedZone.zoneName === "") return;
|
||||
const canvasElement = gl.domElement;
|
||||
const onDrop = async (event: DragEvent) => {
|
||||
event.preventDefault(); // Prevent default browser behavior
|
||||
const email = localStorage.getItem("email") || "";
|
||||
const organization = email?.split("@")[1]?.split(".")[0];
|
||||
if (!widgetSelect.startsWith("ui")) return;
|
||||
const group1 = scene.getObjectByName("itemsGroup");
|
||||
if (!group1) return;
|
||||
const intersects = raycaster
|
||||
.intersectObjects(scene.children, true)
|
||||
.filter(
|
||||
(intersect) =>
|
||||
!intersect.object.name.includes("Roof") &&
|
||||
!intersect.object.name.includes("agv-collider") &&
|
||||
!intersect.object.name.includes("MeasurementReference") &&
|
||||
!intersect.object.userData.isPathObject &&
|
||||
!(intersect.object.type === "GridHelper")
|
||||
);
|
||||
if (intersects.length > 0) {
|
||||
const { x, y, z } = intersects[0].point;
|
||||
|
||||
// ✅ Explicitly define position as a tuple
|
||||
const newWidget: {
|
||||
id: string;
|
||||
type: string;
|
||||
position: [number, number, number];
|
||||
} = {
|
||||
id: generateUniqueId(),
|
||||
type: widgetSelect,
|
||||
position: [x, y, z], // Ensures TypeScript recognizes it as a tuple
|
||||
};
|
||||
|
||||
let response = await adding3dWidgets(
|
||||
selectedZone.zoneId,
|
||||
organization,
|
||||
newWidget
|
||||
);
|
||||
|
||||
// ✅ Store widgets uniquely for each zone
|
||||
setZoneWidgetData((prev) => ({
|
||||
...prev,
|
||||
[selectedZone.zoneId]: [
|
||||
...(prev[selectedZone.zoneId] || []),
|
||||
newWidget,
|
||||
],
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
canvasElement.addEventListener("drop", onDrop);
|
||||
return () => {
|
||||
canvasElement.removeEventListener("drop", onDrop);
|
||||
};
|
||||
}, [widgetSelect, activeModule, selectedZone.zoneId, widgetSubOption]);
|
||||
|
||||
// Get widgets for the currently active zone
|
||||
const activeZoneWidgets = zoneWidgetData[selectedZone.zoneId] || [];
|
||||
|
||||
return (
|
||||
<>
|
||||
{activeZoneWidgets.map(({ id, type, position }) => {
|
||||
switch (type) {
|
||||
case "ui-Widget 1":
|
||||
return <ProductionCapacity key={id} position={position} />;
|
||||
case "ui-Widget 2":
|
||||
return <ReturnOfInvestment key={id} position={position} />;
|
||||
case "ui-Widget 3":
|
||||
return <StateWorking key={id} position={position} />;
|
||||
case "ui-Widget 4":
|
||||
return <Throughput key={id} position={position} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
get3dWidgetData();
|
||||
|
||||
}, [selectedZone.zoneId,activeModule]);
|
||||
// useEffect(() => {
|
||||
// // ✅ Set data only for the selected zone, keeping existing state structure
|
||||
// setZoneWidgetData((prev) => ({
|
||||
// ...prev,
|
||||
// [selectedZone.zoneId]: [
|
||||
// {
|
||||
// "id": "1743322674626-50mucpb1c",
|
||||
// "type": "ui-Widget 1",
|
||||
// "position": [120.94655021768133, 4.142360029666558, 124.39283546121099]
|
||||
// },
|
||||
// {
|
||||
// "id": "1743322682086-je2h9x33v",
|
||||
// "type": "ui-Widget 2",
|
||||
// "position": [131.28751045879255, 0.009999999999970264, 133.92059801984362]
|
||||
// }
|
||||
// ]
|
||||
// }));
|
||||
// }, [selectedZone.zoneId]); // ✅ Only update when the zone changes
|
||||
|
||||
useEffect(() => {
|
||||
if (activeModule !== "visualization") return;
|
||||
if (widgetSubOption === "Floating") return;
|
||||
if (selectedZone.zoneName === "") return
|
||||
const canvasElement = gl.domElement;
|
||||
const onDrop = async (event: DragEvent) => {
|
||||
event.preventDefault(); // Prevent default browser behavior
|
||||
const email = localStorage.getItem("email") || "";
|
||||
const organization = email?.split("@")[1]?.split(".")[0];
|
||||
if (!widgetSelect.startsWith("ui")) return;
|
||||
const group1 = scene.getObjectByName("itemsGroup");
|
||||
if (!group1) return;
|
||||
const intersects = raycaster.intersectObjects(scene.children, true).filter(
|
||||
(intersect) =>
|
||||
!intersect.object.name.includes("Roof") &&
|
||||
!intersect.object.name.includes("agv-collider") &&
|
||||
!intersect.object.name.includes("MeasurementReference") &&
|
||||
!intersect.object.userData.isPathObject &&
|
||||
!(intersect.object.type === "GridHelper")
|
||||
);
|
||||
if (intersects.length > 0) {
|
||||
const { x, y, z } = intersects[0].point;
|
||||
|
||||
// ✅ Explicitly define position as a tuple
|
||||
const newWidget: { id: string; type: string; position: [number, number, number] } = {
|
||||
id: generateUniqueId(),
|
||||
type: widgetSelect,
|
||||
position: [x, y, z], // Ensures TypeScript recognizes it as a tuple
|
||||
};
|
||||
|
||||
|
||||
let response = await adding3dWidgets(selectedZone.zoneId, organization, newWidget)
|
||||
|
||||
|
||||
// ✅ Store widgets uniquely for each zone
|
||||
setZoneWidgetData((prev) => ({
|
||||
...prev,
|
||||
[selectedZone.zoneId]: [...(prev[selectedZone.zoneId] || []), newWidget],
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
canvasElement.addEventListener("drop", onDrop);
|
||||
return () => {
|
||||
canvasElement.removeEventListener("drop", onDrop);
|
||||
};
|
||||
}, [widgetSelect, activeModule, selectedZone.zoneId, widgetSubOption]);
|
||||
|
||||
// Get widgets for the currently active zone
|
||||
const activeZoneWidgets = zoneWidgetData[selectedZone.zoneId] || [];
|
||||
|
||||
return (
|
||||
<>
|
||||
{activeZoneWidgets.map(({ id, type, position }) => {
|
||||
switch (type) {
|
||||
case "ui-Widget 1":
|
||||
return <ProductionCapacity key={id} position={position} />;
|
||||
case "ui-Widget 2":
|
||||
return <ReturnOfInvestment key={id} position={position} />;
|
||||
case "ui-Widget 3":
|
||||
return <StateWorking key={id} position={position} />;
|
||||
case "ui-Widget 4":
|
||||
return <Throughput key={id} position={position} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
})}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ import WarehouseThroughputComponent from "../realTimeVis/floating/WarehouseThrou
|
||||
import FleetEfficiencyComponent from "../realTimeVis/floating/FleetEfficiencyComponent";
|
||||
import { useWidgetStore } from "../../../store/useWidgetStore";
|
||||
import { useClickOutside } from "./functions/handleWidgetsOuterClick";
|
||||
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
||||
import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
||||
interface DraggingState {
|
||||
zone: string;
|
||||
index: number;
|
||||
@@ -43,11 +45,14 @@ interface DraggingState {
|
||||
};
|
||||
}
|
||||
const DroppedObjects: React.FC = () => {
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const zones = useDroppedObjectsStore((state) => state.zones);
|
||||
const [openKebabId, setOpenKebabId] = useState<string | null>(null);
|
||||
const updateObjectPosition = useDroppedObjectsStore(
|
||||
(state) => state.updateObjectPosition
|
||||
);
|
||||
const { setSelectedZone, selectedZone } = useSelectedZoneStore();
|
||||
|
||||
const deleteObject = useDroppedObjectsStore((state) => state.deleteObject);
|
||||
|
||||
const duplicateObject = useDroppedObjectsStore(
|
||||
@@ -70,10 +75,9 @@ const DroppedObjects: React.FC = () => {
|
||||
} | null>(null); // State to track the current position during drag
|
||||
const animationRef = useRef<number | null>(null);
|
||||
const { activeModule } = useModuleStore();
|
||||
const chartWidgetFloating = useRef<HTMLDivElement>(null);
|
||||
|
||||
// useClickOutside(chartWidgetFloating, () => {
|
||||
const chartWidget = useRef<HTMLDivElement>(null);
|
||||
|
||||
// useClickOutside(chartWidget, () => {
|
||||
// setSelectedChartId(null);
|
||||
// });
|
||||
|
||||
@@ -115,7 +119,7 @@ const DroppedObjects: React.FC = () => {
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPlaying === true) return;
|
||||
const obj = zone.objects[index];
|
||||
const element = event.currentTarget as HTMLElement;
|
||||
|
||||
@@ -283,7 +287,6 @@ const DroppedObjects: React.FC = () => {
|
||||
updateObjectPosition(zoneName, draggingIndex.index, boundedPosition);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error in handlePointerUp:", error);
|
||||
} finally {
|
||||
setDraggingIndex(null);
|
||||
setOffset(null);
|
||||
@@ -304,7 +307,7 @@ const DroppedObjects: React.FC = () => {
|
||||
|
||||
const handlePointerMove = (event: React.PointerEvent) => {
|
||||
if (!draggingIndex || !offset) return;
|
||||
|
||||
if (isPlaying === true) return;
|
||||
const container = document.getElementById("real-time-vis-canvas");
|
||||
if (!container) return;
|
||||
|
||||
@@ -414,7 +417,6 @@ const DroppedObjects: React.FC = () => {
|
||||
updateObjectPosition(zoneName, draggingIndex.index, boundedPosition);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error in handlePointerUp:", error);
|
||||
} finally {
|
||||
// Clean up regardless of success or failure
|
||||
setDraggingIndex(null);
|
||||
@@ -447,29 +449,45 @@ const DroppedObjects: React.FC = () => {
|
||||
className={`${obj.className} ${
|
||||
selectedChartId?.id === obj.id && "activeChart"
|
||||
}`}
|
||||
ref={chartWidgetFloating}
|
||||
ref={chartWidget}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top:
|
||||
typeof obj.position.top === "number"
|
||||
? `${obj.position.top}px`
|
||||
? `calc(${obj.position.top}px + ${
|
||||
isPlaying && selectedZone.activeSides.includes("top")
|
||||
? 90
|
||||
: 0
|
||||
}px)`
|
||||
: "auto",
|
||||
left:
|
||||
typeof obj.position.left === "number"
|
||||
? `${obj.position.left}px`
|
||||
? `calc(${obj.position.left}px + ${
|
||||
isPlaying && selectedZone.activeSides.includes("left")
|
||||
? 90
|
||||
: 0
|
||||
}px)`
|
||||
: "auto",
|
||||
right:
|
||||
typeof obj.position.right === "number"
|
||||
? `${obj.position.right}px`
|
||||
? `calc(${obj.position.right}px + ${
|
||||
isPlaying && selectedZone.activeSides.includes("right")
|
||||
? 90
|
||||
: 0
|
||||
}px)`
|
||||
: "auto",
|
||||
bottom:
|
||||
typeof obj.position.bottom === "number"
|
||||
? `${obj.position.bottom}px`
|
||||
? `calc(${obj.position.bottom}px + ${
|
||||
isPlaying && selectedZone.activeSides.includes("bottom")
|
||||
? 90
|
||||
: 0
|
||||
}px)`
|
||||
: "auto",
|
||||
}}
|
||||
onPointerDown={(event) => handlePointerDown(event, index)}
|
||||
onClick={() => {
|
||||
onPointerDown={(event) => {
|
||||
setSelectedChartId(obj);
|
||||
handlePointerDown(event, index);
|
||||
}}
|
||||
>
|
||||
{obj.className === "floating total-card" ? (
|
||||
@@ -523,7 +541,8 @@ const DroppedObjects: React.FC = () => {
|
||||
))}
|
||||
|
||||
{/* Render DistanceLines component during drag */}
|
||||
{draggingIndex !== null &&
|
||||
{isPlaying === false &&
|
||||
draggingIndex !== null &&
|
||||
activeEdges !== null &&
|
||||
currentPosition !== null && (
|
||||
<DistanceLines
|
||||
@@ -555,3 +574,5 @@ const DroppedObjects: React.FC = () => {
|
||||
};
|
||||
|
||||
export default DroppedObjects;
|
||||
|
||||
// always place the mousePointer in the same point in the floatingCard even in pointerMove
|
||||
|
||||
@@ -24,7 +24,7 @@ interface PanelProps {
|
||||
lockedPanels: Side[];
|
||||
zoneId: string;
|
||||
zoneViewPortTarget: number[];
|
||||
zoneViewPortPosition: number[]
|
||||
zoneViewPortPosition: number[];
|
||||
widgets: Widget[];
|
||||
};
|
||||
setSelectedZone: React.Dispatch<
|
||||
@@ -36,7 +36,7 @@ interface PanelProps {
|
||||
lockedPanels: Side[];
|
||||
zoneId: string;
|
||||
zoneViewPortTarget: number[];
|
||||
zoneViewPortPosition: number[]
|
||||
zoneViewPortPosition: number[];
|
||||
widgets: Widget[];
|
||||
}>
|
||||
>;
|
||||
@@ -60,6 +60,14 @@ const Panel: React.FC<PanelProps> = ({
|
||||
const [openKebabId, setOpenKebabId] = useState<string | null>(null);
|
||||
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
console.log("selectedZone: ", selectedZone.panelOrder);
|
||||
console.log("hiddenPanels: ", hiddenPanels);
|
||||
|
||||
// Check if any hidden panel is in the panelOrder of selectedZone
|
||||
const isPanelInSelectedZone = hiddenPanels.some(
|
||||
(panel) => selectedZone.panelOrder.includes(panel as Side) // Typecast to Side
|
||||
);
|
||||
console.log("Is panel in selectedZone: ", isPanelInSelectedZone);
|
||||
|
||||
const getPanelStyle = useMemo(
|
||||
() => (side: Side) => {
|
||||
@@ -75,8 +83,9 @@ const Panel: React.FC<PanelProps> = ({
|
||||
case "top":
|
||||
case "bottom":
|
||||
return {
|
||||
width: `calc(100% - ${(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)
|
||||
}px)`,
|
||||
width: `calc(100% - ${
|
||||
(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)
|
||||
}px)`,
|
||||
height: `${panelSize - 2}px`,
|
||||
left: leftActive ? `${panelSize}px` : "0",
|
||||
right: rightActive ? `${panelSize}px` : "0",
|
||||
@@ -86,8 +95,9 @@ const Panel: React.FC<PanelProps> = ({
|
||||
case "right":
|
||||
return {
|
||||
width: `${panelSize - 2}px`,
|
||||
height: `calc(100% - ${(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)
|
||||
}px)`,
|
||||
height: `calc(100% - ${
|
||||
(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)
|
||||
}px)`,
|
||||
top: topActive ? `${panelSize}px` : "0",
|
||||
bottom: bottomActive ? `${panelSize}px` : "0",
|
||||
[side]: "0",
|
||||
@@ -100,7 +110,6 @@ const Panel: React.FC<PanelProps> = ({
|
||||
);
|
||||
|
||||
const handleDrop = (e: React.DragEvent, panel: Side) => {
|
||||
|
||||
e.preventDefault();
|
||||
const { draggedAsset } = useWidgetStore.getState();
|
||||
if (!draggedAsset) return;
|
||||
@@ -141,15 +150,19 @@ const Panel: React.FC<PanelProps> = ({
|
||||
// while dublicate check this and add
|
||||
const addWidgetToPanel = async (asset: any, panel: Side) => {
|
||||
const email = localStorage.getItem("email") || "";
|
||||
const organization = email?.split("@")[1]?.split(".")[0]
|
||||
const organization = email?.split("@")[1]?.split(".")[0];
|
||||
const newWidget = {
|
||||
...asset,
|
||||
id: generateUniqueId(),
|
||||
panel,
|
||||
};
|
||||
try {
|
||||
let response = await addingWidgets(selectedZone.zoneId, organization, newWidget);
|
||||
|
||||
let response = await addingWidgets(
|
||||
selectedZone.zoneId,
|
||||
organization,
|
||||
newWidget
|
||||
);
|
||||
|
||||
if (response.message === "Widget created successfully") {
|
||||
setSelectedZone((prev) => ({
|
||||
...prev,
|
||||
@@ -159,7 +172,6 @@ const Panel: React.FC<PanelProps> = ({
|
||||
} catch (error) {
|
||||
console.error("Error adding widget:", error);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -191,7 +203,6 @@ const Panel: React.FC<PanelProps> = ({
|
||||
const handleReorder = (fromIndex: number, toIndex: number, panel: Side) => {
|
||||
if (!selectedZone) return; // Ensure selectedZone is not null
|
||||
|
||||
|
||||
setSelectedZone((prev) => {
|
||||
if (!prev) return prev; // Ensure prev is not null
|
||||
|
||||
@@ -218,7 +229,9 @@ const Panel: React.FC<PanelProps> = ({
|
||||
{selectedZone.activeSides.map((side) => (
|
||||
<div
|
||||
key={side}
|
||||
className={`panel ${side}-panel absolute ${isPlaying && ""}`}
|
||||
className={`panel ${side}-panel absolute ${isPlaying ? "" : ""} ${
|
||||
hiddenPanels.includes(side) ? "hidePanel" : ""
|
||||
}`}
|
||||
style={getPanelStyle(side)}
|
||||
onDrop={(e) => handleDrop(e, side)}
|
||||
onDragOver={(e) => e.preventDefault()}
|
||||
@@ -264,4 +277,3 @@ const Panel: React.FC<PanelProps> = ({
|
||||
};
|
||||
|
||||
export default Panel;
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@ import { getZone2dData } from "../../../services/realTimeVisulization/zoneData/g
|
||||
import { generateUniqueId } from "../../../functions/generateUniqueId";
|
||||
import { determinePosition } from "./functions/determinePosition";
|
||||
import { addingFloatingWidgets } from "../../../services/realTimeVisulization/zoneData/addFloatingWidgets";
|
||||
import EditWidgetOption from "../menu/EditWidgetOption";
|
||||
import RenderOverlay from "../../templates/Overlay";
|
||||
import ConfirmationPopup from "../../layout/confirmationPopup/ConfirmationPopup";
|
||||
|
||||
type Side = "top" | "bottom" | "left" | "right";
|
||||
|
||||
@@ -51,6 +54,9 @@ const RealTimeVisulization: React.FC = () => {
|
||||
const [zonesData, setZonesData] = useState<FormattedZoneData>({});
|
||||
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
||||
const { zones } = useZones();
|
||||
|
||||
const [openConfirmationPopup, setOpenConfirmationPopup] = useState(false);
|
||||
|
||||
const [floatingWidgets, setFloatingWidgets] = useState<
|
||||
Record<string, { zoneName: string; zoneId: string; objects: any[] }>
|
||||
>({});
|
||||
@@ -63,6 +69,7 @@ const RealTimeVisulization: React.FC = () => {
|
||||
const organization = email?.split("@")[1]?.split(".")[0];
|
||||
try {
|
||||
const response = await getZone2dData(organization);
|
||||
// console.log('response: ', response);
|
||||
|
||||
if (!Array.isArray(response)) {
|
||||
return;
|
||||
@@ -184,6 +191,20 @@ const RealTimeVisulization: React.FC = () => {
|
||||
left: isPlaying || activeModule !== "visualization" ? "0%" : "",
|
||||
}}
|
||||
>
|
||||
{/* <RenderOverlay>
|
||||
<EditWidgetOption
|
||||
options={["Dublicate", "Vertical Move", "Horizontal Move", "Delete"]}
|
||||
/>
|
||||
</RenderOverlay> */}
|
||||
{openConfirmationPopup && (
|
||||
<RenderOverlay>
|
||||
<ConfirmationPopup
|
||||
message={"Are you sure want to delete?"}
|
||||
onConfirm={() => console.log("confirm")}
|
||||
onCancel={() => setOpenConfirmationPopup(false)}
|
||||
/>
|
||||
</RenderOverlay>
|
||||
)}
|
||||
<div
|
||||
className="scene-container"
|
||||
style={{
|
||||
@@ -195,7 +216,7 @@ const RealTimeVisulization: React.FC = () => {
|
||||
onDrop={(event) => handleDrop(event)}
|
||||
onDragOver={(event) => event.preventDefault()}
|
||||
>
|
||||
<Scene />
|
||||
{/* <Scene /> */}
|
||||
</div>
|
||||
{activeModule === "visualization" && selectedZone.zoneName !== "" && (
|
||||
<DroppedObjects />
|
||||
|
||||
@@ -6,17 +6,15 @@ export const useClickOutside = (
|
||||
) => {
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (ref.current && !ref.current.contains(event.target as Node)) {
|
||||
if (ref.current && !event.composedPath().includes(ref.current)) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
// Add event listener to document
|
||||
document.addEventListener("mousedown", handleClickOutside);
|
||||
|
||||
// Cleanup event listener on component unmount
|
||||
return () => {
|
||||
document.removeEventListener("mousedown", handleClickOutside);
|
||||
};
|
||||
}, [ref, callback]);
|
||||
};
|
||||
};
|
||||
21
app/src/components/ui/menu/EditWidgetOption.tsx
Normal file
21
app/src/components/ui/menu/EditWidgetOption.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import React from "react";
|
||||
|
||||
interface EditWidgetOptionProps {
|
||||
options: string[];
|
||||
}
|
||||
|
||||
const EditWidgetOption: React.FC<EditWidgetOptionProps> = ({ options }) => {
|
||||
return (
|
||||
<div className="editWidgetOptions-wrapper">
|
||||
<div className="editWidgetOptions">
|
||||
{options.map((option, index) => (
|
||||
<div className="option" key={index}>
|
||||
{option}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditWidgetOption;
|
||||
Reference in New Issue
Block a user