merge conflicts resolved
This commit is contained in:
commit
ab0a68c5e5
|
@ -1,29 +1,29 @@
|
|||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
# /package-lock.json
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
|
||||
# remove zip
|
||||
*.zip
|
||||
**/temp/
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
# /package-lock.json
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
|
||||
# remove zip
|
||||
*.zip
|
||||
**/temp/
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
"devDependencies": {
|
||||
"@types/node": "^22.9.1",
|
||||
"@types/three": "^0.169.0",
|
||||
"axios": "^1.8.4",
|
||||
"cypress": "^13.14.2",
|
||||
"dotenv": "^16.4.5",
|
||||
"husky": "^9.1.6",
|
||||
|
@ -7672,6 +7673,25 @@
|
|||
"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": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
"devDependencies": {
|
||||
"@types/node": "^22.9.1",
|
||||
"@types/three": "^0.169.0",
|
||||
"axios": "^1.8.4",
|
||||
"cypress": "^13.14.2",
|
||||
"dotenv": "^16.4.5",
|
||||
"husky": "^9.1.6",
|
||||
|
|
|
@ -130,3 +130,24 @@ export function StarsIconSmall() {
|
|||
</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}
|
||||
showKebabMenu={false}
|
||||
showFocusIcon={true}
|
||||
remove
|
||||
/>
|
||||
<DropDownList
|
||||
value="Scene"
|
||||
|
|
|
@ -12,16 +12,15 @@ import {
|
|||
import useToggleStore from "../../../store/useUIToggleStore";
|
||||
import MachineMechanics from "./mechanics/MachineMechanics";
|
||||
import Visualization from "./visualization/Visualization";
|
||||
import GlobalProperties from "./properties/GlobalProperties";
|
||||
import AsstePropertiies from "./properties/AssetProperties";
|
||||
import Analysis from "./analysis/Analysis";
|
||||
import Simulations from "./simulation/Simulations";
|
||||
import { useSelectedActionSphere } from "../../../store/store";
|
||||
import GlobalProperties from "./properties/GlobalProperties";
|
||||
import AsstePropertiies from "./properties/AssetProperties";
|
||||
import ZoneProperties from "./properties/ZoneProperties";
|
||||
|
||||
const SideBarRight: React.FC = () => {
|
||||
const { activeModule } = useModuleStore();
|
||||
const [activeList] = useState("properties");
|
||||
const { toggleUI } = useToggleStore();
|
||||
const { selectedActionSphere } = useSelectedActionSphere();
|
||||
const { subModule, setSubModule } = useSubModuleStore();
|
||||
|
@ -38,9 +37,8 @@ const SideBarRight: React.FC = () => {
|
|||
<div className="sidebar-actions-container">
|
||||
{/* {activeModule === "builder" && ( */}
|
||||
<div
|
||||
className={`sidebar-action-list ${
|
||||
subModule === "properties" ? "active" : ""
|
||||
}`}
|
||||
className={`sidebar-action-list ${subModule === "properties" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => setSubModule("properties")}
|
||||
>
|
||||
<PropertiesIcon isActive={subModule === "properties"} />
|
||||
|
@ -49,28 +47,25 @@ const SideBarRight: React.FC = () => {
|
|||
{activeModule === "simulation" && (
|
||||
<>
|
||||
<div
|
||||
className={`sidebar-action-list ${
|
||||
subModule === "mechanics" ? "active" : ""
|
||||
}`}
|
||||
className={`sidebar-action-list ${subModule === "mechanics" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => setSubModule("mechanics")}
|
||||
>
|
||||
<MechanicsIcon isActive={activeList === "mechanics"} />
|
||||
<MechanicsIcon isActive={subModule === "mechanics"} />
|
||||
</div>
|
||||
<div
|
||||
className={`sidebar-action-list ${
|
||||
subModule === "simulations" ? "active" : ""
|
||||
}`}
|
||||
className={`sidebar-action-list ${subModule === "simulations" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => setSubModule("simulations")}
|
||||
>
|
||||
<SimulationIcon isActive={activeList === "simulations"} />
|
||||
<SimulationIcon isActive={subModule === "simulations"} />
|
||||
</div>
|
||||
<div
|
||||
className={`sidebar-action-list ${
|
||||
subModule === "analysis" ? "active" : ""
|
||||
}`}
|
||||
className={`sidebar-action-list ${subModule === "analysis" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => setSubModule("analysis")}
|
||||
>
|
||||
<AnalysisIcon isActive={activeList === "analysis"} />
|
||||
<AnalysisIcon isActive={subModule === "analysis"} />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
@ -78,7 +73,7 @@ const SideBarRight: React.FC = () => {
|
|||
)}
|
||||
{/* process builder */}
|
||||
{toggleUI &&
|
||||
activeList === "properties" &&
|
||||
subModule === "properties" &&
|
||||
activeModule !== "visualization" && (
|
||||
<div className="sidebar-right-container">
|
||||
<div className="sidebar-right-content-container">
|
||||
|
@ -88,7 +83,17 @@ const SideBarRight: React.FC = () => {
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{toggleUI &&
|
||||
subModule === "zoneProperties" &&
|
||||
activeModule === "builder" && (
|
||||
<div className="sidebar-right-container">
|
||||
<div className="sidebar-right-content-container">
|
||||
{/* <GlobalProperties /> */}
|
||||
<ZoneProperties />
|
||||
{/* <AsstePropertiies /> */}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{/* simulation */}
|
||||
|
||||
{toggleUI && activeModule === "simulation" && (
|
||||
|
@ -114,7 +119,7 @@ const SideBarRight: React.FC = () => {
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
{activeList === "simulations" && (
|
||||
{subModule === "simulations" && (
|
||||
<div className="sidebar-right-container">
|
||||
<div className="sidebar-right-content-container">
|
||||
<Simulations />
|
||||
|
|
|
@ -1,62 +1,57 @@
|
|||
import React from "react";
|
||||
import { EyeDroperIcon } from "../../../icons/ExportCommonIcons";
|
||||
// import { useThree } from "@react-three/fiber";
|
||||
|
||||
interface PositionInputProps {
|
||||
onChange: (value: string) => void; // Callback for value change
|
||||
onChange: (value: [number, number, number]) => void; // Callback for value change
|
||||
header: string;
|
||||
placeholder?: string; // Optional placeholder
|
||||
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> = ({
|
||||
onChange,
|
||||
header,
|
||||
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 (
|
||||
<div className="custom-input-container">
|
||||
<div className="header">
|
||||
{header}{" "}
|
||||
<div className="eyedrop-button">
|
||||
<EyeDroperIcon isActive={false} />
|
||||
</div>
|
||||
{header}
|
||||
</div>
|
||||
<div className="inputs-container">
|
||||
<div className="input-container">
|
||||
<div className="custom-input-label">X : </div>
|
||||
<input
|
||||
className="custom-input-field"
|
||||
type={type}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
placeholder={placeholder}
|
||||
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>
|
||||
{["X", "Y", "Z"].map((axis, i) => (
|
||||
<div className="input-container" key={axis}>
|
||||
<div className="custom-input-label">{axis}:</div>
|
||||
<input
|
||||
className="custom-input-field"
|
||||
type={type}
|
||||
value={value?.[i] !== undefined ? value[i].toFixed(2) : ""}
|
||||
// onChange={(e) => handleChange(i, e.target.value)}
|
||||
placeholder={placeholder}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Vector3Input;
|
||||
export default Vector3Input;
|
|
@ -1,32 +1,65 @@
|
|||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import RenameInput from "../../../ui/inputs/RenameInput";
|
||||
import Vector3Input from "../customInput/Vector3Input";
|
||||
import { useSelectedZoneStore } from "../../../../store/useZoneStore";
|
||||
import { useEditPosition, usezonePosition, usezoneTarget } from "../../../../store/store";
|
||||
|
||||
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() {
|
||||
console.log("setApi");
|
||||
|
||||
console.log('zoneTarget: ', zoneTarget);
|
||||
console.log('zonePosition: ', zonePosition);
|
||||
setEdit(false);
|
||||
}
|
||||
|
||||
function handleEditView() {
|
||||
if (Edit) {
|
||||
setEdit(false);
|
||||
} else {
|
||||
setEdit(true);
|
||||
}
|
||||
setEdit(!Edit); // This will toggle the `Edit` state correctly
|
||||
}
|
||||
|
||||
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 (
|
||||
<div className="zone-properties-container">
|
||||
<div className="header">
|
||||
<RenameInput value="Selected Zone Name" />
|
||||
<RenameInput value={selectedZone.zoneName} onRename={handleZoneNameChange} />
|
||||
<div className="button" onClick={handleEditView}>
|
||||
{Edit ? "Cancel" : "Edit"}
|
||||
</div>
|
||||
</div>
|
||||
<Vector3Input onChange={() => {}} header="Viewport Target" />
|
||||
<Vector3Input onChange={() => {}} header="Viewport Position" />
|
||||
<Vector3Input
|
||||
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 && (
|
||||
<div className="button-save" onClick={handleSetView}>
|
||||
Set View
|
||||
|
@ -37,3 +70,4 @@ const ZoneProperties: React.FC = () => {
|
|||
};
|
||||
|
||||
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 { AddIcon, RemoveIcon } from "../../../../icons/ExportCommonIcons";
|
||||
import MultiLevelDropDown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||
import LineGrapInput from "../IotInputCards/LineGrapInput";
|
||||
|
||||
// Define the data structure for demonstration purposes
|
||||
const DATA_STRUCTURE = {
|
||||
|
@ -123,41 +124,10 @@ const Data = () => {
|
|||
<div className="sideBarHeader">{selectedChartId?.title}</div>
|
||||
)}
|
||||
{/* Render groups dynamically */}
|
||||
{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>
|
||||
))}
|
||||
|
||||
{
|
||||
chartDataGroups[selectedChartId?.id] && <LineGrapInput />
|
||||
}
|
||||
|
||||
{/* Info Box */}
|
||||
<div className="infoBox">
|
||||
<span className="infoIcon">i</span>
|
||||
|
@ -173,3 +143,40 @@ const 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,
|
||||
LockIcon,
|
||||
} from "../../icons/RealTimeVisulationIcons";
|
||||
import { panelData } from "../../../services/realTimeVisulization/zoneData/panel";
|
||||
|
||||
// Define the type for `Side`
|
||||
type Side = "top" | "bottom" | "left" | "right";
|
||||
|
@ -15,6 +16,9 @@ interface ButtonsProps {
|
|||
activeSides: Side[];
|
||||
panelOrder: Side[];
|
||||
lockedPanels: Side[];
|
||||
zoneId: string;
|
||||
zoneViewPortTarget: number[];
|
||||
zoneViewPortPosition: number[]
|
||||
widgets: {
|
||||
id: string;
|
||||
type: string;
|
||||
|
@ -29,6 +33,9 @@ interface ButtonsProps {
|
|||
activeSides: Side[];
|
||||
panelOrder: Side[];
|
||||
lockedPanels: Side[];
|
||||
zoneId: string;
|
||||
zoneViewPortTarget: number[];
|
||||
zoneViewPortPosition: number[]
|
||||
widgets: {
|
||||
id: string;
|
||||
type: string;
|
||||
|
@ -108,7 +115,7 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
|||
panelOrder: newActiveSides,
|
||||
};
|
||||
|
||||
// Update the selectedZone state
|
||||
// Delete the selectedZone state
|
||||
console.log('updatedZone: ', updatedZone);
|
||||
setSelectedZone(updatedZone);
|
||||
} else {
|
||||
|
@ -120,73 +127,84 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
|||
activeSides: 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
|
||||
console.log('updatedZone: ', updatedZone);
|
||||
console.log("updatedZone: ", updatedZone);
|
||||
setSelectedZone(updatedZone);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
{(["top", "right", "bottom", "left"] as Side[]).map((side) => (
|
||||
<div key={side} className={`side-button-container ${side}`}>
|
||||
<button
|
||||
className={`side-button ${side}`}
|
||||
onClick={() => handlePlusButtonClick(side)}
|
||||
title={
|
||||
selectedZone.activeSides.includes(side)
|
||||
? `Remove all items and close ${side} panel`
|
||||
: `Activate ${side} panel`
|
||||
}
|
||||
>
|
||||
+
|
||||
</button>
|
||||
<>
|
||||
<div>
|
||||
{(["top", "right", "bottom", "left"] as Side[]).map((side) => (
|
||||
<div key={side} className={`side-button-container ${side}`}>
|
||||
{/* "+" Button */}
|
||||
<button
|
||||
className={`side-button ${side}`}
|
||||
onClick={() => handlePlusButtonClick(side)}
|
||||
title={
|
||||
selectedZone.activeSides.includes(side)
|
||||
? `Remove all items and close ${side} panel`
|
||||
: `Activate ${side} panel`
|
||||
}
|
||||
>
|
||||
+
|
||||
</button>
|
||||
|
||||
{/* Extra Buttons */}
|
||||
{selectedZone.activeSides.includes(side) && (
|
||||
<div className="extra-Bs">
|
||||
{/* Hide Panel */}
|
||||
<div
|
||||
className={`icon ${hiddenPanels.includes(side) ? "active" : ""
|
||||
}`}
|
||||
title={
|
||||
hiddenPanels.includes(side) ? "Show Panel" : "Hide Panel"
|
||||
}
|
||||
onClick={() => toggleVisibility(side)}
|
||||
>
|
||||
<EyeIcon
|
||||
fill={hiddenPanels.includes(side) ? "white" : "#1D1E21"}
|
||||
/>
|
||||
</div>
|
||||
{/* Extra Buttons */}
|
||||
{selectedZone.activeSides.includes(side) && (
|
||||
<div className="extra-Bs">
|
||||
{/* Hide Panel */}
|
||||
<div
|
||||
className={`icon ${hiddenPanels.includes(side) ? "active" : ""
|
||||
}`}
|
||||
title={
|
||||
hiddenPanels.includes(side) ? "Show Panel" : "Hide Panel"
|
||||
}
|
||||
onClick={() => toggleVisibility(side)}
|
||||
>
|
||||
<EyeIcon
|
||||
fill={
|
||||
hiddenPanels.includes(side)
|
||||
? "white"
|
||||
: "#1D1E21"
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Clean Panel */}
|
||||
<div
|
||||
className="icon"
|
||||
title="Clean Panel"
|
||||
onClick={() => cleanPanel(side)}
|
||||
>
|
||||
<CleanPannel />
|
||||
</div>
|
||||
{/* Clean Panel */}
|
||||
<div
|
||||
className="icon"
|
||||
title="Clean Panel"
|
||||
onClick={() => cleanPanel(side)}
|
||||
>
|
||||
<CleanPannel />
|
||||
</div>
|
||||
|
||||
{/* Lock/Unlock Panel */}
|
||||
<div
|
||||
className={`icon ${selectedZone.lockedPanels.includes(side) ? "active" : ""
|
||||
}`}
|
||||
title={
|
||||
selectedZone.lockedPanels.includes(side)
|
||||
? "Unlock Panel"
|
||||
: "Lock Panel"
|
||||
}
|
||||
onClick={() => toggleLockPanel(side)}
|
||||
>
|
||||
<LockIcon fill={selectedZone.lockedPanels.includes(side) ? "#ffffff" : "#1D1E21"} />
|
||||
{/* Lock/Unlock Panel */}
|
||||
<div
|
||||
className={`icon ${selectedZone.lockedPanels.includes(side) ? "active" : ""
|
||||
}`}
|
||||
title={
|
||||
selectedZone.lockedPanels.includes(side)
|
||||
? "Unlock Panel"
|
||||
: "Lock Panel"
|
||||
}
|
||||
onClick={() => toggleLockPanel(side)}
|
||||
>
|
||||
<LockIcon fill={selectedZone.lockedPanels.includes(side) ? "#ffffff" : "#1D1E21"} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@ interface DisplayZoneProps {
|
|||
panelOrder: Side[];
|
||||
lockedPanels: Side[];
|
||||
widgets: Widget[];
|
||||
zoneId: string;
|
||||
zoneViewPortTarget: number[];
|
||||
zoneViewPortPosition: number[];
|
||||
};
|
||||
};
|
||||
selectedZone: {
|
||||
|
@ -18,6 +21,9 @@ interface DisplayZoneProps {
|
|||
activeSides: Side[];
|
||||
panelOrder: Side[];
|
||||
lockedPanels: Side[];
|
||||
zoneId: string;
|
||||
zoneViewPortTarget: number[];
|
||||
zoneViewPortPosition: number[];
|
||||
widgets: {
|
||||
id: string;
|
||||
type: string;
|
||||
|
@ -32,6 +38,9 @@ interface DisplayZoneProps {
|
|||
activeSides: Side[];
|
||||
panelOrder: Side[];
|
||||
lockedPanels: Side[];
|
||||
zoneId: string;
|
||||
zoneViewPortTarget: number[];
|
||||
zoneViewPortPosition: number[];
|
||||
widgets: {
|
||||
id: string;
|
||||
type: string;
|
||||
|
@ -152,16 +161,16 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
|
|||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={`zoon-wrapper ${selectedZone.activeSides.includes("bottom") && "bottom"
|
||||
className={`zoon-wrapper ${selectedZone?.activeSides?.includes("bottom") && "bottom"
|
||||
}`}
|
||||
>
|
||||
{Object.keys(zonesData).map((zoneName, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`zone ${selectedZone.zoneName === zoneName ? "active" : ""
|
||||
}`}
|
||||
}`}
|
||||
onClick={() => {
|
||||
console.log('zoneName: ', zoneName);
|
||||
|
||||
|
||||
setSelectedZone({
|
||||
zoneName,
|
||||
|
@ -169,12 +178,15 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
|
|||
panelOrder: zonesData[zoneName].panelOrder || [],
|
||||
lockedPanels: zonesData[zoneName].lockedPanels || [],
|
||||
widgets: zonesData[zoneName].widgets || [],
|
||||
})
|
||||
zoneId: zonesData[zoneName]?.zoneId || "",
|
||||
zoneViewPortTarget: zonesData[zoneName].zoneViewPortTarget || [],
|
||||
zoneViewPortPosition:
|
||||
zonesData[zoneName].zoneViewPortPosition || [],
|
||||
});
|
||||
// setSelectedZone({
|
||||
// zoneName,
|
||||
// ...zonesData[zoneName],
|
||||
// });
|
||||
console.log(selectedZone);
|
||||
}}
|
||||
>
|
||||
{zoneName}
|
||||
|
@ -184,4 +196,4 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
|
|||
);
|
||||
};
|
||||
|
||||
export default DisplayZone;
|
||||
export default DisplayZone;
|
||||
|
|
|
@ -1,165 +1,164 @@
|
|||
import { useWidgetStore } from "../../../store/useWidgetStore";
|
||||
import ProgressCard from "../realTimeVis/charts/ProgressCard";
|
||||
import PieGraphComponent from "../realTimeVis/charts/PieGraphComponent";
|
||||
import BarGraphComponent from "../realTimeVis/charts/BarGraphComponent";
|
||||
import LineGraphComponent from "../realTimeVis/charts/LineGraphComponent";
|
||||
import RadarGraphComponent from "../realTimeVis/charts/RadarGraphComponent";
|
||||
import DoughnutGraphComponent from "../realTimeVis/charts/DoughnutGraphComponent";
|
||||
import PolarAreaGraphComponent from "../realTimeVis/charts/PolarAreaGraphComponent";
|
||||
|
||||
export const DraggableWidget = ({
|
||||
widget,
|
||||
hiddenPanels, // Add this prop to track hidden panels
|
||||
index, onReorder
|
||||
}: {
|
||||
widget: any;
|
||||
hiddenPanels: string[]; // Array of hidden panel names
|
||||
index: number; onReorder: (fromIndex: number, toIndex: number) => void
|
||||
}) => {
|
||||
|
||||
const { selectedChartId, setSelectedChartId } = useWidgetStore();
|
||||
|
||||
const handlePointerDown = () => {
|
||||
if (selectedChartId?.id !== widget.id) {
|
||||
setSelectedChartId(widget);
|
||||
}
|
||||
};
|
||||
|
||||
// Determine if the widget's panel is hidden
|
||||
const isPanelHidden = hiddenPanels.includes(widget.panel);
|
||||
|
||||
const handleDragStart = (event: React.DragEvent<HTMLDivElement>) => {
|
||||
event.dataTransfer.setData('text/plain', index.toString()); // Store the index of the dragged widget
|
||||
};
|
||||
const handleDragEnter = (event: React.DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault(); // Allow drop
|
||||
};
|
||||
|
||||
const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault(); // Allow drop
|
||||
};
|
||||
|
||||
const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
const fromIndex = parseInt(event.dataTransfer.getData('text/plain'), 10); // Get the dragged widget's index
|
||||
const toIndex = index; // The index of the widget where the drop occurred
|
||||
if (fromIndex !== toIndex) {
|
||||
onReorder(fromIndex, toIndex); // Call the reorder function passed as a prop
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
draggable
|
||||
key={widget.id}
|
||||
className={`chart-container ${selectedChartId?.id === widget.id && "activeChart"
|
||||
}`}
|
||||
onPointerDown={handlePointerDown}
|
||||
onDragStart={handleDragStart}
|
||||
onDragEnter={handleDragEnter}
|
||||
onDragOver={handleDragOver}
|
||||
onDrop={handleDrop}
|
||||
style={{
|
||||
opacity: isPanelHidden ? 0 : 1, // Set opacity to 0 if the panel is hidden
|
||||
pointerEvents: isPanelHidden ? "none" : "auto", // Disable interaction when hidden
|
||||
}}
|
||||
>
|
||||
{/* Render charts based on widget type */}
|
||||
{widget.type === "progress" && (
|
||||
<ProgressCard title={widget.title} data={widget.data} />
|
||||
)}
|
||||
{widget.type === "line" && (
|
||||
<LineGraphComponent
|
||||
type={widget.type}
|
||||
title={widget.title}
|
||||
fontSize={widget.fontSize}
|
||||
fontWeight={widget.fontWeight}
|
||||
data={{
|
||||
measurements: [
|
||||
{ name: "testDevice", fields: "powerConsumption" },
|
||||
{ name: "furnace", fields: "powerConsumption" },
|
||||
],
|
||||
interval: 1000,
|
||||
duration: "1h",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{widget.type === "bar" && (
|
||||
<BarGraphComponent
|
||||
type={widget.type}
|
||||
title={widget.title}
|
||||
fontSize={widget.fontSize}
|
||||
fontWeight={widget.fontWeight}
|
||||
data={{
|
||||
measurements: [
|
||||
{ name: "testDevice", fields: "powerConsumption" },
|
||||
{ name: "furnace", fields: "powerConsumption" },
|
||||
],
|
||||
interval: 1000,
|
||||
duration: "1h",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{/* {widget.type === "radar" && (
|
||||
<RadarGraphComponent
|
||||
type={widget.type}
|
||||
title={widget.title}
|
||||
fontSize={widget.fontSize}
|
||||
fontWeight={widget.fontWeight}
|
||||
data={widget.data.measurements.map((item: any) => item.fields)}
|
||||
/>
|
||||
)} */}
|
||||
{widget.type === "pie" && (
|
||||
<PieGraphComponent
|
||||
type={widget.type}
|
||||
title={widget.title}
|
||||
fontSize={widget.fontSize}
|
||||
fontWeight={widget.fontWeight}
|
||||
data={{
|
||||
measurements: [
|
||||
{ name: "testDevice", fields: "powerConsumption" },
|
||||
{ name: "furnace", fields: "powerConsumption" },
|
||||
],
|
||||
interval: 1000,
|
||||
duration: "1h",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{widget.type === "doughnut" && (
|
||||
<DoughnutGraphComponent
|
||||
type={widget.type}
|
||||
title={widget.title}
|
||||
fontSize={widget.fontSize}
|
||||
fontWeight={widget.fontWeight}
|
||||
data={{
|
||||
measurements: [
|
||||
{ name: "testDevice", fields: "powerConsumption" },
|
||||
{ name: "furnace", fields: "powerConsumption" },
|
||||
],
|
||||
interval: 1000,
|
||||
duration: "1h",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{widget.type === "polarArea" && (
|
||||
<PolarAreaGraphComponent
|
||||
type={widget.type}
|
||||
title={widget.title}
|
||||
fontSize={widget.fontSize}
|
||||
fontWeight={widget.fontWeight}
|
||||
data={{
|
||||
measurements: [
|
||||
{ name: "testDevice", fields: "powerConsumption" },
|
||||
{ name: "furnace", fields: "powerConsumption" },
|
||||
],
|
||||
interval: 1000,
|
||||
duration: "1h",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
import { useWidgetStore } from "../../../store/useWidgetStore";
|
||||
import ProgressCard from "../realTimeVis/charts/ProgressCard";
|
||||
import PieGraphComponent from "../realTimeVis/charts/PieGraphComponent";
|
||||
import BarGraphComponent from "../realTimeVis/charts/BarGraphComponent";
|
||||
import LineGraphComponent from "../realTimeVis/charts/LineGraphComponent";
|
||||
import RadarGraphComponent from "../realTimeVis/charts/RadarGraphComponent";
|
||||
import DoughnutGraphComponent from "../realTimeVis/charts/DoughnutGraphComponent";
|
||||
import PolarAreaGraphComponent from "../realTimeVis/charts/PolarAreaGraphComponent";
|
||||
|
||||
export const DraggableWidget = ({
|
||||
widget,
|
||||
hiddenPanels, // Add this prop to track hidden panels
|
||||
index, onReorder
|
||||
}: {
|
||||
widget: any;
|
||||
hiddenPanels: string[]; // Array of hidden panel names
|
||||
index: number; onReorder: (fromIndex: number, toIndex: number) => void
|
||||
}) => {
|
||||
const { selectedChartId, setSelectedChartId } = useWidgetStore();
|
||||
|
||||
const handlePointerDown = () => {
|
||||
if (selectedChartId?.id !== widget.id) {
|
||||
setSelectedChartId(widget);
|
||||
}
|
||||
};
|
||||
|
||||
// Determine if the widget's panel is hidden
|
||||
const isPanelHidden = hiddenPanels.includes(widget.panel);
|
||||
|
||||
const handleDragStart = (event: React.DragEvent<HTMLDivElement>) => {
|
||||
event.dataTransfer.setData('text/plain', index.toString()); // Store the index of the dragged widget
|
||||
};
|
||||
const handleDragEnter = (event: React.DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault(); // Allow drop
|
||||
};
|
||||
|
||||
const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault(); // Allow drop
|
||||
};
|
||||
|
||||
const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
const fromIndex = parseInt(event.dataTransfer.getData('text/plain'), 10); // Get the dragged widget's index
|
||||
const toIndex = index; // The index of the widget where the drop occurred
|
||||
if (fromIndex !== toIndex) {
|
||||
onReorder(fromIndex, toIndex); // Call the reorder function passed as a prop
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
draggable
|
||||
key={widget.id}
|
||||
className={`chart-container ${selectedChartId?.id === widget.id && "activeChart"
|
||||
}`}
|
||||
onPointerDown={handlePointerDown}
|
||||
onDragStart={handleDragStart}
|
||||
onDragEnter={handleDragEnter}
|
||||
onDragOver={handleDragOver}
|
||||
onDrop={handleDrop}
|
||||
style={{
|
||||
opacity: isPanelHidden ? 0 : 1, // Set opacity to 0 if the panel is hidden
|
||||
pointerEvents: isPanelHidden ? "none" : "auto", // Disable interaction when hidden
|
||||
}}
|
||||
>
|
||||
{/* Render charts based on widget type */}
|
||||
{widget.type === "progress" && (
|
||||
<ProgressCard title={widget.title} data={widget.data} />
|
||||
)}
|
||||
{widget.type === "line" && (
|
||||
<LineGraphComponent
|
||||
type={widget.type}
|
||||
title={widget.title}
|
||||
fontSize={widget.fontSize}
|
||||
fontWeight={widget.fontWeight}
|
||||
data={{
|
||||
measurements: [
|
||||
{ name: "testDevice", fields: "powerConsumption" },
|
||||
{ name: "furnace", fields: "powerConsumption" },
|
||||
],
|
||||
interval: 1000,
|
||||
duration: "1h",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{widget.type === "bar" && (
|
||||
<BarGraphComponent
|
||||
type={widget.type}
|
||||
title={widget.title}
|
||||
fontSize={widget.fontSize}
|
||||
fontWeight={widget.fontWeight}
|
||||
data={{
|
||||
measurements: [
|
||||
{ name: "testDevice", fields: "powerConsumption" },
|
||||
{ name: "furnace", fields: "powerConsumption" },
|
||||
],
|
||||
interval: 1000,
|
||||
duration: "1h",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{/* {widget.type === "radar" && (
|
||||
<RadarGraphComponent
|
||||
type={widget.type}
|
||||
title={widget.title}
|
||||
fontSize={widget.fontSize}
|
||||
fontWeight={widget.fontWeight}
|
||||
data={widget.data.measurements.map((item: any) => item.fields)}
|
||||
/>
|
||||
)} */}
|
||||
{widget.type === "pie" && (
|
||||
<PieGraphComponent
|
||||
type={widget.type}
|
||||
title={widget.title}
|
||||
fontSize={widget.fontSize}
|
||||
fontWeight={widget.fontWeight}
|
||||
data={{
|
||||
measurements: [
|
||||
{ name: "testDevice", fields: "powerConsumption" },
|
||||
{ name: "furnace", fields: "powerConsumption" },
|
||||
],
|
||||
interval: 1000,
|
||||
duration: "1h",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{widget.type === "doughnut" && (
|
||||
<DoughnutGraphComponent
|
||||
type={widget.type}
|
||||
title={widget.title}
|
||||
fontSize={widget.fontSize}
|
||||
fontWeight={widget.fontWeight}
|
||||
data={{
|
||||
measurements: [
|
||||
{ name: "testDevice", fields: "powerConsumption" },
|
||||
{ name: "furnace", fields: "powerConsumption" },
|
||||
],
|
||||
interval: 1000,
|
||||
duration: "1h",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{widget.type === "polarArea" && (
|
||||
<PolarAreaGraphComponent
|
||||
type={widget.type}
|
||||
title={widget.title}
|
||||
fontSize={widget.fontSize}
|
||||
fontWeight={widget.fontWeight}
|
||||
data={{
|
||||
measurements: [
|
||||
{ name: "testDevice", fields: "powerConsumption" },
|
||||
{ name: "furnace", fields: "powerConsumption" },
|
||||
],
|
||||
interval: 1000,
|
||||
duration: "1h",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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[];
|
||||
panelOrder: Side[];
|
||||
lockedPanels: Side[];
|
||||
zoneId: string;
|
||||
zoneViewPortTarget: number[];
|
||||
zoneViewPortPosition: number[]
|
||||
widgets: Widget[];
|
||||
};
|
||||
setSelectedZone: React.Dispatch<
|
||||
|
@ -28,6 +31,9 @@ interface PanelProps {
|
|||
activeSides: Side[];
|
||||
panelOrder: Side[];
|
||||
lockedPanels: Side[];
|
||||
zoneId: string;
|
||||
zoneViewPortTarget: number[];
|
||||
zoneViewPortPosition: number[]
|
||||
widgets: Widget[];
|
||||
}>
|
||||
>;
|
||||
|
@ -65,7 +71,7 @@ const Panel: React.FC<PanelProps> = ({
|
|||
return {
|
||||
width: `calc(100% - ${(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)
|
||||
}px)`,
|
||||
height: `${panelSize - 5}px`,
|
||||
height: `${panelSize - 2}px`,
|
||||
left: leftActive ? `${panelSize}px` : "0",
|
||||
right: rightActive ? `${panelSize}px` : "0",
|
||||
[side]: "0",
|
||||
|
@ -73,7 +79,7 @@ const Panel: React.FC<PanelProps> = ({
|
|||
case "left":
|
||||
case "right":
|
||||
return {
|
||||
width: `${panelSize - 5}px`,
|
||||
width: `${panelSize - 2}px`,
|
||||
height: `calc(100% - ${(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)
|
||||
}px)`,
|
||||
top: topActive ? `${panelSize}px` : "0",
|
||||
|
|
|
@ -6,7 +6,9 @@ import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
|||
import DisplayZone from "./DisplayZone";
|
||||
import Scene from "../../../modules/scene/scene";
|
||||
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";
|
||||
|
@ -17,7 +19,9 @@ type FormattedZoneData = Record<
|
|||
activeSides: Side[];
|
||||
panelOrder: Side[];
|
||||
lockedPanels: Side[];
|
||||
zoneCentrePoint: number[];
|
||||
zoneId: string;
|
||||
zoneViewPortTarget: number[];
|
||||
zoneViewPortPosition: number[]
|
||||
widgets: Widget[];
|
||||
}
|
||||
>;
|
||||
|
@ -28,60 +32,39 @@ type Widget = {
|
|||
panel: Side;
|
||||
data: any;
|
||||
};
|
||||
type Zone = {
|
||||
zoneId: string;
|
||||
zoneName: string;
|
||||
points: number[][];
|
||||
layer: number;
|
||||
};
|
||||
|
||||
const RealTimeVisulization: React.FC = () => {
|
||||
const [hiddenPanels, setHiddenPanels] = React.useState<Side[]>([]);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { activeModule } = useModuleStore();
|
||||
|
||||
const [droppedObjects, setDroppedObjects] = useState<any[]>([]);
|
||||
const [zonesData, setZonesData] = useState<FormattedZoneData>({});
|
||||
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
||||
const { zones } = useZones()
|
||||
|
||||
useEffect(() => {
|
||||
async function GetZoneData() {
|
||||
try {
|
||||
const response: { data: Zone[] } | undefined = await getZonesApi(
|
||||
"hexrfactory"
|
||||
);
|
||||
const data = Array.isArray(zones) ? zones : [];
|
||||
|
||||
if (!response || !response.data) {
|
||||
return;
|
||||
}
|
||||
const formattedData = response?.data?.reduce<FormattedZoneData>(
|
||||
(acc, zone) => {
|
||||
acc[zone.zoneName] = {
|
||||
activeSides: [],
|
||||
panelOrder: [],
|
||||
lockedPanels: [],
|
||||
zoneCentrePoint: [],
|
||||
widgets: [],
|
||||
};
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
setZonesData(formattedData);
|
||||
} catch (error) { }
|
||||
}
|
||||
GetZoneData();
|
||||
}, []);
|
||||
const formattedData = data.reduce<FormattedZoneData>((acc, zone) => {
|
||||
acc[zone.zoneName] = {
|
||||
activeSides: [],
|
||||
panelOrder: [],
|
||||
lockedPanels: [],
|
||||
zoneId: zone.zoneId,
|
||||
zoneViewPortTarget: zone.viewPortCenter,
|
||||
zoneViewPortPosition: zone.viewPortposition,
|
||||
widgets: [],
|
||||
};
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
console.log('zonesData: ', zonesData);
|
||||
}, [zonesData]);
|
||||
setZonesData(formattedData);
|
||||
}, [zones]);
|
||||
|
||||
useEffect(() => {
|
||||
setZonesData((prev) => {
|
||||
if (!selectedZone) return prev;
|
||||
|
||||
return {
|
||||
...prev,
|
||||
[selectedZone.zoneName]: {
|
||||
|
@ -89,12 +72,46 @@ const RealTimeVisulization: React.FC = () => {
|
|||
activeSides: selectedZone.activeSides || [],
|
||||
panelOrder: selectedZone.panelOrder || [],
|
||||
lockedPanels: selectedZone.lockedPanels || [],
|
||||
zoneId: selectedZone.zoneId || "",
|
||||
zoneViewPortTarget: selectedZone.zoneViewPortTarget || [],
|
||||
zoneViewPortPosition: selectedZone.zoneViewPortPosition || [],
|
||||
widgets: selectedZone.widgets || [],
|
||||
},
|
||||
};
|
||||
});
|
||||
}, [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 (
|
||||
<div
|
||||
ref={containerRef}
|
||||
|
@ -113,7 +130,10 @@ const RealTimeVisulization: React.FC = () => {
|
|||
width: "100%",
|
||||
borderRadius: isPlaying || activeModule !== "visualization" ? "" : "6px",
|
||||
}}
|
||||
onDrop={(event) => handleDrop(event)}
|
||||
onDragOver={(event) => event.preventDefault()}
|
||||
>
|
||||
|
||||
<Scene />
|
||||
</div>
|
||||
{activeModule === "visualization" && (
|
||||
|
@ -124,7 +144,7 @@ const RealTimeVisulization: React.FC = () => {
|
|||
setSelectedZone={setSelectedZone}
|
||||
/>
|
||||
|
||||
{!isPlaying && (
|
||||
{!isPlaying && selectedZone?.zoneName !== "" && (
|
||||
<AddButtons
|
||||
hiddenPanels={hiddenPanels}
|
||||
setHiddenPanels={setHiddenPanels}
|
||||
|
@ -134,9 +154,10 @@ const RealTimeVisulization: React.FC = () => {
|
|||
)}
|
||||
|
||||
<Panel
|
||||
hiddenPanels={hiddenPanels}
|
||||
selectedZone={selectedZone}
|
||||
setSelectedZone={setSelectedZone}
|
||||
hiddenPanels={hiddenPanels}
|
||||
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
|
|
@ -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";
|
||||
|
||||
// Dropdown Item Component
|
||||
const DropdownItem = ({
|
||||
label,
|
||||
href,
|
||||
onClick,
|
||||
}: {
|
||||
label: string;
|
||||
href?: string;
|
||||
onClick?: () => void;
|
||||
onClick: () => void;
|
||||
}) => (
|
||||
<a
|
||||
href={href || "#"}
|
||||
className="dropdown-item"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
onClick?.();
|
||||
}}
|
||||
>
|
||||
<div className="dropdown-item" onClick={onClick}>
|
||||
{label}
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
|
||||
// Nested Dropdown Component
|
||||
const NestedDropdown = ({
|
||||
label,
|
||||
children,
|
||||
fields,
|
||||
onSelect,
|
||||
}: {
|
||||
label: string;
|
||||
children: React.ReactNode;
|
||||
onSelect: (selectedLabel: string) => void;
|
||||
fields: string[];
|
||||
onSelect: (selectedData: { name: string; fields: 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
|
||||
onClick={() => setOpen(!open)}
|
||||
>
|
||||
{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
|
||||
})}
|
||||
{fields.map((field) => (
|
||||
<DropdownItem
|
||||
key={field}
|
||||
label={field}
|
||||
onClick={() => onSelect({ name: label, fields: field })}
|
||||
/>
|
||||
))}
|
||||
</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)} />
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
// Props type for MultiLevelDropdown
|
||||
interface MultiLevelDropdownProps {
|
||||
data: Record<string, any>;
|
||||
onSelect: (selectedData: { name: string; fields: string }) => void;
|
||||
onUnselect: () => void;
|
||||
selectedValue?: { name: string; fields: string };
|
||||
}
|
||||
|
||||
// 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 [selectedLabel, setSelectedLabel] = useState("Dropdown trigger");
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Handle outer click to close the dropdown
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (
|
||||
|
@ -103,34 +217,51 @@ const MultiLevelDropdown = ({ data }: { data: Record<string, any> }) => {
|
|||
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
|
||||
// Handle item selection
|
||||
const handleItemSelect = (selectedData: { name: string; fields: string }) => {
|
||||
onSelect(selectedData);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
// Handle unselect
|
||||
const handleItemUnselect = () => {
|
||||
onUnselect();
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
// Determine the display label
|
||||
const displayLabel = selectedValue
|
||||
? `${selectedValue.name} - ${selectedValue.fields}`
|
||||
: "Dropdown trigger";
|
||||
|
||||
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
|
||||
onClick={() => setOpen(!open)}
|
||||
>
|
||||
{selectedLabel} <span className="icon">▾</span>
|
||||
{displayLabel} <span className="icon">▾</span>
|
||||
</button>
|
||||
|
||||
{/* Dropdown Menu */}
|
||||
{open && (
|
||||
<div className="dropdown-menu">
|
||||
<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>
|
||||
)}
|
||||
|
@ -138,4 +269,5 @@ 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 {
|
||||
value: string;
|
||||
|
@ -9,6 +9,9 @@ const RenameInput: React.FC<RenameInputProps> = ({ value, onRename }) => {
|
|||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [text, setText] = useState(value);
|
||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||
useEffect(() => {
|
||||
setText(value); // Ensure state updates when parent value changes
|
||||
}, [value]);
|
||||
|
||||
const handleDoubleClick = () => {
|
||||
setIsEditing(true);
|
||||
|
|
|
@ -2,7 +2,8 @@ import React, { useEffect, useState } from "react";
|
|||
import List from "./List";
|
||||
import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons";
|
||||
import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect";
|
||||
import { getZonesApi } from "../../../services/realTimeVisulization/zoneData/getZones";
|
||||
import { useZones } from "../../../store/store";
|
||||
import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
||||
|
||||
interface DropDownListProps {
|
||||
value?: string; // Value to display in the DropDownList
|
||||
|
@ -13,6 +14,7 @@ interface DropDownListProps {
|
|||
kebabMenuItems?: { id: string; name: string }[]; // Items for the KebabMenuList
|
||||
defaultOpen?: boolean; // Determines if the dropdown list should be open by default
|
||||
listType?: string; // Type of list to display
|
||||
remove?: boolean;
|
||||
}
|
||||
|
||||
const DropDownList: React.FC<DropDownListProps> = ({
|
||||
|
@ -28,25 +30,25 @@ const DropDownList: React.FC<DropDownListProps> = ({
|
|||
],
|
||||
defaultOpen = false,
|
||||
listType = "default",
|
||||
remove,
|
||||
}) => {
|
||||
|
||||
const [isOpen, setIsOpen] = useState<boolean>(defaultOpen);
|
||||
const { zones, setZones } = useZones()
|
||||
|
||||
const handleToggle = () => {
|
||||
setIsOpen((prev) => !prev); // Toggle the state
|
||||
};
|
||||
const [zoneDataList, setZoneDataList] = useState<{ id: string; name: string }[]>([]);
|
||||
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
||||
|
||||
useEffect(() => {
|
||||
async function GetZoneData() {
|
||||
const response = await getZonesApi("hexrfactory")
|
||||
// console.log('response: ', response.data);
|
||||
setZoneDataList([{ id: "1", name: "zone1" },
|
||||
{ id: "2", name: "Zone 2" },])
|
||||
}
|
||||
|
||||
GetZoneData()
|
||||
|
||||
}, [])
|
||||
const value = (zones || []).map((val: { zoneId: string; zoneName: string }) => ({
|
||||
id: val.zoneId,
|
||||
name: val.zoneName
|
||||
}));
|
||||
setZoneDataList(prev => (JSON.stringify(prev) !== JSON.stringify(value) ? value : prev));
|
||||
}, [zones]);
|
||||
|
||||
return (
|
||||
<div className="dropdown-list-container">
|
||||
|
@ -81,7 +83,7 @@ const DropDownList: React.FC<DropDownListProps> = ({
|
|||
</div>
|
||||
{isOpen && (
|
||||
<div className="lists-container">
|
||||
{listType === "default" && <List items={items} />}
|
||||
{listType === "default" && <List items={items} remove={remove} />}
|
||||
{listType === "outline" && (
|
||||
<>
|
||||
<DropDownList
|
||||
|
|
|
@ -1,14 +1,38 @@
|
|||
import React from "react";
|
||||
import RenameInput from "../inputs/RenameInput";
|
||||
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 {
|
||||
items?: { id: string; name: string }[]; // Optional array of items to render
|
||||
placeholder?: string; // Optional placeholder text
|
||||
remove?: boolean;
|
||||
}
|
||||
|
||||
const List: React.FC<ListProps> = ({ items = [] }) => {
|
||||
console.log('items: ', items);
|
||||
const List: React.FC<ListProps> = ({ items = [], remove }) => {
|
||||
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 (
|
||||
<>
|
||||
{items.length > 0 ? (
|
||||
|
@ -16,7 +40,7 @@ const List: React.FC<ListProps> = ({ items = [] }) => {
|
|||
{items.map((item, index) => (
|
||||
<li key={index} className="list-container">
|
||||
<div className="list-item">
|
||||
<div className="value">
|
||||
<div className="value" onClick={() => handleSelectZone(item.id)}>
|
||||
<RenameInput value={item.name} />
|
||||
</div>
|
||||
<div className="options-container">
|
||||
|
@ -26,9 +50,11 @@ const List: React.FC<ListProps> = ({ items = [] }) => {
|
|||
<div className="visibe option">
|
||||
<EyeIcon isClosed />
|
||||
</div>
|
||||
<div className="remove option">
|
||||
<RmoveIcon />
|
||||
</div>
|
||||
{remove && (
|
||||
<div className="remove option">
|
||||
<RmoveIcon />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
@ -1,5 +1,107 @@
|
|||
import { useMemo } from "react";
|
||||
import { Line } from "react-chartjs-2";
|
||||
// import { useMemo } from "react";
|
||||
// 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 {
|
||||
type: any;
|
||||
|
@ -11,86 +113,153 @@ interface ChartComponentProps {
|
|||
}
|
||||
|
||||
const LineGraphComponent = ({
|
||||
type,
|
||||
title,
|
||||
fontFamily,
|
||||
fontSize,
|
||||
fontWeight = "Regular",
|
||||
data,
|
||||
}: ChartComponentProps) => {
|
||||
// Memoize Font Weight Mapping
|
||||
const chartFontWeightMap = useMemo(
|
||||
() => ({
|
||||
Light: "lighter" as const,
|
||||
Regular: "normal" as const,
|
||||
Bold: "bold" as const,
|
||||
}),
|
||||
[]
|
||||
);
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
const { themeColor } = useThemeStore();
|
||||
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
||||
labels: [],
|
||||
datasets: [],
|
||||
});
|
||||
|
||||
// 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
|
||||
// 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
|
||||
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]
|
||||
);
|
||||
|
||||
// Memoize Chart Data
|
||||
// const data = useMemo(() => propsData, [propsData]);
|
||||
|
||||
// Memoize Chart Options
|
||||
const options = useMemo(
|
||||
() => ({
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: title,
|
||||
font: chartFontStyle,
|
||||
},
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
[title, chartFontStyle]
|
||||
);
|
||||
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
|
||||
const { measurements, setMeasurements, updateDuration, duration } = useChartStore();
|
||||
|
||||
useEffect(() => {
|
||||
if ( measurements.length > 0 ) {
|
||||
const socket = io("http://192.168.0.192:5010");
|
||||
|
||||
var inputes = {
|
||||
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,
|
||||
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} />;
|
||||
};
|
||||
|
||||
export default LineGraphComponent;
|
||||
|
||||
|
||||
// like this
|
||||
export default LineGraphComponent;
|
|
@ -13,8 +13,22 @@ const SimpleCard: React.FC<SimpleCardProps> = ({
|
|||
value,
|
||||
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 (
|
||||
<div className="floating total-card" draggable>
|
||||
<div className="floating total-card" draggable onDragStart={handleDragStart}>
|
||||
<div className="header-wrapper">
|
||||
<div className="header">{header}</div>
|
||||
<div className="data-values">
|
||||
|
|
|
@ -112,7 +112,7 @@ export default async function assetManager(
|
|||
) {
|
||||
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) {
|
||||
// console.log(`Model ${item.modelname} already exists in the scene.`);
|
||||
resolve();
|
||||
|
|
|
@ -65,6 +65,8 @@ const ZoneGroup: React.FC = () => {
|
|||
zoneId: zone.zoneId,
|
||||
zoneName: zone.zoneName,
|
||||
points: zone.points,
|
||||
viewPortCenter: zone.viewPortCenter,
|
||||
viewPortposition: zone.viewPortposition,
|
||||
layer: zone.layer
|
||||
}));
|
||||
|
||||
|
@ -145,7 +147,7 @@ const ZoneGroup: React.FC = () => {
|
|||
|
||||
const target: [number, number, number] | null = calculateCenter(zone.points);
|
||||
if (!target) return;
|
||||
const position = [target[0], 75, target[2]];
|
||||
const position = [target[0], 10, target[2]];
|
||||
|
||||
const input = {
|
||||
userId: userId,
|
||||
|
@ -186,7 +188,7 @@ const ZoneGroup: React.FC = () => {
|
|||
|
||||
const target: [number, number, number] | null = calculateCenter(zone.points);
|
||||
if (!target) return;
|
||||
const position = [target[0], 75, target[2]];
|
||||
const position = [target[0], 10, target[2]];
|
||||
|
||||
const input = {
|
||||
userId: userId,
|
||||
|
|
|
@ -745,6 +745,7 @@ export default function SocketResponses({
|
|||
return
|
||||
}
|
||||
if (data.message === "zone deleted") {
|
||||
console.log('data: ', data);
|
||||
const updatedZones = zones.filter((zone: any) => zone.zoneId !== data.data.zoneId);
|
||||
setZones(updatedZones);
|
||||
|
||||
|
|
|
@ -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;
|
|
@ -15,4 +15,4 @@ const CardsContainer: React.FC = () => {
|
|||
);
|
||||
};
|
||||
|
||||
export default CardsContainer;
|
||||
export default CardsContainer;
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import React from "react";
|
||||
import FilterSearch from "./FilterSearch";
|
||||
import CardsContainer from "./CardsContainer";
|
||||
|
||||
const MarketPlace = () => {
|
||||
return (
|
||||
<div className="marketplace-wrapper">
|
||||
<div className="marketplace-container">
|
||||
<div className="marketPlace">
|
||||
<FilterSearch />
|
||||
<CardsContainer />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MarketPlace;
|
||||
import React from "react";
|
||||
import FilterSearch from "./FilterSearch";
|
||||
import CardsContainer from "./CardsContainer";
|
||||
|
||||
const MarketPlace = () => {
|
||||
return (
|
||||
<div className="marketplace-wrapper">
|
||||
<div className="marketplace-container">
|
||||
<div className="marketPlace">
|
||||
<FilterSearch />
|
||||
<CardsContainer />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MarketPlace;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useMemo } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { Canvas } from "@react-three/fiber";
|
||||
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 MeasurementTool from "./tools/measurementTool";
|
||||
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";
|
||||
|
||||
export default function Scene() {
|
||||
|
@ -27,6 +33,9 @@ export default function Scene() {
|
|||
// { name: "jump", keys: ["Space"] },
|
||||
], [])
|
||||
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<KeyboardControls map={map}>
|
||||
<Canvas
|
||||
|
@ -36,12 +45,15 @@ export default function Scene() {
|
|||
onContextMenu={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
|
||||
>
|
||||
<DroppedObjects/>
|
||||
<Controls />
|
||||
<TransformControl />
|
||||
<SelectionControls />
|
||||
<MeasurementTool />
|
||||
<World />
|
||||
<ZoneCentreTarget />
|
||||
{/* <Simulation /> */}
|
||||
<Simulation />
|
||||
<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) => {
|
||||
try {
|
||||
const response = await fetch(`${url_Backend_dwinzo}/api/v2/findZones/${organization}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
export const getZoneData = async (zoneId: string, organization: string) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${url_Backend_dwinzo}/api/v2/A_zone/${zoneId}/${organization}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"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);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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,324 +1,344 @@
|
|||
import * as THREE from "three";
|
||||
import * as Types from '../types/world/worldTypes';
|
||||
import * as Types from "../types/world/worldTypes";
|
||||
import { create } from "zustand";
|
||||
import { io } from "socket.io-client";
|
||||
|
||||
export const useSocketStore = create<any>((set: any, get: any) => ({
|
||||
socket: null,
|
||||
initializeSocket: (email: any) => {
|
||||
const existingSocket = get().socket;
|
||||
if (existingSocket) {
|
||||
return;
|
||||
}
|
||||
|
||||
const socket = io(`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/`, {
|
||||
reconnection: false,
|
||||
auth: { email }
|
||||
});
|
||||
|
||||
set({ socket });
|
||||
},
|
||||
disconnectSocket: () => {
|
||||
set((state: any) => {
|
||||
state.socket?.disconnect();
|
||||
return { socket: null };
|
||||
});
|
||||
socket: null,
|
||||
initializeSocket: (email: any) => {
|
||||
const existingSocket = get().socket;
|
||||
if (existingSocket) {
|
||||
return;
|
||||
}
|
||||
|
||||
const socket = io(
|
||||
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/`,
|
||||
{
|
||||
reconnection: false,
|
||||
auth: { email },
|
||||
}
|
||||
);
|
||||
|
||||
set({ socket });
|
||||
},
|
||||
disconnectSocket: () => {
|
||||
set((state: any) => {
|
||||
state.socket?.disconnect();
|
||||
return { socket: null };
|
||||
});
|
||||
},
|
||||
}));
|
||||
|
||||
export const useOrganization = create<any>((set: any) => ({
|
||||
organization: "",
|
||||
setOrganization: (x: any) => set(() => ({ organization: x })),
|
||||
organization: "",
|
||||
setOrganization: (x: any) => set(() => ({ organization: x })),
|
||||
}));
|
||||
|
||||
export const useToggleView = create<any>((set: any) => ({
|
||||
toggleView: false,
|
||||
setToggleView: (x: any) => set(() => ({ toggleView: x })),
|
||||
toggleView: false,
|
||||
setToggleView: (x: any) => set(() => ({ toggleView: x })),
|
||||
}));
|
||||
|
||||
export const useUpdateScene = create<any>((set: any) => ({
|
||||
updateScene: false,
|
||||
setUpdateScene: (x: any) => set(() => ({ updateScene: x })),
|
||||
updateScene: false,
|
||||
setUpdateScene: (x: any) => set(() => ({ updateScene: x })),
|
||||
}));
|
||||
|
||||
export const useWalls = create<any>((set: any) => ({
|
||||
walls: [],
|
||||
setWalls: (x: any) => set(() => ({ walls: x })),
|
||||
walls: [],
|
||||
setWalls: (x: any) => set(() => ({ walls: x })),
|
||||
}));
|
||||
|
||||
export const useZones = create<any>((set: any) => ({
|
||||
zones: [],
|
||||
setZones: (x: any) => set(() => ({ zones: x })),
|
||||
zones: [],
|
||||
setZones: (x: any) => set(() => ({ zones: x })),
|
||||
}));
|
||||
|
||||
interface ZonePointsState {
|
||||
zonePoints: THREE.Vector3[];
|
||||
setZonePoints: (points: THREE.Vector3[]) => void;
|
||||
zonePoints: THREE.Vector3[];
|
||||
setZonePoints: (points: THREE.Vector3[]) => void;
|
||||
}
|
||||
|
||||
export const useZonePoints = create<ZonePointsState>((set) => ({
|
||||
zonePoints: [],
|
||||
setZonePoints: (points) => set({ zonePoints: points }),
|
||||
zonePoints: [],
|
||||
setZonePoints: (points) => set({ zonePoints: points }),
|
||||
}));
|
||||
|
||||
export const useSelectedItem = create<any>((set: any) => ({
|
||||
selectedItem: { name: "", id: "" },
|
||||
setSelectedItem: (x: any) => set(() => ({ selectedItem: x })),
|
||||
selectedItem: { name: "", id: "" },
|
||||
setSelectedItem: (x: any) => set(() => ({ selectedItem: x })),
|
||||
}));
|
||||
|
||||
export const useSelectedAssets = create<any>((set: any) => ({
|
||||
selectedAssets: [],
|
||||
setSelectedAssets: (x: any) => set(() => ({ selectedAssets: x })),
|
||||
selectedAssets: [],
|
||||
setSelectedAssets: (x: any) => set(() => ({ selectedAssets: x })),
|
||||
}));
|
||||
|
||||
export const useLayers = create<any>((set: any) => ({
|
||||
Layers: 1,
|
||||
setLayers: (x: any) => set(() => ({ Layers: x })),
|
||||
Layers: 1,
|
||||
setLayers: (x: any) => set(() => ({ Layers: x })),
|
||||
}));
|
||||
|
||||
export const useCamPosition = create<any>((set: any) => ({
|
||||
camPosition: { x: undefined, y: undefined, z: undefined },
|
||||
setCamPosition: (newCamPosition: any) => set({ camPosition: newCamPosition }),
|
||||
camPosition: { x: undefined, y: undefined, z: undefined },
|
||||
setCamPosition: (newCamPosition: any) => set({ camPosition: newCamPosition }),
|
||||
}));
|
||||
|
||||
export const useMenuVisible = create<any>((set: any) => ({
|
||||
menuVisible: false,
|
||||
setMenuVisible: (x: any) => set(() => ({ menuVisible: x })),
|
||||
menuVisible: false,
|
||||
setMenuVisible: (x: any) => set(() => ({ menuVisible: x })),
|
||||
}));
|
||||
|
||||
export const useDeleteModels = create<any>((set: any) => ({
|
||||
deleteModels: false,
|
||||
setDeleteModels: (x: any) => set(() => ({ deleteModels: x })),
|
||||
deleteModels: false,
|
||||
setDeleteModels: (x: any) => set(() => ({ deleteModels: x })),
|
||||
}));
|
||||
|
||||
export const useToolMode = create<any>((set: any) => ({
|
||||
toolMode: null,
|
||||
setToolMode: (x: any) => set(() => ({ toolMode: x })),
|
||||
toolMode: null,
|
||||
setToolMode: (x: any) => set(() => ({ toolMode: x })),
|
||||
}));
|
||||
|
||||
export const useNewLines = create<any>((set: any) => ({
|
||||
newLines: [],
|
||||
setNewLines: (x: any) => set(() => ({ newLines: x })),
|
||||
newLines: [],
|
||||
setNewLines: (x: any) => set(() => ({ newLines: x })),
|
||||
}));
|
||||
|
||||
export const useDeletedLines = create<any>((set: any) => ({
|
||||
deletedLines: [],
|
||||
setDeletedLines: (x: any) => set(() => ({ deletedLines: x })),
|
||||
deletedLines: [],
|
||||
setDeletedLines: (x: any) => set(() => ({ deletedLines: x })),
|
||||
}));
|
||||
|
||||
export const useMovePoint = create<any>((set: any) => ({
|
||||
movePoint: false,
|
||||
setMovePoint: (x: any) => set(() => ({ movePoint: x })),
|
||||
movePoint: false,
|
||||
setMovePoint: (x: any) => set(() => ({ movePoint: x })),
|
||||
}));
|
||||
|
||||
export const useTransformMode = create<any>((set: any) => ({
|
||||
transformMode: null,
|
||||
setTransformMode: (x: any) => set(() => ({ transformMode: x })),
|
||||
transformMode: null,
|
||||
setTransformMode: (x: any) => set(() => ({ transformMode: x })),
|
||||
}));
|
||||
|
||||
export const useDeletePointOrLine = create<any>((set: any) => ({
|
||||
deletePointOrLine: false,
|
||||
setDeletePointOrLine: (x: any) => set(() => ({ deletePointOrLine: x })),
|
||||
deletePointOrLine: false,
|
||||
setDeletePointOrLine: (x: any) => set(() => ({ deletePointOrLine: x })),
|
||||
}));
|
||||
|
||||
export const useFloorItems = create<any>((set: any) => ({
|
||||
floorItems: null,
|
||||
setFloorItems: (callback: any) =>
|
||||
set((state: any) => ({
|
||||
floorItems:
|
||||
typeof callback === "function"
|
||||
? callback(state.floorItems)
|
||||
: callback,
|
||||
})),
|
||||
floorItems: null,
|
||||
setFloorItems: (callback: any) =>
|
||||
set((state: any) => ({
|
||||
floorItems:
|
||||
typeof callback === "function" ? callback(state.floorItems) : callback,
|
||||
})),
|
||||
}));
|
||||
|
||||
export const useWallItems = create<any>((set: any) => ({
|
||||
wallItems: [],
|
||||
setWallItems: (callback: any) =>
|
||||
set((state: any) => ({
|
||||
wallItems:
|
||||
typeof callback === "function"
|
||||
? callback(state.wallItems)
|
||||
: callback,
|
||||
})),
|
||||
wallItems: [],
|
||||
setWallItems: (callback: any) =>
|
||||
set((state: any) => ({
|
||||
wallItems:
|
||||
typeof callback === "function" ? callback(state.wallItems) : callback,
|
||||
})),
|
||||
}));
|
||||
|
||||
export const useSelectedWallItem = create<any>((set: any) => ({
|
||||
selectedWallItem: null,
|
||||
setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })),
|
||||
selectedWallItem: null,
|
||||
setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })),
|
||||
}));
|
||||
|
||||
export const useselectedFloorItem = create<any>((set: any) => ({
|
||||
selectedFloorItem: null,
|
||||
setselectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })),
|
||||
selectedFloorItem: null,
|
||||
setselectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })),
|
||||
}));
|
||||
|
||||
export const useDeletableFloorItem = create<any>((set: any) => ({
|
||||
deletableFloorItem: null,
|
||||
setDeletableFloorItem: (x: any) => set(() => ({ deletableFloorItem: x })),
|
||||
deletableFloorItem: null,
|
||||
setDeletableFloorItem: (x: any) => set(() => ({ deletableFloorItem: x })),
|
||||
}));
|
||||
|
||||
export const useSetScale = create<any>((set: any) => ({
|
||||
scale: null,
|
||||
setScale: (x: any) => set(() => ({ scale: x })),
|
||||
scale: null,
|
||||
setScale: (x: any) => set(() => ({ scale: x })),
|
||||
}));
|
||||
|
||||
export const useRoofVisibility = create<any>((set: any) => ({
|
||||
roofVisibility: false,
|
||||
setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })),
|
||||
roofVisibility: false,
|
||||
setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })),
|
||||
}));
|
||||
|
||||
export const useWallVisibility = create<any>((set: any) => ({
|
||||
wallVisibility: false,
|
||||
setWallVisibility: (x: any) => set(() => ({ wallVisibility: x })),
|
||||
wallVisibility: false,
|
||||
setWallVisibility: (x: any) => set(() => ({ wallVisibility: x })),
|
||||
}));
|
||||
|
||||
export const useShadows = create<any>((set: any) => ({
|
||||
shadows: false,
|
||||
setShadows: (x: any) => set(() => ({ shadows: x })),
|
||||
shadows: false,
|
||||
setShadows: (x: any) => set(() => ({ shadows: x })),
|
||||
}));
|
||||
|
||||
export const useSunPosition = create<any>((set: any) => ({
|
||||
sunPosition: { x: undefined, y: undefined, z: undefined },
|
||||
setSunPosition: (newSuntPosition: any) => set({ sunPosition: newSuntPosition }),
|
||||
sunPosition: { x: undefined, y: undefined, z: undefined },
|
||||
setSunPosition: (newSuntPosition: any) =>
|
||||
set({ sunPosition: newSuntPosition }),
|
||||
}));
|
||||
|
||||
export const useRemoveLayer = create<any>((set: any) => ({
|
||||
removeLayer: false,
|
||||
setRemoveLayer: (x: any) => set(() => ({ removeLayer: x })),
|
||||
removeLayer: false,
|
||||
setRemoveLayer: (x: any) => set(() => ({ removeLayer: x })),
|
||||
}));
|
||||
|
||||
export const useRemovedLayer = create<any>((set: any) => ({
|
||||
removedLayer: null,
|
||||
setRemovedLayer: (x: any) => set(() => ({ removedLayer: x })),
|
||||
removedLayer: null,
|
||||
setRemovedLayer: (x: any) => set(() => ({ removedLayer: x })),
|
||||
}));
|
||||
|
||||
export const useActiveLayer = create<any>((set: any) => ({
|
||||
activeLayer: 1,
|
||||
setActiveLayer: (x: any) => set({ activeLayer: x }),
|
||||
activeLayer: 1,
|
||||
setActiveLayer: (x: any) => set({ activeLayer: x }),
|
||||
}));
|
||||
|
||||
export const useResetCamera = create<any>((set: any) => ({
|
||||
resetCamera: false,
|
||||
setResetCamera: (x: any) => set({ resetCamera: x }),
|
||||
resetCamera: false,
|
||||
setResetCamera: (x: any) => set({ resetCamera: x }),
|
||||
}));
|
||||
|
||||
export const useAddAction = create<any>((set: any) => ({
|
||||
addAction: null,
|
||||
setAddAction: (x: any) => set({ addAction: x }),
|
||||
addAction: null,
|
||||
setAddAction: (x: any) => set({ addAction: x }),
|
||||
}));
|
||||
|
||||
export const useActiveTool = create<any>((set: any) => ({
|
||||
activeTool: "Cursor",
|
||||
setActiveTool: (x: any) => set({ activeTool: x }),
|
||||
activeTool: "Cursor",
|
||||
setActiveTool: (x: any) => set({ activeTool: x }),
|
||||
}));
|
||||
|
||||
export const use2DUndoRedo = create<any>((set: any) => ({
|
||||
is2DUndoRedo: null,
|
||||
set2DUndoRedo: (x: any) => set({ is2DUndoRedo: x }),
|
||||
}))
|
||||
is2DUndoRedo: null,
|
||||
set2DUndoRedo: (x: any) => set({ is2DUndoRedo: x }),
|
||||
}));
|
||||
|
||||
export const useElevation = create<any>((set: any) => ({
|
||||
elevation: 45,
|
||||
setElevation: (x: any) => set({ elevation: x }),
|
||||
elevation: 45,
|
||||
setElevation: (x: any) => set({ elevation: x }),
|
||||
}));
|
||||
|
||||
export const useAzimuth = create<any>((set: any) => ({
|
||||
azimuth: -160,
|
||||
setAzimuth: (x: any) => set({ azimuth: x }),
|
||||
azimuth: -160,
|
||||
setAzimuth: (x: any) => set({ azimuth: x }),
|
||||
}));
|
||||
|
||||
export const useRenderDistance = create<any>((set: any) => ({
|
||||
renderDistance: 50,
|
||||
setRenderDistance: (x: any) => set({ renderDistance: x }),
|
||||
renderDistance: 50,
|
||||
setRenderDistance: (x: any) => set({ renderDistance: x }),
|
||||
}));
|
||||
|
||||
export const useCamMode = create<any>((set: any) => ({
|
||||
camMode: "ThirdPerson",
|
||||
setCamMode: (x: any) => set({ camMode: x }),
|
||||
camMode: "ThirdPerson",
|
||||
setCamMode: (x: any) => set({ camMode: x }),
|
||||
}));
|
||||
|
||||
export const useUserName = create<any>((set: any) => ({
|
||||
userName: "",
|
||||
setUserName: (x: any) => set({ userName: x }),
|
||||
userName: "",
|
||||
setUserName: (x: any) => set({ userName: x }),
|
||||
}));
|
||||
|
||||
export const useObjectPosition = create<any>((set: any) => ({
|
||||
objectPosition: { x: undefined, y: undefined, z: undefined },
|
||||
setObjectPosition: (newObjectPosition: any) => set({ objectPosition: newObjectPosition }),
|
||||
objectPosition: { x: undefined, y: undefined, z: undefined },
|
||||
setObjectPosition: (newObjectPosition: any) =>
|
||||
set({ objectPosition: newObjectPosition }),
|
||||
}));
|
||||
|
||||
export const useObjectScale = create<any>((set: any) => ({
|
||||
objectScale: { x: undefined, y: undefined, z: undefined },
|
||||
setObjectScale: (newObjectScale: any) => set({ objectScale: newObjectScale }),
|
||||
objectScale: { x: undefined, y: undefined, z: undefined },
|
||||
setObjectScale: (newObjectScale: any) => set({ objectScale: newObjectScale }),
|
||||
}));
|
||||
|
||||
export const useObjectRotation = create<any>((set: any) => ({
|
||||
objectRotation: { x: undefined, y: undefined, z: undefined },
|
||||
setObjectRotation: (newObjectRotation: any) => set({ objectRotation: newObjectRotation }),
|
||||
objectRotation: { x: undefined, y: undefined, z: undefined },
|
||||
setObjectRotation: (newObjectRotation: any) =>
|
||||
set({ objectRotation: newObjectRotation }),
|
||||
}));
|
||||
|
||||
export const useDrieTemp = create<any>((set: any) => ({
|
||||
drieTemp: undefined,
|
||||
setDrieTemp: (x: any) => set({ drieTemp: x }),
|
||||
drieTemp: undefined,
|
||||
setDrieTemp: (x: any) => set({ drieTemp: x }),
|
||||
}));
|
||||
|
||||
export const useActiveUsers = create<any>((set: any) => ({
|
||||
activeUsers: [],
|
||||
setActiveUsers: (x: any) => set({ activeUsers: x }),
|
||||
activeUsers: [],
|
||||
setActiveUsers: (x: any) => set({ activeUsers: x }),
|
||||
}));
|
||||
|
||||
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 } })),
|
||||
setTemperature: (value: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, temperature: value } })),
|
||||
setHumidity: (value: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, humidity: value } })),
|
||||
setTouch: (value: any) =>
|
||||
set((state: any) => ({
|
||||
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) => ({
|
||||
drawMaterialPath: false,
|
||||
setDrawMaterialPath: (x: any) => set({ drawMaterialPath: x }),
|
||||
drawMaterialPath: false,
|
||||
setDrawMaterialPath: (x: any) => set({ drawMaterialPath: x }),
|
||||
}));
|
||||
|
||||
export const useSelectedActionSphere = create<any>((set: any) => ({
|
||||
selectedActionSphere: undefined,
|
||||
setSelectedActionSphere: (x: any) => set({ selectedActionSphere: x }),
|
||||
selectedActionSphere: undefined,
|
||||
setSelectedActionSphere: (x: any) => set({ selectedActionSphere: x }),
|
||||
}));
|
||||
|
||||
export const useSelectedPath = create<any>((set: any) => ({
|
||||
selectedPath: undefined,
|
||||
setSelectedPath: (x: any) => set({ selectedPath: x }),
|
||||
selectedPath: undefined,
|
||||
setSelectedPath: (x: any) => set({ selectedPath: x }),
|
||||
}));
|
||||
|
||||
interface Path {
|
||||
modeluuid: string;
|
||||
modelName: string;
|
||||
points: {
|
||||
uuid: string;
|
||||
position: [number, number, number];
|
||||
rotation: [number, number, number];
|
||||
actions: { uuid: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | [];
|
||||
triggers: { uuid: string; type: string; isUsed: boolean }[] | [];
|
||||
}[];
|
||||
pathPosition: [number, number, number];
|
||||
pathRotation: [number, number, number];
|
||||
speed: number;
|
||||
modeluuid: string;
|
||||
modelName: string;
|
||||
points: {
|
||||
uuid: string;
|
||||
position: [number, number, number];
|
||||
rotation: [number, number, number];
|
||||
actions:
|
||||
| {
|
||||
uuid: string;
|
||||
type: string;
|
||||
material: string;
|
||||
delay: number | string;
|
||||
spawnInterval: number | string;
|
||||
isUsed: boolean;
|
||||
}[]
|
||||
| [];
|
||||
triggers: { uuid: string; type: string; isUsed: boolean }[] | [];
|
||||
}[];
|
||||
pathPosition: [number, number, number];
|
||||
pathRotation: [number, number, number];
|
||||
speed: number;
|
||||
}
|
||||
|
||||
interface SimulationPathsStore {
|
||||
simulationPaths: Path[];
|
||||
setSimulationPaths: (paths: Path[]) => void;
|
||||
simulationPaths: Path[];
|
||||
setSimulationPaths: (paths: Path[]) => void;
|
||||
}
|
||||
|
||||
export const useSimulationPaths = create<SimulationPathsStore>((set) => ({
|
||||
simulationPaths: [],
|
||||
setSimulationPaths: (paths) => set({ simulationPaths: paths }),
|
||||
simulationPaths: [],
|
||||
setSimulationPaths: (paths) => set({ simulationPaths: paths }),
|
||||
}));
|
||||
|
||||
|
||||
// interface Point {
|
||||
// uuid: string;
|
||||
// position: [number, number, number];
|
||||
|
@ -363,40 +383,75 @@ export const useSimulationPaths = create<SimulationPathsStore>((set) => ({
|
|||
// setSimulationPaths: (paths) => set({ simulationPaths: paths }),
|
||||
// }));
|
||||
|
||||
|
||||
export const useConnections = create<Types.ConnectionStore>((set) => ({
|
||||
connections: [],
|
||||
connections: [],
|
||||
|
||||
setConnections: (connections) => set({ connections }),
|
||||
setConnections: (connections) => set({ connections }),
|
||||
|
||||
addConnection: (newConnection) =>
|
||||
set((state) => ({
|
||||
connections: [...state.connections, newConnection],
|
||||
})),
|
||||
addConnection: (newConnection) =>
|
||||
set((state) => ({
|
||||
connections: [...state.connections, newConnection],
|
||||
})),
|
||||
|
||||
removeConnection: (fromUUID, toUUID) =>
|
||||
set((state) => ({
|
||||
connections: state.connections
|
||||
.map((connection) =>
|
||||
connection.fromUUID === fromUUID
|
||||
? {
|
||||
...connection,
|
||||
toConnections: connection.toConnections.filter(
|
||||
(to) => to.toUUID !== toUUID
|
||||
),
|
||||
}
|
||||
: connection
|
||||
)
|
||||
.filter((connection) => connection.toConnections.length > 0),
|
||||
})),
|
||||
removeConnection: (fromUUID, toUUID) =>
|
||||
set((state) => ({
|
||||
connections: state.connections
|
||||
.map((connection) =>
|
||||
connection.fromUUID === fromUUID
|
||||
? {
|
||||
...connection,
|
||||
toConnections: connection.toConnections.filter(
|
||||
(to) => to.toUUID !== toUUID
|
||||
),
|
||||
}
|
||||
: connection
|
||||
)
|
||||
.filter((connection) => connection.toConnections.length > 0),
|
||||
})),
|
||||
}));
|
||||
|
||||
export const useIsConnecting = create<any>((set: any) => ({
|
||||
isConnecting: false,
|
||||
setIsConnecting: (x: any) => set({ isConnecting: x }),
|
||||
isConnecting: false,
|
||||
setIsConnecting: (x: any) => set({ isConnecting: x }),
|
||||
}));
|
||||
|
||||
export const useStartSimulation = create<any>((set: any) => ({
|
||||
startSimulation: false,
|
||||
setStartSimulation: (x: any) => set({ startSimulation: x }),
|
||||
}));
|
||||
startSimulation: false,
|
||||
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] })),
|
||||
}));
|
|
@ -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[];
|
||||
panelOrder: Side[];
|
||||
lockedPanels: Side[];
|
||||
zoneId: string;
|
||||
zoneViewPortTarget: number[];
|
||||
zoneViewPortPosition: number[];
|
||||
widgets: Widget[];
|
||||
}
|
||||
|
||||
interface SelectedZoneStore {
|
||||
selectedZone: SelectedZoneState;
|
||||
setSelectedZone: (zone: Partial<SelectedZoneState> | ((prev: SelectedZoneState) => SelectedZoneState)) => void;
|
||||
setSelectedZone: (
|
||||
zone:
|
||||
| Partial<SelectedZoneState>
|
||||
| ((prev: SelectedZoneState) => SelectedZoneState)
|
||||
) => void;
|
||||
}
|
||||
|
||||
export const useSelectedZoneStore = create<SelectedZoneStore>((set) => ({
|
||||
selectedZone: {
|
||||
zoneName: "",
|
||||
activeSides: [],
|
||||
panelOrder: [],
|
||||
lockedPanels: [],
|
||||
widgets: [],
|
||||
zoneName: "", // Empty string initially
|
||||
activeSides: [], // Empty array
|
||||
panelOrder: [], // Empty array
|
||||
lockedPanels: [], // Empty array
|
||||
zoneId: "",
|
||||
zoneViewPortTarget: [],
|
||||
zoneViewPortPosition: [],
|
||||
widgets: [], // Empty array
|
||||
},
|
||||
setSelectedZone: (zone) =>
|
||||
set((state) => ({
|
||||
|
@ -38,4 +48,4 @@ export const useSelectedZoneStore = create<SelectedZoneStore>((set) => ({
|
|||
? zone(state.selectedZone) // Handle functional updates
|
||||
: { ...state.selectedZone, ...zone }, // Handle partial updates
|
||||
})),
|
||||
}));
|
||||
}));
|
||||
|
|
|
@ -184,4 +184,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,25 +161,49 @@
|
|||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
background-color: var(--accent-color);
|
||||
|
||||
background-color: var(--highlight-accent-color);
|
||||
cursor: pointer;
|
||||
@include flex-center;
|
||||
position: fixed;
|
||||
bottom: 60px;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
transition: background-color 0.3s, transform 0.3s;
|
||||
color: var(--background-color);
|
||||
// transform: none;
|
||||
color: var(--accent-color);
|
||||
z-index: 100;
|
||||
|
||||
isolation: isolate;
|
||||
font-weight: 700;
|
||||
&:hover {
|
||||
font-weight: 500;
|
||||
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 {
|
||||
from {
|
||||
|
|
48
compose.yaml
48
compose.yaml
|
@ -1,24 +1,24 @@
|
|||
services:
|
||||
frontend:
|
||||
build:
|
||||
context: ./app
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- REACT_APP_SERVER_SOCKET_API_BASE_URL=185.100.212.76:8000
|
||||
- REACT_APP_SERVER_REST_API_BASE_URL=185.100.212.76:5000
|
||||
- REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011
|
||||
container_name: dwinzo-beta
|
||||
stdin_open: true
|
||||
tty: true
|
||||
ports:
|
||||
- "8200:3000"
|
||||
environment:
|
||||
- WDS_SOCKET_PORT=0
|
||||
- PORT=3000
|
||||
- DOCSIFY_PORT=8201
|
||||
volumes:
|
||||
- ./app:/app
|
||||
|
||||
volumes:
|
||||
frontend:
|
||||
driver: local
|
||||
services:
|
||||
frontend:
|
||||
build:
|
||||
context: ./app
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- REACT_APP_SERVER_SOCKET_API_BASE_URL=185.100.212.76:8000
|
||||
- REACT_APP_SERVER_REST_API_BASE_URL=185.100.212.76:5000
|
||||
- REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011
|
||||
container_name: dwinzo-beta
|
||||
stdin_open: true
|
||||
tty: true
|
||||
ports:
|
||||
- "8200:3000"
|
||||
environment:
|
||||
- WDS_SOCKET_PORT=0
|
||||
- PORT=3000
|
||||
- DOCSIFY_PORT=8201
|
||||
volumes:
|
||||
- ./app:/app
|
||||
|
||||
volumes:
|
||||
frontend:
|
||||
driver: local
|
||||
|
|
Loading…
Reference in New Issue