├── src ├── index.css ├── App.test.js ├── App.css ├── Portal.js ├── YouTubeRecord.js ├── App.js ├── index.js ├── YouTubeDetails.js ├── YouTubePlayer.js ├── logo.svg ├── SearchResults.js └── registerServiceWorker.js ├── public ├── Ripple.gif ├── favicon.ico ├── manifest.json └── index.html ├── .editorconfig ├── .gitignore ├── package.json └── README.md /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /public/Ripple.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlancer/gapi-to-graphql-play-ytclient/master/public/Ripple.gif -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlancer/gapi-to-graphql-play-ytclient/master/public/favicon.ico -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | indent_style = space 3 | end_of_line = lf 4 | indent_size = 2 5 | charset = utf-8 6 | trim_trailing_whitespace = true 7 | 8 | [*.md] 9 | max_line_length = 0 10 | trim_trailing_whitespace = false 11 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | .idea -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-title { 18 | font-size: 1.5em; 19 | } 20 | 21 | .App-intro { 22 | font-size: large; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { transform: rotate(0deg); } 27 | to { transform: rotate(360deg); } 28 | } 29 | -------------------------------------------------------------------------------- /src/Portal.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | 4 | export default class Portal extends React.Component { 5 | constructor(props) { 6 | super(props) 7 | this.el = document.createElement('div') 8 | } 9 | 10 | componentDidMount() { 11 | document.body.appendChild(this.el) 12 | } 13 | 14 | componentWillUnmount() { 15 | document.body.removeChild(this.el) 16 | } 17 | 18 | render() { 19 | return ReactDOM.createPortal(this.props.children, this.el) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "apollo-cache-inmemory": "^1.1.1", 7 | "apollo-client": "^2.0.3", 8 | "apollo-link-http": "^1.2.0", 9 | "graphql": "^0.11.7", 10 | "graphql-tag": "^2.5.0", 11 | "react": "^16.1.1", 12 | "react-apollo": "^2.0.1", 13 | "react-dom": "^16.1.1", 14 | "react-infinite-scroll-component": "^2.5.0", 15 | "react-scripts": "1.0.17" 16 | }, 17 | "scripts": { 18 | "start": "react-scripts start", 19 | "build": "react-scripts build", 20 | "test": "react-scripts test --env=jsdom", 21 | "eject": "react-scripts eject" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/YouTubeRecord.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {graphql} from 'react-apollo'; 3 | import gql from 'graphql-tag'; 4 | import InfiniteScroll from 'react-infinite-scroll-component' 5 | import YouTubePlayer from "./YouTubePlayer"; 6 | import Portal from "./Portal"; 7 | 8 | export default class YouTubeRecord extends Component { 9 | 10 | constructor() { 11 | super() 12 | this.state = {showModal: false} 13 | } 14 | 15 | render() { 16 | 17 | console.log(this.state.showModal) 18 | 19 | const {item} = this.props 20 | 21 | return [ 22 | 23 | this.state.showModal ? : false, 24 | 25 |
this.setState({showModal: true})}> 26 | 27 | 29 |
] 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | import SearchResults from "./SearchResults"; 5 | 6 | class App extends Component { 7 | 8 | constructor(props) { 9 | super(props) 10 | this.state = {search: ''} 11 | } 12 | 13 | render() { 14 | return ( 15 |
16 |
17 | this.setState({search: e.target.value})} type='text'/> 26 |
27 | 28 |
29 | ); 30 | } 31 | } 32 | 33 | export default App; 34 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import registerServiceWorker from './registerServiceWorker'; 6 | 7 | import {ApolloProvider} from 'react-apollo'; 8 | import {ApolloClient} from 'apollo-client'; 9 | import {HttpLink} from 'apollo-link-http'; 10 | import {InMemoryCache} from 'apollo-cache-inmemory'; 11 | 12 | const client = new ApolloClient({ 13 | link: new HttpLink({uri: 'http://localhost:4000/graphql'}), 14 | cache: new InMemoryCache({ 15 | 16 | dataIdFromObject: object => { 17 | 18 | switch (object.__typename) { 19 | case "SearchResult": 20 | return object.id.videoId 21 | } 22 | 23 | return object.id 24 | 25 | } 26 | 27 | } 28 | ), 29 | 30 | }); 31 | 32 | ReactDOM.render( 33 | 34 | 35 | , 36 | document.getElementById('root') 37 | ) 38 | 39 | registerServiceWorker(); 40 | -------------------------------------------------------------------------------- /src/YouTubeDetails.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {graphql} from 'react-apollo'; 3 | import gql from 'graphql-tag'; 4 | import InfiniteScroll from 'react-infinite-scroll-component' 5 | 6 | 7 | class YouTubeDetails extends Component { 8 | 9 | constructor() { 10 | super() 11 | } 12 | 13 | render() { 14 | 15 | const {item, data} = this.props 16 | 17 | 18 | if (data.loading) { 19 | return false 20 | } 21 | 22 | const [dataItem] = data.youtubeV3.videos.list.items 23 | 24 | 25 | return
{dataItem.snippet.title}
26 | 27 | 28 | 29 | } 30 | } 31 | 32 | export default graphql(gql` 33 | query getVideoDetails($id:String!) { 34 | youtubeV3(key:"noop"){ 35 | videos{ 36 | list(id:$id, part:"snippet") { 37 | items { 38 | snippet{ 39 | title 40 | } 41 | } 42 | } 43 | } 44 | } 45 | }`, 46 | { 47 | options: (props) => ({ 48 | variables: { 49 | id: props.item.id.videoId 50 | } 51 | }) 52 | })(YouTubeDetails) -------------------------------------------------------------------------------- /src/YouTubePlayer.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {graphql} from 'react-apollo'; 3 | import gql from 'graphql-tag'; 4 | import InfiniteScroll from 'react-infinite-scroll-component' 5 | import YouTubeDetails from "./YouTubeDetails"; 6 | 7 | export default class YouTubePlayer extends Component { 8 | 9 | constructor() { 10 | super() 11 | } 12 | 13 | render() { 14 | 15 | const {item} = this.props 16 | 17 | return
19 | 20 | 21 |