component cards imported
This commit is contained in:
parent
538c807766
commit
af4cc08d87
4 changed files with 330 additions and 62 deletions
|
|
@ -3,12 +3,10 @@ import {
|
||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
makeStyles,
|
|
||||||
Step,
|
Step,
|
||||||
StepLabel,
|
StepLabel,
|
||||||
Stepper,
|
Stepper,
|
||||||
createStyles,
|
Grid2 as Grid,
|
||||||
Grid,
|
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
Switch,
|
Switch,
|
||||||
Table,
|
Table,
|
||||||
|
|
@ -19,19 +17,20 @@ import {
|
||||||
Box,
|
Box,
|
||||||
Typography,
|
Typography,
|
||||||
Checkbox
|
Checkbox
|
||||||
} from "@material-ui/core";
|
} from "@mui/material";
|
||||||
|
|
||||||
import ResponsiveDialog from "common/ResponsiveDialog";
|
import ResponsiveDialog from "common/ResponsiveDialog";
|
||||||
import { Component, Device } from "models";
|
import { Component, Device } from "models";
|
||||||
import { pond, quack } from "protobuf-ts/pond";
|
import { pond, quack } from "protobuf-ts/pond";
|
||||||
import { useComponentAPI, useSnackbar } from "providers";
|
import { useComponentAPI, useSnackbar } from "providers";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { getThemeType } from "theme";
|
|
||||||
import { CableInfo } from "./ComponentDiagnostics";
|
import { CableInfo } from "./ComponentDiagnostics";
|
||||||
import ComponentForm from "./ComponentForm";
|
import ComponentForm from "./ComponentForm";
|
||||||
|
import { getThemeType } from "theme/themeType";
|
||||||
|
import { makeStyles } from "@mui/styles";
|
||||||
|
|
||||||
const useStyles = makeStyles(() =>
|
const useStyles = makeStyles(() => {
|
||||||
createStyles({
|
return ({
|
||||||
buttons: {
|
buttons: {
|
||||||
marginLeft: 5,
|
marginLeft: 5,
|
||||||
marginRight: 5
|
marginRight: 5
|
||||||
|
|
@ -48,7 +47,7 @@ const useStyles = makeStyles(() =>
|
||||||
padding: 0
|
padding: 0
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
});
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
|
|
@ -147,8 +146,8 @@ export default function AddCompsFromDiag(props: Props) {
|
||||||
const simpleActions = () => {
|
const simpleActions = () => {
|
||||||
return (
|
return (
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Grid container direction="row" justify="space-between">
|
<Grid container direction="row" justifyContent="space-between">
|
||||||
<Grid item>
|
<Grid>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
|
|
@ -158,7 +157,7 @@ export default function AddCompsFromDiag(props: Props) {
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
<Grid>
|
||||||
<Button
|
<Button
|
||||||
className={classes.buttons}
|
className={classes.buttons}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
|
|
@ -177,8 +176,8 @@ export default function AddCompsFromDiag(props: Props) {
|
||||||
const advancedActions = () => {
|
const advancedActions = () => {
|
||||||
return (
|
return (
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Grid container direction="row" justify="space-between">
|
<Grid container direction="row" justifyContent="space-between">
|
||||||
<Grid item>
|
<Grid>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
|
|
@ -188,7 +187,7 @@ export default function AddCompsFromDiag(props: Props) {
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
<Grid>
|
||||||
{currentStep !== 0 && (
|
{currentStep !== 0 && (
|
||||||
<Button
|
<Button
|
||||||
className={classes.buttons}
|
className={classes.buttons}
|
||||||
|
|
@ -328,9 +327,9 @@ export default function AddCompsFromDiag(props: Props) {
|
||||||
close();
|
close();
|
||||||
}}>
|
}}>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
<Grid container direction="row" justify="space-between">
|
<Grid container direction="row" justifyContent="space-between">
|
||||||
<Grid item>Port {port} Components</Grid>
|
<Grid >Port {port} Components</Grid>
|
||||||
<Grid item>
|
<Grid >
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={
|
control={
|
||||||
<Switch
|
<Switch
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,14 @@
|
||||||
import {
|
import {
|
||||||
createStyles,
|
|
||||||
Divider,
|
Divider,
|
||||||
IconButton,
|
IconButton,
|
||||||
ListItemIcon,
|
ListItemIcon,
|
||||||
ListItemText,
|
ListItemText,
|
||||||
makeStyles,
|
|
||||||
Menu,
|
Menu,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
|
Theme,
|
||||||
Tooltip
|
Tooltip
|
||||||
} from "@material-ui/core";
|
} from "@mui/material";
|
||||||
import { green, teal } from "@material-ui/core/colors";
|
import { AddCircle, DeleteOutline, MoreVert, SaveAlt, Settings } from "@mui/icons-material";
|
||||||
import { Theme } from "@material-ui/core/styles/createMuiTheme";
|
|
||||||
import { AddCircle, DeleteOutline, MoreVert, SaveAlt, Settings } from "@material-ui/icons";
|
|
||||||
import ExportDataSettings from "component/ExportDataSettings";
|
import ExportDataSettings from "component/ExportDataSettings";
|
||||||
import InteractionSettings from "interactions/InteractionSettings";
|
import InteractionSettings from "interactions/InteractionSettings";
|
||||||
import { Component, Device } from "models";
|
import { Component, Device } from "models";
|
||||||
|
|
@ -23,9 +20,11 @@ import { useGlobalState } from "providers";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { or } from "utils/types";
|
import { or } from "utils/types";
|
||||||
import ComponentSettings from "./ComponentSettings";
|
import ComponentSettings from "./ComponentSettings";
|
||||||
|
import { green, teal } from "@mui/material/colors";
|
||||||
|
import { makeStyles } from "@mui/styles";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
const useStyles = makeStyles((_theme: Theme) => {
|
||||||
createStyles({
|
return ({
|
||||||
addIcon: {
|
addIcon: {
|
||||||
color: green["500"],
|
color: green["500"],
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
|
|
@ -48,7 +47,7 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||||
color: "var(--status-alert)"
|
color: "var(--status-alert)"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
});
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
device: Device;
|
device: Device;
|
||||||
|
|
@ -83,7 +82,7 @@ export default function ComponentActions(props: Props) {
|
||||||
const [anchorEl, setAnchorEl] = useState<Element | null>(null);
|
const [anchorEl, setAnchorEl] = useState<Element | null>(null);
|
||||||
const [componentSettingsMode, setComponentSettingsMode] = useState<string>("");
|
const [componentSettingsMode, setComponentSettingsMode] = useState<string>("");
|
||||||
const [isJSON, setIsJSON] = useState(false);
|
const [isJSON, setIsJSON] = useState(false);
|
||||||
const [{ user, newStructure }] = useGlobalState();
|
const [{ user }] = useGlobalState();
|
||||||
|
|
||||||
const openMoreMenu = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
const openMoreMenu = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||||
setAnchorEl(event.currentTarget);
|
setAnchorEl(event.currentTarget);
|
||||||
|
|
@ -115,7 +114,7 @@ export default function ComponentActions(props: Props) {
|
||||||
onClose={closeMoreMenu}
|
onClose={closeMoreMenu}
|
||||||
disableAutoFocusItem>
|
disableAutoFocusItem>
|
||||||
{canAddInteraction && (
|
{canAddInteraction && (
|
||||||
<MenuItem dense onClick={() => setIsAddInteractionOpen(true)} button divider>
|
<MenuItem dense onClick={() => setIsAddInteractionOpen(true)} divider>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<AddCircle className={classes.addIcon} />
|
<AddCircle className={classes.addIcon} />
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
|
|
@ -129,7 +128,7 @@ export default function ComponentActions(props: Props) {
|
||||||
setIsExportDataOpen(true);
|
setIsExportDataOpen(true);
|
||||||
}}>
|
}}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<SaveAlt fontSize="default" className={classes.exportDataIcon} />
|
<SaveAlt className={classes.exportDataIcon} />
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText primary="Export Data" />
|
<ListItemText primary="Export Data" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
@ -137,7 +136,7 @@ export default function ComponentActions(props: Props) {
|
||||||
{canEdit && (
|
{canEdit && (
|
||||||
<MenuItem dense onClick={() => openComponentSettingsDialog("remove")}>
|
<MenuItem dense onClick={() => openComponentSettingsDialog("remove")}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<DeleteOutline fontSize="default" className={classes.red} />
|
<DeleteOutline className={classes.red} />
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText primary="Delete" />
|
<ListItemText primary="Delete" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
@ -173,7 +172,7 @@ export default function ComponentActions(props: Props) {
|
||||||
refreshCallback={refreshCallback}
|
refreshCallback={refreshCallback}
|
||||||
canEdit={canEdit}
|
canEdit={canEdit}
|
||||||
/>
|
/>
|
||||||
<ExportDataSettings
|
{/* <ExportDataSettings
|
||||||
device={device}
|
device={device}
|
||||||
component={component}
|
component={component}
|
||||||
isDialogOpen={isExportDataOpen}
|
isDialogOpen={isExportDataOpen}
|
||||||
|
|
@ -181,9 +180,9 @@ export default function ComponentActions(props: Props) {
|
||||||
initialStartDate={initialStartDate}
|
initialStartDate={initialStartDate}
|
||||||
initialEndDate={initialEndDate}
|
initialEndDate={initialEndDate}
|
||||||
isJSON={isJSON}
|
isJSON={isJSON}
|
||||||
newMeasurements={newStructure}
|
// newMeasurements={newStructure}
|
||||||
user={user}
|
user={user}
|
||||||
/>
|
/> */}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -195,7 +194,7 @@ export default function ComponentActions(props: Props) {
|
||||||
aria-label="Component Settings"
|
aria-label="Component Settings"
|
||||||
onOpen={event => event.stopPropagation()}>
|
onOpen={event => event.stopPropagation()}>
|
||||||
<IconButton color="default" onClick={() => openComponentSettingsDialog("")}>
|
<IconButton color="default" onClick={() => openComponentSettingsDialog("")}>
|
||||||
<Settings fontSize="default" />
|
<Settings />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title="More">
|
<Tooltip title="More">
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
import { Box, Grid, Typography, makeStyles, createStyles, Theme } from "@material-ui/core";
|
import { Box, Grid2 as Grid, Typography, Theme, Divider } from "@mui/material";
|
||||||
import GrainDescriber from "grain/GrainDescriber";
|
import GrainDescriber from "grain/GrainDescriber";
|
||||||
import { Component } from "models";
|
import { Component } from "models";
|
||||||
import { convertedUnitMeasurement } from "models/UnitMeasurement";
|
import { convertedUnitMeasurement } from "models/UnitMeasurement";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { pond } from "protobuf-ts/pond";
|
import { pond } from "protobuf-ts/pond";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import Divider from "@material-ui/core/Divider";
|
// import Divider from "@material-ui/core/Divider";
|
||||||
import { Plenum } from "models/Plenum";
|
import { Plenum } from "models/Plenum";
|
||||||
import { Pressure } from "models/Pressure";
|
import { Pressure } from "models/Pressure";
|
||||||
import { GrainCable } from "models/GrainCable";
|
import { GrainCable } from "models/GrainCable";
|
||||||
import { extension, Summary } from "pbHelpers/ComponentType";
|
import { extension, Summary } from "pbHelpers/ComponentType";
|
||||||
|
import { makeStyles } from "@mui/styles";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
component: Component | Plenum | Pressure | GrainCable;
|
component: Component | Plenum | Pressure | GrainCable;
|
||||||
|
|
@ -24,8 +25,8 @@ interface Props {
|
||||||
excludedNodes?: number[];
|
excludedNodes?: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
const useStyles = makeStyles((theme: Theme) => {
|
||||||
createStyles({
|
return ({
|
||||||
"@keyframes ripple": {
|
"@keyframes ripple": {
|
||||||
from: {
|
from: {
|
||||||
transform: "scale(.8)",
|
transform: "scale(.8)",
|
||||||
|
|
@ -50,7 +51,7 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||||
margin: theme.spacing(1)
|
margin: theme.spacing(1)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
});
|
||||||
|
|
||||||
export default function UnitMeasurementSummary(props: Props) {
|
export default function UnitMeasurementSummary(props: Props) {
|
||||||
const {
|
const {
|
||||||
|
|
@ -112,7 +113,7 @@ export default function UnitMeasurementSummary(props: Props) {
|
||||||
let grain = GrainDescriber(component.settings.grainType);
|
let grain = GrainDescriber(component.settings.grainType);
|
||||||
return (
|
return (
|
||||||
<Grid container>
|
<Grid container>
|
||||||
<Grid item xs={12}>
|
<Grid size={{ xs: 12 }}>
|
||||||
<Typography variant={largeText ? "body1" : "caption"} color="textPrimary">
|
<Typography variant={largeText ? "body1" : "caption"} color="textPrimary">
|
||||||
{summaries.map((summary: Summary, index: number) => {
|
{summaries.map((summary: Summary, index: number) => {
|
||||||
let sumVal = summary.value;
|
let sumVal = summary.value;
|
||||||
|
|
@ -133,7 +134,7 @@ export default function UnitMeasurementSummary(props: Props) {
|
||||||
if (found) {
|
if (found) {
|
||||||
overlays.push(
|
overlays.push(
|
||||||
<React.Fragment key={"overlay" + index}>
|
<React.Fragment key={"overlay" + index}>
|
||||||
<Grid item>
|
<Grid >
|
||||||
<Box
|
<Box
|
||||||
width="20px"
|
width="20px"
|
||||||
height="20px"
|
height="20px"
|
||||||
|
|
@ -142,7 +143,7 @@ export default function UnitMeasurementSummary(props: Props) {
|
||||||
style={{ background: overlay.colour }}
|
style={{ background: overlay.colour }}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
<Grid >
|
||||||
<Typography
|
<Typography
|
||||||
variant={largeText ? "body1" : "caption"}
|
variant={largeText ? "body1" : "caption"}
|
||||||
component="span"
|
component="span"
|
||||||
|
|
@ -178,7 +179,7 @@ export default function UnitMeasurementSummary(props: Props) {
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
{!props.omitTime && (
|
{!props.omitTime && (
|
||||||
<Grid item xs={12}>
|
<Grid size={{ xs: 12 }}>
|
||||||
<Typography color="textSecondary" variant={largeText ? "body1" : "caption"}>
|
<Typography color="textSecondary" variant={largeText ? "body1" : "caption"}>
|
||||||
{moment(timestamp).fromNow()}
|
{moment(timestamp).fromNow()}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
@ -186,7 +187,7 @@ export default function UnitMeasurementSummary(props: Props) {
|
||||||
)}
|
)}
|
||||||
{overlays.length > 0 && (
|
{overlays.length > 0 && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Grid item xs={12}>
|
<Grid size={{ xs: 12 }}>
|
||||||
<Divider variant="middle" className={classes.divider} />
|
<Divider variant="middle" className={classes.divider} />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid container direction="row">
|
<Grid container direction="row">
|
||||||
|
|
@ -205,11 +206,11 @@ export default function UnitMeasurementSummary(props: Props) {
|
||||||
const blacklist: Array<any> = [];
|
const blacklist: Array<any> = [];
|
||||||
const filteredSummaries = summaries.filter((item: any) => !blacklist.includes(item.label));
|
const filteredSummaries = summaries.filter((item: any) => !blacklist.includes(item.label));
|
||||||
return (
|
return (
|
||||||
<Grid container direction="row" justify={centered ? "center" : "flex-start"} spacing={1}>
|
<Grid container direction="row" justifyContent={centered ? "center" : "flex-start"} spacing={1}>
|
||||||
{filteredSummaries.map((summary: Summary, i: number) => {
|
{filteredSummaries.map((summary: Summary, i: number) => {
|
||||||
let sumVal = summary.value;
|
let sumVal = summary.value;
|
||||||
return (
|
return (
|
||||||
<Grid item key={"summary-" + i}>
|
<Grid key={"summary-" + i}>
|
||||||
{summary.label}
|
{summary.label}
|
||||||
{summary.error && <span style={{ color: "red" }}>{" [error(s)]"}</span>}
|
{summary.error && <span style={{ color: "red" }}>{" [error(s)]"}</span>}
|
||||||
{": "}
|
{": "}
|
||||||
|
|
@ -257,7 +258,7 @@ export default function UnitMeasurementSummary(props: Props) {
|
||||||
if (found) {
|
if (found) {
|
||||||
overlays.push(
|
overlays.push(
|
||||||
<React.Fragment key={"overlay" + i}>
|
<React.Fragment key={"overlay" + i}>
|
||||||
<Grid item>
|
<Grid >
|
||||||
<Box
|
<Box
|
||||||
width="20px"
|
width="20px"
|
||||||
height="20px"
|
height="20px"
|
||||||
|
|
@ -266,7 +267,7 @@ export default function UnitMeasurementSummary(props: Props) {
|
||||||
style={{ background: overlay.colour }}
|
style={{ background: overlay.colour }}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
<Grid >
|
||||||
<Typography
|
<Typography
|
||||||
variant={largeText ? "body1" : "caption"}
|
variant={largeText ? "body1" : "caption"}
|
||||||
component="span"
|
component="span"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Button, Grid2 } from "@mui/material";
|
import { Button, Checkbox, Divider, FormControlLabel, Grid2 as Grid, List, ListItem, Typography } from "@mui/material";
|
||||||
import { Component, Device, User } from "models";
|
import { Component, Device, Interaction, User } from "models";
|
||||||
import { getContextKeys, getContextTypes } from "pbHelpers/Context";
|
import { getContextKeys, getContextTypes } from "pbHelpers/Context";
|
||||||
import { useDeviceAPI, useGlobalState, useSnackbar } from "providers";
|
import { useDeviceAPI, useGlobalState, useSnackbar } from "providers";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
@ -9,11 +9,16 @@ import { useMobile } from "hooks";
|
||||||
import LoadingScreen from "app/LoadingScreen";
|
import LoadingScreen from "app/LoadingScreen";
|
||||||
import SmartBreadcrumb from "common/SmartBreadcrumb";
|
import SmartBreadcrumb from "common/SmartBreadcrumb";
|
||||||
import DeviceActions from "device/DeviceActions";
|
import DeviceActions from "device/DeviceActions";
|
||||||
import { pond } from "protobuf-ts/pond";
|
import { pond, quack } from "protobuf-ts/pond";
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import DeviceOverview from "device/DeviceOverview";
|
import DeviceOverview from "device/DeviceOverview";
|
||||||
import { DeviceAvailabilityMap, FindAvailablePositions, OffsetAvailabilityMap } from "pbHelpers/DeviceAvailability";
|
import { DeviceAvailabilityMap, FindAvailablePositions, OffsetAvailabilityMap } from "pbHelpers/DeviceAvailability";
|
||||||
import AddComponentManualDialog from "component/AddComponentManualDialog";
|
import AddComponentManualDialog from "component/AddComponentManualDialog";
|
||||||
|
import ComponentCard from "component/ComponentCard";
|
||||||
|
import { sameComponentID, sortComponents } from "pbHelpers/Component";
|
||||||
|
import { isController } from "pbHelpers/ComponentType";
|
||||||
|
import { or } from "utils";
|
||||||
|
import ComponentDiagnostics from "component/ComponentDiagnostics";
|
||||||
|
|
||||||
export default function DevicePage() {
|
export default function DevicePage() {
|
||||||
const deviceAPI = useDeviceAPI()
|
const deviceAPI = useDeviceAPI()
|
||||||
|
|
@ -28,15 +33,19 @@ export default function DevicePage() {
|
||||||
const [permissions, setPermissions] = useState<pond.Permission[]>([])
|
const [permissions, setPermissions] = useState<pond.Permission[]>([])
|
||||||
const [preferences, setPreferences] = useState<pond.DevicePreferences>(pond.DevicePreferences.create())
|
const [preferences, setPreferences] = useState<pond.DevicePreferences>(pond.DevicePreferences.create())
|
||||||
const [tags, setTags] = useState<pond.Tag[]>([]);
|
const [tags, setTags] = useState<pond.Tag[]>([]);
|
||||||
|
const [interactions, setInteractions] = useState<Interaction[]>([]);
|
||||||
|
const [prefsMap, setPrefsMap] = useState<Map<string, pond.DeviceComponentPreferences>>(new Map());
|
||||||
|
|
||||||
const [cellularUsage, _setCellularUsage] = useState<number>(0);
|
const [cellularUsage, _setCellularUsage] = useState<number>(0);
|
||||||
const [cellularStatus, _setCellularStatus] = useState<string>("");
|
const [cellularStatus, _setCellularStatus] = useState<string>("");
|
||||||
|
|
||||||
const [availablePositions, setAvailablePositions] = useState<DeviceAvailabilityMap>(new Map());
|
const [availablePositions, setAvailablePositions] = useState<DeviceAvailabilityMap>(new Map());
|
||||||
const [availableOffsets, setAvailableOffsets] = useState<OffsetAvailabilityMap>(new Map());
|
const [availableOffsets, setAvailableOffsets] = useState<OffsetAvailabilityMap>(new Map());
|
||||||
|
const [displayOrder, setDisplayOrder] = useState<string[]>([]);
|
||||||
|
|
||||||
// const [components, setComponents] = useState<Map<string, Component>>(new Map());
|
const [components, setComponents] = useState<Map<string, Component>>(new Map());
|
||||||
const [components, setComponents] = useState<Component[]>([]);
|
const [diagnosticComponents, setDiagnosticComponents] = useState<Component[]>([]);
|
||||||
|
// const [components, setComponents] = useState<Component[]>([]);
|
||||||
|
|
||||||
const [addComponentManualDialogOpen, setAddComponentManualDialogOpen] = useState(false)
|
const [addComponentManualDialogOpen, setAddComponentManualDialogOpen] = useState(false)
|
||||||
|
|
||||||
|
|
@ -70,7 +79,42 @@ export default function DevicePage() {
|
||||||
device.settings.product
|
device.settings.product
|
||||||
);
|
);
|
||||||
setAvailablePositions(available.GetAvailability());
|
setAvailablePositions(available.GetAvailability());
|
||||||
setComponents(newComps)
|
let rawComponents: Array<any> = or(resp.data.components, []);
|
||||||
|
let rComponents: Map<string, Component> = new Map();
|
||||||
|
let diagComponents: Component[] = [];
|
||||||
|
rawComponents.forEach((rawComponent: any) => {
|
||||||
|
let component = Component.any(rawComponent);
|
||||||
|
rComponents.set(component.key(), component);
|
||||||
|
//check if is a diagnostic component
|
||||||
|
switch (component.type()) {
|
||||||
|
case quack.ComponentType.COMPONENT_TYPE_GRAIN_CABLE:
|
||||||
|
if (component.subType() === quack.GrainCableSubtype.GRAIN_CABLE_SUBTYPE_OPI_DIAG) {
|
||||||
|
diagComponents.push(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setComponents(rComponents)
|
||||||
|
let interactions: Interaction[] = [];
|
||||||
|
resp.data.interactions.forEach((interaction: pond.Interaction) => {
|
||||||
|
if (
|
||||||
|
interaction.settings &&
|
||||||
|
interaction.settings.nodeOne > interaction.settings.nodeTwo &&
|
||||||
|
interaction.settings.nodeTwo !== 0
|
||||||
|
) {
|
||||||
|
//flip operator and send negative comparitor to save
|
||||||
|
interaction.settings.conditions.forEach(condition => {
|
||||||
|
//coming back from the backend as a string for some reason
|
||||||
|
if (condition.comparison.toString() === "RELATIONAL_OPERATOR_GREATER_THAN") {
|
||||||
|
condition.comparison = quack.RelationalOperator.RELATIONAL_OPERATOR_LESS_THAN;
|
||||||
|
} else {
|
||||||
|
condition.comparison = quack.RelationalOperator.RELATIONAL_OPERATOR_GREATER_THAN;
|
||||||
|
}
|
||||||
|
condition.value = condition.value * -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
interactions.push(Interaction.any(interaction));
|
||||||
|
});
|
||||||
|
setInteractions(interactions);
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
setDevice(Device.create());
|
setDevice(Device.create());
|
||||||
// setComponents(new Map());
|
// setComponents(new Map());
|
||||||
|
|
@ -95,6 +139,10 @@ export default function DevicePage() {
|
||||||
.finally(() => setLoading(false));
|
.finally(() => setLoading(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log(components)
|
||||||
|
}, [components])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadDevice()
|
loadDevice()
|
||||||
}, [deviceID])
|
}, [deviceID])
|
||||||
|
|
@ -126,13 +174,233 @@ export default function DevicePage() {
|
||||||
return usage;
|
return usage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const displayedComponentsBlacklist = [
|
||||||
|
quack.ComponentType.COMPONENT_TYPE_POWER,
|
||||||
|
quack.ComponentType.COMPONENT_TYPE_MODEM
|
||||||
|
];
|
||||||
|
|
||||||
|
const getOrderedComponents = () => {
|
||||||
|
let compsToOrder: Component[] = [];
|
||||||
|
Array.from(components.values()).forEach(comp => {
|
||||||
|
if (!displayedComponentsBlacklist.includes(comp.settings.type)) {
|
||||||
|
compsToOrder.push(comp);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (displayOrder.length === compsToOrder.length) {
|
||||||
|
return compsToOrder.sort((a, b: Component) => sortComponents(a, b, displayOrder));
|
||||||
|
} else {
|
||||||
|
return compsToOrder;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleComponentChanged = (component: Component) => {
|
||||||
|
let updatedComponents = cloneDeep(components);
|
||||||
|
let updatedComponent = cloneDeep(component);
|
||||||
|
if (updatedComponents.has(updatedComponent.key())) {
|
||||||
|
updatedComponents.set(updatedComponent.key(), updatedComponent);
|
||||||
|
setComponents(updatedComponents);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const componentCards = () => {
|
||||||
|
let orderedComponents = getOrderedComponents();
|
||||||
|
let sensorComponents: JSX.Element[] = [];
|
||||||
|
let controllerComponents: JSX.Element[] = [];
|
||||||
|
//let componentCards = [];
|
||||||
|
//let hasGPS = false;
|
||||||
|
for (let i = 0; i < orderedComponents.length; i++) {
|
||||||
|
let c = orderedComponents[i];
|
||||||
|
if (displayedComponentsBlacklist.includes(c.settings.type)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let id: quack.IComponentID = quack.ComponentID.fromObject({
|
||||||
|
type: c.settings.type,
|
||||||
|
addressType: c.settings.addressType,
|
||||||
|
address: c.settings.address
|
||||||
|
});
|
||||||
|
let filteredInteractions = interactions.filter(interaction => {
|
||||||
|
let isSource = false;
|
||||||
|
let isSink = false;
|
||||||
|
if (interaction.settings) {
|
||||||
|
isSource = sameComponentID(interaction.settings.source, id);
|
||||||
|
isSink = sameComponentID(interaction.settings.sink, id);
|
||||||
|
}
|
||||||
|
return isSource || isSink;
|
||||||
|
});
|
||||||
|
// if (id.type === quack.ComponentType.COMPONENT_TYPE_GPS) {
|
||||||
|
// hasGPS = true;
|
||||||
|
// }
|
||||||
|
if (isController(c.settings.type)) {
|
||||||
|
controllerComponents.push(
|
||||||
|
<ComponentCard
|
||||||
|
device={device}
|
||||||
|
availablePositions={availablePositions}
|
||||||
|
availableOffsets={availableOffsets}
|
||||||
|
component={c}
|
||||||
|
components={orderedComponents}
|
||||||
|
interactions={filteredInteractions}
|
||||||
|
permissions={permissions}
|
||||||
|
deviceComponentPreferences={prefsMap.get(c.key())}
|
||||||
|
key={i}
|
||||||
|
refreshCallback={(updatedComponent?: Component) =>
|
||||||
|
updatedComponent ? handleComponentChanged(updatedComponent) : loadDevice()
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
sensorComponents.push(
|
||||||
|
<ComponentCard
|
||||||
|
device={device}
|
||||||
|
availablePositions={availablePositions}
|
||||||
|
availableOffsets={availableOffsets}
|
||||||
|
component={c}
|
||||||
|
components={orderedComponents}
|
||||||
|
interactions={filteredInteractions}
|
||||||
|
permissions={permissions}
|
||||||
|
deviceComponentPreferences={prefsMap.get(c.key())}
|
||||||
|
key={i}
|
||||||
|
refreshCallback={(updatedComponent?: Component) =>
|
||||||
|
updatedComponent ? handleComponentChanged(updatedComponent) : loadDevice()
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<List>
|
||||||
|
<li>
|
||||||
|
<Grid container direction="row" justifyContent="space-between">
|
||||||
|
<Grid >
|
||||||
|
<Typography display="block" variant="h6">
|
||||||
|
Sensors
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid >
|
||||||
|
{/* <FormControlLabel
|
||||||
|
label="Show Errors"
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={showErrors}
|
||||||
|
onChange={() => {
|
||||||
|
//setShowErrors(!showErrors);
|
||||||
|
dispatch({ key: "showErrors", value: !showErrors });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/> */}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</li>
|
||||||
|
<Divider component="li" />
|
||||||
|
<ListItem>
|
||||||
|
<Grid container direction="row" justifyContent="flex-start" spacing={2}>
|
||||||
|
{sensorComponents}
|
||||||
|
</Grid>
|
||||||
|
</ListItem>
|
||||||
|
<li>
|
||||||
|
<Typography display="block" variant="h6">
|
||||||
|
Controls
|
||||||
|
</Typography>
|
||||||
|
</li>
|
||||||
|
<Divider component="li" />
|
||||||
|
<ListItem>
|
||||||
|
<Grid container direction="row" justifyContent="flex-start" spacing={2}>
|
||||||
|
{controllerComponents}
|
||||||
|
</Grid>
|
||||||
|
</ListItem>
|
||||||
|
{device.settings.mutations.length > 0 && (
|
||||||
|
<>
|
||||||
|
<li>
|
||||||
|
<Typography display="block" variant="h6">
|
||||||
|
Calculated Measurements
|
||||||
|
</Typography>
|
||||||
|
</li>
|
||||||
|
<Divider component="li" />
|
||||||
|
<ListItem>
|
||||||
|
<Grid container direction="row" justifyContent="flex-start" spacing={2}>
|
||||||
|
{/* {device.settings.mutations.map((mut, i) => (
|
||||||
|
<DeviceMutationCard
|
||||||
|
key={"mutation" + i}
|
||||||
|
deviceId={device.id()}
|
||||||
|
mutation={mut}
|
||||||
|
showMobile={isMobile}
|
||||||
|
/>
|
||||||
|
))} */}
|
||||||
|
</Grid>
|
||||||
|
</ListItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{device.settings.product !== pond.DeviceProduct.DEVICE_PRODUCT_NONE &&
|
||||||
|
permissions.includes(pond.Permission.PERMISSION_WRITE) && (
|
||||||
|
<>
|
||||||
|
<li>
|
||||||
|
<Typography display="block" variant="h6">
|
||||||
|
Setup
|
||||||
|
</Typography>
|
||||||
|
</li>
|
||||||
|
<Divider component="li" />
|
||||||
|
<ListItem>
|
||||||
|
<Grid container direction="row" spacing={2}>
|
||||||
|
{isMobile ? (
|
||||||
|
<>
|
||||||
|
<Grid size={{ xs: 12 }}>
|
||||||
|
{/* <DeviceWizard
|
||||||
|
device={device}
|
||||||
|
//permissions={permissions}
|
||||||
|
components={Array.from(components.values())}
|
||||||
|
refreshCallback={load}
|
||||||
|
/> */}
|
||||||
|
</Grid>
|
||||||
|
{diagnosticComponents.map(comp => (
|
||||||
|
<Grid size={{ xs: 12 }} key={comp.key()}>
|
||||||
|
<ComponentDiagnostics
|
||||||
|
component={comp}
|
||||||
|
device={device}
|
||||||
|
refreshCallback={loadDevice}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Grid size={{ xs: 6, sm: 6, lg: 4, xl: 3 }} >
|
||||||
|
{/* <DeviceWizard
|
||||||
|
device={device}
|
||||||
|
//permissions={permissions}
|
||||||
|
components={Array.from(components.values())}
|
||||||
|
refreshCallback={load}
|
||||||
|
/> */}
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 6, sm: 6, lg: 8, xl: 9 }} >
|
||||||
|
<Grid container direction="row" spacing={2}>
|
||||||
|
{diagnosticComponents.map(comp => (
|
||||||
|
<Grid size={{ sm: 12, lg: 6, xl: 4 }} key={comp.key()}>
|
||||||
|
<ComponentDiagnostics
|
||||||
|
component={comp}
|
||||||
|
device={device}
|
||||||
|
refreshCallback={loadDevice}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
</ListItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</List>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContainer padding={isMobile ? 0 : 2}>
|
<PageContainer padding={isMobile ? 0 : 2}>
|
||||||
<Grid2 container justifyContent={"space-between"}>
|
<Grid container justifyContent={"space-between"}>
|
||||||
<Grid2>
|
<Grid>
|
||||||
<SmartBreadcrumb />
|
<SmartBreadcrumb />
|
||||||
</Grid2>
|
</Grid>
|
||||||
<Grid2>
|
<Grid>
|
||||||
<AddComponentManualDialog
|
<AddComponentManualDialog
|
||||||
device={device.id()}
|
device={device.id()}
|
||||||
open={addComponentManualDialogOpen}
|
open={addComponentManualDialogOpen}
|
||||||
|
|
@ -152,18 +420,19 @@ export default function DevicePage() {
|
||||||
availablePositions={availablePositions}
|
availablePositions={availablePositions}
|
||||||
availableOffsets={availableOffsets}
|
availableOffsets={availableOffsets}
|
||||||
/>
|
/>
|
||||||
</Grid2>
|
</Grid>
|
||||||
</Grid2>
|
</Grid>
|
||||||
<DeviceOverview
|
<DeviceOverview
|
||||||
device={device}
|
device={device}
|
||||||
// components={[...components.values()]}
|
components={[...components.values()]}
|
||||||
// components={[]}
|
// components={[]}
|
||||||
components={components}
|
// components={components}
|
||||||
usage={getUsage()}
|
usage={getUsage()}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
tags={tags}
|
tags={tags}
|
||||||
groupID={parseInt(groupID)}
|
groupID={parseInt(groupID)}
|
||||||
/>
|
/>
|
||||||
|
{componentCards()}
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue