diff options
Diffstat (limited to 'webui/src/components/Identity')
4 files changed, 142 insertions, 0 deletions
diff --git a/webui/src/components/Identity/CurrentIdentity.graphql b/webui/src/components/Identity/CurrentIdentity.graphql new file mode 100644 index 00000000..054190df --- /dev/null +++ b/webui/src/components/Identity/CurrentIdentity.graphql @@ -0,0 +1,9 @@ +#import "./IdentityFragment.graphql" + +query CurrentIdentity { + repository { + userIdentity { + ...Identity + } + } +} diff --git a/webui/src/components/Identity/CurrentIdentity.tsx b/webui/src/components/Identity/CurrentIdentity.tsx new file mode 100644 index 00000000..1fd424c1 --- /dev/null +++ b/webui/src/components/Identity/CurrentIdentity.tsx @@ -0,0 +1,114 @@ +import React from 'react'; +import { Link as RouterLink } from 'react-router-dom'; + +import { + Button, + ClickAwayListener, + Grow, + Link, + MenuItem, + MenuList, + Paper, + Popper, +} from '@material-ui/core'; +import Avatar from '@material-ui/core/Avatar'; +import { makeStyles } from '@material-ui/core/styles'; +import LockIcon from '@material-ui/icons/Lock'; + +import { useCurrentIdentityQuery } from './CurrentIdentity.generated'; + +const useStyles = makeStyles((theme) => ({ + displayName: { + marginLeft: theme.spacing(2), + }, + hidden: { + display: 'none', + }, + profileLink: { + ...theme.typography.button, + }, + popupButton: { + textTransform: 'none', + color: theme.palette.primary.contrastText, + }, +})); + +const CurrentIdentity = () => { + const classes = useStyles(); + const { loading, error, data } = useCurrentIdentityQuery(); + + const [open, setOpen] = React.useState(false); + const anchorRef = React.useRef<HTMLButtonElement>(null); + + if (error || loading || !data?.repository?.userIdentity) return null; + + const user = data.repository.userIdentity; + + const handleToggle = () => { + setOpen((prevOpen) => !prevOpen); + }; + + const handleClose = (event: any) => { + if (anchorRef.current && anchorRef.current.contains(event.target)) { + return; + } + setOpen(false); + }; + + return ( + <> + <Button + ref={anchorRef} + aria-controls={open ? 'menu-list-grow' : undefined} + aria-haspopup="true" + onClick={handleToggle} + className={classes.popupButton} + > + <Avatar src={user.avatarUrl ? user.avatarUrl : undefined}> + {user.displayName.charAt(0).toUpperCase()} + </Avatar> + <div className={classes.displayName}>{user.displayName}</div> + <LockIcon + color="secondary" + className={user.isProtected ? '' : classes.hidden} + /> + </Button> + <Popper + open={open} + anchorEl={anchorRef.current} + role={undefined} + transition + disablePortal + > + {({ TransitionProps, placement }) => ( + <Grow + {...TransitionProps} + style={{ + transformOrigin: + placement === 'bottom' ? 'center top' : 'center bottom', + }} + > + <Paper> + <ClickAwayListener onClickAway={handleClose}> + <MenuList autoFocusItem={open} id="menu-list-grow"> + <MenuItem> + <Link + color="inherit" + className={classes.profileLink} + component={RouterLink} + to={`/user/${user.humanId}`} + > + Open profile + </Link> + </MenuItem> + </MenuList> + </ClickAwayListener> + </Paper> + </Grow> + )} + </Popper> + </> + ); +}; + +export default CurrentIdentity; diff --git a/webui/src/components/Identity/IdentityFragment.graphql b/webui/src/components/Identity/IdentityFragment.graphql new file mode 100644 index 00000000..6c4e2483 --- /dev/null +++ b/webui/src/components/Identity/IdentityFragment.graphql @@ -0,0 +1,10 @@ +fragment Identity on Identity { + id + humanId + displayName + email + name + avatarUrl + isProtected + login +} diff --git a/webui/src/components/Identity/UserIdentity.graphql b/webui/src/components/Identity/UserIdentity.graphql new file mode 100644 index 00000000..9cf10248 --- /dev/null +++ b/webui/src/components/Identity/UserIdentity.graphql @@ -0,0 +1,9 @@ +#import "./IdentityFragment.graphql" + +query GetUserById($userId: String!) { + repository { + identity(prefix: $userId) { + ...Identity + } + } +} |