mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2025-02-24 13:24:13 -05:00
Move api mixin to lib, remove mixin
The mixin doesn't gain us anything except complexity
This commit is contained in:
parent
56e16bc0dc
commit
d7df1e980f
9 changed files with 109 additions and 103 deletions
|
@ -1,7 +1,6 @@
|
||||||
var classNames = require('classnames');
|
var classNames = require('classnames');
|
||||||
var React = require('react');
|
var React = require('react');
|
||||||
|
|
||||||
var Api = require('../../mixins/api.jsx');
|
|
||||||
var jar = require('../../lib/jar.js');
|
var jar = require('../../lib/jar.js');
|
||||||
var languages = require('../../../languages.json');
|
var languages = require('../../../languages.json');
|
||||||
var Form = require('../forms/form.jsx');
|
var Form = require('../forms/form.jsx');
|
||||||
|
@ -12,9 +11,6 @@ var Select = require('../forms/select.jsx');
|
||||||
*/
|
*/
|
||||||
var LanguageChooser = React.createClass({
|
var LanguageChooser = React.createClass({
|
||||||
type: 'LanguageChooser',
|
type: 'LanguageChooser',
|
||||||
mixins: [
|
|
||||||
Api
|
|
||||||
],
|
|
||||||
getDefaultProps: function () {
|
getDefaultProps: function () {
|
||||||
return {
|
return {
|
||||||
languages: languages,
|
languages: languages,
|
||||||
|
|
|
@ -7,7 +7,7 @@ var injectIntl = ReactIntl.injectIntl;
|
||||||
|
|
||||||
var sessionActions = require('../../../redux/session.js');
|
var sessionActions = require('../../../redux/session.js');
|
||||||
|
|
||||||
var Api = require('../../../mixins/api.jsx');
|
var api = require('../../../lib/api');
|
||||||
var Avatar = require('../../avatar/avatar.jsx');
|
var Avatar = require('../../avatar/avatar.jsx');
|
||||||
var Button = require('../../forms/button.jsx');
|
var Button = require('../../forms/button.jsx');
|
||||||
var Dropdown = require('../../dropdown/dropdown.jsx');
|
var Dropdown = require('../../dropdown/dropdown.jsx');
|
||||||
|
@ -24,9 +24,6 @@ Modal.setAppElement(document.getElementById('view'));
|
||||||
|
|
||||||
var Navigation = React.createClass({
|
var Navigation = React.createClass({
|
||||||
type: 'Navigation',
|
type: 'Navigation',
|
||||||
mixins: [
|
|
||||||
Api
|
|
||||||
],
|
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
return {
|
return {
|
||||||
accountNavOpen: false,
|
accountNavOpen: false,
|
||||||
|
@ -85,7 +82,7 @@ var Navigation = React.createClass({
|
||||||
return '/users/' + this.props.session.session.user.username + '/';
|
return '/users/' + this.props.session.session.user.username + '/';
|
||||||
},
|
},
|
||||||
getMessageCount: function () {
|
getMessageCount: function () {
|
||||||
this.api({
|
api({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
uri: '/users/' + this.props.session.session.user.username + '/messages/count'
|
uri: '/users/' + this.props.session.session.user.username + '/messages/count'
|
||||||
}, function (err, body) {
|
}, function (err, body) {
|
||||||
|
@ -110,7 +107,7 @@ var Navigation = React.createClass({
|
||||||
handleLogIn: function (formData, callback) {
|
handleLogIn: function (formData, callback) {
|
||||||
this.setState({'loginError': null});
|
this.setState({'loginError': null});
|
||||||
formData['useMessages'] = true;
|
formData['useMessages'] = true;
|
||||||
this.api({
|
api({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
host: '',
|
host: '',
|
||||||
uri: '/accounts/login/',
|
uri: '/accounts/login/',
|
||||||
|
@ -142,7 +139,7 @@ var Navigation = React.createClass({
|
||||||
},
|
},
|
||||||
handleLogOut: function (e) {
|
handleLogOut: function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.api({
|
api({
|
||||||
host: '',
|
host: '',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
uri: '/accounts/logout/',
|
uri: '/accounts/logout/',
|
||||||
|
|
79
src/lib/api.js
Normal file
79
src/lib/api.js
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
var defaults = require('lodash.defaults');
|
||||||
|
var xhr = require('xhr');
|
||||||
|
|
||||||
|
var jar = require('./jar');
|
||||||
|
var log = require('./log');
|
||||||
|
var urlParams = require('./url-params');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method that constructs requests to the scratch api.
|
||||||
|
* Custom arguments:
|
||||||
|
* - useCsrf [boolean] – handles unique csrf token retrieval for POST requests. This prevents
|
||||||
|
* CSRF forgeries (see: https://www.squarefree.com/securitytips/web-developers.html#CSRF)
|
||||||
|
*
|
||||||
|
* It also takes in other arguments specified in the xhr library spec.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = function (opts, callback) {
|
||||||
|
defaults(opts, {
|
||||||
|
host: process.env.API_HOST,
|
||||||
|
headers: {},
|
||||||
|
json: {},
|
||||||
|
useCsrf: false
|
||||||
|
});
|
||||||
|
|
||||||
|
defaults(opts.headers, {
|
||||||
|
'X-Requested-With': 'XMLHttpRequest'
|
||||||
|
});
|
||||||
|
|
||||||
|
opts.uri = opts.host + opts.uri;
|
||||||
|
|
||||||
|
if (opts.params) {
|
||||||
|
opts.uri = [opts.uri, urlParams(opts.params)]
|
||||||
|
.join(opts.uri.indexOf('?') === -1 ? '?' : '&');
|
||||||
|
}
|
||||||
|
|
||||||
|
var apiRequest = function (opts) {
|
||||||
|
if (opts.host !== '') {
|
||||||
|
// For IE < 10, we must use XDR for cross-domain requests. XDR does not support
|
||||||
|
// custom headers.
|
||||||
|
defaults(opts, {useXDR: true});
|
||||||
|
delete opts.headers;
|
||||||
|
if (opts.authentication) {
|
||||||
|
var authenticationParams = ['x-token=' + opts.authentication];
|
||||||
|
var parts = opts.uri.split('?');
|
||||||
|
var qs = (parts[1] || '').split('&').concat(authenticationParams).join('&');
|
||||||
|
opts.uri = parts[0] + '?' + qs;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xhr(opts, function (err, res, body) {
|
||||||
|
if (err) log.error(err);
|
||||||
|
// Legacy API responses come as lists, and indicate to redirect the client like
|
||||||
|
// [{success: true, redirect: "/location/to/redirect"}]
|
||||||
|
try {
|
||||||
|
if ('redirect' in body[0]) window.location = body[0].redirect;
|
||||||
|
} catch (err) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
callback(err, body, res);
|
||||||
|
});
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
if (typeof jar.get('scratchlanguage') !== 'undefined') {
|
||||||
|
opts.headers['Accept-Language'] = jar.get('scratchlanguage') + ', en;q=0.8';
|
||||||
|
}
|
||||||
|
if (opts.authentication) {
|
||||||
|
opts.headers['X-Token'] = opts.authentication;
|
||||||
|
}
|
||||||
|
if (opts.useCsrf) {
|
||||||
|
jar.use('scratchcsrftoken', '/csrf_token/', function (err, csrftoken) {
|
||||||
|
if (err) return log.error('Error while retrieving CSRF token', err);
|
||||||
|
opts.json.csrftoken = csrftoken;
|
||||||
|
opts.headers['X-CSRFToken'] = csrftoken;
|
||||||
|
apiRequest(opts);
|
||||||
|
}.bind(this));
|
||||||
|
} else {
|
||||||
|
apiRequest(opts);
|
||||||
|
}
|
||||||
|
};
|
14
src/lib/url-params.js
Normal file
14
src/lib/url-params.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/* Turn an object into an url param string
|
||||||
|
* urlParams({a: 1, b: 2, c: 3})
|
||||||
|
* // a=1&b=2&c=3
|
||||||
|
*/
|
||||||
|
module.exports = function urlParams (values) {
|
||||||
|
return Object
|
||||||
|
.keys(values)
|
||||||
|
.map(function (key) {
|
||||||
|
return [key, values[key]]
|
||||||
|
.map(encodeURIComponent)
|
||||||
|
.join('=');
|
||||||
|
})
|
||||||
|
.join('&');
|
||||||
|
};
|
|
@ -1,76 +0,0 @@
|
||||||
var defaults = require('lodash.defaults');
|
|
||||||
var xhr = require('xhr');
|
|
||||||
|
|
||||||
var jar = require('../lib/jar.js');
|
|
||||||
var log = require('../lib/log.js');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Component mixin that constructs requests to the scratch api.
|
|
||||||
* Custom arguments:
|
|
||||||
* - useCsrf [boolean] – handles unique csrf token retrieval for POST requests. This prevents
|
|
||||||
* CSRF forgeries (see: https://www.squarefree.com/securitytips/web-developers.html#CSRF)
|
|
||||||
*
|
|
||||||
* It also takes in other arguments specified in the xhr library spec.
|
|
||||||
*/
|
|
||||||
var Api = {
|
|
||||||
api: function (opts, callback) {
|
|
||||||
defaults(opts, {
|
|
||||||
host: window.env.API_HOST,
|
|
||||||
headers: {},
|
|
||||||
json: {},
|
|
||||||
useCsrf: false
|
|
||||||
});
|
|
||||||
|
|
||||||
defaults(opts.headers, {
|
|
||||||
'X-Requested-With': 'XMLHttpRequest'
|
|
||||||
});
|
|
||||||
|
|
||||||
opts.uri = opts.host + opts.uri;
|
|
||||||
|
|
||||||
var apiRequest = function (opts) {
|
|
||||||
if (opts.host !== '') {
|
|
||||||
// For IE < 10, we must use XDR for cross-domain requests. XDR does not support
|
|
||||||
// custom headers.
|
|
||||||
defaults(opts, {useXDR: true});
|
|
||||||
delete opts.headers;
|
|
||||||
if (opts.authentication) {
|
|
||||||
var authenticationParams = ['x-token=' + opts.authentication];
|
|
||||||
var parts = opts.uri.split('?');
|
|
||||||
var qs = (parts[1] || '').split('&').concat(authenticationParams).join('&');
|
|
||||||
opts.uri = parts[0] + '?' + qs;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xhr(opts, function (err, res, body) {
|
|
||||||
if (err) log.error(err);
|
|
||||||
// Legacy API responses come as lists, and indicate to redirect the client like
|
|
||||||
// [{success: true, redirect: "/location/to/redirect"}]
|
|
||||||
try {
|
|
||||||
if ('redirect' in body[0]) window.location = body[0].redirect;
|
|
||||||
} catch (err) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
callback(err, body);
|
|
||||||
});
|
|
||||||
}.bind(this);
|
|
||||||
|
|
||||||
if (typeof jar.get('scratchlanguage') !== 'undefined') {
|
|
||||||
opts.headers['Accept-Language'] = jar.get('scratchlanguage') + ', en;q=0.8';
|
|
||||||
}
|
|
||||||
if (opts.authentication) {
|
|
||||||
opts.headers['X-Token'] = opts.authentication;
|
|
||||||
}
|
|
||||||
if (opts.useCsrf) {
|
|
||||||
jar.use('scratchcsrftoken', '/csrf_token/', function (err, csrftoken) {
|
|
||||||
if (err) return log.error('Error while retrieving CSRF token', err);
|
|
||||||
opts.json.csrftoken = csrftoken;
|
|
||||||
opts.headers['X-CSRFToken'] = csrftoken;
|
|
||||||
apiRequest(opts);
|
|
||||||
}.bind(this));
|
|
||||||
} else {
|
|
||||||
apiRequest(opts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = Api;
|
|
|
@ -1,5 +1,5 @@
|
||||||
var keyMirror = require('keymirror');
|
var keyMirror = require('keymirror');
|
||||||
var api = require('../mixins/api.jsx').api;
|
var api = require('../lib/api');
|
||||||
|
|
||||||
var Types = keyMirror({
|
var Types = keyMirror({
|
||||||
SET_DETAILS: null,
|
SET_DETAILS: null,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
var keyMirror = require('keymirror');
|
var keyMirror = require('keymirror');
|
||||||
var api = require('../mixins/api.jsx').api;
|
var api = require('../lib/api');
|
||||||
|
|
||||||
var Types = keyMirror({
|
var Types = keyMirror({
|
||||||
SET_SCHEDULE: null,
|
SET_SCHEDULE: null,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
var keyMirror = require('keymirror');
|
var keyMirror = require('keymirror');
|
||||||
var defaults = require('lodash.defaults');
|
var defaults = require('lodash.defaults');
|
||||||
|
|
||||||
var api = require('../mixins/api.jsx').api;
|
var api = require('../lib/api');
|
||||||
var tokenActions = require('./token.js');
|
var tokenActions = require('./token.js');
|
||||||
|
|
||||||
var Types = keyMirror({
|
var Types = keyMirror({
|
||||||
|
|
|
@ -2,13 +2,12 @@ var connect = require('react-redux').connect;
|
||||||
var injectIntl = require('react-intl').injectIntl;
|
var injectIntl = require('react-intl').injectIntl;
|
||||||
var omit = require('lodash.omit');
|
var omit = require('lodash.omit');
|
||||||
var React = require('react');
|
var React = require('react');
|
||||||
var render = require('../../lib/render.jsx');
|
|
||||||
|
|
||||||
|
var api = require('../../lib/api');
|
||||||
|
var render = require('../../lib/render.jsx');
|
||||||
var sessionActions = require('../../redux/session.js');
|
var sessionActions = require('../../redux/session.js');
|
||||||
var shuffle = require('../../lib/shuffle.js').shuffle;
|
var shuffle = require('../../lib/shuffle.js').shuffle;
|
||||||
|
|
||||||
var Api = require('../../mixins/api.jsx');
|
|
||||||
|
|
||||||
var Activity = require('../../components/activity/activity.jsx');
|
var Activity = require('../../components/activity/activity.jsx');
|
||||||
var AdminPanel = require('../../components/adminpanel/adminpanel.jsx');
|
var AdminPanel = require('../../components/adminpanel/adminpanel.jsx');
|
||||||
var DropdownBanner = require('../../components/dropdown-banner/banner.jsx');
|
var DropdownBanner = require('../../components/dropdown-banner/banner.jsx');
|
||||||
|
@ -25,9 +24,6 @@ require('./splash.scss');
|
||||||
|
|
||||||
var Splash = injectIntl(React.createClass({
|
var Splash = injectIntl(React.createClass({
|
||||||
type: 'Splash',
|
type: 'Splash',
|
||||||
mixins: [
|
|
||||||
Api
|
|
||||||
],
|
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
return {
|
return {
|
||||||
projectCount: 14000000, // gets the shared project count
|
projectCount: 14000000, // gets the shared project count
|
||||||
|
@ -90,42 +86,42 @@ var Splash = injectIntl(React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getActivity: function () {
|
getActivity: function () {
|
||||||
this.api({
|
api({
|
||||||
uri: '/proxy/users/' + this.props.session.session.user.username + '/activity?limit=5'
|
uri: '/proxy/users/' + this.props.session.session.user.username + '/activity?limit=5'
|
||||||
}, function (err, body) {
|
}, function (err, body) {
|
||||||
if (!err) this.setState({activity: body});
|
if (!err) this.setState({activity: body});
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
getFeaturedGlobal: function () {
|
getFeaturedGlobal: function () {
|
||||||
this.api({
|
api({
|
||||||
uri: '/proxy/featured'
|
uri: '/proxy/featured'
|
||||||
}, function (err, body) {
|
}, function (err, body) {
|
||||||
if (!err) this.setState({featuredGlobal: body});
|
if (!err) this.setState({featuredGlobal: body});
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
getFeaturedCustom: function () {
|
getFeaturedCustom: function () {
|
||||||
this.api({
|
api({
|
||||||
uri: '/proxy/users/' + this.props.session.session.user.id + '/featured'
|
uri: '/proxy/users/' + this.props.session.session.user.id + '/featured'
|
||||||
}, function (err, body) {
|
}, function (err, body) {
|
||||||
if (!err) this.setState({featuredCustom: body});
|
if (!err) this.setState({featuredCustom: body});
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
getNews: function () {
|
getNews: function () {
|
||||||
this.api({
|
api({
|
||||||
uri: '/news?limit=3'
|
uri: '/news?limit=3'
|
||||||
}, function (err, body) {
|
}, function (err, body) {
|
||||||
if (!err) this.setState({news: body});
|
if (!err) this.setState({news: body});
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
getProjectCount: function () {
|
getProjectCount: function () {
|
||||||
this.api({
|
api({
|
||||||
uri: '/projects/count/all'
|
uri: '/projects/count/all'
|
||||||
}, function (err, body) {
|
}, function (err, body) {
|
||||||
if (!err) this.setState({projectCount: body.count});
|
if (!err) this.setState({projectCount: body.count});
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
refreshHomepageCache: function () {
|
refreshHomepageCache: function () {
|
||||||
this.api({
|
api({
|
||||||
host: '',
|
host: '',
|
||||||
uri: '/scratch_admin/homepage/clear-cache/',
|
uri: '/scratch_admin/homepage/clear-cache/',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
|
@ -161,7 +157,7 @@ var Splash = injectIntl(React.createClass({
|
||||||
this.setState({emailConfirmationModalOpen: false});
|
this.setState({emailConfirmationModalOpen: false});
|
||||||
},
|
},
|
||||||
handleDismiss: function (cue) {
|
handleDismiss: function (cue) {
|
||||||
this.api({
|
api({
|
||||||
host: '',
|
host: '',
|
||||||
uri: '/site-api/users/set-template-cue/',
|
uri: '/site-api/users/set-template-cue/',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
|
|
Loading…
Reference in a new issue