the component sets are being properly constructed and passed up to the mode dialog that will control adding the interactions to them
This commit is contained in:
parent
ea81610635
commit
393a2f77dc
4 changed files with 512 additions and 9 deletions
|
|
@ -74,6 +74,7 @@ import SearchSelect, { Option } from "common/SearchSelect";
|
|||
import Edit from "@mui/icons-material/Edit";
|
||||
import { makeStyles, styled } from "@mui/styles";
|
||||
import ButtonGroup from "common/ButtonGroup";
|
||||
import ModeChangeDialog from "./conditioning/modeChangeDialog";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => {
|
||||
return ({
|
||||
|
|
@ -256,7 +257,7 @@ export default function BinVisualizer(props: Props) {
|
|||
const [cfmLowOpen, setCFMLowOpen] = useState(false);
|
||||
const [cfmHighOpen, setCFMHighOpen] = useState(false);
|
||||
const [{ user }] = useGlobalState();
|
||||
const [newPreset, setNewPreset] = useState<pond.BinMode>(pond.BinMode.BIN_MODE_NONE);
|
||||
// const [newPreset, setNewPreset] = useState<pond.BinMode>(pond.BinMode.BIN_MODE_NONE);
|
||||
const [newBinMode, setNewBinMode] = useState<pond.BinMode>(pond.BinMode.BIN_MODE_NONE);
|
||||
const [selectedCable, setSelectedCable] = useState<GrainCable>();
|
||||
const [openNodeDialog, setOpenNodeDialog] = useState(false);
|
||||
|
|
@ -293,6 +294,8 @@ export default function BinVisualizer(props: Props) {
|
|||
const [activePlenumIndex, setActivePlenumIndex] = useState(0)
|
||||
const [combinedPlenums, setCombinedPlenums] = useState<CombinedPlenum[]>([])
|
||||
|
||||
const [openModeChange, setOpenModeChange] = useState(false)
|
||||
|
||||
// const StyledToggle = styled(ToggleButton)(({ theme }: { theme: Theme }) => ({
|
||||
// root: {
|
||||
// backgroundColor: "transparent",
|
||||
|
|
@ -373,7 +376,7 @@ export default function BinVisualizer(props: Props) {
|
|||
useEffect(() => {
|
||||
setIsCustomInventory(bin.storage() !== pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN);
|
||||
setStorageType(bin.storage());
|
||||
setNewPreset(pond.BinMode.BIN_MODE_NONE);
|
||||
// setNewPreset(pond.BinMode.BIN_MODE_NONE);
|
||||
if (bin.settings.inventory) {
|
||||
setMoistureInput(bin.settings.inventory.initialMoisture.toString());
|
||||
setCustomTypeName(bin.settings.inventory.customTypeName);
|
||||
|
|
@ -2020,16 +2023,18 @@ export default function BinVisualizer(props: Props) {
|
|||
};
|
||||
|
||||
const setModeStorage = () => {
|
||||
setNewPreset(pond.BinMode.BIN_MODE_STORAGE);
|
||||
// setNewPreset(pond.BinMode.BIN_MODE_STORAGE);
|
||||
setNewBinMode(pond.BinMode.BIN_MODE_STORAGE);
|
||||
setOpenModeChange(true)
|
||||
};
|
||||
|
||||
const setModeCooldown = () => {
|
||||
if (bin.settings.mode === pond.BinMode.BIN_MODE_COOLDOWN) {
|
||||
return;
|
||||
}
|
||||
setNewPreset(pond.BinMode.BIN_MODE_COOLDOWN);
|
||||
// setNewPreset(pond.BinMode.BIN_MODE_COOLDOWN);
|
||||
setNewBinMode(pond.BinMode.BIN_MODE_COOLDOWN);
|
||||
setOpenModeChange(true)
|
||||
};
|
||||
|
||||
const setModeDrying = () => {
|
||||
|
|
@ -2037,16 +2042,17 @@ export default function BinVisualizer(props: Props) {
|
|||
bin.settings.inventory &&
|
||||
bin.settings.inventory?.initialMoisture < bin.settings.inventory?.targetMoisture
|
||||
) {
|
||||
setNewPreset(pond.BinMode.BIN_MODE_HYDRATING);
|
||||
// setNewPreset(pond.BinMode.BIN_MODE_HYDRATING);
|
||||
setNewBinMode(pond.BinMode.BIN_MODE_HYDRATING);
|
||||
} else {
|
||||
setNewPreset(pond.BinMode.BIN_MODE_DRYING);
|
||||
// setNewPreset(pond.BinMode.BIN_MODE_DRYING);
|
||||
setNewBinMode(pond.BinMode.BIN_MODE_DRYING);
|
||||
}
|
||||
setOpenModeChange(true)
|
||||
};
|
||||
|
||||
const closeMoistureDialog = () => {
|
||||
setNewPreset(0);
|
||||
// setNewPreset(0);
|
||||
setNewBinMode(bin.settings.mode);
|
||||
setShowInputMoisture(false);
|
||||
};
|
||||
|
|
@ -2107,7 +2113,7 @@ export default function BinVisualizer(props: Props) {
|
|||
<DialogActions>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setNewPreset(0);
|
||||
// setNewPreset(0);
|
||||
setNewBinMode(bin.settings.mode);
|
||||
setShowInputMoisture(false);
|
||||
}}
|
||||
|
|
@ -2170,7 +2176,7 @@ export default function BinVisualizer(props: Props) {
|
|||
{cfmHighDialog()}
|
||||
{changeGrain()}
|
||||
{storageTimeDialog()}
|
||||
<DevicePresetsFromPicker
|
||||
{/* <DevicePresetsFromPicker
|
||||
preferences={preferences}
|
||||
binKey={bin.key()}
|
||||
devices={devices}
|
||||
|
|
@ -2184,6 +2190,21 @@ export default function BinVisualizer(props: Props) {
|
|||
binCables={cables}
|
||||
compDevMap={componentDevices}
|
||||
presets={binPresets}
|
||||
/> */}
|
||||
<ModeChangeDialog
|
||||
binKey={bin.key()}
|
||||
binMode={newBinMode}
|
||||
devices={devices}
|
||||
open={openModeChange}
|
||||
binCables={cables}
|
||||
compDevMap={componentDevices}
|
||||
preferences={preferences}
|
||||
onClose={(refresh) => {
|
||||
setShowInputMoisture(false)
|
||||
setOpenModeChange(false)
|
||||
if(refresh) updateBin();
|
||||
}}
|
||||
|
||||
/>
|
||||
<Box paddingRight={1}>
|
||||
{binMode()}
|
||||
|
|
|
|||
82
src/bin/conditioning/conditioningSelector.tsx
Normal file
82
src/bin/conditioning/conditioningSelector.tsx
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import { Box, Checkbox, DialogActions, DialogContent, FormControlLabel, Typography } from "@mui/material"
|
||||
import { Ambient } from "models/Ambient"
|
||||
import { Controller } from "models/Controller"
|
||||
import { Plenum } from "models/Plenum"
|
||||
import React, { useEffect, useState } from "react"
|
||||
import PickComponentSet, { ComponentSet } from "./pickComponentSet"
|
||||
import { cloneDeep } from "lodash"
|
||||
|
||||
|
||||
interface Props {
|
||||
plenums: Plenum[]
|
||||
ambients: Ambient[]
|
||||
heaters: Controller[]
|
||||
fans: Controller[]
|
||||
updateSets: (sets: ComponentSet[]) => void
|
||||
}
|
||||
|
||||
|
||||
export default function ConditioningSelector(props: Props){
|
||||
const {plenums, ambients, heaters, fans, updateSets} = props
|
||||
const [currentSets, setCurrentSets] = useState<ComponentSet[]>([])
|
||||
|
||||
const sensorIndex = (key: string) => {
|
||||
let index = -1
|
||||
currentSets.forEach((set, i) => {
|
||||
if(set.sensor.key() === key){
|
||||
index = i
|
||||
}
|
||||
})
|
||||
return index
|
||||
}
|
||||
|
||||
const setUpdate = (key: string, set?: ComponentSet) => {
|
||||
let sets = cloneDeep(currentSets)
|
||||
let index = sensorIndex(key)
|
||||
//if the set is defined, add it to the existing sets as long as it doesn't already exist
|
||||
if(set){
|
||||
//check if there is a set that has a sensor with the key
|
||||
if(index !== -1){
|
||||
sets[index] = set //replace it with the new set
|
||||
}else{//if the set was not found ie is new
|
||||
sets.push(set)//add the new set
|
||||
}
|
||||
}else{ //if the set is undefined
|
||||
if (index !== -1){
|
||||
sets.splice(index, 1)//remove it from the sets
|
||||
}
|
||||
//no else is needed because if it doesn't exist nothing need be done
|
||||
}
|
||||
//once the sets are finished being changed pas that up to the parent via the prop function
|
||||
setCurrentSets(sets)
|
||||
updateSets(sets)
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{(plenums.length > 0 || ambients.length > 0) &&
|
||||
<Typography>Select the sensors you would like to add an interaction to</Typography>
|
||||
}
|
||||
{plenums.map(plenum => {
|
||||
return (
|
||||
<PickComponentSet
|
||||
key={plenum.key()}
|
||||
sensor={plenum}
|
||||
heaters={heaters}
|
||||
fans={fans}
|
||||
updateSet={setUpdate}
|
||||
/>
|
||||
)})}
|
||||
{ambients.map(ambient => {
|
||||
return (
|
||||
<PickComponentSet
|
||||
key={ambient.key()}
|
||||
sensor={ambient}
|
||||
heaters={heaters}
|
||||
fans={fans}
|
||||
updateSet={setUpdate}
|
||||
/>
|
||||
)})}
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
275
src/bin/conditioning/modeChangeDialog.tsx
Normal file
275
src/bin/conditioning/modeChangeDialog.tsx
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
import { Autocomplete, Box, Button, DialogActions, DialogContent, DialogContentText, DialogTitle, TextField } from "@mui/material";
|
||||
import ResponsiveDialog from "common/ResponsiveDialog";
|
||||
import { useComponentAPI, useInteractionsAPI } from "hooks";
|
||||
import { Component, Device, Interaction } from "models";
|
||||
import { Ambient } from "models/Ambient";
|
||||
import { Controller } from "models/Controller";
|
||||
import { DevicePreset } from "models/DevicePreset";
|
||||
import { GrainCable } from "models/GrainCable";
|
||||
import { Plenum } from "models/Plenum";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import { quack } from "protobuf-ts/quack";
|
||||
import { useGlobalState } from "providers";
|
||||
import React from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import ConditioningSelector from "./conditioningSelector";
|
||||
import CableTopNodeSummary from "bin/CableTopNodeSummary";
|
||||
import { ComponentSet } from "./pickComponentSet";
|
||||
|
||||
interface Props {
|
||||
open: boolean
|
||||
onClose: (refresh: boolean) => void
|
||||
binKey: string;
|
||||
devices: Device[];
|
||||
binMode: pond.BinMode;
|
||||
grain?: pond.Grain;
|
||||
preferences?: Map<string, pond.BinComponentPreferences>;
|
||||
binCables?: GrainCable[];
|
||||
compDevMap?: Map<string, number>;
|
||||
presets?: DevicePreset[];
|
||||
}
|
||||
|
||||
interface Option {
|
||||
label: string;
|
||||
device: Device;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
export default function ModeChangeDialog(props: Props){
|
||||
const {
|
||||
open,
|
||||
onClose,
|
||||
binMode,
|
||||
devices,
|
||||
binKey,
|
||||
preferences,
|
||||
binCables,
|
||||
compDevMap
|
||||
} = props
|
||||
const [{as}] = useGlobalState()
|
||||
const [componentSets, setComponentSets] = useState<ComponentSet[]>([])
|
||||
const interactionAPI = useInteractionsAPI()
|
||||
const componentAPI = useComponentAPI();
|
||||
const [selectedDevice, setSelectedDevice] = useState<Device | undefined>()
|
||||
const [existingInteractions, setExistingInteractions] = useState<Interaction[]>([])
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [options, setOptions] = useState<Option[]>([])
|
||||
const [deviceComponents, setDeviceComponents] = useState<Map<string, Component[]>>(
|
||||
new Map<string, Component[]>()
|
||||
);
|
||||
|
||||
const [plenums, setPlenums] = useState<Plenum[]>([])
|
||||
const [ambients, setAmbients] = useState<Ambient[]>([])
|
||||
const [heaters, setHeaters] = useState<Controller[]>([])
|
||||
const [fans, setFans] = useState<Controller[]>([])
|
||||
//get the interactions and components for the device when it is selected from the dropdown
|
||||
useEffect(()=>{
|
||||
if (!binKey) return;
|
||||
if (!selectedDevice) return
|
||||
let comps = deviceComponents.get(selectedDevice.id().toString());
|
||||
if (!comps) {
|
||||
comps = [];
|
||||
setLoading(true);
|
||||
let interactionPromise = interactionAPI.listInteractionsByDevice(selectedDevice.id(), undefined, as);
|
||||
let componentPromise = componentAPI.list(selectedDevice.id(), undefined, [binKey], ["bin"], true, as);
|
||||
let dComponents = new Map<string, Component[]>();
|
||||
Promise.all([componentPromise, interactionPromise])
|
||||
.then(([compResp, interactionResp]) => {
|
||||
let d = pond.ListComponentsResponse.fromObject(compResp.data);
|
||||
d.components.forEach(comp => {
|
||||
let c = Component.create(comp);
|
||||
let deviceNumber = compResp.data.componentDevices[c.key()];
|
||||
comps!.push(c);
|
||||
let newDComponents = dComponents.get(deviceNumber.toString());
|
||||
if (newDComponents === undefined) newDComponents = [];
|
||||
newDComponents.push(c);
|
||||
dComponents.set(deviceNumber.toString(), newDComponents);
|
||||
});
|
||||
setDeviceComponents(dComponents);
|
||||
setExistingInteractions(interactionResp);
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
},[selectedDevice, binKey, componentAPI, interactionAPI, deviceComponents, as])
|
||||
|
||||
//sort the components according to the bin preferences
|
||||
useEffect(()=>{
|
||||
if (loading) return;
|
||||
if (!selectedDevice) return;
|
||||
if (!deviceComponents.get(selectedDevice.id().toString())) return;
|
||||
var plenums: Plenum[] = [];
|
||||
var ambients: Ambient[] = [];
|
||||
//var grainCables: GrainCable[] = [];
|
||||
var heaters: Controller[] = [];
|
||||
var fans: Controller[] = [];
|
||||
deviceComponents.get(selectedDevice.id().toString())!.forEach(comp => {
|
||||
let pref = preferences?.get(comp.key());
|
||||
if (pref) {
|
||||
if (pref.type) {
|
||||
if (pref.type === pond.BinComponent.BIN_COMPONENT_PLENUM)
|
||||
plenums.push(Plenum.create(comp));
|
||||
if (pref.type === pond.BinComponent.BIN_COMPONENT_AMBIENT)
|
||||
ambients.push(Ambient.create(comp));
|
||||
// if (pref.type === pond.BinComponent.BIN_COMPONENT_GRAIN_CABLE)
|
||||
// grainCables.push(GrainCable.create(comp));
|
||||
if (pref.type === pond.BinComponent.BIN_COMPONENT_HEATER) {
|
||||
let heater = Controller.create(comp);
|
||||
heater.settings.defaultOutputState = quack.OutputMode.OUTPUT_MODE_OFF;
|
||||
heaters.push(heater);
|
||||
}
|
||||
if (pref.type === pond.BinComponent.BIN_COMPONENT_FAN) {
|
||||
let fan = Controller.create(comp)
|
||||
fan.settings.defaultOutputState = quack.OutputMode.OUTPUT_MODE_OFF;
|
||||
fans.push(fan);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
setPlenums(plenums);
|
||||
setAmbients(ambients);
|
||||
setHeaters(heaters);
|
||||
setFans(fans);
|
||||
}, [loading, setPlenums, setHeaters, deviceComponents, selectedDevice, preferences]);
|
||||
|
||||
useEffect(() => {
|
||||
let o: Option[] = [];
|
||||
devices.forEach(device => {
|
||||
o.push({ device: device, label: device.name() });
|
||||
});
|
||||
setOptions(o);
|
||||
}, [devices, setOptions]);
|
||||
|
||||
//function to loop through the interaction sets building the settings
|
||||
const createInteractions = () => {
|
||||
|
||||
}
|
||||
|
||||
const deviceSelector = () => {
|
||||
return (
|
||||
<Autocomplete
|
||||
disablePortal
|
||||
options={options}
|
||||
fullWidth
|
||||
getOptionLabel={option => option.label || ""}
|
||||
onChange={(_, newValue) => {
|
||||
if(newValue){
|
||||
setSelectedDevice(newValue.device);
|
||||
}
|
||||
}}
|
||||
renderInput={params => <TextField {...params} variant="outlined" label="Device" />}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const modeDescription = () => {
|
||||
switch(binMode){
|
||||
case pond.BinMode.BIN_MODE_DRYING:
|
||||
return "Drying"
|
||||
case pond.BinMode.BIN_MODE_HYDRATING:
|
||||
return "Hydrating"
|
||||
case pond.BinMode.BIN_MODE_COOLDOWN:
|
||||
return "Cooldown"
|
||||
case pond.BinMode.BIN_MODE_STORAGE:
|
||||
return "Storage"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const close = (refresh: boolean) => {
|
||||
onClose(refresh)
|
||||
}
|
||||
|
||||
const content = () => {
|
||||
switch(binMode){
|
||||
case pond.BinMode.BIN_MODE_STORAGE:
|
||||
return (
|
||||
<React.Fragment>
|
||||
<DialogTitle>Entering Storage Mode</DialogTitle>
|
||||
<DialogContent>
|
||||
{binCables && binCables?.length > 0 && compDevMap && (
|
||||
<Box marginBottom={2}>
|
||||
<CableTopNodeSummary
|
||||
binKey={binKey}
|
||||
cables={binCables}
|
||||
componentDevMap={compDevMap}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
<DialogContentText>
|
||||
Select device to turn off controllers and end conditioning. Any interactions will be
|
||||
left alone. Heaters/Fans will be turned off.
|
||||
</DialogContentText>
|
||||
{deviceSelector()}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button variant="contained" onClick={()=>{
|
||||
close(false)
|
||||
}}>
|
||||
Close
|
||||
</Button>
|
||||
{/* Confirm - button to enter storage and end conditioning */}
|
||||
<Button variant="contained" color="primary" onClick={() => {
|
||||
close(true)
|
||||
if (selectedDevice) {
|
||||
//update the controllers to be off for the selected device
|
||||
// updateControllers();
|
||||
}
|
||||
}}>
|
||||
Confirm
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</React.Fragment>
|
||||
)
|
||||
case pond.BinMode.BIN_MODE_COOLDOWN:
|
||||
case pond.BinMode.BIN_MODE_DRYING:
|
||||
case pond.BinMode.BIN_MODE_HYDRATING:
|
||||
return (
|
||||
<React.Fragment>
|
||||
<DialogTitle>Choose Device for {modeDescription()} Method</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
{modeDescription()} control is handled by interactions between multiple components on the
|
||||
same device. Please choose which device and components will handle this bin's{" "}
|
||||
{modeDescription()}.
|
||||
</DialogContentText>
|
||||
{deviceSelector()}
|
||||
<ConditioningSelector
|
||||
plenums={plenums}
|
||||
ambients={ambients}
|
||||
fans={fans}
|
||||
heaters={heaters}
|
||||
updateSets={(sets) => {
|
||||
//update the component sets that will be used for the interactions
|
||||
console.log(sets)
|
||||
}}/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button variant="contained" onClick={()=>{
|
||||
close(false)
|
||||
}}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="contained" color="primary" onClick={()=>{
|
||||
//remove comflicting interactions
|
||||
//add new interactions to the component sets
|
||||
close(true)
|
||||
}}>
|
||||
Submit
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<ResponsiveDialog open={open} onClose={() => {close(false)}}>
|
||||
{content()}
|
||||
</ResponsiveDialog>
|
||||
)
|
||||
}
|
||||
125
src/bin/conditioning/pickComponentSet.tsx
Normal file
125
src/bin/conditioning/pickComponentSet.tsx
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
import { CheckBox, ExpandMore } from "@mui/icons-material";
|
||||
import { Accordion, AccordionDetails, AccordionSummary, Box, Checkbox, FormControlLabel, Typography } from "@mui/material";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { Ambient } from "models/Ambient";
|
||||
import { Controller } from "models/Controller";
|
||||
import { Plenum } from "models/Plenum";
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
export interface ComponentSet {
|
||||
sensor: Plenum | Ambient,
|
||||
controllers: Controller[]
|
||||
}
|
||||
|
||||
interface Props {
|
||||
sensor: Plenum | Ambient
|
||||
heaters?: Controller[]
|
||||
fans?: Controller[]
|
||||
updateSet: (sensorKey: string, componentSet?: ComponentSet) => void
|
||||
}
|
||||
|
||||
export default function PickComponentSet(props: Props) {
|
||||
const {sensor, heaters, fans, updateSet} = props
|
||||
const [sensorSelected, setSensorSelected] = useState(false)
|
||||
const [currentSet, setCurrentSet] = useState<ComponentSet | undefined>()
|
||||
|
||||
const controllerIndex = (key: string) => {
|
||||
if(!currentSet) return -1
|
||||
let index = -1
|
||||
currentSet.controllers.forEach((cont, i) => {
|
||||
if(cont.key() === key){
|
||||
index = i
|
||||
}
|
||||
})
|
||||
return index
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
value={sensorSelected}
|
||||
checked={sensorSelected}
|
||||
onChange={(_, checked) => {
|
||||
setSensorSelected(checked)
|
||||
let newSet: ComponentSet | undefined
|
||||
if(checked){
|
||||
newSet = {
|
||||
sensor: sensor,
|
||||
controllers: []
|
||||
}
|
||||
}
|
||||
setCurrentSet(newSet)
|
||||
updateSet(sensor.key(), newSet)
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={sensor.name()}
|
||||
/>
|
||||
{sensorSelected && currentSet &&
|
||||
<Accordion>
|
||||
<AccordionSummary expandIcon={<ExpandMore />}>Controllers Selected: {currentSet.controllers.length}</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
{heaters && heaters.length > 0 &&
|
||||
<React.Fragment>
|
||||
<Typography>Heaters</Typography>
|
||||
{heaters.map(heater => (
|
||||
<FormControlLabel
|
||||
key={heater.key()}
|
||||
control={
|
||||
<Checkbox
|
||||
onChange={(_, checked) => {
|
||||
let set = cloneDeep(currentSet)
|
||||
if(checked){//if checked need to add it to the controllers
|
||||
set.controllers.push(heater)
|
||||
}else{//will need to make sure it is not in the controllers
|
||||
let index = controllerIndex(heater.key())
|
||||
if (index !== -1){
|
||||
set.controllers.splice(index, 1)
|
||||
}
|
||||
}
|
||||
setCurrentSet(set)
|
||||
updateSet(sensor.key(), set)
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={heater.name()}
|
||||
/>
|
||||
))}
|
||||
</React.Fragment>
|
||||
}
|
||||
{fans && fans.length > 0 &&
|
||||
<React.Fragment>
|
||||
<Typography>Fans</Typography>
|
||||
{fans.map(fan => (
|
||||
<FormControlLabel
|
||||
key={fan.key()}
|
||||
control={
|
||||
<Checkbox
|
||||
onChange={(_, checked) => {
|
||||
let set = cloneDeep(currentSet)
|
||||
if(checked){//if checked need to add it to the controllers
|
||||
set.controllers.push(fan)
|
||||
}else{//will need to make sure it is not in the controllers
|
||||
let index = controllerIndex(fan.key())
|
||||
if (index !== -1){
|
||||
set.controllers.splice(index, 1)
|
||||
}
|
||||
}
|
||||
setCurrentSet(set)
|
||||
updateSet(sensor.key(), set)
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={fan.name()}
|
||||
/>
|
||||
))}
|
||||
</React.Fragment>
|
||||
}
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue