Commit b578402f116bebccb4189ce893036666ba1b1861

Authored by Igor Kulikov
1 parent 164dbd68

Rule chain edit improvements.

... ... @@ -18,17 +18,17 @@ export default angular.module('thingsboard.directives.confirmOnExit', [])
18 18 .name;
19 19
20 20 /*@ngInject*/
21   -function ConfirmOnExit($state, $mdDialog, $window, $filter, userService) {
  21 +function ConfirmOnExit($state, $mdDialog, $window, $filter, $parse, userService) {
22 22 return {
23   - link: function ($scope) {
24   -
  23 + link: function ($scope, $element, $attributes) {
  24 + $scope.confirmForm = $scope.$eval($attributes.confirmForm);
25 25 $window.onbeforeunload = function () {
26   - if (userService.isAuthenticated() && (($scope.confirmForm && $scope.confirmForm.$dirty) || $scope.isDirty)) {
  26 + if (userService.isAuthenticated() && (($scope.confirmForm && $scope.confirmForm.$dirty) || $scope.$eval($attributes.isDirty))) {
27 27 return $filter('translate')('confirm-on-exit.message');
28 28 }
29 29 }
30 30 $scope.$on('$stateChangeStart', function (event, next, current, params) {
31   - if (userService.isAuthenticated() && (($scope.confirmForm && $scope.confirmForm.$dirty) || $scope.isDirty)) {
  31 + if (userService.isAuthenticated() && (($scope.confirmForm && $scope.confirmForm.$dirty) || $scope.$eval($attributes.isDirty))) {
32 32 event.preventDefault();
33 33 var confirm = $mdDialog.confirm()
34 34 .title($filter('translate')('confirm-on-exit.title'))
... ... @@ -40,7 +40,9 @@ function ConfirmOnExit($state, $mdDialog, $window, $filter, userService) {
40 40 if ($scope.confirmForm) {
41 41 $scope.confirmForm.$setPristine();
42 42 } else {
43   - $scope.isDirty = false;
  43 + var remoteSetter = $parse($attributes.isDirty).assign;
  44 + remoteSetter($scope, false);
  45 + //$scope.isDirty = false;
44 46 }
45 47 $state.go(next.name, params);
46 48 }, function () {
... ... @@ -48,9 +50,6 @@ function ConfirmOnExit($state, $mdDialog, $window, $filter, userService) {
48 50 }
49 51 });
50 52 },
51   - scope: {
52   - confirmForm: '=',
53   - isDirty: '='
54   - }
  53 + scope: false
55 54 };
56 55 }
\ No newline at end of file
... ...
... ... @@ -1177,6 +1177,8 @@ export default angular.module('thingsboard.locale', [])
1177 1177 "type": "Type",
1178 1178 "description": "Description",
1179 1179 "delete": "Delete rule node",
  1180 + "select-all": "Select all nodes and connections",
  1181 + "deselect-all": "Deselect all nodes and connections",
1180 1182 "delete-selected-objects": "Delete selected nodes and connections",
1181 1183 "rulenode-details": "Rule node details",
1182 1184 "debug-mode": "Debug mode",
... ...
... ... @@ -27,15 +27,10 @@ import addRuleNodeLinkTemplate from './add-link.tpl.html';
27 27
28 28 /* eslint-enable import/no-unresolved, import/default */
29 29
30   -
31   -const deleteKeyCode = 46;
32   -const ctrlKeyCode = 17;
33   -const aKeyCode = 65;
34   -const escKeyCode = 27;
35   -
36 30 /*@ngInject*/
37 31 export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, $timeout, $mdExpansionPanel, $document, $mdDialog,
38   - $filter, $translate, types, ruleChainService, Modelfactory, flowchartConstants, ruleChain, ruleChainMetaData) {
  32 + $filter, $translate, hotkeys, types, ruleChainService, Modelfactory, flowchartConstants,
  33 + ruleChain, ruleChainMetaData, ruleNodeComponents) {
39 34
40 35 var vm = this;
41 36
... ... @@ -76,42 +71,62 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
76 71
77 72 vm.modelservice = Modelfactory(vm.ruleChainModel, vm.selectedObjects);
78 73
79   - vm.ctrlDown = false;
80   -
81 74 vm.saveRuleChain = saveRuleChain;
82 75 vm.revertRuleChain = revertRuleChain;
83 76
84 77 vm.objectsSelected = objectsSelected;
85 78 vm.deleteSelected = deleteSelected;
86 79
87   - vm.keyDown = function (evt) {
88   - if (evt.keyCode === ctrlKeyCode) {
89   - vm.ctrlDown = true;
90   - evt.stopPropagation();
91   - evt.preventDefault();
92   - }
93   - };
94   -
95   - vm.keyUp = function (evt) {
96   -
97   - if (evt.keyCode === deleteKeyCode) {
98   - vm.modelservice.deleteSelected();
99   - }
100   -
101   - if (evt.keyCode == aKeyCode && vm.ctrlDown) {
102   - vm.modelservice.selectAll();
103   - }
104   -
105   - if (evt.keyCode == escKeyCode) {
106   - vm.modelservice.deselectAll();
107   - }
108   -
109   - if (evt.keyCode === ctrlKeyCode) {
110   - vm.ctrlDown = false;
111   - evt.stopPropagation();
112   - evt.preventDefault();
113   - }
114   - };
  80 + initHotKeys();
  81 +
  82 + function initHotKeys() {
  83 + hotkeys.bindTo($scope)
  84 + .add({
  85 + combo: 'ctrl+a',
  86 + description: $translate.instant('rulenode.select-all'),
  87 + allowIn: ['INPUT', 'SELECT', 'TEXTAREA'],
  88 + callback: function (event) {
  89 + event.preventDefault();
  90 + vm.modelservice.selectAll();
  91 + }
  92 + })
  93 + .add({
  94 + combo: 'esc',
  95 + description: $translate.instant('rulenode.deselect-all'),
  96 + allowIn: ['INPUT', 'SELECT', 'TEXTAREA'],
  97 + callback: function (event) {
  98 + event.preventDefault();
  99 + vm.modelservice.deselectAll();
  100 + }
  101 + })
  102 + .add({
  103 + combo: 'ctrl+s',
  104 + description: $translate.instant('action.apply'),
  105 + allowIn: ['INPUT', 'SELECT', 'TEXTAREA'],
  106 + callback: function (event) {
  107 + event.preventDefault();
  108 + vm.saveRuleChain();
  109 + }
  110 + })
  111 + .add({
  112 + combo: 'ctrl+z',
  113 + description: $translate.instant('action.decline-changes'),
  114 + allowIn: ['INPUT', 'SELECT', 'TEXTAREA'],
  115 + callback: function (event) {
  116 + event.preventDefault();
  117 + vm.revertRuleChain();
  118 + }
  119 + })
  120 + .add({
  121 + combo: 'del',
  122 + description: $translate.instant('rulenode.delete-selected-objects'),
  123 + allowIn: ['INPUT', 'SELECT', 'TEXTAREA'],
  124 + callback: function (event) {
  125 + event.preventDefault();
  126 + vm.modelservice.deleteSelected();
  127 + }
  128 + })
  129 + }
115 130
116 131 vm.onEditRuleNodeClosed = function() {
117 132 vm.editingRuleNode = null;
... ... @@ -289,44 +304,40 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
289 304 loadRuleChainLibrary();
290 305
291 306 function loadRuleChainLibrary() {
292   - ruleChainService.getRuleNodeComponents().then(
293   - (ruleNodeComponents) => {
294   - for (var i=0;i<ruleNodeComponents.length;i++) {
295   - var ruleNodeComponent = ruleNodeComponents[i];
296   - var componentType = ruleNodeComponent.type;
297   - var model = vm.ruleNodeTypesModel[componentType].model;
298   - var node = {
299   - id: model.nodes.length,
300   - component: ruleNodeComponent,
301   - name: '',
302   - nodeClass: vm.types.ruleNodeType[componentType].nodeClass,
303   - icon: vm.types.ruleNodeType[componentType].icon,
304   - x: 30,
305   - y: 10+50*model.nodes.length,
306   - connectors: []
307   - };
308   - if (ruleNodeComponent.configurationDescriptor.nodeDefinition.inEnabled) {
309   - node.connectors.push(
310   - {
311   - type: flowchartConstants.leftConnectorType,
312   - id: model.nodes.length * 2
313   - }
314   - );
  307 + for (var i=0;i<ruleNodeComponents.length;i++) {
  308 + var ruleNodeComponent = ruleNodeComponents[i];
  309 + var componentType = ruleNodeComponent.type;
  310 + var model = vm.ruleNodeTypesModel[componentType].model;
  311 + var node = {
  312 + id: model.nodes.length,
  313 + component: ruleNodeComponent,
  314 + name: '',
  315 + nodeClass: vm.types.ruleNodeType[componentType].nodeClass,
  316 + icon: vm.types.ruleNodeType[componentType].icon,
  317 + x: 30,
  318 + y: 10+50*model.nodes.length,
  319 + connectors: []
  320 + };
  321 + if (ruleNodeComponent.configurationDescriptor.nodeDefinition.inEnabled) {
  322 + node.connectors.push(
  323 + {
  324 + type: flowchartConstants.leftConnectorType,
  325 + id: model.nodes.length * 2
315 326 }
316   - if (ruleNodeComponent.configurationDescriptor.nodeDefinition.outEnabled) {
317   - node.connectors.push(
318   - {
319   - type: flowchartConstants.rightConnectorType,
320   - id: model.nodes.length * 2 + 1
321   - }
322   - );
  327 + );
  328 + }
  329 + if (ruleNodeComponent.configurationDescriptor.nodeDefinition.outEnabled) {
  330 + node.connectors.push(
  331 + {
  332 + type: flowchartConstants.rightConnectorType,
  333 + id: model.nodes.length * 2 + 1
323 334 }
324   - model.nodes.push(node);
325   - }
326   - vm.ruleChainLibraryLoaded = true;
327   - prepareRuleChain();
  335 + );
328 336 }
329   - );
  337 + model.nodes.push(node);
  338 + }
  339 + vm.ruleChainLibraryLoaded = true;
  340 + prepareRuleChain();
330 341 }
331 342
332 343 function prepareRuleChain() {
... ...
... ... @@ -68,6 +68,11 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider
68 68 /*@ngInject*/
69 69 function($stateParams, ruleChainService) {
70 70 return ruleChainService.getRuleChainMetaData($stateParams.ruleChainId);
  71 + },
  72 + ruleNodeComponents:
  73 + /*@ngInject*/
  74 + function($stateParams, ruleChainService) {
  75 + return ruleChainService.getRuleNodeComponents();
71 76 }
72 77 },
73 78 data: {
... ...
... ... @@ -75,6 +75,7 @@
75 75 padding: 5px 10px;
76 76 border-radius: 5px;
77 77 background-color: #F15B26;
  78 + pointer-events: none;
78 79 color: #333;
79 80 border: solid 1px #777;
80 81 font-size: 12px;
... ... @@ -186,12 +187,27 @@
186 187 margin: 10px;
187 188 border-radius: 5px;
188 189 background-color: #ccc;
  190 + pointer-events: all;
189 191 }
190 192
191 193 .fc-connector.fc-hover {
192 194 background-color: #000;
193 195 }
194 196
  197 +.fc-arrow-marker {
  198 + polygon {
  199 + stroke: gray;
  200 + fill: gray;
  201 + }
  202 +}
  203 +
  204 +.fc-arrow-marker-selected {
  205 + polygon {
  206 + stroke: red;
  207 + fill: red;
  208 + }
  209 +}
  210 +
195 211 .fc-edge {
196 212 outline: none;
197 213 stroke: gray;
... ... @@ -246,11 +262,23 @@
246 262 cursor: pointer;
247 263 }
248 264
  265 +.fc-noselect {
  266 + -webkit-touch-callout: none; /* iOS Safari */
  267 + -webkit-user-select: none; /* Safari */
  268 + -khtml-user-select: none; /* Konqueror HTML */
  269 + -moz-user-select: none; /* Firefox */
  270 + -ms-user-select: none; /* Internet Explorer/Edge */
  271 + user-select: none; /* Non-prefixed version, currently
  272 + supported by Chrome and Opera */
  273 +}
  274 +
249 275 .fc-edge-label {
250 276 position: absolute;
251   - user-select: none;
252 277 transition: transform .2s;
253 278 opacity: 0.8;
  279 + &.ng-leave {
  280 + transition: 0s none;
  281 + }
254 282 &.fc-hover {
255 283 transform: scale(1.25);
256 284 }
... ... @@ -262,6 +290,13 @@
262 290 }
263 291 }
264 292 }
  293 + .fc-nodedelete {
  294 + right: -13px;
  295 + top: -30px;
  296 + }
  297 + &:focus {
  298 + outline: 0;
  299 + }
265 300 }
266 301
267 302 .fc-edge-label-text {
... ... @@ -273,6 +308,7 @@
273 308 font-size: 14px;
274 309 font-weight: 600;
275 310 span {
  311 + cursor: default;
276 312 border: solid 2px #003a79;
277 313 border-radius: 10px;
278 314 color: #003a79;
... ...
... ... @@ -16,8 +16,10 @@
16 16
17 17 -->
18 18
19   -<md-content flex tb-expand-fullscreen
20   - expand-tooltip-direction="bottom" layout="column" class="tb-rulechain">
  19 +<md-content flex tb-expand-fullscreen tb-confirm-on-exit is-dirty="vm.isDirty"
  20 + expand-tooltip-direction="bottom" layout="column" class="tb-rulechain"
  21 + ng-keydown="vm.keyDown($event)"
  22 + ng-keyup="vm.keyUp($event)">
21 23 <section class="tb-rulechain-container" flex layout="column">
22 24 <div class="tb-rulechain-layout" flex layout="row">
23 25 <div class="tb-rulechain-library">
... ... @@ -50,8 +52,6 @@
50 52 </div>
51 53 <div flex class="tb-rulechain-graph">
52 54 <fc-canvas id="tb-rulchain-canvas"
53   - ng-keydown="vm.keyDown($event)"
54   - ng-keyup="vm.keyUp($event)"
55 55 model="vm.ruleChainModel"
56 56 selected-objects="vm.selectedObjects"
57 57 edge-style="curved"
... ...