Skip to content

Commit 09dc5c8

Browse files
author
Ushang Thakker
committed
Added: Github app
1 parent 50fb71e commit 09dc5c8

File tree

16 files changed

+487
-2
lines changed

16 files changed

+487
-2
lines changed

README.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,22 @@
1-
# reactgithubapi
2-
Learning react basics
1+
# ReactGithubAPI
2+
Learning react basics using the free and opensource github API
3+
4+
Update:
5+
6+
To run this in a docker container use `make`
7+
8+
After downloading/forking the repo:
9+
10+
`npm install`
11+
12+
After that to run the app:
13+
14+
`npm start`
15+
16+
and then visit `http://localhost:8080` on your browser.
17+
18+
To run tests:
19+
20+
`npm run test`
21+
22+

package.json

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"name": "ReactGithubAPI",
3+
"version": "1.0.4",
4+
"description": "A simple app to learn the basics of React/webpack and deploy it using a docker instance",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "jest",
8+
"start": "webpack"
9+
},
10+
"keywords": [
11+
"react",
12+
"node",
13+
"webpack",
14+
"docker",
15+
"githubapi"
16+
],
17+
"author": "Ushang Thakker",
18+
"license": "ISC",
19+
"babel": {
20+
"presets": [
21+
"es2015",
22+
"react"
23+
]
24+
},
25+
"jest": {
26+
"scriptPreprocessor": "<rootDir>/node_modules/babel-jest",
27+
"unmockedModulePathPatterns": [
28+
"<rootDir>/node_modules/react",
29+
"<rootDir>/node_modules/react-dom",
30+
"<rootDir>/node_modules/react-addons-test-utils",
31+
"<rootDir>/node_modules/fbjs"
32+
]
33+
},
34+
"devDependencies": {
35+
"babel-core": "^6.10.4",
36+
"babel-jest": "^13.2.2",
37+
"babel-loader": "^6.2.4",
38+
"babel-preset-es2015": "^6.9.0",
39+
"babel-preset-react": "^6.11.1",
40+
"jest-cli": "^13.2.3",
41+
"node-sass": "^3.8.0",
42+
"react-addons-test-utils": "^15.2.1",
43+
"react-hot-loader": "^1.3.0",
44+
"sass-loader": "^4.0.0",
45+
"webpack-dev-server": "^1.14.1"
46+
},
47+
"dependencies": {
48+
"chance": "^1.0.3",
49+
"css-loader": "^0.23.1",
50+
"file-loader": "^0.9.0",
51+
"history": "^3.0.0",
52+
"react": "^15.2.1",
53+
"react-dom": "^15.2.1",
54+
"react-router": "^2.5.2",
55+
"style-loader": "^0.13.1",
56+
"superagent": "^2.1.0",
57+
"webpack": "^1.13.1"
58+
}
59+
}

src/components/App/App.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React from 'react';
2+
3+
class App extends React.Component {
4+
render() {
5+
return(
6+
<div>
7+
<h1> GitHub API using React with Docker & CI </h1>
8+
{this.props.children}
9+
</div>
10+
);
11+
}
12+
}
13+
14+
export default App;

src/components/App/App.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
h1 {
2+
font-weight: 100;
3+
font-size: 250%;
4+
margin-bottom: 0;
5+
color: #0275d8;
6+
}
7+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import React from 'react';
2+
import { IndexLink } from 'react-router';
3+
4+
class Breadcrumb extends React.Component {
5+
render() {
6+
if(this.props.rootNode){
7+
return(<p>You are here: <IndexLink to="/" activeClassName="active">Home</IndexLink></p>);
8+
}
9+
else{
10+
return(
11+
<p>You are here: <IndexLink to="/" activeClassName="active">Home </IndexLink>
12+
> {this.props.childNode}</p>
13+
);
14+
}
15+
}
16+
}
17+
18+
export default Breadcrumb;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
a {
2+
color: #0275d8;
3+
text-decoration: none;
4+
}
5+
6+
a:hover {
7+
text-decoration: underline;
8+
}
9+
10+
a.active {
11+
color: black;
12+
}

src/components/Detail/Detail.js

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import React from 'react';
2+
import { Link } from 'react-router';
3+
import Breadcrumb from '../Breadcrumb/Breadcrumb';
4+
import ajax from 'superagent';
5+
6+
class Detail extends React.Component {
7+
constructor(props) {
8+
super(props);
9+
10+
this.state = {
11+
mode: 'commits',
12+
commits: [],
13+
forks: [],
14+
pulls: []
15+
};
16+
}
17+
18+
19+
fetchFeed(type) {
20+
if(this.props.params.repo === ''){
21+
return;
22+
}
23+
24+
const baseURL = 'https://api.github.com/repos/facebook';
25+
26+
// -------- Discarding fetch for superagent -----------------------------
27+
/*fetch(`${baseURL}/${this.props.params.repo}/${type}`).then((response) => {
28+
return response.json();
29+
}).then((body) => {
30+
this.setState({ [type]: body });
31+
}).catch((err) => {
32+
console.log(`Error fetching ${type}`,err);
33+
});*/
34+
35+
// -------------- superagent code ---------------------------------------------------
36+
ajax.get(`${baseURL}/${this.props.params.repo}/${type}`) //es6 String Interpolation: Need `` and not ''
37+
.end((error, response) => {
38+
if (!error && response) {
39+
this.setState({ [type]: response.body }); //es6 Computed property names: surround variable names by []
40+
} else {
41+
console.log(`Error fetching ${type}`, error);
42+
}
43+
}
44+
);
45+
}
46+
47+
componentWillMount() {
48+
49+
this.fetchFeed('commits');
50+
this.fetchFeed('forks');
51+
this.fetchFeed('pulls');
52+
}
53+
54+
selectMode(mode) {
55+
this.setState({ mode });
56+
}
57+
58+
59+
renderCommits() {
60+
return this.state.commits.map((commit, index) => {
61+
const author = commit.author ? commit.author.login : 'Anonymous';
62+
const profileLink = '/user/'+author;
63+
64+
return (<p key={index}>
65+
<Link to={profileLink}> {author} </Link> :
66+
<a href={commit.html_url}>{commit.commit.message}</a>.
67+
</p>);
68+
});
69+
}
70+
71+
renderForks() {
72+
return this.state.forks.map((fork, index) => {
73+
const owner = fork.owner ? fork.owner.login : 'Anonymous';
74+
const profileLink = '/user/'+owner;
75+
76+
return (<p key={index}>
77+
<Link to={profileLink}> {owner} </Link> : forked to
78+
<a href={fork.html_url}>{fork.html_url}</a> at {fork.created_at}.
79+
</p>);
80+
});
81+
}
82+
83+
renderPulls() {
84+
return this.state.pulls.map((pull, index) => {
85+
const user = pull.user ? pull.user.login : 'Anonymous';
86+
const profileLink = '/user/'+user;
87+
88+
return (<p key={index}>
89+
<Link to={profileLink}> {user} </Link> :
90+
<a href={pull.html_url}>{pull.body}</a>.
91+
</p>);
92+
});
93+
}
94+
95+
render() {
96+
let content;
97+
98+
if (this.state.mode === 'commits') {
99+
content = this.renderCommits();
100+
} else if (this.state.mode === 'forks') {
101+
content = this.renderForks();
102+
} else {
103+
content = this.renderPulls();
104+
}
105+
106+
return (<div>
107+
<Breadcrumb childNode = {this.props.params.repo} />
108+
<br/>
109+
<button onClick={this.selectMode.bind(this, 'commits')}>Show Commits</button>
110+
<button onClick={this.selectMode.bind(this, 'forks')}>Show Forks</button>
111+
<button onClick={this.selectMode.bind(this, 'pulls')}>Show Pulls</button>
112+
<hr/>
113+
<h1>{this.state.mode}</h1>
114+
{content}
115+
</div>);
116+
}
117+
}
118+
119+
export default Detail;

src/components/Detail/Detail.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
button {
2+
padding: 5px 20px;
3+
background-color: white;
4+
margin: 10px;
5+
border: 1px solid #aaaaaa;
6+
border-radius: 5px;
7+
outline-width: 0;
8+
}
9+
10+
button:active {
11+
background-color: #dcdcdc;
12+
}

src/components/List/List.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React from 'react';
2+
import { Link } from 'react-router';
3+
import Breadcrumb from '../Breadcrumb/Breadcrumb';
4+
5+
class List extends React.Component {
6+
7+
render() {
8+
return (
9+
<div>
10+
<Breadcrumb rootNode="true" />
11+
<p> Please choose a repository from the list below </p>
12+
<ul>
13+
<li> <Link to="/detail/react"> React </Link> </li>
14+
<li> <Link to="/detail/react-native"> React Native</Link> </li>
15+
<li> <Link to="/detail/jest"> Jest </Link> </li>
16+
</ul>
17+
</div>
18+
);
19+
}
20+
}
21+
22+
export default List;

src/components/User/User.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import React from 'react';
2+
import { Link } from 'react-router';
3+
import Breadcrumb from '../Breadcrumb/Breadcrumb';
4+
import ajax from 'superagent';
5+
6+
class User extends React.Component {
7+
8+
constructor(props) {
9+
super(props);
10+
11+
this.state = {
12+
events: []
13+
}
14+
}
15+
16+
componentWillMount(){
17+
const baseURL = 'https://api.github.com/users';
18+
19+
// -------- Discarding fetch for superagent -----------------------------
20+
/*fetch(`${baseURL}/${this.props.params.user}/events`).then((response) => {
21+
return response.json();
22+
}).then((body) => {
23+
this.setState({ events: body });
24+
}).catch((err) => {
25+
console.log(`Error fetching ${this.props.params.user}`,err);
26+
});*/
27+
28+
// -------------- superagent code ---------------------------------------------------
29+
ajax.get(`${baseURL}/${this.props.params.user}/events`) //es6 String Interpolation: Need `` and not ''
30+
.end((error, response) => {
31+
if (!error && response) {
32+
this.setState({ events: response.body }); //es6 Computed property names: surround variable names by []
33+
} else {
34+
console.log(`Error fetching ${this.props.params.user} data`, error);
35+
}
36+
}
37+
);
38+
}
39+
40+
getContent() {
41+
return this.state.events.map((event, index) => {
42+
var eventMap = [
43+
{key:"Event Type", value: event.type},
44+
{key:"Actor Name", value: event.actor.login},
45+
{key:"Actor URL", value: event.actor.url},
46+
{key:"Repo Name", value: event.repo.name},
47+
{key:"Repo URL", value: event.repo.url},
48+
{key:"Created At", value: event.created_at}
49+
];
50+
return(
51+
<ul key={index}>
52+
{
53+
eventMap.map((data,index) => {
54+
return <li key={index}> <b> {data.key} </b>: {data.value} </li>;
55+
})
56+
}
57+
</ul>
58+
);
59+
});
60+
}
61+
62+
render() {
63+
let content = this.getContent();
64+
return(<div>
65+
<Breadcrumb childNode = {this.props.params.user} />
66+
{content}
67+
</div>);
68+
}
69+
}
70+
71+
export default User;

0 commit comments

Comments
 (0)