aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2019-03-31 21:39:14 +0200
committerGitHub <noreply@github.com>2019-03-31 21:39:14 +0200
commitdcf973867496273df0c2e8f59c5ee113a4c08bb1 (patch)
tree6f5cf130478dba3e11a7f964e29f35be0d04312f
parent9bc5543206ed7cba02c0bb39165c3c4db149b066 (diff)
parent22089b5e628f1356e517d24d0346a8ec2def97fc (diff)
downloadgit-bug-dcf973867496273df0c2e8f59c5ee113a4c08bb1.tar.gz
Merge pull request #104 from MichaelMure/sandhose/webui-timeline
Use Timeline API instead of raw operations
-rw-r--r--webui/src/Author.js29
-rw-r--r--webui/src/bug/Bug.js24
-rw-r--r--webui/src/bug/LabelChange.js10
-rw-r--r--webui/src/bug/Message.js89
-rw-r--r--webui/src/bug/SetStatus.js5
-rw-r--r--webui/src/bug/SetTitle.js7
-rw-r--r--webui/src/bug/Timeline.js12
-rw-r--r--webui/src/bug/TimelineQuery.js10
8 files changed, 110 insertions, 76 deletions
diff --git a/webui/src/Author.js b/webui/src/Author.js
index 7285ed4b..7bb1bf3c 100644
--- a/webui/src/Author.js
+++ b/webui/src/Author.js
@@ -1,28 +1,25 @@
-import { withStyles } from '@material-ui/core/styles';
import Tooltip from '@material-ui/core/Tooltip/Tooltip';
+import MAvatar from '@material-ui/core/Avatar';
import React from 'react';
-const styles = theme => ({
- author: {
- ...theme.typography.body2,
- },
- bold: {
- fontWeight: 'bold',
- },
-});
-
-const Author = ({ author, bold, classes }) => {
- const klass = bold ? [classes.author, classes.bold] : [classes.author];
-
+const Author = ({ author, ...props }) => {
if (!author.email) {
- return <span className={klass.join(' ')}>{author.displayName}</span>;
+ return <span {...props}>{author.displayName}</span>;
}
return (
<Tooltip title={author.email}>
- <span className={klass.join(' ')}>{author.displayName}</span>
+ <span {...props}>{author.displayName}</span>
</Tooltip>
);
};
-export default withStyles(styles)(Author);
+export const Avatar = ({ author, ...props }) => {
+ if (author.avatarUrl) {
+ return <MAvatar src={author.avatarUrl} {...props} />;
+ }
+
+ return <MAvatar {...props}>{author.displayName[0]}</MAvatar>;
+};
+
+export default Author;
diff --git a/webui/src/bug/Bug.js b/webui/src/bug/Bug.js
index 496d0c4f..9b5f84ad 100644
--- a/webui/src/bug/Bug.js
+++ b/webui/src/bug/Bug.js
@@ -9,29 +9,32 @@ import Label from '../Label';
const styles = theme => ({
main: {
- maxWidth: 600,
+ maxWidth: 800,
margin: 'auto',
marginTop: theme.spacing.unit * 4,
},
- header: {},
+ header: {
+ marginLeft: theme.spacing.unit + 40,
+ },
title: {
...theme.typography.headline,
},
id: {
...theme.typography.subheading,
- marginLeft: 15,
+ marginLeft: theme.spacing.unit,
},
container: {
display: 'flex',
- marginBottom: 30,
+ marginBottom: theme.spacing.unit,
},
timeline: {
- width: '70%',
- marginTop: 20,
- marginRight: 20,
+ flex: 1,
+ marginTop: theme.spacing.unit * 2,
+ marginRight: theme.spacing.unit * 2,
},
sidebar: {
- width: '30%',
+ marginTop: theme.spacing.unit * 2,
+ flex: '0 0 200px',
},
labelList: {
listStyle: 'none',
@@ -39,7 +42,8 @@ const styles = theme => ({
margin: 0,
},
label: {
- margin: '4px 0',
+ marginTop: theme.spacing.unit,
+ marginBottom: theme.spacing.unit,
'& > *': {
display: 'block',
},
@@ -54,7 +58,7 @@ const Bug = ({ bug, classes }) => (
<Typography color={'textSecondary'}>
<Author author={bug.author} />
- <span> opened this bug </span>
+ {' opened this bug '}
<Date date={bug.createdAt} />
</Typography>
</div>
diff --git a/webui/src/bug/LabelChange.js b/webui/src/bug/LabelChange.js
index b1bed4a5..6301f35f 100644
--- a/webui/src/bug/LabelChange.js
+++ b/webui/src/bug/LabelChange.js
@@ -8,6 +8,10 @@ import Label from '../Label';
const styles = theme => ({
main: {
...theme.typography.body2,
+ marginLeft: theme.spacing.unit + 40,
+ },
+ author: {
+ fontWeight: 'bold',
},
});
@@ -15,7 +19,7 @@ const LabelChange = ({ op, classes }) => {
const { added, removed } = op;
return (
<div className={classes.main}>
- <Author author={op.author} bold />
+ <Author author={op.author} className={classes.author} />
{added.length > 0 && <span> added the </span>}
{added.map((label, index) => (
<Label key={index} label={label} />
@@ -36,8 +40,8 @@ const LabelChange = ({ op, classes }) => {
};
LabelChange.fragment = gql`
- fragment LabelChange on Operation {
- ... on LabelChangeOperation {
+ fragment LabelChange on TimelineItem {
+ ... on LabelChangeTimelineItem {
date
author {
name
diff --git a/webui/src/bug/Message.js b/webui/src/bug/Message.js
index a4e3eeb0..493de8ee 100644
--- a/webui/src/bug/Message.js
+++ b/webui/src/bug/Message.js
@@ -1,68 +1,95 @@
import { withStyles } from '@material-ui/core/styles';
-import Typography from '@material-ui/core/Typography';
+import Paper from '@material-ui/core/Paper';
import gql from 'graphql-tag';
import React from 'react';
import Author from '../Author';
+import { Avatar } from '../Author';
import Date from '../Date';
const styles = theme => ({
+ author: {
+ fontWeight: 'bold',
+ },
+ container: {
+ display: 'flex',
+ },
+ avatar: {
+ marginTop: 2,
+ },
+ bubble: {
+ flex: 1,
+ marginLeft: theme.spacing.unit,
+ },
header: {
...theme.typography.body2,
- padding: '3px 3px 3px 6px',
- backgroundColor: '#f1f8ff',
- border: '1px solid #d1d5da',
- borderTopLeftRadius: 3,
- borderTopRightRadius: 3,
+ color: '#444',
+ padding: '0.5rem 1rem',
+ borderBottom: '1px solid #ddd',
+ display: 'flex',
+ },
+ title: {
+ flex: 1,
+ },
+ tag: {
+ ...theme.typography.button,
+ color: '#888',
+ border: '#ddd solid 1px',
+ padding: '0 0.5rem',
+ fontSize: '0.75rem',
+ borderRadius: 2,
+ marginLeft: '0.5rem',
},
- message: {
- borderLeft: '1px solid #d1d5da',
- borderRight: '1px solid #d1d5da',
- borderBottom: '1px solid #d1d5da',
- borderBottomLeftRadius: 3,
- borderBottomRightRadius: 3,
- backgroundColor: '#fff',
- minHeight: 50,
- padding: 5,
+ body: {
+ ...theme.typography.body1,
+ padding: '1rem',
whiteSpace: 'pre-wrap',
},
});
const Message = ({ op, classes }) => (
- <div>
- <div className={classes.header}>
- <Author className={classes.author} author={op.author} bold />
- <span> commented </span>
- <Date date={op.date} />
- </div>
- <div className={classes.message}>
- <Typography>{op.message}</Typography>
- </div>
- </div>
+ <article className={classes.container}>
+ <Avatar author={op.author} className={classes.avatar} />
+ <Paper elevation={1} className={classes.bubble}>
+ <header className={classes.header}>
+ <div className={classes.title}>
+ <Author className={classes.author} author={op.author} />
+ <span> commented </span>
+ <Date date={op.createdAt} />
+ </div>
+ {op.edited && <div className={classes.tag}>Edited</div>}
+ </header>
+ <section className={classes.body}>{op.message}</section>
+ </Paper>
+ </article>
);
Message.createFragment = gql`
- fragment Create on Operation {
- ... on CreateOperation {
- date
+ fragment Create on TimelineItem {
+ ... on CreateTimelineItem {
+ createdAt
author {
name
email
displayName
+ avatarUrl
}
+ edited
message
}
}
`;
Message.commentFragment = gql`
- fragment Comment on Operation {
- ... on AddCommentOperation {
- date
+ fragment AddComment on TimelineItem {
+ ... on AddCommentTimelineItem {
+ createdAt
author {
name
email
displayName
+ avatarUrl
}
+ edited
message
}
}
diff --git a/webui/src/bug/SetStatus.js b/webui/src/bug/SetStatus.js
index 332c8352..58b81630 100644
--- a/webui/src/bug/SetStatus.js
+++ b/webui/src/bug/SetStatus.js
@@ -7,6 +7,7 @@ import Date from '../Date';
const styles = theme => ({
main: {
...theme.typography.body2,
+ marginLeft: theme.spacing.unit + 40,
},
});
@@ -21,8 +22,8 @@ const SetStatus = ({ op, classes }) => {
};
SetStatus.fragment = gql`
- fragment SetStatus on Operation {
- ... on SetStatusOperation {
+ fragment SetStatus on TimelineItem {
+ ... on SetStatusTimelineItem {
date
author {
name
diff --git a/webui/src/bug/SetTitle.js b/webui/src/bug/SetTitle.js
index 5b17c431..f5c48568 100644
--- a/webui/src/bug/SetTitle.js
+++ b/webui/src/bug/SetTitle.js
@@ -7,6 +7,7 @@ import Date from '../Date';
const styles = theme => ({
main: {
...theme.typography.body2,
+ marginLeft: theme.spacing.unit + 40,
},
bold: {
fontWeight: 'bold',
@@ -16,7 +17,7 @@ const styles = theme => ({
const SetTitle = ({ op, classes }) => {
return (
<div className={classes.main}>
- <Author author={op.author} bold />
+ <Author author={op.author} className={classes.bold} />
<span> changed the title from </span>
<span className={classes.bold}>{op.was}</span>
<span> to </span>
@@ -27,8 +28,8 @@ const SetTitle = ({ op, classes }) => {
};
SetTitle.fragment = gql`
- fragment SetTitle on Operation {
- ... on SetTitleOperation {
+ fragment SetTitle on TimelineItem {
+ ... on SetTitleTimelineItem {
date
author {
name
diff --git a/webui/src/bug/Timeline.js b/webui/src/bug/Timeline.js
index d331d11d..3123f45f 100644
--- a/webui/src/bug/Timeline.js
+++ b/webui/src/bug/Timeline.js
@@ -8,7 +8,7 @@ import SetTitle from './SetTitle';
const styles = theme => ({
main: {
'& > *:not(:last-child)': {
- marginBottom: 10,
+ marginBottom: theme.spacing.unit * 2,
},
},
});
@@ -27,15 +27,15 @@ class Timeline extends React.Component {
<div className={classes.main}>
{ops.map((op, index) => {
switch (op.__typename) {
- case 'CreateOperation':
+ case 'CreateTimelineItem':
return <Message key={index} op={op} />;
- case 'AddCommentOperation':
+ case 'AddCommentTimelineItem':
return <Message key={index} op={op} />;
- case 'LabelChangeOperation':
+ case 'LabelChangeTimelineItem':
return <LabelChange key={index} op={op} />;
- case 'SetTitleOperation':
+ case 'SetTitleTimelineItem':
return <SetTitle key={index} op={op} />;
- case 'SetStatusOperation':
+ case 'SetStatusTimelineItem':
return <SetStatus key={index} op={op} />;
default:
diff --git a/webui/src/bug/TimelineQuery.js b/webui/src/bug/TimelineQuery.js
index 78658a6f..ebb20f9d 100644
--- a/webui/src/bug/TimelineQuery.js
+++ b/webui/src/bug/TimelineQuery.js
@@ -12,13 +12,13 @@ const QUERY = gql`
query($id: String!, $first: Int = 10, $after: String) {
defaultRepository {
bug(prefix: $id) {
- operations(first: $first, after: $after) {
+ timeline(first: $first, after: $after) {
nodes {
- ...Create
- ...Comment
...LabelChange
- ...SetTitle
...SetStatus
+ ...SetTitle
+ ...AddComment
+ ...Create
}
pageInfo {
hasNextPage
@@ -42,7 +42,7 @@ const TimelineQuery = ({ id }) => (
if (error) return <p>Error: {error}</p>;
return (
<Timeline
- ops={data.defaultRepository.bug.operations.nodes}
+ ops={data.defaultRepository.bug.timeline.nodes}
fetchMore={fetchMore}
/>
);