thingsboard-developers
Changes
application/src/test/java/org/thingsboard/server/controller/AbstractRuleEngineControllerTest.java 2(+1 -1)
ui/src/app/common/types.constant.js 30(+29 -1)
ui/src/app/event/event-row.directive.js 16(+14 -2)
ui/src/app/event/event-table.directive.js 18(+15 -3)
ui/src/app/locale/locale.constant.js 15(+15 -0)
ui/src/app/rulechain/rulechain.controller.js 15(+10 -5)
ui/src/app/rulechain/rulechain.tpl.html 18(+15 -3)
Details
diff --git a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java
index a5a20b8..9e02946 100644
--- a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java
+++ b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java
@@ -25,6 +25,7 @@ import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import lombok.Getter;
import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@@ -38,6 +39,7 @@ import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.msg.TbMsg;
+import org.thingsboard.server.common.msg.TbMsgDataType;
import org.thingsboard.server.common.msg.cluster.ServerAddress;
import org.thingsboard.server.common.transport.auth.DeviceAuthService;
import org.thingsboard.server.controller.plugin.PluginWebSocketMsgEndpoint;
@@ -60,11 +62,13 @@ import org.thingsboard.server.service.cluster.routing.ClusterRoutingService;
import org.thingsboard.server.service.cluster.rpc.ClusterRpcService;
import org.thingsboard.server.service.component.ComponentDiscoveryService;
+import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
+@Slf4j
@Component
public class ActorSystemContext {
private static final String AKKA_CONF_FILE_NAME = "actor-system.conf";
@@ -292,38 +296,49 @@ public class ActorSystemContext {
}
private void persistDebug(TenantId tenantId, EntityId entityId, String type, TbMsg tbMsg, Throwable error) {
- Event event = new Event();
- event.setTenantId(tenantId);
- event.setEntityId(entityId);
- event.setType(DataConstants.DEBUG);
-
- ObjectNode node = mapper.createObjectNode()
- .put("type", type)
- .put("server", getServerAddress())
- .put("entityId", tbMsg.getOriginator().getId().toString())
- .put("entityName", tbMsg.getOriginator().getEntityType().name())
- .put("msgId", tbMsg.getId().toString())
- .put("msgType", tbMsg.getType())
- .put("dataType", tbMsg.getDataType().name());
-
- ObjectNode mdNode = node.putObject("metadata");
- tbMsg.getMetaData().getData().forEach(mdNode::put);
+ try {
+ Event event = new Event();
+ event.setTenantId(tenantId);
+ event.setEntityId(entityId);
+ event.setType(DataConstants.DEBUG_RULE_NODE);
+
+ String metadata = mapper.writeValueAsString(tbMsg.getMetaData().getData());
+
+ ObjectNode node = mapper.createObjectNode()
+ .put("type", type)
+ .put("server", getServerAddress())
+ .put("entityId", tbMsg.getOriginator().getId().toString())
+ .put("entityName", tbMsg.getOriginator().getEntityType().name())
+ .put("msgId", tbMsg.getId().toString())
+ .put("msgType", tbMsg.getType())
+ .put("dataType", tbMsg.getDataType().name())
+ .put("data", convertToString(tbMsg.getDataType(), tbMsg.getData()))
+ .put("metadata", metadata);
+
+ if (error != null) {
+ node = node.put("error", toString(error));
+ }
+
+ event.setBody(node);
+ eventService.save(event);
+ } catch (IOException ex) {
+ log.warn("Failed to persist rule node debug message", ex);
+ }
+ }
- switch (tbMsg.getDataType()) {
+ private String convertToString(TbMsgDataType messageType, byte[] data) {
+ if (data == null) {
+ return null;
+ }
+ switch (messageType) {
+ case JSON:
+ case TEXT:
+ return new String(data, StandardCharsets.UTF_8);
case BINARY:
- node.put("data", Base64Utils.encodeUrlSafe(tbMsg.getData()));
- break;
+ return Base64Utils.encodeToString(data);
default:
- node.put("data", new String(tbMsg.getData(), StandardCharsets.UTF_8));
- break;
- }
-
- if (error != null) {
- node = node.put("error", toString(error));
+ throw new RuntimeException("Message type: " + messageType + " is not supported!");
}
-
- event.setBody(node);
- eventService.save(event);
}
public static Exception toException(Throwable error) {
diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractRuleEngineControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractRuleEngineControllerTest.java
index bbcb98f..93fe767 100644
--- a/application/src/test/java/org/thingsboard/server/controller/AbstractRuleEngineControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/AbstractRuleEngineControllerTest.java
@@ -51,6 +51,6 @@ public class AbstractRuleEngineControllerTest extends AbstractControllerTest {
TimePageLink pageLink = new TimePageLink(limit);
return doGetTypedWithTimePageLink("/api/events/{entityType}/{entityId}/{eventType}?tenantId={tenantId}&",
new TypeReference<TimePageData<Event>>() {
- }, pageLink, entityId.getEntityType(), entityId.getId(), DataConstants.DEBUG, tenantId.getId());
+ }, pageLink, entityId.getEntityType(), entityId.getId(), DataConstants.DEBUG_RULE_NODE, tenantId.getId());
}
}
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java b/common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java
index 659a242..7d4e480 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java
@@ -37,7 +37,7 @@ public class DataConstants {
public static final String ERROR = "ERROR";
public static final String LC_EVENT = "LC_EVENT";
public static final String STATS = "STATS";
- public static final String DEBUG = "DEBUG";
+ public static final String DEBUG_RULE_NODE = "DEBUG_RULE_NODE";
public static final String ONEWAY = "ONEWAY";
public static final String TWOWAY = "TWOWAY";
ui/src/app/common/types.constant.js 30(+29 -1)
diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js
index 8026115..2186508 100644
--- a/ui/src/app/common/types.constant.js
+++ b/ui/src/app/common/types.constant.js
@@ -279,6 +279,23 @@ export default angular.module('thingsboard.types', [])
function: "function",
alarm: "alarm"
},
+ contentType: {
+ "JSON": {
+ value: "JSON",
+ name: "content-type.json",
+ code: "json"
+ },
+ "TEXT": {
+ value: "TEXT",
+ name: "content-type.text",
+ code: "text"
+ },
+ "BINARY": {
+ value: "BINARY",
+ name: "content-type.binary",
+ code: "text"
+ }
+ },
componentType: {
filter: "FILTER",
processor: "PROCESSOR",
@@ -295,7 +312,8 @@ export default angular.module('thingsboard.types', [])
user: "USER",
dashboard: "DASHBOARD",
alarm: "ALARM",
- rulechain: "RULE_CHAIN"
+ rulechain: "RULE_CHAIN",
+ rulenode: "RULE_NODE"
},
aliasEntityType: {
current_customer: "CURRENT_CUSTOMER"
@@ -388,6 +406,16 @@ export default angular.module('thingsboard.types', [])
name: "event.type-stats"
}
},
+ debugEventType: {
+ debugRuleNode: {
+ value: "DEBUG_RULE_NODE",
+ name: "event.type-debug-rule-node"
+ },
+ debugRuleChain: {
+ value: "DEBUG_RULE_CHAIN",
+ name: "event.type-debug-rule-chain"
+ }
+ },
extensionType: {
http: "HTTP",
mqtt: "MQTT",
diff --git a/ui/src/app/components/details-sidenav.directive.js b/ui/src/app/components/details-sidenav.directive.js
index e455a80..a25374b 100644
--- a/ui/src/app/components/details-sidenav.directive.js
+++ b/ui/src/app/components/details-sidenav.directive.js
@@ -26,7 +26,7 @@ export default angular.module('thingsboard.directives.detailsSidenav', [])
.name;
/*@ngInject*/
-function DetailsSidenav($timeout) {
+function DetailsSidenav($timeout, $window) {
var linker = function (scope, element, attrs) {
@@ -42,6 +42,23 @@ function DetailsSidenav($timeout) {
scope.isEdit = true;
}
+ if (angular.isDefined(attrs.closeOnClickOutside && attrs.closeOnClickOutside)) {
+ scope.closeOnClickOutside = true;
+ var clickOutsideHandler = function() {
+ scope.closeDetails();
+ };
+ angular.element($window).click(clickOutsideHandler);
+ scope.$on("$destroy", function () {
+ angular.element($window).unbind('click', clickOutsideHandler);
+ });
+ }
+
+ scope.onClick = function($event) {
+ if (scope.closeOnClickOutside) {
+ $event.stopPropagation();
+ }
+ };
+
scope.toggleDetailsEditMode = function () {
if (!scope.isAlwaysEdit) {
if (!scope.isEdit) {
diff --git a/ui/src/app/components/details-sidenav.tpl.html b/ui/src/app/components/details-sidenav.tpl.html
index c504a24..a0032ff 100644
--- a/ui/src/app/components/details-sidenav.tpl.html
+++ b/ui/src/app/components/details-sidenav.tpl.html
@@ -19,6 +19,7 @@
md-disable-backdrop="true"
md-is-open="isOpen"
md-component-id="right"
+ ng-click="onClick($event)"
layout="column">
<header>
<md-toolbar class="md-theme-light" ng-style="{'height':headerHeightPx+'px'}">
diff --git a/ui/src/app/event/event-content-dialog.controller.js b/ui/src/app/event/event-content-dialog.controller.js
index 108f95e..8d13f96 100644
--- a/ui/src/app/event/event-content-dialog.controller.js
+++ b/ui/src/app/event/event-content-dialog.controller.js
@@ -17,11 +17,14 @@ import $ from 'jquery';
import 'brace/ext/language_tools';
import 'brace/mode/java';
import 'brace/theme/github';
+import beautify from 'js-beautify';
/* eslint-disable angular/angularelement */
+const js_beautify = beautify.js;
+
/*@ngInject*/
-export default function EventContentDialogController($mdDialog, content, title, showingCallback) {
+export default function EventContentDialogController($mdDialog, types, content, contentType, title, showingCallback) {
var vm = this;
@@ -32,9 +35,19 @@ export default function EventContentDialogController($mdDialog, content, title,
vm.content = content;
vm.title = title;
+ var mode;
+ if (contentType) {
+ mode = types.contentType[contentType].code;
+ if (contentType == types.contentType.JSON.value && vm.content) {
+ vm.content = js_beautify(vm.content, {indent_size: 4});
+ }
+ } else {
+ mode = 'java';
+ }
+
vm.contentOptions = {
useWrapMode: false,
- mode: 'java',
+ mode: mode,
showGutter: false,
showPrintMargin: false,
theme: 'github',
diff --git a/ui/src/app/event/event-header.directive.js b/ui/src/app/event/event-header.directive.js
index afac804..bc4cdbe 100644
--- a/ui/src/app/event/event-header.directive.js
+++ b/ui/src/app/event/event-header.directive.js
@@ -18,6 +18,7 @@
import eventHeaderLcEventTemplate from './event-header-lc-event.tpl.html';
import eventHeaderStatsTemplate from './event-header-stats.tpl.html';
import eventHeaderErrorTemplate from './event-header-error.tpl.html';
+import eventHeaderDebugRuleNodeTemplate from './event-header-debug-rulenode.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
@@ -38,6 +39,12 @@ export default function EventHeaderDirective($compile, $templateCache, types) {
case types.eventType.error.value:
template = eventHeaderErrorTemplate;
break;
+ case types.debugEventType.debugRuleNode.value:
+ template = eventHeaderDebugRuleNodeTemplate;
+ break;
+ case types.debugEventType.debugRuleChain.value:
+ template = eventHeaderDebugRuleNodeTemplate;
+ break;
}
return $templateCache.get(template);
}
diff --git a/ui/src/app/event/event-header-debug-rulenode.tpl.html b/ui/src/app/event/event-header-debug-rulenode.tpl.html
new file mode 100644
index 0000000..b412a0c
--- /dev/null
+++ b/ui/src/app/event/event-header-debug-rulenode.tpl.html
@@ -0,0 +1,27 @@
+<!--
+
+ Copyright © 2016-2018 The Thingsboard Authors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<div hide-xs hide-sm translate class="tb-cell" flex="30">event.event-time</div>
+<div translate class="tb-cell" flex="20">event.server</div>
+<div translate class="tb-cell" flex="20">event.type</div>
+<div translate class="tb-cell" flex="20">event.entity</div>
+<div translate class="tb-cell" flex="20">event.message-id</div>
+<div translate class="tb-cell" flex="20">event.message-type</div>
+<div translate class="tb-cell" flex="20">event.data-type</div>
+<div translate class="tb-cell" flex="20">event.data</div>
+<div translate class="tb-cell" flex="20">event.metadata</div>
+<div translate class="tb-cell" flex="20">event.error</div>
ui/src/app/event/event-row.directive.js 16(+14 -2)
diff --git a/ui/src/app/event/event-row.directive.js b/ui/src/app/event/event-row.directive.js
index f005542..4643761 100644
--- a/ui/src/app/event/event-row.directive.js
+++ b/ui/src/app/event/event-row.directive.js
@@ -20,6 +20,7 @@ import eventErrorDialogTemplate from './event-content-dialog.tpl.html';
import eventRowLcEventTemplate from './event-row-lc-event.tpl.html';
import eventRowStatsTemplate from './event-row-stats.tpl.html';
import eventRowErrorTemplate from './event-row-error.tpl.html';
+import eventRowDebugRuleNodeTemplate from './event-row-debug-rulenode.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
@@ -40,6 +41,12 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $
case types.eventType.error.value:
template = eventRowErrorTemplate;
break;
+ case types.debugEventType.debugRuleNode.value:
+ template = eventRowDebugRuleNodeTemplate;
+ break;
+ case types.debugEventType.debugRuleChain.value:
+ template = eventRowDebugRuleNodeTemplate;
+ break;
}
return $templateCache.get(template);
}
@@ -53,17 +60,22 @@ export default function EventRowDirective($compile, $templateCache, $mdDialog, $
scope.loadTemplate();
});
+ scope.types = types;
+
scope.event = attrs.event;
- scope.showContent = function($event, content, title) {
+ scope.showContent = function($event, content, title, contentType) {
var onShowingCallback = {
onShowing: function(){}
}
+ if (!contentType) {
+ contentType = null;
+ }
$mdDialog.show({
controller: 'EventContentDialogController',
controllerAs: 'vm',
templateUrl: eventErrorDialogTemplate,
- locals: {content: content, title: title, showingCallback: onShowingCallback},
+ locals: {content: content, title: title, contentType: contentType, showingCallback: onShowingCallback},
parent: angular.element($document[0].body),
fullscreen: true,
targetEvent: $event,
diff --git a/ui/src/app/event/event-row-debug-rulenode.tpl.html b/ui/src/app/event/event-row-debug-rulenode.tpl.html
new file mode 100644
index 0000000..ec00b39
--- /dev/null
+++ b/ui/src/app/event/event-row-debug-rulenode.tpl.html
@@ -0,0 +1,63 @@
+<!--
+
+ Copyright © 2016-2018 The Thingsboard Authors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<div hide-xs hide-sm class="tb-cell" flex="30">{{event.createdTime | date : 'yyyy-MM-dd HH:mm:ss'}}</div>
+<div class="tb-cell" flex="20">{{event.body.server}}</div>
+<div class="tb-cell" flex="20">{{event.body.type}}</div>
+<div class="tb-cell" flex="20">{{event.body.entityName}}</div>
+<div class="tb-cell" flex="20">{{event.body.msgId}}</div>
+<div class="tb-cell" flex="20">{{event.body.msgType}}</div>
+<div class="tb-cell" flex="20">{{event.body.dataType}}</div>
+<div class="tb-cell" flex="20">
+ <md-button ng-if="event.body.data" class="md-icon-button md-primary"
+ ng-click="showContent($event, event.body.data, 'event.data', event.body.msgType)"
+ aria-label="{{ 'action.view' | translate }}">
+ <md-tooltip md-direction="top">
+ {{ 'action.view' | translate }}
+ </md-tooltip>
+ <md-icon aria-label="{{ 'action.view' | translate }}"
+ class="material-icons">
+ more_horiz
+ </md-icon>
+ </md-button>
+</div>
+<div class="tb-cell" flex="20">
+ <md-button ng-if="event.body.metadata" class="md-icon-button md-primary"
+ ng-click="showContent($event, event.body.metadata, 'event.metadata', 'JSON')"
+ aria-label="{{ 'action.view' | translate }}">
+ <md-tooltip md-direction="top">
+ {{ 'action.view' | translate }}
+ </md-tooltip>
+ <md-icon aria-label="{{ 'action.view' | translate }}"
+ class="material-icons">
+ more_horiz
+ </md-icon>
+ </md-button>
+</div>
+<div class="tb-cell" flex="20">
+ <md-button ng-if="event.body.error" class="md-icon-button md-primary"
+ ng-click="showContent($event, event.body.error, 'event.error')"
+ aria-label="{{ 'action.view' | translate }}">
+ <md-tooltip md-direction="top">
+ {{ 'action.view' | translate }}
+ </md-tooltip>
+ <md-icon aria-label="{{ 'action.view' | translate }}"
+ class="material-icons">
+ more_horiz
+ </md-icon>
+ </md-button>
+</div>
ui/src/app/event/event-table.directive.js 18(+15 -3)
diff --git a/ui/src/app/event/event-table.directive.js b/ui/src/app/event/event-table.directive.js
index 4291014..c61078d 100644
--- a/ui/src/app/event/event-table.directive.js
+++ b/ui/src/app/event/event-table.directive.js
@@ -36,8 +36,8 @@ export default function EventTableDirective($compile, $templateCache, $rootScope
for (var type in types.eventType) {
var eventType = types.eventType[type];
var enabled = true;
- for (var disabledType in disabledEventTypes) {
- if (eventType.value === disabledEventTypes[disabledType]) {
+ for (var i=0;i<disabledEventTypes.length;i++) {
+ if (eventType.value === disabledEventTypes[i]) {
enabled = false;
break;
}
@@ -47,7 +47,19 @@ export default function EventTableDirective($compile, $templateCache, $rootScope
}
}
} else {
- scope.eventTypes = types.eventType;
+ scope.eventTypes = angular.copy(types.eventType);
+ }
+
+ if (attrs.debugEventTypes) {
+ var debugEventTypes = attrs.debugEventTypes.split(',');
+ for (i=0;i<debugEventTypes.length;i++) {
+ for (type in types.debugEventType) {
+ eventType = types.debugEventType[type];
+ if (eventType.value === debugEventTypes[i]) {
+ scope.eventTypes[type] = eventType;
+ }
+ }
+ }
}
scope.eventType = attrs.defaultEventType;
ui/src/app/locale/locale.constant.js 15(+15 -0)
diff --git a/ui/src/app/locale/locale.constant.js b/ui/src/app/locale/locale.constant.js
index a70ca14..0a17e39 100644
--- a/ui/src/app/locale/locale.constant.js
+++ b/ui/src/app/locale/locale.constant.js
@@ -341,6 +341,11 @@ export default angular.module('thingsboard.locale', [])
"enter-password": "Enter password",
"enter-search": "Enter search"
},
+ "content-type": {
+ "json": "Json",
+ "text": "Text",
+ "binary": "Binary (Base64)"
+ },
"customer": {
"customer": "Customer",
"customers": "Customers",
@@ -762,6 +767,8 @@ export default angular.module('thingsboard.locale', [])
"type-error": "Error",
"type-lc-event": "Lifecycle event",
"type-stats": "Statistics",
+ "type-debug-rule-node": "Debug",
+ "type-debug-rule-chain": "Debug",
"no-events-prompt": "No events found",
"error": "Error",
"alarm": "Alarm",
@@ -769,6 +776,13 @@ export default angular.module('thingsboard.locale', [])
"server": "Server",
"body": "Body",
"method": "Method",
+ "type": "Type",
+ "entity": "Entity",
+ "message-id": "Message Id",
+ "message-type": "Message Type",
+ "data-type": "Data Type",
+ "metadata": "Metadata",
+ "data": "Data",
"event": "Event",
"status": "Status",
"success": "Success",
@@ -1172,6 +1186,7 @@ export default angular.module('thingsboard.locale', [])
},
"rulenode": {
"details": "Details",
+ "events": "Events",
"add": "Add rule node",
"name": "Name",
"name-required": "Name is required.",
ui/src/app/rulechain/rulechain.controller.js 15(+10 -5)
diff --git a/ui/src/app/rulechain/rulechain.controller.js b/ui/src/app/rulechain/rulechain.controller.js
index fbdda22..83bca32 100644
--- a/ui/src/app/rulechain/rulechain.controller.js
+++ b/ui/src/app/rulechain/rulechain.controller.js
@@ -28,7 +28,7 @@ import addRuleNodeLinkTemplate from './add-link.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
/*@ngInject*/
-export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, $timeout, $mdExpansionPanel, $document, $mdDialog,
+export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil, $timeout, $mdExpansionPanel, $window, $document, $mdDialog,
$filter, $translate, hotkeys, types, ruleChainService, Modelfactory, flowchartConstants,
ruleChain, ruleChainMetaData, ruleNodeComponents) {
@@ -77,6 +77,8 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
vm.objectsSelected = objectsSelected;
vm.deleteSelected = deleteSelected;
+ vm.triggerResize = triggerResize;
+
initHotKeys();
function initHotKeys() {
@@ -129,18 +131,17 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
}
vm.onEditRuleNodeClosed = function() {
- vm.editingRuleNode = null;
+ //vm.editingRuleNode = null;
};
vm.onEditRuleNodeLinkClosed = function() {
- vm.editingRuleNodeLink = null;
+ //vm.editingRuleNodeLink = null;
};
vm.saveRuleNode = function(theForm) {
$scope.$broadcast('form-submit');
if (theForm.$valid) {
theForm.$setPristine();
- vm.isEditingRuleNode = false;
vm.ruleChainModel.nodes[vm.editingRuleNodeIndex] = vm.editingRuleNode;
vm.editingRuleNode = angular.copy(vm.editingRuleNode);
}
@@ -148,7 +149,6 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
vm.saveRuleNodeLink = function(theForm) {
theForm.$setPristine();
- vm.isEditingRuleNodeLink = false;
vm.ruleChainModel.edges[vm.editingRuleNodeLinkIndex] = vm.editingRuleNodeLink;
vm.editingRuleNodeLink = angular.copy(vm.editingRuleNodeLink);
};
@@ -663,6 +663,11 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
function deleteSelected() {
vm.modelservice.deleteSelected();
}
+
+ function triggerResize() {
+ var w = angular.element($window);
+ w.triggerHandler('resize');
+ }
}
/*@ngInject*/
ui/src/app/rulechain/rulechain.tpl.html 18(+15 -3)
diff --git a/ui/src/app/rulechain/rulechain.tpl.html b/ui/src/app/rulechain/rulechain.tpl.html
index 3083f83..0d55771 100644
--- a/ui/src/app/rulechain/rulechain.tpl.html
+++ b/ui/src/app/rulechain/rulechain.tpl.html
@@ -67,8 +67,9 @@
header-title="{{vm.editingRuleNode.name}}"
header-subtitle="{{(vm.types.ruleNodeType[vm.editingRuleNode.component.type].name | translate)
+ ' - ' + vm.editingRuleNode.component.name}}"
- is-read-only="false"
+ is-read-only="vm.selectedRuleNodeTabIndex > 0"
is-open="vm.isEditingRuleNode"
+ close-on-click-outside="true"
is-always-edit="true"
on-close-details="vm.onEditRuleNodeClosed()"
on-toggle-details-edit-mode="vm.onRevertRuleNodeEdit(vm.ruleNodeForm)"
@@ -77,9 +78,10 @@
<details-buttons tb-help="vm.helpLinkIdForRuleNodeType()" help-container-id="help-container">
<div id="help-container"></div>
</details-buttons>
- <md-tabs id="ruleNodeTabs" md-border-bottom flex class="tb-absolute-fill">
+ <md-tabs md-selected="vm.selectedRuleNodeTabIndex"
+ id="ruleNodeTabs" md-border-bottom flex class="tb-absolute-fill" ng-if="vm.isEditingRuleNode">
<md-tab label="{{ 'rulenode.details' | translate }}">
- <form name="vm.ruleNodeForm" ng-if="vm.isEditingRuleNode">
+ <form name="vm.ruleNodeForm">
<tb-rule-node
rule-node="vm.editingRuleNode"
rule-chain-id="vm.ruleChain.id.id"
@@ -90,6 +92,15 @@
</tb-rule-node>
</form>
</md-tab>
+ <md-tab ng-if="vm.isEditingRuleNode && vm.editingRuleNode.ruleNodeId"
+ md-on-select="vm.triggerResize()" label="{{ 'rulenode.events' | translate }}">
+ <tb-event-table flex entity-type="vm.types.entityType.rulenode"
+ entity-id="vm.editingRuleNode.ruleNodeId.id"
+ tenant-id="vm.ruleChain.tenantId.id"
+ debug-event-types="{{vm.types.debugEventType.debugRuleNode.value}}"
+ default-event-type="{{vm.types.debugEventType.debugRuleNode.value}}">
+ </tb-event-table>
+ </md-tab>
</md-tabs>
</tb-details-sidenav>
<tb-details-sidenav class="tb-rulenode-link-details-sidenav"
@@ -97,6 +108,7 @@
header-subtitle="{{'rulenode.link-details' | translate}}"
is-read-only="false"
is-open="vm.isEditingRuleNodeLink"
+ close-on-click-outside="true"
is-always-edit="true"
on-close-details="vm.onEditRuleNodeLinkClosed()"
on-toggle-details-edit-mode="vm.onRevertRuleNodeLinkEdit(vm.ruleNodeLinkForm)"
diff --git a/ui/src/app/rulechain/rulechains.tpl.html b/ui/src/app/rulechain/rulechains.tpl.html
index a4fbd79..cf9d256 100644
--- a/ui/src/app/rulechain/rulechains.tpl.html
+++ b/ui/src/app/rulechain/rulechains.tpl.html
@@ -55,7 +55,8 @@
<tb-event-table flex entity-type="vm.types.entityType.rulechain"
entity-id="vm.grid.operatingItem().id.id"
tenant-id="vm.grid.operatingItem().tenantId.id"
- default-event-type="{{vm.types.eventType.lcEvent.value}}">
+ debug-event-types="{{vm.types.debugEventType.debugRuleChain.value}}"
+ default-event-type="{{vm.types.debugEventType.debugRuleChain.value}}">
</tb-event-table>
</md-tab>
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isRuleChainEditable(vm.grid.operatingItem())" md-on-select="vm.grid.triggerResize()" label="{{ 'relation.relations' | translate }}">