diff --git a/application/src/main/data/json/system/widget_bundles/alarm_widgets.json b/application/src/main/data/json/system/widget_bundles/alarm_widgets.json index aec4dd0702..164366dd84 100644 --- a/application/src/main/data/json/system/widget_bundles/alarm_widgets.json +++ b/application/src/main/data/json/system/widget_bundles/alarm_widgets.json @@ -15,7 +15,7 @@ "resources": [], "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n var id = self.ctx.$scope.$injector.get('utils').guid();\n scope.tableId = \"table-\"+id;\n scope.ctx = self.ctx;\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.$broadcast('alarms-table-data-updated', self.ctx.$scope.tableId);\n}\n\nself.onDestroy = function() {\n}\n", + "controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n var id = self.ctx.$scope.$injector.get('utils').guid();\n scope.tableId = \"table-\"+id;\n scope.ctx = self.ctx;\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.$broadcast('alarms-table-data-updated', self.ctx.$scope.tableId);\n}\n\nself.actionSources = function() {\n return {\n 'actionCellButton': {\n name: 'widget-action.action-cell-button',\n multiple: true\n },\n 'rowClick': {\n name: 'widget-action.row-click',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}\n", "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"AlarmTableSettings\",\n \"properties\": {\n \"alarmsTitle\": {\n \"title\": \"Alarms table title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"enableSelection\": {\n \"title\": \"Enable alarms selection\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableSearch\": {\n \"title\": \"Enable alarms search\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayDetails\": {\n \"title\": \"Display alarm details\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"allowAcknowledgment\": {\n \"title\": \"Allow alarms acknowledgment\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"allowClear\": {\n \"title\": \"Allow alarms clear\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayPagination\": {\n \"title\": \"Display pagination\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"defaultPageSize\": {\n \"title\": \"Default page size\",\n \"type\": \"number\",\n \"default\": 10\n },\n \"defaultSortOrder\": {\n \"title\": \"Default sort order\",\n \"type\": \"string\",\n \"default\": \"-createdTime\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"alarmsTitle\",\n \"enableSelection\",\n \"enableSearch\",\n \"displayDetails\",\n \"allowAcknowledgment\",\n \"allowClear\",\n \"displayPagination\",\n \"defaultPageSize\",\n \"defaultSortOrder\"\n ]\n}", "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"columnWidth\": {\n \"title\": \"Column width (px or %)\",\n \"type\": \"string\",\n \"default\": \"0px\"\n },\n \"useCellStyleFunction\": {\n \"title\": \"Use cell style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellStyleFunction\": {\n \"title\": \"Cell style function: f(value)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"useCellContentFunction\": {\n \"title\": \"Use cell content function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellContentFunction\": {\n \"title\": \"Cell content function: f(value, alarm, filter)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"columnWidth\",\n \"useCellStyleFunction\",\n {\n \"key\": \"cellStyleFunction\",\n \"type\": \"javascript\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"enableSelection\":true,\"enableSearch\":true,\"displayDetails\":true,\"allowAcknowledgment\":true,\"allowClear\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"defaultSortOrder\":\"-createdTime\"},\"title\":\"Alarms table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"18px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"alarmSource\":{\"type\":\"function\",\"dataKeys\":[{\"name\":\"createdTime\",\"type\":\"alarm\",\"label\":\"Created time\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.021092237451093787},{\"name\":\"originator\",\"type\":\"alarm\",\"label\":\"Originator\",\"color\":\"#4caf50\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.2780007688856758},{\"name\":\"type\",\"type\":\"alarm\",\"label\":\"Type\",\"color\":\"#f44336\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.7323586880398418},{\"name\":\"severity\",\"type\":\"alarm\",\"label\":\"Severity\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":false,\"useCellContentFunction\":false},\"_hash\":0.09927019860088193},{\"name\":\"status\",\"type\":\"alarm\",\"label\":\"Status\",\"color\":\"#607d8b\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6588418951443418}],\"entityAliasId\":null,\"name\":\"alarms\"},\"alarmSearchStatus\":\"ANY\",\"alarmsPollingInterval\":5}" diff --git a/ui/src/app/api/entity.service.js b/ui/src/app/api/entity.service.js index b20d0b375d..344edf5e7b 100644 --- a/ui/src/app/api/entity.service.js +++ b/ui/src/app/api/entity.service.js @@ -353,16 +353,20 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device function entitiesToEntitiesInfo(entities) { var entitiesInfo = []; - for (var d = 0; d < entities.length; d++) { - entitiesInfo.push(entityToEntityInfo(entities[d])); + if (entities) { + for (var d = 0; d < entities.length; d++) { + entitiesInfo.push(entityToEntityInfo(entities[d])); + } } return entitiesInfo; } function entityRelationInfosToEntitiesInfo(entityRelations, direction) { var entitiesInfo = []; - for (var d = 0; d < entityRelations.length; d++) { - entitiesInfo.push(entityRelationInfoToEntityInfo(entityRelations[d], direction)); + if (entityRelations) { + for (var d = 0; d < entityRelations.length; d++) { + entitiesInfo.push(entityRelationInfoToEntityInfo(entityRelations[d], direction)); + } } return entitiesInfo; } @@ -371,7 +375,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device function resolveAlias(entityAlias, stateParams) { var deferred = $q.defer(); var filter = entityAlias.filter; - resolveAliasFilter(filter, stateParams, -1).then( + resolveAliasFilter(filter, stateParams, -1, false).then( function (result) { var aliasInfo = { alias: entityAlias.alias, @@ -404,10 +408,13 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device entityId = stateParams.entityId; } } + if (!entityId) { + entityId = filter.defaultStateEntity; + } return entityId; } - function resolveAliasFilter(filter, stateParams, maxItems) { + function resolveAliasFilter(filter, stateParams, maxItems, failOnEmpty) { var deferred = $q.defer(); var result = { entities: [], @@ -421,7 +428,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device case types.aliasFilterType.entityList.value: getEntities(filter.entityType, filter.entityList).then( function success(entities) { - if (entities && entities.length) { + if (entities && entities.length || !failOnEmpty) { result.entities = entitiesToEntitiesInfo(entities); deferred.resolve(result); } else { @@ -436,7 +443,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device case types.aliasFilterType.entityName.value: getEntitiesByNameFilter(filter.entityType, filter.entityNameFilter, maxItems).then( function success(entities) { - if (entities && entities.length) { + if (entities && entities.length || !failOnEmpty) { result.entities = entitiesToEntitiesInfo(entities); deferred.resolve(result); } else { @@ -457,7 +464,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device deferred.resolve(result); }, function fail() { - deferred.reject(); + deferred.resolve(result); } ); } else { @@ -467,7 +474,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device case types.aliasFilterType.assetType.value: getEntitiesByNameFilter(types.entityType.asset, filter.assetNameFilter, maxItems, null, filter.assetType).then( function success(entities) { - if (entities && entities.length) { + if (entities && entities.length || !failOnEmpty) { result.entities = entitiesToEntitiesInfo(entities); deferred.resolve(result); } else { @@ -482,7 +489,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device case types.aliasFilterType.deviceType.value: getEntitiesByNameFilter(types.entityType.device, filter.deviceNameFilter, maxItems, null, filter.deviceType).then( function success(entities) { - if (entities && entities.length) { + if (entities && entities.length || !failOnEmpty) { result.entities = entitiesToEntitiesInfo(entities); deferred.resolve(result); } else { @@ -517,8 +524,8 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device searchQuery.parameters.maxLevel = filter.maxLevel && filter.maxLevel > 0 ? filter.maxLevel : -1; entityRelationService.findInfoByQuery(searchQuery).then( function success(allRelations) { - if (allRelations && allRelations.length) { - if (angular.isDefined(maxItems) && maxItems > 0) { + if (allRelations && allRelations.length || !failOnEmpty) { + if (angular.isDefined(maxItems) && maxItems > 0 && allRelations) { var limit = Math.min(allRelations.length, maxItems); allRelations.length = limit; } @@ -566,8 +573,8 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device } findByQueryPromise.then( function success(entities) { - if (entities && entities.length) { - if (angular.isDefined(maxItems) && maxItems > 0) { + if (entities && entities.length || !failOnEmpty) { + if (angular.isDefined(maxItems) && maxItems > 0 && entities) { var limit = Math.min(entities.length, maxItems); entities.length = limit; } @@ -720,7 +727,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device function checkEntityAlias(entityAlias) { var deferred = $q.defer(); - resolveAliasFilter(entityAlias.filter, null, 1).then( + resolveAliasFilter(entityAlias.filter, null, 1, true).then( function success(result) { if (result.stateEntity) { deferred.resolve(true); diff --git a/ui/src/app/api/subscription.js b/ui/src/app/api/subscription.js index 4a6f743877..fd26629502 100644 --- a/ui/src/app/api/subscription.js +++ b/ui/src/app/api/subscription.js @@ -737,7 +737,15 @@ export default class Subscription { this.ctx.datasourceService.subscribeToDatasource(listener); } - if (datasource.unresolvedStateEntity || !datasource.dataKeys.length) { + var forceUpdate = false; + if (datasource.unresolvedStateEntity || + !datasource.dataKeys.length || + (datasource.type === this.ctx.types.datasourceType.entity && !datasource.entityId) + ) { + forceUpdate = true; + } + + if (forceUpdate) { this.notifyDataLoaded(); this.onDataUpdated(); } @@ -767,7 +775,14 @@ export default class Subscription { this.ctx.alarmService.subscribeForAlarms(this.alarmSourceListener); - if (this.alarmSource.unresolvedStateEntity) { + var forceUpdate = false; + if (this.alarmSource.unresolvedStateEntity || + (this.alarmSource.type === this.ctx.types.datasourceType.entity && !this.alarmSource.entityId) + ) { + forceUpdate = true; + } + + if (forceUpdate) { this.notifyDataLoaded(); this.onDataUpdated(); } diff --git a/ui/src/app/dashboard/states/entity-state-controller.js b/ui/src/app/dashboard/states/entity-state-controller.js index f0512d71fc..1e2c2ade17 100644 --- a/ui/src/app/dashboard/states/entity-state-controller.js +++ b/ui/src/app/dashboard/states/entity-state-controller.js @@ -282,10 +282,30 @@ export default function EntityStateController($scope, $location, $state, $stateP function updateLocation() { if (vm.stateObject[vm.stateObject.length-1].id) { - $location.search({state : utils.objToBase64(vm.stateObject)}); + if (isDefaultState()) { + $location.search({state : null}); + } else { + $location.search({state : utils.objToBase64(vm.stateObject)}); + } } } + function isDefaultState() { + if (vm.stateObject.length == 1) { + var state = vm.stateObject[0]; + var rootStateId = dashboardUtils.getRootStateId(vm.states); + if (state.id == rootStateId && (!state.params || isEmpty(state.params))) { + return true; + } + } + return false; + } + function isEmpty(map) { + for(var key in map) { + return !map.hasOwnProperty(key); + } + return true; + } } diff --git a/ui/src/app/entity/alias/entity-alias-dialog.controller.js b/ui/src/app/entity/alias/entity-alias-dialog.controller.js index a5b221adf7..d1f353d632 100644 --- a/ui/src/app/entity/alias/entity-alias-dialog.controller.js +++ b/ui/src/app/entity/alias/entity-alias-dialog.controller.js @@ -71,7 +71,7 @@ export default function EntityAliasDialogController($scope, $mdDialog, $q, $filt entity: null, stateEntity: false } - entityService.resolveAliasFilter(vm.alias.filter, null, 1).then( + entityService.resolveAliasFilter(vm.alias.filter, null, 1, true).then( function success(result) { validationResult.stateEntity = result.stateEntity; var entities = result.entities; diff --git a/ui/src/app/entity/entity-autocomplete.directive.js b/ui/src/app/entity/entity-autocomplete.directive.js index 8f8153d67b..461042676f 100644 --- a/ui/src/app/entity/entity-autocomplete.directive.js +++ b/ui/src/app/entity/entity-autocomplete.directive.js @@ -95,12 +95,16 @@ export default function EntityAutocomplete($compile, $templateCache, $q, $filter } }); - scope.$watch('entity', function () { - scope.updateView(); + scope.$watch('entity', function (newVal, prevVal) { + if (!angular.equals(newVal, prevVal)) { + scope.updateView(); + } }); - scope.$watch('disabled', function () { - scope.updateView(); + scope.$watch('disabled', function (newVal, prevVal) { + if (!angular.equals(newVal, prevVal)) { + scope.updateView(); + } }); diff --git a/ui/src/app/entity/entity-filter.directive.js b/ui/src/app/entity/entity-filter.directive.js index db7a744a60..c68458d1e9 100644 --- a/ui/src/app/entity/entity-filter.directive.js +++ b/ui/src/app/entity/entity-filter.directive.js @@ -55,6 +55,7 @@ export default function EntityFilterDirective($compile, $templateCache, $q, $doc break; case types.aliasFilterType.stateEntity.value: filter.stateEntityParamName = null; + filter.defaultStateEntity = null; break; case types.aliasFilterType.assetType.value: filter.assetType = null; @@ -69,6 +70,7 @@ export default function EntityFilterDirective($compile, $templateCache, $q, $doc case types.aliasFilterType.deviceSearchQuery.value: filter.rootStateEntity = false; filter.stateEntityParamName = null; + filter.defaultStateEntity = null; filter.rootEntity = null; filter.direction = types.entitySearchDirection.from; filter.maxLevel = 1; diff --git a/ui/src/app/entity/entity-filter.tpl.html b/ui/src/app/entity/entity-filter.tpl.html index dae28172af..132a15eade 100644 --- a/ui/src/app/entity/entity-filter.tpl.html +++ b/ui/src/app/entity/entity-filter.tpl.html @@ -66,6 +66,14 @@ ng-model="filter.stateEntityParamName" aria-label="{{ 'alias.state-entity-parameter-name' | translate }}"> +
+ + + +
-
+
+ + + +
+
-
-
- - - -
- - - - +
+
+ + + + +
+ + +
@@ -148,27 +164,35 @@
-
+
+ + + +
+
-
-
- - - -
- - - - +
+
+ + + + +
+ + +
@@ -207,27 +231,35 @@
-
+
+ + + +
+
-
-
- - - -
- - - - +
+
+ + + + +
+ + +
diff --git a/ui/src/app/entity/entity-select.directive.js b/ui/src/app/entity/entity-select.directive.js index 705c6b8627..2778a79a17 100644 --- a/ui/src/app/entity/entity-select.directive.js +++ b/ui/src/app/entity/entity-select.directive.js @@ -48,6 +48,7 @@ export default function EntitySelect($compile, $templateCache) { } ngModelCtrl.$render = function () { + destroyWatchers(); if (ngModelCtrl.$viewValue) { var value = ngModelCtrl.$viewValue; scope.model.entityType = value.entityType; @@ -56,19 +57,43 @@ export default function EntitySelect($compile, $templateCache) { scope.model.entityType = null; scope.model.entityId = null; } + initWatchers(); } - scope.$watch('model.entityType', function () { - scope.updateView(); - }); + function initWatchers() { + scope.entityTypeDeregistration = scope.$watch('model.entityType', function (newVal, prevVal) { + if (!angular.equals(newVal, prevVal)) { + scope.updateView(); + } + }); + + scope.entityIdDeregistration = scope.$watch('model.entityId', function (newVal, prevVal) { + if (!angular.equals(newVal, prevVal)) { + scope.updateView(); + } + }); - scope.$watch('model.entityId', function () { - scope.updateView(); - }); + scope.disabledDeregistration = scope.$watch('disabled', function (newVal, prevVal) { + if (!angular.equals(newVal, prevVal)) { + scope.updateView(); + } + }); + } - scope.$watch('disabled', function () { - scope.updateView(); - }); + function destroyWatchers() { + if (scope.entityTypeDeregistration) { + scope.entityTypeDeregistration(); + scope.entityTypeDeregistration = null; + } + if (scope.entityIdDeregistration) { + scope.entityIdDeregistration(); + scope.entityIdDeregistration = null; + } + if (scope.disabledDeregistration) { + scope.disabledDeregistration(); + scope.disabledDeregistration = null; + } + } $compile(element.contents())(scope); } diff --git a/ui/src/app/locale/locale.constant.js b/ui/src/app/locale/locale.constant.js index 6513ce8821..f16fe9a850 100644 --- a/ui/src/app/locale/locale.constant.js +++ b/ui/src/app/locale/locale.constant.js @@ -188,6 +188,7 @@ export default angular.module('thingsboard.locale', []) "root-state-entity": "Use dashboard state entity as root", "root-entity": "Root entity", "state-entity-parameter-name": "State entity parameter name", + "default-state-entity": "Default state entity", "default-entity-parameter-name": "By default", "max-relation-level": "Max relation level", "unlimited-level": "Unlimited level", diff --git a/ui/src/app/widget/lib/alarms-table-widget.js b/ui/src/app/widget/lib/alarms-table-widget.js index 7618e6a829..a91c2a02af 100644 --- a/ui/src/app/widget/lib/alarms-table-widget.js +++ b/ui/src/app/widget/lib/alarms-table-widget.js @@ -69,6 +69,7 @@ function AlarmsTableWidgetController($element, $scope, $filter, $mdMedia, $mdDia vm.displayDetails = true; vm.allowAcknowledgment = true; vm.allowClear = true; + vm.actionCellDescriptors = []; vm.displayPagination = true; vm.defaultPageSize = 10; vm.defaultSortOrder = '-'+types.alarmFields.createdTime.value; @@ -94,6 +95,7 @@ function AlarmsTableWidgetController($element, $scope, $filter, $mdMedia, $mdDia vm.onReorder = onReorder; vm.onPaginate = onPaginate; vm.onRowClick = onRowClick; + vm.onActionButtonClick = onActionButtonClick; vm.isCurrent = isCurrent; vm.openAlarmDetails = openAlarmDetails; vm.ackAlarms = ackAlarms; @@ -157,6 +159,8 @@ function AlarmsTableWidgetController($element, $scope, $filter, $mdMedia, $mdDia vm.ctx.widgetActions = [ vm.searchAction ]; + vm.actionCellDescriptors = vm.ctx.actionsApi.getActionDescriptors('actionCellButton'); + if (vm.settings.alarmsTitle && vm.settings.alarmsTitle.length) { vm.alarmsTitle = utils.customTranslation(vm.settings.alarmsTitle, vm.settings.alarmsTitle); } else { @@ -280,9 +284,35 @@ function AlarmsTableWidgetController($element, $scope, $filter, $mdMedia, $mdDia } function onRowClick($event, alarm) { + if ($event) { + $event.stopPropagation(); + } if (vm.currentAlarm != alarm) { vm.currentAlarm = alarm; } + var descriptors = vm.ctx.actionsApi.getActionDescriptors('rowClick'); + if (descriptors.length) { + var entityId; + var entityName; + if (vm.currentAlarm && vm.currentAlarm.originator) { + entityId = vm.currentAlarm.originator; + entityName = vm.currentAlarm.originatorName; + } + vm.ctx.actionsApi.handleWidgetAction($event, descriptors[0], entityId, entityName); + } + } + + function onActionButtonClick($event, alarm, actionDescriptor) { + if ($event) { + $event.stopPropagation(); + } + var entityId; + var entityName; + if (alarm && alarm.originator) { + entityId = alarm.originator; + entityName = alarm.originatorName; + } + vm.ctx.actionsApi.handleWidgetAction($event, actionDescriptor, entityId, entityName); } function isCurrent(alarm) { diff --git a/ui/src/app/widget/lib/alarms-table-widget.tpl.html b/ui/src/app/widget/lib/alarms-table-widget.tpl.html index 942b2afb1d..b7416e95a0 100644 --- a/ui/src/app/widget/lib/alarms-table-widget.tpl.html +++ b/ui/src/app/widget/lib/alarms-table-widget.tpl.html @@ -64,6 +64,7 @@ {{ key.title }}   +   @@ -83,6 +84,19 @@ + + + {{actionDescriptor.icon}} + + {{ actionDescriptor.displayName }} + + + diff --git a/ui/src/app/widget/lib/entities-table-widget.js b/ui/src/app/widget/lib/entities-table-widget.js index f0b5835fbe..7d97fe4559 100644 --- a/ui/src/app/widget/lib/entities-table-widget.js +++ b/ui/src/app/widget/lib/entities-table-widget.js @@ -107,6 +107,7 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra vm.datasources = vm.subscription.datasources; initializeConfig(); updateDatasources(); + updateEntities(); } }); @@ -276,16 +277,16 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra } if (vm.currentEntity != entity) { vm.currentEntity = entity; - var descriptors = vm.ctx.actionsApi.getActionDescriptors('rowClick'); - if (descriptors.length) { - var entityId; - var entityName; - if (vm.currentEntity) { - entityId = vm.currentEntity.id; - entityName = vm.currentEntity.entityName; - } - vm.ctx.actionsApi.handleWidgetAction($event, descriptors[0], entityId, entityName); + } + var descriptors = vm.ctx.actionsApi.getActionDescriptors('rowClick'); + if (descriptors.length) { + var entityId; + var entityName; + if (vm.currentEntity) { + entityId = vm.currentEntity.id; + entityName = vm.currentEntity.entityName; } + vm.ctx.actionsApi.handleWidgetAction($event, descriptors[0], entityId, entityName); } }