ListPage.js

  1// @flow
  2import CircularProgress from '@material-ui/core/CircularProgress'
  3import { withStyles } from '@material-ui/core/styles'
  4import Table from '@material-ui/core/Table/Table'
  5import TableBody from '@material-ui/core/TableBody/TableBody'
  6import TablePagination from '@material-ui/core/TablePagination/TablePagination'
  7import gql from 'graphql-tag'
  8import React from 'react'
  9import { Query } from 'react-apollo'
 10
 11import BugSummary from './BugSummary'
 12
 13const QUERY = gql`
 14  query($first: Int = 10, $last: Int, $after: String, $before: String) {
 15    defaultRepository {
 16      bugs: allBugs(first: $first, last: $last, after: $after, before: $before) {
 17        totalCount
 18        edges {
 19          cursor
 20          node {
 21            ...BugSummary
 22          }
 23        }
 24        pageInfo{
 25          hasNextPage
 26          hasPreviousPage
 27          startCursor
 28          endCursor
 29        }
 30      }
 31    }
 32  }
 33
 34
 35  ${BugSummary.fragment}
 36`
 37
 38const styles = theme => ({
 39  main: {
 40    maxWidth: 600,
 41    margin: 'auto',
 42    marginTop: theme.spacing.unit * 4
 43  }
 44})
 45
 46const List = withStyles(styles)(class List extends React.Component {
 47
 48  props: {
 49    bugs: Array,
 50    fetchMore: (any) => any,
 51    classes: any,
 52  }
 53
 54  state = {
 55    page: 0,
 56    rowsPerPage: 10,
 57    lastQuery: {}
 58  }
 59
 60  handleChangePage = (event, page) => {
 61    const {bugs, fetchMore} = this.props
 62    const {rowsPerPage} = this.state
 63    const pageInfo = bugs.pageInfo
 64
 65    if (page === this.state.page + 1) {
 66      if (!pageInfo.hasNextPage) {
 67        return
 68      }
 69
 70      const variables = {
 71        after: pageInfo.endCursor,
 72        first: rowsPerPage
 73      }
 74
 75      fetchMore({
 76        variables,
 77        updateQuery: this.updateQuery,
 78      })
 79
 80      this.setState({page, lastQuery: variables})
 81      return
 82    }
 83
 84    if (page === this.state.page - 1) {
 85      if (!pageInfo.hasPreviousPage) {
 86        return
 87      }
 88
 89      const variables = {
 90        before: pageInfo.startCursor,
 91        last: rowsPerPage
 92      }
 93
 94      fetchMore({
 95        variables,
 96        updateQuery: this.updateQuery,
 97      })
 98
 99      this.setState({page, lastQuery: variables})
100      return
101    }
102
103    throw 'non neighbour page pagination is not supported'
104  }
105
106  handleChangeRowsPerPage = event => {
107    const {fetchMore} = this.props
108    const {lastQuery} = this.state
109    const rowsPerPage = event.target.value
110
111    const variables = lastQuery
112
113    if (lastQuery.first) {
114      variables.first = rowsPerPage
115    } else if (lastQuery.last) {
116      variables.last = rowsPerPage
117    } else {
118      variables.first = rowsPerPage
119    }
120
121    fetchMore({
122      variables,
123      updateQuery: this.updateQuery,
124    })
125
126    this.setState({rowsPerPage, lastQuery: variables})
127  }
128
129  updateQuery = (previousResult, {fetchMoreResult}) => {
130    console.log(fetchMoreResult)
131    return fetchMoreResult ? fetchMoreResult : previousResult
132  }
133
134  render() {
135    const {classes, bugs} = this.props
136    const {page, rowsPerPage} = this.state
137
138    return (
139      <main className={classes.main}>
140        <Table className={classes.table}>
141          <TableBody>
142            {bugs.edges.map(({cursor, node}) => (
143              <BugSummary bug={node} key={cursor}/>
144            ))}
145          </TableBody>
146        </Table>
147        <TablePagination
148          component="div"
149          count={bugs.totalCount}
150          rowsPerPage={rowsPerPage}
151          page={page}
152          backIconButtonProps={{
153            'aria-label': 'Previous Page'
154          }}
155          nextIconButtonProps={{
156            'aria-label': 'Next Page'
157          }}
158          onChangePage={this.handleChangePage}
159          onChangeRowsPerPage={this.handleChangeRowsPerPage}
160        />
161      </main>
162    )
163  }
164})
165
166const ListPage = () => (
167  <Query query={QUERY}>
168    {({loading, error, data, fetchMore}) => {
169      if (loading) return <CircularProgress/>
170      if (error) return <p>Error.</p>
171      return <List bugs={data.defaultRepository.bugs} fetchMore={fetchMore}/>
172    }}
173  </Query>
174)
175
176export default ListPage