aboutsummaryrefslogtreecommitdiffstats
path: root/webui/src
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2018-08-14 02:06:02 +0200
committerMichael Muré <batolettre@gmail.com>2018-08-14 02:06:02 +0200
commit5edcb6c8bd430af4c26567d19c388d4c3e30b681 (patch)
treeb47590b6c880f62f0b386e5433aafd010093ab03 /webui/src
parent4c850b598939536b2e09ed520e427e94d0026211 (diff)
downloadgit-bug-5edcb6c8bd430af4c26567d19c388d4c3e30b681.tar.gz
webui: revamp the bug list
Diffstat (limited to 'webui/src')
-rw-r--r--webui/src/App.js41
-rw-r--r--webui/src/Bug.js28
-rw-r--r--webui/src/BugPage.js29
-rw-r--r--webui/src/BugSummary.js114
-rw-r--r--webui/src/Comment.js27
-rw-r--r--webui/src/ListPage.js47
-rw-r--r--webui/src/index.js20
7 files changed, 174 insertions, 132 deletions
diff --git a/webui/src/App.js b/webui/src/App.js
index 1d6382e5..ced02e43 100644
--- a/webui/src/App.js
+++ b/webui/src/App.js
@@ -1,40 +1,39 @@
-import React from "react";
-import { withRouter, Switch, Route } from "react-router";
-import { Link } from "react-router-dom";
-import { withStyles } from "@material-ui/core/styles";
+import AppBar from '@material-ui/core/AppBar'
+import CssBaseline from '@material-ui/core/CssBaseline'
+import { withStyles } from '@material-ui/core/styles'
+import Toolbar from '@material-ui/core/Toolbar'
+import Typography from '@material-ui/core/Typography'
+import React from 'react'
+import { Route, Switch, withRouter } from 'react-router'
+import { Link } from 'react-router-dom'
-import AppBar from "@material-ui/core/AppBar";
-import CssBaseline from "@material-ui/core/CssBaseline";
-import Toolbar from "@material-ui/core/Toolbar";
-import Typography from "@material-ui/core/Typography";
-
-import BugPage from "./BugPage";
-import ListPage from "./ListPage";
+import BugPage from './BugPage'
+import ListPage from './ListPage'
const styles = theme => ({
appTitle: {
- color: "white",
- textDecoration: "none"
+ color: 'white',
+ textDecoration: 'none'
}
-});
+})
-const App = ({ location, classes }) => (
+const App = ({location, classes}) => (
<React.Fragment>
- <CssBaseline />
+ <CssBaseline/>
<AppBar position="static" color="primary">
<Toolbar>
<Link to="/" className={classes.appTitle}>
<Typography variant="title" color="inherit">
- git-bug-webui(1)
+ git-bug webui
</Typography>
</Link>
</Toolbar>
</AppBar>
<Switch>
- <Route path="/" exact component={ListPage} />
- <Route path="/bug/:id" exact component={BugPage} />
+ <Route path="/" exact component={ListPage}/>
+ <Route path="/bug/:id" exact component={BugPage}/>
</Switch>
</React.Fragment>
-);
+)
-export default withStyles(styles)(withRouter(App));
+export default withStyles(styles)(withRouter(App))
diff --git a/webui/src/Bug.js b/webui/src/Bug.js
index bca23e58..91463b51 100644
--- a/webui/src/Bug.js
+++ b/webui/src/Bug.js
@@ -1,27 +1,27 @@
-import React from "react";
-import gql from "graphql-tag";
-import { withStyles } from "@material-ui/core/styles";
+import { withStyles } from '@material-ui/core/styles'
+import gql from 'graphql-tag'
+import React from 'react'
+import BugSummary from './BugSummary'
-import Comment from "./Comment";
-import BugSummary from "./BugSummary";
+import Comment from './Comment'
const styles = theme => ({
main: {
maxWidth: 600,
- margin: "auto",
+ margin: 'auto',
marginTop: theme.spacing.unit * 4
}
-});
+})
-const Bug = ({ bug, classes }) => (
+const Bug = ({bug, classes}) => (
<main className={classes.main}>
- <BugSummary bug={bug} />
+ <BugSummary bug={bug}/>
- {bug.comments.edges.map(({ cursor, node }) => (
- <Comment key={cursor} comment={node} />
+ {bug.comments.edges.map(({cursor, node}) => (
+ <Comment key={cursor} comment={node}/>
))}
</main>
-);
+)
Bug.fragment = gql`
fragment Bug on Bug {
@@ -38,6 +38,6 @@ Bug.fragment = gql`
${BugSummary.fragment}
${Comment.fragment}
-`;
+`
-export default withStyles(styles)(Bug);
+export default withStyles(styles)(Bug)
diff --git a/webui/src/BugPage.js b/webui/src/BugPage.js
index 0f415841..a91030ab 100644
--- a/webui/src/BugPage.js
+++ b/webui/src/BugPage.js
@@ -1,10 +1,9 @@
-import React from "react";
-import { Query } from "react-apollo";
-import gql from "graphql-tag";
+import CircularProgress from '@material-ui/core/CircularProgress'
+import gql from 'graphql-tag'
+import React from 'react'
+import { Query } from 'react-apollo'
-import CircularProgress from "@material-ui/core/CircularProgress";
-
-import Bug from "./Bug";
+import Bug from './Bug'
const QUERY = gql`
query GetBug($id: String!) {
@@ -16,16 +15,16 @@ const QUERY = gql`
}
${Bug.fragment}
-`;
+`
-const BugPage = ({ match }) => (
- <Query query={QUERY} variables={{ id: match.params.id }}>
- {({ loading, error, data }) => {
- if (loading) return <CircularProgress />;
- if (error) return <p>Error.</p>;
- return <Bug bug={data.defaultRepository.bug} />;
+const BugPage = ({match}) => (
+ <Query query={QUERY} variables={{id: match.params.id}}>
+ {({loading, error, data}) => {
+ if (loading) return <CircularProgress/>
+ if (error) return <p>Error.</p>
+ return <Bug bug={data.defaultRepository.bug}/>
}}
</Query>
-);
+)
-export default BugPage;
+export default BugPage
diff --git a/webui/src/BugSummary.js b/webui/src/BugSummary.js
index 469ab9a8..5ffa8e05 100644
--- a/webui/src/BugSummary.js
+++ b/webui/src/BugSummary.js
@@ -1,53 +1,93 @@
-import React from "react";
-import { Link } from "react-router-dom";
-import gql from "graphql-tag";
-import { withStyles } from "@material-ui/core/styles";
+import { withStyles } from '@material-ui/core/styles'
+import TableCell from '@material-ui/core/TableCell/TableCell'
+import TableRow from '@material-ui/core/TableRow/TableRow'
+import Tooltip from '@material-ui/core/Tooltip/Tooltip'
+import Typography from '@material-ui/core/Typography'
+import ErrorOutline from '@material-ui/icons/ErrorOutline'
+import gql from 'graphql-tag'
+import React from 'react'
+import { Link } from 'react-router-dom'
+import * as moment from 'moment'
-import Card from "@material-ui/core/Card";
-import CardContent from "@material-ui/core/CardContent";
-import Chip from "@material-ui/core/Chip";
-import Typography from "@material-ui/core/Typography";
+const Open = ({className}) => <Tooltip title="Open">
+ <ErrorOutline nativeColor='#28a745' className={className}/>
+</Tooltip>
+
+const Closed = ({className}) => <Tooltip title="Closed">
+ <ErrorOutline nativeColor='#cb2431' className={className}/>
+</Tooltip>
+
+const Status = ({status, className}) => {
+ switch(status) {
+ case 'OPEN': return <Open className={className}/>
+ case 'CLOSED': return <Closed className={className}/>
+ default: return 'unknown status ' + status
+ }
+}
const styles = theme => ({
- labelList: {
- display: "flex",
- flexWrap: "wrap",
- marginTop: theme.spacing.unit
+ cell: {
+ display: 'flex',
+ alignItems: 'center'
},
- label: {
- marginRight: theme.spacing.unit
+ status: {
+ margin: 10
},
- summary: {
- marginBottom: theme.spacing.unit * 2
- }
-});
+ title: {
+ display: 'inline-block',
+ textDecoration: 'none'
+ },
+ labels: {
+ display: 'inline-block',
+ paddingLeft: theme.spacing.unit,
+ '&>span': {
+ padding: '0 4px',
+ margin: '0 1px',
+ backgroundColor: '#da9898',
+ borderRadius: '3px',
+ }
+ },
+})
-const BugSummary = ({ bug, classes }) => (
- <Card className={classes.summary}>
- <CardContent>
- <Typography variant="headline" component="h2">
- {bug.title}
- </Typography>
- <Typography variant="subheading" component="h3" title={bug.id}>
- <Link to={"/bug/" + bug.id.slice(0, 8)}>#{bug.id.slice(0, 8)}</Link> •{" "}
- {bug.status.toUpperCase()}
- </Typography>
- <div className={classes.labelList}>
- {bug.labels.map(label => (
- <Chip key={label} label={label} className={classes.label} />
- ))}
+const BugSummary = ({bug, classes}) => (
+ <TableRow hover>
+ <TableCell className={classes.cell}>
+ <Status status={bug.status} className={classes.status}/>
+ <div>
+ <Link to={'bug/'+bug.humanId}>
+ <Typography variant={'title'} className={classes.title}>
+ {bug.title}
+ </Typography>
+ </Link>
+ <span className={classes.labels}>
+ {bug.labels.map(l => (
+ <span key={l}>{l}</span>)
+ )}
+ </span>
+ <Typography color={'textSecondary'}>
+ {bug.humanId} opened
+ <Tooltip title={moment(bug.createdAt).format('MMMM D, YYYY, h:mm a')}>
+ <span> {moment(bug.createdAt).fromNow()} </span>
+ </Tooltip>
+ by {bug.author.name}
+ </Typography>
</div>
- </CardContent>
- </Card>
-);
+ </TableCell>
+ </TableRow>
+)
BugSummary.fragment = gql`
fragment BugSummary on Bug {
id
+ humanId
title
status
+ createdAt
labels
+ author {
+ name
+ }
}
-`;
+`
-export default withStyles(styles)(BugSummary);
+export default withStyles(styles)(BugSummary)
diff --git a/webui/src/Comment.js b/webui/src/Comment.js
index a4fd1b40..bc108083 100644
--- a/webui/src/Comment.js
+++ b/webui/src/Comment.js
@@ -1,20 +1,19 @@
-import React from "react";
-import gql from "graphql-tag";
-import { withStyles } from "@material-ui/core/styles";
-
-import Avatar from "@material-ui/core/Avatar";
-import Card from "@material-ui/core/Card";
-import CardContent from "@material-ui/core/CardContent";
-import CardHeader from "@material-ui/core/CardHeader";
-import Typography from "@material-ui/core/Typography";
+import Avatar from '@material-ui/core/Avatar'
+import Card from '@material-ui/core/Card'
+import CardContent from '@material-ui/core/CardContent'
+import CardHeader from '@material-ui/core/CardHeader'
+import { withStyles } from '@material-ui/core/styles'
+import Typography from '@material-ui/core/Typography'
+import gql from 'graphql-tag'
+import React from 'react'
const styles = theme => ({
comment: {
marginBottom: theme.spacing.unit
}
-});
+})
-const Comment = withStyles(styles)(({ comment, classes }) => (
+const Comment = withStyles(styles)(({comment, classes}) => (
<Card className={classes.comment}>
<CardHeader
avatar={
@@ -29,7 +28,7 @@ const Comment = withStyles(styles)(({ comment, classes }) => (
<Typography component="p">{comment.message}</Typography>
</CardContent>
</Card>
-));
+))
Comment.fragment = gql`
fragment Comment on Comment {
@@ -39,6 +38,6 @@ Comment.fragment = gql`
email
}
}
-`;
+`
-export default withStyles(styles)(Comment);
+export default withStyles(styles)(Comment)
diff --git a/webui/src/ListPage.js b/webui/src/ListPage.js
index ed56e553..76350ec5 100644
--- a/webui/src/ListPage.js
+++ b/webui/src/ListPage.js
@@ -1,11 +1,12 @@
-import React from "react";
-import { Query } from "react-apollo";
-import gql from "graphql-tag";
-import { withStyles } from "@material-ui/core/styles";
+import CircularProgress from '@material-ui/core/CircularProgress'
+import { withStyles } from '@material-ui/core/styles'
+import Table from '@material-ui/core/Table/Table'
+import TableBody from '@material-ui/core/TableBody/TableBody'
+import gql from 'graphql-tag'
+import React from 'react'
+import { Query } from 'react-apollo'
-import CircularProgress from "@material-ui/core/CircularProgress";
-
-import BugSummary from "./BugSummary";
+import BugSummary from './BugSummary'
const QUERY = gql`
{
@@ -22,32 +23,36 @@ const QUERY = gql`
}
${BugSummary.fragment}
-`;
+`
const styles = theme => ({
main: {
maxWidth: 600,
- margin: "auto",
+ margin: 'auto',
marginTop: theme.spacing.unit * 4
}
-});
+})
-const List = withStyles(styles)(({ bugs, classes }) => (
+const List = withStyles(styles)(({bugs, classes}) => (
<main className={classes.main}>
- {bugs.edges.map(({ cursor, node }) => (
- <BugSummary bug={node} key={cursor} />
- ))}
+ <Table className={classes.table}>
+ <TableBody>
+ {bugs.edges.map(({ cursor, node }) => (
+ <BugSummary bug={node} key={cursor} />
+ ))}
+ </TableBody>
+ </Table>
</main>
-));
+))
const ListPage = () => (
<Query query={QUERY}>
- {({ loading, error, data }) => {
- if (loading) return <CircularProgress />;
- if (error) return <p>Error.</p>;
- return <List bugs={data.defaultRepository.bugs} />;
+ {({loading, error, data}) => {
+ if (loading) return <CircularProgress/>
+ if (error) return <p>Error.</p>
+ return <List bugs={data.defaultRepository.bugs}/>
}}
</Query>
-);
+)
-export default ListPage;
+export default ListPage
diff --git a/webui/src/index.js b/webui/src/index.js
index 80b2651d..c34cc7cc 100644
--- a/webui/src/index.js
+++ b/webui/src/index.js
@@ -1,23 +1,23 @@
-import React from "react";
-import ReactDOM from "react-dom";
-import { BrowserRouter } from "react-router-dom";
-import ApolloClient from "apollo-boost";
-import { ApolloProvider } from "react-apollo";
+import ApolloClient from 'apollo-boost'
+import React from 'react'
+import { ApolloProvider } from 'react-apollo'
+import ReactDOM from 'react-dom'
+import { BrowserRouter } from 'react-router-dom'
-import App from "./App";
+import App from './App'
const client = new ApolloClient({
uri: "/graphql",
connectToDevTools: true
-});
+})
ReactDOM.render(
<ApolloProvider client={client}>
<BrowserRouter>
<React.Fragment>
- <App />
+ <App/>
</React.Fragment>
</BrowserRouter>
</ApolloProvider>,
- document.getElementById("root")
-);
+ document.getElementById('root')
+)