Skip to content

Commit 43168c5

Browse files
authored
Merge pull request #36 from linuxonrails/port_12_tablehttp_from_ts_to_js_#21
Port 12 TableHttp From TS to JS (ES6 >ES6). Issue #21
2 parents 5fb529c + d1acec0 commit 43168c5

File tree

10 files changed

+432
-0
lines changed

10 files changed

+432
-0
lines changed

12 TableHttp/package.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"name": "samplereact",
3+
"version": "1.0.0",
4+
"description": "In this sample we are going to setup the basic plumbing to \"build\" our project and launch it in a dev server.",
5+
"main": "index.js",
6+
"scripts": {
7+
"start": "webpack-dev-server --inline",
8+
"test": "echo \"Error: no test specified\" && exit 1"
9+
},
10+
"author": "",
11+
"license": "ISC",
12+
"devDependencies": {
13+
"babel-core": "^6.18.2",
14+
"babel-loader": "^6.2.7",
15+
"babel-plugin-transform-runtime": "^6.15.0",
16+
"babel-preset-es2015": "^6.18.0",
17+
"babel-preset-react": "^6.16.0",
18+
"core-js": "^2.4.1",
19+
"css-loader": "^0.25.0",
20+
"file-loader": "^0.9.0",
21+
"html-webpack-plugin": "^2.24.1",
22+
"style-loader": "^0.13.1",
23+
"url-loader": "^0.5.7",
24+
"webpack": "^1.13.3",
25+
"webpack-devserver": "0.0.6"
26+
},
27+
"dependencies": {
28+
"bootstrap": "^3.3.7",
29+
"core-js": "^2.4.1",
30+
"react": "^15.3.2",
31+
"react-dom": "^15.3.2",
32+
"whatwg-fetch": "^1.0.0"
33+
}
34+
}

