-
Notifications
You must be signed in to change notification settings - Fork 14
ENYO-5363: Added graphql-example #61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 11 commits
bd35164
077eebe
ff7e3d7
e28f6e1
07c90a2
01e439c
180145b
b2803f1
280516c
e2f670d
c1abd18
5c622ec
c8c2882
c7044ef
c512ed8
ce4c74d
9eb2d7c
f69220a
67796b1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # See http://help.github.com/ignore-files/ for more about ignoring files. | ||
|
|
||
| # dependencies | ||
| node_modules | ||
|
|
||
| # testing | ||
| coverage | ||
|
|
||
| # production | ||
| build | ||
| dist | ||
|
|
||
| # misc | ||
| .DS_Store | ||
| npm-debug.log | ||
| .env |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| ## Use Apollo with Enact and GitHub GraphqQL API | ||
|
|
||
| A sample application that demonstrates how to use GraphqQL with Enact components. It uses [Apollo Client](https://github.com/apollographql/apollo-client), (GraphqQL client.) | ||
|
|
||
| Run `npm install` then `npm run serve` to have the app running on [http://localhost:8080](http://localhost:8080), where you can view it in your browser. | ||
|
|
||
| #### Enact Components Used | ||
| - `moonstone/Panels/ActivityPanels` | ||
| - `moonstone/Panels/Panel` | ||
| - `moonstone/Panels/Header` | ||
| - `moonstone/Button` | ||
| - `moonstone/VirtualList` | ||
| - `moonstone/Item` | ||
| - `moonstone/Divider` | ||
| - `moonstone/Image` | ||
| - `moonstone/Input` | ||
| - `ui/Layout/Column` | ||
| - `ui/Layout/Cell` | ||
| - `ui/resolution/scale` | ||
|
|
||
| ## Setup and use | ||
| 1. Get a personal access token for the [GitHub API](https://github.com/settings/tokens/new). | ||
| - Assign a name to the token and select the "read:org" scope. | ||
| 2. Replace the dummy token in [src/config.json](src/config.json) with the token generated above. | ||
| 3. Install npm modules. | ||
|
|
||
| ```bash | ||
| npm install | ||
| ``` | ||
| 4. Serve. | ||
|
|
||
| ```bash | ||
| npm run serve | ||
| ``` | ||
|
|
||
| 5. Open [localhost](http://localhost:8080/). | ||
| 6. Search for a GitHub id, selecting which information you wish to retrieve. | ||
|
|
||
|
|
||
| ### How Apollo is used. | ||
|
|
||
| In **App.js**, a new `ApolloClient` is created with GitHub URI and request setup: | ||
|
|
||
| [src/App/App.js] | ||
| ```javascript | ||
| import ApolloClient from "apollo-boost"; | ||
|
|
||
| const client = new ApolloClient({ | ||
| uri: 'https://api.github.com/graphql', | ||
| request: operation => { | ||
| operation.setContext({ | ||
| headers: { | ||
| authorization: `Bearer ${config.token}` | ||
| } | ||
| }); | ||
| } | ||
| }); | ||
| ``` | ||
|
|
||
| Next, the `client` prop is passed to the `ApolloProvider` component, which wraps the components that need the queried data: | ||
| [src/App/App.js](src/App/App.js) | ||
| ```javascript | ||
| import { ApolloProvider } from "react-apollo"; | ||
|
|
||
| <ApolloProvider client={client}> | ||
| ... | ||
| </ApolloProvider> | ||
| ``` | ||
|
|
||
| Finally, a GraphQL query (`GET_USER`) is created using `gql` and is passed as the `query` prop to the `Query` component: | ||
|
|
||
| [src/views/Detail.js](src/views/Detail.js) | ||
| ```javascript | ||
| import { Query } from "react-apollo"; | ||
| import gql from "graphql-tag"; | ||
|
|
||
| const GET_USER = gql` | ||
| query($login: String!) { | ||
| user(login: $login) { | ||
| name | ||
| avatarUrl | ||
| organizations(first: 10) { | ||
| nodes { | ||
| name | ||
| } | ||
| } | ||
| repositories(first: 10) { | ||
| nodes { | ||
| name | ||
| url | ||
| } | ||
| } | ||
| followers(first: 10) { | ||
| nodes { | ||
| name | ||
| } | ||
| } | ||
| } | ||
| } | ||
| `; | ||
|
|
||
| <Query query={GET_USER} variables={{login: userId}}> | ||
| {({loading, data}) => { | ||
| ... | ||
| }} | ||
| </Query> | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| { | ||
| "name": "pattern-graphql", | ||
| "version": "1.0.0", | ||
| "description": "An Enact Moonstone GraphQL application.", | ||
| "author": "Hailey HanGyeol Ryu", | ||
| "main": "src/index.js", | ||
| "scripts": { | ||
| "serve": "enact serve", | ||
| "pack": "enact pack", | ||
| "pack-p": "enact pack -p", | ||
| "watch": "enact pack --watch", | ||
| "clean": "enact clean", | ||
| "lint": "enact lint --strict .", | ||
| "license": "enact license", | ||
| "test": "enact test start --single-run", | ||
| "test-watch": "enact test start" | ||
| }, | ||
| "license": "Apache-2.0", | ||
| "private": true, | ||
| "repository": "https://github.com/enactjs/samples", | ||
| "enact": { | ||
| "theme": "moonstone" | ||
| }, | ||
| "eslintConfig": { | ||
| "extends": "enact/strict" | ||
| }, | ||
| "eslintIgnore": [ | ||
| "node_modules/*", | ||
| "build/*", | ||
| "dist/*" | ||
| ], | ||
| "dependencies": { | ||
| "@enact/core": "next", | ||
| "@enact/i18n": "next", | ||
| "@enact/moonstone": "next", | ||
| "@enact/spotlight": "next", | ||
| "@enact/ui": "next", | ||
| "apollo-boost": "^0.1.8", | ||
| "graphql": "^0.13.2", | ||
| "graphql-tag": "^2.9.2", | ||
| "prop-types": "^15.6.0", | ||
| "react": "^16.4.0", | ||
| "react-apollo": "^2.1.5", | ||
| "react-dom": "^16.4.0" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "files": [] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| import {ActivityPanels} from '@enact/moonstone/Panels'; | ||
| import ApolloClient from 'apollo-boost'; | ||
| import {ApolloProvider} from 'react-apollo'; | ||
| import MoonstoneDecorator from '@enact/moonstone/MoonstoneDecorator'; | ||
| import React, {Component} from 'react'; | ||
| import PropTypes from 'prop-types'; | ||
|
|
||
| import Detail from '../views/Detail'; | ||
| import Search from '../views/Search'; | ||
| import config from '../config.json'; | ||
|
|
||
|
|
||
| const client = new ApolloClient({ | ||
| uri: 'https://api.github.com/graphql', | ||
| request: operation => { | ||
| operation.setContext({ | ||
| headers: { | ||
| authorization: `Bearer ${config.token}` | ||
| } | ||
| }); | ||
| } | ||
| }); | ||
|
|
||
| class AppBase extends Component { | ||
| static propTypes = { | ||
| index: PropTypes.number, | ||
| onListSelectionChange: PropTypes.func, | ||
| onSearch: PropTypes.func, | ||
| onUserIdChange: PropTypes.func | ||
| }; | ||
|
|
||
| static defaultProps = { | ||
| index: 0 | ||
| }; | ||
|
|
||
| constructor (props) { | ||
| super(props); | ||
| this.userId = ''; | ||
| this.lists = { | ||
| fol: false, | ||
| org: false, | ||
| repo: false | ||
| }; | ||
|
|
||
| this.state = { | ||
| index: this.props.index, | ||
| lists: {}, | ||
| userId: '' | ||
| }; | ||
| } | ||
|
|
||
| handleSelectBreadcrumb = ({index}) => { | ||
| this.lists = { | ||
| fol: false, | ||
| org: false, | ||
| repo: false | ||
| }; | ||
| this.setState({ | ||
| index, | ||
| lists: this.lists, | ||
| userId: '' | ||
| }); | ||
| }; | ||
|
|
||
| onUserIdChange = (userId) => { | ||
| this.userId = userId; | ||
| }; | ||
|
|
||
| onListSelectionChange = (target, value) => { | ||
| this.lists[target] = value; | ||
| }; | ||
|
|
||
| onSearch = () => { | ||
| this.setState({index: 1, userId: this.userId, lists: this.lists}); | ||
| }; | ||
|
|
||
| render () { | ||
| const {index, userId, lists} = this.state; | ||
|
|
||
| return ( | ||
| <ApolloProvider client={client}> | ||
| <ActivityPanels {...this.props} index={index} onSelectBreadcrumb={this.handleSelectBreadcrumb}> | ||
| <Search | ||
| apiToken={config.token} | ||
|
||
| onListSelectionChange={this.onListSelectionChange} | ||
| onSearch={this.onSearch} | ||
| onUserIdChange={this.onUserIdChange} | ||
| /> | ||
| <Detail lists={lists} userId={userId} /> | ||
| </ActivityPanels> | ||
| </ApolloProvider> | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| const App = MoonstoneDecorator(AppBase); | ||
|
|
||
| export default App; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "main": "App.js" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import {Cell} from '@enact/ui/Layout'; | ||
| import Divider from '@enact/moonstone/Divider'; | ||
| import Item from '@enact/moonstone/Item'; | ||
| import PropTypes from 'prop-types'; | ||
| import React, {Component} from 'react'; | ||
| import {scale} from '@enact/ui/resolution'; | ||
| import VirtualList from '@enact/moonstone/VirtualList'; | ||
|
|
||
| class List extends Component { | ||
| static propTypes = { | ||
| list: PropTypes.arrayOf(PropTypes.object).isRequired, | ||
| userId: PropTypes.string | ||
| } | ||
|
|
||
| renderItem = ({index, ...rest}) => ( | ||
| <Item | ||
| {...rest} | ||
| index={index} | ||
| > | ||
| {this.props.list[index].name} | ||
| </Item> | ||
| ); | ||
|
|
||
| render = () => { | ||
|
||
| const list = this.props.list; | ||
|
|
||
| return [ | ||
| <Cell key="header" shrink><Divider>Repositories</Divider></Cell>, | ||
| <Cell | ||
| component={VirtualList} size={list.length <= 4 ? (60 * list.length) : null} | ||
|
||
| key="list" | ||
| dataSize={list.length} | ||
| focusableScrollbar={null} | ||
| itemRenderer={this.renderItem} | ||
| itemSize={scale(60)} | ||
| spacing={0} | ||
| />]; | ||
| } | ||
| } | ||
|
|
||
| export default List; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "token":"19813c93ca87e38f38cb0c05e6df04ccdb3de577" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| import React from 'react'; | ||
| import {render} from 'react-dom'; | ||
|
|
||
| import App from './App'; | ||
|
|
||
| const appElement = (<App skin="light" />); | ||
|
|
||
| // In a browser environment, render instead of exporting | ||
| if (typeof window !== 'undefined') { | ||
| render(appElement, document.getElementById('root')); | ||
| } | ||
|
|
||
| export default appElement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we mention "read:org" under "admin:org"?