frontend/src/bin/conditioning/modeChangeDialog.tsx

802 lines
No EOL
29 KiB
TypeScript

import { Autocomplete, Box, Button, DialogActions, DialogContent, DialogContentText, DialogTitle, TextField, Stepper, Step, StepLabel, InputAdornment, Typography } 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";
import { sameComponentID } from "pbHelpers/Component";
import moment from "moment";
import { lowerCase } from "lodash";
import { describeMeasurement } from "pbHelpers/MeasurementDescriber";
import { getTemperatureUnit } from "utils";
import { GetGrainExtensionMap } from "grain";
import { PromiseProgress, Stage, Step as PromiseStep } from "common/PromiseProgress";
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[];
startChange: () => void;
changeComplete: () => void;
defaultTargetMoisture?: number;
changeTargetMoisture?: (newTarget: number) => {}
defaultOutdoorTemp?: number;
changeOutdoorTemp?: (newTemp: number) => {}
defaultOutdoorHumidity?: number;
}
interface Option {
label: string;
device: Device;
icon?: string;
}
interface DialogStep {
label: string;
completed?: boolean;
}
export default function ModeChangeDialog(props: Props){
const {
open,
onClose,
binMode,
devices,
binKey,
preferences,
binCables,
compDevMap,
grain,
startChange,
changeComplete,
defaultTargetMoisture
} = 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[]>([])
const [selectedPreset, setSelectedPreset] = useState<DevicePreset | undefined>(undefined);
const grainExtensionMap = GetGrainExtensionMap();
const [conflictingSetInteractions, setConflictingSetInteractions] = useState<Interaction[]>([])
const [interactionsToAdd, setInteractionsToAdd] = useState<pond.MultiInteractionSettings>()
const [promiseStages, setPromiseStages] = useState<Stage[]>([])
const [dialogSteps, setDialogSteps] = useState<DialogStep[]>([])
const [currentStep, setCurrentStep] = useState(0)
//the state variables for the moisture
const [moistureInput, setMoistureInput] = useState<string>("")
useEffect(()=>{
setMoistureInput(defaultTargetMoisture?.toFixed(2) ?? "0")
},[defaultTargetMoisture])
//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]);
//use effect here to determine the steps based on the bin mode
useEffect(() => {
let steps: DialogStep[] = []
switch(binMode){
case pond.BinMode.BIN_MODE_STORAGE:
steps.push({
label: "Storage Settings"
})
break;
case pond.BinMode.BIN_MODE_COOLDOWN:
steps.push({
label: "Set Components"
})
steps.push({
label: "Progress"
})
break;
case pond.BinMode.BIN_MODE_DRYING:
case pond.BinMode.BIN_MODE_HYDRATING:
steps.push({
label: "Weather Conditions"
})
steps.push({
label: "Set Components"
})
steps.push({
label: "Progress"
})
}
setDialogSteps(steps)
},[binMode])
const buildHeaterInteraction = (
sensor: Plenum | Ambient,
heater: Controller
): pond.InteractionSettings => {
let interaction = pond.InteractionSettings.create({
source: sensor.location(),
sink: heater.location(),
schedule: pond.InteractionSchedule.create({
timeOfDayStart: "00:00",
timeOfDayEnd: "24:00",
timezone: moment.tz.guess(),
weekdays: moment.weekdays().map(d => lowerCase(d))
}),
notifications: pond.InteractionNotifications.create({
reports: true
}),
result: pond.InteractionResult.create({
type: quack.InteractionResultType.INTERACTION_RESULT_TYPE_TOGGLE,
value: 1
})
});
let temp = 0;
let hum = 0;
//if a preset was selected use its temp/hum values
if (selectedPreset !== undefined) {
temp = selectedPreset.temp();
hum = selectedPreset.hum();
} else {
//otherwise use default values
switch(binMode){
case pond.BinMode.BIN_MODE_COOLDOWN:
temp = 10
hum = 45
break;
case pond.BinMode.BIN_MODE_DRYING:
if(grain){
//get the values using the grain type
let ext = grainExtensionMap.get(grain)
if (ext) {
temp = ext.setTempC
hum = ext.targetMC
}
}else{//otherwise use the default drying interaction
temp = 40
hum = 20
}
}
}
let conditions = [];
let humidityCondition = pond.InteractionCondition.create({
measurementType: quack.MeasurementType.MEASUREMENT_TYPE_PERCENT,
comparison: quack.RelationalOperator.RELATIONAL_OPERATOR_GREATER_THAN,
value: Math.round(
describeMeasurement(
quack.MeasurementType.MEASUREMENT_TYPE_PERCENT,
sensor.settings.type,
sensor.settings.subtype
).toStored(hum)
)
});
conditions.push(humidityCondition);
//since the measurement describers function to stored does a conversion into celsius if the users pref is fahrenheit for temperature we need to convert the preset value into fahrenheit
if (getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) {
temp = Math.round((temp * (9 / 5) + 32) * 100) / 100;
}
let tempVal = describeMeasurement(
quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE,
sensor.settings.type,
sensor.settings.subtype
).toStored(temp);
let tempCondition = pond.InteractionCondition.create({
measurementType: quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE,
comparison: quack.RelationalOperator.RELATIONAL_OPERATOR_LESS_THAN,
value: Math.round(tempVal) //and then round the converted value since interaction conditions wont take floats
});
conditions.push(tempCondition);
interaction.conditions = conditions;
//the the heater output to auto so that when the components are update it uses the new mode
heater.settings.defaultOutputState = quack.OutputMode.OUTPUT_MODE_AUTO
return interaction;
};
const buildFanInteraction = (
sensor: Plenum | Ambient,
fan: Controller,
tempComparison: "greater" | "less",
humidityComparison: "greater" | "less"
) => {
let interaction = pond.InteractionSettings.create({
source: sensor.location(),
sink: fan.location(),
schedule: pond.InteractionSchedule.create({
timeOfDayStart: "00:00",
timeOfDayEnd: "24:00",
timezone: moment.tz.guess(),
weekdays: moment.weekdays().map(d => lowerCase(d))
}),
notifications: pond.InteractionNotifications.create({
reports: true
}),
result: pond.InteractionResult.create({
type: quack.InteractionResultType.INTERACTION_RESULT_TYPE_TOGGLE,
value: 1
})
});
let tempPreset = 0;
let humidityPreset = 0;
//if a custom preset was selected use it
if (selectedPreset !== undefined) {
tempPreset = selectedPreset.temp();
humidityPreset = selectedPreset.hum();
} else {
//otherwise use one of the defaults
switch (binMode) {
case pond.BinMode.BIN_MODE_COOLDOWN:
tempPreset = 15;
humidityPreset = 60;
break;
case pond.BinMode.BIN_MODE_DRYING:
if(grain){
//get the values using the grain type
let ext = grainExtensionMap.get(grain)
if (ext) {
tempPreset = ext.setTempC
humidityPreset = ext.targetMC
}
}else{//otherwise use the default drying interaction
tempPreset = 40
humidityPreset = 20
}
break;
case pond.BinMode.BIN_MODE_HYDRATING:
tempPreset = 25;
humidityPreset = 60;
break;
}
}
let conditions = [];
let fanConditionOne = pond.InteractionCondition.create({
measurementType: quack.MeasurementType.MEASUREMENT_TYPE_PERCENT,
comparison:
humidityComparison === "greater"
? quack.RelationalOperator.RELATIONAL_OPERATOR_GREATER_THAN
: quack.RelationalOperator.RELATIONAL_OPERATOR_LESS_THAN,
value: describeMeasurement(
quack.MeasurementType.MEASUREMENT_TYPE_PERCENT,
sensor.settings.type,
sensor.settings.subtype
).toStored(humidityPreset)
});
conditions.push(fanConditionOne);
//since the measurement describers function toStored does a conversion into celsius for temperature if the users pref is fahrenheit we need to convert the preset value into fahrenheit
if (getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) {
tempPreset = Math.round((tempPreset * (9 / 5) + 32) * 100) / 100;
}
let tempVal = describeMeasurement(
quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE,
sensor.settings.type,
sensor.settings.subtype
).toStored(tempPreset);
let fanConditionTwo = pond.InteractionCondition.create({
measurementType: quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE,
comparison:
tempComparison === "greater"
? quack.RelationalOperator.RELATIONAL_OPERATOR_GREATER_THAN
: quack.RelationalOperator.RELATIONAL_OPERATOR_LESS_THAN,
value: Math.round(tempVal) //and then round the converted value since the interaction does not take decimals
});
conditions.push(fanConditionTwo);
interaction.conditions = conditions;
//set the output mode to auto in the fan so that when the components are updated it uses the new mode
fan.settings.defaultOutputState = quack.OutputMode.OUTPUT_MODE_AUTO
return interaction;
};
//this is what will use the conflicting interactions
const buildPromises = () => {
//if there is no device selected or there are no interactions to add, do nothing
if(!selectedDevice || !interactionsToAdd) return
//build the stages to pass into the PromiseProgress
//stage one is to remove conflicting interactions
let stages: Stage[] = []
let stage1: Stage = {
title: "Remove Conflicting Interactions",
steps: []
}
conflictingSetInteractions.forEach(i => {
let newStep: PromiseStep = {
title: "Removing Interaction",
promise: interactionAPI.removeInteraction(selectedDevice.id(), i.key(), as)
}
stage1.steps.push(newStep);
});
stages.push(stage1)
//stage two is to add the new interactions
let stage2: Stage = {
title: "Add New Interactions",
steps: [
{
title: "Adding Interactions",
promise: interactionAPI.addMultiInteractions(selectedDevice.id(), interactionsToAdd)
}
]
}
stages.push(stage2)
//stage three is to update the controller components
let stage3: Stage = {
title: "Update Controllers",
steps: []
}
componentSets.forEach(set => {
set.controllers.forEach(controller => {
console.log(controller)
let newStep: PromiseStep = {
title: "Updating " + controller.name(),
promise: componentAPI.update(selectedDevice.id(), controller.settings)
}
stage3.steps.push(newStep)
})
})
stages.push(stage3)
//set those stages to a state variable
setPromiseStages(stages)
}
//this function just takes in the sets as they change and creates the list of conflicting interactions and the settings to create the new ones and returns them
const createInteractions = (sets: ComponentSet[]) => {
if(!selectedDevice) return undefined //if there is no device that was selected, do nothing
let multiInteractionSettings: pond.MultiInteractionSettings = pond.MultiInteractionSettings.create()
let conflictingInteractions: Interaction[] = []
let linkedComponents = deviceComponents.get(selectedDevice.id().toString());
//loop through the sets
sets.forEach((set) => {
//loop through the controllers
set.controllers.forEach(controller => {
//filter the conflicting interactions for that controller
let c = existingInteractions.filter(i => {
let conflicting = false;
if (linkedComponents) {
linkedComponents.forEach(comp => {
if (sameComponentID(comp.location(), i.settings.sink)) {
conflicting = true;
}
});
}
return conflicting;
});
conflictingInteractions = conflictingInteractions.concat(c)
switch(binMode){
case pond.BinMode.BIN_MODE_COOLDOWN:
// if the controller is a heater create heater interaction
if(controller.subType() === quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_HEATER){
multiInteractionSettings.interactions.push(buildHeaterInteraction(set.sensor, controller))
}else if(controller.subType() === quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_AERATION_FAN ||
controller.subType() === quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_EXHAUST_FAN){
// if the controller is a fan create a fan interaction
multiInteractionSettings.interactions.push(buildFanInteraction(set.sensor, controller, "less", "less"))
}
break;
case pond.BinMode.BIN_MODE_DRYING:
// if the controller is a heater create heater interaction
if(controller.subType() === quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_HEATER){
multiInteractionSettings.interactions.push(buildHeaterInteraction(set.sensor, controller))
}else if(controller.subType() === quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_AERATION_FAN ||
controller.subType() === quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_EXHAUST_FAN){// if the controller is a fan
//if it is a combination set using a heater as well just turn the fan on
if(set.combo){
controller.settings.defaultOutputState = quack.OutputMode.OUTPUT_MODE_ON
}else{
//otherwise make a fan interaction
multiInteractionSettings.interactions.push(buildFanInteraction(set.sensor, controller, "greater", "less"))
}
}
break;
case pond.BinMode.BIN_MODE_HYDRATING:
//check to make sure the controller is a fan, you cant hydrate with a heater, if the controller is a heater then it will not add an interaction
if(controller.subType() === quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_AERATION_FAN ||
controller.subType() === quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_EXHAUST_FAN){
//create fan interaction
multiInteractionSettings.interactions.push(buildFanInteraction(set.sensor, controller, "less", "greater"))
}
break;
}
})
})
setComponentSets([...sets])
return {
conflicting: conflictingInteractions,
toAdd: multiInteractionSettings
}
}
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) => {
//clear state data
setCurrentStep(0)
setInteractionsToAdd(undefined)
setPromiseStages([])
onClose(refresh)
}
//this step will only be used for drying and hydrating
const moistureStep = () => {
return (
<Box>
<DialogContentText style={{ paddingBottom: theme.spacing(0) }}>
Updating the current grain moisture will calibrate the estimate for more accurate
results. The outdoor temperature will have some effect on the estimate as well; consider
updating with drastic changes in the weather or using a predicted average.
</DialogContentText>
<TextField
label={"Grain Moisture"}
value={moistureInput}
onChange={event => setMoistureInput(event.target.value)}
InputProps={{
endAdornment: <InputAdornment position="end">%</InputAdornment>
}}
style={{ marginTop: theme.spacing(2) }}
fullWidth
variant="outlined"
/>
<Typography variant="body1" style={{ marginTop: theme.spacing(2) }}>
Weather
</Typography>
<TextField
label={"Outdoor Temperature"}
value={tempInput}
onChange={event => setTempInput(event.target.value)}
InputProps={{
endAdornment: (
<InputAdornment position="end">
{getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT
? "°F"
: "℃"}
</InputAdornment>
)
}}
style={{ marginTop: theme.spacing(2) }}
fullWidth
variant="outlined"
/>
<TextField
label={"Outdoor Humidity"}
value={outdoorHumidityInput}
onChange={event => setOutdoorHumidityInput(event.target.value)}
InputProps={{
endAdornment: <InputAdornment position="end">%</InputAdornment>
}}
style={{ marginTop: theme.spacing(2) }}
fullWidth
variant="outlined"
/>
</Box>
)
};
const selectDeviceStep = () => {
switch(binMode){
case pond.BinMode.BIN_MODE_STORAGE:
return (
<Box>
{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()}
</Box>
)
case pond.BinMode.BIN_MODE_DRYING:
case pond.BinMode.BIN_MODE_COOLDOWN:
case pond.BinMode.BIN_MODE_HYDRATING:
return (
<Box>
<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
//when the sets change it will create the interactions and any conflicting ones that need to be removed will be put into a list
//then when the submit button gets clicked it will use the conflicting list and toAdd to remove conflicting interactions and add the new ones
let i = createInteractions(sets)
if(i !== undefined){
setConflictingSetInteractions(i.conflicting)
setInteractionsToAdd(i.toAdd)
}
}}
/>
</Box>
)
}
}
const progressStep = () => {
return (
<Box>
<PromiseProgress
stages={promiseStages}
failFast
onComplete={()=>{
console.log("COMPLETED PROMISES")
setCurrentStep(0)//reset the stepper
changeComplete()//change the boolean preventing more mode changes
}}
/>
</Box>
)
}
const stepper = () => {
return (
<Stepper nonLinear activeStep={currentStep} style={{ width: "100%" }}>
{dialogSteps.map(dialogStep => {
const labelProps: {
optional?: React.ReactNode;
} = {};
return (
<Step key={dialogStep.label} completed={dialogStep.completed}>
<StepLabel {...labelProps}>{dialogStep.label}</StepLabel>
</Step>
);
})}
</Stepper>
);
}
const actions = () => {
let buttons: JSX.Element[] = []
//this button should be on every step of all of them
buttons.push(
<Button onClick={() => {close(false)}}>Close</Button>
)
// this button should appear if the step they are on is not 0 and not the last step
if(currentStep !== 0 && currentStep !== dialogSteps.length-1){
buttons.push(
<Button onClick={()=>{setCurrentStep(currentStep-1)}}>Back</Button>
)
}
// this button should appear if the step they are on is less than the last step -1
if(currentStep < dialogSteps.length-2){
buttons.push(
<Button onClick={() => {setCurrentStep(currentStep+1)}}>Next</Button>
)
}
if((binMode === pond.BinMode.BIN_MODE_STORAGE || binMode === pond.BinMode.BIN_MODE_COOLDOWN && currentStep === 0) ||
binMode === pond.BinMode.BIN_MODE_DRYING || binMode === pond.BinMode.BIN_MODE_HYDRATING && currentStep === 1){
buttons.push(
<Button onClick={() => {
//if the bin mode is storage, just update the controllers for the selected device and close
if(binMode === pond.BinMode.BIN_MODE_STORAGE){
close(true)
if (selectedDevice) {
//update the controllers to be off for the selected device
heaters.forEach(heater => {
componentAPI
.update(selectedDevice.id(), heater.settings, undefined, undefined, as)
.then()
.catch();
});
fans.forEach(fan => {
componentAPI
.update(selectedDevice.id(), fan.settings, undefined, undefined, as)
.then()
.catch();
});
}
}else{
setCurrentStep(dialogSteps.length-1)//set the stepper to the progress step
buildPromises()
}
//if it is cooldown, drying, or hydrating, it will need to go to the progress step and initiate all of the promises
}}>Confirm</Button>
)
}
return buttons
}
const stepperContent = (step: number) => {
switch(binMode){
case pond.BinMode.BIN_MODE_STORAGE:
return selectDeviceStep();
case pond.BinMode.BIN_MODE_COOLDOWN:
switch (step) {
case 1:
return progressStep();
default:
return selectDeviceStep();
}
case pond.BinMode.BIN_MODE_DRYING:
case pond.BinMode.BIN_MODE_HYDRATING:
switch (step) {
case 1:
return selectDeviceStep();
case 2:
return progressStep();
default:
return moistureStep();
}
}
};
return (
<React.Fragment>
{/* <PromiseProgress
open={openProgress}
stages={promiseStages}
onClose={()=>{
setOpenProgress(false)
close(refresh)
}} /> */}
<ResponsiveDialog open={open} onClose={() => {close(false)}}>
<DialogTitle>
{binMode === pond.BinMode.BIN_MODE_STORAGE ? "Entering Storage Mode" : "Choose Device for " + modeDescription() + " Method"}
</DialogTitle>
<DialogContent>
{stepper()}
{stepperContent(currentStep)}
</DialogContent>
<DialogActions>
{actions()}
</DialogActions>
</ResponsiveDialog>
</React.Fragment>
)
}