Merge branch 'dev_environment' of gitlab.com:brandx/bxt-app into dev_environment
This commit is contained in:
commit
0cc8a7878a
4 changed files with 314 additions and 35 deletions
|
|
@ -21,7 +21,8 @@ import {
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import {
|
import {
|
||||||
ExpandMore,
|
ExpandMore,
|
||||||
Close as CloseIcon
|
Close as CloseIcon,
|
||||||
|
Remove as RemoveIcon
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
import PeriodSelect from "common/time/PeriodSelect";
|
import PeriodSelect from "common/time/PeriodSelect";
|
||||||
import SearchSelect, { Option } from "common/SearchSelect";
|
import SearchSelect, { Option } from "common/SearchSelect";
|
||||||
|
|
@ -97,6 +98,7 @@ interface Props {
|
||||||
component: Component;
|
component: Component;
|
||||||
componentChanged: (component: Component, formValid: boolean) => void;
|
componentChanged: (component: Component, formValid: boolean) => void;
|
||||||
canEdit: boolean;
|
canEdit: boolean;
|
||||||
|
hideControllerFields?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ComponentData {
|
interface ComponentData {
|
||||||
|
|
@ -119,7 +121,7 @@ export default function ComponentForm(props: Props) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const grainOptions = GrainOptions();
|
const grainOptions = GrainOptions();
|
||||||
const [{ user }] = useGlobalState();
|
const [{ user }] = useGlobalState();
|
||||||
const { device, component, componentChanged, canEdit } = props;
|
const { device, component, componentChanged, canEdit, hideControllerFields } = props;
|
||||||
const [reportExpanded, setReportExpanded] = useState(false);
|
const [reportExpanded, setReportExpanded] = useState(false);
|
||||||
const [dataUsageWarningDismissed, setDataUsageWarningDismissed] = useState(true);
|
const [dataUsageWarningDismissed, setDataUsageWarningDismissed] = useState(true);
|
||||||
const [form, setForm] = useState<ComponentData>({
|
const [form, setForm] = useState<ComponentData>({
|
||||||
|
|
@ -137,7 +139,8 @@ export default function ComponentForm(props: Props) {
|
||||||
sensorDistance: "0",
|
sensorDistance: "0",
|
||||||
});
|
});
|
||||||
const [compMode, setCompMode] = useState<any>();
|
const [compMode, setCompMode] = useState<any>();
|
||||||
const [useCustomGrain, setUseCustomGrain] = useState<boolean>(false)
|
const [useCustomGrain, setUseCustomGrain] = useState<boolean>(false);
|
||||||
|
const [controlEmail, setControlEmail] = useState("");
|
||||||
//const [numCalibrations, setNumCalibrations] = useState(0)
|
//const [numCalibrations, setNumCalibrations] = useState(0)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -356,6 +359,21 @@ export default function ComponentForm(props: Props) {
|
||||||
setForm(f);
|
setForm(f);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const addControlEmail = () => {
|
||||||
|
const trimmed = controlEmail.trim().toLowerCase();
|
||||||
|
if (trimmed === "" || form.component.settings.controlEmails.includes(trimmed)) return;
|
||||||
|
let f = cloneDeep(form);
|
||||||
|
f.component.settings.controlEmails.push(trimmed);
|
||||||
|
setForm(f);
|
||||||
|
setControlEmail("");
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeControlEmail = (index: number) => {
|
||||||
|
let f = cloneDeep(form);
|
||||||
|
f.component.settings.controlEmails.splice(index, 1);
|
||||||
|
setForm(f);
|
||||||
|
};
|
||||||
|
|
||||||
const toggleMeasure = (event: any) => {
|
const toggleMeasure = (event: any) => {
|
||||||
let f = cloneDeep(form);
|
let f = cloneDeep(form);
|
||||||
f.measure = event.target.checked;
|
f.measure = event.target.checked;
|
||||||
|
|
@ -1341,7 +1359,7 @@ export default function ComponentForm(props: Props) {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{isController(component.settings.type) && (
|
{isController(component.settings.type) && !hideControllerFields && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Grid size={{ xs: 12 }}>
|
<Grid size={{ xs: 12 }}>
|
||||||
<TextField
|
<TextField
|
||||||
|
|
@ -1382,6 +1400,62 @@ export default function ComponentForm(props: Props) {
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid size={{ xs: 12 }}>
|
||||||
|
<Typography variant="subtitle2" style={{ marginTop: 16, marginBottom: 8 }}>
|
||||||
|
Authorized Control Emails
|
||||||
|
</Typography>
|
||||||
|
<Grid container spacing={1} alignItems="center">
|
||||||
|
<Grid size={{ xs: 9 }}>
|
||||||
|
<TextField
|
||||||
|
label="Email address"
|
||||||
|
type="email"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
size="small"
|
||||||
|
value={controlEmail}
|
||||||
|
onChange={e => setControlEmail(e.target.value)}
|
||||||
|
onKeyDown={e => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
e.preventDefault();
|
||||||
|
addControlEmail();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
disabled={!canEdit}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 3 }}>
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
color="primary"
|
||||||
|
onClick={addControlEmail}
|
||||||
|
disabled={!canEdit || controlEmail.trim() === ""}>
|
||||||
|
Add
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
{component.settings.controlEmails.map((email, i) => (
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
key={i}
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="space-between"
|
||||||
|
style={{ marginTop: 4 }}>
|
||||||
|
<Grid>
|
||||||
|
<Typography variant="body2">{email}</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<IconButton
|
||||||
|
size="small"
|
||||||
|
onClick={() => removeControlEmail(i)}
|
||||||
|
disabled={!canEdit}
|
||||||
|
className={classes.redButton}>
|
||||||
|
<RemoveIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
{showDataUsageWarning && (
|
{showDataUsageWarning && (
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import {
|
||||||
DialogContentText,
|
DialogContentText,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
Divider,
|
Divider,
|
||||||
|
FormControl,
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
Grid2 as Grid,
|
Grid2 as Grid,
|
||||||
IconButton,
|
IconButton,
|
||||||
|
|
@ -41,8 +42,10 @@ import {
|
||||||
GetComponentTypeOptions,
|
GetComponentTypeOptions,
|
||||||
getFriendlyName,
|
getFriendlyName,
|
||||||
getMeasurements,
|
getMeasurements,
|
||||||
isController
|
isController,
|
||||||
} from "pbHelpers/ComponentType";
|
} from "pbHelpers/ComponentType";
|
||||||
|
import PeriodSelect from "common/time/PeriodSelect";
|
||||||
|
import { bestUnit, milliToX } from "common/time/duration";
|
||||||
import {
|
import {
|
||||||
ComponentAvailabilityMap,
|
ComponentAvailabilityMap,
|
||||||
DeviceAvailabilityMap,
|
DeviceAvailabilityMap,
|
||||||
|
|
@ -177,6 +180,7 @@ export default function ComponentSettings(props: Props) {
|
||||||
const [formValid, setFormValid] = useState(false);
|
const [formValid, setFormValid] = useState(false);
|
||||||
const [excludedNodes, setExcludedNodes] = useState<number[]>([]);
|
const [excludedNodes, setExcludedNodes] = useState<number[]>([]);
|
||||||
const [nodeToExclude, setNodeToExclude] = useState(0);
|
const [nodeToExclude, setNodeToExclude] = useState(0);
|
||||||
|
const [controlEmail, setControlEmail] = useState("");
|
||||||
|
|
||||||
const handleChange = (event: React.ChangeEvent<{}>, newValue: number) => {
|
const handleChange = (event: React.ChangeEvent<{}>, newValue: number) => {
|
||||||
setTabVal(newValue);
|
setTabVal(newValue);
|
||||||
|
|
@ -498,6 +502,7 @@ export default function ComponentSettings(props: Props) {
|
||||||
component={formComponent}
|
component={formComponent}
|
||||||
device={device}
|
device={device}
|
||||||
canEdit={canEdit}
|
canEdit={canEdit}
|
||||||
|
hideControllerFields={isController(formComponent.settings.type)}
|
||||||
componentChanged={(formComp, isValid) => {
|
componentChanged={(formComp, isValid) => {
|
||||||
formComponent.settings = formComp.settings;
|
formComponent.settings = formComp.settings;
|
||||||
setFormValid(isValid);
|
setFormValid(isValid);
|
||||||
|
|
@ -867,6 +872,167 @@ export default function ComponentSettings(props: Props) {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const addControlEmail = () => {
|
||||||
|
const trimmed = controlEmail.trim().toLowerCase();
|
||||||
|
if (trimmed === "" || formComponent.settings.controlEmails.includes(trimmed)) return;
|
||||||
|
let f = cloneDeep(formComponent);
|
||||||
|
f.settings.controlEmails.push(trimmed);
|
||||||
|
setFormComponent(f);
|
||||||
|
setControlEmail("");
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeControlEmail = (index: number) => {
|
||||||
|
let f = cloneDeep(formComponent);
|
||||||
|
f.settings.controlEmails.splice(index, 1);
|
||||||
|
setFormComponent(f);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOutputModeChanged = (event: any) => {
|
||||||
|
let f = cloneDeep(formComponent);
|
||||||
|
f.settings.defaultOutputState = event.target.value;
|
||||||
|
setFormComponent(f);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMinCycleTimeChanged = (ms: number) => {
|
||||||
|
let f = cloneDeep(formComponent);
|
||||||
|
f.settings.minCycleTimeMs = Number(ms);
|
||||||
|
setFormComponent(f);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isMinCycleTimeValid = () => {
|
||||||
|
const ext = extension(formComponent.settings.type, formComponent.settings.subtype);
|
||||||
|
if (!ext.isController) return true;
|
||||||
|
let min = Math.max(0, ext.minCycleTimeMs ? ext.minCycleTimeMs : 0);
|
||||||
|
return formComponent.settings.minCycleTimeMs >= min;
|
||||||
|
};
|
||||||
|
|
||||||
|
const minCycleTimeDescription = () => {
|
||||||
|
const ext = extension(formComponent.settings.type, formComponent.settings.subtype);
|
||||||
|
if (!ext.isController) return "";
|
||||||
|
const min = Math.max(0, ext.minCycleTimeMs ? ext.minCycleTimeMs : 0);
|
||||||
|
const unit = bestUnit(min);
|
||||||
|
const value = milliToX(min, unit).toString();
|
||||||
|
return "Must be at least " + value + " " + unit;
|
||||||
|
};
|
||||||
|
|
||||||
|
const controlContent = () => {
|
||||||
|
return (
|
||||||
|
<DialogContent>
|
||||||
|
<TextField
|
||||||
|
id="output-mode"
|
||||||
|
name="outputMode"
|
||||||
|
select
|
||||||
|
label="Output Mode"
|
||||||
|
value={formComponent.settings.defaultOutputState}
|
||||||
|
onChange={handleOutputModeChanged}
|
||||||
|
margin="normal"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
disabled={!canEdit}>
|
||||||
|
<MenuItem value={0}>Auto</MenuItem>
|
||||||
|
<MenuItem value={1}>On</MenuItem>
|
||||||
|
<MenuItem value={2}>Off</MenuItem>
|
||||||
|
</TextField>
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<PeriodSelect
|
||||||
|
id="minCycleTimeMs"
|
||||||
|
label="Minimum cycle time"
|
||||||
|
units={["seconds", "minutes"]}
|
||||||
|
isDisabled={!canEdit}
|
||||||
|
isError={!isMinCycleTimeValid()}
|
||||||
|
initialMs={
|
||||||
|
formComponent.settings.minCycleTimeMs
|
||||||
|
? formComponent.settings.minCycleTimeMs
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
onChange={handleMinCycleTimeChanged}
|
||||||
|
helperText={
|
||||||
|
isMinCycleTimeValid()
|
||||||
|
? "The minimum amount of time that the component spends in a state"
|
||||||
|
: minCycleTimeDescription()
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<Typography variant="subtitle2" sx={{ marginTop: 2, marginBottom: 1 }}>
|
||||||
|
Authorized Control Emails
|
||||||
|
</Typography>
|
||||||
|
<Grid container spacing={1} alignItems="center">
|
||||||
|
<Grid size={{ xs: 9 }}>
|
||||||
|
<TextField
|
||||||
|
label="Email address"
|
||||||
|
type="email"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
size="small"
|
||||||
|
value={controlEmail}
|
||||||
|
onChange={e => setControlEmail(e.target.value)}
|
||||||
|
onKeyDown={e => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
e.preventDefault();
|
||||||
|
addControlEmail();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
disabled={!canEdit}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 3 }}>
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
color="primary"
|
||||||
|
onClick={addControlEmail}
|
||||||
|
disabled={!canEdit || controlEmail.trim() === ""}>
|
||||||
|
Add
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
{formComponent.settings.controlEmails.map((email, i) => (
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
key={i}
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="space-between"
|
||||||
|
style={{ marginTop: 4 }}>
|
||||||
|
<Grid>
|
||||||
|
<Typography variant="body2">{email}</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<IconButton
|
||||||
|
size="small"
|
||||||
|
onClick={() => removeControlEmail(i)}
|
||||||
|
disabled={!canEdit}
|
||||||
|
className={classNames(classes.redButton)}>
|
||||||
|
<RemoveIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
<Divider sx={{ marginTop: 3, marginBottom: 2 }} />
|
||||||
|
<Typography variant="subtitle2" gutterBottom>
|
||||||
|
Email Control
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" color="textSecondary" gutterBottom>
|
||||||
|
Authorized emails can control this component by sending an email to the
|
||||||
|
control address. Contact your administrator for the control email
|
||||||
|
address. Use one of the following as the email subject:
|
||||||
|
</Typography>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "action.hover",
|
||||||
|
borderRadius: 1,
|
||||||
|
padding: 1.5,
|
||||||
|
marginTop: 1,
|
||||||
|
fontFamily: "monospace",
|
||||||
|
fontSize: "0.85rem"
|
||||||
|
}}>
|
||||||
|
<div>{device.id()}:{formComponent.settings.type}-{formComponent.settings.addressType}-{formComponent.settings.address} - ON</div>
|
||||||
|
<div>{device.id()}:{formComponent.settings.type}-{formComponent.settings.addressType}-{formComponent.settings.address} - OFF</div>
|
||||||
|
<div>{device.id()}:{formComponent.settings.type}-{formComponent.settings.addressType}-{formComponent.settings.address} - AUTO</div>
|
||||||
|
</Box>
|
||||||
|
</DialogContent>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const actions = () => {
|
const actions = () => {
|
||||||
return (
|
return (
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
|
|
@ -1042,36 +1208,55 @@ export default function ComponentSettings(props: Props) {
|
||||||
scroll="paper">
|
scroll="paper">
|
||||||
{title()}
|
{title()}
|
||||||
<Divider />
|
<Divider />
|
||||||
{!isController(formComponent.settings.type) && (
|
{isController(formComponent.settings.type) ? (
|
||||||
<Tabs
|
<React.Fragment>
|
||||||
value={tabVal}
|
<Tabs
|
||||||
indicatorColor="primary"
|
value={tabVal}
|
||||||
textColor="primary"
|
indicatorColor="primary"
|
||||||
onChange={handleChange}>
|
textColor="primary"
|
||||||
<Tab label="General" />
|
onChange={handleChange}>
|
||||||
<Tab label="Overlays" />
|
<Tab label="General" />
|
||||||
<Tab label="Nodes" disabled={!prevComponent} />
|
<Tab label="Control" />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
<TabPanelMine value={tabVal} index={0}>
|
||||||
|
{content()}
|
||||||
|
</TabPanelMine>
|
||||||
|
<TabPanelMine value={tabVal} index={1}>
|
||||||
|
{controlContent()}
|
||||||
|
</TabPanelMine>
|
||||||
|
</React.Fragment>
|
||||||
|
) : (
|
||||||
|
<React.Fragment>
|
||||||
|
<Tabs
|
||||||
|
value={tabVal}
|
||||||
|
indicatorColor="primary"
|
||||||
|
textColor="primary"
|
||||||
|
onChange={handleChange}>
|
||||||
|
<Tab label="General" />
|
||||||
|
<Tab label="Overlays" />
|
||||||
|
<Tab label="Nodes" disabled={!prevComponent} />
|
||||||
|
</Tabs>
|
||||||
|
<TabPanelMine value={tabVal} index={0}>
|
||||||
|
{content()}
|
||||||
|
</TabPanelMine>
|
||||||
|
<TabPanelMine value={tabVal} index={1}>
|
||||||
|
<DialogContent>
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
direction="row"
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
alignContent="center"
|
||||||
|
spacing={1}>
|
||||||
|
{overlayGroup()}
|
||||||
|
</Grid>
|
||||||
|
</DialogContent>
|
||||||
|
</TabPanelMine>
|
||||||
|
<TabPanelMine value={tabVal} index={2}>
|
||||||
|
{componentPrefs()}
|
||||||
|
</TabPanelMine>
|
||||||
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
<TabPanelMine value={tabVal} index={0}>
|
|
||||||
{content()}
|
|
||||||
</TabPanelMine>
|
|
||||||
<TabPanelMine value={tabVal} index={1}>
|
|
||||||
<DialogContent>
|
|
||||||
<Grid
|
|
||||||
container
|
|
||||||
direction="row"
|
|
||||||
justifyContent="space-between"
|
|
||||||
alignItems="center"
|
|
||||||
alignContent="center"
|
|
||||||
spacing={1}>
|
|
||||||
{overlayGroup()}
|
|
||||||
</Grid>
|
|
||||||
</DialogContent>
|
|
||||||
</TabPanelMine>
|
|
||||||
<TabPanelMine value={tabVal} index={2}>
|
|
||||||
{componentPrefs()}
|
|
||||||
</TabPanelMine>
|
|
||||||
{actions()}
|
{actions()}
|
||||||
</ResponsiveDialog>
|
</ResponsiveDialog>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,14 @@ class VersionChip extends React.Component<Props, State> {
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
label={firmwareVersionHelper.description}
|
label={firmwareVersionHelper.description}
|
||||||
icon={firmwareVersionHelper.icon}
|
icon={firmwareVersionHelper.icon}
|
||||||
|
sx={
|
||||||
|
firmwareVersionHelper.colour
|
||||||
|
? {
|
||||||
|
borderColor: firmwareVersionHelper.colour,
|
||||||
|
color: firmwareVersionHelper.colour
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ export interface FirmwareVersionHelper {
|
||||||
|
|
||||||
const oldFirmwareColour = "var(--status-warning)";
|
const oldFirmwareColour = "var(--status-warning)";
|
||||||
const currentFirmwareColour = "var(--status-ok)";
|
const currentFirmwareColour = "var(--status-ok)";
|
||||||
|
const unknownFirmwareColour = "var(--status-warning)";
|
||||||
|
|
||||||
export function getFirmwareVersionHelper(
|
export function getFirmwareVersionHelper(
|
||||||
version: string,
|
version: string,
|
||||||
|
|
@ -17,24 +18,35 @@ export function getFirmwareVersionHelper(
|
||||||
const firmwareIcon = <FirmwareIcon />;
|
const firmwareIcon = <FirmwareIcon />;
|
||||||
const oldFirmwareIcon = <FirmwareIcon style={{ color: oldFirmwareColour }} />;
|
const oldFirmwareIcon = <FirmwareIcon style={{ color: oldFirmwareColour }} />;
|
||||||
const currentFirmwareIcon = <FirmwareIcon style={{ color: currentFirmwareColour }} />;
|
const currentFirmwareIcon = <FirmwareIcon style={{ color: currentFirmwareColour }} />;
|
||||||
|
const unknownFirmwareIcon = <FirmwareIcon style={{ color: unknownFirmwareColour }} />;
|
||||||
let helper = {} as FirmwareVersionHelper;
|
let helper = {} as FirmwareVersionHelper;
|
||||||
if (!version || version === "") {
|
if (!version || version === "") {
|
||||||
helper.description = "Unknown version";
|
helper.description = "Unknown version";
|
||||||
helper.icon = oldFirmwareIcon;
|
helper.icon = oldFirmwareIcon;
|
||||||
helper.tooltip = "We don't know what version your device is, it may behave unexpectedly";
|
helper.tooltip = "We don't know what version your device is, it may behave unexpectedly";
|
||||||
|
helper.colour = oldFirmwareColour;
|
||||||
|
} else if (version.startsWith("!")) {
|
||||||
|
const cleanVersion = version.substring(1);
|
||||||
|
helper.description = cleanVersion;
|
||||||
|
helper.icon = unknownFirmwareIcon;
|
||||||
|
helper.tooltip = "Firmware " + cleanVersion + " was reported by the device but is missing from the firmware list";
|
||||||
|
helper.colour = unknownFirmwareColour;
|
||||||
} else if (available !== "" && version !== available) {
|
} else if (available !== "" && version !== available) {
|
||||||
helper.description = version;
|
helper.description = version;
|
||||||
helper.icon = oldFirmwareIcon;
|
helper.icon = oldFirmwareIcon;
|
||||||
helper.tooltip =
|
helper.tooltip =
|
||||||
"A firmware upgrade is available, some features may be disabled for out-of-date devices";
|
"A firmware upgrade is available, some features may be disabled for out-of-date devices";
|
||||||
|
helper.colour = oldFirmwareColour;
|
||||||
} else if (available === "") {
|
} else if (available === "") {
|
||||||
helper.description = version;
|
helper.description = version;
|
||||||
helper.icon = firmwareIcon;
|
helper.icon = firmwareIcon;
|
||||||
helper.tooltip = "Running version " + version;
|
helper.tooltip = "Running version " + version;
|
||||||
|
helper.colour = "";
|
||||||
} else {
|
} else {
|
||||||
helper.description = version;
|
helper.description = version;
|
||||||
helper.icon = currentFirmwareIcon;
|
helper.icon = currentFirmwareIcon;
|
||||||
helper.tooltip = "Your device is running the latest firmware";
|
helper.tooltip = "Your device is running the latest firmware";
|
||||||
|
helper.colour = currentFirmwareColour;
|
||||||
}
|
}
|
||||||
return helper;
|
return helper;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue