mirror of https://github.com/artf/grapesjs.git
2 changed files with 44 additions and 132 deletions
@ -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), |
|||
}; |
|||
} |
|||
}); |
|||
} |
|||
|
|||
Loading…
Reference in new issue