340 lines
9.6 KiB
TypeScript
340 lines
9.6 KiB
TypeScript
import {
|
|
IconButton,
|
|
ListItemIcon,
|
|
ListItemText,
|
|
Menu,
|
|
MenuItem,
|
|
Theme,
|
|
Tooltip
|
|
} from "@mui/material";
|
|
import { blue } from "@mui/material/colors";
|
|
import RemoveSelfIcon from "@mui/icons-material/ExitToApp";
|
|
import MoreIcon from "@mui/icons-material/MoreVert";
|
|
import GroupSettingsIcon from "@mui/icons-material/Settings";
|
|
import ShareObjectIcon from "@mui/icons-material/Share";
|
|
import SensorIcon from "@mui/icons-material/SettingsInputAntenna";
|
|
import ObjectUsersIcon from "@mui/icons-material/AccountCircle";
|
|
import ObjectTeamsIcon from "@mui/icons-material/SupervisedUserCircle";
|
|
import BinSettings from "bin/BinSettings";
|
|
import { Bin, binScope, Component, User } from "models";
|
|
import { pond } from "protobuf-ts/pond";
|
|
import React, { useState } from "react";
|
|
import ObjectUsers from "user/ObjectUsers";
|
|
import RemoveSelfFromObject from "user/RemoveSelfFromObject";
|
|
import ShareObject from "user/ShareObject";
|
|
import { isOffline } from "utils/environment";
|
|
import ObjectTeams from "teams/ObjectTeams";
|
|
import BinDuplication from "./BinDuplication";
|
|
import BinsIcon from "products/Bindapt/BinsIcon";
|
|
import HelpIcon from "@mui/icons-material/Help";
|
|
import BinSensors from "./BinSensors";
|
|
import { useGlobalState, useSnackbar, useUserAPI } from "providers";
|
|
import { useMobile } from "hooks";
|
|
import { makeStyles } from "@mui/styles";
|
|
|
|
const useStyles = makeStyles((theme: Theme) => {
|
|
return ({
|
|
shareIcon: {
|
|
color: blue["500"],
|
|
"&:hover": {
|
|
color: blue["600"]
|
|
}
|
|
},
|
|
removeIcon: {
|
|
color: "var(--status-alert)"
|
|
},
|
|
red: {
|
|
color: "var(--status-alert)"
|
|
}
|
|
});
|
|
});
|
|
|
|
interface Props {
|
|
bin: Bin;
|
|
permissions: pond.Permission[];
|
|
refreshCallback: () => void;
|
|
userID: string;
|
|
components?: Map<string, Component>;
|
|
setComponents?: React.Dispatch<React.SetStateAction<Map<string, Component>>>;
|
|
updateBinStatus?: (componentKeys: string[], removed?: boolean) => void;
|
|
componentDevices?: Map<string, number>
|
|
setComponentDevices?: React.Dispatch<React.SetStateAction<Map<string, number>>>;
|
|
}
|
|
|
|
interface OpenState {
|
|
share: boolean;
|
|
users: boolean;
|
|
teams: boolean;
|
|
settings: boolean;
|
|
sensors: boolean;
|
|
removeSelf: boolean;
|
|
duplication: boolean;
|
|
}
|
|
|
|
export default function BinActions(props: Props) {
|
|
const classes = useStyles();
|
|
const {
|
|
bin,
|
|
permissions,
|
|
refreshCallback,
|
|
userID,
|
|
components,
|
|
componentDevices,
|
|
setComponents,
|
|
setComponentDevices,
|
|
updateBinStatus
|
|
} = props;
|
|
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
|
const [{ user }, dispatch] = useGlobalState();
|
|
const isMobile = useMobile();
|
|
const { error } = useSnackbar();
|
|
const userAPI = useUserAPI();
|
|
const [openState, setOpenState] = useState<OpenState>({
|
|
share: false,
|
|
users: false,
|
|
teams: false,
|
|
settings: false,
|
|
sensors: false,
|
|
removeSelf: false,
|
|
duplication: false
|
|
});
|
|
|
|
const startTour = () => {
|
|
if (user) {
|
|
let u = user.protobuf();
|
|
if (u.status) {
|
|
u.status.finishedBinIntro = "";
|
|
userAPI
|
|
.updateUser(userID, u)
|
|
.then(() => {
|
|
dispatch({ key: "user", value: User.any(u) });
|
|
})
|
|
.catch((err: any) => error(err));
|
|
}
|
|
}
|
|
};
|
|
|
|
const groupMenu = () => {
|
|
const canShare = permissions.includes(pond.Permission.PERMISSION_SHARE);
|
|
const canManageUsers = permissions.includes(pond.Permission.PERMISSION_USERS);
|
|
return (
|
|
<Menu
|
|
id="groupMenu"
|
|
anchorEl={anchorEl}
|
|
open={Boolean(anchorEl)}
|
|
onClose={() => setAnchorEl(null)}
|
|
keepMounted
|
|
disableAutoFocusItem>
|
|
{!isOffline() && canShare && (
|
|
<MenuItem
|
|
dense
|
|
onClick={() => {
|
|
setOpenState({ ...openState, share: true });
|
|
setAnchorEl(null);
|
|
}}
|
|
>
|
|
<ListItemIcon>
|
|
<ShareObjectIcon className={classes.shareIcon} />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Share" />
|
|
</MenuItem>
|
|
)}
|
|
{!isOffline() && canManageUsers && (
|
|
<MenuItem
|
|
dense
|
|
onClick={() => {
|
|
setOpenState({ ...openState, users: true });
|
|
setAnchorEl(null);
|
|
}}
|
|
>
|
|
<ListItemIcon>
|
|
<ObjectUsersIcon />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Users" />
|
|
</MenuItem>
|
|
)}
|
|
{!isOffline() && canManageUsers && (
|
|
<MenuItem
|
|
dense
|
|
onClick={() => {
|
|
setOpenState({ ...openState, teams: true });
|
|
setAnchorEl(null);
|
|
}}
|
|
>
|
|
<ListItemIcon>
|
|
<ObjectTeamsIcon />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Teams" />
|
|
</MenuItem>
|
|
)}
|
|
<MenuItem
|
|
dense
|
|
onClick={() => {
|
|
setOpenState({ ...openState, duplication: true });
|
|
setAnchorEl(null);
|
|
}}
|
|
>
|
|
<ListItemIcon>
|
|
<BinsIcon />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Duplicate Bin" />
|
|
</MenuItem>
|
|
{isMobile && (
|
|
<MenuItem
|
|
dense
|
|
onClick={() => {
|
|
setAnchorEl(null);
|
|
startTour();
|
|
}}
|
|
>
|
|
<ListItemIcon>
|
|
<HelpIcon />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Redo Help Tour" />
|
|
</MenuItem>
|
|
)}
|
|
{isMobile && (
|
|
<MenuItem
|
|
dense
|
|
onClick={() => {
|
|
setAnchorEl(null);
|
|
setOpenState({ ...openState, sensors: true });
|
|
}}
|
|
>
|
|
<ListItemIcon>
|
|
<SensorIcon />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Bin Sensors" />
|
|
</MenuItem>
|
|
)}
|
|
<MenuItem
|
|
dense
|
|
onClick={() => {
|
|
setOpenState({ ...openState, removeSelf: true });
|
|
setAnchorEl(null);
|
|
}}
|
|
>
|
|
<ListItemIcon>
|
|
<RemoveSelfIcon className={classes.red} />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Leave" />
|
|
</MenuItem>
|
|
</Menu>
|
|
);
|
|
};
|
|
|
|
const dialogs = () => {
|
|
const hasWritePermission = permissions.includes(pond.Permission.PERMISSION_WRITE);
|
|
const key = bin.key();
|
|
const label = bin.name();
|
|
return (
|
|
<React.Fragment>
|
|
<BinSettings
|
|
mode="update"
|
|
bin={bin}
|
|
canEdit={hasWritePermission}
|
|
open={openState.settings}
|
|
userID={userID}
|
|
onClose={refresh => {
|
|
if (refresh === true) {
|
|
refreshCallback();
|
|
}
|
|
setOpenState({ ...openState, settings: false });
|
|
}}
|
|
/>
|
|
<BinSensors
|
|
mode="update"
|
|
bin={bin}
|
|
canEdit={hasWritePermission}
|
|
open={openState.sensors}
|
|
userID={userID}
|
|
components={components}
|
|
componentDevices={componentDevices}
|
|
setComponents={setComponents}
|
|
setComponentDevices={setComponentDevices}
|
|
updateBinStatus={updateBinStatus}
|
|
onClose={refresh => {
|
|
if (refresh === true) {
|
|
refreshCallback();
|
|
}
|
|
setOpenState({ ...openState, sensors: false });
|
|
}}
|
|
/>
|
|
<ShareObject
|
|
scope={binScope(key)}
|
|
label={label}
|
|
permissions={permissions}
|
|
isDialogOpen={openState.share}
|
|
closeDialogCallback={() => setOpenState({ ...openState, share: false })}
|
|
/>
|
|
<ObjectUsers
|
|
scope={binScope(key)}
|
|
label={label}
|
|
permissions={permissions}
|
|
isDialogOpen={openState.users}
|
|
closeDialogCallback={() => setOpenState({ ...openState, users: false })}
|
|
refreshCallback={refreshCallback}
|
|
/>
|
|
<BinDuplication
|
|
open={openState.duplication}
|
|
closeDialog={() => {
|
|
setOpenState({ ...openState, duplication: false });
|
|
}}
|
|
bin={bin}
|
|
refreshCallback={refreshCallback}
|
|
/>
|
|
<RemoveSelfFromObject
|
|
scope={binScope(key)}
|
|
label={label}
|
|
isDialogOpen={openState.removeSelf}
|
|
closeDialogCallback={() => setOpenState({ ...openState, removeSelf: false })}
|
|
/>
|
|
</React.Fragment>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<React.Fragment>
|
|
{!isMobile && (
|
|
<Tooltip title="Redo help tour">
|
|
<IconButton onClick={startTour}>
|
|
<HelpIcon />
|
|
</IconButton>
|
|
</Tooltip>
|
|
)}
|
|
{!isMobile && (
|
|
<Tooltip title="Bin Sensors">
|
|
<IconButton
|
|
id="tour-bin-sensors"
|
|
onClick={() => setOpenState({ ...openState, sensors: true })}>
|
|
<SensorIcon />
|
|
</IconButton>
|
|
</Tooltip>
|
|
)}
|
|
<Tooltip title="Bin Settings">
|
|
<IconButton
|
|
id="tour-bin-settings"
|
|
onClick={() => setOpenState({ ...openState, settings: true })}>
|
|
<GroupSettingsIcon />
|
|
</IconButton>
|
|
</Tooltip>
|
|
<IconButton
|
|
aria-owns={anchorEl ? "groupMenu" : undefined}
|
|
aria-haspopup="true"
|
|
id="tour-bin-kebab"
|
|
onClick={(event: React.MouseEvent<HTMLButtonElement>) => setAnchorEl(event.currentTarget)}>
|
|
<MoreIcon />
|
|
</IconButton>
|
|
{groupMenu()}
|
|
{dialogs()}
|
|
<ObjectTeams
|
|
scope={binScope(bin.key())}
|
|
label="Teams"
|
|
permissions={permissions}
|
|
isDialogOpen={openState.teams}
|
|
refreshCallback={refreshCallback}
|
|
closeDialogCallback={() => setOpenState({ ...openState, teams: false })}
|
|
/>
|
|
</React.Fragment>
|
|
);
|
|
}
|