From 076a1915fd83ccd6f778159ba658ea674fd94838 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Fri, 11 Mar 2022 15:55:48 +0100 Subject: [PATCH] Refactor RemoteStorage --- src/storage_manager/config/config.js | 9 -- src/storage_manager/model/RemoteStorage.js | 167 ++++++--------------- 2 files changed, 44 insertions(+), 132 deletions(-) diff --git a/src/storage_manager/config/config.js b/src/storage_manager/config/config.js index 75ad7ea0b..5b9de7271 100644 --- a/src/storage_manager/config/config.js +++ b/src/storage_manager/config/config.js @@ -25,9 +25,6 @@ export default { checkLocal: true, }, remote: { - // Custom parameters to pass with the remote request, eg. csrf token - params: {}, - // Custom headers headers: {}, @@ -37,12 +34,6 @@ export default { // Endpoint URL where to load data project urlLoad: '', - //Callback before request - beforeSend(jqXHR, settings) {}, - - //Callback after request - onComplete(jqXHR, status) {}, - // set contentType paramater of $.ajax // true: application/json; charset=utf-8' // false: 'x-www-form-urlencoded' diff --git a/src/storage_manager/model/RemoteStorage.js b/src/storage_manager/model/RemoteStorage.js index 0555628b0..423a4817e 100644 --- a/src/storage_manager/model/RemoteStorage.js +++ b/src/storage_manager/model/RemoteStorage.js @@ -1,146 +1,67 @@ -import Backbone from 'backbone'; import fetch from 'utils/fetch'; -import { isUndefined, isFunction } from 'underscore'; +import { Model } from 'common'; +import { isUndefined, isFunction, isString } from 'underscore'; -export default Backbone.Model.extend({ - fetch, - - defaults: { - urlStore: '', - urlLoad: '', - params: {}, - beforeSend() {}, - onComplete() {}, - contentTypeJson: false, - credentials: 'include', - fetchOptions: '' - }, - - /** - * Triggered before the request is started - * @private - */ - onStart() { - const em = this.get('em'); - const before = this.get('beforeSend'); - before && before(); - }, - - /** - * Triggered on request error - * @param {Object} err Error - * @param {Function} [clbErr] Error callback - * @private - */ - onError(err, clbErr) { - if (clbErr) { - clbErr(err); - } else { - const em = this.get('em'); - console.error(err); - em && em.trigger('storage:error', err); - } - }, - - /** - * Triggered on request response - * @param {string} text Response text - * @private - */ - onResponse(text, clb) { - const em = this.get('em'); - const complete = this.get('onComplete'); - const typeJson = this.get('contentTypeJson'); - const parsable = text && typeof text === 'string'; - const res = typeJson && parsable ? JSON.parse(text) : text; - complete && complete(res); - clb && clb(res); - em && em.trigger('storage:response', res); - }, - - store(data, clb, clbErr) { - const body = {}; - - for (let key in data) { - body[key] = data[key]; - } +export default class RemoteStorage extends Model { + async store(data, opts = {}) { + await this.request(opts.urlStore, this.__props(opts, data), opts); + } - this.request(this.get('urlStore'), { body }, clb, clbErr); - }, + async load(opts) { + return await this.request(opts.urlLoad, this.__props(opts), opts); + } - load(keys, clb, clbErr) { - this.request(this.get('urlLoad'), { method: 'get' }, clb, clbErr); - }, + request(url, props = {}, opts = {}) { + return fetch(url, props) + .then(res => { + const result = res.text(); + const isOk = ((res.status / 200) | 0) === 1; + return isOk ? result : result.then(Promise.reject); + }) + .then(text => { + const parsable = text && isString(text); + return opts.contentTypeJson && parsable ? JSON.parse(text) : text; + }); + } - /** - * Execute remote request - * @param {string} url Url - * @param {Object} [opts={}] Options - * @param {Function} [clb=null] Callback - * @param {Function} [clbErr=null] Error callback - * @private - */ - request(url, opts = {}, clb = null, clbErr = null) { - const typeJson = this.get('contentTypeJson'); - const headers = this.get('headers') || {}; - const params = this.get('params'); + __props(opts = {}, data) { + const typeJson = opts.contentTypeJson; + const headers = opts.headers || {}; + const fetchOpts = opts.fetchOptions || {}; const reqHead = 'X-Requested-With'; const typeHead = 'Content-Type'; - const bodyObj = opts.body || {}; - let fetchOptions; let body; - for (let param in params) { - bodyObj[param] = params[param]; - } - if (isUndefined(headers[reqHead])) { headers[reqHead] = 'XMLHttpRequest'; } - // With `fetch`, have to send FormData without any 'Content-Type' - // https://stackoverflow.com/questions/39280438/fetch-missing-boundary-in-multipart-form-data-post - if (isUndefined(headers[typeHead]) && typeJson) { headers[typeHead] = 'application/json; charset=utf-8'; } - if (typeJson) { - body = JSON.stringify(bodyObj); - } else { - body = new FormData(); + if (data) { + if (typeJson) { + body = JSON.stringify(data); + } else { + body = new FormData(); - for (let bodyKey in bodyObj) { - body.append(bodyKey, bodyObj[bodyKey]); + for (let key in data) { + body.append(key, data[key]); + } } } - fetchOptions = { - method: opts.method || 'post', - credentials: this.get('credentials'), - headers - }; - // Body should only be included on POST method - if (fetchOptions.method === 'post') { - fetchOptions.body = body; - } - - const fetchOpts = this.get('fetchOptions') || {}; - const addOpts = isFunction(fetchOpts) - ? fetchOpts(fetchOptions) - : fetchOptions; + const result = { + method: body ? 'post' : 'get', + credentials: opts.credentials, + headers, + body, + }; - this.onStart(); - this.fetch(url, { - ...fetchOptions, - ...(addOpts || {}) - }) - .then(res => - ((res.status / 200) | 0) == 1 - ? res.text() - : res.text().then(text => Promise.reject(text)) - ) - .then(text => this.onResponse(text, clb)) - .catch(err => this.onError(err, clbErr)); + return { + ...result, + ...(isFunction(fetchOpts) ? fetchOpts(result) : fetchOpts), + }; } -}); +}