├── .firebase └── hosting.ZGlzdA.cache ├── .firebaserc ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .yo-rc.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── app ├── components │ ├── App.js │ ├── Battle.js │ ├── ForkButton.js │ ├── Home.js │ ├── Loading.js │ ├── Nav.js │ ├── PlayerPreview.js │ ├── Popular.js │ └── Results.js ├── index.css ├── index.html ├── index.js └── utils │ └── api.js ├── firebase.json ├── package-lock.json ├── package.json ├── screen.gif ├── src └── index.js └── webpack.config.js /.firebase/hosting.ZGlzdA.cache: -------------------------------------------------------------------------------- 1 | index.html,1558112768399,c130892890d24e06c8ba29bccbda553950c1b977b7699978bb16eaec7c8b12e4 2 | goGitter.html,1558029922167,c130892890d24e06c8ba29bccbda553950c1b977b7699978bb16eaec7c8b12e4 3 | index.84d7a9afdce44ad5b18b.js,1557729987480,bfb72d05a6be6177f00457a65d7d22a262e2c6855b715ab8adf6089598242104 4 | index_bundle.js,1558112768399,831492b21f31d4eb4ecdf0a3fa79cfaf62354e23d246ff27cd799d47cdc7f04f 5 | -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "gogitter-16d93" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [piyush97] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | custom: paypal.me/mehtapiyush 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. 4 | 5 | Fixes # (issue) 6 | 7 | ## Type of change 8 | 9 | Please delete options that are not relevant. 10 | 11 | - [ ] Bug fix (non-breaking change which fixes an issue) 12 | - [ ] New feature (non-breaking change which adds functionality) 13 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 14 | - [ ] This change requires a documentation update 15 | 16 | # How Has This Been Tested? 17 | 18 | Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration 19 | 20 | - [ ] Test A 21 | - [ ] Test B 22 | 23 | **Test Configuration**: 24 | * Firmware version: 25 | * Hardware: 26 | * Toolchain: 27 | * SDK: 28 | 29 | # Checklist: 30 | 31 | - [ ] My code follows the style guidelines of this project 32 | - [ ] I have performed a self-review of my own code 33 | - [ ] I have commented my code, particularly in hard-to-understand areas 34 | - [ ] I have made corresponding changes to the documentation 35 | - [ ] My changes generate no new warnings 36 | - [ ] I have added tests that prove my fix is effective or that my feature works 37 | - [ ] New and existing unit tests pass locally with my changes 38 | - [ ] Any dependent changes have been merged and published in downstream modules 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | -------------------------------------------------------------------------------- /.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "again": { 3 | "configuration": { 4 | "config": { 5 | "topScope": [ 6 | "const webpack = require('webpack')", 7 | "const path = require('path')", 8 | "\n", 9 | "/*\n * SplitChunksPlugin is enabled by default and replaced\n * deprecated CommonsChunkPlugin. It automatically identifies modules which\n * should be splitted of chunk by heuristics using module duplication count and\n * module category (i. e. node_modules). And splits the chunks…\n *\n * It is safe to remove \"splitChunks\" from the generated configuration\n * and was added as an educational example.\n *\n * https://webpack.js.org/plugins/split-chunks-plugin/\n *\n */", 10 | "/*\n * We've enabled UglifyJSPlugin for you! This minifies your app\n * in order to load faster and run less javascript.\n *\n * https://github.com/webpack-contrib/uglifyjs-webpack-plugin\n *\n */", 11 | "const UglifyJSPlugin = require('uglifyjs-webpack-plugin');", 12 | "\n" 13 | ], 14 | "webpackOptions": { 15 | "module": { 16 | "rules": [ 17 | { 18 | "include": [ 19 | "path.resolve(__dirname, 'src')" 20 | ], 21 | "loader": "'babel-loader'", 22 | "options": { 23 | "plugins": [ 24 | "'syntax-dynamic-import'" 25 | ], 26 | "presets": [ 27 | [ 28 | "'@babel/preset-env'", 29 | { 30 | "'modules'": false 31 | } 32 | ] 33 | ] 34 | }, 35 | "test": "/\\.js$/" 36 | }, 37 | { 38 | "test": "/\\.css$/", 39 | "use": [ 40 | { 41 | "loader": "'style-loader'", 42 | "options": { 43 | "sourceMap": true 44 | } 45 | }, 46 | { 47 | "loader": "'css-loader'" 48 | } 49 | ] 50 | } 51 | ] 52 | }, 53 | "entry": { 54 | "index": "'./app/index'" 55 | }, 56 | "output": { 57 | "filename": "'[name].[chunkhash].js'" 58 | }, 59 | "mode": "'development'", 60 | "plugins": [ 61 | "new UglifyJSPlugin()" 62 | ], 63 | "optimization": { 64 | "splitChunks": { 65 | "cacheGroups": { 66 | "vendors": { 67 | "priority": -10, 68 | "test": "/[\\\\/]node_modules[\\\\/]/" 69 | } 70 | }, 71 | "chunks": "'async'", 72 | "minChunks": 1, 73 | "minSize": 30000, 74 | "name": true 75 | } 76 | } 77 | }, 78 | "configName": "config" 79 | } 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at me@piyushmehta.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 11 | build. 12 | 2. Update the README.md with details of changes to the interface, this includes new environment 13 | variables, exposed ports, useful file locations and container parameters. 14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this 15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 16 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you 17 | do not have permission to do that, you may request the second reviewer to merge it for you. 18 | 19 | ## Code of Conduct 20 | 21 | ### Our Pledge 22 | 23 | In the interest of fostering an open and welcoming environment, we as 24 | contributors and maintainers pledge to making participation in our project and 25 | our community a harassment-free experience for everyone, regardless of age, body 26 | size, disability, ethnicity, gender identity and expression, level of experience, 27 | nationality, personal appearance, race, religion, or sexual identity and 28 | orientation. 29 | 30 | ### Our Standards 31 | 32 | Examples of behavior that contributes to creating a positive environment 33 | include: 34 | 35 | * Using welcoming and inclusive language 36 | * Being respectful of differing viewpoints and experiences 37 | * Gracefully accepting constructive criticism 38 | * Focusing on what is best for the community 39 | * Showing empathy towards other community members 40 | 41 | Examples of unacceptable behavior by participants include: 42 | 43 | * The use of sexualized language or imagery and unwelcome sexual attention or 44 | advances 45 | * Trolling, insulting/derogatory comments, and personal or political attacks 46 | * Public or private harassment 47 | * Publishing others' private information, such as a physical or electronic 48 | address, without explicit permission 49 | * Other conduct which could reasonably be considered inappropriate in a 50 | professional setting 51 | 52 | ### Our Responsibilities 53 | 54 | Project maintainers are responsible for clarifying the standards of acceptable 55 | behavior and are expected to take appropriate and fair corrective action in 56 | response to any instances of unacceptable behavior. 57 | 58 | Project maintainers have the right and responsibility to remove, edit, or 59 | reject comments, commits, code, wiki edits, issues, and other contributions 60 | that are not aligned to this Code of Conduct, or to ban temporarily or 61 | permanently any contributor for other behaviors that they deem inappropriate, 62 | threatening, offensive, or harmful. 63 | 64 | ### Scope 65 | 66 | This Code of Conduct applies both within project spaces and in public spaces 67 | when an individual is representing the project or its community. Examples of 68 | representing a project or community include using an official project e-mail 69 | address, posting via an official social media account, or acting as an appointed 70 | representative at an online or offline event. Representation of a project may be 71 | further defined and clarified by project maintainers. 72 | 73 | ### Enforcement 74 | 75 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 76 | reported by contacting the project team at me@piyushmehta.com . All 77 | complaints will be reviewed and investigated and will result in a response that 78 | is deemed necessary and appropriate to the circumstances. The project team is 79 | obligated to maintain confidentiality with regard to the reporter of an incident. 80 | Further details of specific enforcement policies may be posted separately. 81 | 82 | Project maintainers who do not follow or enforce the Code of Conduct in good 83 | faith may face temporary or permanent repercussions as determined by other 84 | members of the project's leadership. 85 | 86 | ### Attribution 87 | 88 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 89 | available at [http://contributor-covenant.org/version/1/4][version] 90 | 91 | [homepage]: http://contributor-covenant.org 92 | [version]: http://contributor-covenant.org/version/1/4/ 93 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Piyush Mehta 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

