Merge branch 'master' into custom_grain

This commit is contained in:
csawatzky 2025-12-30 11:17:27 -06:00
commit 2f8897d8ed
9 changed files with 32 additions and 73 deletions

View file

@ -12,6 +12,7 @@ import { makeStyles } from '@mui/styles'
import { CssBaseline, Theme } from '@mui/material' import { CssBaseline, Theme } from '@mui/material'
import { AppThemeProvider } from 'theme/AppThemeProvider' import { AppThemeProvider } from 'theme/AppThemeProvider'
import HTTPProvider from 'providers/http' import HTTPProvider from 'providers/http'
import { useSnackbar } from 'hooks'
// import FirmwareLoader from './FirmwareLoader' // import FirmwareLoader from './FirmwareLoader'
const reducer = (state: GlobalState, action: GlobalStateAction): GlobalState => { const reducer = (state: GlobalState, action: GlobalStateAction): GlobalState => {
@ -64,6 +65,7 @@ export default function UserWrapper(props: Props) {
const useAuth = useAuth0(); const useAuth = useAuth0();
const hasFetched = useRef(false); const hasFetched = useRef(false);
const [global, setGlobal] = useState<undefined | GlobalState>(undefined) const [global, setGlobal] = useState<undefined | GlobalState>(undefined)
const snackbar = useSnackbar()
const user_id = or(useAuth.user?.sub, "") const user_id = or(useAuth.user?.sub, "")
@ -81,7 +83,8 @@ export default function UserWrapper(props: Props) {
backgroundTasksComplete: false, backgroundTasksComplete: false,
firmware: new Map() firmware: new Map()
}) })
}).catch(() => { }).catch((err) => {
snackbar.error("get user and team: "+err)
userAPI.getUser(user_id).then(user => { userAPI.getUser(user_id).then(user => {
setGlobal({ setGlobal({
user: user ? user : User.create(), user: user ? user : User.create(),
@ -92,7 +95,8 @@ export default function UserWrapper(props: Props) {
backgroundTasksComplete: false, backgroundTasksComplete: false,
firmware: new Map() firmware: new Map()
}) })
}).catch(() => { }).catch((err) => {
snackbar.error("get user: "+err)
setGlobal(globalDefault) setGlobal(globalDefault)
}) })

View file

@ -259,7 +259,7 @@ export default function BinVisualizer(props: Props) {
//const [highTempCable, setHighTempCable] = useState<GrainCable>(); //const [highTempCable, setHighTempCable] = useState<GrainCable>();
//const [lowTempCable, setLowTempCable] = useState<GrainCable>(); //const [lowTempCable, setLowTempCable] = useState<GrainCable>();
//the switch value to determine what to display in the grain condition box //the switch value to determine what to display in the grain condition box
const [valueDisplay, setValueDisplay] = useState<"low" | "avg" | "high">("avg"); const [valueDisplay, setValueDisplay] = useState<"low" | "avg" | "high">("high");
//the variables to be able to change the grain type through a unique dialog outside of the settings //the variables to be able to change the grain type through a unique dialog outside of the settings
const [grainChangeDialog, setGrainChangeDialog] = useState(false); const [grainChangeDialog, setGrainChangeDialog] = useState(false);
const grainOptions = GrainOptions(); const grainOptions = GrainOptions();

View file

@ -56,55 +56,6 @@ export default function GateDevice(props: Props) {
const [lastTemps, setLastTemps] = useState({ t1: 0, t2: 0 }); const [lastTemps, setLastTemps] = useState({ t1: 0, t2: 0 });
const [lastPressures, setLastPressures] = useState({ p1: 0, p2: 0 }); const [lastPressures, setLastPressures] = useState({ p1: 0, p2: 0 });
// const StyledToggleButtonGroup = withStyles(theme => ({
// grouped: {
// margin: theme.spacing(-0.5),
// border: "none",
// padding: theme.spacing(1),
// "&:not(:first-child):not(:last-child)": {
// borderRadius: 24,
// marginRight: theme.spacing(0.5),
// marginLeft: theme.spacing(0.5)
// },
// "&:first-child": {
// borderRadius: 24,
// marginLeft: theme.spacing(0.25)
// },
// "&:last-child": {
// borderRadius: 24,
// marginRight: theme.spacing(0.25)
// }
// },
// root: {
// backgroundColor: darken(
// theme.palette.background.paper,
// getThemeType() === "light" ? 0.05 : 0.25
// ),
// borderRadius: 24,
// content: "border-box"
// }
// }))(ToggleButtonGroup);
// const StyledToggle = withStyles({
// root: {
// backgroundColor: "transparent",
// overflow: "visible",
// content: "content-box",
// "&$selected": {
// backgroundColor: "gold",
// color: "black",
// borderRadius: 24,
// fontWeight: "bold"
// },
// "&$selected:hover": {
// backgroundColor: "rgb(255, 255, 0)",
// color: "black",
// borderRadius: 24
// }
// },
// selected: {}
// })(ToggleButton);
useEffect(() => { useEffect(() => {
if (comprehensiveDevice.device) { if (comprehensiveDevice.device) {
setDevice(Device.any(comprehensiveDevice.device)); setDevice(Device.any(comprehensiveDevice.device));
@ -338,11 +289,11 @@ export default function GateDevice(props: Props) {
return ( return (
<Grid <Grid
container container
direction={(isMobile) ? "column" : "row"} // direction={(isMobile) ? "column" : "row"}
width="100%" width="100%"
alignItems="center" //alignItems="center"
> >
<Grid size={{ sm: 12, lg: isMobile || drawerView ? 12 : 4}} style={{ padding: 10 }}> <Grid width={"100%"} size={{ sm: 12, lg: isMobile || drawerView ? 12 : 4}} style={{ padding: 10 }}>
<Box <Box
display="flex" display="flex"
justifyContent="space-between" justifyContent="space-between"
@ -363,7 +314,7 @@ export default function GateDevice(props: Props) {
]} ]}
/> />
</Box> </Box>
<Card raised> <Card>
<GateSVG <GateSVG
finalTemp={ finalTemp={
gate.gateMutations[device.id().toString()] && gate.gateMutations[device.id().toString()] &&

View file

@ -70,8 +70,9 @@ export default function GateFlowGraph(props: Props) {
const classes = useStyles(); const classes = useStyles();
const [flowEvents, setFlowEvents] = useState<pond.AirFlowEvent[]>([]); const [flowEvents, setFlowEvents] = useState<pond.AirFlowEvent[]>([]);
const [eventsLoading, setEventsLoading] = useState(false); const [eventsLoading, setEventsLoading] = useState(false);
const eventThreshold = 5; //these two constants could be entered by the user at time of retrieval
const idleFlow = 2.44; const eventThreshold = 5; //the threshold that if crossed from one measurement to the next during a flow event will end the current flow event and start a new one
const idleFlow = 3.5; //the mass air flow that must be crossed in order to start a flow event, anything below this will not start an event but must go below this to end an event
useEffect(() => { useEffect(() => {
if (loadingChartData) return; if (loadingChartData) return;
@ -102,7 +103,6 @@ export default function GateFlowGraph(props: Props) {
timestamp: time.valueOf(), timestamp: time.valueOf(),
value: val.airFlow ?? 0 value: val.airFlow ?? 0
}; };
data.push(newPoint); data.push(newPoint);
if (!recent || recent.timestamp < newPoint.timestamp) { if (!recent || recent.timestamp < newPoint.timestamp) {
recent = newPoint; recent = newPoint;

View file

@ -333,7 +333,7 @@ export default function GateSVG(props: Props) {
const deviceCheckIn = () => { const deviceCheckIn = () => {
return ( return (
<g key={"deviceCheckIn"}> <g key={"deviceCheckIn"}>
<text x={95} y={12} fontSize={7} fontWeight={650} fill={"white"}> <text x={85} y={12} fontSize={7} fontWeight={650} fill={"white"}>
Last Checked In: {moment(checkInTime).fromNow()} Last Checked In: {moment(checkInTime).fromNow()}
</text> </text>
</g> </g>
@ -342,7 +342,7 @@ export default function GateSVG(props: Props) {
return ( return (
<React.Fragment> <React.Fragment>
<Box height={"100%"} maxWidth={isMobile ? 360 : 460} margin="auto"> <Box height={"100%"} maxWidth={isMobile ? 400 : 460} margin="auto">
<svg <svg
width={"100%"} width={"100%"}
height={"100%"} height={"100%"}

View file

@ -196,9 +196,10 @@ export default function Bins(props: Props) {
const { openSnack } = useSnackbar(); const { openSnack } = useSnackbar();
// const history = useHistory(); // const history = useHistory();
const navigate = useNavigate() const navigate = useNavigate()
const [cardValDisplay, setCardValDisplay] = useState<"high" | "low" | "average">("average"); const [cardValDisplay, setCardValDisplay] = useState<"high" | "low" | "average">("high");
const [teamsDialog, setTeamsDialog] = useState(false) const [teamsDialog, setTeamsDialog] = useState(false)
const snackbar = useSnackbar()
// const [scrollTranslations, setScrollTranslations] = useState({ // const [scrollTranslations, setScrollTranslations] = useState({
// bins: 0, // bins: 0,
@ -261,10 +262,12 @@ export default function Bins(props: Props) {
if (doneLoadingPage && grainBins.length < 1 && grainBags.length < 1) { if (doneLoadingPage && grainBins.length < 1 && grainBags.length < 1) {
teamAPI.listTeams(1, 0).then(resp => { teamAPI.listTeams(1, 0).then(resp => {
// console.log(resp.data.teams) // console.log(resp.data.teams)
if (resp.data.teams.length > 0) { if (resp.data?.teams?.length > 0) {
// console.log("should?") // console.log("should?")
setTeamsDialog(true) setTeamsDialog(true)
} }
}).catch(err => {
snackbar.error("error listing teams: "+err)
}) })
} }
}, [doneLoadingPage, grainBins, grainBags]) }, [doneLoadingPage, grainBins, grainBags])

View file

@ -158,9 +158,9 @@ export default function DevicePage() {
if (length > 0) { if (length > 0) {
warningString = warningString + " through " + getContextTypes()[length - 1]; warningString = warningString + " through " + getContextTypes()[length - 1];
} }
snackbar.warning(warningString); snackbar.warning("page data warning: "+warningString);
} else { } else {
snackbar.error(err); snackbar.error("page data error: "+err);
} }
}) })
.finally(() => setLoading(false)); .finally(() => setLoading(false));
@ -174,7 +174,7 @@ export default function DevicePage() {
} }
}) })
.catch(err => { .catch(err => {
console.log(err) console.log("load port scan: "+err)
}) })
} }

View file

@ -181,7 +181,8 @@ export default function Terminals(props: Props) {
const load = useCallback(() => { const load = useCallback(() => {
if(loading) return if(loading) return
setLoading(true) setLoading(true)
terminalAPI.listTerminals(200, 0, "asc", "name", as).then(resp => { terminalAPI.listTerminals(200, 0, "asc", "name", undefined, as).then(resp => {
console.log(resp.data)
if(resp.data.terminals){ if(resp.data.terminals){
setTerminals(resp.data.terminals.map(a => Terminal.any(a))); setTerminals(resp.data.terminals.map(a => Terminal.any(a)));
} }

View file

@ -166,7 +166,7 @@ export default function UserMenu() {
); );
}; };
if (user.id().length < 1) return unauthenticatedUserMenu() if (user.id()?.length < 1) return unauthenticatedUserMenu()
const hasAdmin = user.hasFeature ? user.hasFeature("admin") : false; const hasAdmin = user.hasFeature ? user.hasFeature("admin") : false;
@ -182,7 +182,7 @@ export default function UserMenu() {
<UserTeamName user={user} team={team} /> <UserTeamName user={user} team={team} />
</Box> </Box>
<Box style={{ marginLeft: theme.spacing(1) }}> <Box style={{ marginLeft: theme.spacing(1) }}>
{picture && hasTeams && team.id().length > 0 ? ( {picture && hasTeams && team.id()?.length > 0 ? (
<div> <div>
<UserAvatar <UserAvatar
user={user} user={user}
@ -238,7 +238,7 @@ export default function UserMenu() {
{hasTeams && ( {hasTeams && (
<MenuItem <MenuItem
onClick={() => { onClick={() => {
if (as.length > 1) { if (as?.length > 1) {
user.settings.useTeam = false; user.settings.useTeam = false;
dispatch({ key: "as", value: "" }); dispatch({ key: "as", value: "" });
userAPI.updateUser(user.id(), user.protobuf()).then(_resp => { userAPI.updateUser(user.id(), user.protobuf()).then(_resp => {
@ -252,13 +252,13 @@ export default function UserMenu() {
}); });
} }
}} }}
disabled={user.settings.defaultTeam.length < 1} disabled={user.settings.defaultTeam?.length < 1}
aria-label="Open Team Menu" aria-label="Open Team Menu"
dense> dense>
<ListItemIcon> <ListItemIcon>
<Checkbox <Checkbox
disabled={user.settings.defaultTeam.length < 1} disabled={user.settings.defaultTeam?.length < 1}
checked={as.length > 1} checked={as?.length > 1}
style={{ margin: 0, padding: 0 }} style={{ margin: 0, padding: 0 }}
/> />
</ListItemIcon> </ListItemIcon>