updated realTimeViz componet sturucture and data
This commit is contained in:
196
frontend/src/pages/realTimeVisualization/panel.tsx
Normal file
196
frontend/src/pages/realTimeVisualization/panel.tsx
Normal file
@@ -0,0 +1,196 @@
|
||||
import React, { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { DraggableWidget } from "./draggableWidget";
|
||||
import { useWidgetStore } from "../../store/store";
|
||||
|
||||
type Side = "top" | "bottom" | "left" | "right";
|
||||
|
||||
interface PanelProps {
|
||||
selectedZone: {
|
||||
zoneName: string; // Add zoneName property
|
||||
activeSides: Side[];
|
||||
panelOrder: Side[];
|
||||
lockedPanels: Side[];
|
||||
widgets: {
|
||||
id: string;
|
||||
type: string;
|
||||
title: string;
|
||||
panel: Side;
|
||||
data: any;
|
||||
}[];
|
||||
};
|
||||
setSelectedZone: React.Dispatch<
|
||||
React.SetStateAction<{
|
||||
zoneName: string; // Ensure zoneName is included in the state type
|
||||
activeSides: Side[];
|
||||
panelOrder: Side[];
|
||||
lockedPanels: Side[];
|
||||
widgets: {
|
||||
id: string;
|
||||
type: string;
|
||||
title: string;
|
||||
panel: Side;
|
||||
data: any;
|
||||
}[];
|
||||
}>
|
||||
>;
|
||||
}
|
||||
|
||||
const generateUniqueId = () =>
|
||||
`${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
||||
|
||||
const Panel: React.FC<PanelProps> = ({ selectedZone, setSelectedZone }) => {
|
||||
const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({});
|
||||
const [panelDimensions, setPanelDimensions] = useState<{
|
||||
[side in Side]?: { width: number; height: number };
|
||||
}>({});
|
||||
|
||||
const getPanelStyle = useMemo(
|
||||
() => (side: Side) => {
|
||||
const currentIndex = selectedZone.panelOrder.indexOf(side);
|
||||
const previousPanels = selectedZone.panelOrder.slice(0, currentIndex);
|
||||
const leftActive = previousPanels.includes("left");
|
||||
const rightActive = previousPanels.includes("right");
|
||||
const topActive = previousPanels.includes("top");
|
||||
const bottomActive = previousPanels.includes("bottom");
|
||||
|
||||
switch (side) {
|
||||
case "top":
|
||||
case "bottom":
|
||||
return {
|
||||
width: `calc(100% - ${
|
||||
(leftActive ? 204 : 0) + (rightActive ? 204 : 0)
|
||||
}px)`,
|
||||
left: leftActive ? "204px" : "0",
|
||||
right: rightActive ? "204px" : "0",
|
||||
[side]: "0",
|
||||
height: "200px",
|
||||
};
|
||||
case "left":
|
||||
case "right":
|
||||
return {
|
||||
height: `calc(100% - ${
|
||||
(topActive ? 204 : 0) + (bottomActive ? 204 : 0)
|
||||
}px)`,
|
||||
top: topActive ? "204px" : "0",
|
||||
bottom: bottomActive ? "204px" : "0",
|
||||
[side]: "0",
|
||||
width: "200px",
|
||||
};
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
[selectedZone.panelOrder]
|
||||
);
|
||||
|
||||
const handleDrop = (e: React.DragEvent, panel: Side) => {
|
||||
e.preventDefault();
|
||||
const { draggedAsset } = useWidgetStore.getState();
|
||||
if (draggedAsset) {
|
||||
if (selectedZone.lockedPanels.includes(panel)) return;
|
||||
|
||||
const currentWidgetsInPanel = selectedZone.widgets.filter(
|
||||
(w) => w.panel === panel
|
||||
).length;
|
||||
|
||||
const dimensions = panelDimensions[panel];
|
||||
const CHART_WIDTH = 200; // Width of each chart for top/bottom panels
|
||||
const CHART_HEIGHT = 200; // Height of each chart for left/right panels
|
||||
let maxCharts = 0;
|
||||
|
||||
if (dimensions) {
|
||||
if (panel === "top" || panel === "bottom") {
|
||||
maxCharts = Math.floor(dimensions.width / CHART_WIDTH); // Use width for top/bottom
|
||||
} else {
|
||||
maxCharts = Math.floor(dimensions.height / CHART_HEIGHT); // Use height for left/right
|
||||
}
|
||||
} else {
|
||||
maxCharts = panel === "top" || panel === "bottom" ? 5 : 3; // Default values
|
||||
}
|
||||
|
||||
if (currentWidgetsInPanel >= maxCharts) {
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedZone = {
|
||||
...selectedZone,
|
||||
widgets: [
|
||||
...selectedZone.widgets,
|
||||
{
|
||||
...draggedAsset,
|
||||
id: generateUniqueId(),
|
||||
panel,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Update the selectedZone state
|
||||
setSelectedZone(updatedZone);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const observers: ResizeObserver[] = [];
|
||||
const currentPanelRefs = panelRefs.current;
|
||||
|
||||
selectedZone.activeSides.forEach((side) => {
|
||||
const element = currentPanelRefs[side];
|
||||
if (element) {
|
||||
const observer = new ResizeObserver((entries) => {
|
||||
for (const entry of entries) {
|
||||
const { width, height } = entry.contentRect;
|
||||
setPanelDimensions((prev) => ({
|
||||
...prev,
|
||||
[side]: { width, height },
|
||||
}));
|
||||
}
|
||||
});
|
||||
observer.observe(element);
|
||||
observers.push(observer);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
observers.forEach((observer) => observer.disconnect());
|
||||
};
|
||||
}, [selectedZone.activeSides]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{selectedZone.activeSides.map((side) => (
|
||||
<div
|
||||
key={side}
|
||||
className={`panel ${side}-panel absolute`}
|
||||
style={getPanelStyle(side)} // Pass `side` to `getPanelStyle`
|
||||
onDrop={(e) => handleDrop(e, side)}
|
||||
onDragOver={(e) => e.preventDefault()}
|
||||
ref={(el) => {
|
||||
if (el) {
|
||||
panelRefs.current[side] = el;
|
||||
} else {
|
||||
delete panelRefs.current[side];
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="panel-content"
|
||||
style={{
|
||||
pointerEvents: selectedZone.lockedPanels.includes(side)
|
||||
? "none"
|
||||
: "auto",
|
||||
opacity: selectedZone.lockedPanels.includes(side) ? "0.8" : "1",
|
||||
}}
|
||||
>
|
||||
{selectedZone.widgets
|
||||
.filter((w) => w.panel === side)
|
||||
.map((widget) => (
|
||||
<DraggableWidget widget={widget} key={widget.id} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Panel;
|
||||
Reference in New Issue
Block a user