GoGitter

2 |

Battle with your friends

3 | 4 | Star this repository if you like it 5 | ⭐ 6 | 7 | Screen: 8 | 9 | 10 | 11 | Tech: 12 | 1. React 13 | 2. AJAX 14 | 3. Router 15 | 4. Query String -------------------------------------------------------------------------------- /app/components/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Popular from "./Popular"; 3 | var ReactRouter = require("react-router-dom"); 4 | var Router = ReactRouter.BrowserRouter; 5 | var Route = ReactRouter.Route; 6 | var Switch = ReactRouter.Switch; 7 | import Home from "./Home"; 8 | import Nav from "./Nav"; 9 | import Battle from "./Battle"; 10 | import Results from "./Results"; 11 | import ForkRibbon from "./ForkButton"; 12 | 13 | export default class App extends React.Component { 14 | render() { 15 | return ( 16 | 17 | 18 |
19 |
37 |
38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/components/Battle.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import PropTypes from "prop-types"; 3 | import { Link } from "react-router-dom"; 4 | import PlayerPreview from "./PlayerPreview"; 5 | 6 | class PlayerInput extends React.Component { 7 | constructor(props) { 8 | super(props); 9 | this.state = { 10 | username: "" 11 | }; 12 | 13 | this.handleChange = this.handleChange.bind(this); 14 | this.handleSubmit = this.handleSubmit.bind(this); 15 | } 16 | handleChange(event) { 17 | var value = event.target.value; 18 | 19 | this.setState(function() { 20 | return { 21 | username: value 22 | }; 23 | }); 24 | } 25 | handleSubmit(event) { 26 | event.preventDefault(); 27 | 28 | this.props.onSubmit(this.props.id, this.state.username); 29 | } 30 | render() { 31 | return ( 32 |
33 | 36 | 44 | 51 |
52 | ); 53 | } 54 | } 55 | 56 | PlayerInput.propTypes = { 57 | id: PropTypes.string.isRequired, 58 | label: PropTypes.string.isRequired, 59 | onSubmit: PropTypes.func.isRequired 60 | }; 61 | 62 | PlayerInput.defaultProps = { 63 | label: "Username" 64 | }; 65 | 66 | export default class Battle extends React.Component { 67 | constructor(props) { 68 | super(props); 69 | this.state = { 70 | playerOneName: "", 71 | playerTwoName: "", 72 | playerOneImage: null, 73 | playerTwoImage: null 74 | }; 75 | 76 | this.handleSubmit = this.handleSubmit.bind(this); 77 | } 78 | handleSubmit(id, username) { 79 | this.setState(function() { 80 | var newState = {}; 81 | newState[id + "Name"] = username; 82 | newState[id + "Image"] = 83 | "https://github.com/" + username + ".png?size=200"; 84 | return newState; 85 | }); 86 | } 87 | handleReset(id) { 88 | this.setState(function() { 89 | var newState = {}; 90 | newState[id + "Name"] = ""; 91 | newState[id + "Image"] = null; 92 | return newState; 93 | }); 94 | } 95 | render() { 96 | var match = this.props.match; 97 | var playerOneName = this.state.playerOneName; 98 | var playerOneImage = this.state.playerOneImage; 99 | var playerTwoName = this.state.playerTwoName; 100 | var playerTwoImage = this.state.playerTwoImage; 101 | 102 | return ( 103 |
104 |
105 | {!playerOneName && ( 106 | 111 | )} 112 | 113 | {playerOneImage !== null && ( 114 | 115 | 121 | 122 | )} 123 | 124 | {!playerTwoName && ( 125 | 130 | )} 131 | 132 | {playerTwoImage !== null && ( 133 | 134 | 140 | 141 | )} 142 |
143 | {playerOneImage && playerTwoImage && ( 144 | 12 | Fork me on GitHub 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /app/components/Home.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { Link } from "react-router-dom"; 3 | export default class Home extends Component { 4 | render() { 5 | return ( 6 |
7 |

GoGitter Profile Battle

8 |

Battle with friends

9 | 10 | Battle 11 | 12 |
13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/components/Loading.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | const styles = { 5 | content: { 6 | textAlign: "center", 7 | fontSize: "35px" 8 | } 9 | }; 10 | 11 | export default class Loading extends Component { 12 | constructor(props) { 13 | super(props); 14 | this.state = { 15 | text: props.text 16 | }; 17 | } 18 | componentDidMount() { 19 | let stopper = this.props.text + "..."; 20 | this.interval = window.setInterval( 21 | function() { 22 | if (this.state.text === stopper) { 23 | this.setState({ text: this.props.text }); 24 | } else { 25 | this.setState(function(prevState) { 26 | return { text: prevState.text + "." }; 27 | }); 28 | } 29 | }.bind(this), 30 | this.props.speed 31 | ); 32 | } 33 | componentWillUnmount() { 34 | window.clearInterval(this.interval); 35 | } 36 | 37 | render() { 38 | return

{this.state.text}

; 39 | } 40 | } 41 | Loading.propTypes = { 42 | loading: PropTypes.string.isRequired, 43 | speed: PropTypes.number.isRequired 44 | }; 45 | Loading.defaultProps = { 46 | text: "Loading", 47 | speed: 300 48 | }; 49 | -------------------------------------------------------------------------------- /app/components/Nav.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { NavLink } from "react-router-dom"; 3 | 4 | export default function Nav() { 5 | return ( 6 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /app/components/PlayerPreview.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | function PlayerPreview(props) { 5 | return ( 6 |
7 |
8 | {"Avatar 13 |

@{props.username}

14 |
15 | {props.children} 16 |
17 | ); 18 | } 19 | 20 | PlayerPreview.propTypes = { 21 | avatar: PropTypes.string.isRequired, 22 | username: PropTypes.string.isRequired 23 | }; 24 | 25 | export default PlayerPreview; 26 | -------------------------------------------------------------------------------- /app/components/Popular.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import api from "../utils/api"; 3 | import propTypes from "prop-types"; 4 | import Loading from "./Loading"; 5 | 6 | export default class Popular extends Component { 7 | constructor(props) { 8 | super(props); 9 | this.state = { 10 | selectedLanguage: "All", 11 | repos: null 12 | }; 13 | this.updateLanguage = this.updateLanguage.bind(this); 14 | } 15 | 16 | componentDidMount() { 17 | this.updateLanguage(this.state.selectedLanguage); 18 | } 19 | 20 | updateLanguage(lang) { 21 | this.setState(function() { 22 | return { selectedLanguage: lang, repos: null }; 23 | }); 24 | api.fetchPopularRepos(lang).then( 25 | function(repos) { 26 | this.setState({ repos: repos }); 27 | }.bind(this) 28 | ); 29 | } 30 | 31 | render() { 32 | return ( 33 |
34 | 38 | {!this.state.repos ? ( 39 | 40 | ) : ( 41 | 42 | )} 43 |
44 | ); 45 | } 46 | } 47 | 48 | function RepoGrid(props) { 49 | return ( 50 |