Commit e157f76fcf055594eadd9a73d3ec5e6913a022ab

Authored by pgrisu
1 parent 8daa3f99

add widgets dataKeys reorder by drag-and-drop dataKey chips in widget editor

@@ -110,7 +110,11 @@ function DatasourceEntity($compile, $templateCache, $q, $mdDialog, $window, $doc @@ -110,7 +110,11 @@ function DatasourceEntity($compile, $templateCache, $q, $mdDialog, $window, $doc
110 dataKeys = dataKeys.concat(scope.timeseriesDataKeys); 110 dataKeys = dataKeys.concat(scope.timeseriesDataKeys);
111 dataKeys = dataKeys.concat(scope.attributeDataKeys); 111 dataKeys = dataKeys.concat(scope.attributeDataKeys);
112 dataKeys = dataKeys.concat(scope.alarmDataKeys); 112 dataKeys = dataKeys.concat(scope.alarmDataKeys);
113 - ngModelCtrl.$viewValue.dataKeys = dataKeys; 113 + if (ngModelCtrl.$viewValue.dataKeys != dataKeys)
  114 + {
  115 + ngModelCtrl.$setDirty();
  116 + ngModelCtrl.$viewValue.dataKeys = dataKeys;
  117 + }
114 scope.updateValidity(); 118 scope.updateValidity();
115 } 119 }
116 } 120 }
@@ -60,7 +60,7 @@ @@ -60,7 +60,7 @@
60 <div class="tb-color-result" ng-style="{background: $chip.color}"></div> 60 <div class="tb-color-result" ng-style="{background: $chip.color}"></div>
61 </div> 61 </div>
62 <div layout="row"> 62 <div layout="row">
63 - <div class="tb-chip-label"> 63 + <div class="tb-chip-label" tb-chip-draggable>
64 {{$chip.label}} 64 {{$chip.label}}
65 </div> 65 </div>
66 <div class="tb-chip-separator">: </div> 66 <div class="tb-chip-separator">: </div>
@@ -111,7 +111,7 @@ @@ -111,7 +111,7 @@
111 <div class="tb-color-result" ng-style="{background: $chip.color}"></div> 111 <div class="tb-color-result" ng-style="{background: $chip.color}"></div>
112 </div> 112 </div>
113 <div layout="row"> 113 <div layout="row">
114 - <div class="tb-chip-label"> 114 + <div class="tb-chip-label" tb-chip-draggable>
115 {{$chip.label}} 115 {{$chip.label}}
116 </div> 116 </div>
117 <div class="tb-chip-separator">: </div> 117 <div class="tb-chip-separator">: </div>
@@ -163,7 +163,7 @@ @@ -163,7 +163,7 @@
163 <div class="tb-color-result" ng-style="{background: $chip.color}"></div> 163 <div class="tb-color-result" ng-style="{background: $chip.color}"></div>
164 </div> 164 </div>
165 <div layout="row"> 165 <div layout="row">
166 - <div class="tb-chip-label"> 166 + <div class="tb-chip-label" tb-chip-draggable>
167 {{$chip.label}} 167 {{$chip.label}}
168 </div> 168 </div>
169 <div class="tb-chip-separator">: </div> 169 <div class="tb-chip-separator">: </div>
@@ -88,7 +88,11 @@ function DatasourceFunc($compile, $templateCache, $mdDialog, $window, $document, @@ -88,7 +88,11 @@ function DatasourceFunc($compile, $templateCache, $mdDialog, $window, $document,
88 var dataKeys = []; 88 var dataKeys = [];
89 dataKeys = dataKeys.concat(scope.funcDataKeys); 89 dataKeys = dataKeys.concat(scope.funcDataKeys);
90 dataKeys = dataKeys.concat(scope.alarmDataKeys); 90 dataKeys = dataKeys.concat(scope.alarmDataKeys);
91 - ngModelCtrl.$viewValue.dataKeys = dataKeys; 91 + if (ngModelCtrl.$viewValue.dataKeys != dataKeys)
  92 + {
  93 + ngModelCtrl.$setDirty();
  94 + ngModelCtrl.$viewValue.dataKeys = dataKeys;
  95 + }
92 scope.updateValidity(); 96 scope.updateValidity();
93 } 97 }
94 } 98 }
@@ -62,7 +62,7 @@ @@ -62,7 +62,7 @@
62 <div class="tb-color-result" ng-style="{background: $chip.color}"></div> 62 <div class="tb-color-result" ng-style="{background: $chip.color}"></div>
63 </div> 63 </div>
64 <div layout="row"> 64 <div layout="row">
65 - <div class="tb-chip-label"> 65 + <div class="tb-chip-label" tb-chip-draggable>
66 {{$chip.label}} 66 {{$chip.label}}
67 </div> 67 </div>
68 <div class="tb-chip-separator">: </div> 68 <div class="tb-chip-separator">: </div>
@@ -113,7 +113,7 @@ @@ -113,7 +113,7 @@
113 <div class="tb-color-result" ng-style="{background: $chip.color}"></div> 113 <div class="tb-color-result" ng-style="{background: $chip.color}"></div>
114 </div> 114 </div>
115 <div layout="row"> 115 <div layout="row">
116 - <div class="tb-chip-label"> 116 + <div class="tb-chip-label" tb-chip-draggable>
117 {{$chip.label}} 117 {{$chip.label}}
118 </div> 118 </div>
119 <div class="tb-chip-separator">: </div> 119 <div class="tb-chip-separator">: </div>
  1 +/*
  2 + * Copyright © 2016-2019 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +export default angular.module('thingsboard.directives.mdChipDraggable', [])
  17 + .directive('tbChipDraggable', function () {
  18 + return {
  19 + restrict: 'A',
  20 + scope: {},
  21 + bindToController: true,
  22 + controllerAs: 'vm',
  23 + controller: ['$document', '$scope', '$element', '$timeout',
  24 + function ($document, $scope, $element, $timeout) {
  25 + var options = {
  26 + axis: 'horizontal',
  27 + };
  28 + var handle = $element[0];
  29 + var draggingClassName = 'dragging';
  30 + var droppingClassName = 'dropping';
  31 + var droppingBeforeClassName = 'dropping--before';
  32 + var droppingAfterClassName = 'dropping--after';
  33 + var dragging = false;
  34 + var preventDrag = false;
  35 + var dropPosition;
  36 + var dropTimeout;
  37 +
  38 + var move = function (from, to) {
  39 + this.splice(to, 0, this.splice(from, 1)[0]);
  40 + };
  41 +
  42 + $element = angular.element($element[0].closest('md-chip'));
  43 +
  44 + $element.attr('draggable', true);
  45 +
  46 + $element.on('mousedown', function (event) {
  47 + if (event.target !== handle) {
  48 + preventDrag = true;
  49 + }
  50 + });
  51 +
  52 + $document.on('mouseup', function () {
  53 + preventDrag = false;
  54 + });
  55 +
  56 + $element.on('dragstart', function (event) {
  57 + if (preventDrag) {
  58 + event.preventDefault();
  59 +
  60 + } else {
  61 + dragging = true;
  62 +
  63 + $element.addClass(draggingClassName);
  64 +
  65 + var dataTransfer = event.dataTransfer || event.originalEvent.dataTransfer;
  66 +
  67 + dataTransfer.effectAllowed = 'copyMove';
  68 + dataTransfer.dropEffect = 'move';
  69 + dataTransfer.setData('text/plain', $scope.$parent.$mdChipsCtrl.items.indexOf($scope.$parent.$chip));
  70 + }
  71 + });
  72 +
  73 + $element.on('dragend', function () {
  74 + dragging = false;
  75 +
  76 + $element.removeClass(draggingClassName);
  77 + });
  78 +
  79 + var dragOverHandler = function (event) {
  80 + if (dragging) {
  81 + return;
  82 + }
  83 +
  84 + event.preventDefault();
  85 +
  86 + var bounds = $element[0].getBoundingClientRect();
  87 +
  88 + var props = {
  89 + width: bounds.right - bounds.left,
  90 + height: bounds.bottom - bounds.top,
  91 + x: (event.originalEvent || event).clientX - bounds.left,
  92 + y: (event.originalEvent || event).clientY - bounds.top,
  93 + };
  94 +
  95 + var offset = options.axis === 'vertical' ? props.y : props.x;
  96 + var midPoint = (options.axis === 'vertical' ? props.height : props.width) / 2;
  97 +
  98 + $element.addClass(droppingClassName);
  99 +
  100 + if (offset < midPoint) {
  101 + dropPosition = 'before';
  102 + $element.removeClass(droppingAfterClassName);
  103 + $element.addClass(droppingBeforeClassName);
  104 +
  105 + } else {
  106 + dropPosition = 'after';
  107 + $element.removeClass(droppingBeforeClassName);
  108 + $element.addClass(droppingAfterClassName);
  109 + }
  110 + };
  111 +
  112 + var dropHandler = function (event) {
  113 + event.preventDefault();
  114 +
  115 + var droppedItemIndex = parseInt((event.dataTransfer || event.originalEvent.dataTransfer).getData('text/plain'), 10);
  116 + var currentIndex = $scope.$parent.$mdChipsCtrl.items.indexOf($scope.$parent.$chip);
  117 + var newIndex = null;
  118 +
  119 + if (dropPosition === 'before') {
  120 + if (droppedItemIndex < currentIndex) {
  121 + newIndex = currentIndex - 1;
  122 + } else {
  123 + newIndex = currentIndex;
  124 + }
  125 + } else {
  126 + if (droppedItemIndex < currentIndex) {
  127 + newIndex = currentIndex;
  128 + } else {
  129 + newIndex = currentIndex + 1;
  130 + }
  131 + }
  132 +
  133 + // prevent event firing multiple times in firefox
  134 + $timeout.cancel(dropTimeout);
  135 + dropTimeout = $timeout(function () {
  136 + dropPosition = null;
  137 +
  138 + move.apply($scope.$parent.$mdChipsCtrl.items, [droppedItemIndex, newIndex]);
  139 +
  140 + $scope.$apply(function () {
  141 + $scope.$emit('mdChipDraggable:change', {
  142 + collection: $scope.$parent.$mdChipsCtrl.items,
  143 + item: $scope.$parent.$mdChipsCtrl.items[droppedItemIndex],
  144 + from: droppedItemIndex,
  145 + to: newIndex,
  146 + });
  147 + });
  148 +
  149 + $element.removeClass(droppingClassName);
  150 + $element.removeClass(droppingBeforeClassName);
  151 + $element.removeClass(droppingAfterClassName);
  152 +
  153 + $element.off('drop', dropHandler);
  154 + }, 1000 / 16);
  155 + };
  156 +
  157 + $element.on('dragenter', function () {
  158 + if (dragging) {
  159 + return;
  160 + }
  161 +
  162 + $element.off('dragover', dragOverHandler);
  163 + $element.off('drop', dropHandler);
  164 +
  165 + $element.on('dragover', dragOverHandler);
  166 + $element.on('drop', dropHandler);
  167 + });
  168 +
  169 + $element.on('dragleave', function () {
  170 + $element.removeClass(droppingClassName);
  171 + $element.removeClass(droppingBeforeClassName);
  172 + $element.removeClass(droppingAfterClassName);
  173 + });
  174 +
  175 + }],
  176 + };
  177 + })
  178 + .name;
  179 +
  180 +/* eslint-enable angular/angularelement */
