Merge pull request 'simulation' (#13) from simulation into main

Reviewed-on: http://185.100.212.76:7776/Dwinzo-Beta/Dwinzo_dev/pulls/13
This commit was merged in pull request #13.
This commit is contained in:
2025-03-27 12:27:54 +00:00
28 changed files with 23183 additions and 22726 deletions

View File

@@ -75,7 +75,7 @@ export function CommentsIcon() {
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clip-path="url(#clip0_2926_17620)">
<g clipPath="url(#clip0_2926_17620)">
<path
fillRule="evenodd"
clipRule="evenodd"

View File

@@ -108,7 +108,7 @@ const SideBarRight: React.FC = () => {
{subModule === "mechanics" && !selectedActionSphere && (
<div className="sidebar-right-container">
<div className="sidebar-right-content-container">
<MachineMechanics />
{/* <MachineMechanics /> */}
</div>
</div>
)}

View File

@@ -1,4 +1,4 @@
import React, { useRef, useState } from "react";
import React, { useRef, useState, useMemo, useEffect } from "react";
import {
AddIcon,
InfoIcon,
@@ -11,80 +11,332 @@ import LabledDropdown from "../../../ui/inputs/LabledDropdown";
import RegularDropDown from "../../../ui/inputs/RegularDropDown";
import { handleResize } from "../../../../functions/handleResizePannel";
import EyeDropInput from "../../../ui/inputs/EyeDropInput";
import { useSelectedActionSphere } from "../../../../store/store";
import { useSelectedActionSphere, useSelectedPath, useSimulationPaths } from "../../../../store/store";
import * as THREE from 'three';
import InputToggle from "../../../ui/inputs/InputToggle";
const MachineMechanics: React.FC = () => {
const { selectedActionSphere } = useSelectedActionSphere();
console.log("selectedActionSphere: ", selectedActionSphere);
const [actionList, setActionList] = useState<string[]>([]);
const [triggerList, setTriggerList] = useState<string[]>([]);
const [selectedItem, setSelectedItem] = useState<{
type: "action" | "trigger";
name: string;
} | null>(null);
const { selectedPath, setSelectedPath } = useSelectedPath();
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
const actionsContainerRef = useRef<HTMLDivElement>(null);
const triggersContainerRef = useRef<HTMLDivElement>(null);
const selectedPoint = useMemo(() => {
if (!selectedActionSphere) return null;
return simulationPaths.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.point.uuid);
}, [selectedActionSphere, simulationPaths]);
const handleAddAction = () => {
setActionList([...actionList, `Action ${actionList.length + 1}`]);
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) => {
if (point.uuid === selectedActionSphere.point.uuid) {
const actionIndex = point.actions.length;
const newAction = {
uuid: THREE.MathUtils.generateUUID(),
name: `Action ${actionIndex + 1}`,
type: 'Inherit',
material: 'Inherit',
delay: 'Inherit',
spawnInterval: 'Inherit',
isUsed: false
};
return { ...point, actions: [...point.actions, newAction] };
}
return point;
}),
}));
setSimulationPaths(updatedPaths);
};
const handleDeleteAction = (uuid: string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) }
: point
),
}));
setSimulationPaths(updatedPaths);
};
const handleActionSelect = (uuid: string, actionType: string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) =>
action.uuid === uuid
? {
...action,
type: actionType,
// Reset dependent fields when type changes
material: actionType === 'Spawn' || actionType === 'Swap' ? 'Inherit' : action.material,
delay: actionType === 'Delay' ? 'Inherit' : action.delay,
spawnInterval: actionType === 'Spawn' ? 'Inherit' : action.spawnInterval
}
: action
),
}
: point
),
}));
setSimulationPaths(updatedPaths);
// Update the selected item to reflect changes
if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) {
const updatedAction = updatedPaths
.flatMap(path => path.points)
.find(p => p.uuid === selectedActionSphere.point.uuid)
?.actions.find(a => a.uuid === uuid);
if (updatedAction) {
setSelectedItem({
type: "action",
item: updatedAction
});
}
}
};
// Modified handleMaterialSelect to ensure it only applies to relevant action types
const handleMaterialSelect = (uuid: string, material: string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) =>
action.uuid === uuid &&
(action.type === 'Spawn' || action.type === 'Swap')
? { ...action, material }
: action
),
}
: point
),
}));
setSimulationPaths(updatedPaths);
// Update selected item if it's the current action
if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) {
setSelectedItem({
...selectedItem,
item: {
...selectedItem.item,
material
}
});
}
};
const handleDelayChange = (uuid: string, delay: number | string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) =>
action.uuid === uuid ? { ...action, delay } : action
),
}
: point
),
}));
setSimulationPaths(updatedPaths);
};
const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) =>
action.uuid === uuid ? { ...action, spawnInterval } : action
),
}
: point
),
}));
setSimulationPaths(updatedPaths);
};
const handleSpeedChange = (speed: number) => {
if (!selectedPath) return;
const updatedPaths = simulationPaths.map((path) =>
path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path
);
setSimulationPaths(updatedPaths);
setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } });
};
const handleAddTrigger = () => {
setTriggerList([...triggerList, `Trigger ${triggerList.length + 1}`]);
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) => {
if (point.uuid === selectedActionSphere.point.uuid) {
const triggerIndex = point.triggers.length;
const newTrigger = {
uuid: THREE.MathUtils.generateUUID(),
name: `Trigger ${triggerIndex + 1}`,
type: '',
isUsed: false
};
return { ...point, triggers: [...point.triggers, newTrigger] };
}
return point;
}),
}));
setSimulationPaths(updatedPaths);
};
const handleRemoveAction = (index: number) => {
setActionList(actionList.filter((_, i) => i !== index));
if (
selectedItem?.type === "action" &&
selectedItem.name === actionList[index]
) {
setSelectedItem(null);
const handleDeleteTrigger = (uuid: string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) }
: point
),
}));
setSimulationPaths(updatedPaths);
};
const handleTriggerSelect = (uuid: string, triggerType: string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
triggers: point.triggers.map((trigger) =>
trigger.uuid === uuid ? { ...trigger, type: triggerType } : trigger
),
}
: point
),
}));
setSimulationPaths(updatedPaths);
};
// Update the toggle handlers to immediately update the selected item
const handleActionToggle = (uuid: string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) => ({
...action,
isUsed: action.uuid === uuid ? !action.isUsed : false,
})),
}
: point
),
}));
setSimulationPaths(updatedPaths);
// Immediately update the selected item if it's the one being toggled
if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) {
setSelectedItem({
...selectedItem,
item: {
...selectedItem.item,
isUsed: !selectedItem.item.isUsed
}
});
}
};
const handleRemoveTrigger = (index: number) => {
setTriggerList(triggerList.filter((_, i) => i !== index));
if (
selectedItem?.type === "trigger" &&
selectedItem.name === triggerList[index]
) {
setSelectedItem(null);
// Do the same for trigger toggle
const handleTriggerToggle = (uuid: string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
triggers: point.triggers.map((trigger) => ({
...trigger,
isUsed: trigger.uuid === uuid ? !trigger.isUsed : false,
})),
}
: point
),
}));
setSimulationPaths(updatedPaths);
// Immediately update the selected item if it's the one being toggled
if (selectedItem?.type === "trigger" && selectedItem.item.uuid === uuid) {
setSelectedItem({
...selectedItem,
item: {
...selectedItem.item,
isUsed: !selectedItem.item.isUsed
}
});
}
};
const handleSelectItem = (type: "action" | "trigger", name: string) => {
setSelectedItem({ type, name });
};
const [selectedItem, setSelectedItem] = useState<{ type: "action" | "trigger"; item: any; } | null>(null);
const [processes, setProcesses] = useState<string[]>([]);
const [activeProcess, setActiveProcesses] = useState<string>();
const handleSelect = (option: string) => {
setActiveProcesses(option); // Update the active option state
};
const handleAddProcess = () => {
const newProcess = `Process ${processes.length + 1}`; // Generate new process name dynamically
setProcesses((prevProcesses) => [...prevProcesses, newProcess]); // Update the state with the new process
};
useEffect(() => {
setSelectedItem(null); // Reset selectedItem when selectedActionSphere changes
}, [selectedActionSphere]);
return (
<div className="machine-mechanics-container">
<div className="machine-mechanics-header">
{selectedActionSphere?.path?.modelName || "path name not found"}
{selectedActionSphere?.path?.modelName || "point name not found"}
</div>
{/* <div className="process-list-container">
<div className="label">Process:</div>
<RegularDropDown
header={activeProcess || "add process ->"}
options={processes}
onSelect={handleSelect}
/>
<div className="add-new-process" onClick={handleAddProcess}>
<AddIcon />
</div>
</div> */}
<div className="machine-mechanics-content-container">
<div className="actions">
<div className="header">
@@ -99,25 +351,24 @@ const MachineMechanics: React.FC = () => {
style={{ height: "120px" }}
>
<div className="list-container">
{actionList.map((action, index) => (
{selectedPoint?.actions.map((action) => (
<div
key={index}
className={`list-item ${
selectedItem?.type === "action" &&
selectedItem.name === action
? "active"
: ""
}`}
key={action.uuid}
className={`list-item ${selectedItem?.type === "action" &&
selectedItem.item?.uuid === action.uuid
? "active"
: ""
}`}
>
<div
className="value"
onClick={() => handleSelectItem("action", action)}
onClick={() => setSelectedItem({ type: "action", item: action })}
>
<RenameInput value={action} />
<RenameInput value={action.name} />
</div>
<div
className="remove-button"
onClick={() => handleRemoveAction(index)}
onClick={() => handleDeleteAction(action.uuid)}
>
<RemoveIcon />
</div>
@@ -146,25 +397,24 @@ const MachineMechanics: React.FC = () => {
style={{ height: "120px" }}
>
<div className="list-container">
{triggerList.map((trigger, index) => (
{selectedPoint?.triggers.map((trigger) => (
<div
key={index}
className={`list-item ${
selectedItem?.type === "trigger" &&
selectedItem.name === trigger
? "active"
: ""
}`}
key={trigger.uuid}
className={`list-item ${selectedItem?.type === "trigger" &&
selectedItem.item?.uuid === trigger.uuid
? "active"
: ""
}`}
>
<div
className="value"
onClick={() => handleSelectItem("trigger", trigger)}
onClick={() => setSelectedItem({ type: "trigger", item: trigger })}
>
<RenameInput value={trigger} />
<RenameInput value={trigger.name} />
</div>
<div
className="remove-button"
onClick={() => handleRemoveTrigger(index)}
onClick={() => handleDeleteTrigger(trigger.uuid)}
>
<RemoveIcon />
</div>
@@ -183,28 +433,101 @@ const MachineMechanics: React.FC = () => {
<div className="selected-properties-container">
{selectedItem && (
<>
<div className="properties-header">{selectedItem.name}</div>
<LabledDropdown
defaultOption="On-hit"
options={["On-hit", "Buffer"]}
/>
<InputWithDropDown
label="Speed"
value=""
activeOption=".mm"
onChange={() => {}}
/>
<EyeDropInput />
<div className="properties-header">{selectedItem.item.name}</div>
{selectedItem.type === "action" && (
<>
<InputToggle
inputKey="enableTrigger"
label="Enable Trigger"
value={selectedItem.item.isUsed}
onClick={() => handleActionToggle(selectedItem.item.uuid)}
/>
<LabledDropdown
defaultOption={selectedItem.item.type}
options={["Inherit", "Spawn", "Swap", "Despawn", "Delay"]}
onSelect={(option) => handleActionSelect(selectedItem.item.uuid, option)}
/>
{/* Only show material dropdown for Spawn/Swap actions */}
{(selectedItem.item.type === 'Spawn' || selectedItem.item.type === 'Swap') && (
<LabledDropdown
label={selectedItem.item.type === 'Spawn' ? 'Spawn Material' : 'Swap Material'}
defaultOption={selectedItem.item.material}
options={["Inherit", "Crate", "Box"]}
onSelect={(option) => handleMaterialSelect(selectedItem.item.uuid, option)}
/>
)}
{/* Only show delay input for Delay actions */}
{selectedItem.item.type === 'Delay' && (
<InputWithDropDown
label="Delay Time"
value={selectedItem.item.delay === 'Inherit'
? undefined
: selectedItem.item.delay}
onChange={(value) => {
const numValue = parseInt(value);
handleDelayChange(
selectedItem.item.uuid,
!value ? 'Inherit' : numValue
);
}}
/>
)}
{/* Only show spawn interval for Spawn actions */}
{selectedItem.item.type === 'Spawn' && (
<InputWithDropDown
label="Spawn Interval"
min={0}
defaultValue={selectedItem.item.spawnInterval === "Inherit" ? "" : selectedItem.item.spawnInterval.toString()}
value={selectedItem.item.spawnInterval === "Inherit" ? "" : selectedItem.item.spawnInterval.toString()}
onChange={(value) => {
handleSpawnIntervalChange(selectedItem.item.uuid, (value === "") ? "Inherit" : parseInt(value));
}}
/>
)}
</>
)}
{selectedItem.type === "trigger" && (
<>
<InputToggle
inputKey="enableTrigger"
label="Enable Trigger"
value={selectedItem.item.isUsed}
onClick={() => handleTriggerToggle(selectedItem.item.uuid)}
/>
<LabledDropdown
defaultOption={selectedItem.item.type || "Select Trigger Type"}
options={["On-Hit", "Buffer"]}
onSelect={(option) => handleTriggerSelect(selectedItem.item.uuid, option)}
/>
</>
)}
</>
)}
{selectedPath && !selectedItem && (
<div className="speed-control">
<InputWithDropDown
label="Path Speed"
value={selectedPath.path.speed.toString()}
onChange={(value) => handleSpeedChange(parseFloat(value))}
/>
</div>
)}
</div>
<div className="footer">
<InfoIcon />
By Selecting Path, you can create Object Triggers.
By selecting points, you can create events and triggers.
</div>
</div>
</div>
);
};
export default MachineMechanics;
export default MachineMechanics;

View File

@@ -1,115 +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>
</>
)
}
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

View File

@@ -1,77 +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>
</>
)
}
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

View File

@@ -7,7 +7,6 @@ interface LoadingPageProps {
}
const LoadingPage: React.FC<LoadingPageProps> = ({ progress }) => {
// Ensure progress stays within 0-100 range
const validatedProgress = Math.min(100, Math.max(0, progress));
return (

View File

@@ -1,6 +1,7 @@
import React, { useEffect, useRef, useState, useCallback } from "react";
import { Widget } from "../../../store/useWidgetStore";
import { MoveArrowLeft, MoveArrowRight } from "../../icons/SimulationIcons";
import { InfoIcon } from "../../icons/ExportCommonIcons";
// Define the type for `Side`
type Side = "top" | "bottom" | "left" | "right";
@@ -153,33 +154,40 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
)}
{/* Zones Wrapper */}
<div ref={containerRef} className="zones-wrapper">
{Object.keys(zonesData).map((zoneName, index) => (
<div
key={index}
className={`zone ${
selectedZone.zoneName === zoneName ? "active" : ""
}`}
onClick={() => {
console.log("zoneName: ", zoneName);
setSelectedZone({
zoneName,
activeSides: zonesData[zoneName].activeSides || [],
panelOrder: zonesData[zoneName].panelOrder || [],
lockedPanels: zonesData[zoneName].lockedPanels || [],
widgets: zonesData[zoneName].widgets || [],
zoneId: zonesData[zoneName]?.zoneId || "",
zoneViewPortTarget:
zonesData[zoneName].zoneViewPortTarget || [],
zoneViewPortPosition:
zonesData[zoneName].zoneViewPortPosition || [],
});
}}
>
{zoneName}
</div>
))}
</div>
{Object.keys(zonesData).length !== 0 ? (
<div ref={containerRef} className="zones-wrapper">
{Object.keys(zonesData).map((zoneName, index) => (
<div
key={index}
className={`zone ${
selectedZone.zoneName === zoneName ? "active" : ""
}`}
onClick={() => {
console.log("zoneName: ", zoneName);
setSelectedZone({
zoneName,
activeSides: zonesData[zoneName].activeSides || [],
panelOrder: zonesData[zoneName].panelOrder || [],
lockedPanels: zonesData[zoneName].lockedPanels || [],
widgets: zonesData[zoneName].widgets || [],
zoneId: zonesData[zoneName]?.zoneId || "",
zoneViewPortTarget:
zonesData[zoneName].zoneViewPortTarget || [],
zoneViewPortPosition:
zonesData[zoneName].zoneViewPortPosition || [],
});
}}
>
{zoneName}
</div>
))}
</div>
) : (
<div className="no-zone">
<InfoIcon />
No zones? Create one!
</div>
)}
{/* Right Arrow */}
{showRightArrow && (

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React from "react";
interface InputToggleProps {
label: string; // Represents the toggle state (on/off)
@@ -7,23 +7,18 @@ interface InputToggleProps {
inputKey: string;
}
// Update InputToggle.tsx to be fully controlled
const InputToggle: React.FC<InputToggleProps> = ({
label,
onClick,
value = false,
inputKey,
}) => {
const [activeValue, setActiveValue] = useState<boolean>(value);
// Remove internal state and use the value prop directly
function handleOnClick() {
setActiveValue(!activeValue);
if (onClick) onClick();
}
useEffect(() => {
setActiveValue(value);
}, [value]);
return (
<div className="input-toggle-container">
<label htmlFor={`toogle-input-${inputKey}`} className="label">
@@ -33,15 +28,16 @@ const InputToggle: React.FC<InputToggleProps> = ({
<div
className="check-box-style"
style={{
left: activeValue ? "50%" : "2px",
background: activeValue ? "" : "var(--text-disabled)",
left: value ? "50%" : "2px",
background: value ? "" : "var(--text-disabled)",
}}
></div>
<input
type="checkbox"
name=""
id={`toogle-input-${inputKey}`}
defaultChecked={value}
checked={value}
readOnly
/>
</div>
</div>

View File

@@ -4,21 +4,27 @@ import RenameInput from "./RenameInput";
type InputWithDropDownProps = {
label: string;
value: string;
min?: number
defaultValue?: string;
options?: string[]; // Array of dropdown options
activeOption?: string; // The currently active dropdown option
onClick?: () => void;
onChange: (newValue: string) => void;
editableLabel?: boolean;
placeholder?: string; // New placeholder prop
};
const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
label,
value,
min,
defaultValue,
options,
activeOption,
onClick,
onChange,
editableLabel = false,
placeholder = "Inherit", // Default empty placeholder
}) => {
const separatedWords = label
.split(/(?=[A-Z])/)
@@ -38,11 +44,13 @@ const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
)}
<div className="input default" id={separatedWords}>
<input
type="text"
min={min}
type="number"
defaultValue={value}
onChange={(e) => {
onChange(e.target.value);
}}
placeholder={placeholder} // Added placeholder prop
/>
{activeOption && (
@@ -73,4 +81,4 @@ const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
);
};
export default InputWithDropDown;
export default InputWithDropDown;

View File

@@ -1,29 +1,49 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import RegularDropDown from "./RegularDropDown";
type LabledDropdownProps = {
defaultOption: string; // Initial active option
options: string[]; // Array of dropdown options
label?: string; // Customizable label text
onSelect?: (option: string) => void; // Callback when option is selected
className?: string; // Additional className for styling
disabled?: boolean; // Disable dropdown
search?: boolean; // Enable/disable search functionality
};
const LabledDropdown: React.FC<LabledDropdownProps> = ({ defaultOption, options }) => {
const [activeOption, setActiveOption] = useState(defaultOption); // State for active option
const LabledDropdown: React.FC<LabledDropdownProps> = ({
defaultOption,
options,
label = "Type",
onSelect,
className = "",
search = false
}) => {
const [activeOption, setActiveOption] = useState(defaultOption);
// Update active option if defaultOption changes
useEffect(() => {
setActiveOption(defaultOption);
}, [defaultOption]);
const handleSelect = (option: string) => {
setActiveOption(option); // Update the active option state
setActiveOption(option);
if (onSelect) {
onSelect(option);
}
};
return (
<div className="value-field-container">
<div className="label">Type</div>
<div className={`value-field-container ${className}`}>
<div className="label">{label}</div>
<RegularDropDown
header={activeOption} // Display the current active option
options={options} // Use the options from props
onSelect={handleSelect} // Handle option selection
search = {false}
header={activeOption}
options={options}
onSelect={handleSelect}
search={search}
/>
</div>
);
};
export default LabledDropdown;
export default LabledDropdown;