From 76269a8a1686743a670b864beb80427ff61c8793 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Tue, 23 Apr 2019 08:29:23 +0200 Subject: [PATCH] added drag & drop directives on worker department #1319 --- front/core/components/treeview/child.html | 4 +- front/core/components/treeview/child.js | 6 +- front/core/components/treeview/index.html | 3 +- front/core/components/treeview/index.js | 4 + front/core/components/treeview/style.scss | 14 +++- front/core/directives/draggable.js | 36 +++++++++ front/core/directives/droppable.js | 90 ++++++++++++++++++++++ front/core/directives/index.js | 2 + modules/order/front/catalog/index.html | 2 +- modules/worker/front/department/index.html | 1 + modules/worker/front/department/index.js | 14 ++++ 11 files changed, 170 insertions(+), 6 deletions(-) create mode 100644 front/core/directives/draggable.js create mode 100644 front/core/directives/droppable.js diff --git a/front/core/components/treeview/child.html b/front/core/components/treeview/child.html index a079d8f40..c1f20bcff 100644 --- a/front/core/components/treeview/child.html +++ b/front/core/components/treeview/child.html @@ -5,7 +5,7 @@ 'collapsed': !item.active, 'included': item.selected == 1, 'excluded': item.selected == 0 - }"> + }" vn-draggable vn-droppable on-drop="$ctrl.onDrop(item, dragged, dropped)"> diff --git a/front/core/components/treeview/child.js b/front/core/components/treeview/child.js index ca5b59efb..a26c47b5d 100644 --- a/front/core/components/treeview/child.js +++ b/front/core/components/treeview/child.js @@ -15,7 +15,7 @@ class Controller extends Component { this.treeview.onSelection(item, value); } - onClick(icon, item, parent, index) { + onIconClick(icon, item, parent, index) { let parentScope = this.$scope.$parent.$parent; let parentController = parentScope.$ctrl; icon.callback.call(parentController, item, parent, index); @@ -25,6 +25,10 @@ class Controller extends Component { this.treeview.onCreate(parent); } + onDrop(item, dragged, dropped) { + this.treeview.onDrop(item, dragged, dropped); + } + get isInsertable() { return Array.isArray(this.parent) || this.parent.childs; } diff --git a/front/core/components/treeview/index.html b/front/core/components/treeview/index.html index 85a4e4b6b..606526add 100644 --- a/front/core/components/treeview/index.html +++ b/front/core/components/treeview/index.html @@ -5,5 +5,6 @@ editable="$ctrl.editable" disabled="$ctrl.disabled" icons="$ctrl.icons" - acl-role="$ctrl.aclRole"> + acl-role="$ctrl.aclRole" + vn-droppable> diff --git a/front/core/components/treeview/index.js b/front/core/components/treeview/index.js index 9f2a0a3fa..c34ba2039 100644 --- a/front/core/components/treeview/index.js +++ b/front/core/components/treeview/index.js @@ -69,6 +69,10 @@ export default class Treeview extends Component { item.active = !item.active; } + + onDrop(item, dragged, dropped) { + this.emit('drop', {item, dragged, dropped}); + } } Treeview.$inject = ['$element', '$scope']; diff --git a/front/core/components/treeview/style.scss b/front/core/components/treeview/style.scss index ce51fe482..ff295636d 100644 --- a/front/core/components/treeview/style.scss +++ b/front/core/components/treeview/style.scss @@ -1,6 +1,10 @@ @import "variables"; vn-treeview { + vn-treeview-child { + display: block + } + ul { line-height: 24px; padding: 0; @@ -9,17 +13,25 @@ vn-treeview { li { list-style: none; - cursor: pointer; .actions { min-width: 24px; } .description { + pointer-events: none; padding-left: 5px } } + li[vn-draggable] { + cursor: move + } + + li vn-icon { + cursor: pointer; + } + li ul { padding-left: 1.8em; } diff --git a/front/core/directives/draggable.js b/front/core/directives/draggable.js new file mode 100644 index 000000000..588b97adf --- /dev/null +++ b/front/core/directives/draggable.js @@ -0,0 +1,36 @@ +import ngModule from '../module'; + +/** + * Enables a draggable element and his drag events + * + * @return {Object} The directive + */ +export function directive() { + return { + restrict: 'A', + link: function($scope, $element) { + const element = $element[0]; + + // Enable as draggable element + element.setAttribute('draggable', true); + + /** + * Fires when a drag event starts + */ + element.addEventListener('dragstart', event => { + element.style.opacity = 0.5; + event.stopPropagation(); + }); + + /** + * Fires when a drag event ends + */ + element.addEventListener('dragend', event => { + element.style.opacity = 1; + event.stopPropagation(); + }); + } + }; +} + +ngModule.directive('vnDraggable', directive); diff --git a/front/core/directives/droppable.js b/front/core/directives/droppable.js new file mode 100644 index 000000000..73f0db093 --- /dev/null +++ b/front/core/directives/droppable.js @@ -0,0 +1,90 @@ +import ngModule from '../module'; + + +export function directive($parse) { + return { + restrict: 'A', + link: function($scope, $element, $attrs) { + const element = $element[0]; + const onDropEvent = $parse($attrs.onDrop); + + /** + * Captures current dragging element + */ + element.addEventListener('dragstart', () => { + this.dragged = element; + }); + + /** + * Enter droppable area event + */ + element.addEventListener('dragenter', event => { + element.style.backgroundColor = 'yellow'; + + event.stopImmediatePropagation(); + event.preventDefault(); + }, false); + + + /** + * Exit droppable area event + */ + element.addEventListener('dragleave', event => { + element.style.backgroundColor = 'transparent'; + + event.stopImmediatePropagation(); + event.preventDefault(); + }); + + /** + * Prevent dragover for allowing + * dispatch drop event + */ + element.addEventListener('dragover', event => { + event.stopPropagation(); + event.preventDefault(); + }); + + /** + * Fires when a drop events + */ + element.addEventListener('drop', event => { + const draggedParent = this.dragged.parentNode; + const targetChild = element.querySelector('ul'); + + + element.style.transition = 'background 2s'; + element.style.backgroundColor = 'transparent'; + + if (this.dragged === element) + return event.preventDefault(); + + + if (targetChild) { + const targetNodes = targetChild.querySelectorAll('li'); + const before = targetNodes[targetNodes.length - 1]; + + targetChild.insertBefore(this.dragged, before); + } else + draggedParent.removeChild(this.dragged); + + onDropEvent($scope, { + dragged: { + element: this.dragged, + scope: angular.element(this.dragged).scope() + }, + dropped: { + element: element, + scope: angular.element(element).scope() + } + }); + + event.stopImmediatePropagation(); + }); + } + }; +} + +directive.$inject = ['$parse']; + +ngModule.directive('vnDroppable', directive); diff --git a/front/core/directives/index.js b/front/core/directives/index.js index 9aed1aea3..7db806caf 100644 --- a/front/core/directives/index.js +++ b/front/core/directives/index.js @@ -11,3 +11,5 @@ import './bind'; import './repeat-last'; import './title'; import './uvc'; +import './draggable'; +import './droppable'; diff --git a/modules/order/front/catalog/index.html b/modules/order/front/catalog/index.html index 1d834a66c..0e390d61c 100644 --- a/modules/order/front/catalog/index.html +++ b/modules/order/front/catalog/index.html @@ -7,7 +7,7 @@ on-data-change="$ctrl.onDataChange()">
- +
diff --git a/modules/worker/front/department/index.html b/modules/worker/front/department/index.html index 7cf4bade7..5dac26eca 100644 --- a/modules/worker/front/department/index.html +++ b/modules/worker/front/department/index.html @@ -11,6 +11,7 @@ diff --git a/modules/worker/front/department/index.js b/modules/worker/front/department/index.js index 99d65a478..2047c06c7 100644 --- a/modules/worker/front/department/index.js +++ b/modules/worker/front/department/index.js @@ -26,6 +26,20 @@ class Controller { this.$scope.deleteNode.show(); } + onDrop(item, dragged, dropped) { + if (dropped.scope.item) { + const droppedItem = dropped.scope.item; + const draggedItem = dragged.scope.item; + + if (droppedItem.childs) + droppedItem.childs.push(Object.assign({}, draggedItem)); + + dragged.element.remove(); + + this.$scope.$apply(); + } + } + onCreateDialogOpen() { this.newNode.name = ''; }