-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
2,146 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import React from 'react'; | ||
import Container from 'react-bootstrap/Container'; | ||
import Row from 'react-bootstrap/Row'; | ||
import Col from 'react-bootstrap/Col'; | ||
import SEO from 'components/SEO'; | ||
import AuthorsContainer from './authors/AuthorsContainer'; | ||
|
||
const Authors: React.FC = () => { | ||
return ( | ||
<SEO title="Authors" description="List of Authors implemented in React and Relay."> | ||
<Container> | ||
<Row> | ||
<Col> | ||
<h1>Authors</h1> | ||
</Col> | ||
</Row> | ||
<AuthorsContainer /> | ||
</Container> | ||
</SEO> | ||
); | ||
}; | ||
|
||
export default Authors; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import React from 'react' | ||
import { createFragmentContainer } from 'react-relay'; | ||
import { graphql } from 'babel-plugin-relay/macro'; | ||
import { Author } from '../../types/Author'; | ||
|
||
interface Props { | ||
author: Author; | ||
} | ||
|
||
const AuthorRow = ({ author }: Props) => ( | ||
<> | ||
<td>{author._id}</td> | ||
<td>{author.firstName}</td> | ||
<td>{author.lastName}</td> | ||
</> | ||
); | ||
|
||
const AuthorRowFragmentContainer = createFragmentContainer(AuthorRow, { | ||
author: graphql` | ||
fragment AuthorRow_author on Author { | ||
_id | ||
firstName | ||
lastName | ||
} | ||
` | ||
}); | ||
|
||
export default AuthorRowFragmentContainer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
import React from 'react'; | ||
import Alert from 'react-bootstrap/Alert'; | ||
import Spinner from 'react-bootstrap/Spinner'; | ||
import Button from 'react-bootstrap/Button'; | ||
import Row from 'react-bootstrap/Row'; | ||
import Col from 'react-bootstrap/Col'; | ||
import { QueryRenderer, createPaginationContainer } from 'react-relay'; | ||
import { graphql } from 'babel-plugin-relay/macro'; | ||
import environment from 'environment'; | ||
import AuthorsTable from './AuthorsTable'; | ||
import Filter from './Filter'; | ||
import { Author } from '../../types/Author'; | ||
|
||
interface Props { | ||
authors: { | ||
authors: { | ||
edges: Array<{ | ||
node: Author | ||
}> | ||
}, | ||
}; | ||
relay: any; | ||
} | ||
|
||
const refetch = (relay: any, values: any) => { | ||
relay.refetchConnection( | ||
10, | ||
(error: any) => { | ||
console.log(error); | ||
}, | ||
values, | ||
); | ||
}; | ||
|
||
const Authors: React.FC<Props> = (props: Props) => ( | ||
<> | ||
<Row className="mt-4 mb-4"> | ||
<Col> | ||
<Filter onUpdate={(values: any) => refetch(props.relay, values)} /> | ||
</Col> | ||
</Row> | ||
<AuthorsTable authors={props.authors.authors.edges.map(edge => edge.node)} /> | ||
<Row className="mt-4"> | ||
<Col> | ||
{ | ||
props.relay.hasMore() && | ||
<Button onClick={() => props.relay.loadMore(9, null)}>Load more</Button> | ||
} | ||
</Col> | ||
</Row> | ||
</> | ||
); | ||
|
||
const AuthorsContainer = createPaginationContainer( | ||
Authors, | ||
{ | ||
authors: graphql` | ||
fragment AuthorsContainer_authors on Query { | ||
authors ( | ||
first: $first | ||
after: $after | ||
firstName: $firstName | ||
lastName: $lastName | ||
orderBy: $orderBy | ||
) @connection(key: "AuthorsTable_authors") { | ||
totalCount | ||
edges { | ||
node { | ||
...AuthorsTable_authors | ||
} | ||
} | ||
pageInfo { | ||
startCursor | ||
endCursor | ||
hasNextPage | ||
hasPreviousPage | ||
} | ||
} | ||
}` | ||
}, | ||
{ | ||
direction: 'forward', | ||
getConnectionFromProps(props: any) { | ||
return props.authors.authors; | ||
}, | ||
getFragmentVariables(prevVars: any, totalCount: number) { | ||
return { | ||
...prevVars, | ||
count: totalCount, | ||
}; | ||
}, | ||
getVariables(props: any, { count, cursor }, fragmentVariables: any) { | ||
return { | ||
first: count, | ||
after: cursor, | ||
firstName: fragmentVariables.firstName, | ||
lastName: fragmentVariables.lastName, | ||
orderBy: fragmentVariables.orderBy, | ||
}; | ||
}, | ||
query: graphql` | ||
query AuthorsContainerPaginationQuery( | ||
$first: Int! | ||
$after: String | ||
$firstName: String | ||
$lastName: String | ||
$orderBy: [AuthorsOrder] | ||
) { | ||
...AuthorsContainer_authors | ||
} | ||
` | ||
} | ||
); | ||
|
||
export default function RelayAuthorsContainer() { | ||
return ( | ||
<QueryRenderer | ||
environment={environment} | ||
query={graphql` | ||
query AuthorsContainerQuery($first: Int, $after: String, $firstName: String, $lastName: String, $orderBy: [AuthorsOrder]) { | ||
...AuthorsContainer_authors | ||
} | ||
`} | ||
variables={{ first: 10, after: null, firstName: null, lastName: null, orderBy: [{ field: 'ID', direction: 'ASC' }] }} | ||
render={({error, props}: any) => { | ||
|
||
if (error) { | ||
return ( | ||
<Alert variant={'danger'}> | ||
Unexpected error occured! Please contact maintainer or try again later. | ||
</Alert> | ||
); | ||
} | ||
|
||
if (!props) { | ||
return ( <Spinner animation="border" /> ); | ||
} | ||
|
||
return ( | ||
<AuthorsContainer authors={props} /> | ||
); | ||
}} | ||
/> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import React from 'react' | ||
import Table from 'react-bootstrap/Table'; | ||
import { createFragmentContainer } from 'react-relay'; | ||
import { graphql } from 'babel-plugin-relay/macro'; | ||
import AuthorRow from './AuthorRow'; | ||
import { Author } from '../../types/Author'; | ||
|
||
interface Props { | ||
authors: Array<Author>; | ||
} | ||
|
||
const AuthorsTable = (props: Props) => ( | ||
<Table striped bordered responsive hover> | ||
<thead> | ||
<tr> | ||
<th>#</th> | ||
<th>First name</th> | ||
<th>Last name</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{ | ||
props.authors.map(author => ( | ||
<tr key={author.id}> | ||
<AuthorRow author={author} /> | ||
</tr> | ||
)) | ||
} | ||
</tbody> | ||
</Table> | ||
); | ||
|
||
const AuthorsTableFragmentContainer = createFragmentContainer(AuthorsTable, { | ||
authors: graphql` | ||
fragment AuthorsTable_authors on Author @relay(plural: true) { | ||
id | ||
...AuthorRow_author | ||
} | ||
` | ||
}); | ||
|
||
export default AuthorsTableFragmentContainer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import React, { useState } from 'react'; | ||
import Form from 'react-bootstrap/Form'; | ||
import FormGroup from 'react-bootstrap/FormGroup'; | ||
|
||
interface Props { | ||
onUpdate: (values: any) => void; | ||
} | ||
|
||
const Filter: React.FC<Props> = (props: Props) => { | ||
const [firstName, setFirstName] = useState(''); | ||
const [lastName, setLastName] = useState(''); | ||
const [orderField, setOrderField] = useState('ID'); | ||
const [orderDirection, setOrderDirection] = useState('ASC'); | ||
|
||
const handleFirstNameChange = (e: any) => { | ||
const { value } = e.target; | ||
|
||
setFirstName(value); | ||
update({ firstName: value.length === 0 ? null : value }); | ||
}; | ||
|
||
const handleLastNameChange = (e: any) => { | ||
const { value } = e.target; | ||
|
||
setLastName(value); | ||
update({ lastName: value.length === 0 ? null : value }); | ||
}; | ||
|
||
const handleOrderFieldChange = (e: any) => { | ||
const { value } = e.target; | ||
|
||
setOrderField(value); | ||
update({ orderBy:[{ field: value, direction: orderDirection }] }); | ||
}; | ||
|
||
const handleOrderDirectionChange = (e: any) => { | ||
const { value } = e.target; | ||
|
||
setOrderDirection(value); | ||
update({ orderBy:[{ field: orderField, direction: value }] }); | ||
}; | ||
|
||
const update = (values: any) => { | ||
props.onUpdate({ | ||
...{ | ||
firstName: firstName.length === 0 ? null : firstName, | ||
lastName: lastName.length === 0 ? null : lastName, | ||
orderBy: [{ field: orderField, direction: orderDirection }], | ||
}, ...values | ||
}); | ||
}; | ||
|
||
return ( | ||
<Form inline> | ||
<FormGroup controlId="firstName"> | ||
<Form.Label>First name:</Form.Label> | ||
<Form.Control | ||
type="text" | ||
placeholder="" | ||
value={firstName} | ||
onChange={handleFirstNameChange} | ||
/> | ||
</FormGroup> | ||
<FormGroup controlId="lastName"> | ||
<Form.Label>Last name:</Form.Label> | ||
<Form.Control | ||
type="text" | ||
placeholder="" | ||
value={lastName} | ||
onChange={handleLastNameChange} | ||
/> | ||
</FormGroup> | ||
<FormGroup controlId="orderField"> | ||
<Form.Label>Order by:</Form.Label> | ||
<Form.Control as="select" placeholder="field" value={orderField} onChange={handleOrderFieldChange}> | ||
<option value="ID">ID</option> | ||
<option value="CREATED_AT">CREATED_AT</option> | ||
</Form.Control> | ||
</FormGroup> | ||
<FormGroup controlId="orderDirection"> | ||
<Form.Control as="select" placeholder="direction" value={orderDirection} onChange={handleOrderDirectionChange}> | ||
<option value="ASC">ASC</option> | ||
<option value="DESC">DESC</option> | ||
</Form.Control> | ||
</FormGroup> | ||
</Form> | ||
); | ||
}; | ||
|
||
export default Filter; |
Oops, something went wrong.