Merge remote-tracking branch 'origin/ui' into simulation

This commit is contained in:
2025-04-09 18:41:30 +05:30
15 changed files with 827 additions and 647 deletions

View File

@@ -220,8 +220,8 @@ const ProductionCapacity: React.FC<ProductionCapacityProps> = ({
// e.stopPropagation();
}}
wrapperClass="pointer-none"
className={`${selectedChartId?.id === id ? "activeChart" : ""}`}
>
>
<div
className={`productionCapacity-wrapper card ${selectedChartId?.id === id ? "activeChart" : ""}`}
onClick={() => setSelectedChartId({ id: id, type: type })}

View File

@@ -46,20 +46,32 @@ interface ReturnOfInvestmentProps {
rotation: [number, number, number];
onContextMenu?: (event: React.MouseEvent) => void;
}
const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, position, rotation, onContextMenu }) => {
const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({
id,
type,
position,
rotation,
onContextMenu,
}) => {
const { selectedChartId, setSelectedChartId } = useWidgetStore();
const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore();
const {
measurements: chartMeasurements,
duration: chartDuration,
name: widgetName,
} = useChartStore();
const [measurements, setmeasurements] = useState<any>({});
const [duration, setDuration] = useState("1h")
const [name, setName] = useState("Widget")
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
const [duration, setDuration] = useState("1h");
const [name, setName] = useState("Widget");
const [chartData, setChartData] = useState<{
labels: string[];
datasets: any[];
}>({
labels: [],
datasets: [],
});
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0]
const organization = email?.split("@")[1]?.split(".")[0];
// Improved sample data for the smooth curve graph (single day)
const graphData: ChartData<"line"> = {
labels: [
@@ -129,7 +141,8 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, posit
};
useEffect(() => {
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0)
return;
const socket = io(`http://${iotApiUrl}`);
@@ -139,7 +152,6 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, posit
interval: 1000,
};
const startStream = () => {
socket.emit("lineInput", inputData);
};
@@ -157,8 +169,10 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, posit
return {
label: datasetKey,
data: responseData[datasetKey]?.values ?? [],
borderColor: index === 0 ? "rgba(75, 192, 192, 1)" : "rgba(255, 99, 132, 1)", // Light blue color
backgroundColor: index === 0 ? "rgba(75, 192, 192, 0.2)" : "rgba(255, 99, 132, 0.2)",
borderColor:
index === 0 ? "rgba(75, 192, 192, 1)" : "rgba(255, 99, 132, 1)", // Light blue color
backgroundColor:
index === 0 ? "rgba(75, 192, 192, 0.2)" : "rgba(255, 99, 132, 0.2)",
fill: true,
tension: 0.4, // Smooth curve effect
pointRadius: 0, // Hide dots
@@ -177,14 +191,15 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, posit
}, [measurements, duration, iotApiUrl]);
const fetchSavedInputes = async () => {
if (id !== "") {
try {
const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`);
const response = await axios.get(
`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`
);
if (response.status === 200) {
setmeasurements(response.data.Data.measurements)
setDuration(response.data.Data.duration)
setName(response.data.widgetName)
setmeasurements(response.data.Data.measurements);
setDuration(response.data.Data.duration);
setName(response.data.widgetName);
} else {
console.log("Unexpected response:", response);
}
@@ -192,7 +207,7 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, posit
console.error("There was an error!", error);
}
}
}
};
useEffect(() => {
fetchSavedInputes();
@@ -202,8 +217,7 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, posit
if (selectedChartId?.id === id) {
fetchSavedInputes();
}
}
, [chartMeasurements, chartDuration, widgetName])
}, [chartMeasurements, chartDuration, widgetName]);
const rotationDegrees = {
x: (rotation[0] * 180) / Math.PI,
y: (rotation[1] * 180) / Math.PI,
@@ -215,27 +229,32 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, posit
};
return (
<Html position={[position[0], position[1], position[2]]}
<Html
position={[position[0], position[1], position[2]]}
scale={[0.5, 0.5, 0.5]}
transform
zIndexRange={[1, 0]}
sprite
style={{
transform: transformStyle.transform,
transformStyle: 'preserve-3d',
transition: 'transform 0.1s ease-out'
transformStyle: "preserve-3d",
transition: "transform 0.1s ease-out",
}}
className={`${selectedChartId?.id === id ? "activeChart" : ""}`}
>
<div className="returnOfInvestment card"
<div
className={`returnOfInvestment card ${
selectedChartId?.id === id ? "activeChart" : ""
}`}
onClick={() => setSelectedChartId({ id: id, type: type })}
onContextMenu={onContextMenu}
>
<div className="header">Return of Investment</div>
<div className="lineGraph charts">
{/* Smooth curve graph with two datasets */}
<SmoothLineGraphComponent data={Object.keys(measurements).length > 0 ? chartData : graphData} options={graphOptions} />
<SmoothLineGraphComponent
data={Object.keys(measurements).length > 0 ? chartData : graphData}
options={graphOptions}
/>
</div>
<div className="returns-wrapper">
<div className="icon">

View File

@@ -13,16 +13,26 @@ interface StateWorkingProps {
rotation: [number, number, number];
onContextMenu?: (event: React.MouseEvent) => void;
}
const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotation, onContextMenu }) => {
const StateWorking: React.FC<StateWorkingProps> = ({
id,
type,
position,
rotation,
onContextMenu,
}) => {
const { selectedChartId, setSelectedChartId } = useWidgetStore();
const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore();
const {
measurements: chartMeasurements,
duration: chartDuration,
name: widgetName,
} = useChartStore();
const [measurements, setmeasurements] = useState<any>({});
const [duration, setDuration] = useState("1h")
const [name, setName] = useState("Widget")
const [duration, setDuration] = useState("1h");
const [name, setName] = useState("Widget");
const [datas, setDatas] = useState<any>({});
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0]
const organization = email?.split("@")[1]?.split(".")[0];
// const datas = [
// { key: "Oil Tank:", value: "24/341" },
// { key: "Oil Refin:", value: 36.023 },
@@ -33,7 +43,8 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
// ];
useEffect(() => {
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0)
return;
const socket = io(`http://${iotApiUrl}`);
const inputData = {
measurements,
@@ -46,7 +57,6 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
socket.on("connect", startStream);
socket.on("lastOutput", (response) => {
const responseData = response;
setDatas(responseData);
});
@@ -59,14 +69,15 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
}, [measurements, duration, iotApiUrl]);
const fetchSavedInputes = async () => {
if (id !== "") {
try {
const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`);
const response = await axios.get(
`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`
);
if (response.status === 200) {
setmeasurements(response.data.Data.measurements)
setDuration(response.data.Data.duration)
setName(response.data.widgetName)
setmeasurements(response.data.Data.measurements);
setDuration(response.data.Data.duration);
setName(response.data.widgetName);
} else {
console.log("Unexpected response:", response);
}
@@ -74,10 +85,7 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
console.error("There was an error!", error);
}
}
}
};
useEffect(() => {
fetchSavedInputes();
@@ -87,8 +95,7 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
if (selectedChartId?.id === id) {
fetchSavedInputes();
}
}
, [chartMeasurements, chartDuration, widgetName])
}, [chartMeasurements, chartDuration, widgetName]);
const rotationDegrees = {
x: (rotation[0] * 180) / Math.PI,
@@ -100,20 +107,22 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
transform: `rotateX(${rotationDegrees.x}deg) rotateY(${rotationDegrees.y}deg) rotateZ(${rotationDegrees.z}deg)`,
};
return (
<Html position={[position[0], position[1], position[2]]}
<Html
position={[position[0], position[1], position[2]]}
scale={[0.5, 0.5, 0.5]}
transform
zIndexRange={[1, 0]}
sprite
style={{
transform: transformStyle.transform,
transformStyle: 'preserve-3d',
transition: 'transform 0.1s ease-out'
transformStyle: "preserve-3d",
transition: "transform 0.1s ease-out",
}}
className={`${selectedChartId?.id === id ? "activeChart" : ""}`}
>
<div className="stateWorking-wrapper card"
<div
className={`stateWorking-wrapper card ${
selectedChartId?.id === id ? "activeChart" : ""
}`}
onClick={() => setSelectedChartId({ id: id, type: type })}
onContextMenu={onContextMenu}
>
@@ -121,12 +130,10 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
<div className="header">
<span>State</span>
<span>
{datas?.input1 ? datas.input1 : 'input1'} <span>.</span>
{datas?.input1 ? datas.input1 : "input1"} <span>.</span>
</span>
</div>
<div className="img">
{/* <img src={image} alt="" /> */}
</div>
<div className="img">{/* <img src={image} alt="" /> */}</div>
</div>
{/* Data */}
<div className="data-wrapper">
@@ -137,28 +144,52 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
</div>
))} */}
<div className="data-table">
<div className="data">{measurements?.input2?.fields ? measurements.input2.fields : 'input2'}</div>
<div className="key">{datas?.input2 ? datas.input2 : 'data'}</div>
<div className="data">
{measurements?.input2?.fields
? measurements.input2.fields
: "input2"}
</div>
<div className="key">{datas?.input2 ? datas.input2 : "data"}</div>
</div>
<div className="data-table">
<div className="data">{measurements?.input3?.fields ? measurements.input3.fields : 'input3'}</div>
<div className="key">{datas?.input3 ? datas.input3 : 'data'}</div>
<div className="data">
{measurements?.input3?.fields
? measurements.input3.fields
: "input3"}
</div>
<div className="key">{datas?.input3 ? datas.input3 : "data"}</div>
</div>
<div className="data-table">
<div className="data">{measurements?.input4?.fields ? measurements.input4.fields : 'input4'}</div>
<div className="key">{datas?.input4 ? datas.input4 : 'data'}</div>
<div className="data">
{measurements?.input4?.fields
? measurements.input4.fields
: "input4"}
</div>
<div className="key">{datas?.input4 ? datas.input4 : "data"}</div>
</div>
<div className="data-table">
<div className="data">{measurements?.input5?.fields ? measurements.input5.fields : 'input5'}</div>
<div className="key">{datas?.input5 ? datas.input5 : 'data'}</div>
<div className="data">
{measurements?.input5?.fields
? measurements.input5.fields
: "input5"}
</div>
<div className="key">{datas?.input5 ? datas.input5 : "data"}</div>
</div>
<div className="data-table">
<div className="data">{measurements?.input6?.fields ? measurements.input6.fields : 'input6'}</div>
<div className="key">{datas?.input6 ? datas.input6 : 'data'}</div>
<div className="data">
{measurements?.input6?.fields
? measurements.input6.fields
: "input6"}
</div>
<div className="key">{datas?.input6 ? datas.input6 : "data"}</div>
</div>
<div className="data-table">
<div className="data">{measurements?.input7?.fields ? measurements.input7.fields : 'input7'}</div>
<div className="key">{datas?.input7 ? datas.input7 : 'data'}</div>
<div className="data">
{measurements?.input7?.fields
? measurements.input7.fields
: "input7"}
</div>
<div className="key">{datas?.input7 ? datas.input7 : "data"}</div>
</div>
</div>
</div>
@@ -167,5 +198,3 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
};
export default StateWorking;

View File

@@ -49,20 +49,32 @@ interface ThroughputProps {
onContextMenu?: (event: React.MouseEvent) => void;
}
const Throughput: React.FC<ThroughputProps> = ({ id, type, position, rotation, onContextMenu }) => {
const Throughput: React.FC<ThroughputProps> = ({
id,
type,
position,
rotation,
onContextMenu,
}) => {
const { selectedChartId, setSelectedChartId } = useWidgetStore();
const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore();
const {
measurements: chartMeasurements,
duration: chartDuration,
name: widgetName,
} = useChartStore();
const [measurements, setmeasurements] = useState<any>({});
const [duration, setDuration] = useState("1h")
const [name, setName] = useState("Widget")
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
const [duration, setDuration] = useState("1h");
const [name, setName] = useState("Widget");
const [chartData, setChartData] = useState<{
labels: string[];
datasets: any[];
}>({
labels: [],
datasets: [],
});
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0]
const organization = email?.split("@")[1]?.split(".")[0];
// Sample data for the line graph
const graphData: ChartData<"line"> = {
@@ -112,7 +124,8 @@ const Throughput: React.FC<ThroughputProps> = ({ id, type, position, rotation, o
};
useEffect(() => {
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0)
return;
const socket = io(`http://${iotApiUrl}`);
@@ -122,7 +135,6 @@ const Throughput: React.FC<ThroughputProps> = ({ id, type, position, rotation, o
interval: 1000,
};
const startStream = () => {
socket.emit("lineInput", inputData);
};
@@ -157,14 +169,15 @@ const Throughput: React.FC<ThroughputProps> = ({ id, type, position, rotation, o
}, [measurements, duration, iotApiUrl]);
const fetchSavedInputes = async () => {
if (id !== "") {
try {
const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`);
const response = await axios.get(
`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`
);
if (response.status === 200) {
setmeasurements(response.data.Data.measurements)
setDuration(response.data.Data.duration)
setName(response.data.widgetName)
setmeasurements(response.data.Data.measurements);
setDuration(response.data.Data.duration);
setName(response.data.widgetName);
} else {
console.log("Unexpected response:", response);
}
@@ -172,7 +185,7 @@ const Throughput: React.FC<ThroughputProps> = ({ id, type, position, rotation, o
console.error("There was an error!", error);
}
}
}
};
useEffect(() => {
fetchSavedInputes();
@@ -182,8 +195,7 @@ const Throughput: React.FC<ThroughputProps> = ({ id, type, position, rotation, o
if (selectedChartId?.id === id) {
fetchSavedInputes();
}
}
, [chartMeasurements, chartDuration, widgetName])
}, [chartMeasurements, chartDuration, widgetName]);
const rotationDegrees = {
x: (rotation[0] * 180) / Math.PI,
y: (rotation[1] * 180) / Math.PI,
@@ -195,20 +207,22 @@ const Throughput: React.FC<ThroughputProps> = ({ id, type, position, rotation, o
};
return (
<Html position={[position[0], position[1], position[2]]}
<Html
position={[position[0], position[1], position[2]]}
scale={[0.5, 0.5, 0.5]}
transform
zIndexRange={[1, 0]}
sprite
style={{
transform: transformStyle.transform,
transformStyle: 'preserve-3d',
transition: 'transform 0.1s ease-out'
transformStyle: "preserve-3d",
transition: "transform 0.1s ease-out",
}}
className={`${selectedChartId?.id === id ? "activeChart" : ""}`}
>
<div className="throughput-wrapper"
<div
className={`throughput-wrapper card ${
selectedChartId?.id === id ? "activeChart" : ""
}`}
onClick={() => setSelectedChartId({ id: id, type: type })}
onContextMenu={onContextMenu}
>
@@ -235,7 +249,10 @@ const Throughput: React.FC<ThroughputProps> = ({ id, type, position, rotation, o
</div>
<div className="line-graph">
{/* Line graph using react-chartjs-2 */}
<LineGraphComponent data={Object.keys(measurements).length > 0 ? chartData : graphData} options={graphOptions} />
<LineGraphComponent
data={Object.keys(measurements).length > 0 ? chartData : graphData}
options={graphOptions}
/>
</div>
<div className="footer">
You made an extra <span className="value">$1256.13</span> this month

View File

@@ -148,7 +148,7 @@ const Assets: React.FC = () => {
<div className="assets-container">
{categoryAssets &&
categoryAssets?.map((asset: any, index: number) => (
<div key={index} className="assets">
<div key={index} className="assets" id={asset.filename}>
<img
src={asset?.thumbnail}
alt={asset.filename}
@@ -172,6 +172,7 @@ const Assets: React.FC = () => {
<div className="assets-wrapper">
<div
className="back-button"
id="asset-backButtom"
onClick={() => {
setSelectedCategory(null);
setCategoryAssets([]);
@@ -183,7 +184,7 @@ const Assets: React.FC = () => {
<div className="assets-container">
{categoryAssets &&
categoryAssets?.map((asset: any, index: number) => (
<div key={index} className="assets">
<div key={index} className="assets" id={asset.filename}>
<img
src={asset?.thumbnail}
alt={asset.filename}
@@ -223,6 +224,7 @@ const Assets: React.FC = () => {
<div
key={index}
className="category"
id={category}
onClick={() => fetchCategoryAssets(category)}
>
<img

View File

@@ -4,6 +4,7 @@ import useTemplateStore from "../../../../store/useTemplateStore";
import { useSelectedZoneStore } from "../../../../store/useZoneStore";
import { getTemplateData } from "../../../../services/realTimeVisulization/zoneData/getTemplate";
import { useSocketStore } from "../../../../store/store";
import RenameInput from "../../../ui/inputs/RenameInput";
const Templates = () => {
const { templates, removeTemplate, setTemplates } = useTemplateStore();
@@ -34,7 +35,10 @@ const Templates = () => {
templateID: id,
};
if (visualizationSocket) {
visualizationSocket.emit("v2:viz-template:deleteTemplate", deleteTemplate);
visualizationSocket.emit(
"v2:viz-template:deleteTemplate",
deleteTemplate
);
}
removeTemplate(id);
} catch (error) {
@@ -65,11 +69,15 @@ const Templates = () => {
widgets: template.widgets,
});
useDroppedObjectsStore.getState().setZone(selectedZone.zoneName, selectedZone.zoneId);
useDroppedObjectsStore
.getState()
.setZone(selectedZone.zoneName, selectedZone.zoneId);
if (Array.isArray(template.floatingWidget)) {
template.floatingWidget.forEach((val: any) => {
useDroppedObjectsStore.getState().addObject(selectedZone.zoneName, val);
useDroppedObjectsStore
.getState()
.addObject(selectedZone.zoneName, val);
});
}
} catch (error) {
@@ -79,7 +87,7 @@ const Templates = () => {
return (
<div className="template-list">
{templates.map((template) => (
{templates.map((template, index) => (
<div key={template.id} className="template-item">
{template?.snapshot && (
<div className="template-image-container">
@@ -96,7 +104,8 @@ const Templates = () => {
onClick={() => handleLoadTemplate(template)}
className="template-name"
>
{template.name}
{/* {`Template ${index + 1}`} */}
<RenameInput value={`Template ${index + 1}`} />
</div>
<button
onClick={() => handleDeleteTemplate(template.id)}

View File

@@ -1,12 +1,10 @@
import React, { useEffect } from "react";
import React from "react";
import {
CleanPannel,
EyeIcon,
LockIcon,
} from "../../icons/RealTimeVisulationIcons";
import { panelData } from "../../../services/realTimeVisulization/zoneData/panel";
import { AddIcon } from "../../icons/ExportCommonIcons";
import { deletePanelApi } from "../../../services/realTimeVisulization/zoneData/deletePanel";
import { useSocketStore } from "../../../store/store";
import { clearPanel } from "../../../services/realTimeVisulization/zoneData/clearPanel";
import { lockPanel } from "../../../services/realTimeVisulization/zoneData/lockPanel";
@@ -14,6 +12,11 @@ import { lockPanel } from "../../../services/realTimeVisulization/zoneData/lockP
// Define the type for `Side`
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 {
[zoneId: string]: Side[];
}
// Define the type for the props passed to the Buttons component
interface ButtonsProps {
selectedZone: {
@@ -37,7 +40,6 @@ interface ButtonsProps {
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
zoneId: string;
zoneViewPortTarget: number[];
@@ -51,8 +53,8 @@ interface ButtonsProps {
}[];
}>
>;
hiddenPanels: Side[]; // Add this prop for hidden panels
setHiddenPanels: React.Dispatch<React.SetStateAction<Side[]>>; // Add this prop for updating hidden panels
hiddenPanels: HiddenPanels; // Updated prop type
setHiddenPanels: React.Dispatch<React.SetStateAction<HiddenPanels>>; // Updated prop type
}
const AddButtons: React.FC<ButtonsProps> = ({
@@ -63,11 +65,33 @@ const AddButtons: React.FC<ButtonsProps> = ({
}) => {
const { visualizationSocket } = useSocketStore();
// Local state to track hidden panels
// Function to toggle visibility of a panel
const toggleVisibility = (side: Side) => {
const isHidden = hiddenPanels[selectedZone.zoneId]?.includes(side) ?? false;
if (isHidden) {
// If the panel is already hidden, remove it from the hiddenPanels array for this zone
setHiddenPanels((prevHiddenPanels) => ({
...prevHiddenPanels,
[selectedZone.zoneId]: prevHiddenPanels[selectedZone.zoneId].filter(
(panel) => panel !== side
),
}));
} else {
// If the panel is visible, add it to the hiddenPanels array for this zone
setHiddenPanels((prevHiddenPanels) => ({
...prevHiddenPanels,
[selectedZone.zoneId]: [
...(prevHiddenPanels[selectedZone.zoneId] || []),
side,
],
}));
}
};
// Function to toggle lock/unlock a panel
const toggleLockPanel = async (side: Side) => {
console.log('side: ', side);
// console.log('side: ', side);
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0]; // Fallback value
//add api
@@ -99,23 +123,10 @@ const AddButtons: React.FC<ButtonsProps> = ({
};
// Function to toggle visibility of a panel
const toggleVisibility = (side: Side) => {
const isHidden = hiddenPanels.includes(side);
if (isHidden) {
// If the panel is already hidden, remove it from the hiddenPanels array
setHiddenPanels(hiddenPanels.filter((panel) => panel !== side));
} else {
// If the panel is visible, add it to the hiddenPanels array
setHiddenPanels([...hiddenPanels, side]);
}
};
// Function to clean all widgets from a panel
const cleanPanel = async (side: Side) => {
//add api
console.log('side: ', side);
// console.log('side: ', side);
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0]; // Fallback value
@@ -135,7 +146,7 @@ const AddButtons: React.FC<ButtonsProps> = ({
widgets: cleanedWidgets,
};
// Update the selectedZone state
console.log('updatedZone: ', updatedZone);
// console.log('updatedZone: ', updatedZone);
setSelectedZone(updatedZone);
// let response = await clearPanel(selectedZone.zoneId, organization, side)
@@ -196,8 +207,6 @@ const AddButtons: React.FC<ButtonsProps> = ({
//
// }
} else {
setHiddenPanels(hiddenPanels.filter((panel) => panel !== side));
// Panel does not exist: Create panel
try {
// Get email and organization safely with a default fallback
@@ -234,7 +243,6 @@ const AddButtons: React.FC<ButtonsProps> = ({
} catch (error) { }
}
};
return (
<>
<div>
@@ -261,16 +269,21 @@ const AddButtons: React.FC<ButtonsProps> = ({
<div className="extra-Bs">
{/* Hide Panel */}
<div
className={`icon ${hiddenPanels.includes(side) ? "active" : ""
}`}
className={`icon ${
hiddenPanels[selectedZone.zoneId]?.includes(side)
? "active"
: ""
}`}
title={
hiddenPanels.includes(side) ? "Show Panel" : "Hide Panel"
hiddenPanels[selectedZone.zoneId]?.includes(side)
? "Show Panel"
: "Hide Panel"
}
onClick={() => toggleVisibility(side)}
>
<EyeIcon
fill={
hiddenPanels.includes(side)
hiddenPanels[selectedZone.zoneId]?.includes(side)
? "var(--primary-color)"
: "var(--text-color)"
}

View File

@@ -88,12 +88,15 @@ export const DraggableWidget = ({
const chartWidget = useRef<HTMLDivElement>(null);
const isPanelHidden = hiddenPanels.includes(widget.panel);
// OuterClick({
// contextClassName: ["chart-container", "floating", "sidebar-right-wrapper"],
// setMenuVisible: () => setSelectedChartId(null),
// });
OuterClick({
contextClassName: [
"chart-container",
"floating",
"sidebar-right-wrapper",
"card",
],
setMenuVisible: () => setSelectedChartId(null),
});
const deleteSelectedChart = async () => {
try {
@@ -397,4 +400,4 @@ export const DraggableWidget = ({
);
};
// by using canvasDimensions.height canvasDimensions.width dynamically div value insted of static 6 and 4 calculate according to canvasDimensions.width canvasDimensions.height

View File

@@ -39,7 +39,7 @@ interface PanelProps {
widgets: Widget[];
}>
>;
hiddenPanels: string[];
hiddenPanels: any;
setZonesData: React.Dispatch<React.SetStateAction<any>>;
}
@@ -139,7 +139,12 @@ const Panel: React.FC<PanelProps> = ({
const handleDrop = (e: React.DragEvent, panel: Side) => {
e.preventDefault();
const { draggedAsset } = useWidgetStore.getState();
if (!draggedAsset || isPanelLocked(panel)) return;
if (
!draggedAsset ||
isPanelLocked(panel) ||
hiddenPanels[selectedZone.zoneId]?.includes(panel)
)
return;
const currentWidgetsCount = getCurrentWidgetCount(panel);
const maxCapacity = calculatePanelCapacity(panel);
@@ -261,7 +266,7 @@ const Panel: React.FC<PanelProps> = ({
{`
:root {
--topWidth: ${topWidth};
--bottomWidth: ${bottomWidth};
--bottomWidth: ${bottomWidth} ;
--leftHeight: ${leftHeight};
--rightHeight: ${rightHeight};
@@ -278,7 +283,7 @@ const Panel: React.FC<PanelProps> = ({
key={side}
id="panel-wrapper"
className={`panel ${side}-panel absolute ${
hiddenPanels.includes(side) ? "hidePanel" : ""
hiddenPanels[selectedZone.zoneId]?.includes(side) ? "hidePanel" : ""
}`}
style={getPanelStyle(side)}
onDrop={(e) => handleDrop(e, side)}
@@ -294,9 +299,11 @@ const Panel: React.FC<PanelProps> = ({
<div
className={`panel-content ${isPlaying && "fullScreen"}`}
style={{
pointerEvents: selectedZone.lockedPanels.includes(side)
? "none"
: "auto",
pointerEvents:
selectedZone.lockedPanels.includes(side) ||
hiddenPanels[selectedZone.zoneId]?.includes(side)
? "none"
: "auto",
opacity: selectedZone.lockedPanels.includes(side) ? "0.8" : "1",
}}
>

View File

@@ -53,8 +53,13 @@ type Widget = {
data: any;
};
// Define the type for HiddenPanels, where keys are zone IDs and values are arrays of hidden sides
interface HiddenPanels {
[zoneId: string]: Side[];
}
const RealTimeVisulization: React.FC = () => {
const [hiddenPanels, setHiddenPanels] = React.useState<Side[]>([]);
const [hiddenPanels, setHiddenPanels] = React.useState<HiddenPanels>({});
const containerRef = useRef<HTMLDivElement>(null);
const { isPlaying } = usePlayButtonStore();
const { activeModule } = useModuleStore();
@@ -74,7 +79,6 @@ const RealTimeVisulization: React.FC = () => {
const { widgetSubOption, setWidgetSubOption } = useWidgetSubOption();
const { visualizationSocket } = useSocketStore();
useEffect(() => {
async function GetZoneData() {
const email = localStorage.getItem("email") || "";
@@ -101,7 +105,7 @@ const RealTimeVisulization: React.FC = () => {
{}
);
setZonesData(formattedData);
} catch (error) { }
} catch (error) {}
}
GetZoneData();
@@ -229,8 +233,6 @@ const RealTimeVisulization: React.FC = () => {
};
}, [setRightClickSelected]);
return (
<>
<div
@@ -263,7 +265,6 @@ const RealTimeVisulization: React.FC = () => {
}}
onDrop={(event) => handleDrop(event)}
onDragOver={(event) => event.preventDefault()}
>
<Scene />
</div>