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 fetch from 'utils/fetch'; |
||||
import { isUndefined, isFunction } from 'underscore'; |
import { Model } from 'common'; |
||||
|
import { isUndefined, isFunction, isString } from 'underscore'; |
||||
|
|
||||
export default Backbone.Model.extend({ |
export default class RemoteStorage extends Model { |
||||
fetch, |
async store(data, opts = {}) { |
||||
|
await this.request(opts.urlStore, this.__props(opts, data), opts); |
||||
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]; |
|
||||
} |
|
||||
|
|
||||
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) { |
request(url, props = {}, opts = {}) { |
||||
this.request(this.get('urlLoad'), { method: 'get' }, clb, clbErr); |
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; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
/** |
__props(opts = {}, data) { |
||||
* Execute remote request |
const typeJson = opts.contentTypeJson; |
||||
* @param {string} url Url |
const headers = opts.headers || {}; |
||||
* @param {Object} [opts={}] Options |
const fetchOpts = opts.fetchOptions || {}; |
||||
* @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'); |
|
||||
const reqHead = 'X-Requested-With'; |
const reqHead = 'X-Requested-With'; |
||||
const typeHead = 'Content-Type'; |
const typeHead = 'Content-Type'; |
||||
const bodyObj = opts.body || {}; |
|
||||
let fetchOptions; |
|
||||
let body; |
let body; |
||||
|
|
||||
for (let param in params) { |
|
||||
bodyObj[param] = params[param]; |
|
||||
} |
|
||||
|
|
||||
if (isUndefined(headers[reqHead])) { |
if (isUndefined(headers[reqHead])) { |
||||
headers[reqHead] = 'XMLHttpRequest'; |
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) { |
if (isUndefined(headers[typeHead]) && typeJson) { |
||||
headers[typeHead] = 'application/json; charset=utf-8'; |
headers[typeHead] = 'application/json; charset=utf-8'; |
||||
} |
} |
||||
|
|
||||
if (typeJson) { |
if (data) { |
||||
body = JSON.stringify(bodyObj); |
if (typeJson) { |
||||
} else { |
body = JSON.stringify(data); |
||||
body = new FormData(); |
} else { |
||||
|
body = new FormData(); |
||||
|
|
||||
for (let bodyKey in bodyObj) { |
for (let key in data) { |
||||
body.append(bodyKey, bodyObj[bodyKey]); |
body.append(key, data[key]); |
||||
|
} |
||||
} |
} |
||||
} |
} |
||||
fetchOptions = { |
|
||||
method: opts.method || 'post', |
|
||||
credentials: this.get('credentials'), |
|
||||
headers |
|
||||
}; |
|
||||
|
|
||||
// Body should only be included on POST method
|
const result = { |
||||
if (fetchOptions.method === 'post') { |
method: body ? 'post' : 'get', |
||||
fetchOptions.body = body; |
credentials: opts.credentials, |
||||
} |
headers, |
||||
|
body, |
||||
const fetchOpts = this.get('fetchOptions') || {}; |
}; |
||||
const addOpts = isFunction(fetchOpts) |
|
||||
? fetchOpts(fetchOptions) |
|
||||
: fetchOptions; |
|
||||
|
|
||||
this.onStart(); |
return { |
||||
this.fetch(url, { |
...result, |
||||
...fetchOptions, |
...(isFunction(fetchOpts) ? fetchOpts(result) : fetchOpts), |
||||
...(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)); |
|
||||
} |
} |
||||
}); |
} |
||||
|
|||||
Loading…
Reference in new issue