Commit bb0533c5286c817623b69c8620eb5ec4fa3293ea
Merge branch 'develop/1.5' of github.com:thingsboard/thingsboard into develop/1.5
Showing
7 changed files
with
200 additions
and
94 deletions
@@ -18,17 +18,17 @@ export default angular.module('thingsboard.directives.confirmOnExit', []) | @@ -18,17 +18,17 @@ export default angular.module('thingsboard.directives.confirmOnExit', []) | ||
18 | .name; | 18 | .name; |
19 | 19 | ||
20 | /*@ngInject*/ | 20 | /*@ngInject*/ |
21 | -function ConfirmOnExit($state, $mdDialog, $window, $filter, userService) { | 21 | +function ConfirmOnExit($state, $mdDialog, $window, $filter, $parse, userService) { |
22 | return { | 22 | return { |
23 | - link: function ($scope) { | ||
24 | - | 23 | + link: function ($scope, $element, $attributes) { |
24 | + $scope.confirmForm = $scope.$eval($attributes.confirmForm); | ||
25 | $window.onbeforeunload = function () { | 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 | return $filter('translate')('confirm-on-exit.message'); | 27 | return $filter('translate')('confirm-on-exit.message'); |
28 | } | 28 | } |
29 | } | 29 | } |
30 | $scope.$on('$stateChangeStart', function (event, next, current, params) { | 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 | event.preventDefault(); | 32 | event.preventDefault(); |
33 | var confirm = $mdDialog.confirm() | 33 | var confirm = $mdDialog.confirm() |
34 | .title($filter('translate')('confirm-on-exit.title')) | 34 | .title($filter('translate')('confirm-on-exit.title')) |
@@ -40,7 +40,9 @@ function ConfirmOnExit($state, $mdDialog, $window, $filter, userService) { | @@ -40,7 +40,9 @@ function ConfirmOnExit($state, $mdDialog, $window, $filter, userService) { | ||
40 | if ($scope.confirmForm) { | 40 | if ($scope.confirmForm) { |
41 | $scope.confirmForm.$setPristine(); | 41 | $scope.confirmForm.$setPristine(); |
42 | } else { | 42 | } else { |
43 | - $scope.isDirty = false; | 43 | + var remoteSetter = $parse($attributes.isDirty).assign; |
44 | + remoteSetter($scope, false); | ||
45 | + //$scope.isDirty = false; | ||
44 | } | 46 | } |
45 | $state.go(next.name, params); | 47 | $state.go(next.name, params); |
46 | }, function () { | 48 | }, function () { |
@@ -48,9 +50,6 @@ function ConfirmOnExit($state, $mdDialog, $window, $filter, userService) { | @@ -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 | } |
@@ -1177,6 +1177,9 @@ export default angular.module('thingsboard.locale', []) | @@ -1177,6 +1177,9 @@ export default angular.module('thingsboard.locale', []) | ||
1177 | "type": "Type", | 1177 | "type": "Type", |
1178 | "description": "Description", | 1178 | "description": "Description", |
1179 | "delete": "Delete rule node", | 1179 | "delete": "Delete rule node", |
1180 | + "select-all": "Select all nodes and connections", | ||
1181 | + "deselect-all": "Deselect all nodes and connections", | ||
1182 | + "delete-selected-objects": "Delete selected nodes and connections", | ||
1180 | "rulenode-details": "Rule node details", | 1183 | "rulenode-details": "Rule node details", |
1181 | "debug-mode": "Debug mode", | 1184 | "debug-mode": "Debug mode", |
1182 | "configuration": "Configuration", | 1185 | "configuration": "Configuration", |
@@ -27,15 +27,10 @@ import addRuleNodeLinkTemplate from './add-link.tpl.html'; | @@ -27,15 +27,10 @@ import addRuleNodeLinkTemplate from './add-link.tpl.html'; | ||
27 | 27 | ||
28 | /* eslint-enable import/no-unresolved, import/default */ | 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 | /*@ngInject*/ | 30 | /*@ngInject*/ |
37 | export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, $timeout, $mdExpansionPanel, $document, $mdDialog, | 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 | var vm = this; | 35 | var vm = this; |
41 | 36 | ||
@@ -76,39 +71,62 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, | @@ -76,39 +71,62 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, | ||
76 | 71 | ||
77 | vm.modelservice = Modelfactory(vm.ruleChainModel, vm.selectedObjects); | 72 | vm.modelservice = Modelfactory(vm.ruleChainModel, vm.selectedObjects); |
78 | 73 | ||
79 | - vm.ctrlDown = false; | ||
80 | - | ||
81 | vm.saveRuleChain = saveRuleChain; | 74 | vm.saveRuleChain = saveRuleChain; |
82 | vm.revertRuleChain = revertRuleChain; | 75 | vm.revertRuleChain = revertRuleChain; |
83 | 76 | ||
84 | - vm.keyDown = function (evt) { | ||
85 | - if (evt.keyCode === ctrlKeyCode) { | ||
86 | - vm.ctrlDown = true; | ||
87 | - evt.stopPropagation(); | ||
88 | - evt.preventDefault(); | ||
89 | - } | ||
90 | - }; | ||
91 | - | ||
92 | - vm.keyUp = function (evt) { | ||
93 | - | ||
94 | - if (evt.keyCode === deleteKeyCode) { | ||
95 | - vm.modelservice.deleteSelected(); | ||
96 | - } | ||
97 | - | ||
98 | - if (evt.keyCode == aKeyCode && vm.ctrlDown) { | ||
99 | - vm.modelservice.selectAll(); | ||
100 | - } | 77 | + vm.objectsSelected = objectsSelected; |
78 | + vm.deleteSelected = deleteSelected; | ||
101 | 79 | ||
102 | - if (evt.keyCode == escKeyCode) { | ||
103 | - vm.modelservice.deselectAll(); | ||
104 | - } | 80 | + initHotKeys(); |
105 | 81 | ||
106 | - if (evt.keyCode === ctrlKeyCode) { | ||
107 | - vm.ctrlDown = false; | ||
108 | - evt.stopPropagation(); | ||
109 | - evt.preventDefault(); | ||
110 | - } | ||
111 | - }; | 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 | + } | ||
112 | 130 | ||
113 | vm.onEditRuleNodeClosed = function() { | 131 | vm.onEditRuleNodeClosed = function() { |
114 | vm.editingRuleNode = null; | 132 | vm.editingRuleNode = null; |
@@ -286,44 +304,40 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, | @@ -286,44 +304,40 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, | ||
286 | loadRuleChainLibrary(); | 304 | loadRuleChainLibrary(); |
287 | 305 | ||
288 | function loadRuleChainLibrary() { | 306 | function loadRuleChainLibrary() { |
289 | - ruleChainService.getRuleNodeComponents().then( | ||
290 | - (ruleNodeComponents) => { | ||
291 | - for (var i=0;i<ruleNodeComponents.length;i++) { | ||
292 | - var ruleNodeComponent = ruleNodeComponents[i]; | ||
293 | - var componentType = ruleNodeComponent.type; | ||
294 | - var model = vm.ruleNodeTypesModel[componentType].model; | ||
295 | - var node = { | ||
296 | - id: model.nodes.length, | ||
297 | - component: ruleNodeComponent, | ||
298 | - name: '', | ||
299 | - nodeClass: vm.types.ruleNodeType[componentType].nodeClass, | ||
300 | - icon: vm.types.ruleNodeType[componentType].icon, | ||
301 | - x: 30, | ||
302 | - y: 10+50*model.nodes.length, | ||
303 | - connectors: [] | ||
304 | - }; | ||
305 | - if (ruleNodeComponent.configurationDescriptor.nodeDefinition.inEnabled) { | ||
306 | - node.connectors.push( | ||
307 | - { | ||
308 | - type: flowchartConstants.leftConnectorType, | ||
309 | - id: model.nodes.length * 2 | ||
310 | - } | ||
311 | - ); | 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 | ||
312 | } | 326 | } |
313 | - if (ruleNodeComponent.configurationDescriptor.nodeDefinition.outEnabled) { | ||
314 | - node.connectors.push( | ||
315 | - { | ||
316 | - type: flowchartConstants.rightConnectorType, | ||
317 | - id: model.nodes.length * 2 + 1 | ||
318 | - } | ||
319 | - ); | 327 | + ); |
328 | + } | ||
329 | + if (ruleNodeComponent.configurationDescriptor.nodeDefinition.outEnabled) { | ||
330 | + node.connectors.push( | ||
331 | + { | ||
332 | + type: flowchartConstants.rightConnectorType, | ||
333 | + id: model.nodes.length * 2 + 1 | ||
320 | } | 334 | } |
321 | - model.nodes.push(node); | ||
322 | - } | ||
323 | - vm.ruleChainLibraryLoaded = true; | ||
324 | - prepareRuleChain(); | 335 | + ); |
325 | } | 336 | } |
326 | - ); | 337 | + model.nodes.push(node); |
338 | + } | ||
339 | + vm.ruleChainLibraryLoaded = true; | ||
340 | + prepareRuleChain(); | ||
327 | } | 341 | } |
328 | 342 | ||
329 | function prepareRuleChain() { | 343 | function prepareRuleChain() { |
@@ -632,6 +646,14 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, | @@ -632,6 +646,14 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, | ||
632 | }); | 646 | }); |
633 | } | 647 | } |
634 | 648 | ||
649 | + function objectsSelected() { | ||
650 | + return vm.modelservice.nodes.getSelectedNodes().length > 0 || | ||
651 | + vm.modelservice.edges.getSelectedEdges().length > 0 | ||
652 | + } | ||
653 | + | ||
654 | + function deleteSelected() { | ||
655 | + vm.modelservice.deleteSelected(); | ||
656 | + } | ||
635 | } | 657 | } |
636 | 658 | ||
637 | /*@ngInject*/ | 659 | /*@ngInject*/ |
@@ -68,6 +68,11 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider | @@ -68,6 +68,11 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider | ||
68 | /*@ngInject*/ | 68 | /*@ngInject*/ |
69 | function($stateParams, ruleChainService) { | 69 | function($stateParams, ruleChainService) { |
70 | return ruleChainService.getRuleChainMetaData($stateParams.ruleChainId); | 70 | return ruleChainService.getRuleChainMetaData($stateParams.ruleChainId); |
71 | + }, | ||
72 | + ruleNodeComponents: | ||
73 | + /*@ngInject*/ | ||
74 | + function($stateParams, ruleChainService) { | ||
75 | + return ruleChainService.getRuleNodeComponents(); | ||
71 | } | 76 | } |
72 | }, | 77 | }, |
73 | data: { | 78 | data: { |
@@ -75,6 +75,7 @@ | @@ -75,6 +75,7 @@ | ||
75 | padding: 5px 10px; | 75 | padding: 5px 10px; |
76 | border-radius: 5px; | 76 | border-radius: 5px; |
77 | background-color: #F15B26; | 77 | background-color: #F15B26; |
78 | + pointer-events: none; | ||
78 | color: #333; | 79 | color: #333; |
79 | border: solid 1px #777; | 80 | border: solid 1px #777; |
80 | font-size: 12px; | 81 | font-size: 12px; |
@@ -121,10 +122,6 @@ | @@ -121,10 +122,6 @@ | ||
121 | .fc-node { | 122 | .fc-node { |
122 | z-index: 1; | 123 | z-index: 1; |
123 | outline: none; | 124 | outline: none; |
124 | - &.fc-hover, &.fc-selected { | ||
125 | - -webkit-filter: brightness(70%); | ||
126 | - filter: brightness(70%); | ||
127 | - } | ||
128 | &.fc-dragging { | 125 | &.fc-dragging { |
129 | z-index: 10; | 126 | z-index: 10; |
130 | } | 127 | } |
@@ -132,6 +129,26 @@ | @@ -132,6 +129,26 @@ | ||
132 | padding: 0 15px; | 129 | padding: 0 15px; |
133 | text-align: center; | 130 | text-align: center; |
134 | } | 131 | } |
132 | + .fc-node-overlay { | ||
133 | + position: absolute; | ||
134 | + pointer-events: none; | ||
135 | + left: 0; | ||
136 | + top: 0; | ||
137 | + right: 0; | ||
138 | + bottom: 0; | ||
139 | + background-color: #000; | ||
140 | + opacity: 0; | ||
141 | + } | ||
142 | + &.fc-hover { | ||
143 | + .fc-node-overlay { | ||
144 | + opacity: 0.25; | ||
145 | + } | ||
146 | + } | ||
147 | + &.fc-selected { | ||
148 | + .fc-node-overlay { | ||
149 | + opacity: 0.25; | ||
150 | + } | ||
151 | + } | ||
135 | } | 152 | } |
136 | 153 | ||
137 | .fc-leftConnectors, .fc-rightConnectors { | 154 | .fc-leftConnectors, .fc-rightConnectors { |
@@ -170,17 +187,33 @@ | @@ -170,17 +187,33 @@ | ||
170 | margin: 10px; | 187 | margin: 10px; |
171 | border-radius: 5px; | 188 | border-radius: 5px; |
172 | background-color: #ccc; | 189 | background-color: #ccc; |
190 | + pointer-events: all; | ||
173 | } | 191 | } |
174 | 192 | ||
175 | .fc-connector.fc-hover { | 193 | .fc-connector.fc-hover { |
176 | background-color: #000; | 194 | background-color: #000; |
177 | } | 195 | } |
178 | 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 | + | ||
179 | .fc-edge { | 211 | .fc-edge { |
180 | outline: none; | 212 | outline: none; |
181 | stroke: gray; | 213 | stroke: gray; |
182 | stroke-width: 4; | 214 | stroke-width: 4; |
183 | fill: transparent; | 215 | fill: transparent; |
216 | + transition: stroke-width .2s; | ||
184 | &.fc-selected { | 217 | &.fc-selected { |
185 | stroke: red; | 218 | stroke: red; |
186 | stroke-width: 4; | 219 | stroke-width: 4; |
@@ -229,24 +262,53 @@ | @@ -229,24 +262,53 @@ | ||
229 | cursor: pointer; | 262 | cursor: pointer; |
230 | } | 263 | } |
231 | 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 | + | ||
232 | .fc-edge-label { | 275 | .fc-edge-label { |
233 | position: absolute; | 276 | position: absolute; |
234 | - user-select: none; | ||
235 | - pointer-events: none; | 277 | + transition: transform .2s; |
236 | opacity: 0.8; | 278 | opacity: 0.8; |
279 | + &.ng-leave { | ||
280 | + transition: 0s none; | ||
281 | + } | ||
282 | + &.fc-hover { | ||
283 | + transform: scale(1.25); | ||
284 | + } | ||
285 | + &.fc-selected { | ||
286 | + .fc-edge-label-text { | ||
287 | + span { | ||
288 | + border: solid red; | ||
289 | + color: red; | ||
290 | + } | ||
291 | + } | ||
292 | + } | ||
293 | + .fc-nodedelete { | ||
294 | + right: -13px; | ||
295 | + top: -30px; | ||
296 | + } | ||
297 | + &:focus { | ||
298 | + outline: 0; | ||
299 | + } | ||
237 | } | 300 | } |
238 | 301 | ||
239 | .fc-edge-label-text { | 302 | .fc-edge-label-text { |
240 | position: absolute; | 303 | position: absolute; |
241 | - left: 50%; | ||
242 | - -webkit-transform: translateX(-50%); | ||
243 | - transform: translateX(-50%); | 304 | + -webkit-transform: translate(-50%, -50%); |
305 | + transform: translate(-50%, -50%); | ||
244 | white-space: nowrap; | 306 | white-space: nowrap; |
245 | text-align: center; | 307 | text-align: center; |
246 | font-size: 14px; | 308 | font-size: 14px; |
247 | font-weight: 600; | 309 | font-weight: 600; |
248 | - top: 5px; | ||
249 | span { | 310 | span { |
311 | + cursor: default; | ||
250 | border: solid 2px #003a79; | 312 | border: solid 2px #003a79; |
251 | border-radius: 10px; | 313 | border-radius: 10px; |
252 | color: #003a79; | 314 | color: #003a79; |
@@ -255,6 +317,13 @@ | @@ -255,6 +317,13 @@ | ||
255 | } | 317 | } |
256 | } | 318 | } |
257 | 319 | ||
320 | +.fc-select-rectangle { | ||
321 | + border: 2px dashed #5262ff; | ||
322 | + position: absolute; | ||
323 | + background: rgba(20,125,255,0.1); | ||
324 | + z-index: 2; | ||
325 | +} | ||
326 | + | ||
258 | @keyframes dash { | 327 | @keyframes dash { |
259 | from { | 328 | from { |
260 | stroke-dashoffset: 500; | 329 | stroke-dashoffset: 500; |
@@ -16,8 +16,10 @@ | @@ -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 | <section class="tb-rulechain-container" flex layout="column"> | 23 | <section class="tb-rulechain-container" flex layout="column"> |
22 | <div class="tb-rulechain-layout" flex layout="row"> | 24 | <div class="tb-rulechain-layout" flex layout="row"> |
23 | <div class="tb-rulechain-library"> | 25 | <div class="tb-rulechain-library"> |
@@ -50,8 +52,6 @@ | @@ -50,8 +52,6 @@ | ||
50 | </div> | 52 | </div> |
51 | <div flex class="tb-rulechain-graph"> | 53 | <div flex class="tb-rulechain-graph"> |
52 | <fc-canvas id="tb-rulchain-canvas" | 54 | <fc-canvas id="tb-rulchain-canvas" |
53 | - ng-keydown="vm.keyDown($event)" | ||
54 | - ng-keyup="vm.keyUp($event)" | ||
55 | model="vm.ruleChainModel" | 55 | model="vm.ruleChainModel" |
56 | selected-objects="vm.selectedObjects" | 56 | selected-objects="vm.selectedObjects" |
57 | edge-style="curved" | 57 | edge-style="curved" |
@@ -112,6 +112,13 @@ | @@ -112,6 +112,13 @@ | ||
112 | </tb-details-sidenav> | 112 | </tb-details-sidenav> |
113 | </section> | 113 | </section> |
114 | <section layout="row" layout-wrap class="tb-footer-buttons md-fab" layout-align="start end"> | 114 | <section layout="row" layout-wrap class="tb-footer-buttons md-fab" layout-align="start end"> |
115 | + <md-button ng-disabled="$root.loading" ng-show="vm.objectsSelected()" class="tb-btn-footer md-accent md-hue-2 md-fab" | ||
116 | + ng-click="vm.deleteSelected()" aria-label="{{ 'action.delete' | translate }}"> | ||
117 | + <md-tooltip md-direction="top"> | ||
118 | + {{ 'rulenode.delete-selected-objects' | translate }} | ||
119 | + </md-tooltip> | ||
120 | + <ng-md-icon icon="delete"></ng-md-icon> | ||
121 | + </md-button> | ||
115 | <md-button ng-disabled="$root.loading || !vm.isDirty" | 122 | <md-button ng-disabled="$root.loading || !vm.isDirty" |
116 | class="tb-btn-footer md-accent md-hue-2 md-fab" | 123 | class="tb-btn-footer md-accent md-hue-2 md-fab" |
117 | aria-label="{{ 'action.apply' | translate }}" | 124 | aria-label="{{ 'action.apply' | translate }}" |
@@ -22,6 +22,7 @@ | @@ -22,6 +22,7 @@ | ||
22 | ng-mousedown="callbacks.mouseDown($event, node)" | 22 | ng-mousedown="callbacks.mouseDown($event, node)" |
23 | ng-mouseenter="callbacks.mouseEnter($event, node)" | 23 | ng-mouseenter="callbacks.mouseEnter($event, node)" |
24 | ng-mouseleave="callbacks.mouseLeave($event, node)"> | 24 | ng-mouseleave="callbacks.mouseLeave($event, node)"> |
25 | + <div class="{{flowchartConstants.nodeOverlayClass}}"></div> | ||
25 | <div class="tb-rule-node {{node.nodeClass}}"> | 26 | <div class="tb-rule-node {{node.nodeClass}}"> |
26 | <md-icon aria-label="node-type-icon" flex="15" | 27 | <md-icon aria-label="node-type-icon" flex="15" |
27 | class="material-icons">{{node.icon}}</md-icon> | 28 | class="material-icons">{{node.icon}}</md-icon> |