Merge branch 'staging_environment' into node_exclusion_update
This commit is contained in:
commit
5b4d8d5566
25 changed files with 555 additions and 89 deletions
56
package-lock.json
generated
56
package-lock.json
generated
|
|
@ -49,6 +49,7 @@
|
||||||
"react-color": "^2.19.3",
|
"react-color": "^2.19.3",
|
||||||
"react-day-picker": "^9.6.5",
|
"react-day-picker": "^9.6.5",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
"react-emoji-render": "^2.0.1",
|
||||||
"react-error-boundary": "^5.0.0",
|
"react-error-boundary": "^5.0.0",
|
||||||
"react-full-screen": "^1.1.1",
|
"react-full-screen": "^1.1.1",
|
||||||
"react-horizontal-scrolling-menu": "^7.1.1",
|
"react-horizontal-scrolling-menu": "^7.1.1",
|
||||||
|
|
@ -9188,6 +9189,15 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/invariant": {
|
||||||
|
"version": "2.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||||
|
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"loose-envify": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-array-buffer": {
|
"node_modules/is-array-buffer": {
|
||||||
"version": "3.0.5",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
|
||||||
|
|
@ -9971,6 +9981,18 @@
|
||||||
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||||
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
|
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.flatten": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isstring": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/lodash.memoize": {
|
"node_modules/lodash.memoize": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
||||||
|
|
@ -11107,6 +11129,29 @@
|
||||||
"react": "^18.3.1"
|
"react": "^18.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-emoji-render": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-emoji-render/-/react-emoji-render-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-SKtsdwgEf2BFNiE9y4UBFZBWjkRcyWmhMprVly52+J77/zxThcfaQ3sCA0+2LtGJIRMpm4DGWSvyLg72fd1rXQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"emoji-regex": "^8.0.0",
|
||||||
|
"lodash.flatten": "^4.4.0",
|
||||||
|
"prop-types": "^15.5.8",
|
||||||
|
"string-replace-to-array": "^1.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=0.14.0",
|
||||||
|
"react-dom": ">=0.14.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-emoji-render/node_modules/emoji-regex": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/react-error-boundary": {
|
"node_modules/react-error-boundary": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"integrity": "sha512-tnjAxG+IkpLephNcePNA7v6F/QpWLH8He65+DmedchDwg162JZqx4NmbXj0mlAYVVEd81OW7aFhmbsScYfiAFQ==",
|
"integrity": "sha512-tnjAxG+IkpLephNcePNA7v6F/QpWLH8He65+DmedchDwg162JZqx4NmbXj0mlAYVVEd81OW7aFhmbsScYfiAFQ==",
|
||||||
|
|
@ -12408,6 +12453,17 @@
|
||||||
"safe-buffer": "~5.2.0"
|
"safe-buffer": "~5.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/string-replace-to-array": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-replace-to-array/-/string-replace-to-array-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-QIdKvmfXbdFvblXAAz6IIjR7A+C6SU6m2A+e7fE/0EYDC5yfeWNMJQ193fPsW7nG+9q52dv/UjnVrDaNVZXpmQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"invariant": "^2.2.1",
|
||||||
|
"lodash.flatten": "^4.2.0",
|
||||||
|
"lodash.isstring": "^4.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/string.prototype.matchall": {
|
"node_modules/string.prototype.matchall": {
|
||||||
"version": "4.0.12",
|
"version": "4.0.12",
|
||||||
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz",
|
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz",
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@
|
||||||
"react-color": "^2.19.3",
|
"react-color": "^2.19.3",
|
||||||
"react-day-picker": "^9.6.5",
|
"react-day-picker": "^9.6.5",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
"react-emoji-render": "^2.0.1",
|
||||||
"react-error-boundary": "^5.0.0",
|
"react-error-boundary": "^5.0.0",
|
||||||
"react-full-screen": "^1.1.1",
|
"react-full-screen": "^1.1.1",
|
||||||
"react-horizontal-scrolling-menu": "^7.1.1",
|
"react-horizontal-scrolling-menu": "^7.1.1",
|
||||||
|
|
|
||||||
BIN
public/Streamline/stream-logo-dark.png
Normal file
BIN
public/Streamline/stream-logo-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
|
|
@ -19,7 +19,7 @@ if ('serviceWorker' in navigator) {
|
||||||
}
|
}
|
||||||
|
|
||||||
createRoot(document.getElementById('root')!).render(
|
createRoot(document.getElementById('root')!).render(
|
||||||
<StrictMode>
|
// <StrictMode>
|
||||||
<App />
|
<App />
|
||||||
</StrictMode>,
|
// </StrictMode>,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,9 @@ export default function BinsList(props: Props) {
|
||||||
}}
|
}}
|
||||||
key={i}
|
key={i}
|
||||||
className={classes.gridListTile}
|
className={classes.gridListTile}
|
||||||
onClick={() => goToBin(i)}>
|
onClick={() => {
|
||||||
|
!duplicate && goToBin(i)
|
||||||
|
}}>
|
||||||
<BinCardV2
|
<BinCardV2
|
||||||
bin={b}
|
bin={b}
|
||||||
duplicateBin={duplicateBin}
|
duplicateBin={duplicateBin}
|
||||||
|
|
@ -136,7 +138,9 @@ export default function BinsList(props: Props) {
|
||||||
key={i}
|
key={i}
|
||||||
style={{ width: "184px" }}
|
style={{ width: "184px" }}
|
||||||
className={classes.gridListTile}
|
className={classes.gridListTile}
|
||||||
onClick={() => goToBin(i)}>
|
onClick={() => {
|
||||||
|
!duplicate && goToBin(i)
|
||||||
|
}}>
|
||||||
<BinCardV2
|
<BinCardV2
|
||||||
bin={b}
|
bin={b}
|
||||||
duplicateBin={duplicateBin}
|
duplicateBin={duplicateBin}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import Joyride, { Step, CallBackProps, STATUS, TooltipRenderProps, Locale } from "react-joyride";
|
import Joyride, { Step, CallBackProps, STATUS, TooltipRenderProps, Locale, ACTIONS, EVENTS } from "react-joyride";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
|
|
@ -10,12 +10,13 @@ import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
IconButton,
|
IconButton,
|
||||||
Theme,
|
Theme,
|
||||||
useTheme
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { KeyboardArrowLeft, KeyboardArrowRight, Close as CloseIcon } from "@mui/icons-material";
|
import { KeyboardArrowLeft, KeyboardArrowRight, Close as CloseIcon } from "@mui/icons-material";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { grey } from "@mui/material/colors";
|
import { grey } from "@mui/material/colors";
|
||||||
import { makeStyles } from "@mui/styles";
|
import { makeStyles } from "@mui/styles";
|
||||||
|
import { CSSProperties } from "react";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) => {
|
const useStyles = makeStyles((theme: Theme) => {
|
||||||
return ({
|
return ({
|
||||||
|
|
@ -46,6 +47,10 @@ const useStyles = makeStyles((theme: Theme) => {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export interface TourStep extends Step {
|
||||||
|
onNext?: () => void; // Define onNext as an optional function
|
||||||
|
}
|
||||||
|
|
||||||
const StepContainer = (props: TooltipRenderProps, numSteps: number, skip: () => void) => {
|
const StepContainer = (props: TooltipRenderProps, numSteps: number, skip: () => void) => {
|
||||||
const {
|
const {
|
||||||
continuous,
|
continuous,
|
||||||
|
|
@ -114,18 +119,30 @@ const StepContainer = (props: TooltipRenderProps, numSteps: number, skip: () =>
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
run: boolean;
|
run: boolean;
|
||||||
steps: Step[];
|
steps: TourStep[];
|
||||||
endTourCallback: () => void;
|
endTourCallback: () => void;
|
||||||
|
spotlightStyle?: CSSProperties,
|
||||||
|
setStepIndex?: React.Dispatch<React.SetStateAction<number>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Tour(props: Props) {
|
export default function Tour(props: Props) {
|
||||||
const { run, steps, endTourCallback } = props;
|
const { run, steps, endTourCallback, setStepIndex, spotlightStyle } = props;
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const handleTourCallback = (data: CallBackProps) => {
|
const handleTourCallback = (data: CallBackProps) => {
|
||||||
const { status } = data;
|
const { action, index, status, type } = data;
|
||||||
const finishedStatuses: string[] = [STATUS.FINISHED, STATUS.SKIPPED];
|
const finishedStatuses: string[] = [STATUS.FINISHED, STATUS.SKIPPED];
|
||||||
|
|
||||||
|
if (setStepIndex) setStepIndex(index)
|
||||||
|
|
||||||
|
if (action === ACTIONS.NEXT && type === EVENTS.STEP_AFTER) {
|
||||||
|
// Safely access the step and call onNext if it exists
|
||||||
|
const currentStep = steps[index];
|
||||||
|
if (currentStep.onNext) {
|
||||||
|
currentStep.onNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (finishedStatuses.includes(status)) {
|
if (finishedStatuses.includes(status)) {
|
||||||
endTourCallback();
|
endTourCallback();
|
||||||
}
|
}
|
||||||
|
|
@ -150,6 +167,9 @@ export default function Tour(props: Props) {
|
||||||
primaryColor: theme.palette.primary.main,
|
primaryColor: theme.palette.primary.main,
|
||||||
textColor: theme.palette.text.primary,
|
textColor: theme.palette.text.primary,
|
||||||
zIndex: theme.zIndex.modal
|
zIndex: theme.zIndex.modal
|
||||||
|
},
|
||||||
|
spotlight: {
|
||||||
|
...spotlightStyle
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,10 @@ export default function SyncDevice(props: Props) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
error("Unable to resync device");
|
error("Unable to resync device");
|
||||||
close();
|
close();
|
||||||
});
|
})
|
||||||
|
.finally(() => {
|
||||||
|
close()
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -475,6 +475,37 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
weightConversionKg: 27.2158214642112,
|
weightConversionKg: 27.2158214642112,
|
||||||
bushelsPerTonne: 36.744
|
bushelsPerTonne: 36.744
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
pond.Grain.GRAIN_DRY_BEANS_RED,
|
||||||
|
{
|
||||||
|
name: "Dry Beans Red",
|
||||||
|
group: "Dry Beans",
|
||||||
|
equation: Equation.halsey,
|
||||||
|
a: 4.2669,
|
||||||
|
b: -0.013382,
|
||||||
|
c: 1.6933,
|
||||||
|
setTempC: defaultSetTemp,
|
||||||
|
targetMC: 15.0,
|
||||||
|
colour: "red",
|
||||||
|
weightConversionKg: 27.2155,
|
||||||
|
bushelsPerTonne: 36.744
|
||||||
|
}
|
||||||
|
],[
|
||||||
|
pond.Grain.GRAIN_DRY_BEANS_BLACK,
|
||||||
|
{
|
||||||
|
name: "Dry Beans Black",
|
||||||
|
group: "Dry Beans",
|
||||||
|
equation: Equation.halsey,
|
||||||
|
a: 5.2003,
|
||||||
|
b: -0.022685,
|
||||||
|
c: 1.9656,
|
||||||
|
setTempC: defaultSetTemp,
|
||||||
|
targetMC: 15.0,
|
||||||
|
colour: "grey",
|
||||||
|
weightConversionKg: 27.2155,
|
||||||
|
bushelsPerTonne: 36.744
|
||||||
|
}
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,17 +36,17 @@ const featureVersions: Map<string, FeatureVersionByPlatform> = new Map([
|
||||||
],[
|
],[
|
||||||
"detectI2C",
|
"detectI2C",
|
||||||
{
|
{
|
||||||
photon: "NA",
|
photon: "N/A",
|
||||||
electron: "NA",
|
electron: "N/A",
|
||||||
v2Wifi: "2.1.6",
|
v2Wifi: "N/A",
|
||||||
v2Cell: "2.1.6",
|
v2Cell: "N/A",
|
||||||
v2WifiS3: "2.1.6",
|
v2WifiS3: "N/A",
|
||||||
v2CellS3: "2.1.6",
|
v2CellS3: "N/A",
|
||||||
v2CellBlack: "2.1.6",
|
v2CellBlack: "N/A",
|
||||||
v2CellGreen: "2.1.6",
|
v2CellGreen: "N/A",
|
||||||
v2WifiBlue: "2.1.6",
|
v2WifiBlue: "N/A",
|
||||||
v2CellBlue: "2.1.6",
|
v2CellBlue: "N/A",
|
||||||
v2EthBlue: "2.1.6"
|
v2EthBlue: "N/A"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import { getWhitelabel } from "services/whiteLabel";
|
||||||
import Ventilation from "pages/VentEditor";
|
import Ventilation from "pages/VentEditor";
|
||||||
import { useGlobalState } from "providers";
|
import { useGlobalState } from "providers";
|
||||||
import DeviceSupport from "pages/DeviceSupport";
|
import DeviceSupport from "pages/DeviceSupport";
|
||||||
|
import SignupCallback from "pages/SignupCallback";
|
||||||
|
|
||||||
const DeviceHistory = lazy(() => import("pages/DeviceHistory"));
|
const DeviceHistory = lazy(() => import("pages/DeviceHistory"));
|
||||||
const DevicePage = lazy(() => import("pages/Device"));
|
const DevicePage = lazy(() => import("pages/Device"));
|
||||||
|
|
@ -302,6 +303,8 @@ export default function Router() {
|
||||||
|
|
||||||
{/* Redirects */}
|
{/* Redirects */}
|
||||||
<Route path="/callback" element={<Navigate to="/" />} />
|
<Route path="/callback" element={<Navigate to="/" />} />
|
||||||
|
{/* <Route path="/signupCallback" element={<Navigate to="/" />} /> */}
|
||||||
|
<Route path="/signupCallback" element={<SignupCallback />} />
|
||||||
{/* <Route path="/login" element={<Login />} /> */}
|
{/* <Route path="/login" element={<Login />} /> */}
|
||||||
{/* <Route path="/team/:teamID" element={<Navigate to="/teams/:teamID" />} /> */}
|
{/* <Route path="/team/:teamID" element={<Navigate to="/teams/:teamID" />} /> */}
|
||||||
{/* <Route path="/device/:deviceID" element={<Navigate to="/devices/:devicesID" />} /> */}
|
{/* <Route path="/device/:deviceID" element={<Navigate to="/devices/:devicesID" />} /> */}
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ export default function SideNavigator(props: Props) {
|
||||||
{(isAg || isStreamline || user.hasFeature("admin")) && (
|
{(isAg || isStreamline || user.hasFeature("admin")) && (
|
||||||
<Tooltip title="Bins" placement="right">
|
<Tooltip title="Bins" placement="right">
|
||||||
<ListItemButton
|
<ListItemButton
|
||||||
id="tour-dashboard"
|
id="tour-bins"
|
||||||
onClick={() => goTo("/bins")}
|
onClick={() => goTo("/bins")}
|
||||||
classes={getClasses("/bin")}
|
classes={getClasses("/bin")}
|
||||||
>
|
>
|
||||||
|
|
@ -277,7 +277,7 @@ export default function SideNavigator(props: Props) {
|
||||||
{(isMiVent || user.hasFeature("admin")) && (
|
{(isMiVent || user.hasFeature("admin")) && (
|
||||||
<Tooltip title="Mines" placement="right">
|
<Tooltip title="Mines" placement="right">
|
||||||
<ListItemButton
|
<ListItemButton
|
||||||
id="tour-dashboard"
|
id="tour-mines"
|
||||||
onClick={() => goTo("/mines")}
|
onClick={() => goTo("/mines")}
|
||||||
classes={getClasses("/mine")}
|
classes={getClasses("/mine")}
|
||||||
>
|
>
|
||||||
|
|
@ -330,7 +330,7 @@ export default function SideNavigator(props: Props) {
|
||||||
}
|
}
|
||||||
<Tooltip title="Teams" placement="right">
|
<Tooltip title="Teams" placement="right">
|
||||||
<ListItemButton
|
<ListItemButton
|
||||||
id="tour-dashboard"
|
id="tour-teams"
|
||||||
onClick={() => goTo("/teams")}
|
onClick={() => goTo("/teams")}
|
||||||
classes={getClasses("/team")}
|
classes={getClasses("/team")}
|
||||||
>
|
>
|
||||||
|
|
@ -342,7 +342,7 @@ export default function SideNavigator(props: Props) {
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title="Users" placement="right">
|
<Tooltip title="Users" placement="right">
|
||||||
<ListItemButton
|
<ListItemButton
|
||||||
id="tour-dashboard"
|
id="tour-users"
|
||||||
onClick={() => goTo("/users")}
|
onClick={() => goTo("/users")}
|
||||||
classes={getClasses("/user")}
|
classes={getClasses("/user")}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1107,7 +1107,7 @@ export default function Bin(props: Props) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContainer spacing={1}>
|
<PageContainer >
|
||||||
{showPlenumError()}
|
{showPlenumError()}
|
||||||
<Box
|
<Box
|
||||||
paddingBottom={isMobile || displayMobile ? 1 : 2}
|
paddingBottom={isMobile || displayMobile ? 1 : 2}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ import {
|
||||||
ImageList,
|
ImageList,
|
||||||
ImageListItem,
|
ImageListItem,
|
||||||
InputLabel,
|
InputLabel,
|
||||||
lighten,
|
|
||||||
ListItemIcon,
|
ListItemIcon,
|
||||||
ListItemText,
|
ListItemText,
|
||||||
Menu,
|
Menu,
|
||||||
|
|
@ -26,8 +25,6 @@ import {
|
||||||
Select,
|
Select,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Theme,
|
Theme,
|
||||||
ToggleButton,
|
|
||||||
ToggleButtonGroup,
|
|
||||||
Typography,
|
Typography,
|
||||||
useTheme,
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
|
@ -61,7 +58,8 @@ import {
|
||||||
// useBinYardAPI,
|
// useBinYardAPI,
|
||||||
useGlobalState,
|
useGlobalState,
|
||||||
useInteractionsAPI,
|
useInteractionsAPI,
|
||||||
useSnackbar
|
useSnackbar,
|
||||||
|
useTeamAPI
|
||||||
} from "providers";
|
} from "providers";
|
||||||
import React, { SetStateAction, useCallback, useEffect, useState } from "react";
|
import React, { SetStateAction, useCallback, useEffect, useState } from "react";
|
||||||
// import { getThemeType } from "theme";
|
// import { getThemeType } from "theme";
|
||||||
|
|
@ -72,7 +70,7 @@ import ObjectTable from "objects/ObjectTable";
|
||||||
import ResponsiveDialog from "common/ResponsiveDialog";
|
import ResponsiveDialog from "common/ResponsiveDialog";
|
||||||
import { describeMeasurement } from "pbHelpers/MeasurementDescriber";
|
import { describeMeasurement } from "pbHelpers/MeasurementDescriber";
|
||||||
import { green, yellow } from "@mui/material/colors";
|
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 { useNavigate } from "react-router-dom";
|
||||||
import BinSettings from "bin/BinSettings";
|
import BinSettings from "bin/BinSettings";
|
||||||
import AddBinFab from "bin/AddBinFab";
|
import AddBinFab from "bin/AddBinFab";
|
||||||
|
|
@ -82,6 +80,7 @@ import GrainBagSettings from "grainBag/grainBagSettings";
|
||||||
import GrainBagList from "grainBag/grainBagList";
|
import GrainBagList from "grainBag/grainBagList";
|
||||||
import BinYards from "bin/BinYards";
|
import BinYards from "bin/BinYards";
|
||||||
import ButtonGroup from "common/ButtonGroup";
|
import ButtonGroup from "common/ButtonGroup";
|
||||||
|
import TeamDialog from "teams/TeamDialog";
|
||||||
// import { useHistory } from "react-router";
|
// import { useHistory } from "react-router";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) => {
|
const useStyles = makeStyles((theme: Theme) => {
|
||||||
|
|
@ -141,11 +140,13 @@ export default function Bins(props: Props) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const isMobile = useMobile();
|
const isMobile = useMobile();
|
||||||
const binAPI = useBinAPI();
|
const binAPI = useBinAPI();
|
||||||
|
const teamAPI = useTeamAPI();
|
||||||
// const binyardAPI = useBinYardAPI();
|
// const binyardAPI = useBinYardAPI();
|
||||||
const interactionsAPI = useInteractionsAPI();
|
const interactionsAPI = useInteractionsAPI();
|
||||||
const [{ user, as }] = useGlobalState();
|
const [{ user, as }] = useGlobalState();
|
||||||
const [allLoading, setAllLoading] = useState(false);
|
const [allLoading, setAllLoading] = useState(false);
|
||||||
const [binsLoading, setBinsLoading] = useState(false);
|
const [binsLoading, setBinsLoading] = useState(false);
|
||||||
|
const [doneLoadingPage, setDoneLoadingPage] = useState(false)
|
||||||
const [addBinOpen, setAddBinOpen] = useState(false);
|
const [addBinOpen, setAddBinOpen] = useState(false);
|
||||||
const [paginatedBins, setPaginatedBins] = useState<PaginatedBins>({
|
const [paginatedBins, setPaginatedBins] = useState<PaginatedBins>({
|
||||||
bins: [],
|
bins: [],
|
||||||
|
|
@ -188,13 +189,16 @@ export default function Bins(props: Props) {
|
||||||
const [qrKeyList, setQrKeyList] = useState<QrCodeKey[]>([]);
|
const [qrKeyList, setQrKeyList] = useState<QrCodeKey[]>([]);
|
||||||
const [totalFanControllers, setTotalFanControllers] = useState(0);
|
const [totalFanControllers, setTotalFanControllers] = useState(0);
|
||||||
const [totalFanControllersOn, setTotalFanControllersOn] = useState(0);
|
const [totalFanControllersOn, setTotalFanControllersOn] = useState(0);
|
||||||
const [yardsLoading, setYardsLoading] = useState(false);
|
// const [yardsLoading, setYardsLoading] = useState(false);
|
||||||
const [openAddAlerts, setOpenAddAlerts] = useState(false);
|
const [openAddAlerts, setOpenAddAlerts] = useState(false);
|
||||||
const [alertBins, setAlertBins] = useState<Bin[]>([]);
|
const [alertBins, setAlertBins] = useState<Bin[]>([]);
|
||||||
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">("average");
|
||||||
|
|
||||||
|
const [teamsDialog, setTeamsDialog] = useState(false)
|
||||||
|
|
||||||
// const [scrollTranslations, setScrollTranslations] = useState({
|
// const [scrollTranslations, setScrollTranslations] = useState({
|
||||||
// bins: 0,
|
// bins: 0,
|
||||||
// empty: 0,
|
// empty: 0,
|
||||||
|
|
@ -252,6 +256,18 @@ export default function Bins(props: Props) {
|
||||||
// selected: {}
|
// 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(() => {
|
useEffect(() => {
|
||||||
let ebt = sessionStorage.getItem("expandBinTotal");
|
let ebt = sessionStorage.getItem("expandBinTotal");
|
||||||
if (ebt === "true") {
|
if (ebt === "true") {
|
||||||
|
|
@ -400,7 +416,7 @@ export default function Bins(props: Props) {
|
||||||
const bags = resp.data.bags.map(b => GrainBag.create(b));
|
const bags = resp.data.bags.map(b => GrainBag.create(b));
|
||||||
setGrainBags(bags);
|
setGrainBags(bags);
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(() => {
|
||||||
setPaginatedBins({ bins: [], binsOffset: 0, binsTotal: 0 });
|
setPaginatedBins({ bins: [], binsOffset: 0, binsTotal: 0 });
|
||||||
setBinMetrics(pond.BinMetrics.create());
|
setBinMetrics(pond.BinMetrics.create());
|
||||||
setYards([]);
|
setYards([]);
|
||||||
|
|
@ -408,6 +424,7 @@ export default function Bins(props: Props) {
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
setAllLoading(false);
|
setAllLoading(false);
|
||||||
setBinsLoading(false);
|
setBinsLoading(false);
|
||||||
|
setDoneLoadingPage(true)
|
||||||
});
|
});
|
||||||
}, [binAPI, yardFilter, order, orderBy, as, loadingAs, loadingFilter]); // eslint-disable-line react-hooks/exhaustive-deps
|
}, [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]);
|
setFertilizerBins([...fert]);
|
||||||
setQrKeyList([...newKeyList]);
|
setQrKeyList([...newKeyList]);
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(() => {
|
||||||
setPaginatedBins({ bins: [], binsOffset: 0, binsTotal: 0 });
|
setPaginatedBins({ bins: [], binsOffset: 0, binsTotal: 0 });
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
|
@ -462,13 +479,13 @@ export default function Bins(props: Props) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const searchYards = (
|
// const searchYards = (
|
||||||
search?: string,
|
// search?: string,
|
||||||
limit?: number,
|
// limit?: number,
|
||||||
offset?: number,
|
// offset?: number,
|
||||||
order?: "asc" | "desc"
|
// order?: "asc" | "desc"
|
||||||
) => {
|
// ) => {
|
||||||
setYardsLoading(true);
|
// setYardsLoading(true);
|
||||||
// binyardAPI.listBinYards(limit ?? binsLimit, offset ?? 0, order, "name", search).then(resp => {
|
// binyardAPI.listBinYards(limit ?? binsLimit, offset ?? 0, order, "name", search).then(resp => {
|
||||||
// let y: pond.BinYardSettings[] = [];
|
// let y: pond.BinYardSettings[] = [];
|
||||||
// let p: Dictionary<pond.Permission[]> = {};
|
// let p: Dictionary<pond.Permission[]> = {};
|
||||||
|
|
@ -493,7 +510,7 @@ export default function Bins(props: Props) {
|
||||||
// }
|
// }
|
||||||
// setYardsLoading(false);
|
// setYardsLoading(false);
|
||||||
// });
|
// });
|
||||||
};
|
// };
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadBins();
|
loadBins();
|
||||||
|
|
@ -515,8 +532,8 @@ export default function Bins(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const duplicateBin = (bin: Bin) => {
|
const duplicateBin = (bin: Bin) => {
|
||||||
binAPI.addBin(bin.settings, as).then(resp => {
|
binAPI.addBin(bin.settings, as).then(() => {
|
||||||
loadBins();
|
loadMoreBins(contentFilter);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -556,7 +573,7 @@ export default function Bins(props: Props) {
|
||||||
.then(resp => {
|
.then(resp => {
|
||||||
openSnack("Successfully added " + resp.data.numAlertsSet + " alerts");
|
openSnack("Successfully added " + resp.data.numAlertsSet + " alerts");
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(() => {
|
||||||
console.log("errors found");
|
console.log("errors found");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -1080,7 +1097,7 @@ export default function Bins(props: Props) {
|
||||||
control={
|
control={
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={displayGrain}
|
checked={displayGrain}
|
||||||
onChange={(e, checked) => {
|
onChange={(_, checked) => {
|
||||||
setDisplayGrain(checked);
|
setDisplayGrain(checked);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -1093,7 +1110,7 @@ export default function Bins(props: Props) {
|
||||||
control={
|
control={
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={displayFert}
|
checked={displayFert}
|
||||||
onChange={(e, checked) => {
|
onChange={(_, checked) => {
|
||||||
setDisplayFert(checked);
|
setDisplayFert(checked);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -1106,7 +1123,7 @@ export default function Bins(props: Props) {
|
||||||
control={
|
control={
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={displayEmpty}
|
checked={displayEmpty}
|
||||||
onChange={(e, checked) => {
|
onChange={(_, checked) => {
|
||||||
setDisplayEmpty(checked);
|
setDisplayEmpty(checked);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -1392,15 +1409,17 @@ export default function Bins(props: Props) {
|
||||||
{addALertsDialog()}
|
{addALertsDialog()}
|
||||||
<BinYards
|
<BinYards
|
||||||
yards={yards}
|
yards={yards}
|
||||||
yardsLoading={yardsLoading}
|
// yardsLoading={yardsLoading}
|
||||||
|
yardsLoading={false}
|
||||||
yardPerms={yardPermissions}
|
yardPerms={yardPermissions}
|
||||||
showTabs={!props.insert}
|
showTabs={!props.insert}
|
||||||
setYardFilter={setYardFilter}
|
setYardFilter={setYardFilter}
|
||||||
bins={paginatedBins.bins}
|
bins={paginatedBins.bins}
|
||||||
loadBins={loadBins}
|
loadBins={loadBins}
|
||||||
loadYards={(search, limit, offset) => {
|
// loadYards={(search, limit, offset) => {
|
||||||
searchYards(search, limit, offset);
|
// searchYards(search, limit, offset);
|
||||||
}}
|
// }}
|
||||||
|
loadYards={() => {}}
|
||||||
grainBags={grainBags}
|
grainBags={grainBags}
|
||||||
setShowing={(val: "all" | "bins" | "bags") => {
|
setShowing={(val: "all" | "bins" | "bags") => {
|
||||||
setShowing(val);
|
setShowing(val);
|
||||||
|
|
@ -1473,6 +1492,13 @@ export default function Bins(props: Props) {
|
||||||
/>
|
/>
|
||||||
{binMenu()}
|
{binMenu()}
|
||||||
<AddBinFab onClick={() => setAddBinOpen(true)} pulse={binsTotal < 1 && !allLoading} />
|
<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>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import PageContainer from "./PageContainer";
|
||||||
import { pond } from "protobuf-ts/pond";
|
import { pond } from "protobuf-ts/pond";
|
||||||
import LogsDisplay from "common/LogsDisplay";
|
import LogsDisplay from "common/LogsDisplay";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useDeviceAPI, useSnackbar } from "hooks";
|
import { useDeviceAPI, useMobile, useSnackbar } from "hooks";
|
||||||
import { useLocation, useParams } from "react-router-dom";
|
import { useLocation, useParams } from "react-router-dom";
|
||||||
import { Component, Device, Interaction } from "models";
|
import { Component, Device, Interaction } from "models";
|
||||||
import { getContextKeys, getContextTypes } from "pbHelpers/Context";
|
import { getContextKeys, getContextTypes } from "pbHelpers/Context";
|
||||||
|
|
@ -43,6 +43,7 @@ export default function DeviceSupport() {
|
||||||
const deviceAPI = useDeviceAPI()
|
const deviceAPI = useDeviceAPI()
|
||||||
const snackbar = useSnackbar()
|
const snackbar = useSnackbar()
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
const isMobile = useMobile()
|
||||||
|
|
||||||
const { state } = useLocation();
|
const { state } = useLocation();
|
||||||
const [{ user, as }] = useGlobalState()
|
const [{ user, as }] = useGlobalState()
|
||||||
|
|
@ -188,7 +189,7 @@ export default function DeviceSupport() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContainer>
|
<PageContainer spacing={isMobile ? 0 : 2}>
|
||||||
<Grid container justifyContent={"space-between"}>
|
<Grid container justifyContent={"space-between"}>
|
||||||
<Grid>
|
<Grid>
|
||||||
<SmartBreadcrumb deviceName={device.name()} state={{devicePageData: devicePageData}} />
|
<SmartBreadcrumb deviceName={device.name()} state={{devicePageData: devicePageData}} />
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { makeStyles } from "@mui/styles";
|
||||||
import ResponsiveTable, { Column } from "common/ResponsiveTable";
|
import ResponsiveTable, { Column } from "common/ResponsiveTable";
|
||||||
import ProvisionDevice from "device/ProvisionDevice";
|
import ProvisionDevice from "device/ProvisionDevice";
|
||||||
import { pond } from "protobuf-ts/pond";
|
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 { useCallback, useEffect, useState } from "react";
|
||||||
import PageContainer from "./PageContainer";
|
import PageContainer from "./PageContainer";
|
||||||
import { useMobile } from "hooks";
|
import { useMobile } from "hooks";
|
||||||
|
|
@ -28,6 +28,7 @@ import StatusDust from "common/StatusDust";
|
||||||
import StatusGas from "common/StatusGas";
|
import StatusGas from "common/StatusGas";
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import LoadingScreen from "app/LoadingScreen";
|
import LoadingScreen from "app/LoadingScreen";
|
||||||
|
import TeamDialog from "teams/TeamDialog";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) => {
|
const useStyles = makeStyles((theme: Theme) => {
|
||||||
return ({
|
return ({
|
||||||
|
|
@ -98,9 +99,12 @@ export default function Devices() {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const deviceAPI = useDeviceAPI();
|
const deviceAPI = useDeviceAPI();
|
||||||
const groupAPI = useGroupAPI();
|
const groupAPI = useGroupAPI();
|
||||||
|
const teamAPI = useTeamAPI();
|
||||||
const [devicesLoading, setDevicesLoading] = useState(false)
|
const [devicesLoading, setDevicesLoading] = useState(false)
|
||||||
const [limit, setLimit] = useState(10);
|
const [limit, setLimit] = useState(10);
|
||||||
const [page, setPage] = useState(0);
|
const [page, setPage] = useState(0);
|
||||||
|
const [doneLoading, setDoneLoading] = useState(false)
|
||||||
|
const [teamsDialog, setTeamsDialog] = useState(false)
|
||||||
|
|
||||||
const [{ user }] = useGlobalState()
|
const [{ user }] = useGlobalState()
|
||||||
|
|
||||||
|
|
@ -186,7 +190,7 @@ export default function Devices() {
|
||||||
|
|
||||||
const [preferencesAnchor, setPreferencesAnchor] = useState<any>(null)
|
const [preferencesAnchor, setPreferencesAnchor] = useState<any>(null)
|
||||||
|
|
||||||
const [{ as }] = useGlobalState()
|
const [{ as, team }] = useGlobalState()
|
||||||
|
|
||||||
const updateGroups = (newGroups: Group[]) => {
|
const updateGroups = (newGroups: Group[]) => {
|
||||||
setGroups(newGroups);
|
setGroups(newGroups);
|
||||||
|
|
@ -327,6 +331,7 @@ export default function Devices() {
|
||||||
setTotal(resp.data.total)
|
setTotal(resp.data.total)
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
setDevicesLoading(false)
|
setDevicesLoading(false)
|
||||||
|
setDoneLoading(true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -338,6 +343,16 @@ export default function Devices() {
|
||||||
loadGroups()
|
loadGroups()
|
||||||
}, [groupLimit, groupPage, orderGroup, orderGroupBy, searchGroup, as])
|
}, [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) => {
|
const handleChange = (event: any) => {
|
||||||
setLimit(event.target.value);
|
setLimit(event.target.value);
|
||||||
};
|
};
|
||||||
|
|
@ -826,6 +841,13 @@ export default function Devices() {
|
||||||
addGroupCallback={addGroupCallback}
|
addGroupCallback={addGroupCallback}
|
||||||
/>
|
/>
|
||||||
{preferencesMenu()}
|
{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>
|
</PageContainer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -12,7 +12,7 @@ import {
|
||||||
TypeBackground
|
TypeBackground
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { blue, green, orange, red } from "@mui/material/colors";
|
import { blue, green, orange, red } from "@mui/material/colors";
|
||||||
import { createStyles, makeStyles } from "@mui/styles";
|
import { makeStyles } from "@mui/styles";
|
||||||
//import { TypeBackground } from "@material-ui/core/styles/createPalette";
|
//import { TypeBackground } from "@material-ui/core/styles/createPalette";
|
||||||
import {
|
import {
|
||||||
ArrowUpward,
|
ArrowUpward,
|
||||||
|
|
@ -267,7 +267,7 @@ export default function Firmware() {
|
||||||
if (selected) {
|
if (selected) {
|
||||||
firmwareAPI
|
firmwareAPI
|
||||||
.removeFirmware(selected.settings.platform, selected.settings.version)
|
.removeFirmware(selected.settings.platform, selected.settings.version)
|
||||||
.then((response: any) => {
|
.then(() => {
|
||||||
success("Successfully removed firmware");
|
success("Successfully removed firmware");
|
||||||
})
|
})
|
||||||
.catch((err: any) => {
|
.catch((err: any) => {
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ export const PageContainer: React.FunctionComponent<Props> = (props: Props) => {
|
||||||
const { children, fullViewport, isCenterCenter, sx } = props;
|
const { children, fullViewport, isCenterCenter, sx } = props;
|
||||||
// let fullViewport = false
|
// let fullViewport = false
|
||||||
// let isCenterCenter = false
|
// let isCenterCenter = false
|
||||||
const spacing = props.spacing ? props.spacing : 2;
|
const spacing = props.spacing ?? 0;
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
className={classNames(
|
className={classNames(
|
||||||
|
|
|
||||||
217
src/pages/SignupCallback.tsx
Normal file
217
src/pages/SignupCallback.tsx
Normal file
|
|
@ -0,0 +1,217 @@
|
||||||
|
import { useDeviceAPI, useMobile, useUserAPI } from "hooks";
|
||||||
|
import PageContainer from "./PageContainer";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { Button, CircularProgress, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, Divider, Typography } from "@mui/material";
|
||||||
|
import { useBinAPI, useGlobalState, useTeamAPI } from "providers";
|
||||||
|
import { CheckCircleOutline } from "@mui/icons-material";
|
||||||
|
import { green } from "@mui/material/colors";
|
||||||
|
import Tour, { TourStep } from "common/Tour";
|
||||||
|
import Emoji from "react-emoji-render";
|
||||||
|
import { getWhitelabel, IsAdaptiveAgriculture } from "services/whiteLabel";
|
||||||
|
// import { color } from "framer-motion";
|
||||||
|
|
||||||
|
// interface Props {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// export default function SignupCallback (props: Props) {
|
||||||
|
export default function SignupCallback () {
|
||||||
|
const userAPI = useUserAPI();
|
||||||
|
const teamAPI = useTeamAPI()
|
||||||
|
const deviceAPI = useDeviceAPI();
|
||||||
|
const binAPI = useBinAPI();
|
||||||
|
const isMobile = useMobile()
|
||||||
|
const [{ user }] = useGlobalState();
|
||||||
|
const whiteLabel = getWhitelabel()
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [signupDialogOpen, setSignupDialogOpen] = useState(true)
|
||||||
|
const [hasTeams, setHasTeams] = useState(false)
|
||||||
|
const [hasDevices, setHasDevices] = useState(false)
|
||||||
|
const [hasBins, setHasBins] = useState(false)
|
||||||
|
const [isTourRunning, setIsTourRunning] = useState(false);
|
||||||
|
const [stepIndex, setStepIndex] = useState(0)
|
||||||
|
|
||||||
|
const [doneBins, setDoneBins] = useState(false)
|
||||||
|
const [doneTeams, setDoneTeams] = useState(false)
|
||||||
|
const [doneDevices, setDoneDevices] = useState(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setLoading(true)
|
||||||
|
userAPI.completeSignup().then(() => {
|
||||||
|
teamAPI.listTeams(1, 0).then(resp => {
|
||||||
|
setHasTeams(resp.data.teams.length > 0)
|
||||||
|
}).finally(() => setDoneTeams(true))
|
||||||
|
deviceAPI.list(1, 0).then(resp => {
|
||||||
|
setHasDevices(resp.data.devices.length > 0)
|
||||||
|
}).finally(() => setDoneDevices(true))
|
||||||
|
binAPI.listBins(1, 0).then(resp => {
|
||||||
|
setHasBins(resp.data.bins.length > 0)
|
||||||
|
}).finally(() => setDoneBins(true))
|
||||||
|
}).finally(() => setLoading(false))
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const loadingComplete = () => {
|
||||||
|
return loading === false && doneBins && doneTeams && doneDevices
|
||||||
|
}
|
||||||
|
|
||||||
|
const content = () => {
|
||||||
|
return (
|
||||||
|
<DialogContent sx={{ margin: "auto", textAlign: "center" }}>
|
||||||
|
{ loadingComplete() ?
|
||||||
|
<CheckCircleOutline sx={{ fontSize: 64, color: green[500] }}/>
|
||||||
|
:
|
||||||
|
<CircularProgress size={64}/>
|
||||||
|
}
|
||||||
|
<DialogContentText sx={{marginTop: 2}}>
|
||||||
|
{hasTeams && "Teams found!"}
|
||||||
|
<br/>
|
||||||
|
{hasDevices && "Devices found!"}
|
||||||
|
<br/>
|
||||||
|
{hasBins && "Bins found!"}
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTourSteps = (): TourStep[] => {
|
||||||
|
let steps: TourStep[] = [
|
||||||
|
{
|
||||||
|
title: (
|
||||||
|
<>
|
||||||
|
Welcome to {whiteLabel.name}
|
||||||
|
<Emoji text=" 🎉" />
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
content: (
|
||||||
|
<>
|
||||||
|
<Typography variant="subtitle2" gutterBottom>
|
||||||
|
{"Hello " + user.name()}
|
||||||
|
<Emoji text=" 👋" />
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2">
|
||||||
|
Thank you for signing up! Let me give you the tour
|
||||||
|
<Emoji text=" 😊" />
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
target: "body",
|
||||||
|
placement: "center",
|
||||||
|
disableBeacon: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "User Menu",
|
||||||
|
content: (
|
||||||
|
<>
|
||||||
|
<Typography variant="body2" >
|
||||||
|
In the user menu, you can make changes to your profile, and adjust unit preferences.
|
||||||
|
</Typography>
|
||||||
|
<br/>
|
||||||
|
<Typography variant="body2" >
|
||||||
|
If you are part of a team, you can select it here as well.
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
target: "#tour-user-menu",
|
||||||
|
placement: "bottom",
|
||||||
|
disableBeacon: true,
|
||||||
|
// onNext: () => setDoneFirst(true)
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title:
|
||||||
|
// }
|
||||||
|
];
|
||||||
|
if (hasTeams) steps.push({
|
||||||
|
title: "Teams",
|
||||||
|
content: (
|
||||||
|
<>
|
||||||
|
<Typography variant="body2" >
|
||||||
|
Here, you can view your team(s), access their settings, and choose your favourite.
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
target: "#tour-teams",
|
||||||
|
placement: "right",
|
||||||
|
// spotlightPadding: 50,
|
||||||
|
})
|
||||||
|
steps.push({
|
||||||
|
title: "Devices",
|
||||||
|
content: (
|
||||||
|
<>
|
||||||
|
<Typography variant="body2" >
|
||||||
|
You can view your devices and their readings here.
|
||||||
|
</Typography>
|
||||||
|
<br/>
|
||||||
|
<Typography>
|
||||||
|
If you are viewing as a team, your team's devices will be displayed here instead.
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
target: "#tour-dashboard",
|
||||||
|
placement: "right"
|
||||||
|
})
|
||||||
|
if (IsAdaptiveAgriculture()) steps.push({
|
||||||
|
title: "Bins",
|
||||||
|
content: (
|
||||||
|
<>
|
||||||
|
<Typography variant="body2" >
|
||||||
|
You can view your bins and their inventory here.
|
||||||
|
</Typography>
|
||||||
|
<br/>
|
||||||
|
<Typography>
|
||||||
|
If you are viewing as a team, your team's bins will be displayed here instead.
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
target: "#tour-bins",
|
||||||
|
placement: "right",
|
||||||
|
disableBeacon: true,
|
||||||
|
})
|
||||||
|
return steps;
|
||||||
|
};
|
||||||
|
|
||||||
|
const endTour = () => {
|
||||||
|
setIsTourRunning(false);
|
||||||
|
// if (user) {
|
||||||
|
// user.status.finishedBinIntro = moment().toJSON();
|
||||||
|
// userAPI
|
||||||
|
// .updateUser(userID, user.protobuf())
|
||||||
|
// .then(() => dispatch({ key: "user", value: user }))
|
||||||
|
// .catch((err: any) => error(err));
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeDialog = () => {
|
||||||
|
setSignupDialogOpen(false)
|
||||||
|
setIsTourRunning(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log(stepIndex)
|
||||||
|
}, [stepIndex])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageContainer spacing={1}>
|
||||||
|
<Dialog open={signupDialogOpen} fullScreen={isMobile} >
|
||||||
|
<DialogTitle>
|
||||||
|
Finishing Signup
|
||||||
|
</DialogTitle>
|
||||||
|
<Divider sx={{ marginBottom: 2 }}/>
|
||||||
|
{ content() }
|
||||||
|
<DialogActions>
|
||||||
|
{loadingComplete() &&
|
||||||
|
<Button onClick={closeDialog}>
|
||||||
|
Done
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
<Tour
|
||||||
|
setStepIndex={setStepIndex}
|
||||||
|
spotlightStyle={{ marginTop: stepIndex!==1 ? 74 : 1 }}
|
||||||
|
run={isTourRunning} steps={getTourSteps()}
|
||||||
|
endTourCallback={endTour}
|
||||||
|
/>
|
||||||
|
</PageContainer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -214,7 +214,7 @@ export default function TeamPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContainer padding={isMobile ? 0 : 2}>
|
<PageContainer spacing={isMobile ? 0 : 2}>
|
||||||
<Box className={classes.container}>
|
<Box className={classes.container}>
|
||||||
<Box className={classes.leftBox}>
|
<Box className={classes.leftBox}>
|
||||||
{title()}
|
{title()}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import TeamList from "teams/TeamList";
|
||||||
export default function Teams() {
|
export default function Teams() {
|
||||||
const isMobile = useMobile()
|
const isMobile = useMobile()
|
||||||
return (
|
return (
|
||||||
<PageContainer padding={isMobile ? 0 : 2}>
|
<PageContainer spacing={isMobile ? 0 : 2}>
|
||||||
<TeamList />
|
<TeamList />
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -349,7 +349,7 @@ export default function Users() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContainer padding={isMobile ? 0 : 2}>
|
<PageContainer spacing={isMobile ? 0 : 2}>
|
||||||
<ResponsiveTable<User>
|
<ResponsiveTable<User>
|
||||||
title="Users"
|
title="Users"
|
||||||
rows={rows}
|
rows={rows}
|
||||||
|
|
|
||||||
|
|
@ -9,28 +9,37 @@ interface Props extends PropsWithChildren<any>{
|
||||||
|
|
||||||
export default function AuthWrapper(props: Props) {
|
export default function AuthWrapper(props: Props) {
|
||||||
const { children, setToken } = props;
|
const { children, setToken } = props;
|
||||||
const { isLoading, loginWithRedirect, isAuthenticated, getAccessTokenSilently } = useAuth0();
|
const {
|
||||||
|
isLoading,
|
||||||
|
loginWithRedirect,
|
||||||
|
isAuthenticated,
|
||||||
|
getAccessTokenSilently,
|
||||||
|
// getIdTokenClaims
|
||||||
|
} = useAuth0();
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const url = new URL(window.location.href);
|
const url = new URL(window.location.href);
|
||||||
|
|
||||||
const isManualLoginPage = url.pathname.includes("/login");
|
const isManualLoginPage = url.pathname.includes("/login");
|
||||||
|
const options: RedirectLoginOptions = {
|
||||||
|
authorizationParams: {} // Initialize here
|
||||||
|
};
|
||||||
|
|
||||||
if (isManualLoginPage) {
|
if (isManualLoginPage && options.authorizationParams) {
|
||||||
const options: RedirectLoginOptions = {
|
|
||||||
authorizationParams: {} // Initialize here
|
|
||||||
};
|
|
||||||
|
|
||||||
let parsed = queryString.parse(url.search);
|
let parsed = queryString.parse(url.search);
|
||||||
if (parsed.signup === "true") {
|
if (parsed.signup === "true") {
|
||||||
options.authorizationParams!.screen_hint = "signup";
|
options.authorizationParams.screen_hint = "signUp";
|
||||||
options.authorizationParams!.prompt = "login";
|
// options.authorizationParams.m
|
||||||
|
// options.authorizationParams.prompt = "login";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parsed.email && parsed.email !== "") {
|
if (parsed.email && parsed.email !== "") {
|
||||||
options.authorizationParams!.login_hint = parsed.email.toString(); // prefill email
|
options.authorizationParams.login_hint = parsed.email.toString(); // prefill email
|
||||||
}
|
}
|
||||||
|
|
||||||
|
options.authorizationParams.redirect_uri = "https://" + url.hostname + "/signupCallback"
|
||||||
|
console.log(options.authorizationParams.redirect_uri)
|
||||||
|
|
||||||
loginWithRedirect(options)
|
loginWithRedirect(options)
|
||||||
|
|
||||||
|
|
@ -40,15 +49,27 @@ export default function AuthWrapper(props: Props) {
|
||||||
}, [isAuthenticated, loginWithRedirect, isLoading]);
|
}, [isAuthenticated, loginWithRedirect, isLoading]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isAuthenticated) getAccessTokenSilently().then(t => {
|
// const url = new URL(window.location.href);
|
||||||
if (t.length < 1) {
|
// const isSignupCallback = url.pathname.includes("/signupCallback");
|
||||||
|
if (isAuthenticated) {
|
||||||
|
getAccessTokenSilently().then(t => {
|
||||||
|
if (t.length < 1) {
|
||||||
|
loginWithRedirect()
|
||||||
|
}
|
||||||
|
setToken(t)
|
||||||
|
}).catch(() => {
|
||||||
|
// No token, go back to login
|
||||||
loginWithRedirect()
|
loginWithRedirect()
|
||||||
}
|
})
|
||||||
setToken(t)
|
// if (isSignupCallback) {
|
||||||
}).catch(() => {
|
// getIdTokenClaims().then(id_claims => {
|
||||||
// No token, go back to login
|
// console.log(id_claims)
|
||||||
loginWithRedirect()
|
// console.log(id_claims?.nickname)
|
||||||
})
|
// if (id_claims) console.log(Object.keys(id_claims))
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
}, [setToken, isAuthenticated])
|
}, [setToken, isAuthenticated])
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ export interface IUserAPIContext {
|
||||||
prefixSearch?: string,
|
prefixSearch?: string,
|
||||||
) => Promise<ListUsersResponse>;
|
) => Promise<ListUsersResponse>;
|
||||||
listProfiles: () => Promise<pond.UserProfile[]>;
|
listProfiles: () => Promise<pond.UserProfile[]>;
|
||||||
|
completeSignup: () => Promise<pond.CompleteSignupUserResponse>;
|
||||||
listObjectUsers: (scope: Scope) => Promise<any>;
|
listObjectUsers: (scope: Scope) => Promise<any>;
|
||||||
updateObjectUsers: (scope: Scope, users: pond.IUser[]) => Promise<any>;
|
updateObjectUsers: (scope: Scope, users: pond.IUser[]) => Promise<any>;
|
||||||
getUser: (id: string, scope?: Scope) => Promise<User>;
|
getUser: (id: string, scope?: Scope) => Promise<User>;
|
||||||
|
|
@ -55,8 +56,21 @@ export const UserAPIContext = createContext<IUserAPIContext>({} as IUserAPIConte
|
||||||
|
|
||||||
export default function UserProvider(props: PropsWithChildren<any>) {
|
export default function UserProvider(props: PropsWithChildren<any>) {
|
||||||
const { children } = props;
|
const { children } = props;
|
||||||
const { get, put } = useHTTP();
|
const { get, put, post } = useHTTP();
|
||||||
const [{ as }] = useGlobalState();
|
const [{ as, user }] = useGlobalState();
|
||||||
|
|
||||||
|
const completeSignup = (): Promise<pond.CompleteSignupUserResponse> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let request = pond.CompleteSignupUserRequest.create();
|
||||||
|
request.avatar = user.settings.avatar
|
||||||
|
request.email = user.settings.email
|
||||||
|
request.id = user.id()
|
||||||
|
request.name = user.name()
|
||||||
|
post(pondURL("/signups"), request).then(res => {
|
||||||
|
resolve(pond.CompleteSignupUserResponse.create())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const listUsers = (
|
const listUsers = (
|
||||||
limit: number,
|
limit: number,
|
||||||
|
|
@ -234,6 +248,7 @@ export default function UserProvider(props: PropsWithChildren<any>) {
|
||||||
return (
|
return (
|
||||||
<UserAPIContext.Provider
|
<UserAPIContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
completeSignup,
|
||||||
listUsers,
|
listUsers,
|
||||||
listProfiles,
|
listProfiles,
|
||||||
listObjectUsers,
|
listObjectUsers,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
import {
|
import {
|
||||||
AppBar,
|
AppBar,
|
||||||
Button,
|
Button,
|
||||||
|
Checkbox,
|
||||||
|
FormControlLabel,
|
||||||
|
FormGroup,
|
||||||
IconButton,
|
IconButton,
|
||||||
Theme,
|
Theme,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
|
|
@ -18,6 +21,9 @@ import { makeStyles } from "@mui/styles";
|
||||||
interface Props {
|
interface Props {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
setOpen: (value: React.SetStateAction<boolean>) => void;
|
setOpen: (value: React.SetStateAction<boolean>) => void;
|
||||||
|
title?: string;
|
||||||
|
info?: string;
|
||||||
|
hideKey?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) => {
|
const useStyles = makeStyles((theme: Theme) => {
|
||||||
|
|
@ -37,16 +43,22 @@ const useStyles = makeStyles((theme: Theme) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function TeamDialog(props: Props) {
|
export default function TeamDialog(props: Props) {
|
||||||
const { open, setOpen } = props;
|
const { open, setOpen, title, info, hideKey } = props;
|
||||||
const teamAPI = useTeamAPI();
|
const teamAPI = useTeamAPI();
|
||||||
const userAPI = useUserAPI();
|
const userAPI = useUserAPI();
|
||||||
const [, dispatch] = useGlobalState();
|
const [, dispatch] = useGlobalState();
|
||||||
const [teamKey, setTeamKey] = useState<string>("");
|
const [teamKey, setTeamKey] = useState<string>("");
|
||||||
const [{ team, user }] = useGlobalState();
|
const [{ team, user }] = useGlobalState();
|
||||||
|
const [viewAsTeam, setViewAsTeam] = useState(user.settings.useTeam)
|
||||||
|
const [doNotShow, setDoNotShow] = useState(false)
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
|
const shouldHide = hideKey ?
|
||||||
|
(localStorage.getItem(hideKey) === "true" ? true : false)
|
||||||
|
: false
|
||||||
|
|
||||||
const setTeam = () => {
|
const setTeam = () => {
|
||||||
setOpen(false);
|
onClose()
|
||||||
dispatch({ key: "as", value: teamKey });
|
dispatch({ key: "as", value: teamKey });
|
||||||
if (teamKey === "" || teamKey.includes("auth")) {
|
if (teamKey === "" || teamKey.includes("auth")) {
|
||||||
dispatch({ key: "team", value: Team.create() });
|
dispatch({ key: "team", value: Team.create() });
|
||||||
|
|
@ -55,13 +67,19 @@ export default function TeamDialog(props: Props) {
|
||||||
teamAPI.getTeam(teamKey).then(team => {
|
teamAPI.getTeam(teamKey).then(team => {
|
||||||
dispatch({ key: "team", value: team });
|
dispatch({ key: "team", value: team });
|
||||||
user.settings.defaultTeam = team.key();
|
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());
|
userAPI.updateUser(user.id(), user.protobuf());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onClose = () => {
|
||||||
|
console.log("close")
|
||||||
|
setOpen(false)
|
||||||
|
if (hideKey) localStorage.setItem(hideKey, ""+doNotShow)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ResponsiveDialog open={open} onClose={() => setOpen(false)}>
|
<ResponsiveDialog open={open && !shouldHide} onClose={onClose}>
|
||||||
<AppBar position="relative">
|
<AppBar position="relative">
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
|
@ -72,9 +90,9 @@ export default function TeamDialog(props: Props) {
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<Typography variant="h6" className={classes.title}>
|
<Typography variant="h6" className={classes.title}>
|
||||||
Select a Team to View As
|
{ title ? title : "Select a Team to View As"}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Button color="inherit" onClick={setTeam}>
|
<Button color="inherit" onClick={setTeam} >
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
|
|
@ -84,12 +102,40 @@ export default function TeamDialog(props: Props) {
|
||||||
Viewing as: {team.name()}
|
Viewing as: {team.name()}
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
|
{info &&
|
||||||
|
<Typography variant="body1" className={classes.viewingAs}>
|
||||||
|
{info}
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
<TeamSearch
|
<TeamSearch
|
||||||
//style={{ width: theme.spacing(32) }}
|
//style={{ width: theme.spacing(32) }}
|
||||||
className={classes.searchBar}
|
className={classes.searchBar}
|
||||||
loadUsers={user.hasFeature("admin")}
|
loadUsers={user.hasFeature("admin")}
|
||||||
setTeamCallback={setTeamKey}
|
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>
|
</ResponsiveDialog>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,7 @@ export default function UserMenu() {
|
||||||
<ListItemText primary="Toggle Theme" />
|
<ListItemText primary="Toggle Theme" />
|
||||||
</MenuItem> */}
|
</MenuItem> */}
|
||||||
{hasTeams && (
|
{hasTeams && (
|
||||||
<MenuItem onClick={openTeamDialog} aria-label="Open Team Menu" dense>
|
<MenuItem id="tour-teams" onClick={openTeamDialog} aria-label="Open Team Menu" dense>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<TeamIcon />
|
<TeamIcon />
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue