From 2530cee1eac225924e1119554cf475cdc46ed7dc Mon Sep 17 00:00:00 2001 From: Michael Muré Date: Wed, 15 Aug 2018 15:50:19 +0200 Subject: webui: reorganize the code --- webui/src/list/BugRow.js | 102 ++++++++++++++++++++++++++++++++++ webui/src/list/List.js | 135 +++++++++++++++++++++++++++++++++++++++++++++ webui/src/list/ListPage.js | 45 +++++++++++++++ 3 files changed, 282 insertions(+) create mode 100644 webui/src/list/BugRow.js create mode 100644 webui/src/list/List.js create mode 100644 webui/src/list/ListPage.js (limited to 'webui/src/list') diff --git a/webui/src/list/BugRow.js b/webui/src/list/BugRow.js new file mode 100644 index 00000000..1ce5ea06 --- /dev/null +++ b/webui/src/list/BugRow.js @@ -0,0 +1,102 @@ +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 * as moment from 'moment' +import React from 'react' +import { Link } from 'react-router-dom' + +const Open = ({className}) => + + + +const Closed = ({className}) => + + + +const Status = ({status, className}) => { + switch (status) { + case 'OPEN': + return + case 'CLOSED': + return + default: + return 'unknown status ' + status + } +} + +const styles = theme => ({ + cell: { + display: 'flex', + alignItems: 'center' + }, + status: { + margin: 10 + }, + expand: { + width: '100%' + }, + 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 BugRow = ({bug, classes}) => ( + + + +
+ +
+ + + {bug.title} + + + {bug.labels.map(l => ( + {l}) + )} + +
+ + + {bug.humanId} opened + + {moment(bug.createdAt).fromNow()} + + by {bug.author.name} + +
+
+
+) + +BugRow.fragment = gql` + fragment BugRow on Bug { + id + humanId + title + status + createdAt + labels + author { + name + } + } +` + +export default withStyles(styles)(BugRow) diff --git a/webui/src/list/List.js b/webui/src/list/List.js new file mode 100644 index 00000000..880782c7 --- /dev/null +++ b/webui/src/list/List.js @@ -0,0 +1,135 @@ +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 + } +}) + +class List extends React.Component { + + props: { + bugs: Array, + fetchMore: (any) => any, + classes: any, + } + + state = { + page: 0, + rowsPerPage: 10, + lastQuery: {} + } + + handleChangePage = (event, page) => { + const {bugs, fetchMore} = this.props + const {rowsPerPage} = this.state + const pageInfo = bugs.pageInfo + + if (page === this.state.page + 1) { + if (!pageInfo.hasNextPage) { + return + } + + const variables = { + after: pageInfo.endCursor, + first: rowsPerPage + } + + fetchMore({ + variables, + updateQuery: this.updateQuery, + }) + + this.setState({page, lastQuery: variables}) + return + } + + if (page === this.state.page - 1) { + if (!pageInfo.hasPreviousPage) { + return + } + + const variables = { + before: pageInfo.startCursor, + last: rowsPerPage + } + + fetchMore({ + variables, + updateQuery: this.updateQuery, + }) + + this.setState({page, lastQuery: variables}) + return + } + + 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 variables = lastQuery + + if (lastQuery.first) { + variables.first = rowsPerPage + } else if (lastQuery.last) { + variables.last = rowsPerPage + } else { + variables.first = rowsPerPage + } + + fetchMore({ + variables, + updateQuery: this.updateQuery, + }) + + this.setState({rowsPerPage, lastQuery: variables}) + } + + updateQuery = (previousResult, {fetchMoreResult}) => { + return fetchMoreResult ? fetchMoreResult : previousResult + } + + render() { + const {classes, bugs} = this.props + const {page, rowsPerPage} = this.state + + return ( +
+ + + {bugs.edges.map(({cursor, node}) => ( + + ))} + +
+ +
+ ) + } +} + +export default withStyles(styles)(List) diff --git a/webui/src/list/ListPage.js b/webui/src/list/ListPage.js new file mode 100644 index 00000000..b7de735f --- /dev/null +++ b/webui/src/list/ListPage.js @@ -0,0 +1,45 @@ +// @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' + +const QUERY = gql` + query($first: Int = 10, $last: Int, $after: String, $before: String) { + defaultRepository { + bugs: allBugs(first: $first, last: $last, after: $after, before: $before) { + totalCount + edges { + cursor + node { + ...BugRow + } + } + pageInfo{ + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } + } + } + + + ${BugRow.fragment} +` + +const ListPage = () => ( + + {({loading, error, data, fetchMore}) => { + if (loading) return + if (error) return

Error.

+ return + }} +
+) + +export default ListPage -- cgit