Elvenware

GitHubApi

Welcome to GitHubApi

Git Hub API

Learn how to call the GitHub API.

Node Support for ES6

Note that let and const are fully supported.

Get your version of node:

$ node --version
v7.9.0

GitHub API

Get the GitHub API token:

Install the JavaScript GitHub API:

npm install --save github-api

In a file called routes/gists.js link in the JavaScript GitHub API:

var GitHub = require('github-api');

Here is an FYI

Sign in

Since we are going to being modifying data, we should start by signing in.

const token = require('./tokens');

let getGitHub = function() {
    let gh;
    if (true) {
    gh = new GitHub({
            token: token
        });
    } else {
        gh = new GitHub({
            username: 'charliecalvert',
            password: ''
        });
    }
    return gh;
};

Here is tokens.js:

const tokens = [
    '3bd10af220924e317cd3f76601a29231b507d9a7'
];
module.exports = tokens[0];

But you must get your own token from GitHub. It's in:

Like this:

Get Gist Data

router.get('/get-basic-list', function(request, response) {
    logger.log('GET BASIC LIST CALLED');
    let gh = getGitHub();
    const me = gh.getUser();
    logger.log('ME', me);
    me
        .listGists()
        .then(function({ data }) {
            logger.log('FILES PROMISE', Object.keys(data[0].files));
            const results = data.map(item => ({
                htmlUrl: item.html_url,
                id: item.id,
                gitPullUrl: item.git_pull_url,
                description: item.description,
                ownerLogin: item.owner.login,
                avatarUrl: item.owner.avatar_url,
                files: Object.keys(item.files)
            }));
            response.status(200).send({
                count: results.length,
                result: results
            });
        })
        .catch(function(err) {
            logger.log('USER Promise Rejected', err);
            response.status(500).send({ result: err });
        });
});

listGists returns a fairly complex set of information. The following line of code says that we only want the data property from the bit object that is sent to us:

.then(function({ data }) { ... })

In other words, the data call is intentionally wrapped in a object literal : { data }.

Display Gist Data

In App.js make a copy of the fetch code you used to call the /user route. For now, use it in App.js and call your new method fetchGistList. In fetchGistList, the URL should be /gists/get-basic-list.

GetGist Component

You'll need to create a new component called ShowNewGist that extends React.Component. Its job will be to display the information you get back when you create a gist. This component will take a certain number of props including:

You do not need to display all the fields, at least at first. Two or three would be enough while testing. For the midterm, up this to at least five or six. Be sure to include Description and URL among the fields you display. If possible, making URL clickable so we can see the Gist that you create.

Add a new item to the menu called Insert New Gist or something similar. In DataMaven, you will also need to a new Route in the render method. It should display a component called ShowNewGist At some point the new route will need to pass two pieces of information to the component it calls.

The new component will have one button that will call the fetchGist method from DataMaven.

fetchGist should retrieve the entirety of the JSON data returned from GitHub. On the client side you should add the data to DataMaven's state. This should cause a call to the DataMaven and ShowNewGist render methods.

The Buttons

<RaisedButton
    style={buttonStyle}
    id="prevGist"
    onClick={(e) => this.gistIterator('prevGist', e)}
    disabled={!this.props.gistCanIterate}
    secondary={true}
>
    Back
</RaisedButton>

Thinking about State

I've been trying to get us to the point where we put all our data in a library called Redux. Redux can be helpful when state starts to get complicated, which it appears to be in our case. So Redux should help us eliminate some of this business and keep things clean. I hope.

Reading more on this subject, I'm beginning to see that maybe I should add this: "We should put all the data that we want to preserve between sessions in Redux." In other words, there is some state that a component might need to preserve at runtime, but that does not need to be preserved between sessions. This type of data can be preserved as state in the component because we don't care if we lose it if the user closes the page. But data that we want to preserve should go to our "data store" which right now is DataMaven, but which I think will eventually be Redux.

If there is a theme to this course it would be: Finding the right design, the right architecture, is not easy. It takes time and requires multiple iterations. This may be a case where we have to search for the right solution. We'll see.

The key reference is probably this one:

I found this discussion really helpful:

Read the section called Details, Details here:

Examples

curl https://api.github.com/zen
curl https://api.github.com/users/charliecalvert
curl -i https://api.github.com/repos/twbs/bootstrap
curl -i https://api.github.com/repos/charliecalvert/JsObjects
curl -i https://api.github.com/repos/charliecalvert/repos
curl -i https://api.github.com/repos/charliecalvert
curl -i https://api.github.com/users/charliecalvert/repos

Time till Renew

curl https://api.github.com/users/charliecalvert

And see this line:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1492098563

Convert the reset time:

var f = new Date(1492098563 * 1000);
console.log(f); => "Thu Apr 13 2017 08:49:23 GMT-0700 (PDT)"

Testing Notes

The tests in Header.test.js break after the refactoring explained above. After the refactoring, I was getting this error:

This is because the ElfHeader could not find the Router tag is was expected. The fix is as follows:

import { BrowserRouter as Router } from 'react-router-dom';

it('renders without crashing', () => {
    const div = document.createElement('div');
    ReactDOM.render(<Router><ElfHeader /></Router>, div);
});

https://gist.github.com/charliecalvert/51daef341699943b07c9570c3ad2cbab Question: After making this change, we might want to test to see if ElfHeader properly renders an H2 element. For that test to work, should we now use shallow or mount?

Running One Test File or Suite

We have learned how to use fit and .only. Also, note the menu:

Watch Usage
 › Press o to only run tests related to changed files.
 › Press p to filter by a filename regex pattern.
 › Press q to quit watch mode.
 › Press Enter to trigger a test run.

Select p and enter part of the name of the test file you want to test. For instance, Header. Then only Header.test.js will run.