295 lines
No EOL
8.9 KiB
TypeScript
295 lines
No EOL
8.9 KiB
TypeScript
import { Avatar, Box, Button, Checkbox, Divider, ListItemIcon, ListItemText, Menu, MenuItem, PaletteColor, Theme, Tooltip, useTheme } from "@mui/material";
|
|
import { useGlobalState } from "../providers/StateContainer";
|
|
import { getSecondaryColour, getSignatureAccentColour } from "../services/whiteLabel";
|
|
import { makeStyles } from "@mui/styles";
|
|
import { LockOpen, Person, Lock, Settings, SupervisedUserCircle as TeamIcon, ExitToApp, PersonAdd } from "@mui/icons-material";
|
|
import { useState } from "react";
|
|
import UserTeamName from "./UserTeamName";
|
|
import { useAuth0 } from "@auth0/auth0-react";
|
|
import UserSettings from "./UserSettings";
|
|
import UserAvatar from "./UserAvatar";
|
|
import { purple } from "@mui/material/colors";
|
|
import { useNavigate } from "react-router-dom";
|
|
import TeamDialog from "teams/TeamDialog";
|
|
import AccessObject from "./AccessObject";
|
|
import { useSnackbar, useUserAPI } from "hooks";
|
|
// import { useThemeMode } from "theme/AppThemeProvider";
|
|
|
|
const useStyles = makeStyles((theme: Theme) => ({
|
|
accessIcon: {
|
|
color: "var(--status-ok)"
|
|
},
|
|
userAvatar: {
|
|
color: "#fff",
|
|
backgroundColor: getSecondaryColour()["700" as keyof PaletteColor],
|
|
[theme.breakpoints.down("xs")]: {
|
|
width: "32px",
|
|
height: "32px"
|
|
}
|
|
},
|
|
userAvatar2: {
|
|
color: "#fff",
|
|
backgroundColor: theme.palette.secondary["700" as keyof PaletteColor],
|
|
[theme.breakpoints.down("xs")]: {
|
|
width: "30px",
|
|
height: "30px"
|
|
},
|
|
position: "relative",
|
|
top: -6,
|
|
left: 0
|
|
},
|
|
teamAvatar: {
|
|
color: "#fff",
|
|
backgroundColor: theme.palette.secondary["700" as keyof PaletteColor],
|
|
[theme.breakpoints.down("xs")]: {
|
|
width: "30px",
|
|
height: "30px"
|
|
},
|
|
position: "absolute",
|
|
top: -34,
|
|
left: 8
|
|
},
|
|
profileButton: {
|
|
maxWidth: "50vw"
|
|
},
|
|
profileName: {
|
|
whiteSpace: "nowrap",
|
|
overflow: "hidden",
|
|
textOverflow: "ellipsis",
|
|
textTransform: "capitalize",
|
|
color: getSignatureAccentColour(),
|
|
marginBottom: -3,
|
|
marginTop: -3
|
|
},
|
|
red: {
|
|
color: "var(--status-alert)"
|
|
},
|
|
rightIcon: {
|
|
marginLeft: theme.spacing(1)
|
|
},
|
|
signIn: {
|
|
color: getSignatureAccentColour(),
|
|
borderColor: getSignatureAccentColour()
|
|
},
|
|
}));
|
|
|
|
export default function UserMenu() {
|
|
|
|
// const { toggleMode } = useThemeMode()
|
|
const [{ user, team, as }, dispatch] = useGlobalState();
|
|
const { loginWithRedirect } = useAuth0();
|
|
const classes = useStyles();
|
|
const theme = useTheme();
|
|
|
|
const userAPI = useUserAPI()
|
|
const snackbar = useSnackbar()
|
|
|
|
const name = user.name();
|
|
const picture = user.settings.avatar;
|
|
const [lockIsHovered, setLockIsHovered] = useState<boolean>(false);
|
|
const [userMenuIsOpen, setUserMenuIsOpen] = useState(false);
|
|
const [anchorEl, setAnchorEl] = useState<any>(null);
|
|
const [userSettingsIsOpen, setUserSettingsIsOpen] = useState<boolean>(false);
|
|
const hasTeams = user.hasFeature ? user.hasFeature("teams") : false;
|
|
const [teamDialogIsOpen, setTeamDialogIsOpen] = useState<boolean>(false);
|
|
const [accessDialogOpen, setAccessDialogOpen] = useState<boolean>(false);
|
|
|
|
const navigate = useNavigate()
|
|
|
|
const openTeamDialog = () => {
|
|
setTeamDialogIsOpen(true);
|
|
closeUserMenu();
|
|
};
|
|
|
|
const lockHover = () => {
|
|
setLockIsHovered(true);
|
|
};
|
|
|
|
const lockNoHover = () => {
|
|
setLockIsHovered(false);
|
|
};
|
|
|
|
const handleLogin = () => {
|
|
loginWithRedirect()
|
|
}
|
|
|
|
const openUserMenu = (event: any) => {
|
|
setAnchorEl(event.currentTarget);
|
|
setUserMenuIsOpen(true);
|
|
};
|
|
|
|
const closeUserMenu = () => {
|
|
setUserMenuIsOpen(false);
|
|
setAnchorEl(null);
|
|
};
|
|
|
|
const openUserSettingsDialog = () => {
|
|
setUserMenuIsOpen(false);
|
|
setAnchorEl(null);
|
|
setUserSettingsIsOpen(true)
|
|
}
|
|
|
|
const closeUserSettingsDialog = () => {
|
|
setUserSettingsIsOpen(false)
|
|
}
|
|
|
|
const openAccessObject = () => {
|
|
setAccessDialogOpen(true);
|
|
closeUserMenu();
|
|
};
|
|
|
|
const handleLogout = () => {
|
|
closeUserMenu();
|
|
navigate("/logout");
|
|
};
|
|
|
|
const unauthenticatedUserMenu = () => {
|
|
return (
|
|
<>
|
|
<Button
|
|
variant="outlined"
|
|
aria-label="Sign In"
|
|
onClick={handleLogin}
|
|
onMouseEnter={lockHover}
|
|
onMouseLeave={lockNoHover}
|
|
size="small"
|
|
className={classes.signIn}
|
|
>
|
|
Sign In
|
|
{lockIsHovered ? (
|
|
<LockOpen className={classes.rightIcon} fontSize="small" />
|
|
) : (
|
|
<Lock className={classes.rightIcon} fontSize="small" />
|
|
)}
|
|
</Button>
|
|
</>
|
|
);
|
|
};
|
|
|
|
if (user.id().length < 1) return unauthenticatedUserMenu()
|
|
|
|
const hasAdmin = user.hasFeature ? user.hasFeature("admin") : false;
|
|
|
|
return (
|
|
<>
|
|
<Button
|
|
id="tour-user-menu"
|
|
aria-owns={userMenuIsOpen ? "userMenu" : undefined}
|
|
aria-haspopup="true"
|
|
onClick={openUserMenu}
|
|
className={classes.profileButton}>
|
|
<Box style={{ display: "flex", flexDirection: "column" }}>
|
|
<UserTeamName user={user} team={team} />
|
|
</Box>
|
|
<Box style={{ marginLeft: theme.spacing(1) }}>
|
|
{picture && hasTeams && team.id().length > 0 ? (
|
|
<div>
|
|
<UserAvatar
|
|
user={user}
|
|
className={classes.userAvatar2}
|
|
style={{ zIndex: as === "" ? 1000 : 0 }}
|
|
/>
|
|
<div style={{ position: "relative" }}>
|
|
<Avatar
|
|
src={team.settings.avatar}
|
|
className={classes.teamAvatar}
|
|
style={{ background: purple[500] }}>
|
|
<TeamIcon style={{ fontSize: 38 }} />
|
|
</Avatar>
|
|
</div>
|
|
</div>
|
|
) : picture ? (
|
|
<Avatar alt={name} src={picture} className={classes.userAvatar}>
|
|
{!picture && name}
|
|
</Avatar>
|
|
) : (
|
|
<Avatar alt={name} src={picture} className={classes.userAvatar}>
|
|
<Person />
|
|
</Avatar>
|
|
)}
|
|
</Box>
|
|
</Button>
|
|
<Menu
|
|
id="userMenu"
|
|
anchorEl={anchorEl}
|
|
open={userMenuIsOpen}
|
|
onClose={closeUserMenu}
|
|
disableAutoFocusItem>
|
|
<MenuItem onClick={openUserSettingsDialog} aria-label="Open User Settings" dense>
|
|
<ListItemIcon>
|
|
<Settings />
|
|
</ListItemIcon>
|
|
<ListItemText primary="User Settings" />
|
|
</MenuItem>
|
|
{/* <MenuItem onClick={toggleMode} aria-label="Toggle Theme" dense>
|
|
<ListItemIcon>
|
|
<ThemeIcon />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Toggle Theme" />
|
|
</MenuItem> */}
|
|
{hasTeams && (
|
|
<MenuItem id="tour-teams" onClick={openTeamDialog} aria-label="Open Team Menu" dense>
|
|
<ListItemIcon>
|
|
<TeamIcon />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Select Team" />
|
|
</MenuItem>
|
|
)}
|
|
{hasTeams && (
|
|
<MenuItem
|
|
onClick={() => {
|
|
if (as.length > 1) {
|
|
user.settings.useTeam = false;
|
|
dispatch({ key: "as", value: "" });
|
|
userAPI.updateUser(user.id(), user.protobuf()).then(_resp => {
|
|
snackbar.info("Will no longer view as team by default");
|
|
});
|
|
} else {
|
|
user.settings.useTeam = true;
|
|
dispatch({ key: "as", value: team.key() });
|
|
userAPI.updateUser(user.id(), user.protobuf()).then(_resp => {
|
|
snackbar.info("Will now view as " + team.name() + " by default");
|
|
});
|
|
}
|
|
}}
|
|
disabled={user.settings.defaultTeam.length < 1}
|
|
aria-label="Open Team Menu"
|
|
dense>
|
|
<ListItemIcon>
|
|
<Checkbox
|
|
disabled={user.settings.defaultTeam.length < 1}
|
|
checked={as.length > 1}
|
|
style={{ margin: 0, padding: 0 }}
|
|
/>
|
|
</ListItemIcon>
|
|
<ListItemText primary="View Site as Team" />
|
|
</MenuItem>
|
|
)}
|
|
<Divider />
|
|
{hasAdmin && (
|
|
<Tooltip title="Access Object">
|
|
<MenuItem onClick={() => openAccessObject()} aria-label="Access Object" dense>
|
|
<ListItemIcon>
|
|
<PersonAdd className={classes.accessIcon} />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Access Object" />
|
|
</MenuItem>
|
|
</Tooltip>
|
|
)}
|
|
<Divider />
|
|
<MenuItem onClick={handleLogout} aria-label="Sign Out" dense>
|
|
<ListItemIcon>
|
|
<ExitToApp className={classes.red} />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Sign Out" />
|
|
</MenuItem>
|
|
</Menu>
|
|
<TeamDialog open={teamDialogIsOpen} setOpen={setTeamDialogIsOpen} />
|
|
<UserSettings isOpen={userSettingsIsOpen} closeDialogCallback={closeUserSettingsDialog} />
|
|
<AccessObject
|
|
isOpen={accessDialogOpen}
|
|
closeDialogCallback={() => setAccessDialogOpen(false)}
|
|
/>
|
|
</>
|
|
)
|
|
} |