finished refactoring the object alerts into object interactions
This commit is contained in:
parent
bb92077d0b
commit
c9d2eac6c3
5 changed files with 86 additions and 28 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
import { Add, ExpandMore } from "@mui/icons-material";
|
import { Add, ExpandMore } from "@mui/icons-material";
|
||||||
import { Accordion, AccordionDetails, AccordionSummary, Box, Grid2, IconButton, List, ListItem, ListSubheader, Typography } from "@mui/material";
|
import { Accordion, AccordionDetails, AccordionSummary, Box, Button, Grid2, IconButton, List, ListItem, ListSubheader, Typography } from "@mui/material";
|
||||||
import { Component } from "models";
|
import { Component } from "models";
|
||||||
import { describeMeasurement } from "pbHelpers/MeasurementDescriber";
|
import { describeMeasurement } from "pbHelpers/MeasurementDescriber";
|
||||||
import { pond, quack } from "protobuf-ts/pond";
|
import { pond, quack } from "protobuf-ts/pond";
|
||||||
|
|
@ -71,7 +71,13 @@ export default function Alerts(props: Props){
|
||||||
Alerts
|
Alerts
|
||||||
</Typography>
|
</Typography>
|
||||||
{addNew &&
|
{addNew &&
|
||||||
<IconButton disabled={!permissions.includes(pond.Permission.PERMISSION_WRITE)} onClick={()=>{addNew()}} color="primary"><Add /></IconButton>
|
<Button
|
||||||
|
disabled={!permissions.includes(pond.Permission.PERMISSION_WRITE)}
|
||||||
|
onClick={()=>{addNew()}}
|
||||||
|
variant="contained"
|
||||||
|
color="primary">
|
||||||
|
<Add /> Alert
|
||||||
|
</Button>
|
||||||
}
|
}
|
||||||
</ListSubheader>
|
</ListSubheader>
|
||||||
{alerts.map((alert, i) => (
|
{alerts.map((alert, i) => (
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
import { Add } from "@mui/icons-material";
|
import { Add, ExpandMore } from "@mui/icons-material";
|
||||||
import { Accordion, AccordionDetails, AccordionSummary, Divider, IconButton, List, ListItem, ListSubheader, Menu, MenuItem, Typography } from "@mui/material";
|
import { Accordion, AccordionDetails, AccordionSummary, Box, Button, Divider, IconButton, List, ListItem, ListSubheader, Menu, MenuItem, Typography } from "@mui/material";
|
||||||
import { Component, Device } from "models";
|
import { Component, Device, Interaction } from "models";
|
||||||
import { pond } from "protobuf-ts/pond";
|
import { interactionResultText } from "pbHelpers/Interaction";
|
||||||
|
import { describeMeasurement } from "pbHelpers/MeasurementDescriber";
|
||||||
|
import { pond, quack } from "protobuf-ts/pond";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
||||||
export interface Control {
|
export interface Control {
|
||||||
|
|
@ -39,11 +41,49 @@ export default function Controls(props: Props){
|
||||||
setDeviceControls(map)
|
setDeviceControls(map)
|
||||||
},[controls])
|
},[controls])
|
||||||
|
|
||||||
|
const readableConditions = (control: Control) => {
|
||||||
|
let conditions: string = ""
|
||||||
|
let firstSource = control.sourceComponents[0]
|
||||||
|
control.conditions.forEach((condition, index) => {
|
||||||
|
let describer = describeMeasurement(condition.measurementType, firstSource.type(), firstSource.subType());
|
||||||
|
let type = describer.label();
|
||||||
|
let comparison =
|
||||||
|
condition.comparison === quack.RelationalOperator.RELATIONAL_OPERATOR_EQUAL_TO
|
||||||
|
? "Exactly"
|
||||||
|
: condition.comparison === quack.RelationalOperator.RELATIONAL_OPERATOR_GREATER_THAN
|
||||||
|
? "Above"
|
||||||
|
: "Below";
|
||||||
|
let value = describer.toDisplay(condition.value);
|
||||||
|
conditions = conditions + (index !== 0 ? " and " : "") + type + " " + comparison + " " + value + describer.GetUnit()
|
||||||
|
})
|
||||||
|
return conditions
|
||||||
|
};
|
||||||
|
|
||||||
const controlAccordion = (control: Control) => {
|
const controlAccordion = (control: Control) => {
|
||||||
|
let tempInteraction = Interaction.create()
|
||||||
|
tempInteraction.settings.result = control.result
|
||||||
|
let resultText = interactionResultText(tempInteraction, control.sinkComponent)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Accordion>
|
<Accordion sx={{width: "100%"}}>
|
||||||
<AccordionSummary>Show what the control does</AccordionSummary>
|
<AccordionSummary expandIcon={<ExpandMore />}>
|
||||||
<AccordionDetails>show the components that are doing it</AccordionDetails>
|
<Box>
|
||||||
|
<Typography>
|
||||||
|
{resultText}:
|
||||||
|
</Typography>
|
||||||
|
<Typography>
|
||||||
|
{readableConditions(control)}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</AccordionSummary>
|
||||||
|
<AccordionDetails>
|
||||||
|
<List>
|
||||||
|
<ListSubheader>Controlling Components</ListSubheader>
|
||||||
|
{control.sourceComponents.map((comp, i) => (
|
||||||
|
<ListItem key={i}>{comp.name()}</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</AccordionDetails>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -79,17 +119,20 @@ export default function Controls(props: Props){
|
||||||
<List style={{ margin: 5 }}>
|
<List style={{ margin: 5 }}>
|
||||||
<ListSubheader sx={{paddingY: 1, display: "flex", justifyContent: "space-between", alignItems: "center"}}>
|
<ListSubheader sx={{paddingY: 1, display: "flex", justifyContent: "space-between", alignItems: "center"}}>
|
||||||
<Typography>
|
<Typography>
|
||||||
Alerts
|
Controls
|
||||||
</Typography>
|
</Typography>
|
||||||
<IconButton
|
{addNew &&
|
||||||
|
<Button
|
||||||
disabled={!permissions.includes(pond.Permission.PERMISSION_WRITE)}
|
disabled={!permissions.includes(pond.Permission.PERMISSION_WRITE)}
|
||||||
|
variant="contained"
|
||||||
onClick={(e)=>{
|
onClick={(e)=>{
|
||||||
setOpenDeviceMenu(true)
|
setOpenDeviceMenu(true)
|
||||||
setAnchor(e.currentTarget)
|
setAnchor(e.currentTarget)
|
||||||
}}
|
}}
|
||||||
color="primary">
|
color="primary">
|
||||||
<Add />
|
<Add />Control
|
||||||
</IconButton>
|
</Button>
|
||||||
|
}
|
||||||
</ListSubheader>
|
</ListSubheader>
|
||||||
{devices.map(device => (
|
{devices.map(device => (
|
||||||
<React.Fragment key={device.id()}>
|
<React.Fragment key={device.id()}>
|
||||||
|
|
|
||||||
|
|
@ -996,6 +996,8 @@ export default function NewObjectInteraction(props: Props){
|
||||||
})
|
})
|
||||||
.catch(_err => {
|
.catch(_err => {
|
||||||
openSnack("there was a problem adding the interaction to the selected components");
|
openSnack("there was a problem adding the interaction to the selected components");
|
||||||
|
}).finally(() => {
|
||||||
|
close(true)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,11 @@ export default function Notifications(props: Props){
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<List style={{ margin: 5 }}>
|
<List style={{ margin: 5 }}>
|
||||||
<ListSubheader>Notifications</ListSubheader>
|
<ListSubheader>
|
||||||
|
<Typography sx={{paddingY: 2}}>
|
||||||
|
Notifications
|
||||||
|
</Typography>
|
||||||
|
</ListSubheader>
|
||||||
{recentNotifications && (
|
{recentNotifications && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{recentNotifications.map((notification, i) => (
|
{recentNotifications.map((notification, i) => (
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Box, Button, Card, Typography } from "@mui/material";
|
import { Box, Button, Card, Typography } from "@mui/material";
|
||||||
import { useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import Alerts, { Alert } from "./Alerts";
|
import Alerts, { Alert } from "./Alerts";
|
||||||
import Controls, { Control } from "./Controls";
|
import Controls, { Control } from "./Controls";
|
||||||
import { Component, Device, Interaction } from "models";
|
import { Component, Device, Interaction } from "models";
|
||||||
|
|
@ -21,11 +21,10 @@ interface Props {
|
||||||
objectType: pond.ObjectType
|
objectType: pond.ObjectType
|
||||||
devices: Device[];
|
devices: Device[];
|
||||||
permissions: pond.Permission[]
|
permissions: pond.Permission[]
|
||||||
refreshCallback?: () => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ObjectInteractions(props: Props) {
|
export default function ObjectInteractions(props: Props) {
|
||||||
const { linkedComponents, componentDevices, devices, objectKey, objectType, refreshCallback, permissions } = props
|
const { linkedComponents, componentDevices, devices, objectKey, objectType, permissions } = props
|
||||||
const [{as}] = useGlobalState()
|
const [{as}] = useGlobalState()
|
||||||
//list of alerts, each alert contains a list of interactions with matching conditions
|
//list of alerts, each alert contains a list of interactions with matching conditions
|
||||||
const [alerts, setAlerts] = useState<Alert[]>([]);
|
const [alerts, setAlerts] = useState<Alert[]>([]);
|
||||||
|
|
@ -86,7 +85,7 @@ export default function ObjectInteractions(props: Props) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
const load = useCallback(()=>{
|
||||||
const newInteractions: Interaction[] = [];
|
const newInteractions: Interaction[] = [];
|
||||||
const interactionSourceMap = new Map<string, string>();
|
const interactionSourceMap = new Map<string, string>();
|
||||||
const sinkOptions: Component[] = [];
|
const sinkOptions: Component[] = [];
|
||||||
|
|
@ -183,7 +182,11 @@ export default function ObjectInteractions(props: Props) {
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error("Interaction fetch error:", err)
|
console.error("Interaction fetch error:", err)
|
||||||
})
|
})
|
||||||
}, [linkedComponents, interactionsAPI, componentDevices, as]);
|
},[linkedComponents, interactionsAPI, componentDevices, as])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
load()
|
||||||
|
}, [load]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -193,8 +196,8 @@ export default function ObjectInteractions(props: Props) {
|
||||||
open={openNewInteraction}
|
open={openNewInteraction}
|
||||||
onClose={(refresh) => {
|
onClose={(refresh) => {
|
||||||
setOpenNewInteraction(false)
|
setOpenNewInteraction(false)
|
||||||
if(refresh && refreshCallback){
|
if(refresh){
|
||||||
refreshCallback()
|
load()
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
linkedComponents={linkedComponents}
|
linkedComponents={linkedComponents}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue