added tons of files, got the bin page to render
This commit is contained in:
parent
a027b8a96f
commit
9bbbf0940e
34 changed files with 10492 additions and 19 deletions
517
src/device/presets/devicePresetCard.tsx
Normal file
517
src/device/presets/devicePresetCard.tsx
Normal file
|
|
@ -0,0 +1,517 @@
|
|||
import {
|
||||
Box,
|
||||
Button,
|
||||
Card,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
Grid,
|
||||
InputAdornment,
|
||||
MenuItem,
|
||||
Slider,
|
||||
TextField,
|
||||
Typography
|
||||
} from "@mui/material";
|
||||
import { useMobile } from "hooks";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { DevicePreset } from "models/DevicePreset";
|
||||
import { ObjectTypeString } from "objects/ObjectDescriber";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import { useSnackbar } from "providers";
|
||||
// import { useDevicePresetAPI } from "providers/pond/devicePresetAPI";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { getTemperatureUnit } from "utils";
|
||||
|
||||
interface Props {
|
||||
preset: DevicePreset;
|
||||
existing?: boolean;
|
||||
objectKey?: string;
|
||||
objectType?: pond.ObjectType;
|
||||
addCallback?: (preset: DevicePreset, tempKey: string) => void;
|
||||
removeCallback?: (preset: DevicePreset) => void;
|
||||
updateCallback?: (oldPreset: DevicePreset, newPreset: DevicePreset) => void;
|
||||
}
|
||||
|
||||
export default function DevicePresetCard(props: Props) {
|
||||
const {
|
||||
preset,
|
||||
existing,
|
||||
objectKey,
|
||||
objectType,
|
||||
addCallback,
|
||||
removeCallback,
|
||||
updateCallback
|
||||
} = props;
|
||||
// const devicePresetAPI = useDevicePresetAPI();
|
||||
const [presetName, setPresetName] = useState("");
|
||||
const [presetType, setPresetType] = useState<pond.PresetType>(1);
|
||||
const [controllerType, setControllerType] = useState<pond.ControllerType>(1);
|
||||
const [openDeleteConfirmation, setOpenDeleteConfirmation] = useState(false);
|
||||
const { openSnack } = useSnackbar();
|
||||
const [tempString, setTempString] = useState("0");
|
||||
const [tempC, setTempC] = useState(0);
|
||||
const [humString, setHumString] = useState("0");
|
||||
const [hum, setHum] = useState(0);
|
||||
const isMobile = useMobile();
|
||||
|
||||
useEffect(() => {
|
||||
setPresetName(preset.name);
|
||||
setPresetType(preset.settings.type);
|
||||
setControllerType(preset.settings.controller);
|
||||
setTempC(preset.settings.temperature);
|
||||
setHum(preset.settings.humidity);
|
||||
setHumString(preset.settings.humidity.toString());
|
||||
let displayTemp = preset.settings.temperature.toString();
|
||||
if (getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) {
|
||||
displayTemp = ((preset.settings.temperature * 9) / 5 + 32).toFixed();
|
||||
}
|
||||
setTempString(displayTemp);
|
||||
}, [preset]);
|
||||
|
||||
const saveNewPreset = () => {
|
||||
let typestring;
|
||||
if (objectType) {
|
||||
typestring = ObjectTypeString(objectType);
|
||||
}
|
||||
let p = preset;
|
||||
p.name = presetName;
|
||||
p.settings.type = presetType;
|
||||
p.settings.controller = controllerType;
|
||||
p.settings.temperature = tempC;
|
||||
p.settings.humidity = hum;
|
||||
|
||||
// devicePresetAPI
|
||||
// .addDevicePreset(p.name, p.settings, objectKey, typestring)
|
||||
// .then(resp => {
|
||||
// //get the temp key from the preset
|
||||
// let temp = p.key;
|
||||
// //update the key in the preset with the key that came back from the add
|
||||
// p.key = resp.data.key;
|
||||
// //use the callback function passing in the preset and the temp key
|
||||
// if (addCallback) {
|
||||
// addCallback(p, temp);
|
||||
// }
|
||||
// openSnack("New preset saved");
|
||||
// })
|
||||
// .catch(err => {
|
||||
// openSnack("Failed to save new preset");
|
||||
// });
|
||||
};
|
||||
|
||||
const updatePreset = () => {
|
||||
let newPreset = cloneDeep(preset);
|
||||
let oldPreset = cloneDeep(preset);
|
||||
newPreset.name = presetName;
|
||||
newPreset.settings.type = presetType;
|
||||
newPreset.settings.controller = controllerType;
|
||||
newPreset.settings.temperature = tempC;
|
||||
newPreset.settings.humidity = hum;
|
||||
|
||||
// devicePresetAPI
|
||||
// .updateDevicePreset(newPreset.key, newPreset.name, newPreset.settings)
|
||||
// .then(resp => {
|
||||
// if (updateCallback) {
|
||||
// updateCallback(oldPreset, newPreset);
|
||||
// }
|
||||
// openSnack("Preset Updated");
|
||||
// })
|
||||
// .catch(err => {
|
||||
// openSnack("There was a problem updating the preset");
|
||||
// });
|
||||
};
|
||||
|
||||
const removePreset = () => {
|
||||
// devicePresetAPI
|
||||
// .removeDevicePreset(preset.key)
|
||||
// .then(resp => {
|
||||
// openSnack("Preset has been deleted");
|
||||
// setOpenDeleteConfirmation(false);
|
||||
// if (removeCallback) {
|
||||
// removeCallback(preset);
|
||||
// }
|
||||
// })
|
||||
// .catch(err => {
|
||||
// openSnack("There was a problem deleting this preset");
|
||||
// });
|
||||
};
|
||||
|
||||
const deleteConfirmation = () => {
|
||||
return (
|
||||
<Dialog
|
||||
open={openDeleteConfirmation}
|
||||
onClose={() => {
|
||||
setOpenDeleteConfirmation(false);
|
||||
}}>
|
||||
<DialogTitle>Delete Preset</DialogTitle>
|
||||
<DialogContent>This action will delete the selected preset</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setOpenDeleteConfirmation(false);
|
||||
}}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
removePreset();
|
||||
}}>
|
||||
Confirm
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
const presetComparitors = () => {
|
||||
if (controllerType === pond.ControllerType.CONTROLLER_TYPE_HEATER) {
|
||||
switch (presetType) {
|
||||
case pond.PresetType.PRESET_TYPE_DRYING:
|
||||
return { temp: "below", hum: "above" };
|
||||
case pond.PresetType.PRESET_TYPE_COOLING:
|
||||
return { temp: "below", hum: "above" };
|
||||
}
|
||||
} else {
|
||||
//the controller type is a fan
|
||||
switch (presetType) {
|
||||
case pond.PresetType.PRESET_TYPE_DRYING:
|
||||
return { temp: "above", hum: "below" };
|
||||
case pond.PresetType.PRESET_TYPE_COOLING:
|
||||
return { temp: "below", hum: "below" };
|
||||
case pond.PresetType.PRESET_TYPE_HYDRATING:
|
||||
return { temp: "below", hum: "above" };
|
||||
}
|
||||
}
|
||||
//replace having a default case with final return
|
||||
return { temp: "", hum: "" };
|
||||
};
|
||||
|
||||
return (
|
||||
<Card raised style={{ padding: 10, width: "100%" }}>
|
||||
{deleteConfirmation()}
|
||||
<Grid container direction="row" alignContent="center" alignItems="center">
|
||||
<Grid item xs={12} sm={6}>
|
||||
<TextField
|
||||
variant="outlined"
|
||||
margin="normal"
|
||||
style={{ width: "100%" }}
|
||||
value={presetName}
|
||||
onChange={e => {
|
||||
setPresetName(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
{presetType !== pond.PresetType.PRESET_TYPE_UNKNOWN &&
|
||||
controllerType !== pond.ControllerType.CONTROLLER_TYPE_UNKNOWN && (
|
||||
<Box paddingLeft={2}>
|
||||
<Typography>
|
||||
Toggle{" "}
|
||||
{controllerType === pond.ControllerType.CONTROLLER_TYPE_HEATER ? "heater" : "fan"}{" "}
|
||||
on when temperature {presetComparitors().temp} and humidity{" "}
|
||||
{presetComparitors().hum} set points
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
{/* type */}
|
||||
<TextField
|
||||
style={{ width: "100%", marginRight: 5 }}
|
||||
margin="normal"
|
||||
select
|
||||
label="Type"
|
||||
variant="outlined"
|
||||
value={presetType}
|
||||
onChange={e => {
|
||||
setPresetType(+e.target.value as pond.PresetType);
|
||||
}}>
|
||||
<MenuItem
|
||||
key={pond.PresetType.PRESET_TYPE_UNKNOWN}
|
||||
value={pond.PresetType.PRESET_TYPE_UNKNOWN}>
|
||||
Mode For Preset
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
key={pond.PresetType.PRESET_TYPE_DRYING}
|
||||
value={pond.PresetType.PRESET_TYPE_DRYING}>
|
||||
Drying
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
key={pond.PresetType.PRESET_TYPE_COOLING}
|
||||
value={pond.PresetType.PRESET_TYPE_COOLING}>
|
||||
Cooling
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
key={pond.PresetType.PRESET_TYPE_HYDRATING}
|
||||
value={pond.PresetType.PRESET_TYPE_HYDRATING}>
|
||||
Hydrating
|
||||
</MenuItem>
|
||||
</TextField>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
{/* controller type */}
|
||||
<TextField
|
||||
style={{ width: "100%", marginLeft: 5 }}
|
||||
margin="normal"
|
||||
select
|
||||
label="Controller Type"
|
||||
variant="outlined"
|
||||
value={controllerType}
|
||||
onChange={e => {
|
||||
setControllerType(+e.target.value as pond.ControllerType);
|
||||
}}>
|
||||
<MenuItem
|
||||
key={pond.ControllerType.CONTROLLER_TYPE_UNKNOWN}
|
||||
value={pond.ControllerType.CONTROLLER_TYPE_UNKNOWN}>
|
||||
Controller For Preset
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
key={pond.ControllerType.CONTROLLER_TYPE_HEATER}
|
||||
value={pond.ControllerType.CONTROLLER_TYPE_HEATER}>
|
||||
Heater
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
key={pond.ControllerType.CONTROLLER_TYPE_FAN}
|
||||
value={pond.ControllerType.CONTROLLER_TYPE_FAN}>
|
||||
Fan
|
||||
</MenuItem>
|
||||
</TextField>
|
||||
</Grid>
|
||||
{/* temp slider */}
|
||||
{isMobile ? (
|
||||
<Grid item xs={12}>
|
||||
<Box
|
||||
display="flex"
|
||||
alignContent="center"
|
||||
alignItems="center"
|
||||
justifyContent="space-between">
|
||||
<Typography>Temperature</Typography>
|
||||
<TextField
|
||||
style={{ marginLeft: 5 }}
|
||||
margin="dense"
|
||||
variant="outlined"
|
||||
type="number"
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
{getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT
|
||||
? "°F"
|
||||
: "°C"}
|
||||
</InputAdornment>
|
||||
)
|
||||
}}
|
||||
error={isNaN(+tempString)}
|
||||
value={tempString}
|
||||
onChange={e => {
|
||||
if (!isNaN(+e.target.value)) {
|
||||
let temp = +e.target.value;
|
||||
if (getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) {
|
||||
temp = Math.round((((temp - 32) * 5) / 9) * 10) / 10;
|
||||
}
|
||||
setTempC(temp);
|
||||
}
|
||||
setTempString(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Box paddingLeft={2} paddingRight={2}>
|
||||
<Slider
|
||||
//orientation="vertical"
|
||||
value={tempC}
|
||||
min={-40}
|
||||
max={40}
|
||||
valueLabelDisplay="auto"
|
||||
valueLabelFormat={value => {
|
||||
if (getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) {
|
||||
return ((value * 9) / 5 + 32).toFixed() + "°F";
|
||||
}
|
||||
return value.toFixed() + "°C";
|
||||
}}
|
||||
onChange={(_, value) => {
|
||||
setTempC(value as number);
|
||||
setTempString(value.toString());
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
) : (
|
||||
<React.Fragment>
|
||||
<Grid item xs={2}>
|
||||
<Typography>Temperature</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={7}>
|
||||
<Box paddingRight={2}>
|
||||
<Slider
|
||||
//orientation="vertical"
|
||||
value={tempC}
|
||||
min={-40}
|
||||
max={40}
|
||||
valueLabelDisplay="auto"
|
||||
valueLabelFormat={value => {
|
||||
if (getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) {
|
||||
return ((value * 9) / 5 + 32).toFixed() + "°F";
|
||||
}
|
||||
return value.toFixed() + "°C";
|
||||
}}
|
||||
onChange={(_, value) => {
|
||||
setTempC(value as number);
|
||||
setTempString(value.toString());
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={3}>
|
||||
<TextField
|
||||
style={{ width: "100%" }}
|
||||
margin="dense"
|
||||
variant="outlined"
|
||||
type="number"
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
{getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT
|
||||
? "°F"
|
||||
: "°C"}
|
||||
</InputAdornment>
|
||||
)
|
||||
}}
|
||||
error={isNaN(+tempString)}
|
||||
value={tempString}
|
||||
onChange={e => {
|
||||
if (!isNaN(+e.target.value)) {
|
||||
let temp = +e.target.value;
|
||||
if (getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) {
|
||||
temp = Math.round((((temp - 32) * 5) / 9) * 10) / 10;
|
||||
}
|
||||
setTempC(temp);
|
||||
}
|
||||
setTempString(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
)}
|
||||
{/* humidity slider */}
|
||||
{isMobile ? (
|
||||
<Grid item xs={12}>
|
||||
<Box
|
||||
display="flex"
|
||||
alignContent="center"
|
||||
alignItems="center"
|
||||
justifyContent="space-between">
|
||||
<Typography>Humidity</Typography>
|
||||
<TextField
|
||||
style={{ marginLeft: 5 }}
|
||||
margin="dense"
|
||||
variant="outlined"
|
||||
type="number"
|
||||
InputProps={{
|
||||
endAdornment: <InputAdornment position="end">%</InputAdornment>
|
||||
}}
|
||||
error={isNaN(+humString)}
|
||||
value={humString}
|
||||
onChange={e => {
|
||||
if (!isNaN(+humString)) {
|
||||
setHum(+e.target.value);
|
||||
}
|
||||
setHumString(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Box paddingLeft={2} paddingRight={2}>
|
||||
<Slider
|
||||
//orientation="vertical"
|
||||
value={hum}
|
||||
min={0}
|
||||
max={100}
|
||||
valueLabelDisplay="auto"
|
||||
valueLabelFormat={value => value.toFixed() + "%"}
|
||||
onChange={(_, value) => {
|
||||
setHum(value as number);
|
||||
setHumString(value.toString());
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
) : (
|
||||
<React.Fragment>
|
||||
<Grid item xs={2}>
|
||||
<Typography>Humidity</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={7}>
|
||||
<Box paddingRight={2}>
|
||||
<Slider
|
||||
//orientation="vertical"
|
||||
value={hum}
|
||||
min={0}
|
||||
max={100}
|
||||
valueLabelDisplay="auto"
|
||||
valueLabelFormat={value => value.toFixed() + "%"}
|
||||
onChange={(_, value) => {
|
||||
setHum(value as number);
|
||||
setHumString(value.toString());
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={3}>
|
||||
<TextField
|
||||
style={{ width: "100%" }}
|
||||
margin="dense"
|
||||
variant="outlined"
|
||||
type="number"
|
||||
InputProps={{
|
||||
endAdornment: <InputAdornment position="end">%</InputAdornment>
|
||||
}}
|
||||
error={isNaN(+humString)}
|
||||
value={humString}
|
||||
onChange={e => {
|
||||
if (!isNaN(+humString)) {
|
||||
setHum(+e.target.value);
|
||||
}
|
||||
setHumString(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
)}
|
||||
</Grid>
|
||||
<Box display="flex" justifyContent="flex-end" alignContent="flex-end" marginTop={1}>
|
||||
{existing && (
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{ background: "red" }}
|
||||
onClick={() => {
|
||||
setOpenDeleteConfirmation(true);
|
||||
}}>
|
||||
Delete
|
||||
</Button>
|
||||
)}
|
||||
{existing ? (
|
||||
<Button
|
||||
style={{ marginLeft: 5 }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
updatePreset();
|
||||
}}>
|
||||
Update
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
disabled={
|
||||
presetType === pond.PresetType.PRESET_TYPE_UNKNOWN ||
|
||||
controllerType === pond.ControllerType.CONTROLLER_TYPE_UNKNOWN
|
||||
}
|
||||
onClick={() => saveNewPreset()}
|
||||
variant="contained"
|
||||
color="primary">
|
||||
Save
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue