Browse Source

TB-70: Introduces default entity for alias state parameter. Add actions support for alarms table widget.

pull/224/head
Igor Kulikov 9 years ago
parent
commit
b1a1c0bdf9
  1. 2
      application/src/main/data/json/system/widget_bundles/alarm_widgets.json
  2. 39
      ui/src/app/api/entity.service.js
  3. 19
      ui/src/app/api/subscription.js
  4. 22
      ui/src/app/dashboard/states/entity-state-controller.js
  5. 2
      ui/src/app/entity/alias/entity-alias-dialog.controller.js
  6. 12
      ui/src/app/entity/entity-autocomplete.directive.js
  7. 2
      ui/src/app/entity/entity-filter.directive.js
  8. 122
      ui/src/app/entity/entity-filter.tpl.html
  9. 43
      ui/src/app/entity/entity-select.directive.js
  10. 1
      ui/src/app/locale/locale.constant.js
  11. 30
      ui/src/app/widget/lib/alarms-table-widget.js
  12. 14
      ui/src/app/widget/lib/alarms-table-widget.tpl.html
  13. 19
      ui/src/app/widget/lib/entities-table-widget.js

2
application/src/main/data/json/system/widget_bundles/alarm_widgets.json

@ -15,7 +15,7 @@
"resources": [],
"templateHtml": "<tb-alarms-table-widget \n table-id=\"tableId\"\n ctx=\"ctx\">\n</tb-alarms-table-widget>",
"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}"

39
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);

19
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();
}

22
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;
}
}

2
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;

12
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();
}
});

2
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;

122
ui/src/app/entity/entity-filter.tpl.html

@ -66,6 +66,14 @@
ng-model="filter.stateEntityParamName"
aria-label="{{ 'alias.state-entity-parameter-name' | translate }}">
</md-input-container>
<div layout="column">
<label class="tb-small">{{ 'alias.default-state-entity' | translate }}</label>
<tb-entity-select flex
the-form="theForm"
tb-required="false"
ng-model="filter.defaultStateEntity">
</tb-entity-select>
</div>
</section>
<section layout="column" ng-if="filter.type == types.aliasFilterType.assetType.value" id="assetTypeFilter">
<tb-entity-subtype-autocomplete
@ -97,27 +105,35 @@
</section>
<section layout="column" ng-if="filter.type == types.aliasFilterType.relationsQuery.value" id="relationsQueryFilter">
<label class="tb-small">{{ 'alias.root-entity' | translate }}</label>
<div flex layout="row">
<section class="tb-root-state-entity-switch" layout="row" layout-align="start center" style="padding-left: 0px;">
<md-switch class="root-state-entity-switch" ng-model="filter.rootStateEntity"
aria-label="{{ 'alias.root-state-entity' | translate }}">
</md-switch>
<label class="tb-small root-state-entity-label" translate>alias.root-state-entity</label>
</section>
<div flex layout="row" ng-if="!filter.rootStateEntity">
<tb-entity-select flex
the-form="theForm"
tb-required="!filter.rootStateEntity"
ng-disabled="filter.rootStateEntity"
ng-model="filter.rootEntity">
</tb-entity-select>
<div layout="column">
<section class="tb-root-state-entity-switch" layout="column" layout-align="start center">
<label class="tb-small root-state-entity-label" translate>alias.root-state-entity</label>
<md-switch class="root-state-entity-switch" ng-model="filter.rootStateEntity"
aria-label="{{ 'alias.root-state-entity' | translate }}">
</md-switch>
</section>
<md-input-container ng-if="filter.rootStateEntity" class="md-block">
<label translate>alias.state-entity-parameter-name</label>
<input name="stateEntityParamName"
placeholder="{{ 'alias.default-entity-parameter-name' | translate }}"
ng-model="filter.stateEntityParamName"
aria-label="{{ 'alias.state-entity-parameter-name' | translate }}">
</md-input-container>
</div>
<div flex layout="row" ng-if="filter.rootStateEntity">
<md-input-container class="md-block" style="margin-top: 32px;">
<label translate>alias.state-entity-parameter-name</label>
<input name="stateEntityParamName"
placeholder="{{ 'alias.default-entity-parameter-name' | translate }}"
ng-model="filter.stateEntityParamName"
aria-label="{{ 'alias.state-entity-parameter-name' | translate }}">
</md-input-container>
<div flex layout="column">
<label class="tb-small">{{ 'alias.default-state-entity' | translate }}</label>
<tb-entity-select flex
the-form="theForm"
tb-required="false"
ng-model="filter.defaultStateEntity">
</tb-entity-select>
</div>
</div>
<div flex layout="row">
@ -148,27 +164,35 @@
</section>
<section layout="column" ng-if="filter.type == types.aliasFilterType.assetSearchQuery.value" id="assetSearchQueryFilter">
<label class="tb-small">{{ 'alias.root-entity' | translate }}</label>
<div flex layout="row">
<section class="tb-root-state-entity-switch" layout="row" layout-align="start center" style="padding-left: 0px;">
<md-switch class="root-state-entity-switch" ng-model="filter.rootStateEntity"
aria-label="{{ 'alias.root-state-entity' | translate }}">
</md-switch>
<label class="tb-small root-state-entity-label" translate>alias.root-state-entity</label>
</section>
<div flex layout="row" ng-if="!filter.rootStateEntity">
<tb-entity-select flex
the-form="theForm"
tb-required="!filter.rootStateEntity"
ng-disabled="filter.rootStateEntity"
ng-model="filter.rootEntity">
</tb-entity-select>
<div layout="column">
<section class="tb-root-state-entity-switch" layout="column" layout-align="start center">
<label class="tb-small root-state-entity-label" translate>alias.root-state-entity</label>
<md-switch class="root-state-entity-switch" ng-model="filter.rootStateEntity"
aria-label="{{ 'alias.root-state-entity' | translate }}">
</md-switch>
</section>
<md-input-container ng-if="filter.rootStateEntity" class="md-block">
<label translate>alias.state-entity-parameter-name</label>
<input name="stateEntityParamName"
placeholder="{{ 'alias.default-entity-parameter-name' | translate }}"
ng-model="filter.stateEntityParamName"
aria-label="{{ 'alias.state-entity-parameter-name' | translate }}">
</md-input-container>
</div>
<div flex layout="row" ng-if="filter.rootStateEntity">
<md-input-container class="md-block" style="margin-top: 32px;">
<label translate>alias.state-entity-parameter-name</label>
<input name="stateEntityParamName"
placeholder="{{ 'alias.default-entity-parameter-name' | translate }}"
ng-model="filter.stateEntityParamName"
aria-label="{{ 'alias.state-entity-parameter-name' | translate }}">
</md-input-container>
<div flex layout="column">
<label class="tb-small">{{ 'alias.default-state-entity' | translate }}</label>
<tb-entity-select flex
the-form="theForm"
tb-required="false"
ng-model="filter.defaultStateEntity">
</tb-entity-select>
</div>
</div>
<div flex layout="row">
@ -207,27 +231,35 @@
</section>
<section layout="column" ng-if="filter.type == types.aliasFilterType.deviceSearchQuery.value" id="deviceSearchQueryFilter">
<label class="tb-small">{{ 'alias.root-entity' | translate }}</label>
<div flex layout="row">
<section class="tb-root-state-entity-switch" layout="row" layout-align="start center" style="padding-left: 0px;">
<md-switch class="root-state-entity-switch" ng-model="filter.rootStateEntity"
aria-label="{{ 'alias.root-state-entity' | translate }}">
</md-switch>
<label class="tb-small root-state-entity-label" translate>alias.root-state-entity</label>
</section>
<div flex layout="row" ng-if="!filter.rootStateEntity">
<tb-entity-select flex
the-form="theForm"
tb-required="!filter.rootStateEntity"
ng-disabled="filter.rootStateEntity"
ng-model="filter.rootEntity">
</tb-entity-select>
<div layout="column">
<section class="tb-root-state-entity-switch" layout="column" layout-align="start center">
<label class="tb-small root-state-entity-label" translate>alias.root-state-entity</label>
<md-switch class="root-state-entity-switch" ng-model="filter.rootStateEntity"
aria-label="{{ 'alias.root-state-entity' | translate }}">
</md-switch>
</section>
<md-input-container ng-if="filter.rootStateEntity" class="md-block">
<label translate>alias.state-entity-parameter-name</label>
<input name="stateEntityParamName"
placeholder="{{ 'alias.default-entity-parameter-name' | translate }}"
ng-model="filter.stateEntityParamName"
aria-label="{{ 'alias.state-entity-parameter-name' | translate }}">
</md-input-container>
</div>
<div flex layout="row" ng-if="filter.rootStateEntity">
<md-input-container class="md-block" style="margin-top: 32px;">
<label translate>alias.state-entity-parameter-name</label>
<input name="stateEntityParamName"
placeholder="{{ 'alias.default-entity-parameter-name' | translate }}"
ng-model="filter.stateEntityParamName"
aria-label="{{ 'alias.state-entity-parameter-name' | translate }}">
</md-input-container>
<div flex layout="column">
<label class="tb-small">{{ 'alias.default-state-entity' | translate }}</label>
<tb-entity-select flex
the-form="theForm"
tb-required="false"
ng-model="filter.defaultStateEntity">
</tb-entity-select>
</div>
</div>
<div flex layout="row">

43
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);
}

1
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",

30
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) {

14
ui/src/app/widget/lib/alarms-table-widget.tpl.html

@ -64,6 +64,7 @@
<tr md-row>
<th md-column md-order-by="{{ key.name }}" ng-repeat="key in vm.alarmSource.dataKeys"><span>{{ key.title }}</span></th>
<th md-column ng-if="vm.displayDetails"><span>&nbsp</span></th>
<th md-column ng-if="vm.actionCellDescriptors.length"><span>&nbsp</span></th>
</tr>
</thead>
<tbody md-body>
@ -83,6 +84,19 @@
</md-tooltip>
</md-button>
</td>
<td md-cell ng-if="vm.actionCellDescriptors.length" class="tb-action-cell"
ng-style="{minWidth: vm.actionCellDescriptors.length*36+'px',
maxWidth: vm.actionCellDescriptors.length*36+'px',
width: vm.actionCellDescriptors.length*36+'px'}">
<md-button class="md-icon-button" ng-repeat="actionDescriptor in vm.actionCellDescriptors"
aria-label="{{ actionDescriptor.displayName }}"
ng-click="vm.onActionButtonClick($event, alarm, actionDescriptor)">
<md-icon aria-label="{{ actionDescriptor.displayName }}" class="material-icons">{{actionDescriptor.icon}}</md-icon>
<md-tooltip md-direction="top">
{{ actionDescriptor.displayName }}
</md-tooltip>
</md-button>
</td>
</tr>
</tbody>
</table>

19
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);
}
}

Loading…
Cancel
Save