merge conflicts resolved
This commit is contained in:
20
app/package-lock.json
generated
20
app/package-lock.json
generated
@@ -47,6 +47,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.9.1",
|
"@types/node": "^22.9.1",
|
||||||
"@types/three": "^0.169.0",
|
"@types/three": "^0.169.0",
|
||||||
|
"axios": "^1.8.4",
|
||||||
"cypress": "^13.14.2",
|
"cypress": "^13.14.2",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"husky": "^9.1.6",
|
"husky": "^9.1.6",
|
||||||
@@ -7672,6 +7673,25 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/axios": {
|
||||||
|
"version": "1.8.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz",
|
||||||
|
"integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"follow-redirects": "^1.15.6",
|
||||||
|
"form-data": "^4.0.0",
|
||||||
|
"proxy-from-env": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/axios/node_modules/proxy-from-env": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/axobject-query": {
|
"node_modules/axobject-query": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
||||||
|
|||||||
@@ -69,6 +69,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.9.1",
|
"@types/node": "^22.9.1",
|
||||||
"@types/three": "^0.169.0",
|
"@types/three": "^0.169.0",
|
||||||
|
"axios": "^1.8.4",
|
||||||
"cypress": "^13.14.2",
|
"cypress": "^13.14.2",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"husky": "^9.1.6",
|
"husky": "^9.1.6",
|
||||||
|
|||||||
@@ -130,3 +130,24 @@ export function StarsIconSmall() {
|
|||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function FiileedStarsIconSmall() {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="11"
|
||||||
|
height="12"
|
||||||
|
viewBox="0 0 11 12"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M5.07372 1.61354C5.20877 1.31056 5.27632 1.15908 5.37035 1.11243C5.45202 1.0719 5.54791 1.0719 5.62958 1.11243C5.72362 1.15908 5.79117 1.31056 5.92621 1.61354L7.00187 4.02675C7.04183 4.11631 7.06178 4.16109 7.0927 4.19539C7.12 4.22573 7.15342 4.25 7.1907 4.26662C7.23287 4.2854 7.28164 4.29055 7.37917 4.30084L10.0067 4.57816C10.3366 4.61297 10.5015 4.63038 10.5749 4.70539C10.6387 4.77054 10.6683 4.86177 10.655 4.95198C10.6397 5.05581 10.5165 5.16682 10.2701 5.3889L8.30737 7.15768C8.23457 7.22331 8.19811 7.25615 8.17507 7.29611C8.15466 7.33152 8.14188 7.37077 8.13762 7.41137C8.13278 7.45728 8.14293 7.50523 8.16329 7.60119L8.71151 10.1858C8.78034 10.5103 8.81476 10.6725 8.76611 10.7655C8.72381 10.8463 8.64623 10.9027 8.55634 10.9179C8.45286 10.9354 8.30918 10.8526 8.02183 10.6868L5.73312 9.36677C5.64819 9.31777 5.60572 9.29332 5.56057 9.2837C5.52062 9.27524 5.47931 9.27524 5.43936 9.2837C5.39421 9.29332 5.35174 9.31777 5.26681 9.36677L2.97811 10.6868C2.69077 10.8526 2.5471 10.9354 2.44361 10.9179C2.35372 10.9027 2.27611 10.8463 2.23385 10.7655C2.18521 10.6725 2.21962 10.5103 2.28845 10.1858L2.83664 7.60119C2.85699 7.50523 2.86716 7.45728 2.86233 7.41137C2.85805 7.37077 2.8453 7.33152 2.82488 7.29611C2.80181 7.25615 2.76539 7.22331 2.69254 7.15768L0.72985 5.3889C0.483444 5.16682 0.360238 5.05581 0.34492 4.95198C0.33162 4.86177 0.361259 4.77054 0.425041 4.70539C0.498471 4.63038 0.663408 4.61297 0.993283 4.57816L3.62079 4.30084C3.71831 4.29055 3.76706 4.2854 3.80923 4.26662C3.84653 4.25 3.87993 4.22573 3.90727 4.19539C3.93815 4.16109 3.95812 4.11631 3.99804 4.02675L5.07372 1.61354Z"
|
||||||
|
fill="#F3A50C"
|
||||||
|
stroke="#F3A50C"
|
||||||
|
stroke-width="0.7"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ const Outline: React.FC = () => {
|
|||||||
defaultOpen={true}
|
defaultOpen={true}
|
||||||
showKebabMenu={false}
|
showKebabMenu={false}
|
||||||
showFocusIcon={true}
|
showFocusIcon={true}
|
||||||
|
remove
|
||||||
/>
|
/>
|
||||||
<DropDownList
|
<DropDownList
|
||||||
value="Scene"
|
value="Scene"
|
||||||
|
|||||||
@@ -12,16 +12,15 @@ import {
|
|||||||
import useToggleStore from "../../../store/useUIToggleStore";
|
import useToggleStore from "../../../store/useUIToggleStore";
|
||||||
import MachineMechanics from "./mechanics/MachineMechanics";
|
import MachineMechanics from "./mechanics/MachineMechanics";
|
||||||
import Visualization from "./visualization/Visualization";
|
import Visualization from "./visualization/Visualization";
|
||||||
import GlobalProperties from "./properties/GlobalProperties";
|
|
||||||
import AsstePropertiies from "./properties/AssetProperties";
|
|
||||||
import Analysis from "./analysis/Analysis";
|
import Analysis from "./analysis/Analysis";
|
||||||
import Simulations from "./simulation/Simulations";
|
import Simulations from "./simulation/Simulations";
|
||||||
import { useSelectedActionSphere } from "../../../store/store";
|
import { useSelectedActionSphere } from "../../../store/store";
|
||||||
|
import GlobalProperties from "./properties/GlobalProperties";
|
||||||
|
import AsstePropertiies from "./properties/AssetProperties";
|
||||||
import ZoneProperties from "./properties/ZoneProperties";
|
import ZoneProperties from "./properties/ZoneProperties";
|
||||||
|
|
||||||
const SideBarRight: React.FC = () => {
|
const SideBarRight: React.FC = () => {
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
const [activeList] = useState("properties");
|
|
||||||
const { toggleUI } = useToggleStore();
|
const { toggleUI } = useToggleStore();
|
||||||
const { selectedActionSphere } = useSelectedActionSphere();
|
const { selectedActionSphere } = useSelectedActionSphere();
|
||||||
const { subModule, setSubModule } = useSubModuleStore();
|
const { subModule, setSubModule } = useSubModuleStore();
|
||||||
@@ -38,8 +37,7 @@ const SideBarRight: React.FC = () => {
|
|||||||
<div className="sidebar-actions-container">
|
<div className="sidebar-actions-container">
|
||||||
{/* {activeModule === "builder" && ( */}
|
{/* {activeModule === "builder" && ( */}
|
||||||
<div
|
<div
|
||||||
className={`sidebar-action-list ${
|
className={`sidebar-action-list ${subModule === "properties" ? "active" : ""
|
||||||
subModule === "properties" ? "active" : ""
|
|
||||||
}`}
|
}`}
|
||||||
onClick={() => setSubModule("properties")}
|
onClick={() => setSubModule("properties")}
|
||||||
>
|
>
|
||||||
@@ -49,28 +47,25 @@ const SideBarRight: React.FC = () => {
|
|||||||
{activeModule === "simulation" && (
|
{activeModule === "simulation" && (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
className={`sidebar-action-list ${
|
className={`sidebar-action-list ${subModule === "mechanics" ? "active" : ""
|
||||||
subModule === "mechanics" ? "active" : ""
|
|
||||||
}`}
|
}`}
|
||||||
onClick={() => setSubModule("mechanics")}
|
onClick={() => setSubModule("mechanics")}
|
||||||
>
|
>
|
||||||
<MechanicsIcon isActive={activeList === "mechanics"} />
|
<MechanicsIcon isActive={subModule === "mechanics"} />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`sidebar-action-list ${
|
className={`sidebar-action-list ${subModule === "simulations" ? "active" : ""
|
||||||
subModule === "simulations" ? "active" : ""
|
|
||||||
}`}
|
}`}
|
||||||
onClick={() => setSubModule("simulations")}
|
onClick={() => setSubModule("simulations")}
|
||||||
>
|
>
|
||||||
<SimulationIcon isActive={activeList === "simulations"} />
|
<SimulationIcon isActive={subModule === "simulations"} />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`sidebar-action-list ${
|
className={`sidebar-action-list ${subModule === "analysis" ? "active" : ""
|
||||||
subModule === "analysis" ? "active" : ""
|
|
||||||
}`}
|
}`}
|
||||||
onClick={() => setSubModule("analysis")}
|
onClick={() => setSubModule("analysis")}
|
||||||
>
|
>
|
||||||
<AnalysisIcon isActive={activeList === "analysis"} />
|
<AnalysisIcon isActive={subModule === "analysis"} />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@@ -78,7 +73,7 @@ const SideBarRight: React.FC = () => {
|
|||||||
)}
|
)}
|
||||||
{/* process builder */}
|
{/* process builder */}
|
||||||
{toggleUI &&
|
{toggleUI &&
|
||||||
activeList === "properties" &&
|
subModule === "properties" &&
|
||||||
activeModule !== "visualization" && (
|
activeModule !== "visualization" && (
|
||||||
<div className="sidebar-right-container">
|
<div className="sidebar-right-container">
|
||||||
<div className="sidebar-right-content-container">
|
<div className="sidebar-right-content-container">
|
||||||
@@ -88,7 +83,17 @@ const SideBarRight: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{toggleUI &&
|
||||||
|
subModule === "zoneProperties" &&
|
||||||
|
activeModule === "builder" && (
|
||||||
|
<div className="sidebar-right-container">
|
||||||
|
<div className="sidebar-right-content-container">
|
||||||
|
{/* <GlobalProperties /> */}
|
||||||
|
<ZoneProperties />
|
||||||
|
{/* <AsstePropertiies /> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{/* simulation */}
|
{/* simulation */}
|
||||||
|
|
||||||
{toggleUI && activeModule === "simulation" && (
|
{toggleUI && activeModule === "simulation" && (
|
||||||
@@ -114,7 +119,7 @@ const SideBarRight: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{activeList === "simulations" && (
|
{subModule === "simulations" && (
|
||||||
<div className="sidebar-right-container">
|
<div className="sidebar-right-container">
|
||||||
<div className="sidebar-right-content-container">
|
<div className="sidebar-right-content-container">
|
||||||
<Simulations />
|
<Simulations />
|
||||||
|
|||||||
@@ -1,59 +1,54 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { EyeDroperIcon } from "../../../icons/ExportCommonIcons";
|
import { EyeDroperIcon } from "../../../icons/ExportCommonIcons";
|
||||||
|
// import { useThree } from "@react-three/fiber";
|
||||||
|
|
||||||
interface PositionInputProps {
|
interface PositionInputProps {
|
||||||
onChange: (value: string) => void; // Callback for value change
|
onChange: (value: [number, number, number]) => void; // Callback for value change
|
||||||
header: string;
|
header: string;
|
||||||
placeholder?: string; // Optional placeholder
|
placeholder?: string; // Optional placeholder
|
||||||
type?: string; // Input type (e.g., text, number, email)
|
type?: string; // Input type (e.g., text, number, email)
|
||||||
|
value: [number, number, number] | null;
|
||||||
|
disabled?: boolean; // To enable/disable editing
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vector3Input: React.FC<PositionInputProps> = ({
|
const Vector3Input: React.FC<PositionInputProps> = ({
|
||||||
onChange,
|
onChange,
|
||||||
header,
|
header,
|
||||||
placeholder = "Enter value", // Default placeholder
|
placeholder = "Enter value", // Default placeholder
|
||||||
type = "number", // Default type
|
type = "string", // Default type
|
||||||
|
value,
|
||||||
|
disabled = false, // Default to disabled
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
|
const handleChange = (index: number, newValue: string) => {
|
||||||
|
if (!value) return;
|
||||||
|
const updatedValue = [...value] as [number, number, number];
|
||||||
|
updatedValue[index] = parseFloat(newValue) || 0;
|
||||||
|
console.log('updatedValue: ', updatedValue);
|
||||||
|
onChange(updatedValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="custom-input-container">
|
<div className="custom-input-container">
|
||||||
<div className="header">
|
<div className="header">
|
||||||
{header}{" "}
|
{header}
|
||||||
<div className="eyedrop-button">
|
|
||||||
<EyeDroperIcon isActive={false} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="inputs-container">
|
<div className="inputs-container">
|
||||||
<div className="input-container">
|
{["X", "Y", "Z"].map((axis, i) => (
|
||||||
<div className="custom-input-label">X : </div>
|
<div className="input-container" key={axis}>
|
||||||
|
<div className="custom-input-label">{axis}:</div>
|
||||||
<input
|
<input
|
||||||
className="custom-input-field"
|
className="custom-input-field"
|
||||||
type={type}
|
type={type}
|
||||||
onChange={(e) => onChange(e.target.value)}
|
value={value?.[i] !== undefined ? value[i].toFixed(2) : ""}
|
||||||
|
// onChange={(e) => handleChange(i, e.target.value)}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
disabled
|
disabled={disabled}
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="input-container">
|
|
||||||
<div className="custom-input-label">Y : </div>
|
|
||||||
<input
|
|
||||||
className="custom-input-field"
|
|
||||||
type={type}
|
|
||||||
onChange={(e) => onChange(e.target.value)}
|
|
||||||
placeholder={placeholder}
|
|
||||||
disabled
|
|
||||||
min={0}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="input-container">
|
|
||||||
<div className="custom-input-label">Z : </div>
|
|
||||||
<input
|
|
||||||
className="custom-input-field"
|
|
||||||
type={type}
|
|
||||||
onChange={(e) => onChange(e.target.value)}
|
|
||||||
placeholder={placeholder}
|
|
||||||
disabled
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,32 +1,65 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import RenameInput from "../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../ui/inputs/RenameInput";
|
||||||
import Vector3Input from "../customInput/Vector3Input";
|
import Vector3Input from "../customInput/Vector3Input";
|
||||||
|
import { useSelectedZoneStore } from "../../../../store/useZoneStore";
|
||||||
|
import { useEditPosition, usezonePosition, usezoneTarget } from "../../../../store/store";
|
||||||
|
|
||||||
const ZoneProperties: React.FC = () => {
|
const ZoneProperties: React.FC = () => {
|
||||||
const [Edit, setEdit] = useState(false);
|
const { Edit, setEdit } = useEditPosition();
|
||||||
|
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
||||||
|
const { zonePosition, setZonePosition } = usezonePosition();
|
||||||
|
const { zoneTarget, setZoneTarget } = usezoneTarget();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setZonePosition(selectedZone.zoneViewPortPosition)
|
||||||
|
setZoneTarget(selectedZone.zoneViewPortTarget)
|
||||||
|
}, [selectedZone?.zoneViewPortPosition, selectedZone?.zoneViewPortTarget])
|
||||||
|
|
||||||
function handleSetView() {
|
function handleSetView() {
|
||||||
|
console.log("setApi");
|
||||||
|
|
||||||
|
console.log('zoneTarget: ', zoneTarget);
|
||||||
|
console.log('zonePosition: ', zonePosition);
|
||||||
setEdit(false);
|
setEdit(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleEditView() {
|
function handleEditView() {
|
||||||
if (Edit) {
|
setEdit(!Edit); // This will toggle the `Edit` state correctly
|
||||||
setEdit(false);
|
|
||||||
} else {
|
|
||||||
setEdit(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleZoneNameChange(newName: string) {
|
||||||
|
setSelectedZone((prev) => ({ ...prev, zoneName: newName }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleVectorChange(key: "zoneViewPortTarget" | "zoneViewPortPosition", newValue: [number, number, number]) {
|
||||||
|
setSelectedZone((prev) => ({ ...prev, [key]: newValue }));
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("Updated selectedZone: ", selectedZone);
|
||||||
|
}, [selectedZone]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="zone-properties-container">
|
<div className="zone-properties-container">
|
||||||
<div className="header">
|
<div className="header">
|
||||||
<RenameInput value="Selected Zone Name" />
|
<RenameInput value={selectedZone.zoneName} onRename={handleZoneNameChange} />
|
||||||
<div className="button" onClick={handleEditView}>
|
<div className="button" onClick={handleEditView}>
|
||||||
{Edit ? "Cancel" : "Edit"}
|
{Edit ? "Cancel" : "Edit"}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Vector3Input onChange={() => {}} header="Viewport Target" />
|
<Vector3Input
|
||||||
<Vector3Input onChange={() => {}} header="Viewport Position" />
|
onChange={(value) => handleVectorChange("zoneViewPortTarget", value)}
|
||||||
|
header="Viewport Target"
|
||||||
|
value={zoneTarget as [number, number, number]}
|
||||||
|
disabled={!Edit}
|
||||||
|
/>
|
||||||
|
<Vector3Input
|
||||||
|
onChange={(value) => handleVectorChange("zoneViewPortPosition", value)}
|
||||||
|
header="Viewport Position"
|
||||||
|
value={zonePosition as [number, number, number]}
|
||||||
|
disabled={!Edit}
|
||||||
|
/>
|
||||||
|
|
||||||
{Edit && (
|
{Edit && (
|
||||||
<div className="button-save" onClick={handleSetView}>
|
<div className="button-save" onClick={handleSetView}>
|
||||||
Set View
|
Set View
|
||||||
@@ -37,3 +70,4 @@ const ZoneProperties: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default ZoneProperties;
|
export default ZoneProperties;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
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 axios from 'axios'
|
||||||
|
|
||||||
|
type Props = {}
|
||||||
|
|
||||||
|
const LineGrapInput = (props: Props) => {
|
||||||
|
const [dropDowndata, setDropDownData] = useState({})
|
||||||
|
const [selections, setSelections] = useState<Record<string, { name: string, fields: string }>>({})
|
||||||
|
const [selectedOption, setSelectedOption] = useState('1h')
|
||||||
|
const { measurements, setMeasurements, updateDuration, duration } = useChartStore();
|
||||||
|
|
||||||
|
const handleSelectDuration = (option: string) => {
|
||||||
|
updateDuration(option); // Normalize for key matching
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchZoneData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get('http://192.168.0.192:5010/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(() => {
|
||||||
|
console.log(selections);
|
||||||
|
}, [selections])
|
||||||
|
|
||||||
|
const handleSelect = (inputKey: string, selectedData: { name: string, fields: string } | null) => {
|
||||||
|
setSelections(prev => {
|
||||||
|
if (selectedData === null) {
|
||||||
|
const newSelections = { ...prev };
|
||||||
|
delete newSelections[inputKey];
|
||||||
|
return newSelections;
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
[inputKey]: selectedData
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
interface Measurement {
|
||||||
|
name: string;
|
||||||
|
fields: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface InputData {
|
||||||
|
[key: string]: Measurement;
|
||||||
|
}
|
||||||
|
|
||||||
|
const extractMeasurements = (input: InputData): Measurement[] => {
|
||||||
|
return Object.values(input);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const measurementsData = extractMeasurements(selections);
|
||||||
|
setMeasurements(measurementsData);
|
||||||
|
}, [selections]);
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="inputs-wrapper">
|
||||||
|
{[...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]}
|
||||||
|
/>
|
||||||
|
<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 LineGrapInput
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import MultiLevelDropdown from '../../../../ui/inputs/MultiLevelDropDown'
|
||||||
|
import { AddIcon } from '../../../../icons/ExportCommonIcons'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
type Props = {}
|
||||||
|
|
||||||
|
const PieChartInput = (props: Props) => {
|
||||||
|
const [dropDowndata, setDropDownData] = useState({})
|
||||||
|
const [selections, setSelections] = useState<Record<string, {name: string, fields: string}>>({})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchZoneData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get('http://192.168.0.192:5010/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(() => {console.log(selections);
|
||||||
|
},[selections])
|
||||||
|
|
||||||
|
const handleSelect = (inputKey: string, selectedData: {name: string, fields: string} | null) => {
|
||||||
|
setSelections(prev => {
|
||||||
|
if (selectedData === null) {
|
||||||
|
const newSelections = {...prev};
|
||||||
|
delete newSelections[inputKey];
|
||||||
|
return newSelections;
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
[inputKey]: selectedData
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="inputs-wrapper">
|
||||||
|
{[...Array(3)].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]}
|
||||||
|
/>
|
||||||
|
<div className="icon">
|
||||||
|
<AddIcon />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PieChartInput
|
||||||
@@ -2,6 +2,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
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";
|
||||||
|
|
||||||
// Define the data structure for demonstration purposes
|
// Define the data structure for demonstration purposes
|
||||||
const DATA_STRUCTURE = {
|
const DATA_STRUCTURE = {
|
||||||
@@ -123,40 +124,9 @@ const Data = () => {
|
|||||||
<div className="sideBarHeader">{selectedChartId?.title}</div>
|
<div className="sideBarHeader">{selectedChartId?.title}</div>
|
||||||
)}
|
)}
|
||||||
{/* Render groups dynamically */}
|
{/* Render groups dynamically */}
|
||||||
{chartDataGroups[selectedChartId?.id]?.map((group) => (
|
{
|
||||||
<div key={group.id} className="inputs-wrapper">
|
chartDataGroups[selectedChartId?.id] && <LineGrapInput />
|
||||||
{group.children.map((child, index) => (
|
}
|
||||||
<div key={child.id} className="datas">
|
|
||||||
<div className="datas__label">Input {index + 1}</div>
|
|
||||||
<div className="datas__class">
|
|
||||||
<MultiLevelDropDown data={DATA_STRUCTURE} />
|
|
||||||
{/* Add Icon */}
|
|
||||||
{group.children.length < 7 && (
|
|
||||||
<div
|
|
||||||
className="icon"
|
|
||||||
onClick={() => handleAddClick(group.id)} // Pass groupId to handleAddClick
|
|
||||||
>
|
|
||||||
<AddIcon />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{/* Remove Icon */}
|
|
||||||
|
|
||||||
<span
|
|
||||||
className={`datas__separator ${
|
|
||||||
group.children.length > 1 ? "" : "disable"
|
|
||||||
}`}
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation(); // Prevent event bubbling
|
|
||||||
removeChild(group.id, child.id); // Pass groupId and childId to removeChild
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<RemoveIcon />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{/* Info Box */}
|
{/* Info Box */}
|
||||||
<div className="infoBox">
|
<div className="infoBox">
|
||||||
@@ -173,3 +143,40 @@ const Data = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default Data;
|
export default Data;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// {chartDataGroups[selectedChartId?.id]?.map((group) => (
|
||||||
|
// <div key={group.id} className="inputs-wrapper">
|
||||||
|
// {group.children.map((child, index) => (
|
||||||
|
// <div key={child.id} className="datas">
|
||||||
|
// <div className="datas__label">Input {index + 1}</div>
|
||||||
|
// <div className="datas__class">
|
||||||
|
// <MultiLevelDropDown data={DATA_STRUCTURE} />
|
||||||
|
// {/* Add Icon */}
|
||||||
|
// {group.children.length < 7 && (
|
||||||
|
// <div
|
||||||
|
// className="icon"
|
||||||
|
// onClick={() => handleAddClick(group.id)} // Pass groupId to handleAddClick
|
||||||
|
// >
|
||||||
|
// <AddIcon />
|
||||||
|
// </div>
|
||||||
|
// )}
|
||||||
|
// {/* Remove Icon */}
|
||||||
|
|
||||||
|
// <span
|
||||||
|
// className={`datas__separator ${
|
||||||
|
// group.children.length > 1 ? "" : "disable"
|
||||||
|
// }`}
|
||||||
|
// onClick={(e) => {
|
||||||
|
// e.stopPropagation(); // Prevent event bubbling
|
||||||
|
// removeChild(group.id, child.id); // Pass groupId and childId to removeChild
|
||||||
|
// }}
|
||||||
|
// >
|
||||||
|
// <RemoveIcon />
|
||||||
|
// </span>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// ))}
|
||||||
|
// </div>
|
||||||
|
// ))}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
EyeIcon,
|
EyeIcon,
|
||||||
LockIcon,
|
LockIcon,
|
||||||
} from "../../icons/RealTimeVisulationIcons";
|
} from "../../icons/RealTimeVisulationIcons";
|
||||||
|
import { panelData } from "../../../services/realTimeVisulization/zoneData/panel";
|
||||||
|
|
||||||
// Define the type for `Side`
|
// Define the type for `Side`
|
||||||
type Side = "top" | "bottom" | "left" | "right";
|
type Side = "top" | "bottom" | "left" | "right";
|
||||||
@@ -15,6 +16,9 @@ interface ButtonsProps {
|
|||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
|
zoneId: string;
|
||||||
|
zoneViewPortTarget: number[];
|
||||||
|
zoneViewPortPosition: number[]
|
||||||
widgets: {
|
widgets: {
|
||||||
id: string;
|
id: string;
|
||||||
type: string;
|
type: string;
|
||||||
@@ -29,6 +33,9 @@ interface ButtonsProps {
|
|||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
|
zoneId: string;
|
||||||
|
zoneViewPortTarget: number[];
|
||||||
|
zoneViewPortPosition: number[]
|
||||||
widgets: {
|
widgets: {
|
||||||
id: string;
|
id: string;
|
||||||
type: string;
|
type: string;
|
||||||
@@ -108,7 +115,7 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
|||||||
panelOrder: newActiveSides,
|
panelOrder: newActiveSides,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update the selectedZone state
|
// Delete the selectedZone state
|
||||||
console.log('updatedZone: ', updatedZone);
|
console.log('updatedZone: ', updatedZone);
|
||||||
setSelectedZone(updatedZone);
|
setSelectedZone(updatedZone);
|
||||||
} else {
|
} else {
|
||||||
@@ -120,17 +127,23 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
|||||||
activeSides: newActiveSides,
|
activeSides: newActiveSides,
|
||||||
panelOrder: newActiveSides,
|
panelOrder: newActiveSides,
|
||||||
};
|
};
|
||||||
|
const email = localStorage.getItem('email')
|
||||||
|
const organization = (email!.split("@")[1]).split(".")[0];
|
||||||
|
// let response = panelData(organization, selectedZone.zoneId, newActiveSides)
|
||||||
|
// console.log('response: ', response);
|
||||||
|
|
||||||
// Update the selectedZone state
|
// Update the selectedZone state
|
||||||
console.log('updatedZone: ', updatedZone);
|
console.log("updatedZone: ", updatedZone);
|
||||||
setSelectedZone(updatedZone);
|
setSelectedZone(updatedZone);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<div>
|
<div>
|
||||||
{(["top", "right", "bottom", "left"] as Side[]).map((side) => (
|
{(["top", "right", "bottom", "left"] as Side[]).map((side) => (
|
||||||
<div key={side} className={`side-button-container ${side}`}>
|
<div key={side} className={`side-button-container ${side}`}>
|
||||||
|
{/* "+" Button */}
|
||||||
<button
|
<button
|
||||||
className={`side-button ${side}`}
|
className={`side-button ${side}`}
|
||||||
onClick={() => handlePlusButtonClick(side)}
|
onClick={() => handlePlusButtonClick(side)}
|
||||||
@@ -156,7 +169,11 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
|||||||
onClick={() => toggleVisibility(side)}
|
onClick={() => toggleVisibility(side)}
|
||||||
>
|
>
|
||||||
<EyeIcon
|
<EyeIcon
|
||||||
fill={hiddenPanels.includes(side) ? "white" : "#1D1E21"}
|
fill={
|
||||||
|
hiddenPanels.includes(side)
|
||||||
|
? "white"
|
||||||
|
: "#1D1E21"
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -187,6 +204,7 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ interface DisplayZoneProps {
|
|||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
widgets: Widget[];
|
widgets: Widget[];
|
||||||
|
zoneId: string;
|
||||||
|
zoneViewPortTarget: number[];
|
||||||
|
zoneViewPortPosition: number[];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
selectedZone: {
|
selectedZone: {
|
||||||
@@ -18,6 +21,9 @@ interface DisplayZoneProps {
|
|||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
|
zoneId: string;
|
||||||
|
zoneViewPortTarget: number[];
|
||||||
|
zoneViewPortPosition: number[];
|
||||||
widgets: {
|
widgets: {
|
||||||
id: string;
|
id: string;
|
||||||
type: string;
|
type: string;
|
||||||
@@ -32,6 +38,9 @@ interface DisplayZoneProps {
|
|||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
|
zoneId: string;
|
||||||
|
zoneViewPortTarget: number[];
|
||||||
|
zoneViewPortPosition: number[];
|
||||||
widgets: {
|
widgets: {
|
||||||
id: string;
|
id: string;
|
||||||
type: string;
|
type: string;
|
||||||
@@ -152,7 +161,7 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
className={`zoon-wrapper ${selectedZone.activeSides.includes("bottom") && "bottom"
|
className={`zoon-wrapper ${selectedZone?.activeSides?.includes("bottom") && "bottom"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{Object.keys(zonesData).map((zoneName, index) => (
|
{Object.keys(zonesData).map((zoneName, index) => (
|
||||||
@@ -161,7 +170,7 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
|
|||||||
className={`zone ${selectedZone.zoneName === zoneName ? "active" : ""
|
className={`zone ${selectedZone.zoneName === zoneName ? "active" : ""
|
||||||
}`}
|
}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
console.log('zoneName: ', zoneName);
|
|
||||||
|
|
||||||
setSelectedZone({
|
setSelectedZone({
|
||||||
zoneName,
|
zoneName,
|
||||||
@@ -169,12 +178,15 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
|
|||||||
panelOrder: zonesData[zoneName].panelOrder || [],
|
panelOrder: zonesData[zoneName].panelOrder || [],
|
||||||
lockedPanels: zonesData[zoneName].lockedPanels || [],
|
lockedPanels: zonesData[zoneName].lockedPanels || [],
|
||||||
widgets: zonesData[zoneName].widgets || [],
|
widgets: zonesData[zoneName].widgets || [],
|
||||||
})
|
zoneId: zonesData[zoneName]?.zoneId || "",
|
||||||
|
zoneViewPortTarget: zonesData[zoneName].zoneViewPortTarget || [],
|
||||||
|
zoneViewPortPosition:
|
||||||
|
zonesData[zoneName].zoneViewPortPosition || [],
|
||||||
|
});
|
||||||
// setSelectedZone({
|
// setSelectedZone({
|
||||||
// zoneName,
|
// zoneName,
|
||||||
// ...zonesData[zoneName],
|
// ...zonesData[zoneName],
|
||||||
// });
|
// });
|
||||||
console.log(selectedZone);
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{zoneName}
|
{zoneName}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ export const DraggableWidget = ({
|
|||||||
hiddenPanels: string[]; // Array of hidden panel names
|
hiddenPanels: string[]; // Array of hidden panel names
|
||||||
index: number; onReorder: (fromIndex: number, toIndex: number) => void
|
index: number; onReorder: (fromIndex: number, toIndex: number) => void
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
const { selectedChartId, setSelectedChartId } = useWidgetStore();
|
const { selectedChartId, setSelectedChartId } = useWidgetStore();
|
||||||
|
|
||||||
const handlePointerDown = () => {
|
const handlePointerDown = () => {
|
||||||
|
|||||||
89
app/src/components/ui/componets/DroppedFloatingWidgets.tsx
Normal file
89
app/src/components/ui/componets/DroppedFloatingWidgets.tsx
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
// import { useState } from "react";
|
||||||
|
// import { useThree } from "@react-three/fiber";
|
||||||
|
// import * as THREE from "three";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// const DroppedObjects = () => {
|
||||||
|
// const { camera } = useThree(); // Now inside Canvas ✅
|
||||||
|
// const [objects, setObjects] = useState<{ id: number; position: [number, number, number] }[]>([]);
|
||||||
|
|
||||||
|
// // Function to convert drop event into 3D position
|
||||||
|
// const handleDrop = (event: DragEvent) => {
|
||||||
|
// event.preventDefault();
|
||||||
|
|
||||||
|
// const data = event.dataTransfer?.getData("text/plain");
|
||||||
|
// if (!data) return;
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// const cardData = JSON.parse(data);
|
||||||
|
// if (!cardData.className.includes("floating total-card")) {
|
||||||
|
// console.log("Drop rejected: Incorrect element.");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Convert 2D drop position to 3D world coordinates
|
||||||
|
// const x = (event.clientX / window.innerWidth) * 2 - 1;
|
||||||
|
// const y = -(event.clientY / window.innerHeight) * 2 + 1;
|
||||||
|
|
||||||
|
// // Raycasting to determine the drop position in 3D
|
||||||
|
// const raycaster = new THREE.Raycaster();
|
||||||
|
// const mouseVector = new THREE.Vector2(x, y);
|
||||||
|
// raycaster.setFromCamera(mouseVector, camera);
|
||||||
|
|
||||||
|
// // Intersect with a ground plane (assume y = 0)
|
||||||
|
// const groundPlane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
|
||||||
|
// const intersection = new THREE.Vector3();
|
||||||
|
// raycaster.ray.intersectPlane(groundPlane, intersection);
|
||||||
|
|
||||||
|
// console.log("Spawn Object at:", intersection);
|
||||||
|
|
||||||
|
// // Add the dropped object to the scene state
|
||||||
|
// setObjects((prev) => [...prev, { id: Date.now(), position: [intersection.x, intersection.y, intersection.z] }]);
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("Invalid data:", error);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <group>
|
||||||
|
// {/* Render dropped objects as green boxes */}
|
||||||
|
// {objects.map((obj) => (
|
||||||
|
// <mesh key={obj.id} position={obj.position}>
|
||||||
|
// <boxGeometry args={[1, 1, 1]} />
|
||||||
|
// <meshStandardMaterial color="green" />
|
||||||
|
// </mesh>
|
||||||
|
// ))}
|
||||||
|
// </group>
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
import { Html } from "@react-three/drei";
|
||||||
|
import { useDroppedObjectsStore } from "../../../store/store";
|
||||||
|
|
||||||
|
|
||||||
|
const DroppedObjects: React.FC = () => {
|
||||||
|
const objects = useDroppedObjectsStore((state) => state.objects); // Get objects from Zustand store
|
||||||
|
console.log('objects: ', objects);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{objects.map((obj, index) => (
|
||||||
|
<group key={index} position={[Math.random() * 5, Math.random() * 5, 0]}>
|
||||||
|
<Html wrapperClass={obj.className}>
|
||||||
|
<div style={{ padding: "10px", background: "#fff", borderRadius: "6px" }}>
|
||||||
|
<div className="header">{obj.header}</div>
|
||||||
|
<div className="data-values">
|
||||||
|
<div className="value">{obj.value}</div>
|
||||||
|
<div className="per">{obj.per}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Html>
|
||||||
|
</group>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DroppedObjects;
|
||||||
|
|
||||||
@@ -20,6 +20,9 @@ interface PanelProps {
|
|||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
|
zoneId: string;
|
||||||
|
zoneViewPortTarget: number[];
|
||||||
|
zoneViewPortPosition: number[]
|
||||||
widgets: Widget[];
|
widgets: Widget[];
|
||||||
};
|
};
|
||||||
setSelectedZone: React.Dispatch<
|
setSelectedZone: React.Dispatch<
|
||||||
@@ -28,6 +31,9 @@ interface PanelProps {
|
|||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
|
zoneId: string;
|
||||||
|
zoneViewPortTarget: number[];
|
||||||
|
zoneViewPortPosition: number[]
|
||||||
widgets: Widget[];
|
widgets: Widget[];
|
||||||
}>
|
}>
|
||||||
>;
|
>;
|
||||||
@@ -65,7 +71,7 @@ const Panel: React.FC<PanelProps> = ({
|
|||||||
return {
|
return {
|
||||||
width: `calc(100% - ${(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)
|
width: `calc(100% - ${(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)
|
||||||
}px)`,
|
}px)`,
|
||||||
height: `${panelSize - 5}px`,
|
height: `${panelSize - 2}px`,
|
||||||
left: leftActive ? `${panelSize}px` : "0",
|
left: leftActive ? `${panelSize}px` : "0",
|
||||||
right: rightActive ? `${panelSize}px` : "0",
|
right: rightActive ? `${panelSize}px` : "0",
|
||||||
[side]: "0",
|
[side]: "0",
|
||||||
@@ -73,7 +79,7 @@ const Panel: React.FC<PanelProps> = ({
|
|||||||
case "left":
|
case "left":
|
||||||
case "right":
|
case "right":
|
||||||
return {
|
return {
|
||||||
width: `${panelSize - 5}px`,
|
width: `${panelSize - 2}px`,
|
||||||
height: `calc(100% - ${(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)
|
height: `calc(100% - ${(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)
|
||||||
}px)`,
|
}px)`,
|
||||||
top: topActive ? `${panelSize}px` : "0",
|
top: topActive ? `${panelSize}px` : "0",
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
|||||||
import DisplayZone from "./DisplayZone";
|
import DisplayZone from "./DisplayZone";
|
||||||
import Scene from "../../../modules/scene/scene";
|
import Scene from "../../../modules/scene/scene";
|
||||||
import useModuleStore from "../../../store/useModuleStore";
|
import useModuleStore from "../../../store/useModuleStore";
|
||||||
import { getZonesApi } from "../../../services/realTimeVisulization/zoneData/getZones";
|
import { useDroppedObjectsStore, useZones } from "../../../store/store";
|
||||||
|
import DroppedObjects from "./DroppedFloatingWidgets";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
type Side = "top" | "bottom" | "left" | "right";
|
type Side = "top" | "bottom" | "left" | "right";
|
||||||
@@ -17,7 +19,9 @@ type FormattedZoneData = Record<
|
|||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
zoneCentrePoint: number[];
|
zoneId: string;
|
||||||
|
zoneViewPortTarget: number[];
|
||||||
|
zoneViewPortPosition: number[]
|
||||||
widgets: Widget[];
|
widgets: Widget[];
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
@@ -28,60 +32,39 @@ type Widget = {
|
|||||||
panel: Side;
|
panel: Side;
|
||||||
data: any;
|
data: any;
|
||||||
};
|
};
|
||||||
type Zone = {
|
|
||||||
zoneId: string;
|
|
||||||
zoneName: string;
|
|
||||||
points: number[][];
|
|
||||||
layer: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
const RealTimeVisulization: React.FC = () => {
|
const RealTimeVisulization: React.FC = () => {
|
||||||
const [hiddenPanels, setHiddenPanels] = React.useState<Side[]>([]);
|
const [hiddenPanels, setHiddenPanels] = React.useState<Side[]>([]);
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
|
const [droppedObjects, setDroppedObjects] = useState<any[]>([]);
|
||||||
const [zonesData, setZonesData] = useState<FormattedZoneData>({});
|
const [zonesData, setZonesData] = useState<FormattedZoneData>({});
|
||||||
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
||||||
|
const { zones } = useZones()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function GetZoneData() {
|
const data = Array.isArray(zones) ? zones : [];
|
||||||
try {
|
|
||||||
const response: { data: Zone[] } | undefined = await getZonesApi(
|
|
||||||
"hexrfactory"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!response || !response.data) {
|
const formattedData = data.reduce<FormattedZoneData>((acc, zone) => {
|
||||||
return;
|
|
||||||
}
|
|
||||||
const formattedData = response?.data?.reduce<FormattedZoneData>(
|
|
||||||
(acc, zone) => {
|
|
||||||
acc[zone.zoneName] = {
|
acc[zone.zoneName] = {
|
||||||
activeSides: [],
|
activeSides: [],
|
||||||
panelOrder: [],
|
panelOrder: [],
|
||||||
lockedPanels: [],
|
lockedPanels: [],
|
||||||
zoneCentrePoint: [],
|
zoneId: zone.zoneId,
|
||||||
|
zoneViewPortTarget: zone.viewPortCenter,
|
||||||
|
zoneViewPortPosition: zone.viewPortposition,
|
||||||
widgets: [],
|
widgets: [],
|
||||||
};
|
};
|
||||||
return acc;
|
return acc;
|
||||||
},
|
}, {});
|
||||||
{}
|
|
||||||
);
|
|
||||||
setZonesData(formattedData);
|
setZonesData(formattedData);
|
||||||
} catch (error) { }
|
}, [zones]);
|
||||||
}
|
|
||||||
GetZoneData();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
|
|
||||||
console.log('zonesData: ', zonesData);
|
|
||||||
}, [zonesData]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setZonesData((prev) => {
|
setZonesData((prev) => {
|
||||||
if (!selectedZone) return prev;
|
if (!selectedZone) return prev;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
[selectedZone.zoneName]: {
|
[selectedZone.zoneName]: {
|
||||||
@@ -89,12 +72,46 @@ const RealTimeVisulization: React.FC = () => {
|
|||||||
activeSides: selectedZone.activeSides || [],
|
activeSides: selectedZone.activeSides || [],
|
||||||
panelOrder: selectedZone.panelOrder || [],
|
panelOrder: selectedZone.panelOrder || [],
|
||||||
lockedPanels: selectedZone.lockedPanels || [],
|
lockedPanels: selectedZone.lockedPanels || [],
|
||||||
|
zoneId: selectedZone.zoneId || "",
|
||||||
|
zoneViewPortTarget: selectedZone.zoneViewPortTarget || [],
|
||||||
|
zoneViewPortPosition: selectedZone.zoneViewPortPosition || [],
|
||||||
widgets: selectedZone.widgets || [],
|
widgets: selectedZone.widgets || [],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}, [selectedZone]);
|
}, [selectedZone]);
|
||||||
|
|
||||||
|
// const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {
|
||||||
|
// console.log("Drop event fired! ✅");
|
||||||
|
// event.preventDefault();
|
||||||
|
|
||||||
|
// const data = event.dataTransfer.getData("text/plain");
|
||||||
|
// if (!data) {
|
||||||
|
// console.log("❌ No data received on drop!");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// const droppedData = JSON.parse(data);
|
||||||
|
// console.log("✅ Dropped Data:", droppedData);
|
||||||
|
|
||||||
|
// console.log('droppedData: ', droppedData);
|
||||||
|
// setDroppedObjects((prev) => [...prev, droppedData]); // ✅ Add to state
|
||||||
|
// console.log(droppedObjects);
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("❌ Error parsing dropped data:", error);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {
|
||||||
|
event.preventDefault();
|
||||||
|
const data = event.dataTransfer.getData("text/plain"); // Use "text/plain" to match the drag event
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
const droppedData = JSON.parse(data);
|
||||||
|
useDroppedObjectsStore.getState().addObject(droppedData); // Add to Zustand store
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
@@ -113,7 +130,10 @@ const RealTimeVisulization: React.FC = () => {
|
|||||||
width: "100%",
|
width: "100%",
|
||||||
borderRadius: isPlaying || activeModule !== "visualization" ? "" : "6px",
|
borderRadius: isPlaying || activeModule !== "visualization" ? "" : "6px",
|
||||||
}}
|
}}
|
||||||
|
onDrop={(event) => handleDrop(event)}
|
||||||
|
onDragOver={(event) => event.preventDefault()}
|
||||||
>
|
>
|
||||||
|
|
||||||
<Scene />
|
<Scene />
|
||||||
</div>
|
</div>
|
||||||
{activeModule === "visualization" && (
|
{activeModule === "visualization" && (
|
||||||
@@ -124,7 +144,7 @@ const RealTimeVisulization: React.FC = () => {
|
|||||||
setSelectedZone={setSelectedZone}
|
setSelectedZone={setSelectedZone}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{!isPlaying && (
|
{!isPlaying && selectedZone?.zoneName !== "" && (
|
||||||
<AddButtons
|
<AddButtons
|
||||||
hiddenPanels={hiddenPanels}
|
hiddenPanels={hiddenPanels}
|
||||||
setHiddenPanels={setHiddenPanels}
|
setHiddenPanels={setHiddenPanels}
|
||||||
@@ -134,9 +154,10 @@ const RealTimeVisulization: React.FC = () => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<Panel
|
<Panel
|
||||||
|
hiddenPanels={hiddenPanels}
|
||||||
selectedZone={selectedZone}
|
selectedZone={selectedZone}
|
||||||
setSelectedZone={setSelectedZone}
|
setSelectedZone={setSelectedZone}
|
||||||
hiddenPanels={hiddenPanels}
|
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
107
app/src/components/ui/componets/zoneCameraTarget.tsx
Normal file
107
app/src/components/ui/componets/zoneCameraTarget.tsx
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
|
import { useFrame, useThree } from "@react-three/fiber";
|
||||||
|
import * as THREE from "three";
|
||||||
|
import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
||||||
|
import { useEditPosition, usezonePosition, usezoneTarget } from "../../../store/store";
|
||||||
|
|
||||||
|
export default function ZoneCentreTarget() {
|
||||||
|
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
||||||
|
const [previousZoneCentre, setPreviousZoneCentre] = useState<number[] | null>(null);
|
||||||
|
const sphereRef = useRef<THREE.Mesh>(null);
|
||||||
|
const { camera, controls }: any = useThree();
|
||||||
|
const { zonePosition, setZonePosition } = usezonePosition();
|
||||||
|
const { zoneTarget, setZoneTarget } = usezoneTarget();
|
||||||
|
const { Edit, setEdit } = useEditPosition();
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
selectedZone.zoneViewPortTarget &&
|
||||||
|
JSON.stringify(previousZoneCentre) !== JSON.stringify(selectedZone.zoneViewPortTarget)
|
||||||
|
) {
|
||||||
|
setPreviousZoneCentre(selectedZone.zoneViewPortTarget);
|
||||||
|
}
|
||||||
|
}, [selectedZone.zoneViewPortTarget, previousZoneCentre]);
|
||||||
|
|
||||||
|
const centrePoint = useMemo(() => {
|
||||||
|
if (!previousZoneCentre || !selectedZone.zoneViewPortTarget) return null;
|
||||||
|
return previousZoneCentre.map((value, index) =>
|
||||||
|
(value + selectedZone.zoneViewPortTarget[index]) / 2
|
||||||
|
);
|
||||||
|
}, [previousZoneCentre, selectedZone.zoneViewPortTarget]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedZone.zoneName !== "") {
|
||||||
|
if (sphereRef.current) {
|
||||||
|
sphereRef.current.position.set(selectedZone.zoneViewPortTarget[0], selectedZone.zoneViewPortTarget[1], selectedZone.zoneViewPortTarget[2]);
|
||||||
|
}
|
||||||
|
if (centrePoint) {
|
||||||
|
|
||||||
|
if (centrePoint.length > 0) {
|
||||||
|
|
||||||
|
let camPosition = new THREE.Vector3(...selectedZone.zoneViewPortPosition);
|
||||||
|
let CamTarget = new THREE.Vector3(...selectedZone.zoneViewPortTarget);
|
||||||
|
|
||||||
|
const direction = new THREE.Vector3().subVectors(CamTarget, camPosition).normalize();
|
||||||
|
|
||||||
|
const worldUp = new THREE.Vector3(0, 0, 1);
|
||||||
|
const right = new THREE.Vector3().crossVectors(worldUp, direction).normalize();
|
||||||
|
const up = new THREE.Vector3().crossVectors(direction, right).normalize();
|
||||||
|
|
||||||
|
const offsetPosition = up.clone().multiplyScalar(20);
|
||||||
|
|
||||||
|
camPosition.add(offsetPosition);
|
||||||
|
|
||||||
|
|
||||||
|
const setCam = async () => {
|
||||||
|
controls.setLookAt(centrePoint[0], 100, centrePoint[2], ...centrePoint, true);
|
||||||
|
setTimeout(() => {
|
||||||
|
controls?.setLookAt(
|
||||||
|
...camPosition.toArray(),
|
||||||
|
selectedZone.zoneViewPortTarget[0],
|
||||||
|
selectedZone.zoneViewPortTarget[1],
|
||||||
|
selectedZone.zoneViewPortTarget[2],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}, 400)
|
||||||
|
};
|
||||||
|
setCam();
|
||||||
|
} else {
|
||||||
|
|
||||||
|
let camPosition = new THREE.Vector3(...selectedZone.zoneViewPortPosition);
|
||||||
|
let CamTarget = new THREE.Vector3(...selectedZone.zoneViewPortTarget);
|
||||||
|
|
||||||
|
const direction = new THREE.Vector3().subVectors(CamTarget, camPosition).normalize();
|
||||||
|
|
||||||
|
const worldUp = new THREE.Vector3(0, 0, 1);
|
||||||
|
const right = new THREE.Vector3().crossVectors(worldUp, direction).normalize();
|
||||||
|
const up = new THREE.Vector3().crossVectors(direction, right).normalize();
|
||||||
|
|
||||||
|
const offsetPosition = up.clone().multiplyScalar(20);
|
||||||
|
|
||||||
|
camPosition.add(offsetPosition);
|
||||||
|
const setCam = async () => {
|
||||||
|
controls?.setLookAt(
|
||||||
|
...camPosition.toArray(),
|
||||||
|
selectedZone.zoneViewPortTarget[0],
|
||||||
|
selectedZone.zoneViewPortTarget[1],
|
||||||
|
selectedZone.zoneViewPortTarget[2],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
};
|
||||||
|
setCam();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [selectedZone.zoneViewPortTarget]);
|
||||||
|
|
||||||
|
useFrame(() => {
|
||||||
|
if (Edit) {
|
||||||
|
setZonePosition([controls.getPosition().x, controls.getPosition().y, controls.getPosition().z])
|
||||||
|
setZoneTarget([controls.getTarget().x, controls.getTarget().y, controls.getTarget().z])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return (
|
||||||
|
<> </>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,99 +1,213 @@
|
|||||||
|
// import React, { useState, useRef, useEffect } from "react";
|
||||||
|
|
||||||
|
// // Dropdown Item Component
|
||||||
|
// const DropdownItem = ({
|
||||||
|
// label,
|
||||||
|
// href,
|
||||||
|
// onClick,
|
||||||
|
// }: {
|
||||||
|
// label: string;
|
||||||
|
// href?: string;
|
||||||
|
// onClick?: () => void;
|
||||||
|
// }) => (
|
||||||
|
// <a
|
||||||
|
// href={href || "#"}
|
||||||
|
// className="dropdown-item"
|
||||||
|
// onClick={(e) => {
|
||||||
|
// e.preventDefault();
|
||||||
|
// onClick?.();
|
||||||
|
// }}
|
||||||
|
// >
|
||||||
|
// {label}
|
||||||
|
// </a>
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Nested Dropdown Component
|
||||||
|
// const NestedDropdown = ({
|
||||||
|
// label,
|
||||||
|
// children,
|
||||||
|
// onSelect,
|
||||||
|
// }: {
|
||||||
|
// label: string;
|
||||||
|
// children: React.ReactNode;
|
||||||
|
// onSelect: (selectedLabel: string) => void;
|
||||||
|
// }) => {
|
||||||
|
// const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <div className="nested-dropdown">
|
||||||
|
// {/* Dropdown Trigger */}
|
||||||
|
// <div
|
||||||
|
// className={`dropdown-trigger ${open ? "open" : ""}`}
|
||||||
|
// onClick={() => setOpen(!open)} // Toggle submenu on click
|
||||||
|
// >
|
||||||
|
// {label} <span className="icon">{open ? "▼" : "▶"}</span>
|
||||||
|
// </div>
|
||||||
|
|
||||||
|
// {/* Submenu */}
|
||||||
|
// {open && (
|
||||||
|
// <div className="submenu">
|
||||||
|
// {React.Children.map(children, (child) => {
|
||||||
|
// if (React.isValidElement(child)) {
|
||||||
|
// // Clone the element and pass the `onSelect` prop only if it's expected
|
||||||
|
// return React.cloneElement(child as React.ReactElement<any>, { onSelect });
|
||||||
|
// }
|
||||||
|
// return child; // Return non-element children as-is
|
||||||
|
// })}
|
||||||
|
// </div>
|
||||||
|
// )}
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // Recursive Function to Render Nested Data
|
||||||
|
// const renderNestedData = (
|
||||||
|
// data: Record<string, any>,
|
||||||
|
// onSelect: (selectedLabel: string) => void
|
||||||
|
// ) => {
|
||||||
|
// return Object.entries(data).map(([key, value]) => {
|
||||||
|
// if (typeof value === "object" && !Array.isArray(value)) {
|
||||||
|
// // If the value is an object, render it as a nested dropdown
|
||||||
|
// return (
|
||||||
|
// <NestedDropdown key={key} label={key} onSelect={onSelect}>
|
||||||
|
// {renderNestedData(value, onSelect)}
|
||||||
|
// </NestedDropdown>
|
||||||
|
// );
|
||||||
|
// } else if (Array.isArray(value)) {
|
||||||
|
// // If the value is an array, render each item as a dropdown item
|
||||||
|
// return value.map((item, index) => (
|
||||||
|
// <DropdownItem key={index} label={item} onClick={() => onSelect(item)} />
|
||||||
|
// ));
|
||||||
|
// } else {
|
||||||
|
// // If the value is a simple string, render it as a dropdown item
|
||||||
|
// return (
|
||||||
|
// <DropdownItem key={key} label={value} onClick={() => onSelect(value)} />
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // Main Multi-Level Dropdown Component
|
||||||
|
// const MultiLevelDropdown = ({ data }: { data: Record<string, any> }) => {
|
||||||
|
// const [open, setOpen] = useState(false);
|
||||||
|
// const [selectedLabel, setSelectedLabel] = useState("Dropdown trigger");
|
||||||
|
// const dropdownRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
// // Handle outer click to close the dropdown
|
||||||
|
// useEffect(() => {
|
||||||
|
// const handleClickOutside = (event: MouseEvent) => {
|
||||||
|
// if (
|
||||||
|
// dropdownRef.current &&
|
||||||
|
// !dropdownRef.current.contains(event.target as Node)
|
||||||
|
// ) {
|
||||||
|
// setOpen(false);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// document.addEventListener("mousedown", handleClickOutside);
|
||||||
|
// return () => {
|
||||||
|
// document.removeEventListener("mousedown", handleClickOutside);
|
||||||
|
// };
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
// // Handle selection of an item
|
||||||
|
// const handleSelect = (selectedLabel: string) => {
|
||||||
|
// setSelectedLabel(selectedLabel); // Update the dropdown trigger text
|
||||||
|
// setOpen(false); // Close the dropdown
|
||||||
|
// };
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <div className="multi-level-dropdown" ref={dropdownRef}>
|
||||||
|
// {/* Dropdown Trigger Button */}
|
||||||
|
// <button
|
||||||
|
// className={`dropdown-button ${open ? "open" : ""}`}
|
||||||
|
// onClick={() => setOpen(!open)} // Toggle main menu on click
|
||||||
|
// >
|
||||||
|
// {selectedLabel} <span className="icon">▾</span>
|
||||||
|
// </button>
|
||||||
|
|
||||||
|
// {/* Dropdown Menu */}
|
||||||
|
// {open && (
|
||||||
|
// <div className="dropdown-menu">
|
||||||
|
// <div className="dropdown-content">
|
||||||
|
// {renderNestedData(data, handleSelect)}
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// )}
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// export default MultiLevelDropdown;
|
||||||
|
|
||||||
import React, { useState, useRef, useEffect } from "react";
|
import React, { useState, useRef, useEffect } from "react";
|
||||||
|
|
||||||
// Dropdown Item Component
|
// Dropdown Item Component
|
||||||
const DropdownItem = ({
|
const DropdownItem = ({
|
||||||
label,
|
label,
|
||||||
href,
|
|
||||||
onClick,
|
onClick,
|
||||||
}: {
|
}: {
|
||||||
label: string;
|
label: string;
|
||||||
href?: string;
|
onClick: () => void;
|
||||||
onClick?: () => void;
|
|
||||||
}) => (
|
}) => (
|
||||||
<a
|
<div className="dropdown-item" onClick={onClick}>
|
||||||
href={href || "#"}
|
|
||||||
className="dropdown-item"
|
|
||||||
onClick={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
onClick?.();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{label}
|
{label}
|
||||||
</a>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
// Nested Dropdown Component
|
// Nested Dropdown Component
|
||||||
const NestedDropdown = ({
|
const NestedDropdown = ({
|
||||||
label,
|
label,
|
||||||
children,
|
fields,
|
||||||
onSelect,
|
onSelect,
|
||||||
}: {
|
}: {
|
||||||
label: string;
|
label: string;
|
||||||
children: React.ReactNode;
|
fields: string[];
|
||||||
onSelect: (selectedLabel: string) => void;
|
onSelect: (selectedData: { name: string; fields: string }) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="nested-dropdown">
|
<div className="nested-dropdown">
|
||||||
{/* Dropdown Trigger */}
|
|
||||||
<div
|
<div
|
||||||
className={`dropdown-trigger ${open ? "open" : ""}`}
|
className={`dropdown-trigger ${open ? "open" : ""}`}
|
||||||
onClick={() => setOpen(!open)} // Toggle submenu on click
|
onClick={() => setOpen(!open)}
|
||||||
>
|
>
|
||||||
{label} <span className="icon">{open ? "▼" : "▶"}</span>
|
{label} <span className="icon">{open ? "▼" : "▶"}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Submenu */}
|
|
||||||
{open && (
|
{open && (
|
||||||
<div className="submenu">
|
<div className="submenu">
|
||||||
{React.Children.map(children, (child) => {
|
{fields.map((field) => (
|
||||||
if (React.isValidElement(child)) {
|
<DropdownItem
|
||||||
// Clone the element and pass the `onSelect` prop only if it's expected
|
key={field}
|
||||||
return React.cloneElement(child as React.ReactElement<any>, { onSelect });
|
label={field}
|
||||||
}
|
onClick={() => onSelect({ name: label, fields: field })}
|
||||||
return child; // Return non-element children as-is
|
/>
|
||||||
})}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Recursive Function to Render Nested Data
|
// Props type for MultiLevelDropdown
|
||||||
const renderNestedData = (
|
interface MultiLevelDropdownProps {
|
||||||
data: Record<string, any>,
|
data: Record<string, any>;
|
||||||
onSelect: (selectedLabel: string) => void
|
onSelect: (selectedData: { name: string; fields: string }) => void;
|
||||||
) => {
|
onUnselect: () => void;
|
||||||
return Object.entries(data).map(([key, value]) => {
|
selectedValue?: { name: string; fields: string };
|
||||||
if (typeof value === "object" && !Array.isArray(value)) {
|
}
|
||||||
// If the value is an object, render it as a nested dropdown
|
|
||||||
return (
|
|
||||||
<NestedDropdown key={key} label={key} onSelect={onSelect}>
|
|
||||||
{renderNestedData(value, onSelect)}
|
|
||||||
</NestedDropdown>
|
|
||||||
);
|
|
||||||
} else if (Array.isArray(value)) {
|
|
||||||
// If the value is an array, render each item as a dropdown item
|
|
||||||
return value.map((item, index) => (
|
|
||||||
<DropdownItem key={index} label={item} onClick={() => onSelect(item)} />
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
// If the value is a simple string, render it as a dropdown item
|
|
||||||
return (
|
|
||||||
<DropdownItem key={key} label={value} onClick={() => onSelect(value)} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Main Multi-Level Dropdown Component
|
// Main Multi-Level Dropdown Component
|
||||||
const MultiLevelDropdown = ({ data }: { data: Record<string, any> }) => {
|
const MultiLevelDropdown = ({
|
||||||
|
data,
|
||||||
|
onSelect,
|
||||||
|
onUnselect,
|
||||||
|
selectedValue
|
||||||
|
}: MultiLevelDropdownProps) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [selectedLabel, setSelectedLabel] = useState("Dropdown trigger");
|
|
||||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
// Handle outer click to close the dropdown
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleClickOutside = (event: MouseEvent) => {
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
if (
|
if (
|
||||||
@@ -103,34 +217,51 @@ const MultiLevelDropdown = ({ data }: { data: Record<string, any> }) => {
|
|||||||
setOpen(false);
|
setOpen(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener("mousedown", handleClickOutside);
|
document.addEventListener("mousedown", handleClickOutside);
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener("mousedown", handleClickOutside);
|
document.removeEventListener("mousedown", handleClickOutside);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Handle selection of an item
|
// Handle item selection
|
||||||
const handleSelect = (selectedLabel: string) => {
|
const handleItemSelect = (selectedData: { name: string; fields: string }) => {
|
||||||
setSelectedLabel(selectedLabel); // Update the dropdown trigger text
|
onSelect(selectedData);
|
||||||
setOpen(false); // Close the dropdown
|
setOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle unselect
|
||||||
|
const handleItemUnselect = () => {
|
||||||
|
onUnselect();
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine the display label
|
||||||
|
const displayLabel = selectedValue
|
||||||
|
? `${selectedValue.name} - ${selectedValue.fields}`
|
||||||
|
: "Dropdown trigger";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="multi-level-dropdown" ref={dropdownRef}>
|
<div className="multi-level-dropdown" ref={dropdownRef}>
|
||||||
{/* Dropdown Trigger Button */}
|
|
||||||
<button
|
<button
|
||||||
className={`dropdown-button ${open ? "open" : ""}`}
|
className={`dropdown-button ${open ? "open" : ""}`}
|
||||||
onClick={() => setOpen(!open)} // Toggle main menu on click
|
onClick={() => setOpen(!open)}
|
||||||
>
|
>
|
||||||
{selectedLabel} <span className="icon">▾</span>
|
{displayLabel} <span className="icon">▾</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{/* Dropdown Menu */}
|
|
||||||
{open && (
|
{open && (
|
||||||
<div className="dropdown-menu">
|
<div className="dropdown-menu">
|
||||||
<div className="dropdown-content">
|
<div className="dropdown-content">
|
||||||
{renderNestedData(data, handleSelect)}
|
{/* Unselect Option */}
|
||||||
|
<DropdownItem label="Unselect" onClick={handleItemUnselect} />
|
||||||
|
{/* Nested Dropdown Items */}
|
||||||
|
{Object.entries(data).map(([key, value]) => (
|
||||||
|
<NestedDropdown
|
||||||
|
key={key}
|
||||||
|
label={key}
|
||||||
|
fields={Object.keys(value)}
|
||||||
|
onSelect={handleItemSelect}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -139,3 +270,4 @@ const MultiLevelDropdown = ({ data }: { data: Record<string, any> }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default MultiLevelDropdown;
|
export default MultiLevelDropdown;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useRef } from "react";
|
import React, { useState, useRef, useEffect } from "react";
|
||||||
|
|
||||||
interface RenameInputProps {
|
interface RenameInputProps {
|
||||||
value: string;
|
value: string;
|
||||||
@@ -9,6 +9,9 @@ const RenameInput: React.FC<RenameInputProps> = ({ value, onRename }) => {
|
|||||||
const [isEditing, setIsEditing] = useState(false);
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
const [text, setText] = useState(value);
|
const [text, setText] = useState(value);
|
||||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||||
|
useEffect(() => {
|
||||||
|
setText(value); // Ensure state updates when parent value changes
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
const handleDoubleClick = () => {
|
const handleDoubleClick = () => {
|
||||||
setIsEditing(true);
|
setIsEditing(true);
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import React, { useEffect, useState } from "react";
|
|||||||
import List from "./List";
|
import List from "./List";
|
||||||
import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons";
|
import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons";
|
||||||
import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect";
|
import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect";
|
||||||
import { getZonesApi } from "../../../services/realTimeVisulization/zoneData/getZones";
|
import { useZones } from "../../../store/store";
|
||||||
|
import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
||||||
|
|
||||||
interface DropDownListProps {
|
interface DropDownListProps {
|
||||||
value?: string; // Value to display in the DropDownList
|
value?: string; // Value to display in the DropDownList
|
||||||
@@ -13,6 +14,7 @@ interface DropDownListProps {
|
|||||||
kebabMenuItems?: { id: string; name: string }[]; // Items for the KebabMenuList
|
kebabMenuItems?: { id: string; name: string }[]; // Items for the KebabMenuList
|
||||||
defaultOpen?: boolean; // Determines if the dropdown list should be open by default
|
defaultOpen?: boolean; // Determines if the dropdown list should be open by default
|
||||||
listType?: string; // Type of list to display
|
listType?: string; // Type of list to display
|
||||||
|
remove?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DropDownList: React.FC<DropDownListProps> = ({
|
const DropDownList: React.FC<DropDownListProps> = ({
|
||||||
@@ -28,25 +30,25 @@ const DropDownList: React.FC<DropDownListProps> = ({
|
|||||||
],
|
],
|
||||||
defaultOpen = false,
|
defaultOpen = false,
|
||||||
listType = "default",
|
listType = "default",
|
||||||
|
remove,
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
const [isOpen, setIsOpen] = useState<boolean>(defaultOpen);
|
const [isOpen, setIsOpen] = useState<boolean>(defaultOpen);
|
||||||
|
const { zones, setZones } = useZones()
|
||||||
|
|
||||||
const handleToggle = () => {
|
const handleToggle = () => {
|
||||||
setIsOpen((prev) => !prev); // Toggle the state
|
setIsOpen((prev) => !prev); // Toggle the state
|
||||||
};
|
};
|
||||||
const [zoneDataList, setZoneDataList] = useState<{ id: string; name: string }[]>([]);
|
const [zoneDataList, setZoneDataList] = useState<{ id: string; name: string }[]>([]);
|
||||||
|
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function GetZoneData() {
|
const value = (zones || []).map((val: { zoneId: string; zoneName: string }) => ({
|
||||||
const response = await getZonesApi("hexrfactory")
|
id: val.zoneId,
|
||||||
// console.log('response: ', response.data);
|
name: val.zoneName
|
||||||
setZoneDataList([{ id: "1", name: "zone1" },
|
}));
|
||||||
{ id: "2", name: "Zone 2" },])
|
setZoneDataList(prev => (JSON.stringify(prev) !== JSON.stringify(value) ? value : prev));
|
||||||
}
|
}, [zones]);
|
||||||
|
|
||||||
GetZoneData()
|
|
||||||
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="dropdown-list-container">
|
<div className="dropdown-list-container">
|
||||||
@@ -81,7 +83,7 @@ const DropDownList: React.FC<DropDownListProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<div className="lists-container">
|
<div className="lists-container">
|
||||||
{listType === "default" && <List items={items} />}
|
{listType === "default" && <List items={items} remove={remove} />}
|
||||||
{listType === "outline" && (
|
{listType === "outline" && (
|
||||||
<>
|
<>
|
||||||
<DropDownList
|
<DropDownList
|
||||||
|
|||||||
@@ -1,14 +1,38 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import RenameInput from "../inputs/RenameInput";
|
import RenameInput from "../inputs/RenameInput";
|
||||||
import { EyeIcon, LockIcon, RmoveIcon } from "../../icons/ExportCommonIcons";
|
import { EyeIcon, LockIcon, RmoveIcon } from "../../icons/ExportCommonIcons";
|
||||||
|
import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
||||||
|
import { getZoneData } from "../../../services/realTimeVisulization/zoneData/getZones";
|
||||||
|
import { useSubModuleStore } from "../../../store/useModuleStore";
|
||||||
|
|
||||||
interface ListProps {
|
interface ListProps {
|
||||||
items?: { id: string; name: string }[]; // Optional array of items to render
|
items?: { id: string; name: string }[]; // Optional array of items to render
|
||||||
placeholder?: string; // Optional placeholder text
|
placeholder?: string; // Optional placeholder text
|
||||||
|
remove?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const List: React.FC<ListProps> = ({ items = [] }) => {
|
const List: React.FC<ListProps> = ({ items = [], remove }) => {
|
||||||
console.log('items: ', items);
|
const { setSelectedZone } = useSelectedZoneStore();
|
||||||
|
const { setSubModule } = useSubModuleStore();
|
||||||
|
|
||||||
|
async function handleSelectZone(id: string) {
|
||||||
|
setSubModule("zoneProperties")
|
||||||
|
const email = localStorage.getItem('email')
|
||||||
|
const organization = (email!.split("@")[1]).split(".")[0];
|
||||||
|
let response = await getZoneData(id, organization)
|
||||||
|
setSelectedZone({
|
||||||
|
zoneName: response?.zoneName,
|
||||||
|
activeSides: response?.activeSides || [],
|
||||||
|
panelOrder: response?.panelOrder || [],
|
||||||
|
lockedPanels: response?.lockedPanels || [],
|
||||||
|
widgets: response?.widgets || [],
|
||||||
|
zoneId: response?.zoneId,
|
||||||
|
zoneViewPortTarget: response?.viewPortCenter || [],
|
||||||
|
zoneViewPortPosition:
|
||||||
|
response?.viewPortposition || [],
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{items.length > 0 ? (
|
{items.length > 0 ? (
|
||||||
@@ -16,7 +40,7 @@ const List: React.FC<ListProps> = ({ items = [] }) => {
|
|||||||
{items.map((item, index) => (
|
{items.map((item, index) => (
|
||||||
<li key={index} className="list-container">
|
<li key={index} className="list-container">
|
||||||
<div className="list-item">
|
<div className="list-item">
|
||||||
<div className="value">
|
<div className="value" onClick={() => handleSelectZone(item.id)}>
|
||||||
<RenameInput value={item.name} />
|
<RenameInput value={item.name} />
|
||||||
</div>
|
</div>
|
||||||
<div className="options-container">
|
<div className="options-container">
|
||||||
@@ -26,9 +50,11 @@ const List: React.FC<ListProps> = ({ items = [] }) => {
|
|||||||
<div className="visibe option">
|
<div className="visibe option">
|
||||||
<EyeIcon isClosed />
|
<EyeIcon isClosed />
|
||||||
</div>
|
</div>
|
||||||
|
{remove && (
|
||||||
<div className="remove option">
|
<div className="remove option">
|
||||||
<RmoveIcon />
|
<RmoveIcon />
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -1,5 +1,107 @@
|
|||||||
import { useMemo } from "react";
|
// import { useMemo } from "react";
|
||||||
import { Line } from "react-chartjs-2";
|
// import { Line } from "react-chartjs-2";
|
||||||
|
|
||||||
|
// interface ChartComponentProps {
|
||||||
|
// type: any;
|
||||||
|
// title: string;
|
||||||
|
// fontFamily?: string;
|
||||||
|
// fontSize?: string;
|
||||||
|
// fontWeight?: "Light" | "Regular" | "Bold";
|
||||||
|
// data: any;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const LineGraphComponent = ({
|
||||||
|
// title,
|
||||||
|
// fontFamily,
|
||||||
|
// fontSize,
|
||||||
|
// fontWeight = "Regular",
|
||||||
|
// }: ChartComponentProps) => {
|
||||||
|
// // Memoize Font Weight Mapping
|
||||||
|
// const chartFontWeightMap = useMemo(
|
||||||
|
// () => ({
|
||||||
|
// Light: "lighter" as const,
|
||||||
|
// Regular: "normal" as const,
|
||||||
|
// Bold: "bold" as const,
|
||||||
|
// }),
|
||||||
|
// []
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Parse and Memoize Font Size
|
||||||
|
// const fontSizeValue = useMemo(
|
||||||
|
// () => (fontSize ? parseInt(fontSize) : 12),
|
||||||
|
// [fontSize]
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Determine and Memoize Font Weight
|
||||||
|
// const fontWeightValue = useMemo(
|
||||||
|
// () => chartFontWeightMap[fontWeight],
|
||||||
|
// [fontWeight, chartFontWeightMap]
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Memoize Chart Font Style
|
||||||
|
// const chartFontStyle = useMemo(
|
||||||
|
// () => ({
|
||||||
|
// family: fontFamily || "Arial",
|
||||||
|
// size: fontSizeValue,
|
||||||
|
// weight: fontWeightValue,
|
||||||
|
// }),
|
||||||
|
// [fontFamily, fontSizeValue, fontWeightValue]
|
||||||
|
// );
|
||||||
|
|
||||||
|
// const options = useMemo(
|
||||||
|
// () => ({
|
||||||
|
// responsive: true,
|
||||||
|
// maintainAspectRatio: false,
|
||||||
|
// plugins: {
|
||||||
|
// title: {
|
||||||
|
// display: true,
|
||||||
|
// text: title,
|
||||||
|
// font: chartFontStyle,
|
||||||
|
// },
|
||||||
|
// legend: {
|
||||||
|
// display: false,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// scales: {
|
||||||
|
// x: {
|
||||||
|
// ticks: {
|
||||||
|
// display: true, // This hides the x-axis labels
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// }),
|
||||||
|
// [title, chartFontStyle]
|
||||||
|
// );
|
||||||
|
|
||||||
|
// const chartData = {
|
||||||
|
// labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||||
|
// datasets: [
|
||||||
|
// {
|
||||||
|
// label: "My First Dataset",
|
||||||
|
// data: [65, 59, 80, 81, 56, 55, 40],
|
||||||
|
// backgroundColor: "#6f42c1", // Updated to #6f42c1 (Purple)
|
||||||
|
// borderColor: "#ffffff", // Keeping border color white
|
||||||
|
// borderWidth: 2,
|
||||||
|
// fill: false,
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// };
|
||||||
|
|
||||||
|
// return <Line data={chartData} options={options} />;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// export default LineGraphComponent;
|
||||||
|
|
||||||
|
|
||||||
|
import React, { useEffect, useRef, useMemo, useState } from "react";
|
||||||
|
import { Chart } from "chart.js/auto";
|
||||||
|
import { useThemeStore } from "../../../../store/useThemeStore";
|
||||||
|
import io from "socket.io-client";
|
||||||
|
import { Line } from 'react-chartjs-2';
|
||||||
|
import useChartStore from "../../../../store/useChartStore";
|
||||||
|
|
||||||
|
// WebSocket Connection
|
||||||
|
// const socket = io("http://localhost:5000"); // Adjust to your backend URL
|
||||||
|
|
||||||
interface ChartComponentProps {
|
interface ChartComponentProps {
|
||||||
type: any;
|
type: any;
|
||||||
@@ -11,11 +113,30 @@ interface ChartComponentProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const LineGraphComponent = ({
|
const LineGraphComponent = ({
|
||||||
|
type,
|
||||||
title,
|
title,
|
||||||
fontFamily,
|
fontFamily,
|
||||||
fontSize,
|
fontSize,
|
||||||
fontWeight = "Regular",
|
fontWeight = "Regular",
|
||||||
|
data,
|
||||||
}: ChartComponentProps) => {
|
}: ChartComponentProps) => {
|
||||||
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
|
const { themeColor } = useThemeStore();
|
||||||
|
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
||||||
|
labels: [],
|
||||||
|
datasets: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Memoize Theme Colors to Prevent Unnecessary Recalculations
|
||||||
|
const buttonActionColor = useMemo(
|
||||||
|
() => themeColor[0] || "#5c87df",
|
||||||
|
[themeColor]
|
||||||
|
);
|
||||||
|
const buttonAbortColor = useMemo(
|
||||||
|
() => themeColor[1] || "#ffffff",
|
||||||
|
[themeColor]
|
||||||
|
);
|
||||||
|
|
||||||
// Memoize Font Weight Mapping
|
// Memoize Font Weight Mapping
|
||||||
const chartFontWeightMap = useMemo(
|
const chartFontWeightMap = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
@@ -48,6 +169,10 @@ const LineGraphComponent = ({
|
|||||||
[fontFamily, fontSizeValue, fontWeightValue]
|
[fontFamily, fontSizeValue, fontWeightValue]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Memoize Chart Data
|
||||||
|
// const data = useMemo(() => propsData, [propsData]);
|
||||||
|
|
||||||
|
// Memoize Chart Options
|
||||||
const options = useMemo(
|
const options = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
responsive: true,
|
responsive: true,
|
||||||
@@ -73,24 +198,68 @@ const LineGraphComponent = ({
|
|||||||
[title, chartFontStyle]
|
[title, chartFontStyle]
|
||||||
);
|
);
|
||||||
|
|
||||||
const chartData = {
|
const { measurements, setMeasurements, updateDuration, duration } = useChartStore();
|
||||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
|
||||||
datasets: [
|
useEffect(() => {
|
||||||
{
|
if ( measurements.length > 0 ) {
|
||||||
label: "My First Dataset",
|
const socket = io("http://192.168.0.192:5010");
|
||||||
data: [65, 59, 80, 81, 56, 55, 40],
|
|
||||||
backgroundColor: "#6f42c1", // Updated to #6f42c1 (Purple)
|
var inputes = {
|
||||||
borderColor: "#ffffff", // Keeping border color white
|
measurements: measurements,
|
||||||
|
duration: duration,
|
||||||
|
interval: 1000,
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('graphHHHHHHHHHHHHHHHHHHHHHHHHHHHHH',inputes);
|
||||||
|
|
||||||
|
|
||||||
|
// Start stream
|
||||||
|
const startStream = () => {
|
||||||
|
socket.emit("lineInput", inputes);
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.on('connect', startStream);
|
||||||
|
|
||||||
|
socket.on("lineOutput", (response) => {
|
||||||
|
const responceData = response.data;
|
||||||
|
console.log("Received data:", responceData);
|
||||||
|
|
||||||
|
// Extract timestamps and values
|
||||||
|
const labels = responceData.time;
|
||||||
|
const datasets = data.measurements.map((measurement: any) => ({
|
||||||
|
label: `${measurement.name}.${measurement.fields}`,
|
||||||
|
data: responceData[`${measurement.name}.${measurement.fields}`]?.values || [],
|
||||||
|
backgroundColor: themeColor[0] || "#5c87df",
|
||||||
|
borderColor: themeColor[1] || "#ffffff",
|
||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
fill: false,
|
// fill: false,
|
||||||
},
|
}));
|
||||||
],
|
|
||||||
|
setChartData({ labels, datasets });
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
socket.off("lineOutput");
|
||||||
|
socket.emit("stop_stream"); // Stop streaming when component unmounts
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
}, [measurements, duration]);
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (!canvasRef.current) return;
|
||||||
|
// const ctx = canvasRef.current.getContext("2d");
|
||||||
|
// if (!ctx) return;
|
||||||
|
|
||||||
|
// const chart = new Chart(ctx, {
|
||||||
|
// type,
|
||||||
|
// data: chartData,
|
||||||
|
// options: options,
|
||||||
|
// });
|
||||||
|
|
||||||
|
// return () => chart.destroy();
|
||||||
|
// }, [chartData, type, title]);
|
||||||
|
|
||||||
return <Line data={chartData} options={options} />;
|
return <Line data={chartData} options={options} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LineGraphComponent;
|
export default LineGraphComponent;
|
||||||
|
|
||||||
|
|
||||||
// like this
|
|
||||||
@@ -13,8 +13,22 @@ const SimpleCard: React.FC<SimpleCardProps> = ({
|
|||||||
value,
|
value,
|
||||||
per,
|
per,
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
|
const handleDragStart = (event: React.DragEvent<HTMLDivElement>) => {
|
||||||
|
const cardData = JSON.stringify({
|
||||||
|
header,
|
||||||
|
value,
|
||||||
|
per,
|
||||||
|
className: event.currentTarget.className,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Dragging Data:", cardData); // ✅ Debugging log
|
||||||
|
|
||||||
|
event.dataTransfer.setData("text/plain", cardData);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="floating total-card" draggable>
|
<div className="floating total-card" draggable onDragStart={handleDragStart}>
|
||||||
<div className="header-wrapper">
|
<div className="header-wrapper">
|
||||||
<div className="header">{header}</div>
|
<div className="header">{header}</div>
|
||||||
<div className="data-values">
|
<div className="data-values">
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ export default async function assetManager(
|
|||||||
) {
|
) {
|
||||||
if (!activePromises.get(taskId)) return; // Stop processing if task is canceled
|
if (!activePromises.get(taskId)) return; // Stop processing if task is canceled
|
||||||
|
|
||||||
const existingModel = itemsGroup.current.getObjectByProperty("uuid", item.modeluuid);
|
const existingModel = itemsGroup?.current?.getObjectByProperty("uuid", item.modeluuid);
|
||||||
if (existingModel) {
|
if (existingModel) {
|
||||||
// console.log(`Model ${item.modelname} already exists in the scene.`);
|
// console.log(`Model ${item.modelname} already exists in the scene.`);
|
||||||
resolve();
|
resolve();
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ const ZoneGroup: React.FC = () => {
|
|||||||
zoneId: zone.zoneId,
|
zoneId: zone.zoneId,
|
||||||
zoneName: zone.zoneName,
|
zoneName: zone.zoneName,
|
||||||
points: zone.points,
|
points: zone.points,
|
||||||
|
viewPortCenter: zone.viewPortCenter,
|
||||||
|
viewPortposition: zone.viewPortposition,
|
||||||
layer: zone.layer
|
layer: zone.layer
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -145,7 +147,7 @@ const ZoneGroup: React.FC = () => {
|
|||||||
|
|
||||||
const target: [number, number, number] | null = calculateCenter(zone.points);
|
const target: [number, number, number] | null = calculateCenter(zone.points);
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
const position = [target[0], 75, target[2]];
|
const position = [target[0], 10, target[2]];
|
||||||
|
|
||||||
const input = {
|
const input = {
|
||||||
userId: userId,
|
userId: userId,
|
||||||
@@ -186,7 +188,7 @@ const ZoneGroup: React.FC = () => {
|
|||||||
|
|
||||||
const target: [number, number, number] | null = calculateCenter(zone.points);
|
const target: [number, number, number] | null = calculateCenter(zone.points);
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
const position = [target[0], 75, target[2]];
|
const position = [target[0], 10, target[2]];
|
||||||
|
|
||||||
const input = {
|
const input = {
|
||||||
userId: userId,
|
userId: userId,
|
||||||
|
|||||||
@@ -745,6 +745,7 @@ export default function SocketResponses({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (data.message === "zone deleted") {
|
if (data.message === "zone deleted") {
|
||||||
|
console.log('data: ', data);
|
||||||
const updatedZones = zones.filter((zone: any) => zone.zoneId !== data.data.zoneId);
|
const updatedZones = zones.filter((zone: any) => zone.zoneId !== data.data.zoneId);
|
||||||
setZones(updatedZones);
|
setZones(updatedZones);
|
||||||
|
|
||||||
|
|||||||
95
app/src/modules/market/AssetPreview.tsx
Normal file
95
app/src/modules/market/AssetPreview.tsx
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
import React from "react";
|
||||||
|
import assetImage from "../../assets/image/image.png";
|
||||||
|
import { FiileedStarsIconSmall } from "../../components/icons/marketPlaceIcons";
|
||||||
|
|
||||||
|
// Define the shape of the selected card
|
||||||
|
interface SelectedCard {
|
||||||
|
assetName: string;
|
||||||
|
uploadedOn: string;
|
||||||
|
price: number;
|
||||||
|
rating: number;
|
||||||
|
views: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the props type for AssetPreview
|
||||||
|
interface AssetPreviewProps {
|
||||||
|
selectedCard: SelectedCard;
|
||||||
|
setSelectedCard: React.Dispatch<React.SetStateAction<SelectedCard | null>>; // Type for setter function
|
||||||
|
}
|
||||||
|
|
||||||
|
const AssetPreview: React.FC<AssetPreviewProps> = ({
|
||||||
|
selectedCard,
|
||||||
|
setSelectedCard,
|
||||||
|
}) => {
|
||||||
|
// Ensure rating is a valid number between 0 and 5
|
||||||
|
const rating = Math.max(
|
||||||
|
0,
|
||||||
|
Math.min(5, isNaN(selectedCard.rating) ? 0 : selectedCard.rating)
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("selectedCard: ", selectedCard);
|
||||||
|
|
||||||
|
// Ensure that the rating is a valid positive integer for array length
|
||||||
|
const starsArray = Array.from({ length: rating }, (_, index) => index);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="assetPreview-wrapper">
|
||||||
|
<div className="assetPreview">
|
||||||
|
<div className="image-preview">
|
||||||
|
<img src={assetImage} alt="" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="asset-details-preview">
|
||||||
|
<div className="organization">
|
||||||
|
<div className="image">H</div>
|
||||||
|
<div className="organization-details">
|
||||||
|
<div className="organization-name">HERX FACTORY</div>
|
||||||
|
<div className="follow">Follow +</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* asset details */}
|
||||||
|
<div className="asset-details">
|
||||||
|
<div className="asset-name">{selectedCard.assetName}</div>
|
||||||
|
<div className="asset-description">
|
||||||
|
Lorem ipsum dolor sit amet consectetur adipisicing elit.
|
||||||
|
Doloremque nisi beatae facilis architecto quaerat delectus velit
|
||||||
|
aliquid assumenda cumque vitae! Tempore quibusdam ab natus in
|
||||||
|
minima voluptates, aliquid corrupti excepturi consectetur
|
||||||
|
distinctio sequi beatae odit autem? Distinctio ab, voluptatem
|
||||||
|
omnis quibusdam, incidunt eum ipsa aliquid enim eaque eveniet nisi
|
||||||
|
autem, accusantium vel! Laborum in iste voluptates ad! Harum eum
|
||||||
|
amet pariatur fugit laudantium dolorem maxime voluptates atque
|
||||||
|
molestiae modi inventore quidem maiores dolore numquam, natus
|
||||||
|
quisquam optio distinctio eveniet aliquam, aut eligendi laboriosam
|
||||||
|
eaque! Porro cumque cum distinctio ullam debitis, dolorum
|
||||||
|
similique! Harum cupiditate perferendis voluptatum molestiae,
|
||||||
|
fugiat quisquam assumenda!
|
||||||
|
</div>
|
||||||
|
<div className="asset-review">
|
||||||
|
<div className="asset-rating">
|
||||||
|
<FiileedStarsIconSmall />
|
||||||
|
{selectedCard.rating}
|
||||||
|
</div>
|
||||||
|
<div className="asset-view">{selectedCard.views} views</div>
|
||||||
|
</div>
|
||||||
|
<div className="asset-price">₹ {selectedCard.price}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* buttons */}
|
||||||
|
<div className="button-container">
|
||||||
|
<div className="button">Add to cart</div>
|
||||||
|
<div className="button">Buy now</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* close button */}
|
||||||
|
<div className="closeButton" onClick={() => setSelectedCard(null)}>
|
||||||
|
{`<-back`}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AssetPreview;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useMemo } from "react";
|
import { useMemo, useState } from "react";
|
||||||
import { Canvas } from "@react-three/fiber";
|
import { Canvas } from "@react-three/fiber";
|
||||||
import { Environment, KeyboardControls } from "@react-three/drei";
|
import { Environment, KeyboardControls } from "@react-three/drei";
|
||||||
|
|
||||||
@@ -15,6 +15,12 @@ import background from "../../assets/textures/hdr/mudroadpuresky2k.hdr";
|
|||||||
import SelectionControls from "./controls/selection/selectionControls";
|
import SelectionControls from "./controls/selection/selectionControls";
|
||||||
import MeasurementTool from "./tools/measurementTool";
|
import MeasurementTool from "./tools/measurementTool";
|
||||||
import Simulation from "../simulation/simulation";
|
import Simulation from "../simulation/simulation";
|
||||||
|
import ZoneCentreTarget from "../../components/ui/componets/zoneCameraTarget";
|
||||||
|
|
||||||
|
import { useThree } from "@react-three/fiber";
|
||||||
|
import * as THREE from "three";
|
||||||
|
import DroppedObjects from "../../components/ui/componets/DroppedFloatingWidgets";
|
||||||
|
|
||||||
// import Simulation from "./simulationtemp/simulation";
|
// import Simulation from "./simulationtemp/simulation";
|
||||||
|
|
||||||
export default function Scene() {
|
export default function Scene() {
|
||||||
@@ -27,6 +33,9 @@ export default function Scene() {
|
|||||||
// { name: "jump", keys: ["Space"] },
|
// { name: "jump", keys: ["Space"] },
|
||||||
], [])
|
], [])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KeyboardControls map={map}>
|
<KeyboardControls map={map}>
|
||||||
<Canvas
|
<Canvas
|
||||||
@@ -36,12 +45,15 @@ export default function Scene() {
|
|||||||
onContextMenu={(e) => {
|
onContextMenu={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}}
|
}}
|
||||||
|
|
||||||
>
|
>
|
||||||
|
<DroppedObjects/>
|
||||||
<Controls />
|
<Controls />
|
||||||
<TransformControl />
|
<TransformControl />
|
||||||
<SelectionControls />
|
<SelectionControls />
|
||||||
<MeasurementTool />
|
<MeasurementTool />
|
||||||
<World />
|
<World />
|
||||||
|
<ZoneCentreTarget />
|
||||||
{/* <Simulation /> */}
|
{/* <Simulation /> */}
|
||||||
<Simulation />
|
<Simulation />
|
||||||
<PostProcessing />
|
<PostProcessing />
|
||||||
|
|||||||
@@ -1,25 +1,23 @@
|
|||||||
let url_Backend_dwinzo = `http://185.100.212.76:5000`;
|
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
|
||||||
|
|
||||||
export const getZonesApi = async (organization: string) => {
|
export const getZoneData = async (zoneId: string, organization: string) => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${url_Backend_dwinzo}/api/v2/findZones/${organization}`, {
|
const response = await fetch(
|
||||||
|
`${url_Backend_dwinzo}/api/v2/A_zone/${zoneId}/${organization}`,
|
||||||
|
{
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
});
|
|
||||||
|
|
||||||
// if (!response.ok) {
|
|
||||||
// throw new Error("Failed to get Zones");
|
|
||||||
// }
|
|
||||||
|
|
||||||
const result = await response.json();
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof Error) {
|
|
||||||
throw new Error(error.message);
|
|
||||||
} else {
|
|
||||||
throw new Error("An unknown error occurred");
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to fetch zoneData");
|
||||||
|
}
|
||||||
|
|
||||||
|
return await response.json();
|
||||||
|
} catch (error: any) {
|
||||||
|
throw new Error(error.message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
31
app/src/services/realTimeVisulization/zoneData/panel.ts
Normal file
31
app/src/services/realTimeVisulization/zoneData/panel.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_BACKEND_URL}`;
|
||||||
|
|
||||||
|
type Side = "top" | "bottom" | "left" | "right";
|
||||||
|
|
||||||
|
export const panelData = async (organization: string, zoneID: string, panelOrder: Side[]) => {
|
||||||
|
console.log('panelOrder: ', panelOrder);
|
||||||
|
console.log('zoneID: ', zoneID);
|
||||||
|
console.log('organization: ', organization);
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${url_Backend_dwinzo}/api/v1/panel/save`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ organization, zoneID, panelOrder }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to add panelOrder for Zone");
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
throw new Error(error.message);
|
||||||
|
} else {
|
||||||
|
throw new Error("An unknown error occurred");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import * as Types from '../types/world/worldTypes';
|
import * as Types from "../types/world/worldTypes";
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { io } from "socket.io-client";
|
import { io } from "socket.io-client";
|
||||||
|
|
||||||
@@ -11,10 +11,13 @@ export const useSocketStore = create<any>((set: any, get: any) => ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const socket = io(`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/`, {
|
const socket = io(
|
||||||
|
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/`,
|
||||||
|
{
|
||||||
reconnection: false,
|
reconnection: false,
|
||||||
auth: { email }
|
auth: { email },
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
set({ socket });
|
set({ socket });
|
||||||
},
|
},
|
||||||
@@ -23,7 +26,7 @@ export const useSocketStore = create<any>((set: any, get: any) => ({
|
|||||||
state.socket?.disconnect();
|
state.socket?.disconnect();
|
||||||
return { socket: null };
|
return { socket: null };
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useOrganization = create<any>((set: any) => ({
|
export const useOrganization = create<any>((set: any) => ({
|
||||||
@@ -126,9 +129,7 @@ export const useFloorItems = create<any>((set: any) => ({
|
|||||||
setFloorItems: (callback: any) =>
|
setFloorItems: (callback: any) =>
|
||||||
set((state: any) => ({
|
set((state: any) => ({
|
||||||
floorItems:
|
floorItems:
|
||||||
typeof callback === "function"
|
typeof callback === "function" ? callback(state.floorItems) : callback,
|
||||||
? callback(state.floorItems)
|
|
||||||
: callback,
|
|
||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -137,9 +138,7 @@ export const useWallItems = create<any>((set: any) => ({
|
|||||||
setWallItems: (callback: any) =>
|
setWallItems: (callback: any) =>
|
||||||
set((state: any) => ({
|
set((state: any) => ({
|
||||||
wallItems:
|
wallItems:
|
||||||
typeof callback === "function"
|
typeof callback === "function" ? callback(state.wallItems) : callback,
|
||||||
? callback(state.wallItems)
|
|
||||||
: callback,
|
|
||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -180,7 +179,8 @@ export const useShadows = create<any>((set: any) => ({
|
|||||||
|
|
||||||
export const useSunPosition = create<any>((set: any) => ({
|
export const useSunPosition = create<any>((set: any) => ({
|
||||||
sunPosition: { x: undefined, y: undefined, z: undefined },
|
sunPosition: { x: undefined, y: undefined, z: undefined },
|
||||||
setSunPosition: (newSuntPosition: any) => set({ sunPosition: newSuntPosition }),
|
setSunPosition: (newSuntPosition: any) =>
|
||||||
|
set({ sunPosition: newSuntPosition }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useRemoveLayer = create<any>((set: any) => ({
|
export const useRemoveLayer = create<any>((set: any) => ({
|
||||||
@@ -216,7 +216,7 @@ export const useActiveTool = create<any>((set: any) => ({
|
|||||||
export const use2DUndoRedo = create<any>((set: any) => ({
|
export const use2DUndoRedo = create<any>((set: any) => ({
|
||||||
is2DUndoRedo: null,
|
is2DUndoRedo: null,
|
||||||
set2DUndoRedo: (x: any) => set({ is2DUndoRedo: x }),
|
set2DUndoRedo: (x: any) => set({ is2DUndoRedo: x }),
|
||||||
}))
|
}));
|
||||||
|
|
||||||
export const useElevation = create<any>((set: any) => ({
|
export const useElevation = create<any>((set: any) => ({
|
||||||
elevation: 45,
|
elevation: 45,
|
||||||
@@ -245,7 +245,8 @@ export const useUserName = create<any>((set: any) => ({
|
|||||||
|
|
||||||
export const useObjectPosition = create<any>((set: any) => ({
|
export const useObjectPosition = create<any>((set: any) => ({
|
||||||
objectPosition: { x: undefined, y: undefined, z: undefined },
|
objectPosition: { x: undefined, y: undefined, z: undefined },
|
||||||
setObjectPosition: (newObjectPosition: any) => set({ objectPosition: newObjectPosition }),
|
setObjectPosition: (newObjectPosition: any) =>
|
||||||
|
set({ objectPosition: newObjectPosition }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useObjectScale = create<any>((set: any) => ({
|
export const useObjectScale = create<any>((set: any) => ({
|
||||||
@@ -255,7 +256,8 @@ export const useObjectScale = create<any>((set: any) => ({
|
|||||||
|
|
||||||
export const useObjectRotation = create<any>((set: any) => ({
|
export const useObjectRotation = create<any>((set: any) => ({
|
||||||
objectRotation: { x: undefined, y: undefined, z: undefined },
|
objectRotation: { x: undefined, y: undefined, z: undefined },
|
||||||
setObjectRotation: (newObjectRotation: any) => set({ objectRotation: newObjectRotation }),
|
setObjectRotation: (newObjectRotation: any) =>
|
||||||
|
set({ objectRotation: newObjectRotation }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useDrieTemp = create<any>((set: any) => ({
|
export const useDrieTemp = create<any>((set: any) => ({
|
||||||
@@ -271,11 +273,21 @@ export const useActiveUsers = create<any>((set: any) => ({
|
|||||||
export const useDrieUIValue = create<any>((set: any) => ({
|
export const useDrieUIValue = create<any>((set: any) => ({
|
||||||
drieUIValue: { touch: null, temperature: null, humidity: null },
|
drieUIValue: { touch: null, temperature: null, humidity: null },
|
||||||
|
|
||||||
setDrieUIValue: (x: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, ...x } })),
|
setDrieUIValue: (x: any) =>
|
||||||
|
set((state: any) => ({ drieUIValue: { ...state.drieUIValue, ...x } })),
|
||||||
|
|
||||||
setTouch: (value: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, touch: value } })),
|
setTouch: (value: any) =>
|
||||||
setTemperature: (value: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, temperature: value } })),
|
set((state: any) => ({
|
||||||
setHumidity: (value: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, humidity: value } })),
|
drieUIValue: { ...state.drieUIValue, touch: value },
|
||||||
|
})),
|
||||||
|
setTemperature: (value: any) =>
|
||||||
|
set((state: any) => ({
|
||||||
|
drieUIValue: { ...state.drieUIValue, temperature: value },
|
||||||
|
})),
|
||||||
|
setHumidity: (value: any) =>
|
||||||
|
set((state: any) => ({
|
||||||
|
drieUIValue: { ...state.drieUIValue, humidity: value },
|
||||||
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useDrawMaterialPath = create<any>((set: any) => ({
|
export const useDrawMaterialPath = create<any>((set: any) => ({
|
||||||
@@ -300,7 +312,16 @@ interface Path {
|
|||||||
uuid: string;
|
uuid: string;
|
||||||
position: [number, number, number];
|
position: [number, number, number];
|
||||||
rotation: [number, number, number];
|
rotation: [number, number, number];
|
||||||
actions: { uuid: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | [];
|
actions:
|
||||||
|
| {
|
||||||
|
uuid: string;
|
||||||
|
type: string;
|
||||||
|
material: string;
|
||||||
|
delay: number | string;
|
||||||
|
spawnInterval: number | string;
|
||||||
|
isUsed: boolean;
|
||||||
|
}[]
|
||||||
|
| [];
|
||||||
triggers: { uuid: string; type: string; isUsed: boolean }[] | [];
|
triggers: { uuid: string; type: string; isUsed: boolean }[] | [];
|
||||||
}[];
|
}[];
|
||||||
pathPosition: [number, number, number];
|
pathPosition: [number, number, number];
|
||||||
@@ -318,7 +339,6 @@ export const useSimulationPaths = create<SimulationPathsStore>((set) => ({
|
|||||||
setSimulationPaths: (paths) => set({ simulationPaths: paths }),
|
setSimulationPaths: (paths) => set({ simulationPaths: paths }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
// interface Point {
|
// interface Point {
|
||||||
// uuid: string;
|
// uuid: string;
|
||||||
// position: [number, number, number];
|
// position: [number, number, number];
|
||||||
@@ -363,7 +383,6 @@ export const useSimulationPaths = create<SimulationPathsStore>((set) => ({
|
|||||||
// setSimulationPaths: (paths) => set({ simulationPaths: paths }),
|
// setSimulationPaths: (paths) => set({ simulationPaths: paths }),
|
||||||
// }));
|
// }));
|
||||||
|
|
||||||
|
|
||||||
export const useConnections = create<Types.ConnectionStore>((set) => ({
|
export const useConnections = create<Types.ConnectionStore>((set) => ({
|
||||||
connections: [],
|
connections: [],
|
||||||
|
|
||||||
@@ -400,3 +419,39 @@ export const useStartSimulation = create<any>((set: any) => ({
|
|||||||
startSimulation: false,
|
startSimulation: false,
|
||||||
setStartSimulation: (x: any) => set({ startSimulation: x }),
|
setStartSimulation: (x: any) => set({ startSimulation: x }),
|
||||||
}));
|
}));
|
||||||
|
export const usezoneTarget = create<any>((set: any) => ({
|
||||||
|
zoneTarget: [],
|
||||||
|
setZoneTarget: (x: any) => set({ zoneTarget: x }),
|
||||||
|
}));
|
||||||
|
export const usezonePosition = create<any>((set: any) => ({
|
||||||
|
zonePosition: [],
|
||||||
|
setZonePosition: (x: any) => set({ zonePosition: x }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
interface EditPositionState {
|
||||||
|
Edit: boolean;
|
||||||
|
setEdit: (value: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useEditPosition = create<EditPositionState>((set) => ({
|
||||||
|
Edit: false,
|
||||||
|
setEdit: (value) => set({ Edit: value }), // Properly updating the state
|
||||||
|
}));
|
||||||
|
|
||||||
|
interface DroppedObject {
|
||||||
|
header: string;
|
||||||
|
value: string;
|
||||||
|
per: string;
|
||||||
|
className: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DroppedObjectsState {
|
||||||
|
objects: DroppedObject[];
|
||||||
|
addObject: (obj: DroppedObject) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useDroppedObjectsStore = create<DroppedObjectsState>((set) => ({
|
||||||
|
objects: [],
|
||||||
|
addObject: (obj) => set((state) => ({ objects: [...state.objects, obj] })),
|
||||||
|
}));
|
||||||
28
app/src/store/useChartStore.ts
Normal file
28
app/src/store/useChartStore.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { create } from "zustand";
|
||||||
|
|
||||||
|
interface Measurement {
|
||||||
|
name: string;
|
||||||
|
fields: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MeasurementStore {
|
||||||
|
measurements: Measurement[];
|
||||||
|
interval: number;
|
||||||
|
duration: string;
|
||||||
|
setMeasurements: (newMeasurements: Measurement[]) => void;
|
||||||
|
updateDuration: (newDuration: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useChartStore = create<MeasurementStore>((set) => ({
|
||||||
|
measurements: [],
|
||||||
|
interval: 1000,
|
||||||
|
duration: "1h",
|
||||||
|
|
||||||
|
setMeasurements: (newMeasurements) =>
|
||||||
|
set(() => ({ measurements: newMeasurements })),
|
||||||
|
|
||||||
|
updateDuration: (newDuration) =>
|
||||||
|
set(() => ({ duration: newDuration })),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export default useChartStore;
|
||||||
@@ -15,21 +15,31 @@ interface SelectedZoneState {
|
|||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
|
zoneId: string;
|
||||||
|
zoneViewPortTarget: number[];
|
||||||
|
zoneViewPortPosition: number[];
|
||||||
widgets: Widget[];
|
widgets: Widget[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SelectedZoneStore {
|
interface SelectedZoneStore {
|
||||||
selectedZone: SelectedZoneState;
|
selectedZone: SelectedZoneState;
|
||||||
setSelectedZone: (zone: Partial<SelectedZoneState> | ((prev: SelectedZoneState) => SelectedZoneState)) => void;
|
setSelectedZone: (
|
||||||
|
zone:
|
||||||
|
| Partial<SelectedZoneState>
|
||||||
|
| ((prev: SelectedZoneState) => SelectedZoneState)
|
||||||
|
) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useSelectedZoneStore = create<SelectedZoneStore>((set) => ({
|
export const useSelectedZoneStore = create<SelectedZoneStore>((set) => ({
|
||||||
selectedZone: {
|
selectedZone: {
|
||||||
zoneName: "",
|
zoneName: "", // Empty string initially
|
||||||
activeSides: [],
|
activeSides: [], // Empty array
|
||||||
panelOrder: [],
|
panelOrder: [], // Empty array
|
||||||
lockedPanels: [],
|
lockedPanels: [], // Empty array
|
||||||
widgets: [],
|
zoneId: "",
|
||||||
|
zoneViewPortTarget: [],
|
||||||
|
zoneViewPortPosition: [],
|
||||||
|
widgets: [], // Empty array
|
||||||
},
|
},
|
||||||
setSelectedZone: (zone) =>
|
setSelectedZone: (zone) =>
|
||||||
set((state) => ({
|
set((state) => ({
|
||||||
|
|||||||
@@ -161,25 +161,49 @@
|
|||||||
width: 30px;
|
width: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: var(--accent-color);
|
background-color: var(--highlight-accent-color);
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@include flex-center;
|
@include flex-center;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 60px;
|
bottom: 60px;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, 0);
|
transform: translate(-50%, 0);
|
||||||
transition: background-color 0.3s, transform 0.3s;
|
color: var(--accent-color);
|
||||||
color: var(--background-color);
|
|
||||||
// transform: none;
|
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
isolation: isolate;
|
||||||
|
font-weight: 700;
|
||||||
&:hover {
|
&:hover {
|
||||||
|
font-weight: 500;
|
||||||
background-color: var(--accent-color);
|
background-color: var(--accent-color);
|
||||||
|
color: var(--highlight-accent-color);
|
||||||
|
&::after{
|
||||||
|
animation: pulse 1s ease-out infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&::after{
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background: var(--background-color-secondary);
|
||||||
|
border-radius: #{$border-radius-circle};
|
||||||
|
z-index: -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0%{
|
||||||
|
opacity: 0;
|
||||||
|
scale: .5;
|
||||||
|
}
|
||||||
|
50%{
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100%{
|
||||||
|
opacity: 0;
|
||||||
|
scale: 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes expandWidth {
|
@keyframes expandWidth {
|
||||||
from {
|
from {
|
||||||
|
|||||||
Reference in New Issue
Block a user