@@ -27,6 +27,7 @@ import thingsboardConfirmOnExit from '../components/confirm-on-exit.directive'; @@ -27,6 +27,7 @@ import thingsboardConfirmOnExit from '../components/confirm-on-exit.directive';
27 import thingsboardDashboard from '../components/dashboard.directive'; 27 import thingsboardDashboard from '../components/dashboard.directive';
28 import thingsboardExpandFullscreen from '../components/expand-fullscreen.directive'; 28 import thingsboardExpandFullscreen from '../components/expand-fullscreen.directive';
29 import thingsboardCircularProgress from '../components/circular-progress.directive'; 29 import thingsboardCircularProgress from '../components/circular-progress.directive';
  30 +import thingsboardMdChipDraggable from '../components/md-chip-draggable.directive';
30 31
31 import WidgetLibraryRoutes from './widget-library.routes'; 32 import WidgetLibraryRoutes from './widget-library.routes';
32 import WidgetLibraryController from './widget-library.controller'; 33 import WidgetLibraryController from './widget-library.controller';
@@ -46,6 +47,7 @@ export default angular.module('thingsboard.widget-library', [ @@ -46,6 +47,7 @@ export default angular.module('thingsboard.widget-library', [
46 thingsboardDashboard, 47 thingsboardDashboard,
47 thingsboardExpandFullscreen, 48 thingsboardExpandFullscreen,
48 thingsboardCircularProgress, 49 thingsboardCircularProgress,
  50 + thingsboardMdChipDraggable,
49 'cfp.hotkeys', 51 'cfp.hotkeys',
50 'ui.ace' 52 'ui.ace'
51 ]) 53 ])