diff options
-rw-r--r-- | .travis.yml | 22 | ||||
-rw-r--r-- | webui/.eslintrc | 3 | ||||
-rw-r--r-- | webui/.prettierrc | 4 | ||||
-rw-r--r-- | webui/Makefile | 11 | ||||
-rw-r--r-- | webui/package-lock.json | 47 | ||||
-rw-r--r-- | webui/package.json | 8 | ||||
-rw-r--r-- | webui/src/App.js | 38 | ||||
-rw-r--r-- | webui/src/Author.js | 22 | ||||
-rw-r--r-- | webui/src/Date.js | 12 | ||||
-rw-r--r-- | webui/src/Label.js | 32 | ||||
-rw-r--r-- | webui/src/bug/Bug.js | 52 | ||||
-rw-r--r-- | webui/src/bug/BugQuery.js | 28 | ||||
-rw-r--r-- | webui/src/bug/LabelChange.js | 48 | ||||
-rw-r--r-- | webui/src/bug/Message.js | 26 | ||||
-rw-r--r-- | webui/src/bug/SetStatus.js | 25 | ||||
-rw-r--r-- | webui/src/bug/SetTitle.js | 28 | ||||
-rw-r--r-- | webui/src/bug/Timeline.js | 47 | ||||
-rw-r--r-- | webui/src/bug/TimelineQuery.js | 41 | ||||
-rw-r--r-- | webui/src/index.js | 22 | ||||
-rw-r--r-- | webui/src/list/BugRow.js | 54 | ||||
-rw-r--r-- | webui/src/list/List.js | 103 | ||||
-rw-r--r-- | webui/src/list/ListQuery.js | 36 |
22 files changed, 400 insertions, 309 deletions
diff --git a/.travis.yml b/.travis.yml index 50e9672a..521902f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,14 @@ -language: go - -go: - - "1.9" - - "1.10.x" - -before_install: - - go get github.com/mitchellh/gox +matrix: + include: + - language: go + go: "1.9" + - language: go + go: "1.10.x" + - language: node_js + node_js: 8 + before_install: + - cd webui + after_success: [] install: - make install @@ -13,6 +16,9 @@ install: script: - make test +before_install: + - go get github.com/mitchellh/gox + after_success: - if [ ! -z "$TRAVIS_TAG" ]; then gox -tags=deploy_build -output "dist/{{.Dir}}_{{.OS}}_{{.Arch}}"; fi diff --git a/webui/.eslintrc b/webui/.eslintrc new file mode 100644 index 00000000..9cf9d009 --- /dev/null +++ b/webui/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": ["react-app", "plugin:prettier/recommended"] +} diff --git a/webui/.prettierrc b/webui/.prettierrc new file mode 100644 index 00000000..c1a6f667 --- /dev/null +++ b/webui/.prettierrc @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "trailingComma": "es5" +} diff --git a/webui/Makefile b/webui/Makefile new file mode 100644 index 00000000..1f023cc9 --- /dev/null +++ b/webui/Makefile @@ -0,0 +1,11 @@ +start: + npm start + +install: + npm install + +test: + npm run lint + +build: + npm run build diff --git a/webui/package-lock.json b/webui/package-lock.json index 58af97ae..174ff2ed 100644 --- a/webui/package-lock.json +++ b/webui/package-lock.json @@ -3366,6 +3366,23 @@ } } }, + "eslint-config-prettier": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-3.0.1.tgz", + "integrity": "sha512-vA0TB8HCx/idHXfKHYcg9J98p0Q8nkfNwNAoP7e+ywUidn6ScaFS5iqncZAHPz+/a0A/tp657ulFHFx/2JDP4Q==", + "dev": true, + "requires": { + "get-stdin": "^6.0.0" + }, + "dependencies": { + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + } + } + }, "eslint-config-react-app": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-2.1.0.tgz", @@ -3521,6 +3538,24 @@ "jsx-ast-utils": "^1.4.0" } }, + "eslint-plugin-prettier": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.2.tgz", + "integrity": "sha512-tGek5clmW5swrAx1mdPYM8oThrBE83ePh7LeseZHBWfHVGrHPhKn7Y5zgRMbU/9D5Td9K4CEmUPjGxA7iw98Og==", + "dev": true, + "requires": { + "fast-diff": "^1.1.1", + "jest-docblock": "^21.0.0" + }, + "dependencies": { + "jest-docblock": { + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-21.2.0.tgz", + "integrity": "sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw==", + "dev": true + } + } + }, "eslint-plugin-react": { "version": "7.4.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.4.0.tgz", @@ -3913,6 +3948,12 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, + "fast-diff": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz", + "integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==", + "dev": true + }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", @@ -9016,6 +9057,12 @@ "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" }, + "prettier": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.14.2.tgz", + "integrity": "sha512-McHPg0n1pIke+A/4VcaS2en+pTNjy4xF+Uuq86u/5dyDO59/TtFZtQ708QIRkEZ3qwKz3GVkVa6mpxK/CpB8Rg==", + "dev": true + }, "pretty-bytes": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", diff --git a/webui/package.json b/webui/package.json index 54deb684..58f90dee 100644 --- a/webui/package.json +++ b/webui/package.json @@ -15,11 +15,17 @@ "react-router-dom": "^4.3.1", "react-scripts": "1.1.4" }, + "devDependencies": { + "eslint-config-prettier": "^3.0.1", + "eslint-plugin-prettier": "^2.6.2", + "prettier": "1.14.2" + }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", - "eject": "react-scripts eject" + "eject": "react-scripts eject", + "lint": "eslint src/" }, "proxy": "http://localhost:3001" } diff --git a/webui/src/App.js b/webui/src/App.js index 47a31e45..3a693dcb 100644 --- a/webui/src/App.js +++ b/webui/src/App.js @@ -1,25 +1,25 @@ -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 { 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 BugQuery from './bug/BugQuery' -import ListQuery from './list/ListQuery' +import BugQuery from './bug/BugQuery'; +import ListQuery from './list/ListQuery'; const styles = theme => ({ appTitle: { color: 'white', - textDecoration: 'none' - } -}) + 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}> @@ -30,10 +30,10 @@ const App = ({location, classes}) => ( </Toolbar> </AppBar> <Switch> - <Route path="/" exact component={ListQuery}/> - <Route path="/bug/:id" exact component={BugQuery}/> + <Route path="/" exact component={ListQuery} /> + <Route path="/bug/:id" exact component={BugQuery} /> </Switch> </React.Fragment> -) +); -export default withStyles(styles)(withRouter(App)) +export default withStyles(styles)(withRouter(App)); diff --git a/webui/src/Author.js b/webui/src/Author.js index 37de7aa7..0ad7e257 100644 --- a/webui/src/Author.js +++ b/webui/src/Author.js @@ -1,24 +1,24 @@ -import Tooltip from '@material-ui/core/Tooltip/Tooltip' -import React from 'react' -import { withStyles } from '@material-ui/core/styles' +import Tooltip from '@material-ui/core/Tooltip/Tooltip'; +import React from 'react'; +import { withStyles } from '@material-ui/core/styles'; const styles = theme => ({ author: { ...theme.typography.body2, }, bold: { - fontWeight: 'bold' - } -}) + fontWeight: 'bold', + }, +}); -const Author = ({author, bold, classes}) => { - const klass = bold ? [classes.author, classes.bold] : [classes.author] +const Author = ({ author, bold, classes }) => { + const klass = bold ? [classes.author, classes.bold] : [classes.author]; return ( <Tooltip title={author.email}> <span className={klass.join(' ')}>{author.name}</span> </Tooltip> - ) -} + ); +}; -export default withStyles(styles)(Author) +export default withStyles(styles)(Author); diff --git a/webui/src/Date.js b/webui/src/Date.js index b20fd274..46741924 100644 --- a/webui/src/Date.js +++ b/webui/src/Date.js @@ -1,11 +1,11 @@ -import Tooltip from '@material-ui/core/Tooltip/Tooltip' -import * as moment from 'moment' -import React from 'react' +import Tooltip from '@material-ui/core/Tooltip/Tooltip'; +import * as moment from 'moment'; +import React from 'react'; -const Date = ({date}) => ( +const Date = ({ date }) => ( <Tooltip title={moment(date).format('MMMM D, YYYY, h:mm a')}> <span> {moment(date).fromNow()} </span> </Tooltip> -) +); -export default Date +export default Date; diff --git a/webui/src/Label.js b/webui/src/Label.js index 8981142d..e7c25c23 100644 --- a/webui/src/Label.js +++ b/webui/src/Label.js @@ -1,11 +1,11 @@ -import React from "react"; -import { withStyles } from "@material-ui/core/styles"; +import React from 'react'; +import { withStyles } from '@material-ui/core/styles'; import { getContrastRatio, - darken -} from "@material-ui/core/styles/colorManipulator"; -import * as allColors from "@material-ui/core/colors"; -import { common } from "@material-ui/core/colors"; + darken, +} from '@material-ui/core/styles/colorManipulator'; +import * as allColors from '@material-ui/core/colors'; +import { common } from '@material-ui/core/colors'; // JS's modulo returns negative numbers sometimes. // This ensures the result is positive. @@ -21,7 +21,7 @@ const labelColors = Object.entries(allColors) // Generate a hash (number) from a string const hash = string => - string.split("").reduce((a, b) => ((a << 5) - a + b.charCodeAt(0)) | 0, 0); + string.split('').reduce((a, b) => ((a << 5) - a + b.charCodeAt(0)) | 0, 0); // Get the background color from the label const getColor = label => @@ -36,7 +36,7 @@ const getTextColor = background => const _genStyle = background => ({ backgroundColor: background, color: getTextColor(background), - borderBottomColor: darken(background, 0.2) + borderBottomColor: darken(background, 0.2), }); // Generate a style object (text, background and border colors) from the label @@ -45,14 +45,14 @@ const genStyle = label => _genStyle(getColor(label)); const styles = theme => ({ label: { ...theme.typography.body2, - padding: "0 6px", - fontSize: "0.9em", - margin: "0 1px", - borderRadius: "3px", - display: "inline-block", - borderBottom: "solid 1.5px", - verticalAlign: "bottom" - } + padding: '0 6px', + fontSize: '0.9em', + margin: '0 1px', + borderRadius: '3px', + display: 'inline-block', + borderBottom: 'solid 1.5px', + verticalAlign: 'bottom', + }, }); const Label = ({ label, classes }) => ( diff --git a/webui/src/bug/Bug.js b/webui/src/bug/Bug.js index c6edda35..329fdd72 100644 --- a/webui/src/bug/Bug.js +++ b/webui/src/bug/Bug.js @@ -1,49 +1,49 @@ -import { withStyles } from "@material-ui/core/styles"; -import Typography from "@material-ui/core/Typography/Typography"; -import gql from "graphql-tag"; -import React from "react"; -import Author from "../Author"; -import Date from "../Date"; -import TimelineQuery from "./TimelineQuery"; -import Label from "../Label"; +import { withStyles } from '@material-ui/core/styles'; +import Typography from '@material-ui/core/Typography/Typography'; +import gql from 'graphql-tag'; +import React from 'react'; +import Author from '../Author'; +import Date from '../Date'; +import TimelineQuery from './TimelineQuery'; +import Label from '../Label'; const styles = theme => ({ main: { maxWidth: 600, - margin: "auto", - marginTop: theme.spacing.unit * 4 + margin: 'auto', + marginTop: theme.spacing.unit * 4, }, header: {}, title: { - ...theme.typography.headline + ...theme.typography.headline, }, id: { ...theme.typography.subheading, - marginLeft: 15 + marginLeft: 15, }, container: { - display: "flex", - marginBottom: 30 + display: 'flex', + marginBottom: 30, }, timeline: { - width: "70%", + width: '70%', marginTop: 20, - marginRight: 20 + marginRight: 20, }, sidebar: { - width: "30%" + width: '30%', }, labelList: { - listStyle: "none", + listStyle: 'none', padding: 0, - margin: 0 + margin: 0, }, label: { - margin: "4px 0", - "& > *": { - display: "block" - } - } + margin: '4px 0', + '& > *': { + display: 'block', + }, + }, }); const Bug = ({ bug, classes }) => ( @@ -52,7 +52,7 @@ const Bug = ({ bug, classes }) => ( <span className={classes.title}>{bug.title}</span> <span className={classes.id}>{bug.humanId}</span> - <Typography color={"textSecondary"}> + <Typography color={'textSecondary'}> <Author author={bug.author} /> <span> opened this bug </span> <Date date={bug.createdAt} /> @@ -64,7 +64,7 @@ const Bug = ({ bug, classes }) => ( <TimelineQuery id={bug.id} /> </div> <div className={classes.sidebar}> - <Typography variant={"subheading"}>Labels</Typography> + <Typography variant={'subheading'}>Labels</Typography> <ul className={classes.labelList}> {bug.labels.map(l => ( <li className={classes.label}> diff --git a/webui/src/bug/BugQuery.js b/webui/src/bug/BugQuery.js index 22421414..dbf24c31 100644 --- a/webui/src/bug/BugQuery.js +++ b/webui/src/bug/BugQuery.js @@ -1,9 +1,9 @@ -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 gql from 'graphql-tag'; +import React from 'react'; +import { Query } from 'react-apollo'; -import Bug from './Bug' +import Bug from './Bug'; const QUERY = gql` query GetBug($id: String!) { @@ -15,16 +15,16 @@ const QUERY = gql` } ${Bug.fragment} -` +`; -const BugQuery = ({match}) => ( - <Query query={QUERY} variables={{id: match.params.id}}> - {({loading, error, data}) => { - if (loading) return <CircularProgress/> - if (error) return <p>Error: {error}</p> - return <Bug bug={data.defaultRepository.bug}/> +const BugQuery = ({ match }) => ( + <Query query={QUERY} variables={{ id: match.params.id }}> + {({ loading, error, data }) => { + if (loading) return <CircularProgress />; + if (error) return <p>Error: {error}</p>; + return <Bug bug={data.defaultRepository.bug} />; }} </Query> -) +); -export default BugQuery +export default BugQuery; diff --git a/webui/src/bug/LabelChange.js b/webui/src/bug/LabelChange.js index f954372a..bb546678 100644 --- a/webui/src/bug/LabelChange.js +++ b/webui/src/bug/LabelChange.js @@ -1,31 +1,39 @@ -import { withStyles } from '@material-ui/core/styles' -import gql from 'graphql-tag' -import React from 'react' -import Author from '../Author' -import Date from '../Date' -import Label from '../Label' +import { withStyles } from '@material-ui/core/styles'; +import gql from 'graphql-tag'; +import React from 'react'; +import Author from '../Author'; +import Date from '../Date'; +import Label from '../Label'; const styles = theme => ({ main: { - ...theme.typography.body2 + ...theme.typography.body2, }, -}) +}); -const LabelChange = ({op, classes}) => { - const {added, removed} = op +const LabelChange = ({ op, classes }) => { + const { added, removed } = op; return ( <div className={classes.main}> <Author author={op.author} bold /> - { added.length > 0 && <span> added the </span>} - { added.map((label, index) => <Label key={index} label={label} />)} - { (added.length > 0 && removed.length > 0) && <span> and</span>} - { removed.length > 0 && <span> removed the </span>} - { removed.map((label, index) => <Label key={index} label={label} />)} - <span> label{ (added.length + removed.length > 1) && 's'} </span> + {added.length > 0 && <span> added the </span>} + {added.map((label, index) => ( + <Label key={index} label={label} /> + ))} + {added.length > 0 && removed.length > 0 && <span> and</span>} + {removed.length > 0 && <span> removed the </span>} + {removed.map((label, index) => ( + <Label key={index} label={label} /> + ))} + <span> + {' '} + label + {added.length + removed.length > 1 && 's'}{' '} + </span> <Date date={op.date} /> </div> - ) -} + ); +}; LabelChange.fragment = gql` fragment LabelChange on Operation { @@ -39,6 +47,6 @@ LabelChange.fragment = gql` removed } } -` +`; -export default withStyles(styles)(LabelChange) +export default withStyles(styles)(LabelChange); diff --git a/webui/src/bug/Message.js b/webui/src/bug/Message.js index 2a96e52d..2d03e780 100644 --- a/webui/src/bug/Message.js +++ b/webui/src/bug/Message.js @@ -1,9 +1,9 @@ -import { withStyles } from '@material-ui/core/styles' -import Typography from '@material-ui/core/Typography' -import gql from 'graphql-tag' -import React from 'react' -import Author from '../Author' -import Date from '../Date' +import { withStyles } from '@material-ui/core/styles'; +import Typography from '@material-ui/core/Typography'; +import gql from 'graphql-tag'; +import React from 'react'; +import Author from '../Author'; +import Date from '../Date'; const styles = theme => ({ header: { @@ -24,10 +24,10 @@ const styles = theme => ({ minHeight: 50, padding: 5, whiteSpace: 'pre-wrap', - } -}) + }, +}); -const Message = ({op, classes}) => ( +const Message = ({ op, classes }) => ( <div> <div className={classes.header}> <Author className={classes.author} author={op.author} bold /> @@ -38,7 +38,7 @@ const Message = ({op, classes}) => ( <Typography>{op.message}</Typography> </div> </div> -) +); Message.createFragment = gql` fragment Create on Operation { @@ -51,7 +51,7 @@ Message.createFragment = gql` message } } -` +`; Message.commentFragment = gql` fragment Comment on Operation { @@ -64,6 +64,6 @@ Message.commentFragment = gql` message } } -` +`; -export default withStyles(styles)(Message) +export default withStyles(styles)(Message); diff --git a/webui/src/bug/SetStatus.js b/webui/src/bug/SetStatus.js index eb41fc28..7d6bccf3 100644 --- a/webui/src/bug/SetStatus.js +++ b/webui/src/bug/SetStatus.js @@ -1,25 +1,24 @@ -import { withStyles } from '@material-ui/core/styles' -import gql from 'graphql-tag' -import React from 'react' -import Author from '../Author' -import Date from '../Date' +import { withStyles } from '@material-ui/core/styles'; +import gql from 'graphql-tag'; +import React from 'react'; +import Author from '../Author'; +import Date from '../Date'; const styles = theme => ({ main: { - ...theme.typography.body2 + ...theme.typography.body2, }, -}) - -const SetStatus = ({op, classes}) => { +}); +const SetStatus = ({ op, classes }) => { return ( <div className={classes.main}> <Author author={op.author} bold /> <span> {op.status.toLowerCase()} this</span> <Date date={op.date} /> </div> - ) -} + ); +}; SetStatus.fragment = gql` fragment SetStatus on Operation { @@ -32,6 +31,6 @@ SetStatus.fragment = gql` status } } -` +`; -export default withStyles(styles)(SetStatus) +export default withStyles(styles)(SetStatus); diff --git a/webui/src/bug/SetTitle.js b/webui/src/bug/SetTitle.js index b6bb8b70..838219e2 100644 --- a/webui/src/bug/SetTitle.js +++ b/webui/src/bug/SetTitle.js @@ -1,19 +1,19 @@ -import { withStyles } from '@material-ui/core/styles' -import gql from 'graphql-tag' -import React from 'react' -import Author from '../Author' -import Date from '../Date' +import { withStyles } from '@material-ui/core/styles'; +import gql from 'graphql-tag'; +import React from 'react'; +import Author from '../Author'; +import Date from '../Date'; const styles = theme => ({ main: { - ...theme.typography.body2 + ...theme.typography.body2, }, bold: { - fontWeight: 'bold' - } -}) + fontWeight: 'bold', + }, +}); -const SetTitle = ({op, classes}) => { +const SetTitle = ({ op, classes }) => { return ( <div className={classes.main}> <Author author={op.author} bold /> @@ -23,8 +23,8 @@ const SetTitle = ({op, classes}) => { <span className={classes.bold}>{op.title}</span> <Date date={op.date} /> </div> - ) -} + ); +}; SetTitle.fragment = gql` fragment SetTitle on Operation { @@ -38,6 +38,6 @@ SetTitle.fragment = gql` was } } -` +`; -export default withStyles(styles)(SetTitle) +export default withStyles(styles)(SetTitle); diff --git a/webui/src/bug/Timeline.js b/webui/src/bug/Timeline.js index a15409ab..d331d11d 100644 --- a/webui/src/bug/Timeline.js +++ b/webui/src/bug/Timeline.js @@ -1,52 +1,51 @@ -import { withStyles } from '@material-ui/core/styles' -import React from 'react' -import LabelChange from './LabelChange' -import Message from './Message' -import SetStatus from './SetStatus' -import SetTitle from './SetTitle' +import { withStyles } from '@material-ui/core/styles'; +import React from 'react'; +import LabelChange from './LabelChange'; +import Message from './Message'; +import SetStatus from './SetStatus'; +import SetTitle from './SetTitle'; const styles = theme => ({ main: { '& > *:not(:last-child)': { - marginBottom: 10 - } - } -}) + marginBottom: 10, + }, + }, +}); class Timeline extends React.Component { - props: { ops: Array, - fetchMore: (any) => any, + fetchMore: any => any, classes: any, - } + }; render() { - const {ops, classes} = this.props + const { ops, classes } = this.props; return ( <div className={classes.main}> - { ops.map((op, index) => { + {ops.map((op, index) => { switch (op.__typename) { case 'CreateOperation': - return <Message key={index} op={op}/> + return <Message key={index} op={op} />; case 'AddCommentOperation': - return <Message key={index} op={op}/> + return <Message key={index} op={op} />; case 'LabelChangeOperation': - return <LabelChange key={index} op={op}/> + return <LabelChange key={index} op={op} />; case 'SetTitleOperation': - return <SetTitle key={index} op={op}/> + return <SetTitle key={index} op={op} />; case 'SetStatusOperation': - return <SetStatus key={index} op={op}/> + return <SetStatus key={index} op={op} />; default: - console.log('unsupported operation type ' + op.__typename) - return null + console.log('unsupported operation type ' + op.__typename); + return null; } })} </div> - ) + ); } } -export default withStyles(styles)(Timeline) +export default withStyles(styles)(Timeline); diff --git a/webui/src/bug/TimelineQuery.js b/webui/src/bug/TimelineQuery.js index 3ee4cb28..78658a6f 100644 --- a/webui/src/bug/TimelineQuery.js +++ b/webui/src/bug/TimelineQuery.js @@ -1,12 +1,12 @@ -import CircularProgress from '@material-ui/core/CircularProgress' -import gql from 'graphql-tag' -import React from 'react' -import { Query } from 'react-apollo' -import LabelChange from './LabelChange' -import SetStatus from './SetStatus' -import SetTitle from './SetTitle' -import Timeline from './Timeline' -import Message from './Message' +import CircularProgress from '@material-ui/core/CircularProgress'; +import gql from 'graphql-tag'; +import React from 'react'; +import { Query } from 'react-apollo'; +import LabelChange from './LabelChange'; +import SetStatus from './SetStatus'; +import SetTitle from './SetTitle'; +import Timeline from './Timeline'; +import Message from './Message'; const QUERY = gql` query($id: String!, $first: Int = 10, $after: String) { @@ -33,16 +33,21 @@ const QUERY = gql` ${LabelChange.fragment} ${SetTitle.fragment} ${SetStatus.fragment} -` +`; -const TimelineQuery = ({id}) => ( - <Query query={QUERY} variables={{id, first: 100}}> - {({loading, error, data, fetchMore}) => { - if (loading) return <CircularProgress/> - if (error) return <p>Error: {error}</p> - return <Timeline ops={data.defaultRepository.bug.operations.nodes} fetchMore={fetchMore}/> +const TimelineQuery = ({ id }) => ( + <Query query={QUERY} variables={{ id, first: 100 }}> + {({ loading, error, data, fetchMore }) => { + if (loading) return <CircularProgress />; + if (error) return <p>Error: {error}</p>; + return ( + <Timeline + ops={data.defaultRepository.bug.operations.nodes} + fetchMore={fetchMore} + /> + ); }} </Query> -) +); -export default TimelineQuery +export default TimelineQuery; diff --git a/webui/src/index.js b/webui/src/index.js index c34cc7cc..f5d95ccc 100644 --- a/webui/src/index.js +++ b/webui/src/index.js @@ -1,23 +1,23 @@ -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 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 -}) + uri: '/graphql', + connectToDevTools: true, +}); ReactDOM.render( <ApolloProvider client={client}> <BrowserRouter> <React.Fragment> - <App/> + <App /> </React.Fragment> </BrowserRouter> </ApolloProvider>, document.getElementById('root') -) +); diff --git a/webui/src/list/BugRow.js b/webui/src/list/BugRow.js index 05eafe92..9253cc88 100644 --- a/webui/src/list/BugRow.js +++ b/webui/src/list/BugRow.js @@ -1,14 +1,14 @@ -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 Date from "../Date"; -import Label from "../Label"; +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 Date from '../Date'; +import Label from '../Label'; const Open = ({ className }) => ( <Tooltip title="Open"> @@ -24,35 +24,35 @@ const Closed = ({ className }) => ( const Status = ({ status, className }) => { switch (status) { - case "OPEN": + case 'OPEN': return <Open className={className} />; - case "CLOSED": + case 'CLOSED': return <Closed className={className} />; default: - return "unknown status " + status; + return 'unknown status ' + status; } }; const styles = theme => ({ cell: { - display: "flex", - alignItems: "center", - "& a": { - textDecoration: "none" - } + display: 'flex', + alignItems: 'center', + '& a': { + textDecoration: 'none', + }, }, status: { - margin: 10 + margin: 10, }, expand: { - width: "100%" + width: '100%', }, title: { - display: "inline" + display: 'inline', }, labels: { - paddingLeft: theme.spacing.unit - } + paddingLeft: theme.spacing.unit, + }, }); const BugRow = ({ bug, classes }) => ( @@ -60,9 +60,9 @@ const BugRow = ({ bug, classes }) => ( <TableCell className={classes.cell}> <Status status={bug.status} className={classes.status} /> <div className={classes.expand}> - <Link to={"bug/" + bug.humanId}> + <Link to={'bug/' + bug.humanId}> <div className={classes.expand}> - <Typography variant={"title"} className={classes.title}> + <Typography variant={'title'} className={classes.title}> {bug.title} </Typography> {bug.labels.length > 0 && ( @@ -74,7 +74,7 @@ const BugRow = ({ bug, classes }) => ( )} </div> </Link> - <Typography color={"textSecondary"}> + <Typography color={'textSecondary'}> {bug.humanId} opened <Date date={bug.createdAt} /> by {bug.author.name} diff --git a/webui/src/list/List.js b/webui/src/list/List.js index 880782c7..d36be8a1 100644 --- a/webui/src/list/List.js +++ b/webui/src/list/List.js @@ -1,115 +1,114 @@ -import { withStyles } from '@material-ui/core/styles' -import Table from '@material-ui/core/Table/Table' -import TableBody from '@material-ui/core/TableBody/TableBody' -import TablePagination from '@material-ui/core/TablePagination/TablePagination' -import React from 'react' -import BugRow from './BugRow' +import { withStyles } from '@material-ui/core/styles'; +import Table from '@material-ui/core/Table/Table'; +import TableBody from '@material-ui/core/TableBody/TableBody'; +import TablePagination from '@material-ui/core/TablePagination/TablePagination'; +import React from 'react'; +import BugRow from './BugRow'; const styles = theme => ({ main: { maxWidth: 600, margin: 'auto', - marginTop: theme.spacing.unit * 4 - } -}) + marginTop: theme.spacing.unit * 4, + }, +}); class List extends React.Component { - props: { bugs: Array, - fetchMore: (any) => any, + fetchMore: any => any, classes: any, - } + }; state = { page: 0, rowsPerPage: 10, - lastQuery: {} - } + lastQuery: {}, + }; handleChangePage = (event, page) => { - const {bugs, fetchMore} = this.props - const {rowsPerPage} = this.state - const pageInfo = bugs.pageInfo + const { bugs, fetchMore } = this.props; + const { rowsPerPage } = this.state; + const pageInfo = bugs.pageInfo; if (page === this.state.page + 1) { if (!pageInfo.hasNextPage) { - return + return; } const variables = { after: pageInfo.endCursor, - first: rowsPerPage - } + first: rowsPerPage, + }; fetchMore({ variables, updateQuery: this.updateQuery, - }) + }); - this.setState({page, lastQuery: variables}) - return + this.setState({ page, lastQuery: variables }); + return; } if (page === this.state.page - 1) { if (!pageInfo.hasPreviousPage) { - return + return; } const variables = { before: pageInfo.startCursor, - last: rowsPerPage - } + last: rowsPerPage, + }; fetchMore({ variables, updateQuery: this.updateQuery, - }) + }); - this.setState({page, lastQuery: variables}) - return + this.setState({ page, lastQuery: variables }); + return; } - throw new Error('non neighbour page pagination is not supported') - } + throw new Error('non neighbour page pagination is not supported'); + }; handleChangeRowsPerPage = event => { - const {fetchMore} = this.props - const {lastQuery} = this.state - const rowsPerPage = event.target.value + const { fetchMore } = this.props; + const { lastQuery } = this.state; + const rowsPerPage = event.target.value; - const variables = lastQuery + const variables = lastQuery; if (lastQuery.first) { - variables.first = rowsPerPage + variables.first = rowsPerPage; } else if (lastQuery.last) { - variables.last = rowsPerPage + variables.last = rowsPerPage; } else { - variables.first = rowsPerPage + variables.first = rowsPerPage; } fetchMore({ variables, updateQuery: this.updateQuery, - }) + }); - this.setState({rowsPerPage, lastQuery: variables}) - } + this.setState({ rowsPerPage, lastQuery: variables }); + }; - updateQuery = (previousResult, {fetchMoreResult}) => { - return fetchMoreResult ? fetchMoreResult : previousResult - } + updateQuery = (previousResult, { fetchMoreResult }) => { + return fetchMoreResult ? fetchMoreResult : previousResult; + }; render() { - const {classes, bugs} = this.props - const {page, rowsPerPage} = this.state + const { classes, bugs } = this.props; + const { page, rowsPerPage } = this.state; return ( <main className={classes.main}> <Table className={classes.table}> <TableBody> - {bugs.edges.map(({cursor, node}) => ( - <BugRow bug={node} key={cursor}/> + {bugs.edges.map(({ cursor, node }) => ( + <BugRow bug={node} key={cursor} /> ))} </TableBody> </Table> @@ -119,17 +118,17 @@ class List extends React.Component { rowsPerPage={rowsPerPage} page={page} backIconButtonProps={{ - 'aria-label': 'Previous Page' + 'aria-label': 'Previous Page', }} nextIconButtonProps={{ - 'aria-label': 'Next Page' + 'aria-label': 'Next Page', }} onChangePage={this.handleChangePage} onChangeRowsPerPage={this.handleChangeRowsPerPage} /> </main> - ) + ); } } -export default withStyles(styles)(List) +export default withStyles(styles)(List); diff --git a/webui/src/list/ListQuery.js b/webui/src/list/ListQuery.js index 3b57fcc2..9dbe4e53 100644 --- a/webui/src/list/ListQuery.js +++ b/webui/src/list/ListQuery.js @@ -1,15 +1,20 @@ // @flow -import CircularProgress from '@material-ui/core/CircularProgress' -import gql from 'graphql-tag' -import React from 'react' -import { Query } from 'react-apollo' -import BugRow from './BugRow' -import List from './List' +import CircularProgress from '@material-ui/core/CircularProgress'; +import gql from 'graphql-tag'; +import React from 'react'; +import { Query } from 'react-apollo'; +import BugRow from './BugRow'; +import List from './List'; const QUERY = gql` query($first: Int = 10, $last: Int, $after: String, $before: String) { defaultRepository { - bugs: allBugs(first: $first, last: $last, after: $after, before: $before) { + bugs: allBugs( + first: $first + last: $last + after: $after + before: $before + ) { totalCount edges { cursor @@ -17,7 +22,7 @@ const QUERY = gql` ...BugRow } } - pageInfo{ + pageInfo { hasNextPage hasPreviousPage startCursor @@ -27,18 +32,17 @@ const QUERY = gql` } } - ${BugRow.fragment} -` +`; const ListQuery = () => ( <Query query={QUERY}> - {({loading, error, data, fetchMore}) => { - if (loading) return <CircularProgress/> - if (error) return <p>Error: {error}</p> - return <List bugs={data.defaultRepository.bugs} fetchMore={fetchMore}/> + {({ loading, error, data, fetchMore }) => { + if (loading) return <CircularProgress />; + if (error) return <p>Error: {error}</p>; + return <List bugs={data.defaultRepository.bugs} fetchMore={fetchMore} />; }} </Query> -) +); -export default ListQuery +export default ListQuery; |