diff --git a/src/asset_manager/config/config.js b/src/asset_manager/config/config.js index 531ddfa1e..4551c2a58 100644 --- a/src/asset_manager/config/config.js +++ b/src/asset_manager/config/config.js @@ -8,6 +8,25 @@ module.exports = { // Url where uploads will be send, set false to disable upload upload: 'http://localhost/assets/upload', + // Custom headers to pass with the upload request + headers: {}, + + // Custom parameters to pass with the upload request, eg. csrf token + params: {}, + + // If true, tries to add automatically uploaded assets. + // To make it work the server should respond with a JSON containing assets + // in a data key, eg: + // { + // data: [ + // 'https://.../image.png', + // ... + // {src: 'https://.../image2.png'}, + // ... + // ] + // } + autoAdd: 1, + // Text on upload input uploadText: 'Drop files here or click to upload', diff --git a/src/asset_manager/view/FileUploader.js b/src/asset_manager/view/FileUploader.js index a0f0cf0d2..817900ae7 100644 --- a/src/asset_manager/view/FileUploader.js +++ b/src/asset_manager/view/FileUploader.js @@ -1,15 +1,14 @@ -var Backbone = require('backbone'); -var fileUploaderTemplate = ` -
-
<%= title %>
- multiple/> -
-
-`; +import fetch from 'utils/fetch'; module.exports = Backbone.View.extend({ - template: _.template(fileUploaderTemplate), + template: _.template(` +
+
<%= title %>
+ multiple/> +
+
+ `), events: {}, @@ -32,18 +31,79 @@ module.exports = Backbone.View.extend({ this.delegateEvents(); }, + onUploadStart() { + const em = this.config.em; + em && em.trigger('asset:upload:start'); + }, + + onUploadEnd() { + const em = this.config.em; + em && em.trigger('asset:upload:end'); + }, + + onUploadError(err) { + console.error(err); + this.onUploadEnd(err); + }, + + onUploadResponse(res) { + const em = this.config.em; + const config = this.config; + const target = this.target; + em && em.trigger('asset:upload:response', res); + + if (config.autoAdd && target) { + if ((req.status/200|0) == 1) { + const json = JSON.parse(req.responseText); + target.add(json.data); + } else { + onUploadError(res); + return; + } + } + + this.onUploadEnd(res); + }, + /** * Upload files * @param {Object} e Event + * @return {Promise} * @private * */ uploadFile(e) { - var files = e.dataTransfer ? e.dataTransfer.files : e.target.files, - formData = new FormData(); - for (var i = 0; i < files.length; i++) { - formData.append('files[]', files[i]); - } + const files = e.dataTransfer ? e.dataTransfer.files : e.target.files; + const formData = new FormData(); + const config = this.config; + const params = config.params; + + for (let i = 0; i < files.length; i++) { + formData.append('files[]', files[i]); + } + + for (let param in params) { + formData.append(param, params[param]); + } + var target = this.target; + const url = config.upload; + + if (url) { + this.onUploadStart(); + return fetch(url, { + method: 'post', + credentials: 'include', + headers: config.headers, + body: formData, + }).then(this.onUploadResponse) + .catch(this.onUploadError); + } + + //onStart upload:start + //onEnd upload:end + //onResponse upload:response + //autoAdd + /* $.ajax({ url : this.config.upload, type : 'POST', @@ -53,7 +113,7 @@ module.exports = Backbone.View.extend({ xhrFields : { onprogress(e) { if (e.lengthComputable) { - /*var result = e.loaded / e.total * 100 + '%';*/ + var result = e.loaded / e.total * 100 + '%'; } }, onload(e) { @@ -66,6 +126,8 @@ module.exports = Backbone.View.extend({ }).always(() => { //turnOff loading }); + + */ }, /** @@ -124,6 +186,7 @@ module.exports = Backbone.View.extend({ const onDrop = (e) => { cleanEditorElCls(); e.preventDefault(); + e.stopPropagation(); this.uploadFile(e); if (c.openAssetsOnDrop && editor) { diff --git a/src/editor/index.js b/src/editor/index.js index fc6130ba9..e9ab6a2b4 100644 --- a/src/editor/index.js +++ b/src/editor/index.js @@ -32,20 +32,23 @@ * ``` * * **Available Events** - * `component:add` - Triggered when a new component is added to the editor, the model is passed as an argument to the callback - * `component:update` - Triggered when a component is, generally, updated (moved, styled, etc.) - * `component:update:{propertyName}` - Listen any property change - * `component:styleUpdate` - Triggered when the style of the component is updated - * `component:styleUpdate:{propertyName}` - Listen for a specific style property change - * `styleManager:change` - Triggered on style property change from new selected component, the view of the property is passed as an argument to the callback - * `styleManager:change:{propertyName}` - As above but for a specific style property - * `storage:load` - Triggered when something was loaded from the storage, loaded object passed as an argumnet - * `storage:store` - Triggered when something is stored to the storage, stored object passed as an argumnet - * `selector:add` - Triggers when a new selector/class is created - * `canvasScroll` - Triggered when the canvas is scrolled - * `run:{commandName}` - Triggered when some command is called to run (eg. editor.runCommand('preview')) - * `stop:{commandName}` - Triggered when some command is called to stop (eg. editor.stopCommand('preview')) - * `load` - When the editor is loaded + * * `component:add` - Triggered when a new component is added to the editor, the model is passed as an argument to the callback + * * `component:update` - Triggered when a component is, generally, updated (moved, styled, etc.) + * * `component:update:{propertyName}` - Listen any property change + * * `component:styleUpdate` - Triggered when the style of the component is updated + * * `component:styleUpdate:{propertyName}` - Listen for a specific style property change + * * `asset:upload:start` - Before the upload is started + * * `asset:upload:end` - After the upload is ended + * * `asset:upload:response` - On upload response, passes a response object as the argument + * * `styleManager:change` - Triggered on style property change from new selected component, the view of the property is passed as an argument to the callback + * * `styleManager:change:{propertyName}` - As above but for a specific style property + * * `storage:load` - Triggered when something was loaded from the storage, loaded object passed as an argumnet + * * `storage:store` - Triggered when something is stored to the storage, stored object passed as an argumnet + * * `selector:add` - Triggers when a new selector/class is created + * * `canvasScroll` - Triggered when the canvas is scrolled + * * `run:{commandName}` - Triggered when some command is called to run (eg. editor.runCommand('preview')) + * * `stop:{commandName}` - Triggered when some command is called to stop (eg. editor.stopCommand('preview')) + * * `load` - When the editor is loaded * * @module Editor * @param {Object} config Configurations diff --git a/src/utils/fetch.js b/src/utils/fetch.js index 82b0d23d3..adfd32b28 100644 --- a/src/utils/fetch.js +++ b/src/utils/fetch.js @@ -12,7 +12,7 @@ export default typeof fetch == 'function' ? fetch.bind() : (url, options) => { req.setRequestHeader(k, options.headers[k]); } - req.onload = e => res(e.target.responseText, req); + req.onload = e => res(req); req.onerror = rej; // Actually, fetch doesn't support onProgress feature