diff options
author | Michael Muré <batolettre@gmail.com> | 2021-04-23 00:16:57 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-23 00:16:57 +0200 |
commit | a8f3b55986982db5f7c3918acaba2c214c919d11 (patch) | |
tree | 19706066a71c32684979b019aa62525481ff4891 /webui/src/components | |
parent | 271ca35d19a9649f6d0512760aed70c8778822fc (diff) | |
parent | 774bae6d432c13cfa0de3ddc2f111927743243fe (diff) | |
download | git-bug-a8f3b55986982db5f7c3918acaba2c214c919d11.tar.gz |
Merge pull request #605 from GlancingMind/upstream-12-allow-users-to-inspect-their-current-identity-details
WebUI: Add user profile
Diffstat (limited to 'webui/src/components')
-rw-r--r-- | webui/src/components/Author.tsx | 12 | ||||
-rw-r--r-- | webui/src/components/BugTitleForm/BugTitleForm.tsx | 8 | ||||
-rw-r--r-- | webui/src/components/CurrentIdentity/CurrentIdentity.tsx | 31 | ||||
-rw-r--r-- | webui/src/components/Header/Header.tsx | 2 | ||||
-rw-r--r-- | webui/src/components/Identity/CurrentIdentity.graphql (renamed from webui/src/components/CurrentIdentity/CurrentIdentity.graphql) | 5 | ||||
-rw-r--r-- | webui/src/components/Identity/CurrentIdentity.tsx | 114 | ||||
-rw-r--r-- | webui/src/components/Identity/IdentityFragment.graphql | 10 | ||||
-rw-r--r-- | webui/src/components/Identity/UserIdentity.graphql | 9 | ||||
-rw-r--r-- | webui/src/components/IfLoggedIn/IfLoggedIn.tsx | 2 |
9 files changed, 150 insertions, 43 deletions
diff --git a/webui/src/components/Author.tsx b/webui/src/components/Author.tsx index d60e8969..593b5d36 100644 --- a/webui/src/components/Author.tsx +++ b/webui/src/components/Author.tsx @@ -1,6 +1,8 @@ import React from 'react'; +import { Link as RouterLink } from 'react-router-dom'; import MAvatar from '@material-ui/core/Avatar'; +import Link from '@material-ui/core/Link'; import Tooltip from '@material-ui/core/Tooltip/Tooltip'; import { AuthoredFragment } from '../graphql/fragments.generated'; @@ -11,13 +13,11 @@ type Props = AuthoredFragment & { }; const Author = ({ author, ...props }: Props) => { - if (!author.email) { - return <span {...props}>{author.displayName}</span>; - } - return ( - <Tooltip title={author.email}> - <span {...props}>{author.displayName}</span> + <Tooltip title={`Goto the ${author.displayName}'s profile.`}> + <Link {...props} component={RouterLink} to={`/user/${author.id}`}> + {author.displayName} + </Link> </Tooltip> ); }; diff --git a/webui/src/components/BugTitleForm/BugTitleForm.tsx b/webui/src/components/BugTitleForm/BugTitleForm.tsx index 665ecd4c..2a3c4db0 100644 --- a/webui/src/components/BugTitleForm/BugTitleForm.tsx +++ b/webui/src/components/BugTitleForm/BugTitleForm.tsx @@ -52,6 +52,10 @@ const useStyles = makeStyles((theme) => ({ saveButton: { marginRight: theme.spacing(1), }, + author: { + fontWeight: 'bold', + color: theme.palette.text.secondary, + }, })); interface Props { @@ -86,7 +90,7 @@ function BugTitleForm({ bug }: Props) { setTitle({ variables: { input: { - prefix: bug.humanId, + prefix: bug.id, title: issueTitleInput.value, }, }, @@ -182,7 +186,7 @@ function BugTitleForm({ bug }: Props) { {bugTitleEdition ? editableBugTitle() : readonlyBugTitle()} <div className="classes.headerSubtitle"> <Typography color={'textSecondary'}> - <Author author={bug.author} /> + <Author author={bug.author} className={classes.author} /> {' opened this bug '} <Date date={bug.createdAt} /> </Typography> diff --git a/webui/src/components/CurrentIdentity/CurrentIdentity.tsx b/webui/src/components/CurrentIdentity/CurrentIdentity.tsx deleted file mode 100644 index 8cd3585b..00000000 --- a/webui/src/components/CurrentIdentity/CurrentIdentity.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react'; - -import Avatar from '@material-ui/core/Avatar'; -import { makeStyles } from '@material-ui/core/styles'; - -import { useCurrentIdentityQuery } from './CurrentIdentity.generated'; - -const useStyles = makeStyles((theme) => ({ - displayName: { - marginLeft: theme.spacing(2), - }, -})); - -const CurrentIdentity = () => { - const classes = useStyles(); - const { loading, error, data } = useCurrentIdentityQuery(); - - if (error || loading || !data?.repository?.userIdentity) return null; - - const user = data.repository.userIdentity; - return ( - <> - <Avatar src={user.avatarUrl ? user.avatarUrl : undefined}> - {user.displayName.charAt(0).toUpperCase()} - </Avatar> - <div className={classes.displayName}>{user.displayName}</div> - </> - ); -}; - -export default CurrentIdentity; diff --git a/webui/src/components/Header/Header.tsx b/webui/src/components/Header/Header.tsx index 63146cc9..56b35968 100644 --- a/webui/src/components/Header/Header.tsx +++ b/webui/src/components/Header/Header.tsx @@ -8,7 +8,7 @@ import Toolbar from '@material-ui/core/Toolbar'; import Tooltip from '@material-ui/core/Tooltip/Tooltip'; import { makeStyles } from '@material-ui/core/styles'; -import CurrentIdentity from '../CurrentIdentity/CurrentIdentity'; +import CurrentIdentity from '../Identity/CurrentIdentity'; import { LightSwitch } from '../Themer'; const useStyles = makeStyles((theme) => ({ diff --git a/webui/src/components/CurrentIdentity/CurrentIdentity.graphql b/webui/src/components/Identity/CurrentIdentity.graphql index 2794a40f..054190df 100644 --- a/webui/src/components/CurrentIdentity/CurrentIdentity.graphql +++ b/webui/src/components/Identity/CurrentIdentity.graphql @@ -1,8 +1,9 @@ +#import "./IdentityFragment.graphql" + query CurrentIdentity { repository { userIdentity { - displayName - avatarUrl + ...Identity } } } diff --git a/webui/src/components/Identity/CurrentIdentity.tsx b/webui/src/components/Identity/CurrentIdentity.tsx new file mode 100644 index 00000000..2d62dcdb --- /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.id}`} + > + 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 + } + } +} diff --git a/webui/src/components/IfLoggedIn/IfLoggedIn.tsx b/webui/src/components/IfLoggedIn/IfLoggedIn.tsx index 2476aad8..ce120da1 100644 --- a/webui/src/components/IfLoggedIn/IfLoggedIn.tsx +++ b/webui/src/components/IfLoggedIn/IfLoggedIn.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { useCurrentIdentityQuery } from '../CurrentIdentity/CurrentIdentity.generated'; +import { useCurrentIdentityQuery } from '../Identity/CurrentIdentity.generated'; type Props = { children: () => React.ReactNode }; const IfLoggedIn = ({ children }: Props) => { |