Refactor fetch, WIP

This commit is contained in:
vrde 2015-06-01 14:22:04 +02:00
parent 9f255d7db7
commit f50d28be98
11 changed files with 152 additions and 34 deletions

View File

@ -14,6 +14,7 @@ class PieceListActions {
PieceListFetcher
.fetch(page, pageSize, search, orderBy, orderAsc)
.then((res) => {
console.log(res);
this.actions.updatePieceList({
page,
pageSize,
@ -23,9 +24,6 @@ class PieceListActions {
'pieceList': res.pieces,
'pieceListCount': res.count
});
})
.catch((err) => {
console.log(err);
});
}

View File

@ -2,12 +2,33 @@
import React from 'react';
import Router from 'react-router';
import promise from 'es6-promise';
promise.polyfill();
import AscribeApp from './components/ascribe_app';
import AppConstants from './constants/application_constants';
import ApiUrls from './constants/api_urls';
import routes from './routes';
import alt from './alt';
import fetch from './utils/fetch';
import AlertDismissable from './components/ascribe_forms/alert';
fetch.defaults({
urlMap: ApiUrls,
http: {
headers: {
'Authorization': 'Basic ' + AppConstants.debugCredentialBase64,
'Accept': 'application/json'
}
},
fatalErrorHandler: (err) => {
console.log(err);
//alert('Something went wrong, please reload the page');
}
});
Router.run(routes, Router.HashLocation, (AscribeApp) => {
React.render(
<AscribeApp />,

View File

@ -28,4 +28,4 @@ let AlertDismissable = React.createClass({
}
});
export default AlertDismissable;
export default AlertDismissable;

View File

@ -1,5 +1,4 @@
import React from 'react';
import ImageViewer from './ascribe_media/image_viewer';
import TransferModalButton from './ascribe_modal/modal_transfer';
import ShareModalButton from './ascribe_modal/modal_share';

View File

View File

@ -2,7 +2,9 @@ import AppConstants from './application_constants';
let apiUrls = {
'ownership_shares_mail' : AppConstants.baseUrl + 'ownership/shares/mail/',
'ownership_transfers' : AppConstants.baseUrl + 'ownership/transfers/'
'ownership_transfers' : AppConstants.baseUrl + 'ownership/transfers/',
'pieces_list': AppConstants.baseUrl + 'pieces/',
'edition': AppConstants.baseUrl + 'editions/${bitcoin_id}/'
};
export default apiUrls;
export default apiUrls;

View File

@ -5,4 +5,4 @@ let constants = {
'aclList': ['edit', 'consign', 'transfer', 'loan', 'share', 'download', 'view', 'delete', 'del_from_collection', 'add_to_collection']
};
export default constants;
export default constants;

View File

@ -1,4 +1,4 @@
import fetch from 'isomorphic-fetch';
import fetch from '../utils/fetch';
import AppConstants from '../constants/application_constants';
import FetchApiUtils from '../utils/fetch_api_utils';
@ -11,13 +11,7 @@ let EditionFetcher = {
*
*/
fetchOne(editionId) {
return fetch(AppConstants.baseUrl + 'editions/' + editionId + '/', {
headers: {
'Authorization': 'Basic ' + AppConstants.debugCredentialBase64
}
}).then(
(res) => res.json()
);
return fetch.get('edition', {'bitcoin_id': editionId});
}
};

View File

@ -1,7 +1,6 @@
import fetch from 'isomorphic-fetch';
import AppConstants from '../constants/application_constants';
import FetchApiUtils from '../utils/fetch_api_utils';
import fetch from '../utils/fetch';
let PieceListFetcher = {
@ -10,21 +9,8 @@ let PieceListFetcher = {
* Can be called with all supplied queryparams the API.
*/
fetch(page, pageSize, search, orderBy, orderAsc) {
let ordering = FetchApiUtils.generateOrderingQueryParams(orderBy, orderAsc);
let params = FetchApiUtils.argsToQueryParams({
page,
pageSize,
search,
ordering
});
return fetch(AppConstants.baseUrl + 'pieces/' + params, {
headers: {
'Authorization': 'Basic ' + AppConstants.debugCredentialBase64
}
}).then((res) => res.json());
return fetch.get('pieces_list', { page, pageSize, search, ordering });
}
};

117
js/utils/fetch.js Normal file
View File

@ -0,0 +1,117 @@
import { default as _fetch } from 'isomorphic-fetch';
import FetchApiUtils from '../utils/fetch_api_utils';
class UrlMapError extends Error {};
class ServerError extends Error {};
class APIError extends Error {};
class Fetch {
_merge(defaults, options) {
let merged = {};
for (let key in defaults) {
merged[key] = defaults[key];
}
for (let key in options) {
merged[key] = options[key];
}
return merged;
}
unpackResponse(response) {
if (response.status >= 500) {
throw new ServerError();
}
return response.text();
}
handleFatalError(err) {
this.fatalErrorHandler(err);
throw new ServerError(err);
}
handleAPIError(json) {
if (!json['success']) {
let error = new APIError();
error.json = json;
throw error;
}
return json;
}
getUrl(url) {
let name = url;
if (!url.match(/^http/)) {
url = this.urlMap[url];
if (!url) {
throw new UrlMapError(`Cannot find a mapping for "${name}"`);
}
}
return url;
}
extractParamsFromUrl(url) {
let re = /\${(\w+)}/g;
let match = null;
let results = [];
while (match = re.exec(url)) {
results.push(match[1]);
}
return results;
}
prepareUrl(url, params) {
let newUrl = this.getUrl(url);
let re = /\${(\w+)}/g;
newUrl = newUrl.replace(re, (match, key) => {
let val = params[key]
if (!val) {
throw new Error(`Cannot find param ${key}`);
}
delete params[key];
return val;
});
if (params && Object.keys(params).length > 0) {
newUrl += FetchApiUtils.argsToQueryParams(params);
}
return newUrl;
}
request(verb, url, options) {
options = options || {};
let merged = this._merge(this.httpOptions, options);
merged['method'] = verb;
let promise = _fetch(url, merged);
return promise.then(this.unpackResponse)
.then(JSON.parse)
.catch(this.handleFatalError.bind(this))
.then(this.handleAPIError);
}
get(url, params, options) {
let newUrl = this.prepareUrl(url, params);
return this.request('get', newUrl, options);
}
post(url, params, options) {
options = options || {};
return this.request('post', url, options);
}
defaults(options) {
this.httpOptions = options.http || {};
this.urlMap = options.urlMap || {};
this.fatalErrorHandler = options.fatalErrorHandler || (() => {});
}
}
let fetch = new Fetch();
export default fetch;

View File

@ -5,6 +5,7 @@
"main": "js/app.js",
"author": "Ascribe",
"license": "Copyright",
"private": true,
"devDependencies": {
"babel-jest": "^4.0.0",
"babelify": "^6.1.2",
@ -32,9 +33,9 @@
"isomorphic-fetch": "^2.0.2",
"object-assign": "^2.0.0",
"react": "^0.13.2",
"react-bootstrap": "~0.22.6",
"react-router": "^0.13.3",
"uglifyjs": "^2.4.10",
"react-bootstrap": "~0.22.6"
"uglifyjs": "^2.4.10"
},
"jest": {
"scriptPreprocessor": "node_modules/babel-jest",