Merge remote-tracking branch 'origin/realTimeVisulization' into simulation
This commit is contained in:
2
app/.env
2
app/.env
@@ -7,6 +7,8 @@ REACT_APP_SERVER_SOCKET_API_BASE_URL=185.100.212.76:8000
|
|||||||
# Base URL for the server REST API, used for HTTP requests to the backend server.
|
# Base URL for the server REST API, used for HTTP requests to the backend server.
|
||||||
REACT_APP_SERVER_REST_API_BASE_URL=185.100.212.76:5000
|
REACT_APP_SERVER_REST_API_BASE_URL=185.100.212.76:5000
|
||||||
|
|
||||||
|
REACT_APP_SERVER_REST_API_LOCAL_BASE_URL=192.168.0.102:5000
|
||||||
|
|
||||||
# Base URL for the server marketplace API.
|
# Base URL for the server marketplace API.
|
||||||
# REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011
|
# REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011
|
||||||
REACT_APP_SERVER_MARKETPLACE_URL=192.168.0.111:3501
|
REACT_APP_SERVER_MARKETPLACE_URL=192.168.0.111:3501
|
||||||
|
|||||||
10
app/package-lock.json
generated
10
app/package-lock.json
generated
@@ -26,6 +26,7 @@
|
|||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@use-gesture/react": "^10.3.1",
|
"@use-gesture/react": "^10.3.1",
|
||||||
"chart.js": "^4.4.8",
|
"chart.js": "^4.4.8",
|
||||||
|
"chartjs-plugin-annotation": "^3.1.0",
|
||||||
"glob": "^11.0.0",
|
"glob": "^11.0.0",
|
||||||
"gsap": "^3.12.5",
|
"gsap": "^3.12.5",
|
||||||
"leva": "^0.10.0",
|
"leva": "^0.10.0",
|
||||||
@@ -8499,6 +8500,15 @@
|
|||||||
"pnpm": ">=8"
|
"pnpm": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/chartjs-plugin-annotation": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chartjs-plugin-annotation/-/chartjs-plugin-annotation-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-EkAed6/ycXD/7n0ShrlT1T2Hm3acnbFhgkIEJLa0X+M6S16x0zwj1Fv4suv/2bwayCT3jGPdAtI9uLcAMToaQQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"chart.js": ">=4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/check-more-types": {
|
"node_modules/check-more-types": {
|
||||||
"version": "2.24.0",
|
"version": "2.24.0",
|
||||||
"resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz",
|
"resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@use-gesture/react": "^10.3.1",
|
"@use-gesture/react": "^10.3.1",
|
||||||
"chart.js": "^4.4.8",
|
"chart.js": "^4.4.8",
|
||||||
|
"chartjs-plugin-annotation": "^3.1.0",
|
||||||
"glob": "^11.0.0",
|
"glob": "^11.0.0",
|
||||||
"gsap": "^3.12.5",
|
"gsap": "^3.12.5",
|
||||||
"leva": "^0.10.0",
|
"leva": "^0.10.0",
|
||||||
|
|||||||
@@ -0,0 +1,177 @@
|
|||||||
|
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 FlotingWidgetInput = (props: Props) => {
|
||||||
|
const [widgetName, setWidgetName] = useState('Widget');
|
||||||
|
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 { selectedChartId } = useWidgetStore();
|
||||||
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
|
const email = localStorage.getItem("email") || "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0]
|
||||||
|
|
||||||
|
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/WidgetData/${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/floatwidget/save`, {
|
||||||
|
organization: organization,
|
||||||
|
zoneId: selectedZone.zoneId,
|
||||||
|
widget: {
|
||||||
|
id: selectedChartId.id,
|
||||||
|
panel: selectedChartId.panel,
|
||||||
|
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={selectedChartId?.title || "untited"} onRename={handleNameChange}/>
|
||||||
|
</div>
|
||||||
|
{[...Array(6)].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 FlotingWidgetInput;
|
||||||
@@ -125,11 +125,13 @@ import useChartStore from "../../../../../store/useChartStore";
|
|||||||
import { useSelectedZoneStore } from "../../../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../../store/useZoneStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
|
||||||
type Props = {};
|
type Props = {};
|
||||||
|
|
||||||
const LineGrapInput = (props: Props) => {
|
const LineGrapInput = (props: Props) => {
|
||||||
const { setMeasurements, updateDuration } = useChartStore();
|
const [widgetName, setWidgetName] = useState('Widget');
|
||||||
|
const { setMeasurements, updateDuration, updateName } = useChartStore();
|
||||||
const [duration, setDuration] = useState('1h')
|
const [duration, setDuration] = useState('1h')
|
||||||
const [dropDowndata, setDropDownData] = useState({});
|
const [dropDowndata, setDropDownData] = useState({});
|
||||||
const [selections, setSelections] = useState<Record<string, { name: string; fields: string }>>({});
|
const [selections, setSelections] = useState<Record<string, { name: string; fields: string }>>({});
|
||||||
@@ -157,13 +159,14 @@ const LineGrapInput = (props: Props) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchSavedInputes = async() => {
|
const fetchSavedInputes = async () => {
|
||||||
if (selectedChartId.id !== "") {
|
if (selectedChartId.id !== "") {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/WidgetData/${selectedChartId.id}/${organization}`);
|
const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/WidgetData/${selectedChartId.id}/${organization}`);
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
setSelections(response.data.Data.measurements)
|
setSelections(response.data.Data.measurements)
|
||||||
setDuration(response.data.Data.duration)
|
setDuration(response.data.Data.duration)
|
||||||
|
setWidgetName(response.data.widgetName)
|
||||||
} else {
|
} else {
|
||||||
console.log("Unexpected response:", response);
|
console.log("Unexpected response:", response);
|
||||||
}
|
}
|
||||||
@@ -181,17 +184,19 @@ const LineGrapInput = (props: Props) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMeasurements(selections);
|
setMeasurements(selections);
|
||||||
updateDuration(duration);
|
updateDuration(duration);
|
||||||
}, [selections, duration]);
|
updateName(widgetName);
|
||||||
|
}, [selections, duration, widgetName]);
|
||||||
|
|
||||||
|
|
||||||
const sendInputes = async(inputMeasurement: any, inputDuration: any) => {
|
const sendInputes = async (inputMeasurement: any, inputDuration: any, inputName: any) => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget/save`,{
|
const response = await axios.post(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget/save`, {
|
||||||
organization: organization,
|
organization: organization,
|
||||||
zoneId: selectedZone.zoneId,
|
zoneId: selectedZone.zoneId,
|
||||||
widget:{
|
widget: {
|
||||||
id: selectedChartId.id,
|
id: selectedChartId.id,
|
||||||
panel: selectedChartId.panel,
|
panel: selectedChartId.panel,
|
||||||
|
widgetName: inputName,
|
||||||
Data: {
|
Data: {
|
||||||
measurements: inputMeasurement,
|
measurements: inputMeasurement,
|
||||||
duration: inputDuration
|
duration: inputDuration
|
||||||
@@ -210,7 +215,7 @@ const LineGrapInput = (props: Props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSelect = async(inputKey: string, selectedData: { name: string; fields: string } | null) => {
|
const handleSelect = async (inputKey: string, selectedData: { name: string; fields: string } | null) => {
|
||||||
|
|
||||||
// async() => {
|
// async() => {
|
||||||
const newSelections = { ...selections };
|
const newSelections = { ...selections };
|
||||||
@@ -221,7 +226,7 @@ const LineGrapInput = (props: Props) => {
|
|||||||
}
|
}
|
||||||
// setMeasurements(newSelections); // Update Zustand store
|
// setMeasurements(newSelections); // Update Zustand store
|
||||||
console.log(newSelections);
|
console.log(newSelections);
|
||||||
if ( await sendInputes(newSelections, duration)) {
|
if (await sendInputes(newSelections, duration, widgetName)) {
|
||||||
setSelections(newSelections);
|
setSelections(newSelections);
|
||||||
}
|
}
|
||||||
// sendInputes(newSelections, duration); // Send data to server
|
// sendInputes(newSelections, duration); // Send data to server
|
||||||
@@ -229,16 +234,28 @@ const LineGrapInput = (props: Props) => {
|
|||||||
// };
|
// };
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectDuration = async(option: string) => {
|
const handleSelectDuration = async (option: string) => {
|
||||||
if ( await sendInputes(selections, option)) {
|
if (await sendInputes(selections, option, widgetName)) {
|
||||||
setDuration(option);
|
setDuration(option);
|
||||||
}
|
}
|
||||||
// setDuration(option);
|
// setDuration(option);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleNameChange = async (name:any) => {
|
||||||
|
console.log('name change requested',name);
|
||||||
|
|
||||||
|
if (await sendInputes(selections, duration, name)) {
|
||||||
|
setWidgetName(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="inputs-wrapper">
|
<div className="inputs-wrapper">
|
||||||
|
<div className="datas">
|
||||||
|
<div className="datas__label">Title</div>
|
||||||
|
<RenameInput value={selectedChartId?.title || "untited"} onRename={handleNameChange}/>
|
||||||
|
</div>
|
||||||
{[...Array(6)].map((_, index) => {
|
{[...Array(6)].map((_, index) => {
|
||||||
const inputKey = `input${index + 1}`;
|
const inputKey = `input${index + 1}`;
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
|||||||
import { AddIcon, RemoveIcon } from "../../../../icons/ExportCommonIcons";
|
import { AddIcon, RemoveIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
import MultiLevelDropDown from "../../../../ui/inputs/MultiLevelDropDown";
|
import MultiLevelDropDown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||||
import LineGrapInput from "../IotInputCards/LineGrapInput";
|
import LineGrapInput from "../IotInputCards/LineGrapInput";
|
||||||
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
|
||||||
// Define the data structure for demonstration purposes
|
// Define the data structure for demonstration purposes
|
||||||
const DATA_STRUCTURE = {
|
const DATA_STRUCTURE = {
|
||||||
@@ -117,15 +118,24 @@ const Data = () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
console.log("selectedChartId", selectedChartId);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="dataSideBar">
|
<div className="dataSideBar">
|
||||||
{selectedChartId?.title && (
|
{/* {selectedChartId?.title && (
|
||||||
<div className="sideBarHeader">{selectedChartId?.title}</div>
|
<div className="sideBarHeader">{selectedChartId?.title}</div>
|
||||||
)}
|
)} */}
|
||||||
|
|
||||||
|
|
||||||
|
{/* <RenameInput value={selectedChartId?.title || "untited"} /> */}
|
||||||
|
|
||||||
{/* Render groups dynamically */}
|
{/* Render groups dynamically */}
|
||||||
{
|
{
|
||||||
chartDataGroups[selectedChartId?.id] && <LineGrapInput />
|
chartDataGroups[selectedChartId?.id] &&
|
||||||
|
<>
|
||||||
|
<div className="sideBarHeader">2D Widget Input</div>
|
||||||
|
<LineGrapInput />
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
{/* Info Box */}
|
{/* Info Box */}
|
||||||
|
|||||||
@@ -306,34 +306,20 @@ export const DraggableWidget = ({
|
|||||||
)}
|
)}
|
||||||
{widget.type === "doughnut" && (
|
{widget.type === "doughnut" && (
|
||||||
<DoughnutGraphComponent
|
<DoughnutGraphComponent
|
||||||
|
id={widget.id}
|
||||||
type={widget.type}
|
type={widget.type}
|
||||||
title={widget.title}
|
title={widget.title}
|
||||||
fontSize={widget.fontSize}
|
fontSize={widget.fontSize}
|
||||||
fontWeight={widget.fontWeight}
|
fontWeight={widget.fontWeight}
|
||||||
data={{
|
|
||||||
measurements: [
|
|
||||||
{ name: "testDevice", fields: "powerConsumption" },
|
|
||||||
{ name: "furnace", fields: "powerConsumption" },
|
|
||||||
],
|
|
||||||
interval: 1000,
|
|
||||||
duration: "1h",
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{widget.type === "polarArea" && (
|
{widget.type === "polarArea" && (
|
||||||
<PolarAreaGraphComponent
|
<PolarAreaGraphComponent
|
||||||
|
id={widget.id}
|
||||||
type={widget.type}
|
type={widget.type}
|
||||||
title={widget.title}
|
title={widget.title}
|
||||||
fontSize={widget.fontSize}
|
fontSize={widget.fontSize}
|
||||||
fontWeight={widget.fontWeight}
|
fontWeight={widget.fontWeight}
|
||||||
data={{
|
|
||||||
measurements: [
|
|
||||||
{ name: "testDevice", fields: "powerConsumption" },
|
|
||||||
{ name: "furnace", fields: "powerConsumption" },
|
|
||||||
],
|
|
||||||
interval: 1000,
|
|
||||||
duration: "1h",
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ import { determinePosition } from "./functions/determinePosition";
|
|||||||
import { getActiveProperties } from "./functions/getActiveProperties";
|
import { getActiveProperties } from "./functions/getActiveProperties";
|
||||||
import { addingFloatingWidgets } from "../../../services/realTimeVisulization/zoneData/addFloatingWidgets";
|
import { addingFloatingWidgets } from "../../../services/realTimeVisulization/zoneData/addFloatingWidgets";
|
||||||
|
|
||||||
|
import TotalCardComponent from "../realTimeVis/floating/TotalCardComponent";
|
||||||
|
import WarehouseThroughputComponent from "../realTimeVis/floating/WarehouseThroughputComponent";
|
||||||
|
import FleetEfficiencyComponent from "../realTimeVis/floating/FleetEfficiencyComponent";
|
||||||
|
import { useWidgetStore } from "../../../store/useWidgetStore";
|
||||||
const DroppedObjects: React.FC = () => {
|
const DroppedObjects: React.FC = () => {
|
||||||
const zones = useDroppedObjectsStore((state) => state.zones);
|
const zones = useDroppedObjectsStore((state) => state.zones);
|
||||||
|
|
||||||
@@ -21,6 +25,7 @@ const DroppedObjects: React.FC = () => {
|
|||||||
index: number;
|
index: number;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
const [offset, setOffset] = useState<[number, number] | null>(null);
|
const [offset, setOffset] = useState<[number, number] | null>(null);
|
||||||
|
const { setSelectedChartId } = useWidgetStore();
|
||||||
const positionRef = useRef<[number, number] | null>(null);
|
const positionRef = useRef<[number, number] | null>(null);
|
||||||
const animationRef = useRef<number | null>(null);
|
const animationRef = useRef<number | null>(null);
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
@@ -29,9 +34,13 @@ const DroppedObjects: React.FC = () => {
|
|||||||
const zoneEntries = Object.entries(zones);
|
const zoneEntries = Object.entries(zones);
|
||||||
if (zoneEntries.length === 0) return null; // No zone, nothing to render
|
if (zoneEntries.length === 0) return null; // No zone, nothing to render
|
||||||
const [zoneName, zone] = zoneEntries[0]; // Only render the first zone
|
const [zoneName, zone] = zoneEntries[0]; // Only render the first zone
|
||||||
|
console.log("zone", zone);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Handle pointer down event
|
// Handle pointer down event
|
||||||
function handlePointerDown(event: React.PointerEvent, index: number) {
|
function handlePointerDown(event: React.PointerEvent, index: number) {
|
||||||
|
|
||||||
const obj = zone.objects[index];
|
const obj = zone.objects[index];
|
||||||
const container = document.getElementById("real-time-vis-canvas");
|
const container = document.getElementById("real-time-vis-canvas");
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
@@ -194,53 +203,21 @@ const DroppedObjects: React.FC = () => {
|
|||||||
// transition: draggingIndex?.index === index ? "none" : "transform 0.1s ease-out",
|
// transition: draggingIndex?.index === index ? "none" : "transform 0.1s ease-out",
|
||||||
}}
|
}}
|
||||||
onPointerDown={(event) => handlePointerDown(event, index)}
|
onPointerDown={(event) => handlePointerDown(event, index)}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedChartId(obj)
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{obj.className === "floating total-card" ? (
|
{obj.className === "floating total-card" ? (
|
||||||
<>
|
<>
|
||||||
<div className="header-wrapper">
|
<TotalCardComponent object={obj} />
|
||||||
<div className="header">{obj.header}</div>
|
|
||||||
<div className="data-values">
|
|
||||||
<div className="value">{obj.value}</div>
|
|
||||||
<div className="per">{obj.per}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="icon">
|
|
||||||
<WalletIcon />
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
) : obj.className === "warehouseThroughput floating" ? (
|
) : obj.className === "warehouseThroughput floating" ? (
|
||||||
<>
|
<>
|
||||||
<div className="header">
|
<WarehouseThroughputComponent />
|
||||||
<h2>Warehouse Throughput</h2>
|
|
||||||
<p>
|
|
||||||
<span>(+5) more</span> in 2025
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="lineGraph" style={{ height: "100%" }}>
|
|
||||||
{/* <Line data={lineGraphData} options={lineGraphOptions} /> */}
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
) : obj.className === "fleetEfficiency floating" ? (
|
) : obj.className === "fleetEfficiency floating" ? (
|
||||||
<>
|
<>
|
||||||
<h2 className="header">Fleet Efficiency</h2>
|
<FleetEfficiencyComponent object={obj} />
|
||||||
<div className="progressContainer">
|
|
||||||
<div className="progress">
|
|
||||||
<div className="barOverflow">
|
|
||||||
<div
|
|
||||||
className="bar"
|
|
||||||
style={{ transform: `rotate(${obj.value}deg)` }}
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="scaleLabels">
|
|
||||||
<span>0%</span>
|
|
||||||
<div className="centerText">
|
|
||||||
<div className="percentage">{obj.per}%</div>
|
|
||||||
<div className="status">Optimal</div>
|
|
||||||
</div>
|
|
||||||
<span>100%</span>
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -211,9 +211,10 @@ const BarGraphComponent = ({
|
|||||||
fontWeight = "Regular",
|
fontWeight = "Regular",
|
||||||
}: ChartComponentProps) => {
|
}: ChartComponentProps) => {
|
||||||
const { themeColor } = useThemeStore();
|
const { themeColor } = useThemeStore();
|
||||||
const { measurements: chartMeasurements, duration: chartDuration } = useChartStore();
|
const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore();
|
||||||
const [measurements, setmeasurements] = useState<any>({});
|
const [measurements, setmeasurements] = useState<any>({});
|
||||||
const [duration, setDuration] = useState("1h")
|
const [duration, setDuration] = useState("1h")
|
||||||
|
const [name, setName] = useState("Widget")
|
||||||
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
||||||
labels: [],
|
labels: [],
|
||||||
datasets: [],
|
datasets: [],
|
||||||
@@ -236,6 +237,10 @@ const BarGraphComponent = ({
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("titleeeeeeeeeeeeeeeeeee",title);
|
||||||
|
},[])
|
||||||
|
|
||||||
// Memoize Theme Colors
|
// Memoize Theme Colors
|
||||||
const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]);
|
const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]);
|
||||||
const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]);
|
const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]);
|
||||||
@@ -270,7 +275,7 @@ const BarGraphComponent = ({
|
|||||||
plugins: {
|
plugins: {
|
||||||
title: {
|
title: {
|
||||||
display: true,
|
display: true,
|
||||||
text: title,
|
text: name,
|
||||||
font: chartFontStyle,
|
font: chartFontStyle,
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
@@ -285,7 +290,7 @@ const BarGraphComponent = ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
[title, chartFontStyle]
|
[title, chartFontStyle, name]
|
||||||
);
|
);
|
||||||
|
|
||||||
// useEffect(() => {console.log(measurements);
|
// useEffect(() => {console.log(measurements);
|
||||||
@@ -304,15 +309,12 @@ const BarGraphComponent = ({
|
|||||||
|
|
||||||
|
|
||||||
const startStream = () => {
|
const startStream = () => {
|
||||||
console.log("inputtttttttttt",inputData);
|
|
||||||
socket.emit("lineInput", inputData);
|
socket.emit("lineInput", inputData);
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.on("connect", startStream);
|
socket.on("connect", startStream);
|
||||||
|
|
||||||
socket.on("lineOutput", (response) => {
|
socket.on("lineOutput", (response) => {
|
||||||
console.log("responce dataaaaaaaaa",response.data);
|
|
||||||
|
|
||||||
const responseData = response.data;
|
const responseData = response.data;
|
||||||
|
|
||||||
// Extract timestamps and values
|
// Extract timestamps and values
|
||||||
@@ -347,6 +349,7 @@ const BarGraphComponent = ({
|
|||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
setmeasurements(response.data.Data.measurements)
|
setmeasurements(response.data.Data.measurements)
|
||||||
setDuration(response.data.Data.duration)
|
setDuration(response.data.Data.duration)
|
||||||
|
setName(response.data.widgetName)
|
||||||
} else {
|
} else {
|
||||||
console.log("Unexpected response:", response);
|
console.log("Unexpected response:", response);
|
||||||
}
|
}
|
||||||
@@ -365,7 +368,7 @@ const BarGraphComponent = ({
|
|||||||
fetchSavedInputes();
|
fetchSavedInputes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
,[chartMeasurements, chartDuration])
|
,[chartMeasurements, chartDuration, widgetName])
|
||||||
|
|
||||||
return <Bar data={Object.keys(measurements).length > 0 ? chartData : defaultData} options={options} />;
|
return <Bar data={Object.keys(measurements).length > 0 ? chartData : defaultData} options={options} />;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,22 +1,64 @@
|
|||||||
import { useMemo } from "react";
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
import { Doughnut, Line } from "react-chartjs-2";
|
import { Doughnut } from "react-chartjs-2";
|
||||||
|
import io from "socket.io-client";
|
||||||
|
import { useThemeStore } from "../../../../store/useThemeStore";
|
||||||
|
import useChartStore from "../../../../store/useChartStore";
|
||||||
|
import { useWidgetStore } from "../../../../store/useWidgetStore";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
interface ChartComponentProps {
|
interface ChartComponentProps {
|
||||||
|
id: string;
|
||||||
type: any;
|
type: any;
|
||||||
title: string;
|
title: string;
|
||||||
fontFamily?: string;
|
fontFamily?: string;
|
||||||
fontSize?: string;
|
fontSize?: string;
|
||||||
fontWeight?: "Light" | "Regular" | "Bold";
|
fontWeight?: "Light" | "Regular" | "Bold";
|
||||||
data: any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const DoughnutGraphComponent = ({
|
const DoughnutGraphComponent = ({
|
||||||
|
id,
|
||||||
|
type,
|
||||||
title,
|
title,
|
||||||
fontFamily,
|
fontFamily,
|
||||||
fontSize,
|
fontSize,
|
||||||
fontWeight = "Regular",
|
fontWeight = "Regular",
|
||||||
}: ChartComponentProps) => {
|
}: ChartComponentProps) => {
|
||||||
// Memoize Font Weight Mapping
|
const { themeColor } = useThemeStore();
|
||||||
|
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 { selectedChartId } = useWidgetStore();
|
||||||
|
|
||||||
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
|
const email = localStorage.getItem("email") || "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0]
|
||||||
|
const defaultData = {
|
||||||
|
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Dataset",
|
||||||
|
data: [12, 19, 3, 5, 2, 3],
|
||||||
|
backgroundColor: ["#6f42c1"],
|
||||||
|
borderColor: "#b392f0",
|
||||||
|
borderWidth: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("titleeeeeeeeeeeeeeeeeee",title);
|
||||||
|
},[])
|
||||||
|
|
||||||
|
// Memoize Theme Colors
|
||||||
|
const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]);
|
||||||
|
const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]);
|
||||||
|
|
||||||
|
// Memoize Font Styling
|
||||||
const chartFontWeightMap = useMemo(
|
const chartFontWeightMap = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
Light: "lighter" as const,
|
Light: "lighter" as const,
|
||||||
@@ -26,19 +68,9 @@ const DoughnutGraphComponent = ({
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Parse and Memoize Font Size
|
const fontSizeValue = useMemo(() => (fontSize ? parseInt(fontSize) : 12), [fontSize]);
|
||||||
const fontSizeValue = useMemo(
|
const fontWeightValue = useMemo(() => chartFontWeightMap[fontWeight], [fontWeight, chartFontWeightMap]);
|
||||||
() => (fontSize ? parseInt(fontSize) : 12),
|
|
||||||
[fontSize]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Determine and Memoize Font Weight
|
|
||||||
const fontWeightValue = useMemo(
|
|
||||||
() => chartFontWeightMap[fontWeight],
|
|
||||||
[fontWeight, chartFontWeightMap]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Memoize Chart Font Style
|
|
||||||
const chartFontStyle = useMemo(
|
const chartFontStyle = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
family: fontFamily || "Arial",
|
family: fontFamily || "Arial",
|
||||||
@@ -48,6 +80,7 @@ const DoughnutGraphComponent = ({
|
|||||||
[fontFamily, fontSizeValue, fontWeightValue]
|
[fontFamily, fontSizeValue, fontWeightValue]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Memoize Chart Options
|
||||||
const options = useMemo(
|
const options = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
responsive: true,
|
responsive: true,
|
||||||
@@ -55,7 +88,7 @@ const DoughnutGraphComponent = ({
|
|||||||
plugins: {
|
plugins: {
|
||||||
title: {
|
title: {
|
||||||
display: true,
|
display: true,
|
||||||
text: title,
|
text: name,
|
||||||
font: chartFontStyle,
|
font: chartFontStyle,
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
@@ -63,31 +96,94 @@ const DoughnutGraphComponent = ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
scales: {
|
scales: {
|
||||||
x: {
|
// x: {
|
||||||
ticks: {
|
// ticks: {
|
||||||
display: false, // This hides the x-axis labels
|
// display: true, // This hides the x-axis labels
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
[title, chartFontStyle]
|
[title, chartFontStyle, name]
|
||||||
);
|
);
|
||||||
|
|
||||||
const chartData = {
|
// useEffect(() => {console.log(measurements);
|
||||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
// },[measurements])
|
||||||
datasets: [
|
|
||||||
{
|
useEffect(() => {
|
||||||
label: "My First Dataset",
|
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
|
||||||
data: [65, 59, 80, 81, 56, 55, 40],
|
|
||||||
backgroundColor: "#6f42c1", // Updated to #6f42c1 (Purple)
|
const socket = io(`http://${iotApiUrl}`);
|
||||||
borderColor: "#ffffff", // Keeping border color white
|
|
||||||
borderWidth: 2,
|
const inputData = {
|
||||||
fill: false,
|
measurements,
|
||||||
},
|
duration,
|
||||||
],
|
interval: 1000,
|
||||||
};
|
};
|
||||||
|
|
||||||
return <Doughnut data={chartData} options={options} />;
|
|
||||||
|
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",
|
||||||
|
borderColor: "#b392f0",
|
||||||
|
borderWidth: 1,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
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/WidgetData/${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 <Doughnut data={Object.keys(measurements).length > 0 ? chartData : defaultData} options={options} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DoughnutGraphComponent;
|
export default DoughnutGraphComponent;
|
||||||
@@ -24,9 +24,10 @@ const LineGraphComponent = ({
|
|||||||
fontWeight = "Regular",
|
fontWeight = "Regular",
|
||||||
}: ChartComponentProps) => {
|
}: ChartComponentProps) => {
|
||||||
const { themeColor } = useThemeStore();
|
const { themeColor } = useThemeStore();
|
||||||
const { measurements: chartMeasurements, duration: chartDuration } = useChartStore();
|
const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore();
|
||||||
const [measurements, setmeasurements] = useState<any>({});
|
const [measurements, setmeasurements] = useState<any>({});
|
||||||
const [duration, setDuration] = useState("1h")
|
const [duration, setDuration] = useState("1h")
|
||||||
|
const [name, setName] = useState("Widget")
|
||||||
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
||||||
labels: [],
|
labels: [],
|
||||||
datasets: [],
|
datasets: [],
|
||||||
@@ -49,6 +50,10 @@ const LineGraphComponent = ({
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("titleeeeeeeeeeeeeeeeeee",title);
|
||||||
|
},[])
|
||||||
|
|
||||||
// Memoize Theme Colors
|
// Memoize Theme Colors
|
||||||
const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]);
|
const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]);
|
||||||
const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]);
|
const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]);
|
||||||
@@ -83,7 +88,7 @@ const LineGraphComponent = ({
|
|||||||
plugins: {
|
plugins: {
|
||||||
title: {
|
title: {
|
||||||
display: true,
|
display: true,
|
||||||
text: title,
|
text: name,
|
||||||
font: chartFontStyle,
|
font: chartFontStyle,
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
@@ -98,7 +103,7 @@ const LineGraphComponent = ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
[title, chartFontStyle]
|
[title, chartFontStyle, name]
|
||||||
);
|
);
|
||||||
|
|
||||||
// useEffect(() => {console.log(measurements);
|
// useEffect(() => {console.log(measurements);
|
||||||
@@ -157,6 +162,7 @@ const LineGraphComponent = ({
|
|||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
setmeasurements(response.data.Data.measurements)
|
setmeasurements(response.data.Data.measurements)
|
||||||
setDuration(response.data.Data.duration)
|
setDuration(response.data.Data.duration)
|
||||||
|
setName(response.data.widgetName)
|
||||||
} else {
|
} else {
|
||||||
console.log("Unexpected response:", response);
|
console.log("Unexpected response:", response);
|
||||||
}
|
}
|
||||||
@@ -175,7 +181,7 @@ const LineGraphComponent = ({
|
|||||||
fetchSavedInputes();
|
fetchSavedInputes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
,[chartMeasurements, chartDuration])
|
,[chartMeasurements, chartDuration, widgetName])
|
||||||
|
|
||||||
return <Line data={Object.keys(measurements).length > 0 ? chartData : defaultData} options={options} />;
|
return <Line data={Object.keys(measurements).length > 0 ? chartData : defaultData} options={options} />;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -210,9 +210,10 @@ const PieChartComponent = ({
|
|||||||
fontWeight = "Regular",
|
fontWeight = "Regular",
|
||||||
}: ChartComponentProps) => {
|
}: ChartComponentProps) => {
|
||||||
const { themeColor } = useThemeStore();
|
const { themeColor } = useThemeStore();
|
||||||
const { measurements: chartMeasurements, duration: chartDuration } = useChartStore();
|
const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore();
|
||||||
const [measurements, setmeasurements] = useState<any>({});
|
const [measurements, setmeasurements] = useState<any>({});
|
||||||
const [duration, setDuration] = useState("1h")
|
const [duration, setDuration] = useState("1h")
|
||||||
|
const [name, setName] = useState("Widget")
|
||||||
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
||||||
labels: [],
|
labels: [],
|
||||||
datasets: [],
|
datasets: [],
|
||||||
@@ -235,6 +236,10 @@ const PieChartComponent = ({
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("titleeeeeeeeeeeeeeeeeee",title);
|
||||||
|
},[])
|
||||||
|
|
||||||
// Memoize Theme Colors
|
// Memoize Theme Colors
|
||||||
const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]);
|
const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]);
|
||||||
const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]);
|
const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]);
|
||||||
@@ -269,7 +274,7 @@ const PieChartComponent = ({
|
|||||||
plugins: {
|
plugins: {
|
||||||
title: {
|
title: {
|
||||||
display: true,
|
display: true,
|
||||||
text: title,
|
text: name,
|
||||||
font: chartFontStyle,
|
font: chartFontStyle,
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
@@ -284,7 +289,7 @@ const PieChartComponent = ({
|
|||||||
// },
|
// },
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
[title, chartFontStyle]
|
[title, chartFontStyle, name]
|
||||||
);
|
);
|
||||||
|
|
||||||
// useEffect(() => {console.log(measurements);
|
// useEffect(() => {console.log(measurements);
|
||||||
@@ -343,6 +348,7 @@ const PieChartComponent = ({
|
|||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
setmeasurements(response.data.Data.measurements)
|
setmeasurements(response.data.Data.measurements)
|
||||||
setDuration(response.data.Data.duration)
|
setDuration(response.data.Data.duration)
|
||||||
|
setName(response.data.widgetName)
|
||||||
} else {
|
} else {
|
||||||
console.log("Unexpected response:", response);
|
console.log("Unexpected response:", response);
|
||||||
}
|
}
|
||||||
@@ -361,7 +367,7 @@ const PieChartComponent = ({
|
|||||||
fetchSavedInputes();
|
fetchSavedInputes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
,[chartMeasurements, chartDuration])
|
,[chartMeasurements, chartDuration, widgetName])
|
||||||
|
|
||||||
return <Pie data={Object.keys(measurements).length > 0 ? chartData : defaultData} options={options} />;
|
return <Pie data={Object.keys(measurements).length > 0 ? chartData : defaultData} options={options} />;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,22 +1,64 @@
|
|||||||
import { useMemo } from "react";
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
import { Line, PolarArea } from "react-chartjs-2";
|
import { PolarArea } from "react-chartjs-2";
|
||||||
|
import io from "socket.io-client";
|
||||||
|
import { useThemeStore } from "../../../../store/useThemeStore";
|
||||||
|
import useChartStore from "../../../../store/useChartStore";
|
||||||
|
import { useWidgetStore } from "../../../../store/useWidgetStore";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
interface ChartComponentProps {
|
interface ChartComponentProps {
|
||||||
|
id: string;
|
||||||
type: any;
|
type: any;
|
||||||
title: string;
|
title: string;
|
||||||
fontFamily?: string;
|
fontFamily?: string;
|
||||||
fontSize?: string;
|
fontSize?: string;
|
||||||
fontWeight?: "Light" | "Regular" | "Bold";
|
fontWeight?: "Light" | "Regular" | "Bold";
|
||||||
data: any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PolarAreaGraphComponent = ({
|
const PolarAreaGraphComponent = ({
|
||||||
|
id,
|
||||||
|
type,
|
||||||
title,
|
title,
|
||||||
fontFamily,
|
fontFamily,
|
||||||
fontSize,
|
fontSize,
|
||||||
fontWeight = "Regular",
|
fontWeight = "Regular",
|
||||||
}: ChartComponentProps) => {
|
}: ChartComponentProps) => {
|
||||||
// Memoize Font Weight Mapping
|
const { themeColor } = useThemeStore();
|
||||||
|
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 { selectedChartId } = useWidgetStore();
|
||||||
|
|
||||||
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
|
const email = localStorage.getItem("email") || "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0]
|
||||||
|
const defaultData = {
|
||||||
|
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Dataset",
|
||||||
|
data: [12, 19, 3, 5, 2, 3],
|
||||||
|
backgroundColor: ["#6f42c1"],
|
||||||
|
borderColor: "#b392f0",
|
||||||
|
borderWidth: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("titleeeeeeeeeeeeeeeeeee",title);
|
||||||
|
},[])
|
||||||
|
|
||||||
|
// Memoize Theme Colors
|
||||||
|
const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]);
|
||||||
|
const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]);
|
||||||
|
|
||||||
|
// Memoize Font Styling
|
||||||
const chartFontWeightMap = useMemo(
|
const chartFontWeightMap = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
Light: "lighter" as const,
|
Light: "lighter" as const,
|
||||||
@@ -26,19 +68,9 @@ const PolarAreaGraphComponent = ({
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Parse and Memoize Font Size
|
const fontSizeValue = useMemo(() => (fontSize ? parseInt(fontSize) : 12), [fontSize]);
|
||||||
const fontSizeValue = useMemo(
|
const fontWeightValue = useMemo(() => chartFontWeightMap[fontWeight], [fontWeight, chartFontWeightMap]);
|
||||||
() => (fontSize ? parseInt(fontSize) : 12),
|
|
||||||
[fontSize]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Determine and Memoize Font Weight
|
|
||||||
const fontWeightValue = useMemo(
|
|
||||||
() => chartFontWeightMap[fontWeight],
|
|
||||||
[fontWeight, chartFontWeightMap]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Memoize Chart Font Style
|
|
||||||
const chartFontStyle = useMemo(
|
const chartFontStyle = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
family: fontFamily || "Arial",
|
family: fontFamily || "Arial",
|
||||||
@@ -48,6 +80,7 @@ const PolarAreaGraphComponent = ({
|
|||||||
[fontFamily, fontSizeValue, fontWeightValue]
|
[fontFamily, fontSizeValue, fontWeightValue]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Memoize Chart Options
|
||||||
const options = useMemo(
|
const options = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
responsive: true,
|
responsive: true,
|
||||||
@@ -55,7 +88,7 @@ const PolarAreaGraphComponent = ({
|
|||||||
plugins: {
|
plugins: {
|
||||||
title: {
|
title: {
|
||||||
display: true,
|
display: true,
|
||||||
text: title,
|
text: name,
|
||||||
font: chartFontStyle,
|
font: chartFontStyle,
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
@@ -63,31 +96,94 @@ const PolarAreaGraphComponent = ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
scales: {
|
scales: {
|
||||||
x: {
|
// x: {
|
||||||
ticks: {
|
// ticks: {
|
||||||
display: false, // This hides the x-axis labels
|
// display: true, // This hides the x-axis labels
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
[title, chartFontStyle]
|
[title, chartFontStyle, name]
|
||||||
);
|
);
|
||||||
|
|
||||||
const chartData = {
|
// useEffect(() => {console.log(measurements);
|
||||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
// },[measurements])
|
||||||
datasets: [
|
|
||||||
{
|
useEffect(() => {
|
||||||
label: "My First Dataset",
|
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
|
||||||
data: [65, 59, 80, 81, 56, 55, 40],
|
|
||||||
backgroundColor: "#6f42c1", // Updated to #6f42c1 (Purple)
|
const socket = io(`http://${iotApiUrl}`);
|
||||||
borderColor: "#ffffff", // Keeping border color white
|
|
||||||
borderWidth: 2,
|
const inputData = {
|
||||||
fill: false,
|
measurements,
|
||||||
},
|
duration,
|
||||||
],
|
interval: 1000,
|
||||||
};
|
};
|
||||||
|
|
||||||
return <PolarArea data={chartData} options={options} />;
|
|
||||||
|
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",
|
||||||
|
borderColor: "#b392f0",
|
||||||
|
borderWidth: 1,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
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/WidgetData/${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 <PolarArea data={Object.keys(measurements).length > 0 ? chartData : defaultData} options={options} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PolarAreaGraphComponent;
|
export default PolarAreaGraphComponent;
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
type Props = {}
|
||||||
|
|
||||||
|
const FleetEfficiencyComponent = ({
|
||||||
|
object
|
||||||
|
}: any) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h2 className="header">Fleet Efficiency</h2>
|
||||||
|
<div className="progressContainer">
|
||||||
|
<div className="progress">
|
||||||
|
<div className="barOverflow">
|
||||||
|
<div
|
||||||
|
className="bar"
|
||||||
|
style={{ transform: `rotate(${object.value}deg)` }}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="scaleLabels">
|
||||||
|
<span>0%</span>
|
||||||
|
<div className="centerText">
|
||||||
|
<div className="percentage">{object.per}%</div>
|
||||||
|
<div className="status">Optimal</div>
|
||||||
|
</div>
|
||||||
|
<span>100%</span>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FleetEfficiencyComponent
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { WalletIcon } from '../../../icons/3dChartIcons'
|
||||||
|
import { useWidgetStore } from '../../../../store/useWidgetStore';
|
||||||
|
|
||||||
|
const TotalCardComponent = ({
|
||||||
|
object
|
||||||
|
}: any) => {
|
||||||
|
|
||||||
|
const { setSelectedChartId } =
|
||||||
|
useWidgetStore();
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="header-wrapper" onClick={() => {
|
||||||
|
setSelectedChartId(object.id)
|
||||||
|
}}>
|
||||||
|
<div className="header">{object.header}</div>
|
||||||
|
<div className="data-values">
|
||||||
|
<div className="value">{object.value}</div>
|
||||||
|
<div className="per">{object.per}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="icon">
|
||||||
|
<WalletIcon />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TotalCardComponent
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
import React, { useState } from 'react'
|
||||||
|
import { Line } from 'react-chartjs-2'
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const WarehouseThroughputComponent = ({
|
||||||
|
object
|
||||||
|
}: any) => {
|
||||||
|
|
||||||
|
const [measurements, setmeasurements] = useState<any>({});
|
||||||
|
const [duration, setDuration] = useState("1h")
|
||||||
|
|
||||||
|
const lineGraphData = {
|
||||||
|
labels: [
|
||||||
|
"Jan",
|
||||||
|
"Feb",
|
||||||
|
"Mar",
|
||||||
|
"Apr",
|
||||||
|
"May",
|
||||||
|
"Jun",
|
||||||
|
"Jul",
|
||||||
|
"Aug",
|
||||||
|
"Sep",
|
||||||
|
"Oct",
|
||||||
|
"Nov",
|
||||||
|
"Dec",
|
||||||
|
], // Months of the year
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Throughput (units/month)",
|
||||||
|
data: [500, 400, 300, 450, 350, 250, 200, 300, 250, 150, 100, 150], // Example monthly data
|
||||||
|
borderColor: "#6f42c1", // Use the desired color for the line (purple)
|
||||||
|
backgroundColor: "rgba(111, 66, 193, 0.2)", // Use a semi-transparent purple for the fill
|
||||||
|
borderWidth: 2, // Line thickness
|
||||||
|
fill: true, // Enable fill for this dataset
|
||||||
|
pointRadius: 0, // Remove dots at each data point
|
||||||
|
tension: 0.5, // Smooth interpolation for the line
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// Line graph options
|
||||||
|
const lineGraphOptions = {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false, // Allow custom height/width adjustments
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: false, // Hide legend
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: false, // No chart title needed
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
callbacks: {
|
||||||
|
label: (context: any) => {
|
||||||
|
const value = context.parsed.y;
|
||||||
|
return `${value} units`; // Customize tooltip to display "units"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
grid: {
|
||||||
|
display: false, // Hide x-axis grid lines
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
maxRotation: 0, // Prevent label rotation
|
||||||
|
autoSkip: false, // Display all months
|
||||||
|
font: {
|
||||||
|
size: 8, // Adjust font size for readability
|
||||||
|
color: "#ffffff", // Light text color for labels
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
display: true, // Show y-axis
|
||||||
|
grid: {
|
||||||
|
drawBorder: false, // Remove border line
|
||||||
|
color: "rgba(255, 255, 255, 0.2)", // Light gray color for grid lines
|
||||||
|
borderDash: [5, 5], // Dotted line style (array defines dash and gap lengths)
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
font: {
|
||||||
|
size: 8, // Adjust font size for readability
|
||||||
|
color: "#ffffff", // Light text color for ticks
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
elements: {
|
||||||
|
line: {
|
||||||
|
tension: 0.5, // Smooth interpolation for the line
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// const fetchSavedInputes = async() => {
|
||||||
|
|
||||||
|
// if (object.id !== "") {
|
||||||
|
// try {
|
||||||
|
// const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_LOCAL_BASE_URL}/api/v2/WidgetData/${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);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="header">
|
||||||
|
<h2>Warehouse Throughput</h2>
|
||||||
|
<p>
|
||||||
|
<span>(+5) more</span> in 2025
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="lineGraph" style={{ height: "100%" }}>
|
||||||
|
<Line data={lineGraphData} options={lineGraphOptions} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WarehouseThroughputComponent
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
|
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
|
||||||
|
console.log("url_Backend_dwinzo: ", url_Backend_dwinzo);
|
||||||
|
|
||||||
export const getSelect2dZoneData = async (
|
export const getSelect2dZoneData = async (
|
||||||
ZoneId?: string,
|
ZoneId?: string,
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ export const getZoneData = async (zoneId: string, organization: string) => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error("Failed to fetch zoneData");
|
throw new Error("Failed to fetch zoneData");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,20 +9,26 @@ interface MeasurementStore {
|
|||||||
measurements: Record<string, Measurement>; // Change array to Record<string, Measurement>
|
measurements: Record<string, Measurement>; // Change array to Record<string, Measurement>
|
||||||
interval: number;
|
interval: number;
|
||||||
duration: string;
|
duration: string;
|
||||||
|
name: string;
|
||||||
setMeasurements: (newMeasurements: Record<string, Measurement>) => void;
|
setMeasurements: (newMeasurements: Record<string, Measurement>) => void;
|
||||||
updateDuration: (newDuration: string) => void;
|
updateDuration: (newDuration: string) => void;
|
||||||
|
updateName: (newName: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useChartStore = create<MeasurementStore>((set) => ({
|
const useChartStore = create<MeasurementStore>((set) => ({
|
||||||
measurements: {}, // Initialize as an empty object
|
measurements: {}, // Initialize as an empty object
|
||||||
interval: 1000,
|
interval: 1000,
|
||||||
duration: "1h",
|
duration: "1h",
|
||||||
|
name:'',
|
||||||
|
|
||||||
setMeasurements: (newMeasurements) =>
|
setMeasurements: (newMeasurements) =>
|
||||||
set(() => ({ measurements: newMeasurements })),
|
set(() => ({ measurements: newMeasurements })),
|
||||||
|
|
||||||
updateDuration: (newDuration) =>
|
updateDuration: (newDuration) =>
|
||||||
set(() => ({ duration: newDuration })),
|
set(() => ({ duration: newDuration })),
|
||||||
|
|
||||||
|
updateName: (newName) =>
|
||||||
|
set(() => ({ duration: newName })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export default useChartStore;
|
export default useChartStore;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ interface WidgetStore {
|
|||||||
setDraggedAsset: (asset: Widget | null) => void; // Setter for draggedAsset
|
setDraggedAsset: (asset: Widget | null) => void; // Setter for draggedAsset
|
||||||
addWidget: (widget: Widget) => void; // Add a new widget
|
addWidget: (widget: Widget) => void; // Add a new widget
|
||||||
setWidgets: (widgets: Widget[]) => void; // Replace the entire widgets array
|
setWidgets: (widgets: Widget[]) => void; // Replace the entire widgets array
|
||||||
setSelectedChartId: (widget: Widget | null) => void; // Set the selected chart/widget
|
setSelectedChartId: (widget: any | null) => void; // Set the selected chart/widget
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the store with Zustand
|
// Create the store with Zustand
|
||||||
|
|||||||
@@ -318,6 +318,25 @@
|
|||||||
|
|
||||||
.sidebar-right-content-container {
|
.sidebar-right-content-container {
|
||||||
.dataSideBar {
|
.dataSideBar {
|
||||||
|
.inputs-wrapper {
|
||||||
|
.datas {
|
||||||
|
|
||||||
|
.input-value {
|
||||||
|
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-value,
|
||||||
|
.rename-input {
|
||||||
|
margin-right: 24px;
|
||||||
|
width: 170px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -991,11 +1010,9 @@
|
|||||||
top: 50%;
|
top: 50%;
|
||||||
right: -10px;
|
right: -10px;
|
||||||
transform: translate(0, -50%);
|
transform: translate(0, -50%);
|
||||||
background: linear-gradient(
|
background: linear-gradient(144.19deg,
|
||||||
144.19deg,
|
|
||||||
#f1e7cd 16.62%,
|
#f1e7cd 16.62%,
|
||||||
#fffaef 85.81%
|
#fffaef 85.81%);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-image {
|
.category-image {
|
||||||
|
|||||||
Reference in New Issue
Block a user