thingsboard-memoizeit
Changes
ui/src/app/api/alias-controller.js 3(+1 -2)
ui/src/app/api/entity.service.js 245(+159 -86)
ui/src/app/api/subscription.js 6(+3 -3)
ui/src/app/common/types.constant.js 51(+51 -0)
ui/src/app/common/utils.service.js 26(+1 -25)
ui/src/app/entity/entity-alias-dialog.scss 27(+27 -0)
ui/src/app/entity/entity-alias-dialog.tpl.html 77(+25 -52)
ui/src/app/entity/entity-aliases.controller.js 133(+72 -61)
ui/src/app/entity/entity-aliases.scss 12(+12 -0)
ui/src/app/entity/entity-aliases.tpl.html 98(+52 -46)
ui/src/app/entity/entity-filter.directive.js 100(+45 -55)
ui/src/app/entity/entity-filter.scss 19(+2 -17)
ui/src/app/entity/entity-filter.tpl.html 104(+72 -32)
ui/src/app/entity/entity-filter-view.directive.js 106(+106 -0)
ui/src/app/entity/entity-filter-view.scss 33(+33 -0)
ui/src/app/entity/index.js 4(+4 -0)
ui/src/app/locale/locale.constant.js 55(+41 -14)
Details
ui/src/app/api/alias-controller.js 3(+1 -2)
diff --git a/ui/src/app/api/alias-controller.js b/ui/src/app/api/alias-controller.js
index b6d29a9..60e8a31 100644
--- a/ui/src/app/api/alias-controller.js
+++ b/ui/src/app/api/alias-controller.js
@@ -95,8 +95,7 @@ export default class AliasController {
this.entityService.resolveAlias(entityAlias, this.stateController.getStateParams()).then(
function success(aliasInfo) {
aliasCtrl.resolvedAliases[aliasId] = aliasInfo;
- if (entityAlias.filter.stateEntity) {
- aliasInfo.stateEntity = true;
+ if (aliasInfo.stateEntity) {
aliasCtrl.resolvedAliasesToStateEntities[aliasId] =
aliasCtrl.stateController.getStateParams().entityId;
}
ui/src/app/api/entity.service.js 245(+159 -86)
diff --git a/ui/src/app/api/entity.service.js b/ui/src/app/api/entity.service.js
index 91c8df3..e647d9c 100644
--- a/ui/src/app/api/entity.service.js
+++ b/ui/src/app/api/entity.service.js
@@ -31,6 +31,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
resolveAliasFilter: resolveAliasFilter,
checkEntityAlias: checkEntityAlias,
filterAliasByEntityTypes: filterAliasByEntityTypes,
+ getAliasFilterTypesByEntityTypes: getAliasFilterTypesByEntityTypes,
getEntityKeys: getEntityKeys,
createDatasourcesFromSubscriptionsInfo: createDatasourcesFromSubscriptionsInfo,
getRelatedEntities: getRelatedEntities,
@@ -223,17 +224,21 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
return promise;
}
- function getEntitiesByNameFilter(entityType, entityNameFilter, limit, config, subType) {
- var deferred = $q.defer();
- var pageLink = {limit: limit, textSearch: entityNameFilter};
+ function getEntitiesByPageLink(entityType, pageLink, config, subType, data, deferred) {
var promise = getEntitiesByPageLinkPromise(entityType, pageLink, config, subType);
if (promise) {
promise.then(
function success(result) {
- if (result.data && result.data.length > 0) {
- deferred.resolve(result.data);
+ data = data.concat(result.data);
+ if (result.hasNext) {
+ pageLink = result.nextPageLink;
+ getEntitiesByPageLink(entityType, pageLink, config, subType, data, deferred);
} else {
- deferred.resolve(null);
+ if (data && data.length > 0) {
+ deferred.resolve(data);
+ } else {
+ deferred.resolve(null);
+ }
}
},
function fail() {
@@ -243,6 +248,34 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
} else {
deferred.resolve(null);
}
+ }
+
+ function getEntitiesByNameFilter(entityType, entityNameFilter, limit, config, subType) {
+ var deferred = $q.defer();
+ var pageLink = {limit: limit, textSearch: entityNameFilter};
+ if (limit == -1) { // all
+ var data = [];
+ pageLink.limit = 100;
+ getEntitiesByPageLink(entityType, pageLink, config, subType, data, deferred);
+ } else {
+ var promise = getEntitiesByPageLinkPromise(entityType, pageLink, config, subType);
+ if (promise) {
+ promise.then(
+ function success(result) {
+ if (result.data && result.data.length > 0) {
+ deferred.resolve(result.data);
+ } else {
+ deferred.resolve(null);
+ }
+ },
+ function fail() {
+ deferred.resolve(null);
+ }
+ );
+ } else {
+ deferred.resolve(null);
+ }
+ }
return deferred.promise;
}
@@ -261,11 +294,12 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
function resolveAlias(entityAlias, stateParams) {
var deferred = $q.defer();
var filter = entityAlias.filter;
- resolveAliasFilter(filter, stateParams, 100).then(
+ resolveAliasFilter(filter, stateParams, -1).then(
function (result) {
var entities = result.entities;
var aliasInfo = {
alias: entityAlias.alias,
+ stateEntity: result.stateEntity,
resolveMultiple: filter.resolveMultiple
};
var resolvedEntities = entitiesToEntitiesInfo(entities);
@@ -291,39 +325,68 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
};
switch (filter.type) {
case types.aliasFilterType.entityList.value:
- if (filter.stateEntity) {
- result.stateEntity = true;
- if (stateParams && stateParams.entityId) {
- getEntity(stateParams.entityId.entityType, stateParams.entityId.id).then(
- function success(entity) {
- result.entities = [entity];
- deferred.resolve(result);
- },
- function fail() {
- deferred.reject();
- }
- );
- } else {
- deferred.resolve(result);
+ getEntities(filter.entityType, filter.entityList).then(
+ function success(entities) {
+ if (entities && entities.length) {
+ result.entities = entities;
+ deferred.resolve(result);
+ } else {
+ deferred.reject();
+ }
+ },
+ function fail() {
+ deferred.reject();
}
- } else {
- getEntities(filter.entityType, filter.entityList).then(
- function success(entities) {
- if (entities && entities.length) {
- result.entities = entities;
- deferred.resolve(result);
- } else {
- deferred.reject();
- }
+ );
+ break;
+ case types.aliasFilterType.entityName.value:
+ getEntitiesByNameFilter(filter.entityType, filter.entityNameFilter, maxItems).then(
+ function success(entities) {
+ if (entities && entities.length) {
+ result.entities = entities;
+ deferred.resolve(result);
+ } else {
+ deferred.reject();
+ }
+ },
+ function fail() {
+ deferred.reject();
+ }
+ );
+ break;
+ case types.aliasFilterType.stateEntity.value:
+ result.stateEntity = true;
+ if (stateParams && stateParams.entityId) {
+ getEntity(stateParams.entityId.entityType, stateParams.entityId.id).then(
+ function success(entity) {
+ result.entities = [entity];
+ deferred.resolve(result);
},
function fail() {
deferred.reject();
}
);
+ } else {
+ deferred.resolve(result);
}
break;
- case types.aliasFilterType.entityName.value:
- getEntitiesByNameFilter(filter.entityType, filter.entityNameFilter, maxItems).then(
+ case types.aliasFilterType.assetType.value:
+ getEntitiesByNameFilter(types.entityType.asset, filter.assetNameFilter, maxItems, null, filter.assetType).then(
+ function success(entities) {
+ if (entities && entities.length) {
+ result.entities = entities;
+ deferred.resolve(result);
+ } else {
+ deferred.reject();
+ }
+ },
+ function fail() {
+ deferred.reject();
+ }
+ );
+ break;
+ case types.aliasFilterType.deviceType.value:
+ getEntitiesByNameFilter(types.entityType.device, filter.deviceNameFilter, maxItems, null, filter.deviceType).then(
function success(entities) {
if (entities && entities.length) {
result.entities = entities;
@@ -337,27 +400,81 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
}
);
break;
- //TODO:
+
+ //TODO: Alias filter
}
return deferred.promise;
}
function filterAliasByEntityTypes(entityAlias, entityTypes) {
var filter = entityAlias.filter;
- switch (filter.type) {
- case types.aliasFilterType.entityList.value:
- if (filter.stateEntity) {
- return true;
- } else {
+ if (filterAliasFilterTypeByEntityTypes(filter.type, entityTypes)) {
+ switch (filter.type) {
+ case types.aliasFilterType.entityList.value:
return entityTypes.indexOf(filter.entityType) > -1 ? true : false;
- }
+ case types.aliasFilterType.entityName.value:
+ return entityTypes.indexOf(filter.entityType) > -1 ? true : false;
+ case types.aliasFilterType.stateEntity.value:
+ return true;
+ case types.aliasFilterType.assetType.value:
+ return entityTypes.indexOf(types.entityType.asset) > -1 ? true : false;
+ case types.aliasFilterType.deviceType.value:
+ return entityTypes.indexOf(types.entityType.device) > -1 ? true : false;
+ }
+ }
+ //TODO: Alias filter
+ return false;
+ }
+
+ function filterAliasFilterTypeByEntityType(aliasFilterType, entityType) {
+ switch (aliasFilterType) {
+ case types.aliasFilterType.entityList.value:
+ return true;
case types.aliasFilterType.entityName.value:
- return entityTypes.indexOf(filter.entityType) > -1 ? true : false;
+ return true;
+ case types.aliasFilterType.stateEntity.value:
+ return true;
+ case types.aliasFilterType.assetType.value:
+ return entityType === types.entityType.asset;
+ case types.aliasFilterType.deviceType.value:
+ return entityType === types.entityType.device;
+ case types.aliasFilterType.relationsQuery.value:
+ return true;
+ case types.aliasFilterType.assetSearchQuery.value:
+ return entityType === types.entityType.asset;
+ case types.aliasFilterType.deviceSearchQuery.value:
+ return entityType === types.entityType.device;
}
- //TODO:
return false;
}
+ function filterAliasFilterTypeByEntityTypes(aliasFilterType, entityTypes) {
+ if (!entityTypes || !entityTypes.length) {
+ return true;
+ }
+ var valid = false;
+ entityTypes.forEach(function(entityType) {
+ valid = valid || filterAliasFilterTypeByEntityType(aliasFilterType, entityType);
+ });
+ return valid;
+ }
+
+ function getAliasFilterTypesByEntityTypes(entityTypes) {
+ var allAliasFilterTypes = types.aliasFilterType;
+ if (!entityTypes || !entityTypes.length) {
+ return allAliasFilterTypes;
+ }
+ var result = {};
+ for (var type in allAliasFilterTypes) {
+ var aliasFilterType = allAliasFilterTypes[type];
+ if (filterAliasFilterTypeByEntityTypes(aliasFilterType.value, entityTypes)) {
+ result[type] = aliasFilterType;
+ }
+ }
+ return result;
+ }
+
+
function checkEntityAlias(entityAlias) {
var deferred = $q.defer();
resolveAliasFilter(entityAlias.filter, null, 1).then(
@@ -380,50 +497,6 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
return deferred.promise;
}
- /*function processEntityAlias(index, aliasIds, entityAliases, stateParams, resolution, deferred) {
- if (index < aliasIds.length) {
- var aliasId = aliasIds[index];
- var entityAlias = entityAliases[aliasId];
- var alias = entityAlias.alias;
- var filter = entityAlias.filter;
- resolveAliasFilter(filter, stateParams).then(
- function (entities) {
- if (entities && entities.length) {
- var entity = entities[0];
- var resolvedAlias = {alias: alias, entityType: entity.id.entityType, entityId: entity.id.id};
- resolution.aliasesInfo.entityAliases[aliasId] = resolvedAlias;
- resolution.aliasesInfo.entityAliasesInfo[aliasId] = entitiesToEntitiesInfo(entities);
- index++;
- processEntityAlias(index, aliasIds, entityAliases, stateParams, resolution, deferred);
- } else {
- if (!resolution.error) {
- resolution.error = 'dashboard.invalid-aliases-config';
- }
- index++;
- processEntityAlias(index, aliasIds, entityAliases, stateParams, resolution, deferred);
- }
- }
- );
- } else {
- deferred.resolve(resolution);
- }
- }*/
-
- /*function processEntityAliases(entityAliases, stateParams) {
- var deferred = $q.defer();
- var resolution = {
- aliasesInfo: {}
- };
- var aliasIds = [];
- if (entityAliases) {
- for (var aliasId in entityAliases) {
- aliasIds.push(aliasId);
- }
- }
- processEntityAlias(0, aliasIds, entityAliases, stateParams, resolution, deferred);
- return deferred.promise;
- }*/
-
function getEntityKeys(entityType, entityId, query, type) {
var deferred = $q.defer();
var url = '/api/plugins/telemetry/' + entityType + '/' + entityId + '/keys/';
@@ -889,4 +962,4 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
}
}
-}
\ No newline at end of file
+}
ui/src/app/api/subscription.js 6(+3 -3)
diff --git a/ui/src/app/api/subscription.js b/ui/src/app/api/subscription.js
index 4cb382c..1d4eb30 100644
--- a/ui/src/app/api/subscription.js
+++ b/ui/src/app/api/subscription.js
@@ -258,17 +258,17 @@ export default class Subscription {
} else {
subscription.rpcEnabled = subscription.ctx.$scope.widgetEditMode ? true : false;
}
- subscription.callbacks.rpcStateChanged(this);
+ subscription.callbacks.rpcStateChanged(subscription);
deferred.resolve();
} else {
subscription.rpcEnabled = false;
- subscription.callbacks.rpcStateChanged(this);
+ subscription.callbacks.rpcStateChanged(subscription);
deferred.resolve();
}
},
function fail () {
subscription.rpcEnabled = false;
- subscription.callbacks.rpcStateChanged(this);
+ subscription.callbacks.rpcStateChanged(subscription);
deferred.resolve();
}
);
diff --git a/ui/src/app/common/dashboard-utils.service.js b/ui/src/app/common/dashboard-utils.service.js
index fe8aa93..915d550 100644
--- a/ui/src/app/common/dashboard-utils.service.js
+++ b/ui/src/app/common/dashboard-utils.service.js
@@ -110,14 +110,12 @@ function DashboardUtils(types, utils, timeService) {
deviceAlias.deviceFilter.useFilter ? types.aliasFilterType.entityName.value : types.aliasFilterType.entityList.value;
if (entityAlias.filter.type == types.aliasFilterType.entityList.value) {
entityAlias.filter.entityList = deviceAlias.deviceFilter.deviceList;
- entityAlias.filter.stateEntity = false;
} else {
entityAlias.filter.entityNameFilter = deviceAlias.deviceFilter.deviceNameFilter;
}
} else {
entityAlias.filter.type = types.aliasFilterType.entityList.value;
entityAlias.filter.entityList = [deviceAlias.deviceId];
- entityAlias.filter.stateEntity = false;
}
return entityAlias;
}
@@ -132,7 +130,6 @@ function DashboardUtils(types, utils, timeService) {
}
if (entityAlias.filter.type == types.aliasFilterType.entityList.value) {
entityAlias.filter.entityList = entityAlias.entityFilter.entityList;
- entityAlias.filter.stateEntity = false;
} else {
entityAlias.filter.entityNameFilter = entityAlias.entityFilter.entityNameFilter;
}
@@ -342,7 +339,6 @@ function DashboardUtils(types, utils, timeService) {
function createSingleEntityFilter(entityType, entityId) {
return {
type: types.aliasFilterType.entityList.value,
- stateEntity: false,
entityList: [entityId],
entityType: entityType,
resolveMultiple: false
ui/src/app/common/types.constant.js 51(+51 -0)
diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js
index 40b6639..522abff 100644
--- a/ui/src/app/common/types.constant.js
+++ b/ui/src/app/common/types.constant.js
@@ -74,6 +74,10 @@ export default angular.module('thingsboard.types', [])
value: 'entityName',
name: 'alias.filter-type-entity-name'
},
+ stateEntity: {
+ value: 'stateEntity',
+ name: 'alias.filter-type-state-entity'
+ },
assetType: {
value: 'assetType',
name: 'alias.filter-type-asset-type'
@@ -139,6 +143,53 @@ export default angular.module('thingsboard.types', [])
dashboard: "DASHBOARD",
alarm: "ALARM"
},
+ entityTypeTranslations: {
+ "DEVICE": {
+ type: 'entity.type-device',
+ list: 'entity.list-of-devices',
+ nameStartsWith: 'entity.device-name-starts-with'
+ },
+ "ASSET": {
+ type: 'entity.type-asset',
+ list: 'entity.list-of-assets',
+ nameStartsWith: 'entity.asset-name-starts-with'
+ },
+ "RULE": {
+ type: 'entity.type-rule',
+ list: 'entity.list-of-rules',
+ nameStartsWith: 'entity.rule-name-starts-with'
+ },
+ "PLUGIN": {
+ type: 'entity.type-plugin',
+ list: 'entity.list-of-plugins',
+ nameStartsWith: 'entity.plugin-name-starts-with'
+ },
+ "TENANT": {
+ type: 'entity.type-tenant',
+ list: 'entity.list-of-tenants',
+ nameStartsWith: 'entity.tenant-name-starts-with'
+ },
+ "CUSTOMER": {
+ type: 'entity.type-customer',
+ list: 'entity.list-of-customers',
+ nameStartsWith: 'entity.customer-name-starts-with'
+ },
+ "USER": {
+ type: 'entity.type-user',
+ list: 'entity.list-of-users',
+ nameStartsWith: 'entity.user-name-starts-with'
+ },
+ "DASHBOARD": {
+ type: 'entity.type-dashboard',
+ list: 'entity.list-of-dashboards',
+ nameStartsWith: 'entity.dashboard-name-starts-with'
+ },
+ "ALARM": {
+ type: 'entity.type-alarm',
+ list: 'entity.list-of-alarms',
+ nameStartsWith: 'entity.alarm-name-starts-with'
+ }
+ },
entitySearchDirection: {
from: "FROM",
to: "TO"
ui/src/app/common/utils.service.js 26(+1 -25)
diff --git a/ui/src/app/common/utils.service.js b/ui/src/app/common/utils.service.js
index 8bf76c4..8d2e565 100644
--- a/ui/src/app/common/utils.service.js
+++ b/ui/src/app/common/utils.service.js
@@ -109,8 +109,7 @@ function Utils($mdColorPalette, $rootScope, $window, types) {
cleanCopy: cleanCopy,
isLocalUrl: isLocalUrl,
validateDatasources: validateDatasources,
- createKey: createKey,
- entityTypeName: entityTypeName
+ createKey: createKey
}
return service;
@@ -358,27 +357,4 @@ function Utils($mdColorPalette, $rootScope, $window, types) {
return dataKey;
}
- function entityTypeName (type) {
- switch (type) {
- case types.entityType.device:
- return 'entity.type-device';
- case types.entityType.asset:
- return 'entity.type-asset';
- case types.entityType.rule:
- return 'entity.type-rule';
- case types.entityType.plugin:
- return 'entity.type-plugin';
- case types.entityType.tenant:
- return 'entity.type-tenant';
- case types.entityType.customer:
- return 'entity.type-customer';
- case types.entityType.user:
- return 'entity.type-user';
- case types.entityType.dashboard:
- return 'entity.type-dashboard';
- case types.entityType.alarm:
- return 'entity.type-alarm';
- }
- }
-
}
diff --git a/ui/src/app/dashboard/add-widget.controller.js b/ui/src/app/dashboard/add-widget.controller.js
index 586fb46..a9a68c7 100644
--- a/ui/src/app/dashboard/add-widget.controller.js
+++ b/ui/src/app/dashboard/add-widget.controller.js
@@ -15,7 +15,7 @@
*/
/* eslint-disable import/no-unresolved, import/default */
-import entityAliasesTemplate from '../entity/entity-aliases.tpl.html';
+import entityAliasDialogTemplate from '../entity/entity-alias-dialog.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
@@ -130,17 +130,14 @@ export default function AddWidgetController($scope, widgetService, entityService
var singleEntityAlias = {id: null, alias: alias, filter: {}};
$mdDialog.show({
- controller: 'EntityAliasesController',
+ controller: 'EntityAliasDialogController',
controllerAs: 'vm',
- templateUrl: entityAliasesTemplate,
+ templateUrl: entityAliasDialogTemplate,
locals: {
- config: {
- entityAliases: angular.copy(vm.dashboard.configuration.entityAliases),
- widgets: null,
- isSingleEntityAlias: true,
- singleEntityAlias: singleEntityAlias,
- allowedEntityTypes: allowedEntityTypes
- }
+ isAdd: true,
+ allowedEntityTypes: allowedEntityTypes,
+ entityAliases: vm.dashboard.configuration.entityAliases,
+ alias: singleEntityAlias
},
parent: angular.element($document[0].body),
fullscreen: true,
diff --git a/ui/src/app/dashboard/edit-widget.directive.js b/ui/src/app/dashboard/edit-widget.directive.js
index 4bd4e3d..5b788cc 100644
--- a/ui/src/app/dashboard/edit-widget.directive.js
+++ b/ui/src/app/dashboard/edit-widget.directive.js
@@ -15,7 +15,7 @@
*/
/* eslint-disable import/no-unresolved, import/default */
-import entityAliasesTemplate from '../entity/entity-aliases.tpl.html';
+import entityAliasDialogTemplate from '../entity/entity-alias-dialog.tpl.html';
import editWidgetTemplate from './edit-widget.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
@@ -98,17 +98,14 @@ export default function EditWidgetDirective($compile, $templateCache, types, wid
var singleEntityAlias = {id: null, alias: alias, filter: {}};
$mdDialog.show({
- controller: 'EntityAliasesController',
+ controller: 'EntityAliasDialogController',
controllerAs: 'vm',
- templateUrl: entityAliasesTemplate,
+ templateUrl: entityAliasDialogTemplate,
locals: {
- config: {
- entityAliases: angular.copy(scope.dashboard.configuration.entityAliases),
- widgets: null,
- isSingleEntityAlias: true,
- singleEntityAlias: singleEntityAlias,
- allowedEntityTypes: allowedEntityTypes
- }
+ isAdd: true,
+ allowedEntityTypes: allowedEntityTypes,
+ entityAliases: scope.dashboard.configuration.entityAliases,
+ alias: singleEntityAlias
},
parent: angular.element($document[0].body),
fullscreen: true,
ui/src/app/entity/entity-alias-dialog.scss 27(+27 -0)
diff --git a/ui/src/app/entity/entity-alias-dialog.scss b/ui/src/app/entity/entity-alias-dialog.scss
new file mode 100644
index 0000000..96df6fd
--- /dev/null
+++ b/ui/src/app/entity/entity-alias-dialog.scss
@@ -0,0 +1,27 @@
+/**
+ * Copyright © 2016-2017 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.
+ */
+
+.tb-entity-alias-dialog {
+ .tb-resolve-multiple-switch {
+ padding-left: 10px;
+ .resolve-multiple-switch {
+ margin: 0;
+ }
+ .resolve-multiple-label {
+ margin: 5px 0;
+ }
+ }
+}
\ No newline at end of file
ui/src/app/entity/entity-aliases.controller.js 133(+72 -61)
diff --git a/ui/src/app/entity/entity-aliases.controller.js b/ui/src/app/entity/entity-aliases.controller.js
index 50bbfd9..b72b9ec 100644
--- a/ui/src/app/entity/entity-aliases.controller.js
+++ b/ui/src/app/entity/entity-aliases.controller.js
@@ -15,22 +15,27 @@
*/
import './entity-aliases.scss';
+/* eslint-disable import/no-unresolved, import/default */
+
+import entityAliasDialogTemplate from './entity-alias-dialog.tpl.html';
+
+/* eslint-enable import/no-unresolved, import/default */
+
/*@ngInject*/
export default function EntityAliasesController(utils, entityService, toast, $scope, $mdDialog, $document, $q, $translate,
types, config) {
var vm = this;
- vm.isSingleEntityAlias = config.isSingleEntityAlias;
- vm.singleEntityAlias = config.singleEntityAlias;
+ vm.types = types;
vm.entityAliases = [];
vm.title = config.customTitle ? config.customTitle : 'entity.aliases';
vm.disableAdd = config.disableAdd;
vm.aliasToWidgetsMap = {};
vm.allowedEntityTypes = config.allowedEntityTypes;
- vm.onFilterEntityChanged = onFilterEntityChanged;
vm.addAlias = addAlias;
+ vm.editAlias = editAlias;
vm.removeAlias = removeAlias;
vm.cancel = cancel;
@@ -79,42 +84,61 @@ export default function EntityAliasesController(utils, entityService, toast, $sc
}
}
- if (vm.isSingleEntityAlias) {
- checkEntityAlias(vm.singleEntityAlias);
- }
-
for (aliasId in config.entityAliases) {
var entityAlias = config.entityAliases[aliasId];
- var result = {id: aliasId, alias: entityAlias.alias, filter: entityAlias.filter, changed: true};
- checkEntityAlias(result);
+ var filter = entityAlias.filter;
+ if (!filter) {
+ filter = {
+ resolveMultiple: false
+ };
+ }
+ if (!filter.resolveMultiple) {
+ filter.resolveMultiple = false;
+ }
+ var result = {id: aliasId, alias: entityAlias.alias, filter: filter};
vm.entityAliases.push(result);
}
}
- function checkEntityAlias(entityAlias) {
- if (!entityAlias.filter || entityAlias.filter == null) {
- entityAlias.filter = {};
- }
+ function addAlias($event) {
+ openAliasDialog($event);
}
- function onFilterEntityChanged(entity, stateEntity, entityAlias) {
- if (entityAlias) {
- if (!entityAlias.alias || entityAlias.alias.length == 0) {
- entityAlias.changed = false;
- }
- if (!entityAlias.changed && entityAlias.filter && entityAlias.filter.type) {
- if (stateEntity) {
- entityAlias.alias = $translate.instant('alias.state-entity');
- } else {
- entityAlias.alias = entity.name;
- }
- }
- }
+ function editAlias($event, entityAlias) {
+ openAliasDialog($event, entityAlias);
}
- function addAlias() {
- var entityAlias = {id: utils.guid(), alias: '', filter: {}, changed: false};
- vm.entityAliases.push(entityAlias);
+ function openAliasDialog($event, entityAlias) {
+ var isAdd = entityAlias ? false : true;
+ var aliasIndex;
+ if (!isAdd) {
+ aliasIndex = vm.entityAliases.indexOf(entityAlias);
+ }
+ $mdDialog.show({
+ controller: 'EntityAliasDialogController',
+ controllerAs: 'vm',
+ templateUrl: entityAliasDialogTemplate,
+ locals: {
+ isAdd: isAdd,
+ allowedEntityTypes: vm.allowedEntityTypes,
+ entityAliases: vm.entityAliases,
+ alias: isAdd ? null : angular.copy(entityAlias)
+ },
+ parent: angular.element($document[0].body),
+ fullscreen: true,
+ skipHide: true,
+ targetEvent: $event
+ }).then(function (alias) {
+ if (isAdd) {
+ vm.entityAliases.push(alias);
+ } else {
+ vm.entityAliases[aliasIndex] = alias;
+ }
+ if ($scope.theForm) {
+ $scope.theForm.$setDirty();
+ }
+ }, function () {
+ });
}
function removeAlias($event, entityAlias) {
@@ -157,43 +181,30 @@ export default function EntityAliasesController(utils, entityService, toast, $sc
var uniqueAliasList = {};
var valid = true;
- var aliasId;
- var alias;
- var i;
-
- if (vm.isSingleEntityAlias) {
- if (!vm.singleEntityAlias.id) {
- vm.singleEntityAlias.id = utils.guid();
- }
- for (i = 0; i < vm.entityAliases.length; i ++) {
- alias = vm.entityAliases[i].alias;
- if (alias === vm.singleEntityAlias.alias) {
- valid = false;
- break;
- }
- }
- } else {
- for (i = 0; i < vm.entityAliases.length; i++) {
- aliasId = vm.entityAliases[i].id;
- alias = vm.entityAliases[i].alias;
- if (!uniqueAliasList[alias]) {
- uniqueAliasList[alias] = alias;
- entityAliases[aliasId] = {id: aliasId, alias: alias, filter: vm.entityAliases[i].filter};
- } else {
- valid = false;
- break;
- }
+ var message, aliasId, alias, filter;
+
+ for (var i = 0; i < vm.entityAliases.length; i++) {
+ aliasId = vm.entityAliases[i].id;
+ alias = vm.entityAliases[i].alias;
+ filter = vm.entityAliases[i].filter;
+ if (uniqueAliasList[alias]) {
+ valid = false;
+ message = $translate.instant('entity.duplicate-alias-error', {alias: alias});
+ break;
+ } else if (!filter || !filter.type) {
+ valid = false;
+ message = $translate.instant('entity.missing-entity-filter-error', {alias: alias});
+ break;
+ } else {
+ uniqueAliasList[alias] = alias;
+ entityAliases[aliasId] = {id: aliasId, alias: alias, filter: filter};
}
}
if (valid) {
$scope.theForm.$setPristine();
- if (vm.isSingleEntityAlias) {
- $mdDialog.hide(vm.singleEntityAlias);
- } else {
- $mdDialog.hide(entityAliases);
- }
+ $mdDialog.hide(entityAliases);
} else {
- toast.showError($translate.instant('entity.duplicate-alias-error', {alias: alias}));
+ toast.showError(message);
}
}
ui/src/app/entity/entity-aliases.scss 12(+12 -0)
diff --git a/ui/src/app/entity/entity-aliases.scss b/ui/src/app/entity/entity-aliases.scss
index 4180bce..9803be1 100644
--- a/ui/src/app/entity/entity-aliases.scss
+++ b/ui/src/app/entity/entity-aliases.scss
@@ -17,6 +17,7 @@
.tb-aliases-dialog {
.md-dialog-content {
padding-bottom: 0px;
+ padding-top: 0px;
}
.tb-aliases-header {
min-height: 40px;
@@ -33,5 +34,16 @@
md-input-container {
margin: 0px;
}
+ .tb-resolve-multiple-switch {
+ padding-left: 10px;
+ .resolve-multiple-switch {
+ margin: 0;
+ }
+ }
+ .md-button {
+ &.md-icon-button {
+ margin: 0px;
+ }
+ }
}
}
ui/src/app/entity/entity-aliases.tpl.html 98(+52 -46)
diff --git a/ui/src/app/entity/entity-aliases.tpl.html b/ui/src/app/entity/entity-aliases.tpl.html
index 4fd33d9..40010a2 100644
--- a/ui/src/app/entity/entity-aliases.tpl.html
+++ b/ui/src/app/entity/entity-aliases.tpl.html
@@ -19,7 +19,7 @@
<form name="theForm" ng-submit="vm.save()">
<md-toolbar>
<div class="md-toolbar-tools">
- <h2>{{ vm.isSingleEntityAlias ? ('entity.configure-alias' | translate:vm.singleEntityAlias ) : (vm.title | translate) }}</h2>
+ <h2>{{ vm.title | translate }}</h2>
<span flex></span>
<md-button class="md-icon-button" ng-click="vm.cancel()">
<ng-md-icon icon="close" aria-label="{{ 'dialog.close' | translate }}"></ng-md-icon>
@@ -28,66 +28,72 @@
</md-toolbar>
<md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear>
<span style="min-height: 5px;" flex="" ng-show="!loading"></span>
- <div class="tb-aliases-header" ng-show="!vm.isSingleEntityAlias" flex layout="row" layout-align="start center">
+ <div class="tb-aliases-header" flex layout="row" layout-align="start center">
<span flex="5"></span>
<div flex layout="row" layout-align="start center">
- <span class="tb-header-label" translate flex="20" style="min-width: 150px;">entity.alias</span>
- <div flex="80" layout="row" layout-align="start center" style="min-width: 240px; padding-left: 10px;">
- <span class="tb-header-label" translate flex="70">alias.entity-filter</span>
- <span class="tb-header-label" translate flex="30" style="padding-left: 10px;" >alias.resolve-multiple</span>
- </div>
- <span style="min-width: 40px; margin: 0 6px;"></span>
+ <span class="tb-header-label" translate flex="20" style="min-width: 150px;">alias.name</span>
+ <span class="tb-header-label" translate flex="70" style="padding-left: 10px;">alias.entity-filter</span>
+ <span class="tb-header-label" translate flex="10" style="padding-left: 10px; min-width: 120px;">alias.resolve-multiple</span>
+ <span style="min-width: 80px;"></span>
</div>
</div>
- <md-divider ng-show="!vm.isSingleEntityAlias"></md-divider>
+ <md-divider></md-divider>
<md-dialog-content>
<div class="md-dialog-content">
<fieldset ng-disabled="loading">
- <div ng-show="vm.isSingleEntityAlias" layout="row">
- <tb-entity-filter flex
- allowed-entity-types="vm.allowedEntityTypes"
- ng-model="vm.singleEntityAlias.filter">
- </tb-entity-filter>
- </div>
- <div ng-show="!vm.isSingleEntityAlias" style="height: 100%; overflow: auto; padding-bottom: 20px;">
- <div ng-form name="aliasForm" flex layout="row" layout-align="start center" ng-repeat="entityAlias in vm.entityAliases track by $index">
- <span flex="5">{{$index + 1}}.</span>
- <div class="md-whiteframe-4dp tb-alias" flex layout="row" layout-align="start center">
- <md-input-container flex="20" style="min-width: 150px;" md-no-float class="md-block">
- <input required ng-change="entityAlias.changed=true" name="alias" placeholder="{{ 'entity.alias' | translate }}" ng-model="entityAlias.alias">
- <div ng-messages="aliasForm.alias.$error">
- <div translate ng-message="required">entity.alias-required</div>
- </div>
- </md-input-container>
- <tb-entity-filter flex="80" style="min-width: 240px; padding-left: 10px;"
- hide-labels
- allowed-entity-types="vm.allowedEntityTypes"
- ng-model="entityAlias.filter"
- on-matching-entity-change="vm.onFilterEntityChanged(entity, stateEntity, entityAlias)">
- </tb-entity-filter>
- <md-button ng-disabled="loading" class="md-icon-button md-primary" style="min-width: 40px;"
- ng-click="vm.removeAlias($event, entityAlias)" aria-label="{{ 'action.remove' | translate }}">
- <md-tooltip md-direction="top">
- {{ 'entity.remove-alias' | translate }}
- </md-tooltip>
- <md-icon aria-label="{{ 'action.delete' | translate }}" class="material-icons">
- close
- </md-icon>
- </md-button>
- </div>
- </div>
+ <div ng-form name="aliasForm" flex layout="row" layout-align="start center" ng-repeat="entityAlias in vm.entityAliases track by $index">
+ <span flex="5">{{$index + 1}}.</span>
+ <di class="md-whiteframe-4dp tb-alias" flex layout="row" layout-align="start center">
+ <md-input-container flex="20" style="min-width: 150px;" md-no-float class="md-block">
+ <input required name="alias" placeholder="{{ 'entity.alias' | translate }}" ng-model="entityAlias.alias">
+ <div ng-messages="aliasForm.alias.$error">
+ <div translate ng-message="required">entity.alias-required</div>
+ </div>
+ </md-input-container>
+ <tb-entity-filter-view
+ flex="70" style="padding-left: 10px;"
+ ng-model="entityAlias.filter">
+ </tb-entity-filter-view>
+ <section flex="10" style="padding-left: 10px; min-width: 120px;"
+ class="tb-resolve-multiple-switch"
+ layout="column"
+ layout-align="center center">
+ <md-switch class="resolve-multiple-switch"
+ ng-model="entityAlias.filter.resolveMultiple"
+ aria-label="resolve-multiple-switcher">
+ </md-switch>
+ </section>
+ <md-button ng-disabled="loading" class="md-icon-button md-primary" style="min-width: 40px;"
+ ng-click="vm.editAlias($event, entityAlias)" aria-label="{{ 'action.edit' | translate }}">
+ <md-tooltip md-direction="top">
+ {{ 'alias.edit' | translate }}
+ </md-tooltip>
+ <md-icon aria-label="{{ 'alias.edit' | translate }}" class="material-icons">
+ edit
+ </md-icon>
+ </md-button>
+ <md-button ng-disabled="loading" class="md-icon-button md-primary" style="min-width: 40px;"
+ ng-click="vm.removeAlias($event, entityAlias)" aria-label="{{ 'action.remove' | translate }}">
+ <md-tooltip md-direction="top">
+ {{ 'entity.remove-alias' | translate }}
+ </md-tooltip>
+ <md-icon aria-label="{{ 'action.delete' | translate }}" class="material-icons">
+ close
+ </md-icon>
+ </md-button>
+ </di>
</div>
</fieldset>
</div>
</md-dialog-content>
<md-dialog-actions layout="row">
- <md-button ng-show="!vm.isSingleEntityAlias && !vm.disableAdd" ng-disabled="loading" class="md-primary md-raised"
+ <md-button ng-show="!vm.disableAdd" ng-disabled="loading" class="md-primary md-raised"
ng-click="vm.addAlias($event)"
- aria-label="{{ 'action.add' | translate }}">
+ aria-label="{{ 'alias.add' | translate }}">
<md-tooltip md-direction="top">
- {{ 'entity.add-alias' | translate }}
+ {{ 'alias.add' | translate }}
</md-tooltip>
- <span translate>action.add</span>
+ <span translate>alias.add</span>
</md-button>
<span flex></span>
<md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary">
ui/src/app/entity/entity-filter.directive.js 100(+45 -55)
diff --git a/ui/src/app/entity/entity-filter.directive.js b/ui/src/app/entity/entity-filter.directive.js
index 0f9cf5c..9566716 100644
--- a/ui/src/app/entity/entity-filter.directive.js
+++ b/ui/src/app/entity/entity-filter.directive.js
@@ -17,16 +17,13 @@
/* eslint-disable import/no-unresolved, import/default */
import entityFilterTemplate from './entity-filter.tpl.html';
-import entityFilterDialogTemplate from './entity-filter-dialog.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
-import EntityFilterDialogController from './entity-filter-dialog.controller';
-
import './entity-filter.scss';
/*@ngInject*/
-export default function EntityFilterDirective($compile, $templateCache, $q, $document, $mdDialog, types) {
+export default function EntityFilterDirective($compile, $templateCache, $q, $document, $mdDialog, types, entityService) {
var linker = function (scope, element, attrs, ngModelCtrl) {
@@ -35,66 +32,59 @@ export default function EntityFilterDirective($compile, $templateCache, $q, $doc
scope.ngModelCtrl = ngModelCtrl;
scope.types = types;
- scope.hideLabels = angular.isDefined(attrs.hideLabels);
+ scope.aliasFilterTypes = entityService.getAliasFilterTypesByEntityTypes(scope.allowedEntityTypes);
- scope.updateValidity = function() {
- if (ngModelCtrl.$viewValue) {
- var value = ngModelCtrl.$viewValue;
- ngModelCtrl.$setValidity('filter', value.type ? true : false);
+ scope.$watch('filter.type', function (newType, prevType) {
+ if (newType && newType != prevType) {
+ updateFilter();
}
- }
+ });
- ngModelCtrl.$render = function () {
- if (ngModelCtrl.$viewValue) {
- scope.model = angular.copy(ngModelCtrl.$viewValue);
- } else {
- scope.model = {
- type: null,
- resolveMultiple: false
- }
+ function updateFilter() {
+ var filter = {};
+ filter.type = scope.filter.type;
+ filter.resolveMultiple = scope.filter.resolveMultiple;
+ switch (filter.type) {
+ case types.aliasFilterType.entityList.value:
+ filter.entityType = null;
+ filter.entityList = [];
+ break;
+ case types.aliasFilterType.entityName.value:
+ filter.entityType = null;
+ filter.entityNameFilter = '';
+ break;
+ case types.aliasFilterType.stateEntity.value:
+ break;
+ case types.aliasFilterType.assetType.value:
+ filter.assetType = null;
+ filter.assetNameFilter = '';
+ break;
+ case types.aliasFilterType.deviceType.value:
+ filter.deviceType = null;
+ filter.deviceNameFilter = '';
+ break;
+ //TODO: Alias filter
}
+ scope.filter = filter;
}
- scope.$watch('model.resolveMultiple', function () {
- if (ngModelCtrl.$viewValue) {
- var value = ngModelCtrl.$viewValue;
- value.resolveMultiple = scope.model.resolveMultiple;
- ngModelCtrl.$setViewValue(value);
- scope.updateValidity();
- }
+ scope.$watch('filter', function () {
+ scope.updateView();
});
- scope.editFilter = function($event) {
- openEntityFilterDialog($event, false);
+ scope.updateView = function() {
+ ngModelCtrl.$setViewValue(scope.filter);
}
- scope.createFilter = function($event) {
- openEntityFilterDialog($event, true);
- }
-
- function openEntityFilterDialog($event, isAdd) {
- $mdDialog.show({
- controller: EntityFilterDialogController,
- controllerAs: 'vm',
- templateUrl: entityFilterDialogTemplate,
- locals: {
- isAdd: isAdd,
- allowedEntityTypes: scope.allowedEntityTypes,
- filter: angular.copy(scope.model)
- },
- parent: angular.element($document[0].body),
- fullscreen: true,
- skipHide: true,
- targetEvent: $event
- }).then(function (result) {
- scope.model = result.filter;
- ngModelCtrl.$setViewValue(result.filter);
- scope.updateValidity();
- if (scope.onMatchingEntityChange) {
- scope.onMatchingEntityChange({entity: result.entity, stateEntity: result.stateEntity});
+ ngModelCtrl.$render = function () {
+ if (ngModelCtrl.$viewValue) {
+ scope.filter = ngModelCtrl.$viewValue;
+ } else {
+ scope.filter = {
+ type: null,
+ resolveMultiple: false
}
- }, function () {
- });
+ }
}
$compile(element.contents())(scope);
@@ -106,8 +96,8 @@ export default function EntityFilterDirective($compile, $templateCache, $q, $doc
require: "^ngModel",
link: linker,
scope: {
- allowedEntityTypes: '=?',
- onMatchingEntityChange: '&'
+ theForm: '=',
+ allowedEntityTypes: '=?'
}
};
ui/src/app/entity/entity-filter.scss 19(+2 -17)
diff --git a/ui/src/app/entity/entity-filter.scss b/ui/src/app/entity/entity-filter.scss
index 10ddcd3..ebbea3d 100644
--- a/ui/src/app/entity/entity-filter.scss
+++ b/ui/src/app/entity/entity-filter.scss
@@ -13,22 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
.tb-entity-filter {
- .tb-filter-switch {
- padding-left: 10px;
- .filter-switch {
- margin: 0;
- }
- .filter-label {
- margin: 5px 0;
- }
- }
- .tb-error-messages {
- margin-top: -11px;
- height: 35px;
- .tb-error-message {
- padding-left: 8px;
- padding-top: 14px;
- }
- }
+
}
\ No newline at end of file
ui/src/app/entity/entity-filter.tpl.html 104(+72 -32)
diff --git a/ui/src/app/entity/entity-filter.tpl.html b/ui/src/app/entity/entity-filter.tpl.html
index 6ce95fa..77b6d3c 100644
--- a/ui/src/app/entity/entity-filter.tpl.html
+++ b/ui/src/app/entity/entity-filter.tpl.html
@@ -15,37 +15,77 @@
limitations under the License.
-->
-<section layout='row' class="tb-entity-filter">
- <section layout="row" flex="70">
- <section flex layout="column" layout-align="center start">
- <div ng-if="model.type">{{ types.aliasFilterType[model.type].name | translate }}</div>
- <md-button ng-if="!model.type"
- ng-disabled="loading" class="md-primary"
- ng-click="createFilter($event)"
- aria-label="{{ 'alias.create-entity-filter' | translate }}">
- <md-icon aria-label="{{ 'alias.create-entity-filter' | translate }}"
- class="material-icons">
- add
- </md-icon>
- {{ 'alias.create-entity-filter' | translate }}
- </md-button>
- </section>
- <md-button ng-if="model.type" ng-disabled="loading" class="md-icon-button md-primary"
- style="min-width: 40px;"
- ng-click="editFilter($event)"
- aria-label="{{ 'alias.edit-entity-filter' | translate }}">
- <md-tooltip md-direction="top">
- {{ 'alias.edit-entity-filter' | translate }}
- </md-tooltip>
- <md-icon aria-label="{{ 'alias.edit-entity-filter' | translate }}"
- class="material-icons">
- edit
- </md-icon>
- </md-button>
+<div layout='column' class="tb-entity-filter">
+ <md-input-container class="md-block">
+ <label>{{ 'alias.filter-type' | translate }}</label>
+ <md-select required name="filterType"
+ ng-model="filter.type" aria-label="{{ 'alias.filter-type' | translate }}">
+ <md-option ng-repeat="type in aliasFilterTypes" ng-value="type.value">
+ {{type.name | translate}}
+ </md-option>
+ </md-select>
+ <div ng-messages="theForm.filterType.$error">
+ <div ng-message="required" translate>alias.filter-type-required</div>
+ </div>
+ </md-input-container>
+ <section layout="column" ng-if="filter.type == types.aliasFilterType.entityList.value" id="entityListFilter">
+ <tb-entity-type-select
+ ng-model="filter.entityType"
+ the-form="theForm"
+ tb-required="true"
+ allowed-entity-types="allowedEntityTypes">
+ </tb-entity-type-select>
+ <tb-entity-list
+ ng-model="filter.entityList"
+ tb-required="true"
+ entity-type="filter.entityType">
+ </tb-entity-list>
</section>
- <section class="tb-filter-switch" layout="column" flex="30" layout-align="center center">
- <label ng-if="!hideLabels" class="tb-small filter-label" translate>alias.resolve-multiple</label>
- <md-switch class="filter-switch" ng-model="model.resolveMultiple" aria-label="resolve-multiple-switcher">
- </md-switch>
+ <section flex layout="column" ng-if="filter.type == types.aliasFilterType.entityName.value" id="entityNameFilter">
+ <tb-entity-type-select
+ ng-model="filter.entityType"
+ the-form="theForm"
+ tb-required="true"
+ allowed-entity-types="allowedEntityTypes">
+ </tb-entity-type-select>
+ <md-input-container class="md-block">
+ <label translate>entity.name-starts-with</label>
+ <input required name="entityNameFilter"
+ ng-model="filter.entityNameFilter"
+ aria-label="{{ 'entity.name-starts-with' | translate }}">
+ <div ng-messages="theForm.entityNameFilter.$error">
+ <div ng-message="required" translate>entity.entity-name-filter-required</div>
+ </div>
+ </md-input-container>
</section>
-</section>
+ <section layout="column" ng-if="filter.type == types.aliasFilterType.stateEntity.value" id="stateEntityFilter">
+ </section>
+ <section layout="column" ng-if="filter.type == types.aliasFilterType.assetType.value" id="assetTypeFilter">
+ <tb-entity-subtype-autocomplete
+ tb-required="true"
+ the-form="theForm"
+ ng-model="filter.assetType"
+ entity-type="types.entityType.asset">
+ </tb-entity-subtype-autocomplete>
+ <md-input-container class="md-block">
+ <label translate>asset.name-starts-with</label>
+ <input name="assetNameFilter"
+ ng-model="filter.assetNameFilter"
+ aria-label="{{ 'asset.name-starts-with' | translate }}">
+ </md-input-container>
+ </section>
+ <section layout="column" ng-if="filter.type == types.aliasFilterType.deviceType.value" id="deviceTypeFilter">
+ <tb-entity-subtype-autocomplete
+ tb-required="true"
+ the-form="theForm"
+ ng-model="filter.deviceType"
+ entity-type="types.entityType.device">
+ </tb-entity-subtype-autocomplete>
+ <md-input-container class="md-block">
+ <label translate>device.name-starts-with</label>
+ <input name="deviceNameFilter"
+ ng-model="filter.deviceNameFilter"
+ aria-label="{{ 'device.name-starts-with' | translate }}">
+ </md-input-container>
+ </section>
+</div>
ui/src/app/entity/entity-filter-view.directive.js 106(+106 -0)
diff --git a/ui/src/app/entity/entity-filter-view.directive.js b/ui/src/app/entity/entity-filter-view.directive.js
new file mode 100644
index 0000000..6a358b2
--- /dev/null
+++ b/ui/src/app/entity/entity-filter-view.directive.js
@@ -0,0 +1,106 @@
+/*
+ * Copyright © 2016-2017 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.
+ */
+
+/* eslint-disable import/no-unresolved, import/default */
+
+import entityFilterViewTemplate from './entity-filter-view.tpl.html';
+
+/* eslint-enable import/no-unresolved, import/default */
+
+import './entity-filter-view.scss';
+
+/*@ngInject*/
+export default function EntityFilterViewDirective($compile, $templateCache, $q, $document, $mdDialog, $translate, types/*, entityService*/) {
+
+ var linker = function (scope, element, attrs, ngModelCtrl) {
+
+ var template = $templateCache.get(entityFilterViewTemplate);
+ element.html(template);
+
+ scope.ngModelCtrl = ngModelCtrl;
+ scope.types = types;
+ scope.filterDisplayValue = '';
+
+ scope.$watch('filter', function () {
+ scope.updateDisplayValue();
+ });
+
+ scope.updateDisplayValue = function() {
+ if (scope.filter && scope.filter.type) {
+ var entityType;
+ var prefix;
+ switch (scope.filter.type) {
+ case types.aliasFilterType.entityList.value:
+ entityType = scope.filter.entityType;
+ var count = scope.filter.entityList.length;
+ scope.filterDisplayValue = $translate.instant(types.entityTypeTranslations[entityType].list, {count: count}, 'messageformat');
+ break;
+ case types.aliasFilterType.entityName.value:
+ entityType = scope.filter.entityType;
+ prefix = scope.filter.entityNameFilter;
+ scope.filterDisplayValue = $translate.instant(types.entityTypeTranslations[entityType].nameStartsWith, {prefix: prefix});
+ break;
+ case types.aliasFilterType.stateEntity.value:
+ scope.filterDisplayValue = $translate.instant('alias.filter-type-state-entity-description');
+ break;
+ case types.aliasFilterType.assetType.value:
+ var assetType = scope.filter.assetType;
+ prefix = scope.filter.assetNameFilter;
+ if (prefix && prefix.length) {
+ scope.filterDisplayValue = $translate.instant('alias.filter-type-asset-type-and-name-description', {assetType: assetType, prefix: prefix});
+ } else {
+ scope.filterDisplayValue = $translate.instant('alias.filter-type-asset-type-description', {assetType: assetType});
+ }
+ break;
+ case types.aliasFilterType.deviceType.value:
+ var deviceType = scope.filter.deviceType;
+ prefix = scope.filter.deviceNameFilter;
+ if (prefix && prefix.length) {
+ scope.filterDisplayValue = $translate.instant('alias.filter-type-device-type-and-name-description', {deviceType: deviceType, prefix: prefix});
+ } else {
+ scope.filterDisplayValue = $translate.instant('alias.filter-type-device-type-description', {deviceType: deviceType});
+ }
+ break;
+ //TODO: Alias filter
+ default:
+ scope.filterDisplayValue = scope.filter.type;
+ break;
+ }
+ } else {
+ scope.filterDisplayValue = '';
+ }
+ }
+
+ ngModelCtrl.$render = function () {
+ if (ngModelCtrl.$viewValue) {
+ scope.filter = ngModelCtrl.$viewValue;
+ } else {
+ scope.filter = null;
+ }
+ }
+
+ $compile(element.contents())(scope);
+
+ }
+
+ return {
+ restrict: "E",
+ require: "^ngModel",
+ link: linker,
+ scope: true
+ };
+
+}
ui/src/app/entity/entity-filter-view.scss 33(+33 -0)
diff --git a/ui/src/app/entity/entity-filter-view.scss b/ui/src/app/entity/entity-filter-view.scss
new file mode 100644
index 0000000..437f296
--- /dev/null
+++ b/ui/src/app/entity/entity-filter-view.scss
@@ -0,0 +1,33 @@
+/**
+ * Copyright © 2016-2017 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.
+ */
+
+.tb-entity-filter-view {
+ .entity-filter-empty {
+ color: rgba(221, 44, 0, 0.87);
+ font-size: 14px;
+ line-height: 16px;
+ }
+ .entity-filter-type {
+ font-size: 14px;
+ line-height: 16px;
+ color: rgba(0, 0, 0, 0.570588);
+ }
+ .entity-filter-value {
+ font-size: 14px;
+ line-height: 16px;
+ color: rgba(0, 0, 0, 0.570588);
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/entity/entity-filter-view.tpl.html b/ui/src/app/entity/entity-filter-view.tpl.html
new file mode 100644
index 0000000..84c5405
--- /dev/null
+++ b/ui/src/app/entity/entity-filter-view.tpl.html
@@ -0,0 +1,24 @@
+<!--
+
+ Copyright © 2016-2017 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 layout='column' class="tb-entity-filter-view">
+ <div ng-if="!filter || !filter.type" class="entity-filter-empty" translate>alias.no-entity-filter-specified</div>
+ <div ng-if="filter && filter.type" layout="column">
+ <div class="entity-filter-value">{{ filterDisplayValue }}</div>
+ </div>
+</div>
diff --git a/ui/src/app/entity/entity-type-select.directive.js b/ui/src/app/entity/entity-type-select.directive.js
index 1dc6741..bca2ee0 100644
--- a/ui/src/app/entity/entity-type-select.directive.js
+++ b/ui/src/app/entity/entity-type-select.directive.js
@@ -71,7 +71,7 @@ export default function EntityTypeSelect($compile, $templateCache, utils, userSe
}
scope.typeName = function(type) {
- return utils.entityTypeName(type);
+ return type ? types.entityTypeTranslations[type].type : '';
}
scope.updateValidity = function () {
ui/src/app/entity/index.js 4(+4 -0)
diff --git a/ui/src/app/entity/index.js b/ui/src/app/entity/index.js
index 6be118f..2fc1d63 100644
--- a/ui/src/app/entity/index.js
+++ b/ui/src/app/entity/index.js
@@ -15,6 +15,7 @@
*/
import EntityAliasesController from './entity-aliases.controller';
+import EntityAliasDialogController from './entity-alias-dialog.controller';
import EntityTypeSelectDirective from './entity-type-select.directive';
import EntitySubtypeSelectDirective from './entity-subtype-select.directive';
import EntitySubtypeAutocompleteDirective from './entity-subtype-autocomplete.directive';
@@ -22,6 +23,7 @@ import EntityAutocompleteDirective from './entity-autocomplete.directive';
import EntityListDirective from './entity-list.directive';
import EntitySelectDirective from './entity-select.directive';
import EntityFilterDirective from './entity-filter.directive';
+import EntityFilterViewDirective from './entity-filter-view.directive';
import AliasesEntitySelectPanelController from './aliases-entity-select-panel.controller';
import AliasesEntitySelectDirective from './aliases-entity-select.directive';
import AddAttributeDialogController from './attribute/add-attribute-dialog.controller';
@@ -32,6 +34,7 @@ import RelationTypeAutocompleteDirective from './relation/relation-type-autocomp
export default angular.module('thingsboard.entity', [])
.controller('EntityAliasesController', EntityAliasesController)
+ .controller('EntityAliasDialogController', EntityAliasDialogController)
.controller('AliasesEntitySelectPanelController', AliasesEntitySelectPanelController)
.controller('AddAttributeDialogController', AddAttributeDialogController)
.controller('AddWidgetToDashboardDialogController', AddWidgetToDashboardDialogController)
@@ -42,6 +45,7 @@ export default angular.module('thingsboard.entity', [])
.directive('tbEntityList', EntityListDirective)
.directive('tbEntitySelect', EntitySelectDirective)
.directive('tbEntityFilter', EntityFilterDirective)
+ .directive('tbEntityFilterView', EntityFilterViewDirective)
.directive('tbAliasesEntitySelect', AliasesEntitySelectDirective)
.directive('tbAttributeTable', AttributeTableDirective)
.directive('tbRelationTable', RelationTableDirective)
diff --git a/ui/src/app/entity/relation/relation-table.directive.js b/ui/src/app/entity/relation/relation-table.directive.js
index 729ff36..f0c192b 100644
--- a/ui/src/app/entity/relation/relation-table.directive.js
+++ b/ui/src/app/entity/relation/relation-table.directive.js
@@ -218,9 +218,9 @@ function RelationTableController($scope, $q, $mdDialog, $document, $translate, $
function success(allRelations) {
allRelations.forEach(function(relation) {
if (vm.direction == vm.types.entitySearchDirection.from) {
- relation.toEntityTypeName = $translate.instant(utils.entityTypeName(relation.to.entityType));
+ relation.toEntityTypeName = $translate.instant(types.entityTypeTranslations[relation.to.entityType].type);
} else {
- relation.fromEntityTypeName = $translate.instant(utils.entityTypeName(relation.from.entityType));
+ relation.fromEntityTypeName = $translate.instant(types.entityTypeTranslations[relation.from.entityType].type);
}
});
vm.allRelations = allRelations;
diff --git a/ui/src/app/import-export/import-export.service.js b/ui/src/app/import-export/import-export.service.js
index 9b36c38..8d4a098 100644
--- a/ui/src/app/import-export/import-export.service.js
+++ b/ui/src/app/import-export/import-export.service.js
@@ -365,7 +365,6 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document,
alias = aliasInfo.aliasName;
filter = {
type: types.aliasFilterType.entityList.value,
- stateEntity: false,
entityType: types.entityType.device,
entityList: [aliasInfo.deviceId],
resolveMultiple: false
@@ -378,7 +377,6 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document,
resolveMultiple: false
}
if (filter.type == types.aliasFilterType.entityList.value) {
- filter.stateEntity = false;
filter.entityList = aliasInfo.deviceFilter.deviceList
} else {
filter.entityNameFilter = aliasInfo.deviceFilter.deviceNameFilter;
@@ -391,7 +389,6 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document,
resolveMultiple: false
}
if (filter.type == types.aliasFilterType.entityList.value) {
- filter.stateEntity = false;
filter.entityList = aliasInfo.entityFilter.entityList;
} else {
filter.entityNameFilter = aliasInfo.entityFilter.entityNameFilter;
@@ -662,8 +659,6 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document,
entityAliases: missingEntityAliases,
widgets: widgets,
isSingleWidget: isSingleWidget,
- isSingleEntityAlias: false,
- singleEntityAlias: null,
customTitle: customTitle,
disableAdd: true
}
ui/src/app/locale/locale.constant.js 55(+41 -14)
diff --git a/ui/src/app/locale/locale.constant.js b/ui/src/app/locale/locale.constant.js
index 9c6695b..88a6021 100644
--- a/ui/src/app/locale/locale.constant.js
+++ b/ui/src/app/locale/locale.constant.js
@@ -113,23 +113,30 @@ export default angular.module('thingsboard.locale', [])
"alarm-required": "Alarm is required"
},
"alias": {
+ "add": "Add alias",
+ "edit": "Edit alias",
+ "name": "Alias name",
+ "name-required": "Alias name is required",
+ "duplicate-alias": "Alias with same name is already exists.",
"filter-type-entity-list": "Entity list",
"filter-type-entity-name": "Entity name",
+ "filter-type-state-entity": "Entity from dashboard state",
+ "filter-type-state-entity-description": "Entity taken from dashboard state parameters",
"filter-type-asset-type": "Asset type",
+ "filter-type-asset-type-description": "Assets of type '{{assetType}}'",
+ "filter-type-asset-type-and-name-description": "Assets of type '{{assetType}}' and with name starting with '{{prefix}}'",
"filter-type-device-type": "Device type",
+ "filter-type-device-type-description": "Devices of type '{{deviceType}}'",
+ "filter-type-device-type-and-name-description": "Devices of type '{{deviceType}}' and with name starting with '{{prefix}}'",
"filter-type-relations-query": "Relations query",
"filter-type-asset-search-query": "Asset search query",
"filter-type-device-search-query": "Device search query",
"entity-filter": "Entity filter",
- "create-entity-filter": "Create entity filter",
- "edit-entity-filter": "Edit entity filter",
- "entity-filter-required": "Entity filter is required.",
"resolve-multiple": "Resolve as multiple entities",
"filter-type": "Filter type",
"filter-type-required": "Filter type is required.",
- "use-state-entity": "Use state entity",
- "state-entity": "State entity",
"entity-filter-no-entity-matched": "No entities matching specified filter were found.",
+ "no-entity-filter-specified": "No entity filter specified"
},
"asset": {
"asset": "Asset",
@@ -185,7 +192,8 @@ export default angular.module('thingsboard.locale', [])
"idCopiedMessage": "Asset Id has been copied to clipboard",
"select-asset": "Select asset",
"no-assets-matching": "No assets matching '{{entity}}' were found.",
- "asset-required": "Asset is required"
+ "asset-required": "Asset is required",
+ "name-starts-with": "Asset name starts with"
},
"attribute": {
"attributes": "Attributes",
@@ -463,7 +471,7 @@ export default angular.module('thingsboard.locale', [])
"alias-required": "Device alias is required.",
"remove-alias": "Remove device alias",
"add-alias": "Add device alias",
- "name-starts-with": "Name starts with",
+ "name-starts-with": "Device name starts with",
"device-list": "Device list",
"use-device-name-filter": "Use filter",
"device-list-empty": "No devices selected.",
@@ -549,6 +557,7 @@ export default angular.module('thingsboard.locale', [])
"unable-delete-entity-alias-title": "Unable to delete entity alias",
"unable-delete-entity-alias-text": "Entity alias '{{entityAlias}}' can't be deleted as it used by the following widget(s):<br/>{{widgetsList}}",
"duplicate-alias-error": "Duplicate alias found '{{alias}}'.<br>Entity aliases must be unique whithin the dashboard.",
+ "missing-entity-filter-error": "Filter is missing for alias '{{alias}}'.",
"configure-alias": "Configure '{{alias}}' alias",
"alias": "Alias",
"alias-required": "Entity alias is required.",
@@ -562,24 +571,42 @@ export default angular.module('thingsboard.locale', [])
"entity-name-filter-required": "Entity name filter is required.",
"entity-name-filter-no-entity-matched": "No entities starting with '{{entity}}' were found.",
"all-subtypes": "All",
+ "select-entities": "Select entities",
+ "no-aliases-found": "No aliases found.",
+ "no-alias-matching": "'{{alias}}' not found.",
+ "create-new-alias": "Create a new one!",
+ "no-keys-found": "No keys found.",
+ "no-key-matching": "'{{key}}' not found.",
+ "create-new-key": "Create a new one!",
"type": "Type",
"type-required": "Entity type is required.",
"type-device": "Device",
+ "list-of-devices": "{ count, select, 1 {One device} other {List of # devices} }",
+ "device-name-starts-with": "Devices whose names start with '{{prefix}}'",
"type-asset": "Asset",
+ "list-of-assets": "{ count, select, 1 {One asset} other {List of # assets} }",
+ "asset-name-starts-with": "Assets whose names start with '{{prefix}}'",
"type-rule": "Rule",
+ "list-of-rules": "{ count, select, 1 {One rule} other {List of # rules} }",
+ "rule-name-starts-with": "Rules whose names start with '{{prefix}}'",
"type-plugin": "Plugin",
+ "list-of-plugins": "{ count, select, 1 {One plugin} other {List of # plugins} }",
+ "plugin-name-starts-with": "Plugins whose names start with '{{prefix}}'",
"type-tenant": "Tenant",
+ "list-of-tenants": "{ count, select, 1 {One tenant} other {List of # tenants} }",
+ "tenant-name-starts-with": "Tenants whose names start with '{{prefix}}'",
"type-customer": "Customer",
+ "list-of-customers": "{ count, select, 1 {One customer} other {List of # customers} }",
+ "customer-name-starts-with": "Customers whose names start with '{{prefix}}'",
"type-user": "User",
+ "list-of-users": "{ count, select, 1 {One user} other {List of # users} }",
+ "user-name-starts-with": "Users whose names start with '{{prefix}}'",
"type-dashboard": "Dashboard",
+ "list-of-dashboards": "{ count, select, 1 {One dashboard} other {List of # dashboards} }",
+ "dashboard-name-starts-with": "Dashboards whose names start with '{{prefix}}'",
"type-alarm": "Alarm",
- "select-entities": "Select entities",
- "no-aliases-found": "No aliases found.",
- "no-alias-matching": "'{{alias}}' not found.",
- "create-new-alias": "Create a new one!",
- "no-keys-found": "No keys found.",
- "no-key-matching": "'{{key}}' not found.",
- "create-new-key": "Create a new one!"
+ "list-of-alarms": "{ count, select, 1 {One alarms} other {List of # alarms} }",
+ "alarm-name-starts-with": "Alarms whose names start with '{{prefix}}'"
},
"event": {
"event-type": "Event type",