view as team notification pops up if they don't have devices or bins but have a team
This commit is contained in:
parent
4f8b0254bb
commit
0127eeefc7
4 changed files with 130 additions and 35 deletions
|
|
@ -18,7 +18,6 @@ import {
|
|||
ImageList,
|
||||
ImageListItem,
|
||||
InputLabel,
|
||||
lighten,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Menu,
|
||||
|
|
@ -26,8 +25,6 @@ import {
|
|||
Select,
|
||||
Skeleton,
|
||||
Theme,
|
||||
ToggleButton,
|
||||
ToggleButtonGroup,
|
||||
Typography,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
|
|
@ -61,7 +58,8 @@ import {
|
|||
// useBinYardAPI,
|
||||
useGlobalState,
|
||||
useInteractionsAPI,
|
||||
useSnackbar
|
||||
useSnackbar,
|
||||
useTeamAPI
|
||||
} from "providers";
|
||||
import React, { SetStateAction, useCallback, useEffect, useState } from "react";
|
||||
// import { getThemeType } from "theme";
|
||||
|
|
@ -72,7 +70,7 @@ import ObjectTable from "objects/ObjectTable";
|
|||
import ResponsiveDialog from "common/ResponsiveDialog";
|
||||
import { describeMeasurement } from "pbHelpers/MeasurementDescriber";
|
||||
import { green, yellow } from "@mui/material/colors";
|
||||
import { makeStyles, styled } from "@mui/styles";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import BinSettings from "bin/BinSettings";
|
||||
import AddBinFab from "bin/AddBinFab";
|
||||
|
|
@ -82,6 +80,7 @@ import GrainBagSettings from "grainBag/grainBagSettings";
|
|||
import GrainBagList from "grainBag/grainBagList";
|
||||
import BinYards from "bin/BinYards";
|
||||
import ButtonGroup from "common/ButtonGroup";
|
||||
import TeamDialog from "teams/TeamDialog";
|
||||
// import { useHistory } from "react-router";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => {
|
||||
|
|
@ -141,11 +140,13 @@ export default function Bins(props: Props) {
|
|||
const classes = useStyles();
|
||||
const isMobile = useMobile();
|
||||
const binAPI = useBinAPI();
|
||||
const teamAPI = useTeamAPI();
|
||||
// const binyardAPI = useBinYardAPI();
|
||||
const interactionsAPI = useInteractionsAPI();
|
||||
const [{ user, as }] = useGlobalState();
|
||||
const [allLoading, setAllLoading] = useState(false);
|
||||
const [binsLoading, setBinsLoading] = useState(false);
|
||||
const [doneLoadingPage, setDoneLoadingPage] = useState(false)
|
||||
const [addBinOpen, setAddBinOpen] = useState(false);
|
||||
const [paginatedBins, setPaginatedBins] = useState<PaginatedBins>({
|
||||
bins: [],
|
||||
|
|
@ -188,13 +189,16 @@ export default function Bins(props: Props) {
|
|||
const [qrKeyList, setQrKeyList] = useState<QrCodeKey[]>([]);
|
||||
const [totalFanControllers, setTotalFanControllers] = useState(0);
|
||||
const [totalFanControllersOn, setTotalFanControllersOn] = useState(0);
|
||||
const [yardsLoading, setYardsLoading] = useState(false);
|
||||
// const [yardsLoading, setYardsLoading] = useState(false);
|
||||
const [openAddAlerts, setOpenAddAlerts] = useState(false);
|
||||
const [alertBins, setAlertBins] = useState<Bin[]>([]);
|
||||
const { openSnack } = useSnackbar();
|
||||
// const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
const [cardValDisplay, setCardValDisplay] = useState<"high" | "low" | "average">("average");
|
||||
|
||||
const [teamsDialog, setTeamsDialog] = useState(false)
|
||||
|
||||
// const [scrollTranslations, setScrollTranslations] = useState({
|
||||
// bins: 0,
|
||||
// empty: 0,
|
||||
|
|
@ -252,6 +256,18 @@ export default function Bins(props: Props) {
|
|||
// selected: {}
|
||||
// }));
|
||||
|
||||
useEffect(() => {
|
||||
if (doneLoadingPage && grainBins.length < 1 && grainBags.length < 1) {
|
||||
teamAPI.listTeams(1, 0).then(resp => {
|
||||
// console.log(resp.data.teams)
|
||||
if (resp.data.teams.length > 0) {
|
||||
// console.log("should?")
|
||||
setTeamsDialog(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [doneLoadingPage, grainBins, grainBags])
|
||||
|
||||
useEffect(() => {
|
||||
let ebt = sessionStorage.getItem("expandBinTotal");
|
||||
if (ebt === "true") {
|
||||
|
|
@ -400,7 +416,7 @@ export default function Bins(props: Props) {
|
|||
const bags = resp.data.bags.map(b => GrainBag.create(b));
|
||||
setGrainBags(bags);
|
||||
})
|
||||
.catch(err => {
|
||||
.catch(() => {
|
||||
setPaginatedBins({ bins: [], binsOffset: 0, binsTotal: 0 });
|
||||
setBinMetrics(pond.BinMetrics.create());
|
||||
setYards([]);
|
||||
|
|
@ -408,6 +424,7 @@ export default function Bins(props: Props) {
|
|||
.finally(() => {
|
||||
setAllLoading(false);
|
||||
setBinsLoading(false);
|
||||
setDoneLoadingPage(true)
|
||||
});
|
||||
}, [binAPI, yardFilter, order, orderBy, as, loadingAs, loadingFilter]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
|
|
@ -454,7 +471,7 @@ export default function Bins(props: Props) {
|
|||
setFertilizerBins([...fert]);
|
||||
setQrKeyList([...newKeyList]);
|
||||
})
|
||||
.catch(err => {
|
||||
.catch(() => {
|
||||
setPaginatedBins({ bins: [], binsOffset: 0, binsTotal: 0 });
|
||||
})
|
||||
.finally(() => {
|
||||
|
|
@ -462,13 +479,13 @@ export default function Bins(props: Props) {
|
|||
});
|
||||
};
|
||||
|
||||
const searchYards = (
|
||||
search?: string,
|
||||
limit?: number,
|
||||
offset?: number,
|
||||
order?: "asc" | "desc"
|
||||
) => {
|
||||
setYardsLoading(true);
|
||||
// const searchYards = (
|
||||
// search?: string,
|
||||
// limit?: number,
|
||||
// offset?: number,
|
||||
// order?: "asc" | "desc"
|
||||
// ) => {
|
||||
// setYardsLoading(true);
|
||||
// binyardAPI.listBinYards(limit ?? binsLimit, offset ?? 0, order, "name", search).then(resp => {
|
||||
// let y: pond.BinYardSettings[] = [];
|
||||
// let p: Dictionary<pond.Permission[]> = {};
|
||||
|
|
@ -493,7 +510,7 @@ export default function Bins(props: Props) {
|
|||
// }
|
||||
// setYardsLoading(false);
|
||||
// });
|
||||
};
|
||||
// };
|
||||
|
||||
useEffect(() => {
|
||||
loadBins();
|
||||
|
|
@ -515,7 +532,7 @@ export default function Bins(props: Props) {
|
|||
}
|
||||
|
||||
const duplicateBin = (bin: Bin) => {
|
||||
binAPI.addBin(bin.settings, as).then(resp => {
|
||||
binAPI.addBin(bin.settings, as).then(() => {
|
||||
loadBins();
|
||||
});
|
||||
};
|
||||
|
|
@ -556,7 +573,7 @@ export default function Bins(props: Props) {
|
|||
.then(resp => {
|
||||
openSnack("Successfully added " + resp.data.numAlertsSet + " alerts");
|
||||
})
|
||||
.catch(err => {
|
||||
.catch(() => {
|
||||
console.log("errors found");
|
||||
});
|
||||
};
|
||||
|
|
@ -1080,7 +1097,7 @@ export default function Bins(props: Props) {
|
|||
control={
|
||||
<Checkbox
|
||||
checked={displayGrain}
|
||||
onChange={(e, checked) => {
|
||||
onChange={(_, checked) => {
|
||||
setDisplayGrain(checked);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -1093,7 +1110,7 @@ export default function Bins(props: Props) {
|
|||
control={
|
||||
<Checkbox
|
||||
checked={displayFert}
|
||||
onChange={(e, checked) => {
|
||||
onChange={(_, checked) => {
|
||||
setDisplayFert(checked);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -1106,7 +1123,7 @@ export default function Bins(props: Props) {
|
|||
control={
|
||||
<Checkbox
|
||||
checked={displayEmpty}
|
||||
onChange={(e, checked) => {
|
||||
onChange={(_, checked) => {
|
||||
setDisplayEmpty(checked);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -1392,15 +1409,17 @@ export default function Bins(props: Props) {
|
|||
{addALertsDialog()}
|
||||
<BinYards
|
||||
yards={yards}
|
||||
yardsLoading={yardsLoading}
|
||||
// yardsLoading={yardsLoading}
|
||||
yardsLoading={false}
|
||||
yardPerms={yardPermissions}
|
||||
showTabs={!props.insert}
|
||||
setYardFilter={setYardFilter}
|
||||
bins={paginatedBins.bins}
|
||||
loadBins={loadBins}
|
||||
loadYards={(search, limit, offset) => {
|
||||
searchYards(search, limit, offset);
|
||||
}}
|
||||
// loadYards={(search, limit, offset) => {
|
||||
// searchYards(search, limit, offset);
|
||||
// }}
|
||||
loadYards={() => {}}
|
||||
grainBags={grainBags}
|
||||
setShowing={(val: "all" | "bins" | "bags") => {
|
||||
setShowing(val);
|
||||
|
|
@ -1473,6 +1492,13 @@ export default function Bins(props: Props) {
|
|||
/>
|
||||
{binMenu()}
|
||||
<AddBinFab onClick={() => setAddBinOpen(true)} pulse={binsTotal < 1 && !allLoading} />
|
||||
<TeamDialog
|
||||
open={teamsDialog}
|
||||
setOpen={setTeamsDialog}
|
||||
title={"You have teams!"}
|
||||
info={"Looks like you don't have any bins, but are a part of at least one team. If you want to see your teams bins, please select your team and choose the option \"View as team\""}
|
||||
hideKey={"bins-teams-notification-dialog"}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import PageContainer from "./PageContainer";
|
|||
import { pond } from "protobuf-ts/pond";
|
||||
import LogsDisplay from "common/LogsDisplay";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useDeviceAPI, useSnackbar } from "hooks";
|
||||
import { useDeviceAPI, useMobile, useSnackbar } from "hooks";
|
||||
import { useLocation, useParams } from "react-router-dom";
|
||||
import { Component, Device, Interaction } from "models";
|
||||
import { getContextKeys, getContextTypes } from "pbHelpers/Context";
|
||||
|
|
@ -43,6 +43,7 @@ export default function DeviceSupport() {
|
|||
const deviceAPI = useDeviceAPI()
|
||||
const snackbar = useSnackbar()
|
||||
const theme = useTheme()
|
||||
const isMobile = useMobile()
|
||||
|
||||
const { state } = useLocation();
|
||||
const [{ user, as }] = useGlobalState()
|
||||
|
|
@ -188,7 +189,7 @@ export default function DeviceSupport() {
|
|||
}
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
<PageContainer spacing={isMobile ? 0 : 2}>
|
||||
<Grid container justifyContent={"space-between"}>
|
||||
<Grid>
|
||||
<SmartBreadcrumb deviceName={device.name()} state={{devicePageData: devicePageData}} />
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { makeStyles } from "@mui/styles";
|
|||
import ResponsiveTable, { Column } from "common/ResponsiveTable";
|
||||
import ProvisionDevice from "device/ProvisionDevice";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import { useDeviceAPI, useGlobalState, useGroupAPI } from "providers";
|
||||
import { useDeviceAPI, useGlobalState, useGroupAPI, useTeamAPI } from "providers";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import PageContainer from "./PageContainer";
|
||||
import { useMobile } from "hooks";
|
||||
|
|
@ -28,6 +28,7 @@ import StatusDust from "common/StatusDust";
|
|||
import StatusGas from "common/StatusGas";
|
||||
import { cloneDeep } from "lodash";
|
||||
import LoadingScreen from "app/LoadingScreen";
|
||||
import TeamDialog from "teams/TeamDialog";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => {
|
||||
return ({
|
||||
|
|
@ -98,9 +99,12 @@ export default function Devices() {
|
|||
const location = useLocation();
|
||||
const deviceAPI = useDeviceAPI();
|
||||
const groupAPI = useGroupAPI();
|
||||
const teamAPI = useTeamAPI();
|
||||
const [devicesLoading, setDevicesLoading] = useState(false)
|
||||
const [limit, setLimit] = useState(10);
|
||||
const [page, setPage] = useState(0);
|
||||
const [doneLoading, setDoneLoading] = useState(false)
|
||||
const [teamsDialog, setTeamsDialog] = useState(false)
|
||||
|
||||
const [{ user }] = useGlobalState()
|
||||
|
||||
|
|
@ -186,7 +190,7 @@ export default function Devices() {
|
|||
|
||||
const [preferencesAnchor, setPreferencesAnchor] = useState<any>(null)
|
||||
|
||||
const [{ as }] = useGlobalState()
|
||||
const [{ as, team }] = useGlobalState()
|
||||
|
||||
const updateGroups = (newGroups: Group[]) => {
|
||||
setGroups(newGroups);
|
||||
|
|
@ -327,6 +331,7 @@ export default function Devices() {
|
|||
setTotal(resp.data.total)
|
||||
}).finally(() => {
|
||||
setDevicesLoading(false)
|
||||
setDoneLoading(true)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -338,6 +343,16 @@ export default function Devices() {
|
|||
loadGroups()
|
||||
}, [groupLimit, groupPage, orderGroup, orderGroupBy, searchGroup, as])
|
||||
|
||||
useEffect(() => {
|
||||
if (doneLoading && devices.length < 1 && groups.length < 1) {
|
||||
teamAPI.listTeams(1, 0).then(resp => {
|
||||
if (resp.data.teams.length > 0 && team.key().length < 1) {
|
||||
setTeamsDialog(true);
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [doneLoading, devices, groups])
|
||||
|
||||
const handleChange = (event: any) => {
|
||||
setLimit(event.target.value);
|
||||
};
|
||||
|
|
@ -826,6 +841,13 @@ export default function Devices() {
|
|||
addGroupCallback={addGroupCallback}
|
||||
/>
|
||||
{preferencesMenu()}
|
||||
<TeamDialog
|
||||
open={teamsDialog}
|
||||
setOpen={setTeamsDialog}
|
||||
title={"You have teams!"}
|
||||
info={"Looks like you don't have any devices, but are a part of at least one team. If you want to see your teams devices, please select your team and choose the option \"View as team\""}
|
||||
hideKey={"devices-teams-notification-dialog"}
|
||||
/>
|
||||
</PageContainer>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
import {
|
||||
AppBar,
|
||||
Button,
|
||||
Checkbox,
|
||||
FormControlLabel,
|
||||
FormGroup,
|
||||
IconButton,
|
||||
Theme,
|
||||
Toolbar,
|
||||
|
|
@ -18,6 +21,9 @@ import { makeStyles } from "@mui/styles";
|
|||
interface Props {
|
||||
open: boolean;
|
||||
setOpen: (value: React.SetStateAction<boolean>) => void;
|
||||
title?: string;
|
||||
info?: string;
|
||||
hideKey?: string;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => {
|
||||
|
|
@ -37,16 +43,22 @@ const useStyles = makeStyles((theme: Theme) => {
|
|||
});
|
||||
|
||||
export default function TeamDialog(props: Props) {
|
||||
const { open, setOpen } = props;
|
||||
const { open, setOpen, title, info, hideKey } = props;
|
||||
const teamAPI = useTeamAPI();
|
||||
const userAPI = useUserAPI();
|
||||
const [, dispatch] = useGlobalState();
|
||||
const [teamKey, setTeamKey] = useState<string>("");
|
||||
const [{ team, user }] = useGlobalState();
|
||||
const [viewAsTeam, setViewAsTeam] = useState(user.settings.useTeam)
|
||||
const [doNotShow, setDoNotShow] = useState(false)
|
||||
const classes = useStyles();
|
||||
|
||||
const shouldHide = hideKey ?
|
||||
(localStorage.getItem(hideKey) === "true" ? true : false)
|
||||
: false
|
||||
|
||||
const setTeam = () => {
|
||||
setOpen(false);
|
||||
onClose()
|
||||
dispatch({ key: "as", value: teamKey });
|
||||
if (teamKey === "" || teamKey.includes("auth")) {
|
||||
dispatch({ key: "team", value: Team.create() });
|
||||
|
|
@ -55,13 +67,19 @@ export default function TeamDialog(props: Props) {
|
|||
teamAPI.getTeam(teamKey).then(team => {
|
||||
dispatch({ key: "team", value: team });
|
||||
user.settings.defaultTeam = team.key();
|
||||
user.settings.useTeam = true; //when selecting a team now set to view as team by default
|
||||
user.settings.useTeam = viewAsTeam; //when selecting a team now set to view as team by default
|
||||
userAPI.updateUser(user.id(), user.protobuf());
|
||||
});
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
console.log("close")
|
||||
setOpen(false)
|
||||
if (hideKey) localStorage.setItem(hideKey, ""+doNotShow)
|
||||
}
|
||||
|
||||
return (
|
||||
<ResponsiveDialog open={open} onClose={() => setOpen(false)}>
|
||||
<ResponsiveDialog open={open && !shouldHide} onClose={onClose}>
|
||||
<AppBar position="relative">
|
||||
<Toolbar>
|
||||
<IconButton
|
||||
|
|
@ -72,9 +90,9 @@ export default function TeamDialog(props: Props) {
|
|||
<CloseIcon />
|
||||
</IconButton>
|
||||
<Typography variant="h6" className={classes.title}>
|
||||
Select a Team to View As
|
||||
{ title ? title : "Select a Team to View As"}
|
||||
</Typography>
|
||||
<Button color="inherit" onClick={setTeam}>
|
||||
<Button color="inherit" onClick={setTeam} >
|
||||
Save
|
||||
</Button>
|
||||
</Toolbar>
|
||||
|
|
@ -84,12 +102,40 @@ export default function TeamDialog(props: Props) {
|
|||
Viewing as: {team.name()}
|
||||
</Typography>
|
||||
)}
|
||||
{info &&
|
||||
<Typography variant="body1" className={classes.viewingAs}>
|
||||
{info}
|
||||
</Typography>
|
||||
}
|
||||
<TeamSearch
|
||||
//style={{ width: theme.spacing(32) }}
|
||||
className={classes.searchBar}
|
||||
loadUsers={user.hasFeature("admin")}
|
||||
setTeamCallback={setTeamKey}
|
||||
/>
|
||||
{/* <Checkbox checked={viewAsTeam} onChange={() => setViewAsTeam(!viewAsTeam)} /> */}
|
||||
<FormGroup sx={{ margin: 1, marginLeft: 2 }}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={viewAsTeam}
|
||||
onChange={() => setViewAsTeam(!viewAsTeam)}
|
||||
/>
|
||||
}
|
||||
label="View as team"
|
||||
/>
|
||||
</FormGroup>
|
||||
{hideKey && <FormGroup sx={{ margin: 1, marginLeft: 2 }}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={doNotShow}
|
||||
onChange={() => setDoNotShow(!doNotShow)}
|
||||
/>
|
||||
}
|
||||
label="Do not show again"
|
||||
/>
|
||||
</FormGroup>}
|
||||
</ResponsiveDialog>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue