Commit dc47727cf5e29f657fd00ec0422da5fd4799bbb6

Authored by Igor Kulikov
1 parent 39f682ce

UI: Improve Rule Chain Editor

@@ -69,14 +69,18 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod @@ -69,14 +69,18 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod
69 && ruleNode.getConfiguration().equals(newRuleNode.getConfiguration())); 69 && ruleNode.getConfiguration().equals(newRuleNode.getConfiguration()));
70 this.ruleNode = newRuleNode; 70 this.ruleNode = newRuleNode;
71 if (restartRequired) { 71 if (restartRequired) {
72 - tbNode.destroy(); 72 + if (tbNode != null) {
  73 + tbNode.destroy();
  74 + }
73 start(context); 75 start(context);
74 } 76 }
75 } 77 }
76 78
77 @Override 79 @Override
78 public void stop(ActorContext context) throws Exception { 80 public void stop(ActorContext context) throws Exception {
79 - tbNode.destroy(); 81 + if (tbNode != null) {
  82 + tbNode.destroy();
  83 + }
80 context.stop(self); 84 context.stop(self);
81 } 85 }
82 86
@@ -15,13 +15,13 @@ @@ -15,13 +15,13 @@
15 limitations under the License. 15 limitations under the License.
16 16
17 --> 17 -->
18 -<div hide-xs hide-sm translate class="tb-cell" flex="30">event.event-time</div> 18 +<div hide-xs hide-sm translate class="tb-cell" flex="25">event.event-time</div>
19 <div translate class="tb-cell" flex="20">event.server</div> 19 <div translate class="tb-cell" flex="20">event.server</div>
20 -<div translate class="tb-cell" flex="20">event.type</div>  
21 -<div translate class="tb-cell" flex="20">event.entity</div> 20 +<div translate class="tb-cell" flex="10">event.type</div>
  21 +<div translate class="tb-cell" flex="15">event.entity</div>
22 <div translate class="tb-cell" flex="20">event.message-id</div> 22 <div translate class="tb-cell" flex="20">event.message-id</div>
23 <div translate class="tb-cell" flex="20">event.message-type</div> 23 <div translate class="tb-cell" flex="20">event.message-type</div>
24 -<div translate class="tb-cell" flex="20">event.data-type</div>  
25 -<div translate class="tb-cell" flex="20">event.data</div>  
26 -<div translate class="tb-cell" flex="20">event.metadata</div>  
27 -<div translate class="tb-cell" flex="20">event.error</div> 24 +<div translate class="tb-cell" flex="15">event.data-type</div>
  25 +<div translate class="tb-cell" flex="10">event.data</div>
  26 +<div translate class="tb-cell" flex="10">event.metadata</div>
  27 +<div translate class="tb-cell" flex="10">event.error</div>
@@ -15,14 +15,14 @@ @@ -15,14 +15,14 @@
15 limitations under the License. 15 limitations under the License.
16 16
17 --> 17 -->
18 -<div hide-xs hide-sm class="tb-cell" flex="30">{{event.createdTime | date : 'yyyy-MM-dd HH:mm:ss'}}</div> 18 +<div hide-xs hide-sm class="tb-cell" flex="25">{{event.createdTime | date : 'yyyy-MM-dd HH:mm:ss'}}</div>
19 <div class="tb-cell" flex="20">{{event.body.server}}</div> 19 <div class="tb-cell" flex="20">{{event.body.server}}</div>
20 -<div class="tb-cell" flex="20">{{event.body.type}}</div>  
21 -<div class="tb-cell" flex="20">{{event.body.entityName}}</div>  
22 -<div class="tb-cell" flex="20">{{event.body.msgId}}</div>  
23 -<div class="tb-cell" flex="20">{{event.body.msgType}}</div>  
24 -<div class="tb-cell" flex="20">{{event.body.dataType}}</div>  
25 -<div class="tb-cell" flex="20"> 20 +<div class="tb-cell" flex="10">{{event.body.type}}</div>
  21 +<div class="tb-cell" flex="15">{{event.body.entityName}}</div>
  22 +<div class="tb-cell tb-nowrap" flex="20" ng-mouseenter="checkTooltip($event)">{{event.body.msgId}}</div>
  23 +<div class="tb-cell" flex="20" ng-mouseenter="checkTooltip($event)">{{event.body.msgType}}</div>
  24 +<div class="tb-cell" flex="15">{{event.body.dataType}}</div>
  25 +<div class="tb-cell" flex="10">
26 <md-button ng-if="event.body.data" class="md-icon-button md-primary" 26 <md-button ng-if="event.body.data" class="md-icon-button md-primary"
27 ng-click="showContent($event, event.body.data, 'event.data', event.body.dataType)" 27 ng-click="showContent($event, event.body.data, 'event.data', event.body.dataType)"
28 aria-label="{{ 'action.view' | translate }}"> 28 aria-label="{{ 'action.view' | translate }}">
@@ -35,7 +35,7 @@ @@ -35,7 +35,7 @@
35 </md-icon> 35 </md-icon>
36 </md-button> 36 </md-button>
37 </div> 37 </div>
38 -<div class="tb-cell" flex="20"> 38 +<div class="tb-cell" flex="10">
39 <md-button ng-if="event.body.metadata" class="md-icon-button md-primary" 39 <md-button ng-if="event.body.metadata" class="md-icon-button md-primary"
40 ng-click="showContent($event, event.body.metadata, 'event.metadata', 'JSON')" 40 ng-click="showContent($event, event.body.metadata, 'event.metadata', 'JSON')"
41 aria-label="{{ 'action.view' | translate }}"> 41 aria-label="{{ 'action.view' | translate }}">
@@ -48,7 +48,7 @@ @@ -48,7 +48,7 @@
48 </md-icon> 48 </md-icon>
49 </md-button> 49 </md-button>
50 </div> 50 </div>
51 -<div class="tb-cell" flex="20"> 51 +<div class="tb-cell" flex="10">
52 <md-button ng-if="event.body.error" class="md-icon-button md-primary" 52 <md-button ng-if="event.body.error" class="md-icon-button md-primary"
53 ng-click="showContent($event, event.body.error, 'event.error')" 53 ng-click="showContent($event, event.body.error, 'event.error')"
54 aria-label="{{ 'action.view' | translate }}"> 54 aria-label="{{ 'action.view' | translate }}">
@@ -86,6 +86,14 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $ @@ -86,6 +86,14 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $
86 }); 86 });
87 } 87 }
88 88
  89 + scope.checkTooltip = function($event) {
  90 + var el = $event.target;
  91 + var $el = angular.element(el);
  92 + if(el.offsetWidth < el.scrollWidth && !$el.attr('title')){
  93 + $el.attr('title', $el.text());
  94 + }
  95 + }
  96 +
89 $compile(element.contents())(scope); 97 $compile(element.contents())(scope);
90 } 98 }
91 99
@@ -24,6 +24,17 @@ md-list.tb-event-table { @@ -24,6 +24,17 @@ md-list.tb-event-table {
24 height: 48px; 24 height: 48px;
25 padding: 0px; 25 padding: 0px;
26 overflow: hidden; 26 overflow: hidden;
  27 + .tb-cell {
  28 + text-overflow: ellipsis;
  29 + &.tb-scroll {
  30 + white-space: nowrap;
  31 + overflow-y: hidden;
  32 + overflow-x: auto;
  33 + }
  34 + &.tb-nowrap {
  35 + white-space: nowrap;
  36 + }
  37 + }
27 } 38 }
28 39
29 .tb-row:hover { 40 .tb-row:hover {
@@ -39,13 +50,19 @@ md-list.tb-event-table { @@ -39,13 +50,19 @@ md-list.tb-event-table {
39 color: rgba(0,0,0,.54); 50 color: rgba(0,0,0,.54);
40 font-size: 12px; 51 font-size: 12px;
41 font-weight: 700; 52 font-weight: 700;
42 - white-space: nowrap;  
43 background: none; 53 background: none;
  54 + white-space: nowrap;
44 } 55 }
45 } 56 }
46 57
47 .tb-cell { 58 .tb-cell {
48 - padding: 0 24px; 59 + &:first-child {
  60 + padding-left: 14px;
  61 + }
  62 + &:last-child {
  63 + padding-right: 14px;
  64 + }
  65 + padding: 0 6px;
49 margin: auto 0; 66 margin: auto 0;
50 color: rgba(0,0,0,.87); 67 color: rgba(0,0,0,.87);
51 font-size: 13px; 68 font-size: 13px;
@@ -53,8 +70,8 @@ md-list.tb-event-table { @@ -53,8 +70,8 @@ md-list.tb-event-table {
53 text-align: left; 70 text-align: left;
54 overflow: hidden; 71 overflow: hidden;
55 .md-button { 72 .md-button {
56 - padding: 0;  
57 - margin: 0; 73 + padding: 0;
  74 + margin: 0;
58 } 75 }
59 } 76 }
60 77
@@ -43,6 +43,7 @@ export default angular.module('thingsboard.locale', []) @@ -43,6 +43,7 @@ export default angular.module('thingsboard.locale', [])
43 "update": "Update", 43 "update": "Update",
44 "remove": "Remove", 44 "remove": "Remove",
45 "search": "Search", 45 "search": "Search",
  46 + "clear-search": "Clear search",
46 "assign": "Assign", 47 "assign": "Assign",
47 "unassign": "Unassign", 48 "unassign": "Unassign",
48 "share": "Share", 49 "share": "Share",
@@ -1188,6 +1189,7 @@ export default angular.module('thingsboard.locale', []) @@ -1188,6 +1189,7 @@ export default angular.module('thingsboard.locale', [])
1188 "details": "Details", 1189 "details": "Details",
1189 "events": "Events", 1190 "events": "Events",
1190 "search": "Search nodes", 1191 "search": "Search nodes",
  1192 + "open-node-library": "Open node library",
1191 "add": "Add rule node", 1193 "add": "Add rule node",
1192 "name": "Name", 1194 "name": "Name",
1193 "name-required": "Name is required.", 1195 "name-required": "Name is required.",
@@ -37,6 +37,8 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, @@ -37,6 +37,8 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
37 vm.$mdExpansionPanel = $mdExpansionPanel; 37 vm.$mdExpansionPanel = $mdExpansionPanel;
38 vm.types = types; 38 vm.types = types;
39 39
  40 + vm.isFullscreen = false;
  41 +
40 vm.editingRuleNode = null; 42 vm.editingRuleNode = null;
41 vm.isEditingRuleNode = false; 43 vm.isEditingRuleNode = false;
42 44
@@ -57,6 +59,7 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, @@ -57,6 +59,7 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
57 }; 59 };
58 60
59 vm.ruleNodeTypesModel = {}; 61 vm.ruleNodeTypesModel = {};
  62 + vm.ruleNodeTypesCanvasControl = {};
60 vm.ruleChainLibraryLoaded = false; 63 vm.ruleChainLibraryLoaded = false;
61 for (var type in types.ruleNodeType) { 64 for (var type in types.ruleNodeType) {
62 if (!types.ruleNodeType[type].special) { 65 if (!types.ruleNodeType[type].special) {
@@ -67,9 +70,12 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, @@ -67,9 +70,12 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
67 }, 70 },
68 selectedObjects: [] 71 selectedObjects: []
69 }; 72 };
  73 + vm.ruleNodeTypesCanvasControl[type] = {};
70 } 74 }
71 } 75 }
72 76
  77 +
  78 +
73 vm.selectedObjects = []; 79 vm.selectedObjects = [];
74 80
75 vm.modelservice = Modelfactory(vm.ruleChainModel, vm.selectedObjects); 81 vm.modelservice = Modelfactory(vm.ruleChainModel, vm.selectedObjects);
@@ -147,6 +153,7 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, @@ -147,6 +153,7 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
147 theForm.$setPristine(); 153 theForm.$setPristine();
148 vm.ruleChainModel.nodes[vm.editingRuleNodeIndex] = vm.editingRuleNode; 154 vm.ruleChainModel.nodes[vm.editingRuleNodeIndex] = vm.editingRuleNode;
149 vm.editingRuleNode = angular.copy(vm.editingRuleNode); 155 vm.editingRuleNode = angular.copy(vm.editingRuleNode);
  156 + updateRuleNodesHighlight();
150 } 157 }
151 }; 158 };
152 159
@@ -313,12 +320,28 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, @@ -313,12 +320,28 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
313 } 320 }
314 }; 321 };
315 322
316 - loadRuleChainLibrary(); 323 + loadRuleChainLibrary(ruleNodeComponents, true);
  324 +
  325 + $scope.$watch('vm.ruleNodeSearch',
  326 + function (newVal, oldVal) {
  327 + if (!angular.equals(newVal, oldVal)) {
  328 + var res = $filter('filter')(ruleNodeComponents, {name: vm.ruleNodeSearch});
  329 + loadRuleChainLibrary(res);
  330 + }
  331 + }
  332 + );
317 333
318 - function loadRuleChainLibrary() { 334 + $scope.$on('searchTextUpdated', function () {
  335 + updateRuleNodesHighlight();
  336 + });
  337 +
  338 + function loadRuleChainLibrary(ruleNodeComponents, loadRuleChain) {
  339 + for (var componentType in vm.ruleNodeTypesModel) {
  340 + vm.ruleNodeTypesModel[componentType].model.nodes.length = 0;
  341 + }
319 for (var i=0;i<ruleNodeComponents.length;i++) { 342 for (var i=0;i<ruleNodeComponents.length;i++) {
320 var ruleNodeComponent = ruleNodeComponents[i]; 343 var ruleNodeComponent = ruleNodeComponents[i];
321 - var componentType = ruleNodeComponent.type; 344 + componentType = ruleNodeComponent.type;
322 var model = vm.ruleNodeTypesModel[componentType].model; 345 var model = vm.ruleNodeTypesModel[componentType].model;
323 var node = { 346 var node = {
324 id: 'node-lib-' + componentType + '-' + model.nodes.length, 347 id: 'node-lib-' + componentType + '-' + model.nodes.length,
@@ -349,7 +372,16 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, @@ -349,7 +372,16 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
349 model.nodes.push(node); 372 model.nodes.push(node);
350 } 373 }
351 vm.ruleChainLibraryLoaded = true; 374 vm.ruleChainLibraryLoaded = true;
352 - prepareRuleChain(); 375 + if (loadRuleChain) {
  376 + prepareRuleChain();
  377 + }
  378 + $mdUtil.nextTick(() => {
  379 + for (componentType in vm.ruleNodeTypesCanvasControl) {
  380 + if (vm.ruleNodeTypesCanvasControl[componentType].adjustCanvasSize) {
  381 + vm.ruleNodeTypesCanvasControl[componentType].adjustCanvasSize(true);
  382 + }
  383 + }
  384 + });
353 } 385 }
354 386
355 function prepareRuleChain() { 387 function prepareRuleChain() {
@@ -519,6 +551,8 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, @@ -519,6 +551,8 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
519 551
520 vm.isDirty = false; 552 vm.isDirty = false;
521 553
  554 + updateRuleNodesHighlight();
  555 +
522 $mdUtil.nextTick(() => { 556 $mdUtil.nextTick(() => {
523 vm.ruleChainWatch = $scope.$watch('vm.ruleChainModel', 557 vm.ruleChainWatch = $scope.$watch('vm.ruleChainModel',
524 function (newVal, oldVal) { 558 function (newVal, oldVal) {
@@ -530,6 +564,20 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, @@ -530,6 +564,20 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
530 }); 564 });
531 } 565 }
532 566
  567 + function updateRuleNodesHighlight() {
  568 + for (var i=0;i<vm.ruleChainModel.nodes.length;i++) {
  569 + vm.ruleChainModel.nodes[i].highlighted = false;
  570 + }
  571 + if ($scope.searchConfig.searchText) {
  572 + var res = $filter('filter')(vm.ruleChainModel.nodes, {name: $scope.searchConfig.searchText});
  573 + if (res) {
  574 + for (i=0;i<res.length;i++) {
  575 + res[i].highlighted = true;
  576 + }
  577 + }
  578 + }
  579 + }
  580 +
533 function saveRuleChain() { 581 function saveRuleChain() {
534 var ruleChainMetaData = { 582 var ruleChainMetaData = {
535 ruleChainId: vm.ruleChain.id, 583 ruleChainId: vm.ruleChain.id,
@@ -642,6 +690,7 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, @@ -642,6 +690,7 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
642 ); 690 );
643 } 691 }
644 vm.ruleChainModel.nodes.push(ruleNode); 692 vm.ruleChainModel.nodes.push(ruleNode);
  693 + updateRuleNodesHighlight();
645 }, function () { 694 }, function () {
646 }); 695 });
647 } 696 }
@@ -76,7 +76,7 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider @@ -76,7 +76,7 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider
76 } 76 }
77 }, 77 },
78 data: { 78 data: {
79 - searchEnabled: false, 79 + searchEnabled: true,
80 pageTitle: 'rulechain.rulechain' 80 pageTitle: 'rulechain.rulechain'
81 }, 81 },
82 ncyBreadcrumb: { 82 ncyBreadcrumb: {
@@ -125,6 +125,13 @@ @@ -125,6 +125,13 @@
125 color: #333; 125 color: #333;
126 border: solid 1px #777; 126 border: solid 1px #777;
127 font-size: 12px; 127 font-size: 12px;
  128 + &.tb-rule-node-highlighted {
  129 + box-shadow: 0 0 10px 6px #51cbee;
  130 + .tb-node-title {
  131 + text-decoration: underline;
  132 + font-weight: bold;
  133 + }
  134 + }
128 &.tb-input-type { 135 &.tb-input-type {
129 background-color: #a3eaa9; 136 background-color: #a3eaa9;
130 user-select: none; 137 user-select: none;
@@ -156,7 +163,7 @@ @@ -156,7 +163,7 @@
156 163
157 } 164 }
158 .tb-node-title { 165 .tb-node-title {
159 - font-weight: 600; 166 + font-weight: 500;
160 } 167 }
161 .tb-node-type, .tb-node-title { 168 .tb-node-type, .tb-node-title {
162 overflow: hidden; 169 overflow: hidden;
@@ -184,6 +191,10 @@ @@ -184,6 +191,10 @@
184 bottom: 0; 191 bottom: 0;
185 background-color: #000; 192 background-color: #000;
186 opacity: 0; 193 opacity: 0;
  194 +/* &.tb-rule-node-highlighted {
  195 + background-color: green;
  196 + opacity: 0.15;
  197 + }*/
187 } 198 }
188 &.fc-hover { 199 &.fc-hover {
189 .fc-node-overlay { 200 .fc-node-overlay {
@@ -19,17 +19,17 @@ @@ -19,17 +19,17 @@
19 <md-content flex tb-expand-fullscreen tb-confirm-on-exit is-dirty="vm.isDirty" 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" 20 expand-tooltip-direction="bottom" layout="column" class="tb-rulechain"
21 ng-keydown="vm.keyDown($event)" 21 ng-keydown="vm.keyDown($event)"
22 - ng-keyup="vm.keyUp($event)"> 22 + ng-keyup="vm.keyUp($event)" on-fullscreen-changed="vm.isFullscreen = expanded">
23 <section class="tb-rulechain-container" flex layout="column"> 23 <section class="tb-rulechain-container" flex layout="column">
24 <div class="tb-rulechain-layout" flex layout="row"> 24 <div class="tb-rulechain-layout" flex layout="row">
25 <section layout="row" layout-wrap 25 <section layout="row" layout-wrap
26 class="tb-header-buttons md-fab tb-library-open"> 26 class="tb-header-buttons md-fab tb-library-open">
27 <md-button ng-show="!vm.isLibraryOpen" 27 <md-button ng-show="!vm.isLibraryOpen"
28 class="tb-btn-header tb-btn-open-library md-primary md-fab md-fab-top-left" 28 class="tb-btn-header tb-btn-open-library md-primary md-fab md-fab-top-left"
29 - aria-label="{{ 'action.apply' | translate }}" 29 + aria-label="{{ 'rulenode.open-node-library' | translate }}"
30 ng-click="vm.isLibraryOpen = true"> 30 ng-click="vm.isLibraryOpen = true">
31 - <md-tooltip md-direction="top">  
32 - {{ 'action.apply-changes' | translate }} 31 + <md-tooltip md-direction="{{vm.isFullscreen ? 'bottom' : 'top'}}">
  32 + {{ 'rulenode.open-node-library' | translate }}
33 </md-tooltip> 33 </md-tooltip>
34 <ng-md-icon icon="menu"></ng-md-icon> 34 <ng-md-icon icon="menu"></ng-md-icon>
35 </md-button> 35 </md-button>
@@ -43,7 +43,7 @@ @@ -43,7 +43,7 @@
43 <div class="md-toolbar-tools"> 43 <div class="md-toolbar-tools">
44 <md-button class="md-icon-button tb-small" aria-label="{{ 'action.search' | translate }}"> 44 <md-button class="md-icon-button tb-small" aria-label="{{ 'action.search' | translate }}">
45 <md-icon aria-label="{{ 'action.search' | translate }}" class="material-icons">search</md-icon> 45 <md-icon aria-label="{{ 'action.search' | translate }}" class="material-icons">search</md-icon>
46 - <md-tooltip md-direction="top"> 46 + <md-tooltip md-direction="{{vm.isFullscreen ? 'bottom' : 'top'}}">
47 {{'rulenode.search' | translate}} 47 {{'rulenode.search' | translate}}
48 </md-tooltip> 48 </md-tooltip>
49 </md-button> 49 </md-button>
@@ -53,15 +53,17 @@ @@ -53,15 +53,17 @@
53 <input ng-model="vm.ruleNodeSearch" placeholder="{{'rulenode.search' | translate}}"/> 53 <input ng-model="vm.ruleNodeSearch" placeholder="{{'rulenode.search' | translate}}"/>
54 </md-input-container> 54 </md-input-container>
55 </div> 55 </div>
56 - <md-button class="md-icon-button tb-small" aria-label="Close" ng-click="vm.ruleNodeSearch = ''"> 56 + <md-button class="md-icon-button tb-small" aria-label="Close"
  57 + ng-show="vm.ruleNodeSearch"
  58 + ng-click="vm.ruleNodeSearch = ''">
57 <md-icon aria-label="Close" class="material-icons">close</md-icon> 59 <md-icon aria-label="Close" class="material-icons">close</md-icon>
58 - <md-tooltip md-direction="top">  
59 - {{ 'action.close' | translate }} 60 + <md-tooltip md-direction="{{vm.isFullscreen ? 'bottom' : 'top'}}">
  61 + {{ 'action.clear-search' | translate }}
60 </md-tooltip> 62 </md-tooltip>
61 </md-button> 63 </md-button>
62 <md-button class="md-icon-button tb-small" aria-label="Close" ng-click="vm.isLibraryOpen = false"> 64 <md-button class="md-icon-button tb-small" aria-label="Close" ng-click="vm.isLibraryOpen = false">
63 <md-icon aria-label="Close" class="material-icons">chevron_left</md-icon> 65 <md-icon aria-label="Close" class="material-icons">chevron_left</md-icon>
64 - <md-tooltip md-direction="top"> 66 + <md-tooltip md-direction="{{vm.isFullscreen ? 'bottom' : 'top'}}">
65 {{ 'action.close' | translate }} 67 {{ 'action.close' | translate }}
66 </md-tooltip> 68 </md-tooltip>
67 </md-button> 69 </md-button>
@@ -90,6 +92,7 @@ @@ -90,6 +92,7 @@
90 callbacks="vm.nodeLibCallbacks" 92 callbacks="vm.nodeLibCallbacks"
91 node-width="170" 93 node-width="170"
92 node-height="50" 94 node-height="50"
  95 + control="vm.ruleNodeTypesCanvasControl[typeId]"
93 drop-target-id="'tb-rulchain-canvas'"></fc-canvas> 96 drop-target-id="'tb-rulchain-canvas'"></fc-canvas>
94 </md-expansion-panel-content> 97 </md-expansion-panel-content>
95 </md-expansion-panel-expanded> 98 </md-expansion-panel-expanded>
@@ -22,8 +22,8 @@ @@ -22,8 +22,8 @@
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>  
26 - <div class="tb-rule-node {{node.nodeClass}}"> 25 + <div class="{{flowchartConstants.nodeOverlayClass}}" ng-class="{'tb-rule-node-highlighted' : node.highlighted}"></div>
  26 + <div class="tb-rule-node {{node.nodeClass}}" ng-class="{'tb-rule-node-highlighted' : node.highlighted}">
27 <md-icon aria-label="node-type-icon" flex="15" 27 <md-icon aria-label="node-type-icon" flex="15"
28 class="material-icons">{{node.icon}}</md-icon> 28 class="material-icons">{{node.icon}}</md-icon>
29 <div layout="column" flex="85" layout-align="center"> 29 <div layout="column" flex="85" layout-align="center">