12 TableHttp/readme.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# 12 Table Http
2+
3+
Let's move forward with the table sample, this time we are going to replace the
4+
mock data by real one.
5+
6+
We will take a startup point sample _11 TableMock_:
7+
8+
Summary steps:
9+
10+
- Install promises dependencies and typescript definitions.
11+
- Update API in order to work with promises and fetch data from Github API.
12+
- Update the _tableComponent_ in order to show this data.
13+
14+
15+
## Prerequisites
16+
17+
Install [Node.js and npm](https://nodejs.org/en/) (v6.6.0 or newer) if they are not already installed on your computer.
18+
19+
> Verify that you are running at least node v6.x.x and npm 3.x.x by running `node -v` and `npm -v` in a terminal/console window. Older versions may produce errors.
20+
21+
## Steps to build it
22+
23+
- Copy the content from _11 TableMock_ and execute:
24+
25+
```
26+
npm install
27+
```
28+
29+
- Let's add the dependencies to manage promises and typescript definitions
30+
31+
- **[core-js](https://github.com/zloirock/core-js)**: includes polyfills for ECMAScript 5, ECMAScript 6: **promises**, symbols, collections, iterators, typed arrays, ECMAScript 7+ proposals, setImmediate, etc.
32+
33+
```
34+
npm install core-js --save
35+
```
36+
37+
- **[whatwg-fetch](https://github.com/github/fetch)**: AJAX calls.
38+
39+
```
40+
npm install whatwg-fetch --save
41+
```
42+
43+
- Let's remove the file _mermberMockData.ts_ in _src/api_ directory.
44+
45+
- Let's define a model entity in _src/model/member.ts_:
46+
47+
```javascript
48+
class MemberEntity {
49+
constructor() {
50+
this.id = -1;
51+
this.login = '';
52+
this.avatar_url = '';
53+
}
54+
}
55+
56+
export default MemberEntity;
57+
58+
```
59+
60+
- Let's replace _memberAPI_ load members with the fetch / promise one:
61+
62+
```javascript
63+
import {} from 'core-js';
64+
import 'whatwg-fetch';
65+
import MemberEntity from '../model/member';
66+
67+
// Sync mock data API, inspired from:
68+
// https://gist.github.com/coryhouse/fd6232f95f9d601158e4
69+
class MemberAPI {
70+
71+
// Just return a copy of the mock data
72+
getAllMembers() {
73+
const gitHubMembersUrl = 'https://api.github.com/orgs/lemoncode/members';
74+
75+
return fetch(gitHubMembersUrl)
76+
.then(response => this.checkStatus(response))
77+
.then(response => this.parseJSON(response))
78+
.then(data => this.resolveMembers(data));
79+
}
80+
81+
checkStatus(response) {
82+
if (!(response.status >= 200 && response.status < 300)) {
83+
const error = new Error(response.statusText);
84+
throw error;
85+
}
86+
return Promise.resolve(response);
87+
}
88+
89+
parseJSON(response) {
90+
return response.json();
91+
}
92+
93+
resolveMembers(data) {
94+
const members = data.map((gitHubMember) => {
95+
const member = new MemberEntity();
96+
97+
member.id = gitHubMember.id;
98+
member.login = gitHubMember.login;
99+
member.avatar_url = gitHubMember.avatar_url;
100+
101+
return member;
102+
});
103+
104+
return Promise.resolve(members);
105+
}
106+
}
107+
108+
const memberAPI = new MemberAPI();
109+
110+
export default memberAPI;
111+
112+
```
113+
114+
- Now it's time to update our _membersTable_ component. <br />
115+
Let's consume the new promise base method to retrieve the users:
116+
117+
```jsx
118+
// Standard react lifecycle function:
119+
// https://facebook.github.io/react/docs/component-specs.html
120+
componentWillMount() {
121+
memberAPI.getAllMembers().then(members =>
122+
this.setState({members: members})
123+
);
124+
}
125+
126+
```
127+
128+
- Let's give a try and check the results
129+
130+
```
131+
npm start
132+
```

12 TableHttp/src/api/memberAPI.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import {} from 'core-js';
2+
import 'whatwg-fetch';
3+
import MemberEntity from '../model/member';
4+
5+
// Sync mock data API, inspired from:
6+
// https://gist.github.com/coryhouse/fd6232f95f9d601158e4
7+
class MemberAPI {
8+
9+
// Just return a copy of the mock data
10+
getAllMembers() {
11+
const gitHubMembersUrl = 'https://api.github.com/orgs/lemoncode/members';
12+
13+
return fetch(gitHubMembersUrl)
14+
.then(response => this.checkStatus(response))
15+
.then(response => this.parseJSON(response))
16+
.then(data => this.resolveMembers(data));
17+
}
18+
19+
checkStatus(response) {
20+
if (!(response.status >= 200 && response.status < 300)) {
21+
const error = new Error(response.statusText);
22+
throw error;
23+
}
24+
return Promise.resolve(response);
25+
}
26+
27+
parseJSON(response) {
28+
return response.json();
29+
}
30+
31+
resolveMembers(data) {
32+
const members = data.map((gitHubMember) => {
33+
const member = new MemberEntity();
34+
35+
member.id = gitHubMember.id;
36+
member.login = gitHubMember.login;
37+
member.avatar_url = gitHubMember.avatar_url;
38+
39+
return member;
40+
});
41+
42+
return Promise.resolve(members);
43+
}
44+
}
45+
46+
const memberAPI = new MemberAPI();
47+
48+
export default memberAPI;

12 TableHttp/src/app.jsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import React from 'react';
2+
import MembersTableComponent from './membersTable';
3+
4+
export class App extends React.Component {
5+
constructor(props) {
6+
super(props);
7+
8+
this.state = {
9+
userName: 'defaultUserName',
10+
};
11+
12+
this.setUsernameState = this.setUsernameState.bind(this);
13+
}
14+
15+
setUsernameState(event) {
16+
// If the state gets more complex we should use object.assign
17+
this.setState({
18+
userName: event.target.value,
19+
});
20+
}
21+
22+
render() {
23+
return (
24+
<div className="col-xs-12">
25+
<MembersTableComponent />
26+
</div>
27+
);
28+
}
29+
}

12 TableHttp/src/index.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Sample 11: TableMock</title>
6+
</head>
7+
<body>
8+
<h1>Sample app</h1>
9+
<div id="root"></div>
10+
</body>
11+
</html>

12 TableHttp/src/main.jsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* global document */
2+
3+
import React from 'react';
4+
import { render } from 'react-dom';
5+
import { App } from './app';
6+
7+
render(
8+
<App />
9+
, document.getElementById('root')
10+
);

12 TableHttp/src/memberRow.jsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import * as React from 'react';
2+
3+
const MemberRow = props => (
4+
<tr>
5+
<td>
6+
<img src={props.member.avatar_url} style={{ maxWidth: '150px' }} alt="Avatar" />
7+
</td>
8+
<td>
9+
<span>{props.member.id}</span>
10+
</td>
11+
<td>
12+
<span>{props.member.login}</span>
13+
</td>
14+
</tr>
15+
);
16+
17+
MemberRow.propTypes = {
18+
// Is impossible to use:
19+
// member: React.PropTypes.instanceOf(MemberEntity),
20+
// with _clone().
21+
member: React.PropTypes.shape({
22+
id: React.PropTypes.number,
23+
avatar_url: React.PropTypes.string,
24+
login: React.PropTypes.string,
25+
}),
26+
};
27+
28+
export default MemberRow;

12 TableHttp/src/membersTable.jsx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import * as React from 'react';
2+
import memberAPI from './api/memberAPI';
3+
import MemberRow from './memberRow';
4+
5+
class MembersTable extends React.Component {
6+
7+
constructor(props) {
8+
super(props);
9+
// set initial state
10+
this.state = { members: [] };
11+
}
12+
13+
// Standard react lifecycle function:
14+
// https://facebook.github.io/react/docs/component-specs.html
15+
componentWillMount() {
16+
memberAPI.getAllMembers().then(members =>
17+
this.setState({ members })
18+
);
19+
}
20+
21+
render() {
22+
return (
23+
<div className="row">
24+
<h2> Members Page</h2>
25+
<table className="table">
26+
<thead>
27+
<tr>
28+
<th>
29+
Avatar
30+
</th>
31+
<th>
32+
Id
33+
</th>
34+
<th>
35+
Name
36+
</th>
37+
</tr>
38+
</thead>
39+
<tbody>
40+
{
41+
this.state.members.map(member =>
42+
<MemberRow key={member.id} member={member} />
43+
)
44+
}
45+
</tbody>
46+
</table>
47+
</div>
48+
);
49+
}
50+
}
51+
52+
export default MembersTable;

12 TableHttp/src/model/member.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class MemberEntity {
2+
constructor() {
3+
this.id = -1;
4+
this.login = '';
5+
this.avatar_url = '';
6+
}
7+
}
8+
9+
export default MemberEntity;

0 commit comments

Comments
 (0)