Skip to content

Commit 3ce7947

Browse files
Merge pull request #39 from ekonstantinidis/use-react
Use React for Live API Endpoints
2 parents bcdc1eb + 3858424 commit 3ce7947

File tree

25 files changed

+642
-254
lines changed

25 files changed

+642
-254
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ dist/
1010
drfdocs.egg-info/
1111

1212
rest_framework_docs/static/node_modules/
13+
rest_framework_docs/static/rest_framework_docs/js/dist.js.map

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ env:
1212
- DJANGO_VERSION=1.9
1313

1414
install:
15+
- cd rest_framework_docs/static/ && npm install && cd ../../
1516
- pip install -r requirements.txt
1617
- pip install -U Django==$DJANGO_VERSION
1718
- pip install codecov

MANIFEST.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ prune rest_framework_docs/static/node_modules
1010

1111
graft rest_framework_docs/static/rest_framework_docs
1212
graft rest_framework_docs/templates/rest_framework_docs
13+
14+
recursive-exclude rest_framework_docs/static/rest_framework_docs dist.js.map index.js
15+
recursive-exclude rest_framework_docs/static/rest_framework_docs/*/* *
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"rules": {
3+
"max-len": [1, 120, 2],
4+
"no-undef": 2,
5+
"no-unreachable": 2,
6+
"no-unused-vars": 2,
7+
"no-undef-init": 2,
8+
"no-multiple-empty-lines": [2, {"max": 2}],
9+
"indent": [2, 2],
10+
"semi": 2,
11+
"strict": 0,
12+
"space-after-keywords": 2,
13+
"space-before-keywords": 2,
14+
"space-before-blocks": 2,
15+
"space-before-function-paren": 0,
16+
"space-infix-ops": 2,
17+
"space-return-throw-case": 2,
18+
"space-unary-ops": 2,
19+
"quotes": [1, "single", "avoid-escape"]
20+
},
21+
"env": {
22+
"browser": true,
23+
"node": true,
24+
"es6": true
25+
},
26+
"ecmaFeatures": {
27+
"jsx": true,
28+
"modules": true
29+
},
30+
"plugins": [
31+
"react"
32+
]
33+
}

rest_framework_docs/static/package.json

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@
66
"scripts": {
77
"build-font-awesome": "cp -r node_modules/font-awesome/fonts rest_framework_docs/",
88
"build-bootstrap-fonts": "cp -r node_modules/bootstrap/fonts rest_framework_docs/",
9+
"build-js": "webpack",
910
"build-less": "lessc --clean-css rest_framework_docs/less/style.less rest_framework_docs/css/style.css",
11+
"watch-js": "webpack --progress --colors --watch",
1012
"watch-less": "watch 'npm run build-less' rest_framework_docs/less/",
11-
"watch": "npm run watch-less",
12-
"build": "npm run build-font-awesome && npm run build-bootstrap-fonts && npm run build-less",
13+
"watch": "npm run watch-js & npm run watch-less",
14+
"build": "npm run build-font-awesome && npm run build-bootstrap-fonts && npm run build-js && npm run build-less",
15+
"release-js": "webpack --config webpack.rel.config.js",
16+
"release": "npm run build-font-awesome && npm run build-bootstrap-fonts && npm run release-js && npm run build-less",
1317
"start": "npm run build && npm run watch-less",
14-
"test": "echo \"Error: no test specified\" && exit 1"
18+
"lint": "eslint 'rest_framework_docs/js/' --ignore-pattern 'rest_framework_docs/js/dist.js'",
19+
"test": "npm run lint"
1520
},
1621
"repository": {
1722
"type": "git",
@@ -32,11 +37,26 @@
3237
"dependencies": {
3338
"bootstrap": "=3.3.6",
3439
"bootswatch": "=3.3.6",
35-
"font-awesome": "=4.5.0"
40+
"font-awesome": "=4.5.0",
41+
"jquery": "=1.11.3",
42+
"react": "=0.14.3",
43+
"react-dom": "=0.14.3",
44+
"react-modal": "=0.6.1",
45+
"superagent": "=1.6.1",
46+
"underscore": "=1.8.3",
47+
"underscore.string": "=3.2.2"
3648
},
3749
"devDependencies": {
50+
"babel-core": "=6.3.26",
51+
"babel-eslint": "=4.1.6",
52+
"babel-loader": "=6.2.0",
53+
"babel-preset-es2015": "=6.3.13",
54+
"babel-preset-react": "=6.3.13",
55+
"eslint": "=1.10.3",
56+
"eslint-plugin-react": "=3.11.3",
3857
"less": "=2.5.3",
3958
"less-plugin-clean-css": "=1.5.1",
40-
"watch": "=0.16.0"
59+
"watch": "=0.16.0",
60+
"webpack": "=1.12.9"
4161
}
4262
}

rest_framework_docs/static/rest_framework_docs/css/style.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
var React = require('react');
2+
3+
var Header = React.createClass({
4+
5+
render: function () {
6+
return (
7+
<h5 className='section-title'>{this.props.title}</h5>
8+
);
9+
}
10+
});
11+
12+
module.exports = Header;
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
var React = require('react');
2+
3+
var Input = React.createClass({
4+
5+
handleChange: function (value) {
6+
this.props.onChange(value);
7+
},
8+
9+
render: function () {
10+
return (
11+
<div className="form-group">
12+
<label
13+
htmlFor={this.props.name}
14+
className="col-sm-4 control-label">
15+
{this.props.name}
16+
</label>
17+
<div className="col-sm-8">
18+
<input
19+
type={this.props.type}
20+
className="form-control input-sm"
21+
id={this.props.name}
22+
placeholder={this.props.placeholder}
23+
onChange={this.handleChange}
24+
value={this.props.value}
25+
required={this.props.required} />
26+
</div>
27+
</div>
28+
);
29+
}
30+
});
31+
32+
module.exports = Input;
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
var React = require('react');
2+
var APIRequest = require('superagent');
3+
4+
var RequestUtils = require('../utils/request');
5+
var Request = require('./request');
6+
var Response = require('./response');
7+
8+
var LiveAPIEndpoints = React.createClass({
9+
10+
getInitialState: function() {
11+
return {
12+
endpoint: this.props.endpoint,
13+
response: null
14+
};
15+
},
16+
17+
getData: function () {
18+
var method = this.refs.request.state.selectedMethod;
19+
return RequestUtils.shouldAddData(method) ? null : (
20+
this.refs.request.state.data
21+
);
22+
},
23+
24+
makeRequest: function (event) {
25+
event.preventDefault();
26+
27+
var self = this;
28+
var request = this.refs.request.state;
29+
30+
var headers = {};
31+
if (this.refs.request.state.headers.authorization) {
32+
headers['Authorization'] = this.refs.request.state.headers.authorization;
33+
};
34+
35+
var data = this.getData();
36+
37+
// Now Make the Request
38+
APIRequest(request.selectedMethod, request.endpoint.path)
39+
.set(headers)
40+
.send(data)
41+
.end(function (err, res) {
42+
self.setState({
43+
response: res
44+
});
45+
});
46+
},
47+
48+
render: function () {
49+
return (
50+
<form className="form-horizontal" onSubmit={this.makeRequest}>
51+
<div className="modal-body">
52+
<div className="row">
53+
<div className="col-md-6 request">
54+
<Request endpoint={this.state.endpoint} ref='request' />
55+
</div>
56+
<div className="col-md-6 response">
57+
<Response payload={this.state.response} />
58+
</div>
59+
</div>
60+
</div>
61+
<div className="modal-footer">
62+
<button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
63+
<button type="submit" className="btn btn-primary">Send</button>
64+
</div>
65+
</form>
66+
);
67+
}
68+
});
69+
70+
module.exports = LiveAPIEndpoints;
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
var React = require('react');
2+
3+
var Header = require('./helpers/header');
4+
var Headers = require('./request/headers');
5+
var FieldsData = require('./request/fields-data');
6+
var FieldUrl = require('./request/field-url');
7+
var Methods = require('./request/methods');
8+
var RequestUtils = require('../utils/request');
9+
10+
var Request = React.createClass({
11+
getInitialState: function () {
12+
return {
13+
data: {},
14+
endpoint: null,
15+
headers: {},
16+
selectedMethod: null,
17+
};
18+
},
19+
20+
componentWillMount: function() {
21+
var endpoint = this.props.endpoint;
22+
var headers = this.state.headers;
23+
headers['authorization'] = window.token ? window.token : '';
24+
25+
this.setState({
26+
endpoint: endpoint,
27+
headers: headers,
28+
selectedMethod: endpoint['methods'][0]
29+
});
30+
},
31+
32+
setSelectedMethod: function (method) {
33+
this.setState({
34+
selectedMethod: method
35+
});
36+
},
37+
38+
handleUrlChange: function (event) {
39+
var endpoint = this.state.endpoint;
40+
endpoint.path = event.target.value;
41+
42+
this.setState({
43+
endpoint: endpoint
44+
});
45+
},
46+
47+
handleHeaderChange: function (value, fieldName) {
48+
var headers = this.state.headers;
49+
headers[fieldName] = value;
50+
this.setState({
51+
headers: headers
52+
});
53+
},
54+
55+
handleDataFieldChange: function (value, fieldName) {
56+
var data = this.state.data;
57+
data[fieldName] = value;
58+
this.setState({
59+
data: data
60+
});
61+
},
62+
63+
render: function () {
64+
var endpoint = this.state.endpoint;
65+
return (
66+
<div>
67+
<h3>Request</h3>
68+
69+
<FieldUrl
70+
name='urlEndpoint'
71+
url={endpoint.path}
72+
onChange={this.handleUrlChange} />
73+
74+
<Methods
75+
methods={this.state.endpoint.methods}
76+
selectedMethod={this.state.selectedMethod}
77+
setMethod={this.setSelectedMethod} />
78+
79+
<Headers
80+
headers={this.state.headers}
81+
permissions={this.state.endpoint.permissions}
82+
handleHeaderChange={this.handleHeaderChange} />
83+
84+
{RequestUtils.shouldAddData(this.state.method) ? null : (
85+
<div>
86+
{this.state.endpoint.fields.length ? <Header title='Data' /> : null}
87+
<FieldsData
88+
fields={endpoint.fields}
89+
data={this.state.data}
90+
onChange={this.handleDataFieldChange} />
91+
</div>
92+
)}
93+
</div>
94+
);
95+
}
96+
});
97+
98+
module.exports = Request;

0 commit comments

Comments
 (0)