added iot data and input card for 3D widget
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { Html } from "@react-three/drei";
|
import { Html } from "@react-three/drei";
|
||||||
import React from "react";
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
import { Bar } from "react-chartjs-2";
|
import { Bar } from "react-chartjs-2";
|
||||||
import {
|
import {
|
||||||
Chart as ChartJS,
|
Chart as ChartJS,
|
||||||
@@ -11,6 +11,11 @@ import {
|
|||||||
Legend,
|
Legend,
|
||||||
TooltipItem, // Import TooltipItem for typing
|
TooltipItem, // Import TooltipItem for typing
|
||||||
} from "chart.js";
|
} from "chart.js";
|
||||||
|
import { ThroughputIcon } from "../../../icons/3dChartIcons";
|
||||||
|
import { useWidgetStore } from "../../../../store/useWidgetStore";
|
||||||
|
import useChartStore from "../../../../store/useChartStore";
|
||||||
|
import axios from "axios";
|
||||||
|
import io from "socket.io-client";
|
||||||
|
|
||||||
// Register ChartJS components
|
// Register ChartJS components
|
||||||
ChartJS.register(
|
ChartJS.register(
|
||||||
@@ -22,12 +27,28 @@ ChartJS.register(
|
|||||||
Legend
|
Legend
|
||||||
);
|
);
|
||||||
interface ProductionCapacityProps {
|
interface ProductionCapacityProps {
|
||||||
|
id: string;
|
||||||
|
type: string;
|
||||||
position: [number, number, number];
|
position: [number, number, number];
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProductionCapacity : React.FC<ProductionCapacityProps> = ({ position }) => {
|
const ProductionCapacity : React.FC<ProductionCapacityProps> = ({ id, type, position }) => {
|
||||||
|
|
||||||
|
const { selectedChartId,setSelectedChartId } = useWidgetStore();
|
||||||
|
|
||||||
|
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[] }>({
|
||||||
|
labels: [],
|
||||||
|
datasets: [],
|
||||||
|
});
|
||||||
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
|
const email = localStorage.getItem("email") || "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0]
|
||||||
// Chart data for a week
|
// Chart data for a week
|
||||||
const chartData = {
|
const defaultChartData = {
|
||||||
labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], // Days of the week
|
labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], // Days of the week
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
@@ -78,12 +99,94 @@ const ProductionCapacity : React.FC<ProductionCapacityProps> = ({ position }) =>
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
|
||||||
|
|
||||||
|
const socket = io(`http://${iotApiUrl}`);
|
||||||
|
|
||||||
|
const inputData = {
|
||||||
|
measurements,
|
||||||
|
duration,
|
||||||
|
interval: 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const startStream = () => {
|
||||||
|
socket.emit("lineInput", inputData);
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.on("connect", startStream);
|
||||||
|
|
||||||
|
socket.on("lineOutput", (response) => {
|
||||||
|
const responseData = response.data;
|
||||||
|
|
||||||
|
// Extract timestamps and values
|
||||||
|
const labels = responseData.time;
|
||||||
|
const datasets = Object.keys(measurements).map((key) => {
|
||||||
|
const measurement = measurements[key];
|
||||||
|
const datasetKey = `${measurement.name}.${measurement.fields}`;
|
||||||
|
return {
|
||||||
|
label: datasetKey,
|
||||||
|
data: responseData[datasetKey]?.values ?? [],
|
||||||
|
backgroundColor: "#6f42c1", // Theme color
|
||||||
|
borderColor: "#6f42c1",
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 8, // Rounded corners for the bars
|
||||||
|
borderSkipped: false, // Ensure all corners are rounded
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
setChartData({ labels, datasets });
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
socket.off("lineOutput");
|
||||||
|
socket.emit("stop_stream"); // Stop streaming when component unmounts
|
||||||
|
socket.disconnect();
|
||||||
|
};
|
||||||
|
}, [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}`);
|
||||||
|
if (response.status === 200) {
|
||||||
|
setmeasurements(response.data.Data.measurements)
|
||||||
|
setDuration(response.data.Data.duration)
|
||||||
|
setName(response.data.widgetName)
|
||||||
|
} else {
|
||||||
|
console.log("Unexpected response:", response);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("There was an error!", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchSavedInputes();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedChartId?.id === id) {
|
||||||
|
fetchSavedInputes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
,[chartMeasurements, chartDuration, widgetName])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Html position={[position[0], position[1], position[2]]}
|
<Html position={[position[0], position[1], position[2]]}
|
||||||
scale={[0.5, 0.5, 0.5]}
|
scale={[0.5, 0.5, 0.5]}
|
||||||
transform
|
transform
|
||||||
sprite>
|
sprite>
|
||||||
<div className="productionCapacity-wrapper card">
|
<div className="productionCapacity-wrapper card"
|
||||||
|
onClick={
|
||||||
|
() => setSelectedChartId({
|
||||||
|
id: id,
|
||||||
|
type: type
|
||||||
|
})
|
||||||
|
}>
|
||||||
<div className="headeproductionCapacityr-wrapper">
|
<div className="headeproductionCapacityr-wrapper">
|
||||||
<div className="header">Production Capacity</div>
|
<div className="header">Production Capacity</div>
|
||||||
<div className="production-capacity">
|
<div className="production-capacity">
|
||||||
@@ -104,7 +207,7 @@ const ProductionCapacity : React.FC<ProductionCapacityProps> = ({ position }) =>
|
|||||||
</div>{" "}
|
</div>{" "}
|
||||||
<div className="bar-chart charts">
|
<div className="bar-chart charts">
|
||||||
{/* Bar Chart */}
|
{/* Bar Chart */}
|
||||||
<Bar data={chartData} options={chartOptions} />
|
<Bar data={Object.keys(measurements).length > 0 ? chartData : defaultChartData } options={chartOptions} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Html>
|
</Html>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Html } from "@react-three/drei";
|
import { Html } from "@react-three/drei";
|
||||||
import React from "react";
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
import { Line } from "react-chartjs-2";
|
import { Line } from "react-chartjs-2";
|
||||||
import {
|
import {
|
||||||
Chart as ChartJS,
|
Chart as ChartJS,
|
||||||
@@ -12,6 +12,10 @@ import {
|
|||||||
ChartOptions,
|
ChartOptions,
|
||||||
} from "chart.js";
|
} from "chart.js";
|
||||||
import { WavyIcon } from "../../../icons/3dChartIcons";
|
import { WavyIcon } from "../../../icons/3dChartIcons";
|
||||||
|
import { useWidgetStore } from "../../../../store/useWidgetStore";
|
||||||
|
import useChartStore from "../../../../store/useChartStore";
|
||||||
|
import axios from "axios";
|
||||||
|
import io from "socket.io-client";
|
||||||
|
|
||||||
// Register Chart.js components
|
// Register Chart.js components
|
||||||
ChartJS.register(
|
ChartJS.register(
|
||||||
@@ -36,9 +40,24 @@ const SmoothLineGraphComponent: React.FC<SmoothLineGraphProps> = ({
|
|||||||
return <Line data={data} options={options} />;
|
return <Line data={data} options={options} />;
|
||||||
};
|
};
|
||||||
interface ReturnOfInvestmentProps {
|
interface ReturnOfInvestmentProps {
|
||||||
|
id: string;
|
||||||
|
type: string;
|
||||||
position: [number, number, number];
|
position: [number, number, number];
|
||||||
}
|
}
|
||||||
const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ position }) => {
|
const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, position }) => {
|
||||||
|
|
||||||
|
const { selectedChartId,setSelectedChartId } = useWidgetStore();
|
||||||
|
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[] }>({
|
||||||
|
labels: [],
|
||||||
|
datasets: [],
|
||||||
|
});
|
||||||
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
|
const email = localStorage.getItem("email") || "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0]
|
||||||
// Improved sample data for the smooth curve graph (single day)
|
// Improved sample data for the smooth curve graph (single day)
|
||||||
const graphData: ChartData<"line"> = {
|
const graphData: ChartData<"line"> = {
|
||||||
labels: [
|
labels: [
|
||||||
@@ -107,16 +126,99 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ position }) =>
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
|
||||||
|
|
||||||
|
const socket = io(`http://${iotApiUrl}`);
|
||||||
|
|
||||||
|
const inputData = {
|
||||||
|
measurements,
|
||||||
|
duration,
|
||||||
|
interval: 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const startStream = () => {
|
||||||
|
socket.emit("lineInput", inputData);
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.on("connect", startStream);
|
||||||
|
|
||||||
|
socket.on("lineOutput", (response) => {
|
||||||
|
const responseData = response.data;
|
||||||
|
|
||||||
|
// Extract timestamps and values
|
||||||
|
const labels = responseData.time;
|
||||||
|
const datasets = Object.keys(measurements).map((key, index) => {
|
||||||
|
const measurement = measurements[key];
|
||||||
|
const datasetKey = `${measurement.name}.${measurement.fields}`;
|
||||||
|
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)",
|
||||||
|
fill: true,
|
||||||
|
tension: 0.4, // Smooth curve effect
|
||||||
|
pointRadius: 0, // Hide dots
|
||||||
|
pointHoverRadius: 0, // Hide hover dots
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
setChartData({ labels, datasets });
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
socket.off("lineOutput");
|
||||||
|
socket.emit("stop_stream"); // Stop streaming when component unmounts
|
||||||
|
socket.disconnect();
|
||||||
|
};
|
||||||
|
}, [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}`);
|
||||||
|
if (response.status === 200) {
|
||||||
|
setmeasurements(response.data.Data.measurements)
|
||||||
|
setDuration(response.data.Data.duration)
|
||||||
|
setName(response.data.widgetName)
|
||||||
|
} else {
|
||||||
|
console.log("Unexpected response:", response);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("There was an error!", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchSavedInputes();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedChartId?.id === id) {
|
||||||
|
fetchSavedInputes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
,[chartMeasurements, chartDuration, widgetName])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Html position={[position[0], position[1], position[2]]}
|
<Html position={[position[0], position[1], position[2]]}
|
||||||
scale={[0.5, 0.5, 0.5]}
|
scale={[0.5, 0.5, 0.5]}
|
||||||
transform
|
transform
|
||||||
sprite>
|
sprite>
|
||||||
<div className="returnOfInvestment card">
|
<div className="returnOfInvestment card"
|
||||||
|
onClick={
|
||||||
|
() => setSelectedChartId({
|
||||||
|
id: id,
|
||||||
|
type: type
|
||||||
|
})
|
||||||
|
}>
|
||||||
<div className="header">Return of Investment</div>
|
<div className="header">Return of Investment</div>
|
||||||
<div className="lineGraph charts">
|
<div className="lineGraph charts">
|
||||||
{/* Smooth curve graph with two datasets */}
|
{/* Smooth curve graph with two datasets */}
|
||||||
<SmoothLineGraphComponent data={graphData} options={graphOptions} />
|
<SmoothLineGraphComponent data={Object.keys(measurements).length > 0 ? chartData : graphData} options={graphOptions} />
|
||||||
</div>
|
</div>
|
||||||
<div className="returns-wrapper">
|
<div className="returns-wrapper">
|
||||||
<div className="icon">
|
<div className="icon">
|
||||||
|
|||||||
@@ -1,28 +1,111 @@
|
|||||||
import { Html } from "@react-three/drei";
|
import { Html } from "@react-three/drei";
|
||||||
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
|
import { useWidgetStore } from "../../../../store/useWidgetStore";
|
||||||
|
import useChartStore from "../../../../store/useChartStore";
|
||||||
|
import axios from "axios";
|
||||||
|
import io from "socket.io-client";
|
||||||
|
|
||||||
// import image from "../../../../assets/image/temp/image.png";
|
// import image from "../../../../assets/image/temp/image.png";
|
||||||
interface StateWorkingProps {
|
interface StateWorkingProps {
|
||||||
|
id:string;
|
||||||
|
type: string;
|
||||||
position: [number, number, number];
|
position: [number, number, number];
|
||||||
}
|
}
|
||||||
const StateWorking: React.FC<StateWorkingProps> = ({ position }) => {
|
const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position }) => {
|
||||||
const datas = [
|
const { selectedChartId, setSelectedChartId } = useWidgetStore();
|
||||||
{ key: "Oil Tank:", value: "24/341" },
|
const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore();
|
||||||
{ key: "Oil Refin:", value: 36.023 },
|
const [measurements, setmeasurements] = useState<any>({});
|
||||||
{ key: "Transmission:", value: 36.023 },
|
const [duration, setDuration] = useState("1h")
|
||||||
{ key: "Fuel:", value: 36732 },
|
const [name, setName] = useState("Widget")
|
||||||
{ key: "Power:", value: 1300 },
|
const [datas, setDatas] = useState<any>({});
|
||||||
{ key: "Time:", value: 13 - 9 - 2023 },
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
];
|
const email = localStorage.getItem("email") || "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0]
|
||||||
|
// const datas = [
|
||||||
|
// { key: "Oil Tank:", value: "24/341" },
|
||||||
|
// { key: "Oil Refin:", value: 36.023 },
|
||||||
|
// { key: "Transmission:", value: 36.023 },
|
||||||
|
// { key: "Fuel:", value: 36732 },
|
||||||
|
// { key: "Power:", value: 1300 },
|
||||||
|
// { key: "Time:", value: 13 - 9 - 2023 },
|
||||||
|
// ];
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
|
||||||
|
const socket = io(`http://${iotApiUrl}`);
|
||||||
|
const inputData = {
|
||||||
|
measurements,
|
||||||
|
duration,
|
||||||
|
interval: 1000,
|
||||||
|
};
|
||||||
|
const startStream = () => {
|
||||||
|
socket.emit("lastInput", inputData);
|
||||||
|
};
|
||||||
|
socket.on("connect", startStream);
|
||||||
|
socket.on("lastOutput", (response) => {
|
||||||
|
const responseData = response;
|
||||||
|
console.log("responceeeeeeeeeee",response);
|
||||||
|
|
||||||
|
setDatas(responseData);
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
socket.off("lastOutput");
|
||||||
|
socket.emit("stop_stream"); // Stop streaming when component unmounts
|
||||||
|
socket.disconnect();
|
||||||
|
};
|
||||||
|
}, [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}`);
|
||||||
|
if (response.status === 200) {
|
||||||
|
setmeasurements(response.data.Data.measurements)
|
||||||
|
setDuration(response.data.Data.duration)
|
||||||
|
setName(response.data.widgetName)
|
||||||
|
} else {
|
||||||
|
console.log("Unexpected response:", response);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("There was an error!", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("dataaaaa",datas);
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchSavedInputes();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedChartId?.id === id) {
|
||||||
|
fetchSavedInputes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
,[chartMeasurements, chartDuration, widgetName])
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Html position={[position[0], position[1], position[2]]}
|
<Html position={[position[0], position[1], position[2]]}
|
||||||
scale={[0.5, 0.5, 0.5]}
|
scale={[0.5, 0.5, 0.5]}
|
||||||
transform
|
transform
|
||||||
sprite>
|
sprite>
|
||||||
<div className="stateWorking-wrapper card">
|
<div className="stateWorking-wrapper card"
|
||||||
|
onClick={
|
||||||
|
() => setSelectedChartId({
|
||||||
|
id: id,
|
||||||
|
type: type
|
||||||
|
})
|
||||||
|
}>
|
||||||
<div className="header-wrapper">
|
<div className="header-wrapper">
|
||||||
<div className="header">
|
<div className="header">
|
||||||
<span>State</span>
|
<span>State</span>
|
||||||
<span>
|
<span>
|
||||||
Working <span>.</span>
|
{datas?.input1 ? datas.input1 : 'input1'} <span>.</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="img">
|
<div className="img">
|
||||||
@@ -31,12 +114,36 @@ const StateWorking: React.FC<StateWorkingProps> = ({ position }) => {
|
|||||||
</div>
|
</div>
|
||||||
{/* Data */}
|
{/* Data */}
|
||||||
<div className="data-wrapper">
|
<div className="data-wrapper">
|
||||||
{datas.map((data, index) => (
|
{/* {datas.map((data, index) => (
|
||||||
<div className="data-table" key={index}>
|
<div className="data-table" key={index}>
|
||||||
<div className="data">{data.key}</div>
|
<div className="data">{data.key}</div>
|
||||||
<div className="key">{data.value}</div>
|
<div className="key">{data.value}</div>
|
||||||
</div>
|
</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>
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Html>
|
</Html>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Html } from "@react-three/drei";
|
import { Html } from "@react-three/drei";
|
||||||
import React from "react";
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
import { Line } from "react-chartjs-2";
|
import { Line } from "react-chartjs-2";
|
||||||
import {
|
import {
|
||||||
Chart as ChartJS,
|
Chart as ChartJS,
|
||||||
@@ -14,6 +14,10 @@ import {
|
|||||||
ChartOptions,
|
ChartOptions,
|
||||||
} from "chart.js";
|
} from "chart.js";
|
||||||
import { ThroughputIcon } from "../../../icons/3dChartIcons";
|
import { ThroughputIcon } from "../../../icons/3dChartIcons";
|
||||||
|
import { useWidgetStore } from "../../../../store/useWidgetStore";
|
||||||
|
import useChartStore from "../../../../store/useChartStore";
|
||||||
|
import axios from "axios";
|
||||||
|
import io from "socket.io-client";
|
||||||
|
|
||||||
// Register Chart.js components
|
// Register Chart.js components
|
||||||
ChartJS.register(
|
ChartJS.register(
|
||||||
@@ -38,10 +42,25 @@ const LineGraphComponent: React.FC<LineGraphProps> = ({ data, options }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
interface ThroughputProps {
|
interface ThroughputProps {
|
||||||
|
id: string;
|
||||||
|
type: string;
|
||||||
position: [number, number, number];
|
position: [number, number, number];
|
||||||
}
|
}
|
||||||
|
|
||||||
const Throughput: React.FC<ThroughputProps> = ({ position }) => {
|
const Throughput: React.FC<ThroughputProps> = ({ id, type, position }) => {
|
||||||
|
|
||||||
|
const { selectedChartId,setSelectedChartId } = useWidgetStore();
|
||||||
|
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[] }>({
|
||||||
|
labels: [],
|
||||||
|
datasets: [],
|
||||||
|
});
|
||||||
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
|
const email = localStorage.getItem("email") || "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0]
|
||||||
|
|
||||||
// Sample data for the line graph
|
// Sample data for the line graph
|
||||||
const graphData: ChartData<"line"> = {
|
const graphData: ChartData<"line"> = {
|
||||||
@@ -90,13 +109,93 @@ const Throughput: React.FC<ThroughputProps> = ({ position }) => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
|
||||||
|
|
||||||
|
const socket = io(`http://${iotApiUrl}`);
|
||||||
|
|
||||||
|
const inputData = {
|
||||||
|
measurements,
|
||||||
|
duration,
|
||||||
|
interval: 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const startStream = () => {
|
||||||
|
socket.emit("lineInput", inputData);
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.on("connect", startStream);
|
||||||
|
|
||||||
|
socket.on("lineOutput", (response) => {
|
||||||
|
const responseData = response.data;
|
||||||
|
|
||||||
|
// Extract timestamps and values
|
||||||
|
const labels = responseData.time;
|
||||||
|
const datasets = Object.keys(measurements).map((key) => {
|
||||||
|
const measurement = measurements[key];
|
||||||
|
const datasetKey = `${measurement.name}.${measurement.fields}`;
|
||||||
|
return {
|
||||||
|
label: datasetKey,
|
||||||
|
data: responseData[datasetKey]?.values ?? [],
|
||||||
|
borderColor: "rgba(75, 192, 192, 1)",
|
||||||
|
backgroundColor: "rgba(75, 192, 192, 0.2)",
|
||||||
|
fill: true,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
setChartData({ labels, datasets });
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
socket.off("lineOutput");
|
||||||
|
socket.emit("stop_stream"); // Stop streaming when component unmounts
|
||||||
|
socket.disconnect();
|
||||||
|
};
|
||||||
|
}, [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}`);
|
||||||
|
if (response.status === 200) {
|
||||||
|
setmeasurements(response.data.Data.measurements)
|
||||||
|
setDuration(response.data.Data.duration)
|
||||||
|
setName(response.data.widgetName)
|
||||||
|
} else {
|
||||||
|
console.log("Unexpected response:", response);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("There was an error!", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchSavedInputes();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedChartId?.id === id) {
|
||||||
|
fetchSavedInputes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
,[chartMeasurements, chartDuration, widgetName])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Html position={[position[0], position[1], position[2]]}
|
<Html position={[position[0], position[1], position[2]]}
|
||||||
scale={[0.5, 0.5, 0.5]}
|
scale={[0.5, 0.5, 0.5]}
|
||||||
transform
|
transform
|
||||||
sprite>
|
sprite>
|
||||||
<div className="throughput-wrapper">
|
<div className="throughput-wrapper"
|
||||||
<div className="header">Throughput</div>
|
onClick={
|
||||||
|
() => setSelectedChartId({
|
||||||
|
id: id,
|
||||||
|
type: type
|
||||||
|
})
|
||||||
|
}>
|
||||||
|
<div className="header">{name}</div>
|
||||||
<div className="display-value">
|
<div className="display-value">
|
||||||
<div className="left">
|
<div className="left">
|
||||||
<div className="icon">
|
<div className="icon">
|
||||||
@@ -119,7 +218,7 @@ const Throughput: React.FC<ThroughputProps> = ({ position }) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="line-graph">
|
<div className="line-graph">
|
||||||
{/* Line graph using react-chartjs-2 */}
|
{/* Line graph using react-chartjs-2 */}
|
||||||
<LineGraphComponent data={graphData} options={graphOptions} />
|
<LineGraphComponent data={Object.keys(measurements).length > 0 ? chartData : graphData} options={graphOptions} />
|
||||||
</div>
|
</div>
|
||||||
<div className="footer">
|
<div className="footer">
|
||||||
You made an extra <span className="value">$1256.13</span> this month
|
You made an extra <span className="value">$1256.13</span> this month
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import FlotingWidgetInput from './FlotingWidgetInput'
|
|||||||
import FleetEfficiencyInputComponent from './FleetEfficiencyInputComponent'
|
import FleetEfficiencyInputComponent from './FleetEfficiencyInputComponent'
|
||||||
import Progress1Input from './Progress1Input'
|
import Progress1Input from './Progress1Input'
|
||||||
import Progress2Input from './Progress2Input'
|
import Progress2Input from './Progress2Input'
|
||||||
|
import Widget2InputCard3D from './Widget2InputCard3D'
|
||||||
|
import Widget3InputCard3D from './Widget3InputCard3D'
|
||||||
|
import Widget4InputCard3D from './Widget4InputCard3D'
|
||||||
import WarehouseThroughputInputComponent from './WarehouseThroughputInputComponent'
|
import WarehouseThroughputInputComponent from './WarehouseThroughputInputComponent'
|
||||||
import { useWidgetStore } from '../../../../../store/useWidgetStore'
|
import { useWidgetStore } from '../../../../../store/useWidgetStore'
|
||||||
|
|
||||||
@@ -104,6 +107,42 @@ const InputSelecterComponent = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (selectedChartId && selectedChartId.type && selectedChartId.type === 'ui-Widget 1' ) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="sideBarHeader">3D Widget Input</div>
|
||||||
|
<Widget4InputCard3D />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (selectedChartId && selectedChartId.type && selectedChartId.type === 'ui-Widget 2' ) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="sideBarHeader">3D Widget Input</div>
|
||||||
|
<Widget2InputCard3D />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (selectedChartId && selectedChartId.type && selectedChartId.type === 'ui-Widget 3' ) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="sideBarHeader">3D Widget Input</div>
|
||||||
|
<Widget3InputCard3D />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (selectedChartId && selectedChartId.type && selectedChartId.type === 'ui-Widget 4' ) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="sideBarHeader">3D Widget Input</div>
|
||||||
|
<Widget4InputCard3D />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
return (
|
return (
|
||||||
<div>No chart selected</div>
|
<div>No chart selected</div>
|
||||||
|
|||||||
@@ -0,0 +1,165 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||||
|
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
|
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
||||||
|
import useChartStore from "../../../../../store/useChartStore";
|
||||||
|
import { useSelectedZoneStore } from "../../../../../store/useZoneStore";
|
||||||
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
|
import axios from "axios";
|
||||||
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
|
||||||
|
type Props = {};
|
||||||
|
|
||||||
|
const Widget2InputCard3D = (props: Props) => {
|
||||||
|
const { selectedChartId } = useWidgetStore();
|
||||||
|
const [widgetName, setWidgetName] = useState("untited");
|
||||||
|
const { setMeasurements, updateDuration, updateName } = useChartStore();
|
||||||
|
const [duration, setDuration] = useState('1h')
|
||||||
|
const [dropDowndata, setDropDownData] = useState({});
|
||||||
|
const [selections, setSelections] = useState<Record<string, { name: string; fields: string }>>({});
|
||||||
|
const { selectedZone } = useSelectedZoneStore();
|
||||||
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
|
const email = localStorage.getItem("email") || "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0]
|
||||||
|
console.log(selectedChartId);
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchZoneData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`http://${iotApiUrl}/getinput`);
|
||||||
|
if (response.status === 200) {
|
||||||
|
// console.log("dropdown data:", response.data);
|
||||||
|
setDropDownData(response.data);
|
||||||
|
} else {
|
||||||
|
console.log("Unexpected response:", response);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("There was an error!", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchZoneData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchSavedInputes = async () => {
|
||||||
|
if (selectedChartId.id !== "") {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${selectedChartId.id}/${organization}`);
|
||||||
|
if (response.status === 200) {
|
||||||
|
setSelections(response.data.Data.measurements)
|
||||||
|
setDuration(response.data.Data.duration)
|
||||||
|
setWidgetName(response.data.widgetName)
|
||||||
|
} else {
|
||||||
|
console.log("Unexpected response:", response);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("There was an error!", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchSavedInputes();
|
||||||
|
|
||||||
|
}, [selectedChartId.id]);
|
||||||
|
|
||||||
|
// Sync Zustand state when component mounts
|
||||||
|
useEffect(() => {
|
||||||
|
setMeasurements(selections);
|
||||||
|
updateDuration(duration);
|
||||||
|
updateName(widgetName);
|
||||||
|
}, [selections, duration, widgetName]);
|
||||||
|
|
||||||
|
|
||||||
|
const sendInputes = async (inputMeasurement: any, inputDuration: any, inputName: any) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/3dwidget/save`, {
|
||||||
|
organization: organization,
|
||||||
|
zoneId: selectedZone.zoneId,
|
||||||
|
widget: {
|
||||||
|
id: selectedChartId.id,
|
||||||
|
widgetName: inputName,
|
||||||
|
Data: {
|
||||||
|
measurements: inputMeasurement,
|
||||||
|
duration: inputDuration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} as any);
|
||||||
|
if (response.status === 200) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
console.log("Unexpected response:", response);
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("There was an error!", error);
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSelect = async (inputKey: string, selectedData: { name: string; fields: string } | null) => {
|
||||||
|
|
||||||
|
// async() => {
|
||||||
|
const newSelections = { ...selections };
|
||||||
|
if (selectedData === null) {
|
||||||
|
delete newSelections[inputKey];
|
||||||
|
} else {
|
||||||
|
newSelections[inputKey] = selectedData;
|
||||||
|
}
|
||||||
|
// setMeasurements(newSelections); // Update Zustand store
|
||||||
|
console.log(newSelections);
|
||||||
|
if (await sendInputes(newSelections, duration, widgetName)) {
|
||||||
|
setSelections(newSelections);
|
||||||
|
}
|
||||||
|
// sendInputes(newSelections, duration); // Send data to server
|
||||||
|
// return newSelections;
|
||||||
|
// };
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectDuration = async (option: string) => {
|
||||||
|
if (await sendInputes(selections, option, widgetName)) {
|
||||||
|
setDuration(option);
|
||||||
|
}
|
||||||
|
// setDuration(option);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNameChange = async (name:any) => {
|
||||||
|
console.log('name change requested',name);
|
||||||
|
|
||||||
|
if (await sendInputes(selections, duration, name)) {
|
||||||
|
setWidgetName(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="inputs-wrapper">
|
||||||
|
<div className="datas">
|
||||||
|
<div className="datas__label">Title</div>
|
||||||
|
<RenameInput value={widgetName} onRename={handleNameChange}/>
|
||||||
|
</div>
|
||||||
|
{[...Array(2)].map((_, index) => {
|
||||||
|
const inputKey = `input${index + 1}`;
|
||||||
|
return (
|
||||||
|
<div key={index} className="datas">
|
||||||
|
<div className="datas__label">Input {index + 1}</div>
|
||||||
|
<div className="datas__class">
|
||||||
|
<MultiLevelDropdown
|
||||||
|
data={dropDowndata}
|
||||||
|
onSelect={(selectedData) => handleSelect(inputKey, selectedData)}
|
||||||
|
onUnselect={() => handleSelect(inputKey, null)}
|
||||||
|
selectedValue={selections[inputKey]} // Load from Zustand
|
||||||
|
/>
|
||||||
|
<div className="icon">
|
||||||
|
<AddIcon />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Widget2InputCard3D;
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||||
|
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
|
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
||||||
|
import useChartStore from "../../../../../store/useChartStore";
|
||||||
|
import { useSelectedZoneStore } from "../../../../../store/useZoneStore";
|
||||||
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
|
import axios from "axios";
|
||||||
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
|
||||||
|
const Widget3InputCard3D = () => {
|
||||||
|
const { selectedChartId } = useWidgetStore();
|
||||||
|
const [widgetName, setWidgetName] = useState("untited");
|
||||||
|
const { setMeasurements, updateDuration, updateName } = useChartStore();
|
||||||
|
const [duration, setDuration] = useState('1h')
|
||||||
|
const [dropDowndata, setDropDownData] = useState({});
|
||||||
|
const [selections, setSelections] = useState<Record<string, { name: string; fields: string }>>({});
|
||||||
|
const { selectedZone } = useSelectedZoneStore();
|
||||||
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
|
const email = localStorage.getItem("email") || "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0]
|
||||||
|
console.log(selectedChartId);
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchZoneData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`http://${iotApiUrl}/getinput`);
|
||||||
|
if (response.status === 200) {
|
||||||
|
// console.log("dropdown data:", response.data);
|
||||||
|
setDropDownData(response.data);
|
||||||
|
} else {
|
||||||
|
console.log("Unexpected response:", response);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("There was an error!", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchZoneData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchSavedInputes = async () => {
|
||||||
|
if (selectedChartId.id !== "") {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${selectedChartId.id}/${organization}`);
|
||||||
|
if (response.status === 200) {
|
||||||
|
setSelections(response.data.Data.measurements)
|
||||||
|
setDuration(response.data.Data.duration)
|
||||||
|
setWidgetName(response.data.widgetName)
|
||||||
|
} else {
|
||||||
|
console.log("Unexpected response:", response);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("There was an error!", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchSavedInputes();
|
||||||
|
|
||||||
|
}, [selectedChartId.id]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setMeasurements(selections);
|
||||||
|
updateDuration(duration);
|
||||||
|
updateName(widgetName);
|
||||||
|
}, [selections, duration, widgetName]);
|
||||||
|
|
||||||
|
|
||||||
|
const sendInputes = async (inputMeasurement: any, inputDuration: any, inputName: any) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/3dwidget/save`, {
|
||||||
|
organization: organization,
|
||||||
|
zoneId: selectedZone.zoneId,
|
||||||
|
widget: {
|
||||||
|
id: selectedChartId.id,
|
||||||
|
widgetName: inputName,
|
||||||
|
Data: {
|
||||||
|
measurements: inputMeasurement,
|
||||||
|
duration: inputDuration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} as any);
|
||||||
|
if (response.status === 200) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
console.log("Unexpected response:", response);
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("There was an error!", error);
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSelect = async (inputKey: string, selectedData: { name: string; fields: string } | null) => {
|
||||||
|
|
||||||
|
// async() => {
|
||||||
|
const newSelections = { ...selections };
|
||||||
|
if (selectedData === null) {
|
||||||
|
delete newSelections[inputKey];
|
||||||
|
} else {
|
||||||
|
newSelections[inputKey] = selectedData;
|
||||||
|
}
|
||||||
|
// setMeasurements(newSelections); // Update Zustand store
|
||||||
|
console.log(newSelections);
|
||||||
|
if (await sendInputes(newSelections, duration, widgetName)) {
|
||||||
|
setSelections(newSelections);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectDuration = async (option: string) => {
|
||||||
|
if (await sendInputes(selections, option, widgetName)) {
|
||||||
|
setDuration(option);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNameChange = async (name:any) => {
|
||||||
|
console.log('name change requested',name);
|
||||||
|
|
||||||
|
if (await sendInputes(selections, duration, name)) {
|
||||||
|
setWidgetName(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="inputs-wrapper">
|
||||||
|
<div className="datas">
|
||||||
|
<div className="datas__label">Title</div>
|
||||||
|
<RenameInput value={widgetName} onRename={handleNameChange}/>
|
||||||
|
</div>
|
||||||
|
{[...Array(7)].map((_, index) => {
|
||||||
|
const inputKey = `input${index + 1}`;
|
||||||
|
return (
|
||||||
|
<div key={index} className="datas">
|
||||||
|
<div className="datas__label">Input {index + 1}</div>
|
||||||
|
<div className="datas__class">
|
||||||
|
<MultiLevelDropdown
|
||||||
|
data={dropDowndata}
|
||||||
|
onSelect={(selectedData) => handleSelect(inputKey, selectedData)}
|
||||||
|
onUnselect={() => handleSelect(inputKey, null)}
|
||||||
|
selectedValue={selections[inputKey]} // Load from Zustand
|
||||||
|
/>
|
||||||
|
<div className="icon">
|
||||||
|
<AddIcon />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Widget3InputCard3D;
|
||||||
@@ -0,0 +1,178 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||||
|
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
|
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
||||||
|
import useChartStore from "../../../../../store/useChartStore";
|
||||||
|
import { useSelectedZoneStore } from "../../../../../store/useZoneStore";
|
||||||
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
|
import axios from "axios";
|
||||||
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
|
||||||
|
type Props = {};
|
||||||
|
|
||||||
|
const Widget4InputCard3D = (props: Props) => {
|
||||||
|
const { selectedChartId } = useWidgetStore();
|
||||||
|
const [widgetName, setWidgetName] = useState("untited");
|
||||||
|
const { setMeasurements, updateDuration, updateName } = useChartStore();
|
||||||
|
const [duration, setDuration] = useState('1h')
|
||||||
|
const [dropDowndata, setDropDownData] = useState({});
|
||||||
|
const [selections, setSelections] = useState<Record<string, { name: string; fields: string }>>({});
|
||||||
|
const { selectedZone } = useSelectedZoneStore();
|
||||||
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
|
const email = localStorage.getItem("email") || "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0]
|
||||||
|
console.log(selectedChartId);
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchZoneData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`http://${iotApiUrl}/getinput`);
|
||||||
|
if (response.status === 200) {
|
||||||
|
// console.log("dropdown data:", response.data);
|
||||||
|
setDropDownData(response.data);
|
||||||
|
} else {
|
||||||
|
console.log("Unexpected response:", response);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("There was an error!", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchZoneData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchSavedInputes = async () => {
|
||||||
|
if (selectedChartId.id !== "") {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${selectedChartId.id}/${organization}`);
|
||||||
|
if (response.status === 200) {
|
||||||
|
setSelections(response.data.Data.measurements)
|
||||||
|
setDuration(response.data.Data.duration)
|
||||||
|
setWidgetName(response.data.widgetName)
|
||||||
|
} else {
|
||||||
|
console.log("Unexpected response:", response);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("There was an error!", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchSavedInputes();
|
||||||
|
|
||||||
|
}, [selectedChartId.id]);
|
||||||
|
|
||||||
|
// Sync Zustand state when component mounts
|
||||||
|
useEffect(() => {
|
||||||
|
setMeasurements(selections);
|
||||||
|
updateDuration(duration);
|
||||||
|
updateName(widgetName);
|
||||||
|
}, [selections, duration, widgetName]);
|
||||||
|
|
||||||
|
|
||||||
|
const sendInputes = async (inputMeasurement: any, inputDuration: any, inputName: any) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/3dwidget/save`, {
|
||||||
|
organization: organization,
|
||||||
|
zoneId: selectedZone.zoneId,
|
||||||
|
widget: {
|
||||||
|
id: selectedChartId.id,
|
||||||
|
widgetName: inputName,
|
||||||
|
Data: {
|
||||||
|
measurements: inputMeasurement,
|
||||||
|
duration: inputDuration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} as any);
|
||||||
|
if (response.status === 200) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
console.log("Unexpected response:", response);
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("There was an error!", error);
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSelect = async (inputKey: string, selectedData: { name: string; fields: string } | null) => {
|
||||||
|
|
||||||
|
// async() => {
|
||||||
|
const newSelections = { ...selections };
|
||||||
|
if (selectedData === null) {
|
||||||
|
delete newSelections[inputKey];
|
||||||
|
} else {
|
||||||
|
newSelections[inputKey] = selectedData;
|
||||||
|
}
|
||||||
|
// setMeasurements(newSelections); // Update Zustand store
|
||||||
|
console.log(newSelections);
|
||||||
|
if (await sendInputes(newSelections, duration, widgetName)) {
|
||||||
|
setSelections(newSelections);
|
||||||
|
}
|
||||||
|
// sendInputes(newSelections, duration); // Send data to server
|
||||||
|
// return newSelections;
|
||||||
|
// };
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectDuration = async (option: string) => {
|
||||||
|
if (await sendInputes(selections, option, widgetName)) {
|
||||||
|
setDuration(option);
|
||||||
|
}
|
||||||
|
// setDuration(option);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNameChange = async (name:any) => {
|
||||||
|
console.log('name change requested',name);
|
||||||
|
|
||||||
|
if (await sendInputes(selections, duration, name)) {
|
||||||
|
setWidgetName(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="inputs-wrapper">
|
||||||
|
<div className="datas">
|
||||||
|
<div className="datas__label">Title</div>
|
||||||
|
<RenameInput value={widgetName} onRename={handleNameChange}/>
|
||||||
|
</div>
|
||||||
|
{[...Array(1)].map((_, index) => {
|
||||||
|
const inputKey = `input${index + 1}`;
|
||||||
|
return (
|
||||||
|
<div key={index} className="datas">
|
||||||
|
<div className="datas__label">Input {index + 1}</div>
|
||||||
|
<div className="datas__class">
|
||||||
|
<MultiLevelDropdown
|
||||||
|
data={dropDowndata}
|
||||||
|
onSelect={(selectedData) => handleSelect(inputKey, selectedData)}
|
||||||
|
onUnselect={() => handleSelect(inputKey, null)}
|
||||||
|
selectedValue={selections[inputKey]} // Load from Zustand
|
||||||
|
/>
|
||||||
|
<div className="icon">
|
||||||
|
<AddIcon />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="datas">
|
||||||
|
<div className="datas__label">Duration</div>
|
||||||
|
<div className="datas__class">
|
||||||
|
<RegularDropDown
|
||||||
|
header={duration}
|
||||||
|
options={["1h", "2h", "12h"]}
|
||||||
|
onSelect={handleSelectDuration}
|
||||||
|
search={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Widget4InputCard3D;
|
||||||
@@ -129,13 +129,13 @@ export default function Dropped3dWidgets() {
|
|||||||
console.log('Typeeeeeeeeeeee',type);
|
console.log('Typeeeeeeeeeeee',type);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "ui-Widget 1":
|
case "ui-Widget 1":
|
||||||
return <ProductionCapacity key={id} position={position} />;
|
return <ProductionCapacity key={id} id={id} type={type} position={position} />;
|
||||||
case "ui-Widget 2":
|
case "ui-Widget 2":
|
||||||
return <ReturnOfInvestment key={id} position={position} />;
|
return <ReturnOfInvestment key={id} id={id} type={type} position={position} />;
|
||||||
case "ui-Widget 3":
|
case "ui-Widget 3":
|
||||||
return <StateWorking key={id} position={position} />;
|
return <StateWorking key={id} id={id} type={type} position={position} />;
|
||||||
case "ui-Widget 4":
|
case "ui-Widget 4":
|
||||||
return <Throughput key={id} position={position} />;
|
return <Throughput key={id} id={id} type={type} position={position} />;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user