aboutsummaryrefslogtreecommitdiffstats
path: root/webui/src/pages
diff options
context:
space:
mode:
authorSascha <GlancingMind@outlook.com>2021-03-20 15:13:10 +0100
committerSascha <GlancingMind@outlook.com>2021-04-13 19:07:57 +0200
commit41e85023019bc13c06a1de2c431e0bd920e9e29a (patch)
tree95ea962e484912538f3b8611d3eb54056bbf3658 /webui/src/pages
parent998ae348b10efd5af758944143b70125a98e8f86 (diff)
downloadgit-bug-41e85023019bc13c06a1de2c431e0bd920e9e29a.tar.gz
Use profile page for each identity
Authorcomponent links to the authors profile page. Replace pofile buglist with statistics
Diffstat (limited to 'webui/src/pages')
-rw-r--r--webui/src/pages/bug/LabelChange.tsx8
-rw-r--r--webui/src/pages/bug/Message.tsx1
-rw-r--r--webui/src/pages/bug/SetStatus.tsx8
-rw-r--r--webui/src/pages/bug/SetTitle.tsx8
-rw-r--r--webui/src/pages/identity/BugList.tsx4
-rw-r--r--webui/src/pages/identity/GetUserStatistic.graphql13
-rw-r--r--webui/src/pages/identity/Identity.tsx207
-rw-r--r--webui/src/pages/identity/IdentityQuery.tsx24
-rw-r--r--webui/src/pages/identity/index.tsx1
-rw-r--r--webui/src/pages/list/BugRow.tsx4
-rw-r--r--webui/src/pages/list/ListQuery.tsx2
11 files changed, 175 insertions, 105 deletions
diff --git a/webui/src/pages/bug/LabelChange.tsx b/webui/src/pages/bug/LabelChange.tsx
index 712c33fa..868d8c9b 100644
--- a/webui/src/pages/bug/LabelChange.tsx
+++ b/webui/src/pages/bug/LabelChange.tsx
@@ -1,5 +1,6 @@
import React from 'react';
+import { Typography } from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
import Author from 'src/components/Author';
@@ -10,11 +11,12 @@ import { LabelChangeFragment } from './LabelChangeFragment.generated';
const useStyles = makeStyles((theme) => ({
main: {
- ...theme.typography.body2,
+ color: theme.palette.text.secondary,
marginLeft: theme.spacing(1) + 40,
},
author: {
fontWeight: 'bold',
+ color: theme.palette.text.secondary,
},
label: {
maxWidth: '50ch',
@@ -31,7 +33,7 @@ function LabelChange({ op }: Props) {
const { added, removed } = op;
const classes = useStyles();
return (
- <div className={classes.main}>
+ <Typography className={classes.main}>
<Author author={op.author} className={classes.author} />
{added.length > 0 && <span> added the </span>}
{added.map((label, index) => (
@@ -48,7 +50,7 @@ function LabelChange({ op }: Props) {
{added.length + removed.length > 1 && 's'}{' '}
</span>
<Date date={op.date} />
- </div>
+ </Typography>
);
}
diff --git a/webui/src/pages/bug/Message.tsx b/webui/src/pages/bug/Message.tsx
index 39b11ccd..808bb525 100644
--- a/webui/src/pages/bug/Message.tsx
+++ b/webui/src/pages/bug/Message.tsx
@@ -21,6 +21,7 @@ import MessageHistoryDialog from './MessageHistoryDialog';
const useStyles = makeStyles((theme) => ({
author: {
fontWeight: 'bold',
+ color: theme.palette.info.contrastText,
},
container: {
display: 'flex',
diff --git a/webui/src/pages/bug/SetStatus.tsx b/webui/src/pages/bug/SetStatus.tsx
index 855848f9..f231b917 100644
--- a/webui/src/pages/bug/SetStatus.tsx
+++ b/webui/src/pages/bug/SetStatus.tsx
@@ -1,5 +1,6 @@
import React from 'react';
+import { Typography } from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
import { Status } from '../../gqlTypes';
@@ -10,11 +11,12 @@ import { SetStatusFragment } from './SetStatusFragment.generated';
const useStyles = makeStyles((theme) => ({
main: {
- ...theme.typography.body2,
+ color: theme.palette.text.secondary,
marginLeft: theme.spacing(1) + 40,
},
author: {
fontWeight: 'bold',
+ color: theme.palette.text.secondary,
},
}));
@@ -29,11 +31,11 @@ function SetStatus({ op }: Props) {
];
return (
- <div className={classes.main}>
+ <Typography className={classes.main}>
<Author author={op.author} className={classes.author} />
<span> {status} this </span>
<Date date={op.date} />
- </div>
+ </Typography>
);
}
diff --git a/webui/src/pages/bug/SetTitle.tsx b/webui/src/pages/bug/SetTitle.tsx
index 98bea928..057062f7 100644
--- a/webui/src/pages/bug/SetTitle.tsx
+++ b/webui/src/pages/bug/SetTitle.tsx
@@ -1,5 +1,6 @@
import React from 'react';
+import { Typography } from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
import Author from 'src/components/Author';
@@ -9,11 +10,12 @@ import { SetTitleFragment } from './SetTitleFragment.generated';
const useStyles = makeStyles((theme) => ({
main: {
- ...theme.typography.body2,
+ color: theme.palette.text.secondary,
marginLeft: theme.spacing(1) + 40,
},
author: {
fontWeight: 'bold',
+ color: theme.palette.text.secondary,
},
before: {
fontWeight: 'bold',
@@ -31,14 +33,14 @@ type Props = {
function SetTitle({ op }: Props) {
const classes = useStyles();
return (
- <div className={classes.main}>
+ <Typography className={classes.main}>
<Author author={op.author} className={classes.author} />
<span> changed the title from </span>
<span className={classes.before}>{op.was}</span>
<span> to </span>
<span className={classes.after}>{op.title}</span>&nbsp;
<Date date={op.date} />
- </div>
+ </Typography>
);
}
diff --git a/webui/src/pages/identity/BugList.tsx b/webui/src/pages/identity/BugList.tsx
index e74c11d4..c7994827 100644
--- a/webui/src/pages/identity/BugList.tsx
+++ b/webui/src/pages/identity/BugList.tsx
@@ -1,6 +1,6 @@
import React from 'react';
-import { Card, Link, Typography } from '@material-ui/core';
+import { Card, Divider, Link, Typography } from '@material-ui/core';
import CircularProgress from '@material-ui/core/CircularProgress';
import { makeStyles } from '@material-ui/core/styles';
@@ -53,6 +53,7 @@ function BugList({ humanId }: Props) {
{bug.title}
</Link>
</Typography>
+ <Divider />
<Typography variant="subtitle2">
Created&nbsp;
<Date date={bug.createdAt} />
@@ -64,6 +65,7 @@ function BugList({ humanId }: Props) {
</Card>
);
})}
+ {bugs?.length === 0 && <p>No authored bugs by this user found.</p>}
</div>
);
}
diff --git a/webui/src/pages/identity/GetUserStatistic.graphql b/webui/src/pages/identity/GetUserStatistic.graphql
new file mode 100644
index 00000000..318b860d
--- /dev/null
+++ b/webui/src/pages/identity/GetUserStatistic.graphql
@@ -0,0 +1,13 @@
+query GetUserStatistic($authorQuery: String!, $participantQuery: String!, $actionQuery: String!) {
+ repository {
+ authored: allBugs(query: $authorQuery) {
+ totalCount
+ },
+ participated: allBugs(query: $participantQuery) {
+ totalCount
+ }
+ actions: allBugs(query: $actionQuery) {
+ totalCount
+ }
+ }
+}
diff --git a/webui/src/pages/identity/Identity.tsx b/webui/src/pages/identity/Identity.tsx
index 8261c0f4..5bfc87c0 100644
--- a/webui/src/pages/identity/Identity.tsx
+++ b/webui/src/pages/identity/Identity.tsx
@@ -1,124 +1,145 @@
import React from 'react';
+import { Link as RouterLink } from 'react-router-dom';
-import {
- Checkbox,
- FormControlLabel,
- Link,
- Paper,
- Typography,
-} from '@material-ui/core';
+import { Link, Paper, Typography } from '@material-ui/core';
import Avatar from '@material-ui/core/Avatar';
+import CircularProgress from '@material-ui/core/CircularProgress';
+import Grid from '@material-ui/core/Grid';
import { makeStyles } from '@material-ui/core/styles';
import InfoIcon from '@material-ui/icons/Info';
import MailOutlineIcon from '@material-ui/icons/MailOutline';
-import { useCurrentIdentityQuery } from '../../components/CurrentIdentity/CurrentIdentity.generated';
+import { IdentityFragment } from '../../components/Identity/IdentityFragment.generated';
-import BugList from './BugList';
+import { useGetUserStatisticQuery } from './GetUserStatistic.generated';
const useStyles = makeStyles((theme) => ({
main: {
maxWidth: 1000,
margin: 'auto',
- marginTop: theme.spacing(4),
- padding: theme.spacing(3, 2),
- display: 'flex',
- },
- container: {
- display: 'flex',
- marginBottom: theme.spacing(1),
- },
- leftSidebar: {
- marginTop: theme.spacing(2),
- flex: '0 0 200px',
+ marginTop: theme.spacing(3),
},
content: {
- marginTop: theme.spacing(5),
- padding: theme.spacing(3, 2),
- minWidth: 800,
- backgroundColor: theme.palette.background.paper,
- },
- rightSidebar: {
- marginTop: theme.spacing(5),
- flex: '0 0 200px',
+ padding: theme.spacing(0.5, 2, 2, 2),
+ wordWrap: 'break-word',
},
large: {
- width: theme.spacing(20),
- height: theme.spacing(20),
+ minWidth: 200,
+ minHeight: 200,
+ margin: 'auto',
+ maxWidth: '100%',
+ maxHeight: '100%',
},
- control: {
- paddingBottom: theme.spacing(3),
+ heading: {
+ marginTop: theme.spacing(3),
},
header: {
...theme.typography.h4,
+ wordBreak: 'break-word',
+ },
+ infoIcon: {
+ verticalAlign: 'bottom',
},
}));
-const Identity = () => {
+type Props = {
+ identity: IdentityFragment;
+};
+const Identity = ({ identity }: Props) => {
const classes = useStyles();
- const { data } = useCurrentIdentityQuery();
- const user = data?.repository?.userIdentity;
- console.log(user);
+ const user = identity;
+
+ const { loading, error, data } = useGetUserStatisticQuery({
+ variables: {
+ authorQuery: 'author:' + user?.humanId,
+ participantQuery: 'participant:' + user?.humanId,
+ actionQuery: 'actor:' + user?.humanId,
+ },
+ });
+
+ if (loading) return <CircularProgress />;
+ if (error) return <p>Error: {error}</p>;
+ const statistic = data?.repository;
+ const authoredCount = statistic?.authored?.totalCount;
+ const participatedCount = statistic?.participated?.totalCount;
+ const actionCount = statistic?.actions?.totalCount;
return (
<main className={classes.main}>
- <div className={classes.container}>
- <div className={classes.leftSidebar}>
- <h1 className={classes.header}>
- {user?.displayName ? user?.displayName : 'none'}
- </h1>
- <Avatar
- src={user?.avatarUrl ? user.avatarUrl : undefined}
- className={classes.large}
- >
- {user?.displayName.charAt(0).toUpperCase()}
- </Avatar>
- <Typography variant="h5" component="h2">
- Your account
- </Typography>
- <Typography variant="subtitle2" component="h2">
- Name: {user?.name ? user?.name : '---'}
- </Typography>
- <Typography variant="subtitle2" component="h3">
- Id (truncated): {user?.humanId ? user?.humanId : '---'}
- <InfoIcon
- fontSize={'small'}
- titleAccess={user?.id ? user?.id : '---'}
- />
- </Typography>
- <Typography variant="subtitle2" component="h3">
- Login: {user?.login ? user?.login : '---'}
- </Typography>
- <Typography
- variant="subtitle2"
- component="h3"
- style={{
- display: 'flex',
- alignItems: 'center',
- flexWrap: 'wrap',
- }}
- >
- <MailOutlineIcon />
- <Link href={'mailto:' + user?.email} color={'inherit'}>
- {user?.email ? user?.email : '---'}
- </Link>
- </Typography>
- <FormControlLabel
- className={classes.control}
- label="Protected"
- labelPlacement="end"
- value={user?.isProtected}
- control={<Checkbox color="secondary" indeterminate />}
- />
- </div>
- <Paper className={classes.content}>
- <Typography variant="h5" component="h2">
- Bugs authored by {user?.displayName}
- </Typography>
- <BugList humanId={user?.humanId ? user?.humanId : ''} />
- </Paper>
- <div className={classes.rightSidebar}></div>
- </div>
+ <Paper elevation={3} className={classes.content}>
+ <Grid spacing={2} container direction="row">
+ <Grid xs={12} sm={4} className={classes.heading} item>
+ <Avatar
+ src={user?.avatarUrl ? user.avatarUrl : undefined}
+ className={classes.large}
+ >
+ {user?.displayName.charAt(0).toUpperCase()}
+ </Avatar>
+ </Grid>
+ <Grid xs={12} sm={4} item>
+ <section>
+ <h1 className={classes.header}>{user?.name}</h1>
+ <Typography variant="subtitle1">
+ Name: {user?.displayName ? user?.displayName : '---'}
+ </Typography>
+ <Typography variant="subtitle1">
+ Id (truncated): {user?.humanId ? user?.humanId : '---'}
+ <InfoIcon
+ titleAccess={user?.id ? user?.id : '---'}
+ className={classes.infoIcon}
+ />
+ </Typography>
+ {user?.email && (
+ <Typography
+ variant="subtitle1"
+ style={{
+ display: 'flex',
+ alignItems: 'center',
+ flexWrap: 'wrap',
+ }}
+ >
+ <MailOutlineIcon />
+ <Link href={'mailto:' + user?.email} color={'inherit'}>
+ {user?.email}
+ </Link>
+ </Typography>
+ )}
+ </section>
+ </Grid>
+ <Grid xs={12} sm={4} item>
+ <section>
+ <h1 className={classes.header}>Statistics</h1>
+ <Link
+ component={RouterLink}
+ to={`/?q=author%3A${user?.humanId}+sort%3Acreation`}
+ color={'inherit'}
+ >
+ <Typography variant="subtitle1">
+ Created {authoredCount} bugs.
+ </Typography>
+ </Link>
+ <Link
+ component={RouterLink}
+ to={`/?q=participant%3A${user?.humanId}+sort%3Acreation`}
+ color={'inherit'}
+ >
+ <Typography variant="subtitle1">
+ Participated to {participatedCount} bugs.
+ </Typography>
+ </Link>
+ <Link
+ component={RouterLink}
+ to={`/?q=actor%3A${user?.humanId}+sort%3Acreation`}
+ color={'inherit'}
+ >
+ <Typography variant="subtitle1">
+ Interacted with {actionCount} bugs.
+ </Typography>
+ </Link>
+ </section>
+ </Grid>
+ </Grid>
+ </Paper>
</main>
);
};
diff --git a/webui/src/pages/identity/IdentityQuery.tsx b/webui/src/pages/identity/IdentityQuery.tsx
new file mode 100644
index 00000000..964a9bac
--- /dev/null
+++ b/webui/src/pages/identity/IdentityQuery.tsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import { RouteComponentProps } from 'react-router-dom';
+
+import CircularProgress from '@material-ui/core/CircularProgress';
+
+import { useGetUserByIdQuery } from '../../components/Identity/UserIdentity.generated';
+
+import Identity from './Identity';
+
+type Props = RouteComponentProps<{
+ id: string;
+}>;
+
+const UserQuery: React.FC<Props> = ({ match }: Props) => {
+ const { loading, error, data } = useGetUserByIdQuery({
+ variables: { userId: match.params.id },
+ });
+ if (loading) return <CircularProgress />;
+ if (error) return <p>Error: {error}</p>;
+ if (!data?.repository?.identity) return <p>404.</p>;
+ return <Identity identity={data.repository.identity} />;
+};
+
+export default UserQuery;
diff --git a/webui/src/pages/identity/index.tsx b/webui/src/pages/identity/index.tsx
new file mode 100644
index 00000000..06208687
--- /dev/null
+++ b/webui/src/pages/identity/index.tsx
@@ -0,0 +1 @@
+export { default } from './IdentityQuery';
diff --git a/webui/src/pages/list/BugRow.tsx b/webui/src/pages/list/BugRow.tsx
index 87e45581..a1466d63 100644
--- a/webui/src/pages/list/BugRow.tsx
+++ b/webui/src/pages/list/BugRow.tsx
@@ -9,6 +9,7 @@ import CheckCircleOutline from '@material-ui/icons/CheckCircleOutline';
import CommentOutlinedIcon from '@material-ui/icons/CommentOutlined';
import ErrorOutline from '@material-ui/icons/ErrorOutline';
+import Author from 'src/components/Author';
import Date from 'src/components/Date';
import Label from 'src/components/Label';
import { Status } from 'src/gqlTypes';
@@ -117,7 +118,8 @@ function BugRow({ bug }: Props) {
<div className={classes.details}>
{bug.humanId} opened&nbsp;
<Date date={bug.createdAt} />
- &nbsp;by {bug.author.displayName}
+ &nbsp;by&nbsp;
+ <Author className={classes.details} author={bug.author} />
</div>
</div>
<span className={classes.commentCountCell}>
diff --git a/webui/src/pages/list/ListQuery.tsx b/webui/src/pages/list/ListQuery.tsx
index 2b46dca5..9aefd02d 100644
--- a/webui/src/pages/list/ListQuery.tsx
+++ b/webui/src/pages/list/ListQuery.tsx
@@ -14,7 +14,7 @@ import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft';
import KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight';
import Skeleton from '@material-ui/lab/Skeleton';
-import { useCurrentIdentityQuery } from '../../components/CurrentIdentity/CurrentIdentity.generated';
+import { useCurrentIdentityQuery } from '../../components/Identity/CurrentIdentity.generated';
import IfLoggedIn from 'src/components/IfLoggedIn/IfLoggedIn';
import { parse, Query, stringify } from './Filter';