From ea4fa3bd8e2838965ae8be68f8a0fca63950d464 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Thu, 11 Jan 2018 14:42:35 +0100 Subject: [PATCH 01/22] Create Droppable class for the canvas --- src/utils/Droppable.js | 133 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 src/utils/Droppable.js diff --git a/src/utils/Droppable.js b/src/utils/Droppable.js new file mode 100644 index 000000000..3357413ff --- /dev/null +++ b/src/utils/Droppable.js @@ -0,0 +1,133 @@ +import { on, off } from 'utils/mixins'; +import { bindAll } from 'underscore'; + +export class Droppable { + + constructor(em) { + this.em = em; + this.el = this.em.get('DomComponents').getWrapper().getEl(); + this.counter = 0; + bindAll(this, 'handleDragEnter', 'handleDragOver', 'handleDrop', 'handleDragLeave'); + on(el, 'dragenter', this.handleDragEnter); + on(el, 'dragover', this.handleDragOver); + on(el, 'drop', this.handleDrop); + on(el, 'dragleave', this.handleDragLeave); + + return this; + } + + endDrop(cancel) { + this.counter = 0; + this.over = 0; + console.log('DROP END'); + // force out like in BlockView + const sorter = this.sorter; + cancel && (sorter.moved = 0); + this.em.set('dragContent', ''); + sorter.endMove(); + } + + handleDragLeave(ev) { + this.updateCounter(-1); + } + + updateCounter(value) { + this.counter += value; + if (this.counter === 0) { + this.endDrop(1); + } + } + + + handleDragEnter(ev) { + this.updateCounter(1); + if (this.over) return; + this.over = 1; + console.log('IM IN'); + + + var utils = this.em.get('Utils'); + var canvas = this.em.get('Canvas'); + this.sorter = new utils.Sorter({ + container: canvas.getBody(), + placer: canvas.getPlacerEl(), + eventMoving: 'mousemove dragover', + containerSel: '*', + itemSel: '*', + pfx: 'gjs-', + onStart: () => { this.em.stopDefault() }, + onEndMove: () => { this.em.runDefault() }, + document: canvas.getFrameEl().contentDocument, + direction: 'a', + wmargin: 1, + nested: 1, + em, + canvasRelative: 1, + }); + const content = this.getContentByData(ev.dataTransfer) || '
'; + this.sorter.setDropContent(content);// should not be empty + this.sorter.startSort(this.el); + } + + /** + * Always need to have this handler active for enabling the drop + * @param {Event} ev + */ + handleDragOver(ev) { + ev.preventDefault(); + } + + + handleDrop(ev) { + ev.preventDefault(); + var content = this.getContentByData(ev.dataTransfer); + ev.target.style.border = ''; + if (content) { + this.sorter.setDropContent(content); + } else { + this.sorter.moved = 0; + } + this.endDrop(); + } + + getContentByData(dataTransfer) { + let result = dataTransfer.getData('text'); + let dragContent = this.em.get('dragContent'); + const types = dataTransfer.types; + const files = dataTransfer.files; + console.log('Files', files); + + const items = dataTransfer.items; + for (var i = 0; i < items.length; i++) console.log('DataType', items[i]); + + if (files.length) { + result = []; + for (let i = 0; i < files.length; i++) { + const file = files[i]; + result.push({ + type: 'image', + attributes: { alt: file.name } + }); + } + const fu = this.em.get('AssetManager').FileUploader(); + fu.uploadFile({ dataTransfer }, res => console.log('RES upload', res)); + } else if (types.indexOf('text/html') >= 0) { + result = dataTransfer.getData('text/html').replace(/<\/?meta[^>]*>/g,''); + } else if (types.indexOf('text/uri-list') >= 0) { + result = { + type: 'link', + attributes: { href: result }, + content: result, + } + } else if (dragContent) { + result = dragContent; + } else { + result = result && `
${result}
`; + } + + //this.uploadFile(e); + console.log('CONTENT', result); + // TODO result = clbContent(result); + return result; + } +} From 431da8b4b3163cdbd143763bac15b3312949fe47 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Thu, 11 Jan 2018 14:44:45 +0100 Subject: [PATCH 02/22] Update precommit command --- package.json | 2 +- src/utils/Droppable.js | 35 ++++++++++++++++++++++------------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 3f3be32e7..954a6fe7e 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "scripts": { "lint": "eslint src", "check": "npm run lint && npm run test", - "precommit": "npm run format && git add", + "precommit": "npm run format && git add .", "build": "npm run check && npm run v:patch && npm run build-dev && webpack --env=prod", "build-n": "npm run check && npm run build:css && webpack --env=prod", "build-dev": "webpack --env=dev && npm run build:css", diff --git a/src/utils/Droppable.js b/src/utils/Droppable.js index 3357413ff..29ba28c96 100644 --- a/src/utils/Droppable.js +++ b/src/utils/Droppable.js @@ -2,12 +2,20 @@ import { on, off } from 'utils/mixins'; import { bindAll } from 'underscore'; export class Droppable { - constructor(em) { this.em = em; - this.el = this.em.get('DomComponents').getWrapper().getEl(); + this.el = this.em + .get('DomComponents') + .getWrapper() + .getEl(); this.counter = 0; - bindAll(this, 'handleDragEnter', 'handleDragOver', 'handleDrop', 'handleDragLeave'); + bindAll( + this, + 'handleDragEnter', + 'handleDragOver', + 'handleDrop', + 'handleDragLeave' + ); on(el, 'dragenter', this.handleDragEnter); on(el, 'dragover', this.handleDragOver); on(el, 'drop', this.handleDrop); @@ -38,14 +46,12 @@ export class Droppable { } } - handleDragEnter(ev) { this.updateCounter(1); if (this.over) return; this.over = 1; console.log('IM IN'); - var utils = this.em.get('Utils'); var canvas = this.em.get('Canvas'); this.sorter = new utils.Sorter({ @@ -55,17 +61,21 @@ export class Droppable { containerSel: '*', itemSel: '*', pfx: 'gjs-', - onStart: () => { this.em.stopDefault() }, - onEndMove: () => { this.em.runDefault() }, + onStart: () => { + this.em.stopDefault(); + }, + onEndMove: () => { + this.em.runDefault(); + }, document: canvas.getFrameEl().contentDocument, direction: 'a', wmargin: 1, nested: 1, em, - canvasRelative: 1, + canvasRelative: 1 }); const content = this.getContentByData(ev.dataTransfer) || '
'; - this.sorter.setDropContent(content);// should not be empty + this.sorter.setDropContent(content); // should not be empty this.sorter.startSort(this.el); } @@ -77,7 +87,6 @@ export class Droppable { ev.preventDefault(); } - handleDrop(ev) { ev.preventDefault(); var content = this.getContentByData(ev.dataTransfer); @@ -112,13 +121,13 @@ export class Droppable { const fu = this.em.get('AssetManager').FileUploader(); fu.uploadFile({ dataTransfer }, res => console.log('RES upload', res)); } else if (types.indexOf('text/html') >= 0) { - result = dataTransfer.getData('text/html').replace(/<\/?meta[^>]*>/g,''); + result = dataTransfer.getData('text/html').replace(/<\/?meta[^>]*>/g, ''); } else if (types.indexOf('text/uri-list') >= 0) { result = { type: 'link', attributes: { href: result }, - content: result, - } + content: result + }; } else if (dragContent) { result = dragContent; } else { From fb1548669fdbabb6ef9e3bad41741fd9b64a0e5c Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Thu, 11 Jan 2018 14:55:33 +0100 Subject: [PATCH 03/22] Add `dragover` event in the Sorter --- src/utils/Sorter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/Sorter.js b/src/utils/Sorter.js index 36307504f..2b919e53e 100644 --- a/src/utils/Sorter.js +++ b/src/utils/Sorter.js @@ -277,7 +277,7 @@ module.exports = Backbone.View.extend({ srcModel && srcModel.set && srcModel.set('status', 'freezed'); } - on(container, 'mousemove', this.onMove); + on(container, 'mousemove dragover', this.onMove); on(docs, 'mouseup', this.endMove); on(docs, 'keydown', this.rollback); onStart && onStart(); @@ -906,7 +906,7 @@ module.exports = Backbone.View.extend({ var created; const docs = this.getDocuments(); const container = this.getContainerEl(); - off(container, 'mousemove', this.onMove); + off(container, 'mousemove dragover', this.onMove); off(docs, 'mouseup', this.endMove); off(docs, 'keydown', this.rollback); //this.$document.off('mouseup', this.endMove); From 1b400d9f1ace16499a0b8fa1c115ccaf2c2628aa Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Thu, 11 Jan 2018 15:00:49 +0100 Subject: [PATCH 04/22] Make blocks draggable --- src/block_manager/view/BlockView.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/block_manager/view/BlockView.js b/src/block_manager/view/BlockView.js index 950d370ac..810641a89 100644 --- a/src/block_manager/view/BlockView.js +++ b/src/block_manager/view/BlockView.js @@ -2,7 +2,8 @@ import { on, off } from 'utils/mixins'; module.exports = Backbone.View.extend({ events: { - mousedown: 'startDrag' + mousedown: 'startDrag', + dragstart: 'handleDragStart' }, initialize(o, config = {}) { @@ -17,23 +18,24 @@ module.exports = Backbone.View.extend({ * @private */ startDrag(e) { + const config = this.config; //Right or middel click - if (e.button !== 0) { - return; - } - - if (!this.config.getSorter) { - return; - } - - this.config.em.refreshCanvas(); - var sorter = this.config.getSorter(); + if (e.button !== 0 || !config.getSorter || this.el.draggable) return; + config.em.refreshCanvas(); + const sorter = config.getSorter(); sorter.setDragHelper(this.el, e); sorter.setDropContent(this.model.get('content')); sorter.startSort(this.el); on(document, 'mouseup', this.endDrag); }, + handleDragStart(ev) { + const content = this.model.get('content'); + // Can't put the content in dataTransfer as it will not be available + // on `dragenter` event for security reason + this.config.em.set('dragContent', content); + }, + /** * Drop block * @private @@ -58,6 +60,7 @@ module.exports = Backbone.View.extend({ el.innerHTML = `
${this.model.get( 'label' )}
`; + el.setAttribute('draggable', true); return this; } }); From 17557edac51aba72089f4a0f5af82d214176b2e9 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Thu, 11 Jan 2018 15:02:04 +0100 Subject: [PATCH 05/22] Update BlockView --- src/block_manager/view/BlockView.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/block_manager/view/BlockView.js b/src/block_manager/view/BlockView.js index 810641a89..8dd766cc5 100644 --- a/src/block_manager/view/BlockView.js +++ b/src/block_manager/view/BlockView.js @@ -56,10 +56,9 @@ module.exports = Backbone.View.extend({ const el = this.el; const pfx = this.ppfx; const className = `${pfx}block`; + const label = this.model.get('label'); el.className += ` ${className} ${pfx}one-bg ${pfx}four-color-h`; - el.innerHTML = `
${this.model.get( - 'label' - )}
`; + el.innerHTML = `
${label}
`; el.setAttribute('draggable', true); return this; } From 563a478b74744b6ed9430a66fdaa4ee080da8a8f Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Thu, 11 Jan 2018 15:05:07 +0100 Subject: [PATCH 06/22] Make the FileUploader receive the callback --- src/asset_manager/view/FileUploader.js | 31 +++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/asset_manager/view/FileUploader.js b/src/asset_manager/view/FileUploader.js index 54291dca1..2c7098094 100644 --- a/src/asset_manager/view/FileUploader.js +++ b/src/asset_manager/view/FileUploader.js @@ -72,7 +72,7 @@ module.exports = Backbone.View.extend( * @param {string} text Response text * @private */ - onUploadResponse(text) { + onUploadResponse(text, clb) { const em = this.config.em; const config = this.config; const target = this.target; @@ -84,6 +84,7 @@ module.exports = Backbone.View.extend( } this.onUploadEnd(text); + clb && clb(json); }, /** @@ -92,7 +93,7 @@ module.exports = Backbone.View.extend( * @return {Promise} * @private * */ - uploadFile(e) { + uploadFile(e, clb) { const files = e.dataTransfer ? e.dataTransfer.files : e.target.files; const body = new FormData(); const config = this.config; @@ -129,7 +130,7 @@ module.exports = Backbone.View.extend( ? res.text() : res.text().then(text => Promise.reject(text)) ) - .then(text => this.onUploadResponse(text)) + .then(text => this.onUploadResponse(text, clb)) .catch(err => this.onUploadError(err)); } }, @@ -235,7 +236,7 @@ module.exports = Backbone.View.extend( } }, { - embedAsBase64: function(e) { + embedAsBase64: function(e, clb) { // List files dropped const files = e.dataTransfer ? e.dataTransfer.files : e.target.files; const response = { data: [] }; @@ -268,6 +269,26 @@ module.exports = Backbone.View.extend( type = file.type; } + /* + // Show local video files, http://jsfiddle.net/dsbonev/cCCZ2/embedded/result,js,html,css/ + var URL = window.URL || window.webkitURL + var file = this.files[0] + var type = file.type + var videoNode = document.createElement('video'); + var canPlay = videoNode.canPlayType(type) // can use also for 'audio' types + if (canPlay === '') canPlay = 'no' + var message = 'Can play type "' + type + '": ' + canPlay + var isError = canPlay === 'no' + displayMessage(message, isError) + + if (isError) { + return + } + + var fileURL = URL.createObjectURL(file) + videoNode.src = fileURL + */ + // If it's an image, try to find its size if (type === 'image') { const data = { @@ -316,7 +337,7 @@ module.exports = Backbone.View.extend( Promise.all(promises).then( data => { response.data = data; - this.onUploadResponse(response); + this.onUploadResponse(response, clb); }, error => { this.onUploadError(error); From 8a14e5f48ec01bbccf74d97f99335470814d3228 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Thu, 11 Jan 2018 15:07:38 +0100 Subject: [PATCH 07/22] Prepare local upload of video files --- src/asset_manager/view/FileUploader.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/asset_manager/view/FileUploader.js b/src/asset_manager/view/FileUploader.js index 2c7098094..ef5a42338 100644 --- a/src/asset_manager/view/FileUploader.js +++ b/src/asset_manager/view/FileUploader.js @@ -289,6 +289,25 @@ module.exports = Backbone.View.extend( videoNode.src = fileURL */ + /* + // Show local video files + var file = this.files[0] + var type = file.type + var videoNode = document.createElement('video'); + var canPlay = videoNode.canPlayType(type) // can use also for 'audio' types + if (canPlay === '') canPlay = 'no' + var message = 'Can play type "' + type + '": ' + canPlay + var isError = canPlay === 'no' + displayMessage(message, isError) + + if (isError) { + return + } + + var fileURL = URL.createObjectURL(file) + videoNode.src = fileURL + */ + // If it's an image, try to find its size if (type === 'image') { const data = { From b0f87d75fb57fc7367e3d78c0df1d848edc651b9 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Thu, 11 Jan 2018 15:15:48 +0100 Subject: [PATCH 08/22] Update precommit with lint-staged --- package-lock.json | 643 +++++++++++++++++++++++++++++++++++++++++ package.json | 6 +- src/utils/Droppable.js | 5 +- 3 files changed, 649 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index c96446667..8c08aac06 100644 --- a/package-lock.json +++ b/package-lock.json @@ -150,6 +150,12 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, + "any-observable": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.2.0.tgz", + "integrity": "sha1-xnhwBYADV5AJCD9UrAq6+1wz0kI=", + "dev": true + }, "anymatch": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", @@ -183,6 +189,12 @@ } } }, + "app-root-path": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.0.1.tgz", + "integrity": "sha1-zWLc+OT9WkF+/GZNLlsQZTxlG0Y=", + "dev": true + }, "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -2059,6 +2071,30 @@ "restore-cursor": "2.0.0" } }, + "cli-spinners": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", + "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=", + "dev": true + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "dev": true, + "requires": { + "slice-ansi": "0.0.4", + "string-width": "1.0.2" + }, + "dependencies": { + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + } + } + }, "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", @@ -2368,6 +2404,29 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "cosmiconfig": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-3.1.0.tgz", + "integrity": "sha512-zedsBhLSbPBms+kE7AH4vHg6JsKDz6epSv2/+5XHs8ILHlgDciSJfSWf8sX9aQ52Jb7KI7VswUTsLpR/G0cr2Q==", + "dev": true, + "requires": { + "is-directory": "0.3.1", + "js-yaml": "3.10.0", + "parse-json": "3.0.0", + "require-from-string": "2.0.1" + }, + "dependencies": { + "parse-json": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-3.0.0.tgz", + "integrity": "sha1-+m9HsY4jgm6tMvJj50TQ4ehH+xM=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + } + } + }, "create-ecdh": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", @@ -2536,6 +2595,12 @@ "assert-plus": "1.0.0" } }, + "date-fns": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", + "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==", + "dev": true + }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -2563,6 +2628,12 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", @@ -3054,6 +3125,12 @@ "integrity": "sha1-eOy4o5kGYYe7N07t412ccFZagD0=", "dev": true }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "dev": true + }, "elliptic": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", @@ -3524,6 +3601,12 @@ "strip-eof": "1.0.0" } }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, "expand-brackets": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", @@ -3747,6 +3830,12 @@ "pkg-dir": "2.0.0" } }, + "find-parent-dir": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", + "dev": true + }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -4813,6 +4902,12 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, + "get-own-enumerable-property-symbols": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz", + "integrity": "sha512-TtY/sbOemiMKPRUDDanGCSgBYe7Mf0vbRsWnBZ+9yghpZ1MvcpSpuZFjHdEeY/LZjZy0vdLjS77L6HosisFiug==", + "dev": true + }, "get-port": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", @@ -6059,6 +6154,12 @@ } } }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", @@ -6159,6 +6260,21 @@ "integrity": "sha1-8mWrian0RQNO9q/xWo8AsA9VF5k=", "dev": true }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-observable": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-0.2.0.tgz", + "integrity": "sha1-s2ExHYPG5dcmyr9eJQsCNxBvWuI=", + "dev": true, + "requires": { + "symbol-observable": "0.2.4" + } + }, "is-odd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-1.0.0.tgz", @@ -6253,6 +6369,12 @@ "has": "1.0.1" } }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, "is-relative": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", @@ -6448,6 +6570,55 @@ } } }, + "jest-get-type": { + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-21.2.0.tgz", + "integrity": "sha512-y2fFw3C+D0yjNSDp7ab1kcd6NUYfy3waPTlD8yWkAtiocJdBRQqNoRqVfMNxgj+IjT0V5cBIHJO0z9vuSSZ43Q==", + "dev": true + }, + "jest-validate": { + "version": "21.2.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-21.2.1.tgz", + "integrity": "sha512-k4HLI1rZQjlU+EC682RlQ6oZvLrE5SCh3brseQc24vbZTxzT/k/3urar5QMCVgjadmSO7lECeGdc6YxnM3yEGg==", + "dev": true, + "requires": { + "chalk": "2.3.0", + "jest-get-type": "21.2.0", + "leven": "2.1.0", + "pretty-format": "21.2.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, "js-base64": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.3.2.tgz", @@ -6732,6 +6903,12 @@ "invert-kv": "1.0.0" } }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "dev": true + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -6742,6 +6919,248 @@ "type-check": "0.3.2" } }, + "lint-staged": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-6.0.0.tgz", + "integrity": "sha512-ZUftK94S4vedpQG1LlA2tc2AuQXXBwc+1lB+j8SEfG5+p2dqu3Ug8iYQ8jdap+uLkhDw4OaJXqE+CZ/L+vfv+Q==", + "dev": true, + "requires": { + "app-root-path": "2.0.1", + "chalk": "2.3.0", + "commander": "2.11.0", + "cosmiconfig": "3.1.0", + "debug": "3.1.0", + "dedent": "0.7.0", + "execa": "0.8.0", + "find-parent-dir": "0.3.0", + "is-glob": "4.0.0", + "jest-validate": "21.2.1", + "listr": "0.13.0", + "lodash": "4.17.4", + "log-symbols": "2.1.0", + "minimatch": "3.0.4", + "npm-which": "3.0.1", + "p-map": "1.2.0", + "path-is-inside": "1.0.2", + "pify": "3.0.0", + "staged-git-files": "0.0.4", + "stringify-object": "3.2.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "execa": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", + "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "listr": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.13.0.tgz", + "integrity": "sha1-ILsLowuuZg7oTMBQPfS+PVYjiH0=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "cli-truncate": "0.2.1", + "figures": "1.7.0", + "indent-string": "2.1.0", + "is-observable": "0.2.0", + "is-promise": "2.1.0", + "is-stream": "1.1.0", + "listr-silent-renderer": "1.1.1", + "listr-update-renderer": "0.4.0", + "listr-verbose-renderer": "0.4.1", + "log-symbols": "1.0.2", + "log-update": "1.0.2", + "ora": "0.2.3", + "p-map": "1.2.0", + "rxjs": "5.5.6", + "stream-to-observable": "0.2.0", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "1.1.3" + } + } + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", + "dev": true + }, + "listr-update-renderer": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz", + "integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "cli-truncate": "0.2.1", + "elegant-spinner": "1.0.1", + "figures": "1.7.0", + "indent-string": "3.2.0", + "log-symbols": "1.0.2", + "log-update": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "1.1.3" + } + } + } + }, + "listr-verbose-renderer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", + "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "date-fns": "1.29.0", + "figures": "1.7.0" + }, + "dependencies": { + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "1.0.1" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + } + } + }, "livereload-js": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.2.2.tgz", @@ -6906,6 +7325,89 @@ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, + "log-symbols": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.1.0.tgz", + "integrity": "sha512-zLeLrzMA1A2vRF1e/0Mo+LNINzi6jzBylHj5WqvQ/WK/5WCZt8si9SyN4p9llr/HRYvVR1AoXHRHl4WTHyQAzQ==", + "dev": true, + "requires": { + "chalk": "2.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "log-update": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz", + "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", + "dev": true, + "requires": { + "ansi-escapes": "1.4.0", + "cli-cursor": "1.0.2" + }, + "dependencies": { + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "1.0.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + } + } + }, "loglevel": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.5.1.tgz", @@ -8027,6 +8529,15 @@ "remove-trailing-separator": "1.1.0" } }, + "npm-path": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", + "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", + "dev": true, + "requires": { + "which": "1.3.0" + } + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -8036,6 +8547,17 @@ "path-key": "2.0.1" } }, + "npm-which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", + "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", + "dev": true, + "requires": { + "commander": "2.11.0", + "npm-path": "2.0.4", + "which": "1.3.0" + } + }, "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", @@ -8270,6 +8792,45 @@ "wordwrap": "1.0.0" } }, + "ora": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", + "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-spinners": "0.1.2", + "object-assign": "4.1.1" + }, + "dependencies": { + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "1.0.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + } + } + }, "ordered-read-streams": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", @@ -8723,6 +9284,33 @@ "utila": "0.4.0" } }, + "pretty-format": { + "version": "21.2.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-21.2.1.tgz", + "integrity": "sha512-ZdWPGYAnYfcVP8yKA3zFjCn8s4/17TeYH28MXuC8vTp0o21eXjbFGcOAXZEaDaOFJjc3h2qa7HQNHNshhvoh2A==", + "dev": true, + "requires": { + "ansi-regex": "3.0.0", + "ansi-styles": "3.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + } + } + }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", @@ -9297,6 +9885,12 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, + "require-from-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.1.tgz", + "integrity": "sha1-xUUjPp19pmFunVmt+zn8n1iGdv8=", + "dev": true + }, "require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", @@ -9419,6 +10013,23 @@ "rx-lite": "4.0.8" } }, + "rxjs": { + "version": "5.5.6", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.6.tgz", + "integrity": "sha512-v4Q5HDC0FHAQ7zcBX7T2IL6O5ltl1a2GX4ENjPXg6SjDY69Cmx9v4113C99a4wGF16ClPv5Z8mghuYorVkg/kg==", + "dev": true, + "requires": { + "symbol-observable": "1.0.1" + }, + "dependencies": { + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", + "dev": true + } + } + }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", @@ -10111,6 +10722,12 @@ "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", "dev": true }, + "staged-git-files": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-0.0.4.tgz", + "integrity": "sha1-15fhtVHKemOd7AI33G60u5vhfTU=", + "dev": true + }, "state-toggle": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.0.tgz", @@ -10375,6 +10992,15 @@ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, + "stream-to-observable": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.2.0.tgz", + "integrity": "sha1-WdbqOT2HwsDdrBCqDVYbxrpvDhA=", + "dev": true, + "requires": { + "any-observable": "0.2.0" + } + }, "string-replace-loader": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string-replace-loader/-/string-replace-loader-1.3.0.tgz", @@ -10433,6 +11059,17 @@ "is-hexadecimal": "1.0.1" } }, + "stringify-object": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.2.1.tgz", + "integrity": "sha512-jPcQYw/52HUPP8uOE4kkjxl5bB9LfHkKCTptIk3qw7ozP5XMIMlHMLjt00GGSwW6DJAf/njY5EU6Vpwl4LlBKQ==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "2.0.1", + "is-obj": "1.0.1", + "is-regexp": "1.0.0" + } + }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", @@ -10519,6 +11156,12 @@ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, + "symbol-observable": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-0.2.4.tgz", + "integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=", + "dev": true + }, "symbol-tree": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", diff --git a/package.json b/package.json index 954a6fe7e..074885198 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "husky": "^0.14.3", "istanbul": "^0.4.2", "jsdom": "^11.2.0", + "lint-staged": "^6.0.0", "mocha": "^3.1.2", "node-sass": "^4.5.3", "prettier": "1.10.1", @@ -74,10 +75,13 @@ "transform-object-rest-spread" ] }, + "lint-staged": { + "./{src,test}/**/*.js": ["prettier --single-quote --write", "git add"] + }, "scripts": { "lint": "eslint src", "check": "npm run lint && npm run test", - "precommit": "npm run format && git add .", + "precommit": "lint-staged", "build": "npm run check && npm run v:patch && npm run build-dev && webpack --env=prod", "build-n": "npm run check && npm run build:css && webpack --env=prod", "build-dev": "webpack --env=dev && npm run build:css", diff --git a/src/utils/Droppable.js b/src/utils/Droppable.js index 29ba28c96..25303f5ec 100644 --- a/src/utils/Droppable.js +++ b/src/utils/Droppable.js @@ -4,10 +4,7 @@ import { bindAll } from 'underscore'; export class Droppable { constructor(em) { this.em = em; - this.el = this.em - .get('DomComponents') - .getWrapper() - .getEl(); + this.el = this.em.get('DomComponents').getWrapper().getEl(); this.counter = 0; bindAll( this, From ed03e097a4ade031361dce7ac6b144fd948d3bbf Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Thu, 11 Jan 2018 15:19:44 +0100 Subject: [PATCH 09/22] Update lint-staged --- package.json | 2 +- src/utils/Droppable.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 074885198..0ddd1c6d9 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ ] }, "lint-staged": { - "./{src,test}/**/*.js": ["prettier --single-quote --write", "git add"] + "{src,test}/**/*.js": ["prettier --single-quote --write", "git add"] }, "scripts": { "lint": "eslint src", diff --git a/src/utils/Droppable.js b/src/utils/Droppable.js index 25303f5ec..29ba28c96 100644 --- a/src/utils/Droppable.js +++ b/src/utils/Droppable.js @@ -4,7 +4,10 @@ import { bindAll } from 'underscore'; export class Droppable { constructor(em) { this.em = em; - this.el = this.em.get('DomComponents').getWrapper().getEl(); + this.el = this.em + .get('DomComponents') + .getWrapper() + .getEl(); this.counter = 0; bindAll( this, From 5d60914cae8cddceb3e150227296a583eb2c8e42 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Thu, 11 Jan 2018 15:35:09 +0100 Subject: [PATCH 10/22] Add `getEl` in Component --- src/asset_manager/view/FileUploader.js | 3 ++- src/canvas/index.js | 5 +++++ src/dom_components/model/Component.js | 9 ++++++++ src/utils/Droppable.js | 30 ++++++++++++-------------- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/asset_manager/view/FileUploader.js b/src/asset_manager/view/FileUploader.js index ef5a42338..e58a0c3d3 100644 --- a/src/asset_manager/view/FileUploader.js +++ b/src/asset_manager/view/FileUploader.js @@ -290,7 +290,8 @@ module.exports = Backbone.View.extend( */ /* - // Show local video files + // Show local video files, http://jsfiddle.net/dsbonev/cCCZ2/embedded/result,js,html,css/ + var URL = window.URL || window.webkitURL var file = this.files[0] var type = file.type var videoNode = document.createElement('video'); diff --git a/src/canvas/index.js b/src/canvas/index.js index 8e3398cf4..12d1a10a9 100644 --- a/src/canvas/index.js +++ b/src/canvas/index.js @@ -1,4 +1,5 @@ import { on, off } from 'utils/mixins'; +import Droppable from 'utils/Droppable'; module.exports = () => { var c = {}, @@ -393,6 +394,10 @@ module.exports = () => { return [this.getFrameEl().contentWindow, this.getElement()]; }, + postRender() { + this.droppable = new Droppable(c.em); + }, + /** * Returns wrapper element * @return {HTMLElement} diff --git a/src/dom_components/model/Component.js b/src/dom_components/model/Component.js index 3486c9965..96ba79524 100644 --- a/src/dom_components/model/Component.js +++ b/src/dom_components/model/Component.js @@ -690,6 +690,15 @@ const Component = Backbone.Model.extend(Styleable).extend( return attrs.id || this.ccid || this.cid; }, + /** + * Get the DOM element of the model. This works only of the + * model is alredy rendered + * @return {HTMLElement} + */ + getEl() { + return this.view && this.view.el; + }, + /** * Return script in string format, cleans 'function() {..' from scripts * if it's a function diff --git a/src/utils/Droppable.js b/src/utils/Droppable.js index 29ba28c96..f165cbf68 100644 --- a/src/utils/Droppable.js +++ b/src/utils/Droppable.js @@ -1,13 +1,14 @@ import { on, off } from 'utils/mixins'; import { bindAll } from 'underscore'; -export class Droppable { +export default class Droppable { constructor(em) { this.em = em; - this.el = this.em + const el = em .get('DomComponents') .getWrapper() .getEl(); + this.el = el; this.counter = 0; bindAll( this, @@ -47,32 +48,29 @@ export class Droppable { } handleDragEnter(ev) { + const em = this.em; this.updateCounter(1); if (this.over) return; this.over = 1; console.log('IM IN'); - var utils = this.em.get('Utils'); - var canvas = this.em.get('Canvas'); + const utils = em.get('Utils'); + const canvas = em.get('Canvas'); this.sorter = new utils.Sorter({ + em, + wmargin: 1, + nested: 1, + canvasRelative: 1, + direction: 'a', container: canvas.getBody(), placer: canvas.getPlacerEl(), eventMoving: 'mousemove dragover', containerSel: '*', itemSel: '*', pfx: 'gjs-', - onStart: () => { - this.em.stopDefault(); - }, - onEndMove: () => { - this.em.runDefault(); - }, - document: canvas.getFrameEl().contentDocument, - direction: 'a', - wmargin: 1, - nested: 1, - em, - canvasRelative: 1 + onStart: () => em.stopDefault(), + onEndMove: () => em.runDefault(), + document: canvas.getFrameEl().contentDocument }); const content = this.getContentByData(ev.dataTransfer) || '
'; this.sorter.setDropContent(content); // should not be empty From a27bf4d9eb48bcce7db4e628f2cf6c4917ac3d40 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Thu, 11 Jan 2018 17:50:19 +0100 Subject: [PATCH 11/22] Update Droppable events --- src/utils/Droppable.js | 73 +++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/src/utils/Droppable.js b/src/utils/Droppable.js index f165cbf68..9111e8729 100644 --- a/src/utils/Droppable.js +++ b/src/utils/Droppable.js @@ -1,4 +1,8 @@ -import { on, off } from 'utils/mixins'; +/* + This class makes the canvas droppable + */ + +import { on } from 'utils/mixins'; import { bindAll } from 'underscore'; export default class Droppable { @@ -25,35 +29,33 @@ export default class Droppable { return this; } - endDrop(cancel) { + endDrop(cancel, ev) { + const em = this.em; this.counter = 0; this.over = 0; - console.log('DROP END'); // force out like in BlockView const sorter = this.sorter; cancel && (sorter.moved = 0); - this.em.set('dragContent', ''); + em.set('dragContent', ''); sorter.endMove(); + em.trigger('canvas:dragend', ev); } handleDragLeave(ev) { - this.updateCounter(-1); + this.updateCounter(-1, ev); } - updateCounter(value) { + updateCounter(value, ev) { this.counter += value; - if (this.counter === 0) { - this.endDrop(1); - } + this.counter === 0 && this.endDrop(1, ev); } handleDragEnter(ev) { const em = this.em; - this.updateCounter(1); + const dt = ev.dataTransfer; + this.updateCounter(1, ev); if (this.over) return; this.over = 1; - console.log('IM IN'); - const utils = em.get('Utils'); const canvas = em.get('Canvas'); this.sorter = new utils.Sorter({ @@ -72,9 +74,10 @@ export default class Droppable { onEndMove: () => em.runDefault(), document: canvas.getFrameEl().contentDocument }); - const content = this.getContentByData(ev.dataTransfer) || '
'; + const content = this.getContentByData(dt).content || '
'; this.sorter.setDropContent(content); // should not be empty this.sorter.startSort(this.el); + em.trigger('canvas:dragenter', dt, content); } /** @@ -83,58 +86,62 @@ export default class Droppable { */ handleDragOver(ev) { ev.preventDefault(); + this.em.trigger('canvas:dragover', ev); } handleDrop(ev) { ev.preventDefault(); - var content = this.getContentByData(ev.dataTransfer); + const dt = ev.dataTransfer; + const content = this.getContentByData(dt).content; ev.target.style.border = ''; + if (content) { this.sorter.setDropContent(content); } else { this.sorter.moved = 0; } - this.endDrop(); + + this.endDrop(0, ev); + this.em.trigger('canvas:drop', dt, content); } getContentByData(dataTransfer) { - let result = dataTransfer.getData('text'); - let dragContent = this.em.get('dragContent'); + const em = this.em; const types = dataTransfer.types; const files = dataTransfer.files; - console.log('Files', files); - - const items = dataTransfer.items; - for (var i = 0; i < items.length; i++) console.log('DataType', items[i]); + const dragContent = em.get('dragContent'); // Used by blocks + let content = dataTransfer.getData('text'); if (files.length) { - result = []; + content = []; for (let i = 0; i < files.length; i++) { const file = files[i]; - result.push({ + content.push({ type: 'image', attributes: { alt: file.name } }); } - const fu = this.em.get('AssetManager').FileUploader(); + const fu = em.get('AssetManager').FileUploader(); fu.uploadFile({ dataTransfer }, res => console.log('RES upload', res)); } else if (types.indexOf('text/html') >= 0) { - result = dataTransfer.getData('text/html').replace(/<\/?meta[^>]*>/g, ''); + content = dataTransfer + .getData('text/html') + .replace(/<\/?meta[^>]*>/g, ''); } else if (types.indexOf('text/uri-list') >= 0) { - result = { + content = { type: 'link', - attributes: { href: result }, - content: result + attributes: { href: content }, + content: content }; } else if (dragContent) { - result = dragContent; + content = dragContent; } else { - result = result && `
${result}
`; + content = content && `
${content}
`; } - //this.uploadFile(e); - console.log('CONTENT', result); - // TODO result = clbContent(result); + const result = { content, dragContent }; + em.trigger('canvas:dragdata', dataTransfer, result); + return result; } } From f5ef980086b3f828c383f3d0a275468fdac1e294 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Thu, 11 Jan 2018 18:07:48 +0100 Subject: [PATCH 12/22] Remove uploading from Droppable --- src/utils/Droppable.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/utils/Droppable.js b/src/utils/Droppable.js index 9111e8729..3276a87b0 100644 --- a/src/utils/Droppable.js +++ b/src/utils/Droppable.js @@ -116,13 +116,16 @@ export default class Droppable { content = []; for (let i = 0; i < files.length; i++) { const file = files[i]; - content.push({ - type: 'image', - attributes: { alt: file.name } - }); + const type = file.type.split('/')[0]; + + if (type == 'image') { + content.push({ + type, + file, + attributes: { alt: file.name } + }); + } } - const fu = em.get('AssetManager').FileUploader(); - fu.uploadFile({ dataTransfer }, res => console.log('RES upload', res)); } else if (types.indexOf('text/html') >= 0) { content = dataTransfer .getData('text/html') From 85553da2b936a20261ab566037bb5d3e4f66540a Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Thu, 11 Jan 2018 18:32:09 +0100 Subject: [PATCH 13/22] Allow async loading of images --- src/dom_components/model/ComponentImage.js | 5 ++++- src/dom_components/view/ComponentImageView.js | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/dom_components/model/ComponentImage.js b/src/dom_components/model/ComponentImage.js index 1a1a047c9..21cf03600 100644 --- a/src/dom_components/model/ComponentImage.js +++ b/src/dom_components/model/ComponentImage.js @@ -12,7 +12,10 @@ module.exports = Component.extend( editable: 1, highlightable: 0, resizable: 1, - traits: ['alt'] + traits: ['alt'], + + // File to load asynchronously once the model is rendered + file: '' }, initialize(o, opt) { diff --git a/src/dom_components/view/ComponentImageView.js b/src/dom_components/view/ComponentImageView.js index 753d2e72c..2bc6fe9c5 100644 --- a/src/dom_components/view/ComponentImageView.js +++ b/src/dom_components/view/ComponentImageView.js @@ -18,6 +18,27 @@ module.exports = ComponentView.extend({ const config = this.config; config.modal && (this.modal = config.modal); config.am && (this.am = config.am); + this.uploadFile(); + }, + + uploadFile() { + const model = this.model; + const file = model.get('file'); + + if (file) { + const fu = this.em.get('AssetManager').FileUploader(); + fu.uploadFile( + { + dataTransfer: { files: [file] } + }, + res => { + const obj = res && res.data && res.data[0]; + const src = obj && obj.src; + src && model.set({ src }); + } + ); + model.set('file', ''); + } }, /** From d6500380e6c33dedfe970088575fbb5dd36e1651 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Thu, 11 Jan 2018 18:32:55 +0100 Subject: [PATCH 14/22] Upload Component Image view --- src/dom_components/view/ComponentImageView.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/dom_components/view/ComponentImageView.js b/src/dom_components/view/ComponentImageView.js index 2bc6fe9c5..4fc8927e8 100644 --- a/src/dom_components/view/ComponentImageView.js +++ b/src/dom_components/view/ComponentImageView.js @@ -18,10 +18,13 @@ module.exports = ComponentView.extend({ const config = this.config; config.modal && (this.modal = config.modal); config.am && (this.am = config.am); - this.uploadFile(); + this.fetchFile(); }, - uploadFile() { + /** + * Fetch file if exists + */ + fetchFile() { const model = this.model; const file = model.get('file'); From a151cc21635d38c76263ad2ebd2e6275986b9c1c Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Fri, 12 Jan 2018 23:08:26 +0100 Subject: [PATCH 15/22] Add HTML5 D&D support in `tlb-move` --- src/commands/index.js | 28 +++++++++++++------- src/dom_components/model/Component.js | 3 ++- src/dom_components/view/ToolbarButtonView.js | 12 +++++++-- src/utils/Sorter.js | 2 +- 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/commands/index.js b/src/commands/index.js index b65d5d1cb..219d7cb86 100644 --- a/src/commands/index.js +++ b/src/commands/index.js @@ -142,8 +142,16 @@ module.exports = () => { defaultCommands['tlb-move'] = { run(ed, sender, opts) { - var sel = ed.getSelected(); - var dragger; + let dragger; + const em = ed.getModel(); + const event = opts && opts.event; + const sel = ed.getSelected(); + const toolbarStyle = ed.Canvas.getToolbarEl().style; + + setTimeout(() => { + toolbarStyle.display = 'none'; + em.stopDefault(); + }, 0); if (!sel || !sel.get('draggable')) { console.warn('The element is not draggable'); @@ -160,7 +168,7 @@ module.exports = () => { const onEnd = (e, opts) => { em.runDefault(); - em.set('selectedComponent', sel); + em.setSelected(sel); sel.emitUpdate(); dragger && dragger.blur(); }; @@ -170,24 +178,24 @@ module.exports = () => { console.log('Current ', opts.current); }; - var toolbarEl = ed.Canvas.getToolbarEl(); - toolbarEl.style.display = 'none'; - var em = ed.getModel(); - em.stopDefault(); - if (em.get('designerMode')) { // TODO move grabbing func in editor/canvas from the Sorter dragger = editor.runCommand('drag', { el: sel.view.el, options: { - event: opts && opts.event, + event, onStart, onDrag, onEnd } }); } else { - var cmdMove = ed.Commands.get('move-comp'); + if (event.type == 'dragstart') { + event.dataTransfer.setDragImage(sel.view.el, 0, 0); + //sel.set('status', 'freezed'); + } + + const cmdMove = ed.Commands.get('move-comp'); cmdMove.onEndMoveFromModel = onEnd; cmdMove.initSorterFromModel(sel); } diff --git a/src/dom_components/model/Component.js b/src/dom_components/model/Component.js index 96ba79524..17f6c78d4 100644 --- a/src/dom_components/model/Component.js +++ b/src/dom_components/model/Component.js @@ -497,7 +497,8 @@ const Component = Backbone.Model.extend(Styleable).extend( } if (model.get('draggable')) { tb.push({ - attributes: { class: 'fa fa-arrows' }, + attributes: { class: 'fa fa-arrows', draggable: true }, + events: { dragstart: 'execCommand' }, command: 'tlb-move' }); } diff --git a/src/dom_components/view/ToolbarButtonView.js b/src/dom_components/view/ToolbarButtonView.js index 13d87930c..e49468176 100644 --- a/src/dom_components/view/ToolbarButtonView.js +++ b/src/dom_components/view/ToolbarButtonView.js @@ -1,8 +1,12 @@ var Backbone = require('backbone'); module.exports = Backbone.View.extend({ - events: { - mousedown: 'handleClick' + events() { + return ( + this.model.get('events') || { + mousedown: 'handleClick' + } + ); }, attributes() { @@ -16,6 +20,10 @@ module.exports = Backbone.View.extend({ handleClick(event) { event.preventDefault(); event.stopPropagation(); + this.execCommand(event); + }, + + execCommand(event) { const opts = { event }; const command = this.model.get('command'); const editor = this.editor; diff --git a/src/utils/Sorter.js b/src/utils/Sorter.js index 2b919e53e..b9b500779 100644 --- a/src/utils/Sorter.js +++ b/src/utils/Sorter.js @@ -278,7 +278,7 @@ module.exports = Backbone.View.extend({ } on(container, 'mousemove dragover', this.onMove); - on(docs, 'mouseup', this.endMove); + on(docs, 'mouseup dragend', this.endMove); on(docs, 'keydown', this.rollback); onStart && onStart(); From 0b5ac9c7bc7c30f6a5097068647ec12eea6f7708 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Fri, 12 Jan 2018 23:21:56 +0100 Subject: [PATCH 16/22] Check draggability for blocks by using `hasDnd` and `nativeDnd` --- src/block_manager/view/BlockView.js | 5 +++-- src/commands/index.js | 1 + src/editor/config/config.js | 3 +++ src/utils/Sorter.js | 2 +- src/utils/mixins.js | 8 ++++++++ 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/block_manager/view/BlockView.js b/src/block_manager/view/BlockView.js index 8dd766cc5..ad3984e96 100644 --- a/src/block_manager/view/BlockView.js +++ b/src/block_manager/view/BlockView.js @@ -1,4 +1,4 @@ -import { on, off } from 'utils/mixins'; +import { on, off, hasDnd } from 'utils/mixins'; module.exports = Backbone.View.extend({ events: { @@ -7,6 +7,7 @@ module.exports = Backbone.View.extend({ }, initialize(o, config = {}) { + this.em = config.em; this.config = config; this.endDrag = this.endDrag.bind(this); this.ppfx = config.pStylePrefix || ''; @@ -59,7 +60,7 @@ module.exports = Backbone.View.extend({ const label = this.model.get('label'); el.className += ` ${className} ${pfx}one-bg ${pfx}four-color-h`; el.innerHTML = `
${label}
`; - el.setAttribute('draggable', true); + hasDnd(this.em) && el.setAttribute('draggable', true); return this; } }); diff --git a/src/commands/index.js b/src/commands/index.js index 219d7cb86..5c5199492 100644 --- a/src/commands/index.js +++ b/src/commands/index.js @@ -190,6 +190,7 @@ module.exports = () => { } }); } else { + console.log(em.get('Config')); if (event.type == 'dragstart') { event.dataTransfer.setDragImage(sel.view.el, 0, 0); //sel.set('status', 'freezed'); diff --git a/src/editor/config/config.js b/src/editor/config/config.js index 2c44d3da4..5741697ef 100644 --- a/src/editor/config/config.js +++ b/src/editor/config/config.js @@ -59,6 +59,9 @@ module.exports = { // Return JS of components inside HTML from 'editor.getHtml()' jsInHtml: true, + // Enable native HTML5 drag and drop + nativeDnD: 0, + // Show the wrapper component in the final code, eg. in editor.getHtml() exportWrapper: 0, diff --git a/src/utils/Sorter.js b/src/utils/Sorter.js index b9b500779..524a45f78 100644 --- a/src/utils/Sorter.js +++ b/src/utils/Sorter.js @@ -907,7 +907,7 @@ module.exports = Backbone.View.extend({ const docs = this.getDocuments(); const container = this.getContainerEl(); off(container, 'mousemove dragover', this.onMove); - off(docs, 'mouseup', this.endMove); + off(docs, 'mouseup dragend', this.endMove); off(docs, 'keydown', this.rollback); //this.$document.off('mouseup', this.endMove); //this.$document.off('keydown', this.rollback); diff --git a/src/utils/mixins.js b/src/utils/mixins.js index 1d21cbc89..9d56d78e6 100644 --- a/src/utils/mixins.js +++ b/src/utils/mixins.js @@ -90,9 +90,17 @@ const normalizeFloat = (value, step = 1, valueDef = 0) => { return stepDecimals ? parseFloat(value.toFixed(stepDecimals)) : value; }; +const hasDnd = em => { + return ( + 'draggable' in document.createElement('i') && + (em ? em.get('Config').nativeDnD : 1) + ); +}; + export { on, off, + hasDnd, upFirst, matches, camelCase, From 3aeafacbe358eb0a5fed5ffd7ae82a2db91ce962 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Fri, 12 Jan 2018 23:51:23 +0100 Subject: [PATCH 17/22] Check draggability for the canvas and components --- src/canvas/index.js | 4 ++-- src/commands/index.js | 1 - src/dom_components/model/Component.js | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/canvas/index.js b/src/canvas/index.js index 12d1a10a9..9f28202d5 100644 --- a/src/canvas/index.js +++ b/src/canvas/index.js @@ -1,4 +1,4 @@ -import { on, off } from 'utils/mixins'; +import { on, off, hasDnd } from 'utils/mixins'; import Droppable from 'utils/Droppable'; module.exports = () => { @@ -395,7 +395,7 @@ module.exports = () => { }, postRender() { - this.droppable = new Droppable(c.em); + if (hasDnd(c.em)) this.droppable = new Droppable(c.em); }, /** diff --git a/src/commands/index.js b/src/commands/index.js index 5c5199492..219d7cb86 100644 --- a/src/commands/index.js +++ b/src/commands/index.js @@ -190,7 +190,6 @@ module.exports = () => { } }); } else { - console.log(em.get('Config')); if (event.type == 'dragstart') { event.dataTransfer.setDragImage(sel.view.el, 0, 0); //sel.set('status', 'freezed'); diff --git a/src/dom_components/model/Component.js b/src/dom_components/model/Component.js index 17f6c78d4..2e5fb596a 100644 --- a/src/dom_components/model/Component.js +++ b/src/dom_components/model/Component.js @@ -7,7 +7,7 @@ import { isString, keys } from 'underscore'; -import { shallowDiff } from 'utils/mixins'; +import { shallowDiff, hasDnd } from 'utils/mixins'; import Styleable from 'domain_abstract/model/Styleable'; const Backbone = require('backbone'); @@ -498,7 +498,7 @@ const Component = Backbone.Model.extend(Styleable).extend( if (model.get('draggable')) { tb.push({ attributes: { class: 'fa fa-arrows', draggable: true }, - events: { dragstart: 'execCommand' }, + events: hasDnd(this.em) ? { dragstart: 'execCommand' } : '', command: 'tlb-move' }); } From ece0083047421d849fe1c7d84541946996fb9b09 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Sat, 13 Jan 2018 00:11:07 +0100 Subject: [PATCH 18/22] Enable native D&D by default but skip it for components --- src/block_manager/view/BlockView.js | 2 ++ src/dom_components/model/Component.js | 2 +- src/editor/config/config.js | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/block_manager/view/BlockView.js b/src/block_manager/view/BlockView.js index ad3984e96..99fd15bb4 100644 --- a/src/block_manager/view/BlockView.js +++ b/src/block_manager/view/BlockView.js @@ -32,6 +32,8 @@ module.exports = Backbone.View.extend({ handleDragStart(ev) { const content = this.model.get('content'); + // Firefox requires setData + ev.dataTransfer.setData('text', null); // Can't put the content in dataTransfer as it will not be available // on `dragenter` event for security reason this.config.em.set('dragContent', content); diff --git a/src/dom_components/model/Component.js b/src/dom_components/model/Component.js index 2e5fb596a..e21b6b315 100644 --- a/src/dom_components/model/Component.js +++ b/src/dom_components/model/Component.js @@ -498,7 +498,7 @@ const Component = Backbone.Model.extend(Styleable).extend( if (model.get('draggable')) { tb.push({ attributes: { class: 'fa fa-arrows', draggable: true }, - events: hasDnd(this.em) ? { dragstart: 'execCommand' } : '', + //events: hasDnd(this.em) ? { dragstart: 'execCommand' } : '', command: 'tlb-move' }); } diff --git a/src/editor/config/config.js b/src/editor/config/config.js index 5741697ef..50392fbbe 100644 --- a/src/editor/config/config.js +++ b/src/editor/config/config.js @@ -60,7 +60,7 @@ module.exports = { jsInHtml: true, // Enable native HTML5 drag and drop - nativeDnD: 0, + nativeDnD: 1, // Show the wrapper component in the final code, eg. in editor.getHtml() exportWrapper: 0, From 14316f2934e474cd93692bae005ce3f5a2bff196 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Sat, 13 Jan 2018 00:26:23 +0100 Subject: [PATCH 19/22] Fix freezed class on drag of components --- src/commands/index.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/commands/index.js b/src/commands/index.js index 219d7cb86..445a3f925 100644 --- a/src/commands/index.js +++ b/src/commands/index.js @@ -147,17 +147,21 @@ module.exports = () => { const event = opts && opts.event; const sel = ed.getSelected(); const toolbarStyle = ed.Canvas.getToolbarEl().style; + const nativeDrag = event.type == 'dragstart'; - setTimeout(() => { + const hideTlb = () => { toolbarStyle.display = 'none'; em.stopDefault(); - }, 0); + }; if (!sel || !sel.get('draggable')) { console.warn('The element is not draggable'); return; } + // Without setTimeout the ghost image disappears + nativeDrag ? setTimeout(() => hideTlb, 0) : hideTlb(); + const onStart = (e, opts) => { console.log('start mouse pos ', opts.start); console.log('el rect ', opts.elRect); @@ -190,7 +194,7 @@ module.exports = () => { } }); } else { - if (event.type == 'dragstart') { + if (nativeDrag) { event.dataTransfer.setDragImage(sel.view.el, 0, 0); //sel.set('status', 'freezed'); } From 5569b64c5389bd2272591a1be6fbf73adbb18f3b Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Sat, 13 Jan 2018 01:43:02 +0100 Subject: [PATCH 20/22] Stop using `dragContent` --- src/block_manager/view/BlockView.js | 12 +++++++----- src/utils/Droppable.js | 10 +++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/block_manager/view/BlockView.js b/src/block_manager/view/BlockView.js index 99fd15bb4..bae9e572a 100644 --- a/src/block_manager/view/BlockView.js +++ b/src/block_manager/view/BlockView.js @@ -1,3 +1,4 @@ +import { isObject } from 'underscore'; import { on, off, hasDnd } from 'utils/mixins'; module.exports = Backbone.View.extend({ @@ -32,11 +33,12 @@ module.exports = Backbone.View.extend({ handleDragStart(ev) { const content = this.model.get('content'); - // Firefox requires setData - ev.dataTransfer.setData('text', null); - // Can't put the content in dataTransfer as it will not be available - // on `dragenter` event for security reason - this.config.em.set('dragContent', content); + const isObj = isObject(content); + const type = isObj ? 'text/json' : 'text'; + const data = isObj ? JSON.stringify(content) : content; + console.log('handleDragStart', data); + // Note: data are not available on dragenter for security reason + ev.dataTransfer.setData(type, data); }, /** diff --git a/src/utils/Droppable.js b/src/utils/Droppable.js index 3276a87b0..5edf4d607 100644 --- a/src/utils/Droppable.js +++ b/src/utils/Droppable.js @@ -36,7 +36,7 @@ export default class Droppable { // force out like in BlockView const sorter = this.sorter; cancel && (sorter.moved = 0); - em.set('dragContent', ''); + //em.set('dragContent', ''); sorter.endMove(); em.trigger('canvas:dragend', ev); } @@ -109,7 +109,6 @@ export default class Droppable { const em = this.em; const types = dataTransfer.types; const files = dataTransfer.files; - const dragContent = em.get('dragContent'); // Used by blocks let content = dataTransfer.getData('text'); if (files.length) { @@ -136,13 +135,14 @@ export default class Droppable { attributes: { href: content }, content: content }; - } else if (dragContent) { - content = dragContent; + } else if (types.indexOf('text/json') >= 0) { + const json = dataTransfer.getData('text/json'); + json && (content = JSON.parse(json)); } else { content = content && `
${content}
`; } - const result = { content, dragContent }; + const result = { content }; em.trigger('canvas:dragdata', dataTransfer, result); return result; From 3b07616692e6be8ab56bb25c648e8d7902324d58 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Sat, 13 Jan 2018 02:07:14 +0100 Subject: [PATCH 21/22] Stop using `dragContent` in Droppable and add activeOnRender --- src/block_manager/view/BlockView.js | 8 ++++++-- src/utils/Droppable.js | 10 ++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/block_manager/view/BlockView.js b/src/block_manager/view/BlockView.js index bae9e572a..39243d9d8 100644 --- a/src/block_manager/view/BlockView.js +++ b/src/block_manager/view/BlockView.js @@ -4,7 +4,12 @@ import { on, off, hasDnd } from 'utils/mixins'; module.exports = Backbone.View.extend({ events: { mousedown: 'startDrag', - dragstart: 'handleDragStart' + dragstart: 'handleDragStart', + dragend: 'handleDragEnd' + }, + + handleDragEnd(ev) { + console.log('handleDragEnd'); }, initialize(o, config = {}) { @@ -36,7 +41,6 @@ module.exports = Backbone.View.extend({ const isObj = isObject(content); const type = isObj ? 'text/json' : 'text'; const data = isObj ? JSON.stringify(content) : content; - console.log('handleDragStart', data); // Note: data are not available on dragenter for security reason ev.dataTransfer.setData(type, data); }, diff --git a/src/utils/Droppable.js b/src/utils/Droppable.js index 5edf4d607..6853371ef 100644 --- a/src/utils/Droppable.js +++ b/src/utils/Droppable.js @@ -36,7 +36,6 @@ export default class Droppable { // force out like in BlockView const sorter = this.sorter; cancel && (sorter.moved = 0); - //em.set('dragContent', ''); sorter.endMove(); em.trigger('canvas:dragend', ev); } @@ -71,7 +70,14 @@ export default class Droppable { itemSel: '*', pfx: 'gjs-', onStart: () => em.stopDefault(), - onEndMove: () => em.runDefault(), + onEndMove: model => { + em.runDefault(); + + if (model && model.get && model.get('activeOnRender')) { + model.trigger('active'); + model.set('activeOnRender', 0); + } + }, document: canvas.getFrameEl().contentDocument }); const content = this.getContentByData(dt).content || '
'; From a84c04c5889a403b9d9ccf01332f8a81752304e9 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Sat, 13 Jan 2018 02:10:10 +0100 Subject: [PATCH 22/22] Clean BlockView --- src/block_manager/view/BlockView.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/block_manager/view/BlockView.js b/src/block_manager/view/BlockView.js index 39243d9d8..41510b404 100644 --- a/src/block_manager/view/BlockView.js +++ b/src/block_manager/view/BlockView.js @@ -4,12 +4,7 @@ import { on, off, hasDnd } from 'utils/mixins'; module.exports = Backbone.View.extend({ events: { mousedown: 'startDrag', - dragstart: 'handleDragStart', - dragend: 'handleDragEnd' - }, - - handleDragEnd(ev) { - console.log('handleDragEnd'); + dragstart: 'handleDragStart' }, initialize(o, config = {}) {