TB-61: Improve Alias Filter. Miltiple datasources resolution.
This commit is contained in:
parent
ae4148d7fa
commit
0c0b3dade4
259
ui/src/app/api/alias-controller.js
Normal file
259
ui/src/app/api/alias-controller.js
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
const varsRegex = /\$\{([^\}]*)\}/g;
|
||||
|
||||
export default class AliasController {
|
||||
|
||||
constructor($scope, $q, $filter, utils, types, entityService, stateController, entityAliases) {
|
||||
this.$scope = $scope;
|
||||
this.$q = $q;
|
||||
this.$filter = $filter;
|
||||
this.utils = utils;
|
||||
this.types = types;
|
||||
this.entityService = entityService;
|
||||
this.stateController = stateController;
|
||||
this.entityAliases = angular.copy(entityAliases);
|
||||
this.resolvedAliases = {};
|
||||
this.resolvedAliasesPromise = {};
|
||||
this.resolvedAliasesToStateEntities = {};
|
||||
}
|
||||
|
||||
updateEntityAliases(newEntityAliases) {
|
||||
var changedAliasIds = [];
|
||||
for (var aliasId in newEntityAliases) {
|
||||
var newEntityAlias = newEntityAliases[aliasId];
|
||||
var prevEntityAlias = this.entityAliases[aliasId];
|
||||
if (!angular.equals(newEntityAlias, prevEntityAlias)) {
|
||||
changedAliasIds.push(aliasId);
|
||||
this.setAliasUnresolved(aliasId);
|
||||
}
|
||||
}
|
||||
for (aliasId in this.entityAliases) {
|
||||
if (!newEntityAliases[aliasId]) {
|
||||
changedAliasIds.push(aliasId);
|
||||
this.setAliasUnresolved(aliasId);
|
||||
}
|
||||
}
|
||||
this.entityAliases = angular.copy(newEntityAliases);
|
||||
if (changedAliasIds.length) {
|
||||
this.$scope.$broadcast('entityAliasesChanged', changedAliasIds);
|
||||
}
|
||||
}
|
||||
|
||||
dashboardStateChanged() {
|
||||
var newEntityId = this.stateController.getStateParams().entityId;
|
||||
var changedAliasIds = [];
|
||||
for (var aliasId in this.resolvedAliasesToStateEntities) {
|
||||
var prevEntityId = this.resolvedAliasesToStateEntities[aliasId];
|
||||
if (!angular.equals(newEntityId, prevEntityId)) {
|
||||
changedAliasIds.push(aliasId);
|
||||
this.setAliasUnresolved(aliasId);
|
||||
}
|
||||
}
|
||||
if (changedAliasIds.length) {
|
||||
this.$scope.$broadcast('entityAliasesChanged', changedAliasIds);
|
||||
}
|
||||
}
|
||||
|
||||
setAliasUnresolved(aliasId) {
|
||||
delete this.resolvedAliases[aliasId];
|
||||
delete this.resolvedAliasesPromise[aliasId];
|
||||
delete this.resolvedAliasesToStateEntities[aliasId];
|
||||
}
|
||||
|
||||
getEntityAliases() {
|
||||
return this.entityAliases;
|
||||
}
|
||||
|
||||
getAliasInfo(aliasId) {
|
||||
var deferred = this.$q.defer();
|
||||
var aliasInfo = this.resolvedAliases[aliasId];
|
||||
if (aliasInfo) {
|
||||
deferred.resolve(aliasInfo);
|
||||
return deferred.promise;
|
||||
} else if (this.resolvedAliasesPromise[aliasId]) {
|
||||
return this.resolvedAliasesPromise[aliasId];
|
||||
} else {
|
||||
this.resolvedAliasesPromise[aliasId] = deferred.promise;
|
||||
var aliasCtrl = this;
|
||||
var entityAlias = this.entityAliases[aliasId];
|
||||
if (entityAlias) {
|
||||
this.entityService.resolveAlias(entityAlias, this.stateController.getStateParams()).then(
|
||||
function success(aliasInfo) {
|
||||
aliasCtrl.resolvedAliases[aliasId] = aliasInfo;
|
||||
if (entityAlias.filter.stateEntity) {
|
||||
aliasCtrl.resolvedAliasesToStateEntities[aliasId] =
|
||||
aliasCtrl.stateController.getStateParams().entityId;
|
||||
}
|
||||
deferred.resolve(aliasInfo);
|
||||
},
|
||||
function fail() {
|
||||
deferred.reject();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
deferred.reject();
|
||||
}
|
||||
return this.resolvedAliasesPromise[aliasId];
|
||||
}
|
||||
}
|
||||
|
||||
resolveDatasource(datasource) {
|
||||
var deferred = this.$q.defer();
|
||||
if (datasource.type === this.types.datasourceType.entity) {
|
||||
if (datasource.entityAliasId) {
|
||||
this.getAliasInfo(datasource.entityAliasId).then(
|
||||
function success(aliasInfo) {
|
||||
datasource.aliasName = aliasInfo.alias;
|
||||
if (aliasInfo.resolveMultiple) {
|
||||
var resolvedEntities = aliasInfo.resolvedEntities;
|
||||
if (resolvedEntities && resolvedEntities.length) {
|
||||
var datasources = [];
|
||||
for (var i=0;i<resolvedEntities.length;i++) {
|
||||
var resolvedEntity = resolvedEntities[i];
|
||||
var newDatasource = angular.copy(datasource);
|
||||
newDatasource.entityId = resolvedEntity.id;
|
||||
newDatasource.entityType = resolvedEntity.entityType;
|
||||
newDatasource.entityName = resolvedEntity.name;
|
||||
newDatasource.name = resolvedEntity.name;
|
||||
newDatasource.generated = i > 0 ? true : false;
|
||||
datasources.push(newDatasource);
|
||||
}
|
||||
deferred.resolve(datasources);
|
||||
} else {
|
||||
deferred.reject();
|
||||
}
|
||||
} else {
|
||||
var entity = aliasInfo.currentEntity;
|
||||
datasource.entityId = entity.id;
|
||||
datasource.entityType = entity.entityType;
|
||||
datasource.entityName = entity.name;
|
||||
datasource.name = entity.name;
|
||||
deferred.resolve([datasource]);
|
||||
}
|
||||
},
|
||||
function fail() {
|
||||
deferred.reject();
|
||||
}
|
||||
);
|
||||
} else { // entityId
|
||||
datasource.aliasName = datasource.entityName;
|
||||
datasource.name = datasource.entityName;
|
||||
deferred.resolve([datasource]);
|
||||
}
|
||||
} else { // function
|
||||
deferred.resolve([datasource]);
|
||||
}
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
resolveDatasources(datasources) {
|
||||
|
||||
function updateDataKeyLabel(dataKey, datasource) {
|
||||
if (!dataKey.pattern) {
|
||||
dataKey.pattern = angular.copy(dataKey.label);
|
||||
}
|
||||
var pattern = dataKey.pattern;
|
||||
var label = dataKey.pattern;
|
||||
var match = varsRegex.exec(pattern);
|
||||
while (match !== null) {
|
||||
var variable = match[0];
|
||||
var variableName = match[1];
|
||||
if (variableName === 'dsName') {
|
||||
label = label.split(variable).join(datasource.name);
|
||||
} else if (variableName === 'entityName') {
|
||||
label = label.split(variable).join(datasource.entityName);
|
||||
} else if (variableName === 'deviceName') {
|
||||
label = label.split(variable).join(datasource.entityName);
|
||||
} else if (variableName === 'aliasName') {
|
||||
label = label.split(variable).join(datasource.aliasName);
|
||||
}
|
||||
match = varsRegex.exec(pattern);
|
||||
}
|
||||
dataKey.label = label;
|
||||
}
|
||||
|
||||
function updateDatasourceKeyLabels(datasource) {
|
||||
for (var dk = 0; dk < datasource.dataKeys.length; dk++) {
|
||||
updateDataKeyLabel(datasource.dataKeys[dk], datasource);
|
||||
}
|
||||
}
|
||||
|
||||
var deferred = this.$q.defer();
|
||||
var newDatasources = angular.copy(datasources);
|
||||
var datasorceResolveTasks = [];
|
||||
var aliasCtrl = this;
|
||||
newDatasources.forEach(function (datasource) {
|
||||
var resolveDatasourceTask = aliasCtrl.resolveDatasource(datasource);
|
||||
datasorceResolveTasks.push(resolveDatasourceTask);
|
||||
});
|
||||
this.$q.all(datasorceResolveTasks).then(
|
||||
function success(datasourcesArrays) {
|
||||
var datasources = [].concat.apply([], datasourcesArrays);
|
||||
datasources = aliasCtrl.$filter('orderBy')(datasources, '+generated');
|
||||
var index = 0;
|
||||
var functionIndex = 0;
|
||||
datasources.forEach(function(datasource) {
|
||||
if (datasource.type === aliasCtrl.types.datasourceType.function) {
|
||||
var name;
|
||||
if (datasource.name && datasource.name.length) {
|
||||
name = datasource.name;
|
||||
} else {
|
||||
functionIndex++;
|
||||
name = aliasCtrl.types.datasourceType.function;
|
||||
if (functionIndex > 1) {
|
||||
name += ' ' + functionIndex;
|
||||
}
|
||||
}
|
||||
datasource.name = name;
|
||||
datasource.aliasName = name;
|
||||
datasource.entityName = name;
|
||||
}
|
||||
datasource.dataKeys.forEach(function(dataKey) {
|
||||
if (datasource.generated) {
|
||||
dataKey._hash = Math.random();
|
||||
dataKey.color = aliasCtrl.utils.getMaterialColor(index);
|
||||
}
|
||||
index++;
|
||||
});
|
||||
updateDatasourceKeyLabels(datasource);
|
||||
});
|
||||
deferred.resolve(datasources);
|
||||
},
|
||||
function fail() {
|
||||
deferred.reject();
|
||||
}
|
||||
);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
getInstantAliasInfo(aliasId) {
|
||||
return this.resolvedAliases[aliasId];
|
||||
}
|
||||
|
||||
updateCurrentAliasEntity(aliasId, currentEntity) {
|
||||
var aliasInfo = this.resolvedAliases[aliasId];
|
||||
if (aliasInfo) {
|
||||
var prevCurrentEntity = aliasInfo.currentEntity;
|
||||
if (!angular.equals(currentEntity, prevCurrentEntity)) {
|
||||
aliasInfo.currentEntity = currentEntity;
|
||||
this.$scope.$broadcast('entityAliasesChanged', [aliasId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -27,10 +27,13 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
|
||||
getEntity: getEntity,
|
||||
getEntities: getEntities,
|
||||
getEntitiesByNameFilter: getEntitiesByNameFilter,
|
||||
processEntityAliases: processEntityAliases,
|
||||
resolveAlias: resolveAlias,
|
||||
resolveAliasFilter: resolveAliasFilter,
|
||||
filterAliasByEntityTypes: filterAliasByEntityTypes,
|
||||
//processEntityAliases: processEntityAliases,
|
||||
getEntityKeys: getEntityKeys,
|
||||
checkEntityAlias: checkEntityAlias,
|
||||
createDatasoucesFromSubscriptionsInfo: createDatasoucesFromSubscriptionsInfo,
|
||||
createDatasourcesFromSubscriptionsInfo: createDatasourcesFromSubscriptionsInfo,
|
||||
getRelatedEntities: getRelatedEntities,
|
||||
saveRelatedEntity: saveRelatedEntity,
|
||||
getRelatedEntity: getRelatedEntity,
|
||||
@ -244,81 +247,151 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function entityToEntityInfo(entityType, entity) {
|
||||
return { name: entity.name, entityType: entityType, id: entity.id.id };
|
||||
function entityToEntityInfo(entity) {
|
||||
return { name: entity.name, entityType: entity.id.entityType, id: entity.id.id };
|
||||
}
|
||||
|
||||
function entitiesToEntitiesInfo(entityType, entities) {
|
||||
function entitiesToEntitiesInfo(entities) {
|
||||
var entitiesInfo = [];
|
||||
for (var d = 0; d < entities.length; d++) {
|
||||
entitiesInfo.push(entityToEntityInfo(entityType, entities[d]));
|
||||
entitiesInfo.push(entityToEntityInfo(entities[d]));
|
||||
}
|
||||
return entitiesInfo;
|
||||
}
|
||||
|
||||
function processEntityAlias(index, aliasIds, entityAliases, resolution, deferred) {
|
||||
function resolveAliasFilter(filter, stateParams) {
|
||||
var deferred = $q.defer();
|
||||
var result = {
|
||||
entities: [],
|
||||
stateEntity: false
|
||||
};
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
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();
|
||||
}
|
||||
);
|
||||
}
|
||||
break;
|
||||
case types.aliasFilterType.entityName.value:
|
||||
getEntitiesByNameFilter(filter.entityType, filter.entityNameFilter, 100).then(
|
||||
function success(entities) {
|
||||
if (entities && entities.length) {
|
||||
result.entities = entities;
|
||||
deferred.resolve(result);
|
||||
} else {
|
||||
deferred.reject();
|
||||
}
|
||||
},
|
||||
function fail() {
|
||||
deferred.reject();
|
||||
}
|
||||
);
|
||||
break;
|
||||
//TODO:
|
||||
}
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function resolveAlias(entityAlias, stateParams) {
|
||||
var deferred = $q.defer();
|
||||
var filter = entityAlias.filter;
|
||||
resolveAliasFilter(filter, stateParams).then(
|
||||
function (result) {
|
||||
var entities = result.entities;
|
||||
var aliasInfo = {
|
||||
alias: entityAlias.alias,
|
||||
resolveMultiple: filter.resolveMultiple
|
||||
};
|
||||
var resolvedEntities = entitiesToEntitiesInfo(entities);
|
||||
aliasInfo.resolvedEntities = resolvedEntities;
|
||||
aliasInfo.currentEntity = null;
|
||||
if (aliasInfo.resolvedEntities.length) {
|
||||
aliasInfo.currentEntity = aliasInfo.resolvedEntities[0];
|
||||
}
|
||||
deferred.resolve(aliasInfo);
|
||||
},
|
||||
function fail() {
|
||||
deferred.reject();
|
||||
}
|
||||
);
|
||||
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 {
|
||||
return entityTypes.indexOf(filter.entityType) > -1 ? true : false;
|
||||
}
|
||||
case types.aliasFilterType.entityName.value:
|
||||
return entityTypes.indexOf(filter.entityType) > -1 ? true : false;
|
||||
}
|
||||
//TODO:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*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 entityFilter = entityAlias.entityFilter;
|
||||
if (entityFilter.useFilter) {
|
||||
var entityNameFilter = entityFilter.entityNameFilter;
|
||||
getEntitiesByNameFilter(entityAlias.entityType, entityNameFilter, 100).then(
|
||||
function(entities) {
|
||||
if (entities && entities != null) {
|
||||
var resolvedAlias = {alias: alias, entityType: entityAlias.entityType, entityId: entities[0].id.id};
|
||||
resolution.aliasesInfo.entityAliases[aliasId] = resolvedAlias;
|
||||
resolution.aliasesInfo.entityAliasesInfo[aliasId] = entitiesToEntitiesInfo(entityAlias.entityType, entities);
|
||||
index++;
|
||||
processEntityAlias(index, aliasIds, entityAliases, resolution, deferred);
|
||||
} else {
|
||||
if (!resolution.error) {
|
||||
resolution.error = 'dashboard.invalid-aliases-config';
|
||||
}
|
||||
index++;
|
||||
processEntityAlias(index, aliasIds, entityAliases, resolution, deferred);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var entityList = entityFilter.entityList;
|
||||
getEntities(entityAlias.entityType, entityList).then(
|
||||
function success(entities) {
|
||||
if (entities && entities.length > 0) {
|
||||
var resolvedAlias = {alias: alias, entityType: entityAlias.entityType, entityId: entities[0].id.id};
|
||||
resolution.aliasesInfo.entityAliases[aliasId] = resolvedAlias;
|
||||
resolution.aliasesInfo.entityAliasesInfo[aliasId] = entitiesToEntitiesInfo(entityAlias.entityType, entities);
|
||||
index++;
|
||||
processEntityAlias(index, aliasIds, entityAliases, resolution, deferred);
|
||||
} else {
|
||||
if (!resolution.error) {
|
||||
resolution.error = 'dashboard.invalid-aliases-config';
|
||||
}
|
||||
index++;
|
||||
processEntityAlias(index, aliasIds, entityAliases, resolution, deferred);
|
||||
}
|
||||
},
|
||||
function fail() {
|
||||
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, resolution, deferred);
|
||||
processEntityAlias(index, aliasIds, entityAliases, stateParams, resolution, deferred);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
deferred.resolve(resolution);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
function processEntityAliases(entityAliases) {
|
||||
/*function processEntityAliases(entityAliases, stateParams) {
|
||||
var deferred = $q.defer();
|
||||
var resolution = {
|
||||
aliasesInfo: {
|
||||
entityAliases: {},
|
||||
entityAliasesInfo: {}
|
||||
}
|
||||
aliasesInfo: {}
|
||||
};
|
||||
var aliasIds = [];
|
||||
if (entityAliases) {
|
||||
@ -326,9 +399,9 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
|
||||
aliasIds.push(aliasId);
|
||||
}
|
||||
}
|
||||
processEntityAlias(0, aliasIds, entityAliases, resolution, deferred);
|
||||
processEntityAlias(0, aliasIds, entityAliases, stateParams, resolution, deferred);
|
||||
return deferred.promise;
|
||||
}
|
||||
}*/
|
||||
|
||||
function getEntityKeys(entityType, entityId, query, type) {
|
||||
var deferred = $q.defer();
|
||||
@ -354,8 +427,8 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
|
||||
}
|
||||
}
|
||||
deferred.resolve(result);
|
||||
}, function fail(response) {
|
||||
deferred.reject(response.data);
|
||||
}, function fail() {
|
||||
deferred.reject();
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
@ -387,7 +460,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function createDatasoucesFromSubscriptionsInfo(subscriptionsInfo) {
|
||||
function createDatasourcesFromSubscriptionsInfo(subscriptionsInfo) {
|
||||
var deferred = $q.defer();
|
||||
var datasources = [];
|
||||
processSubscriptionsInfo(0, subscriptionsInfo, datasources, deferred);
|
||||
|
||||
@ -39,6 +39,9 @@ export default class Subscription {
|
||||
this.cafs = {};
|
||||
this.registrations = [];
|
||||
|
||||
var subscription = this;
|
||||
var deferred = this.ctx.$q.defer();
|
||||
|
||||
if (this.type === this.ctx.types.widgetType.rpc.value) {
|
||||
this.callbacks.rpcStateChanged = this.callbacks.rpcStateChanged || function(){};
|
||||
this.callbacks.onRpcSuccess = this.callbacks.onRpcSuccess || function(){};
|
||||
@ -56,7 +59,11 @@ export default class Subscription {
|
||||
this.rpcEnabled = false;
|
||||
this.executingRpcRequest = false;
|
||||
this.executingPromises = [];
|
||||
this.initRpc();
|
||||
this.initRpc().then(
|
||||
function() {
|
||||
deferred.resolve(subscription);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this.callbacks.onDataUpdated = this.callbacks.onDataUpdated || function(){};
|
||||
this.callbacks.onDataUpdateError = this.callbacks.onDataUpdateError || function(){};
|
||||
@ -103,11 +110,36 @@ export default class Subscription {
|
||||
this.legendConfig.showMax === true ||
|
||||
this.legendConfig.showAvg === true ||
|
||||
this.legendConfig.showTotal === true);
|
||||
this.initDataSubscription();
|
||||
this.initDataSubscription().then(
|
||||
function success() {
|
||||
deferred.resolve(subscription);
|
||||
},
|
||||
function fail() {
|
||||
deferred.reject();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
initDataSubscription() {
|
||||
var deferred = this.ctx.$q.defer();
|
||||
var subscription = this;
|
||||
this.ctx.aliasController.resolveDatasources(this.datasources).then(
|
||||
function success(datasources) {
|
||||
subscription.datasources = datasources;
|
||||
subscription.configureData();
|
||||
deferred.resolve();
|
||||
},
|
||||
function fail() {
|
||||
deferred.reject();
|
||||
}
|
||||
);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
configureData() {
|
||||
var dataIndex = 0;
|
||||
for (var i = 0; i < this.datasources.length; i++) {
|
||||
var datasource = this.datasources[i];
|
||||
@ -199,21 +231,46 @@ export default class Subscription {
|
||||
}
|
||||
|
||||
initRpc() {
|
||||
var deferred = this.ctx.$q.defer();
|
||||
if (this.targetDeviceAliasIds && this.targetDeviceAliasIds.length > 0) {
|
||||
this.targetDeviceAliasId = this.targetDeviceAliasIds[0];
|
||||
if (this.ctx.aliasesInfo.entityAliases[this.targetDeviceAliasId]) {
|
||||
this.targetDeviceId = this.ctx.aliasesInfo.entityAliases[this.targetDeviceAliasId].entityId;
|
||||
var subscription = this;
|
||||
this.ctx.aliasController.getAliasInfo(this.targetDeviceAliasId).then(
|
||||
function success(aliasInfo) {
|
||||
if (aliasInfo.currentEntity && aliasInfo.currentEntity.entityType == subscription.ctx.types.entityType.device) {
|
||||
subscription.targetDeviceId = aliasInfo.currentEntity.id;
|
||||
if (subscription.targetDeviceId) {
|
||||
subscription.rpcEnabled = true;
|
||||
} else {
|
||||
subscription.rpcEnabled = subscription.ctx.$scope.widgetEditMode ? true : false;
|
||||
}
|
||||
subscription.callbacks.rpcStateChanged(this);
|
||||
deferred.resolve();
|
||||
} else {
|
||||
subscription.rpcEnabled = false;
|
||||
subscription.callbacks.rpcStateChanged(this);
|
||||
deferred.resolve();
|
||||
}
|
||||
},
|
||||
function fail () {
|
||||
subscription.rpcEnabled = false;
|
||||
subscription.callbacks.rpcStateChanged(this);
|
||||
deferred.resolve();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
if (this.targetDeviceIds && this.targetDeviceIds.length > 0) {
|
||||
this.targetDeviceId = this.targetDeviceIds[0];
|
||||
}
|
||||
} else if (this.targetDeviceIds && this.targetDeviceIds.length > 0) {
|
||||
this.targetDeviceId = this.targetDeviceIds[0];
|
||||
if (this.targetDeviceId) {
|
||||
this.rpcEnabled = true;
|
||||
} else {
|
||||
this.rpcEnabled = this.ctx.$scope.widgetEditMode ? true : false;
|
||||
}
|
||||
this.callbacks.rpcStateChanged(this);
|
||||
deferred.resolve();
|
||||
}
|
||||
|
||||
if (this.targetDeviceId) {
|
||||
this.rpcEnabled = true;
|
||||
} else {
|
||||
this.rpcEnabled = this.ctx.$scope.widgetEditMode ? true : false;
|
||||
}
|
||||
this.callbacks.rpcStateChanged(this);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
clearRpcError() {
|
||||
@ -319,11 +376,11 @@ export default class Subscription {
|
||||
this.onDataUpdated();
|
||||
}
|
||||
|
||||
onAliasesChanged() {
|
||||
onAliasesChanged(aliasIds) {
|
||||
if (this.type === this.ctx.types.widgetType.rpc.value) {
|
||||
this.checkRpcTarget();
|
||||
return this.checkRpcTarget(aliasIds);
|
||||
} else {
|
||||
this.checkSubscriptions();
|
||||
return this.checkSubscriptions(aliasIds);
|
||||
}
|
||||
}
|
||||
|
||||
@ -481,7 +538,7 @@ export default class Subscription {
|
||||
var datasource = this.datasources[i];
|
||||
if (angular.isFunction(datasource))
|
||||
continue;
|
||||
var entityId = null;
|
||||
/* var entityId = null;
|
||||
var entityType = null;
|
||||
if (datasource.type === this.ctx.types.datasourceType.entity) {
|
||||
var aliasName = null;
|
||||
@ -513,7 +570,7 @@ export default class Subscription {
|
||||
}
|
||||
for (var dk = 0; dk < datasource.dataKeys.length; dk++) {
|
||||
updateDataKeyLabel(datasource.dataKeys[dk], datasource.name, entityName, aliasName);
|
||||
}
|
||||
}*/
|
||||
|
||||
var subscription = this;
|
||||
|
||||
@ -521,8 +578,8 @@ export default class Subscription {
|
||||
subscriptionType: this.type,
|
||||
subscriptionTimewindow: this.subscriptionTimewindow,
|
||||
datasource: datasource,
|
||||
entityType: entityType,
|
||||
entityId: entityId,
|
||||
entityType: datasource.entityType,
|
||||
entityId: datasource.entityId,
|
||||
dataUpdated: function (data, datasourceIndex, dataKeyIndex, apply) {
|
||||
subscription.dataUpdated(data, datasourceIndex, dataKeyIndex, apply);
|
||||
},
|
||||
@ -557,8 +614,13 @@ export default class Subscription {
|
||||
}
|
||||
}
|
||||
|
||||
checkRpcTarget() {
|
||||
var deviceId = null;
|
||||
checkRpcTarget(aliasIds) {
|
||||
if (aliasIds.indexOf(this.targetDeviceAliasId) > -1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
/*var deviceId = null;
|
||||
if (this.ctx.aliasesInfo.entityAliases[this.targetDeviceAliasId]) {
|
||||
deviceId = this.ctx.aliasesInfo.entityAliases[this.targetDeviceAliasId].entityId;
|
||||
}
|
||||
@ -570,14 +632,20 @@ export default class Subscription {
|
||||
this.rpcEnabled = this.ctx.$scope.widgetEditMode ? true : false;
|
||||
}
|
||||
this.callbacks.rpcStateChanged(this);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
checkSubscriptions() {
|
||||
checkSubscriptions(aliasIds) {
|
||||
var subscriptionsChanged = false;
|
||||
for (var i = 0; i < this.datasourceListeners.length; i++) {
|
||||
var listener = this.datasourceListeners[i];
|
||||
var entityId = null;
|
||||
if (listener.datasource.entityAliasId) {
|
||||
if (aliasIds.indexOf(listener.datasource.entityAliasId) > -1) {
|
||||
subscriptionsChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*var entityId = null;
|
||||
var entityType = null;
|
||||
var aliasName = null;
|
||||
if (listener.datasource.type === this.ctx.types.datasourceType.entity) {
|
||||
@ -593,12 +661,13 @@ export default class Subscription {
|
||||
subscriptionsChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
if (subscriptionsChanged) {
|
||||
return subscriptionsChanged;
|
||||
/*if (subscriptionsChanged) {
|
||||
this.unsubscribe();
|
||||
this.subscribe();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
destroy() {
|
||||
@ -617,7 +686,7 @@ export default class Subscription {
|
||||
|
||||
}
|
||||
|
||||
const varsRegex = /\$\{([^\}]*)\}/g;
|
||||
/*const varsRegex = /\$\{([^\}]*)\}/g;
|
||||
|
||||
function updateDataKeyLabel(dataKey, dsName, entityName, aliasName) {
|
||||
var pattern = dataKey.pattern;
|
||||
@ -638,7 +707,7 @@ function updateDataKeyLabel(dataKey, dsName, entityName, aliasName) {
|
||||
match = varsRegex.exec(pattern);
|
||||
}
|
||||
dataKey.label = label;
|
||||
}
|
||||
}*/
|
||||
|
||||
function calculateMin(data) {
|
||||
if (data.length > 0) {
|
||||
|
||||
@ -40,39 +40,75 @@ function DashboardUtils(types, utils, timeService) {
|
||||
return service;
|
||||
|
||||
function validateAndUpdateEntityAliases(configuration) {
|
||||
var aliasId, entityAlias;
|
||||
if (angular.isUndefined(configuration.entityAliases)) {
|
||||
configuration.entityAliases = {};
|
||||
if (configuration.deviceAliases) {
|
||||
var deviceAliases = configuration.deviceAliases;
|
||||
for (var aliasId in deviceAliases) {
|
||||
for (aliasId in deviceAliases) {
|
||||
var deviceAlias = deviceAliases[aliasId];
|
||||
var alias = deviceAlias.alias;
|
||||
var entityFilter = {
|
||||
useFilter: false,
|
||||
entityNameFilter: '',
|
||||
entityList: []
|
||||
}
|
||||
if (deviceAlias.deviceFilter) {
|
||||
entityFilter.useFilter = deviceAlias.deviceFilter.useFilter;
|
||||
entityFilter.entityNameFilter = deviceAlias.deviceFilter.deviceNameFilter;
|
||||
entityFilter.entityList = deviceAlias.deviceFilter.deviceList;
|
||||
} else if (deviceAlias.deviceId) {
|
||||
entityFilter.entityList = [deviceAlias.deviceId];
|
||||
}
|
||||
var entityAlias = {
|
||||
id: aliasId,
|
||||
alias: alias,
|
||||
entityType: types.entityType.device,
|
||||
entityFilter: entityFilter
|
||||
};
|
||||
entityAlias = validateAndUpdateDeviceAlias(aliasId, deviceAlias);
|
||||
configuration.entityAliases[aliasId] = entityAlias;
|
||||
}
|
||||
delete configuration.deviceAliases;
|
||||
}
|
||||
} else {
|
||||
var entityAliases = configuration.entityAliases;
|
||||
for (aliasId in entityAliases) {
|
||||
entityAlias = entityAliases[aliasId];
|
||||
entityAliases[aliasId] = validateAndUpdateEntityAlias(entityAlias);
|
||||
}
|
||||
}
|
||||
return configuration;
|
||||
}
|
||||
|
||||
function validateAndUpdateDeviceAlias(aliasId, deviceAlias) {
|
||||
var alias = deviceAlias.alias;
|
||||
var entityAlias = {
|
||||
id: aliasId,
|
||||
alias: alias,
|
||||
filter: {
|
||||
type: null,
|
||||
entityType: types.entityType.device,
|
||||
resolveMultiple: false
|
||||
},
|
||||
}
|
||||
if (deviceAlias.deviceFilter) {
|
||||
entityAlias.filter.type =
|
||||
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;
|
||||
}
|
||||
|
||||
function validateAndUpdateEntityAlias(entityAlias) {
|
||||
if (!entityAlias.filter) {
|
||||
entityAlias.filter = {
|
||||
type: entityAlias.entityFilter.useFilter ? types.aliasFilterType.entityName.value : types.aliasFilterType.entityList.value,
|
||||
entityType: entityAlias.entityType,
|
||||
resolveMultiple: false
|
||||
}
|
||||
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;
|
||||
}
|
||||
delete entityAlias.entityType;
|
||||
delete entityAlias.entityFilter;
|
||||
}
|
||||
return entityAlias;
|
||||
}
|
||||
|
||||
function validateAndUpdateWidget(widget) {
|
||||
if (!widget.config) {
|
||||
widget.config = {};
|
||||
|
||||
@ -65,6 +65,36 @@ export default angular.module('thingsboard.types', [])
|
||||
clearedUnack: "CLEARED_UNACK",
|
||||
clearedAck: "CLEARED_ACK"
|
||||
},
|
||||
aliasFilterType: {
|
||||
entityList: {
|
||||
value: 'entityList',
|
||||
name: 'alias.filter-type-entity-list'
|
||||
},
|
||||
entityName: {
|
||||
value: 'entityName',
|
||||
name: 'alias.filter-type-entity-name'
|
||||
},
|
||||
assetType: {
|
||||
value: 'assetType',
|
||||
name: 'alias.filter-type-asset-type'
|
||||
},
|
||||
deviceType: {
|
||||
value: 'deviceType',
|
||||
name: 'alias.filter-type-device-type'
|
||||
},
|
||||
relationsQuery: {
|
||||
value: 'relationsQuery',
|
||||
name: 'alias.filter-type-relations-query'
|
||||
},
|
||||
assetSearchQuery: {
|
||||
value: 'assetSearchQuery',
|
||||
name: 'alias.filter-type-asset-search-query'
|
||||
},
|
||||
deviceSearchQuery: {
|
||||
value: 'deviceSearchQuery',
|
||||
name: 'alias.filter-type-device-search-query'
|
||||
}
|
||||
},
|
||||
position: {
|
||||
top: {
|
||||
value: "top",
|
||||
|
||||
@ -52,7 +52,7 @@ function Dashboard() {
|
||||
bindToController: {
|
||||
widgets: '=',
|
||||
widgetLayouts: '=?',
|
||||
aliasesInfo: '=',
|
||||
aliasController: '=',
|
||||
stateController: '=',
|
||||
dashboardTimewindow: '=?',
|
||||
columns: '=',
|
||||
@ -329,10 +329,6 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, t
|
||||
$scope.$broadcast('toggleDashboardEditMode', vm.isEdit);
|
||||
});
|
||||
|
||||
$scope.$watch('vm.aliasesInfo.entityAliases', function () {
|
||||
$scope.$broadcast('entityAliasListChanged', vm.aliasesInfo);
|
||||
}, true);
|
||||
|
||||
$scope.$on('gridster-resized', function (event, sizes, theGridster) {
|
||||
if (checkIsLocalGridsterElement(theGridster)) {
|
||||
vm.gridster = theGridster;
|
||||
|
||||
@ -89,7 +89,7 @@
|
||||
<div flex tb-widget
|
||||
locals="{ visibleRect: vm.visibleRect,
|
||||
widget: widget,
|
||||
aliasesInfo: vm.aliasesInfo,
|
||||
aliasController: vm.aliasController,
|
||||
stateController: vm.stateController,
|
||||
isEdit: vm.isEdit,
|
||||
stDiff: vm.stDiff,
|
||||
|
||||
@ -20,14 +20,14 @@ export default angular.module('thingsboard.dialogs.datakeyConfigDialog', [things
|
||||
.name;
|
||||
|
||||
/*@ngInject*/
|
||||
function DatakeyConfigDialogController($scope, $mdDialog, entityService, dataKey, dataKeySettingsSchema, entityAlias, entityAliases) {
|
||||
function DatakeyConfigDialogController($scope, $mdDialog, $q, entityService, dataKey, dataKeySettingsSchema, entityAlias, aliasController) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.dataKey = dataKey;
|
||||
vm.dataKeySettingsSchema = dataKeySettingsSchema;
|
||||
vm.entityAlias = entityAlias;
|
||||
vm.entityAliases = entityAliases;
|
||||
vm.aliasController = aliasController;
|
||||
|
||||
vm.hide = function () {
|
||||
$mdDialog.hide();
|
||||
@ -38,12 +38,28 @@ function DatakeyConfigDialogController($scope, $mdDialog, entityService, dataKey
|
||||
};
|
||||
|
||||
vm.fetchEntityKeys = function (entityAliasId, query, type) {
|
||||
var alias = vm.entityAliases[entityAliasId];
|
||||
if (alias) {
|
||||
return entityService.getEntityKeys(alias.entityType, alias.entityId, query, type);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
var deferred = $q.defer();
|
||||
vm.aliasController.getAliasInfo(entityAliasId).then(
|
||||
function success(aliasInfo) {
|
||||
var entity = aliasInfo.currentEntity;
|
||||
if (entity) {
|
||||
entityService.getEntityKeys(entity.entityType, entity.id, query, type).then(
|
||||
function success(keys) {
|
||||
deferred.resolve(keys);
|
||||
},
|
||||
function fail() {
|
||||
deferred.resolve([]);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
deferred.resolve([]);
|
||||
}
|
||||
},
|
||||
function fail() {
|
||||
deferred.resolve([]);
|
||||
}
|
||||
);
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
vm.save = function () {
|
||||
|
||||
@ -103,10 +103,9 @@ function DatasourceEntity($compile, $templateCache, $q, $mdDialog, $window, $doc
|
||||
ngModelCtrl.$render = function () {
|
||||
if (ngModelCtrl.$viewValue) {
|
||||
var entityAliasId = ngModelCtrl.$viewValue.entityAliasId;
|
||||
if (scope.entityAliases[entityAliasId]) {
|
||||
scope.entityAlias = {id: entityAliasId, alias: scope.entityAliases[entityAliasId].alias,
|
||||
entityType: scope.entityAliases[entityAliasId].entityType,
|
||||
entityId: scope.entityAliases[entityAliasId].entityId};
|
||||
var entityAliases = scope.aliasController.getEntityAliases();
|
||||
if (entityAliases[entityAliasId]) {
|
||||
scope.entityAlias = entityAliases[entityAliasId];
|
||||
} else {
|
||||
scope.entityAlias = null;
|
||||
}
|
||||
@ -182,7 +181,7 @@ function DatasourceEntity($compile, $templateCache, $q, $mdDialog, $window, $doc
|
||||
dataKey: angular.copy(dataKey),
|
||||
dataKeySettingsSchema: scope.datakeySettingsSchema,
|
||||
entityAlias: scope.entityAlias,
|
||||
entityAliases: scope.entityAliases
|
||||
aliasController: scope.aliasController
|
||||
},
|
||||
parent: angular.element($document[0].body),
|
||||
fullscreen: true,
|
||||
@ -236,7 +235,7 @@ function DatasourceEntity($compile, $templateCache, $q, $mdDialog, $window, $doc
|
||||
require: "^ngModel",
|
||||
scope: {
|
||||
widgetType: '=',
|
||||
entityAliases: '=',
|
||||
aliasController: '=',
|
||||
datakeySettingsSchema: '=',
|
||||
generateDataKey: '&',
|
||||
fetchEntityKeys: '&',
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
<section flex layout='column' layout-align="center" layout-gt-sm='row' layout-align-gt-sm="start center">
|
||||
<tb-entity-alias-select
|
||||
tb-required="true"
|
||||
entity-aliases="entityAliases"
|
||||
alias-controller="aliasController"
|
||||
ng-model="entityAlias"
|
||||
on-create-entity-alias="onCreateEntityAlias({event: event, alias: alias})">
|
||||
</tb-entity-alias-select>
|
||||
|
||||
@ -76,7 +76,7 @@ function Datasource($compile, $templateCache, types) {
|
||||
restrict: "E",
|
||||
require: "^ngModel",
|
||||
scope: {
|
||||
entityAliases: '=',
|
||||
aliasController: '=',
|
||||
widgetType: '=',
|
||||
functionsOnly: '=',
|
||||
datakeySettingsSchema: '=',
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
ng-switch-when="entity"
|
||||
ng-required="model.type === types.datasourceType.entity"
|
||||
widget-type="widgetType"
|
||||
entity-aliases="entityAliases"
|
||||
alias-controller="aliasController"
|
||||
generate-data-key="generateDataKey({chip: chip, type: type})"
|
||||
fetch-entity-keys="fetchEntityKeys({entityAliasId: entityAliasId, query: query, type: type})"
|
||||
on-create-entity-alias="onCreateEntityAlias({event: event, alias: alias})">
|
||||
|
||||
@ -31,7 +31,7 @@ export default angular.module('thingsboard.directives.entityAliasSelect', [])
|
||||
.name;
|
||||
|
||||
/*@ngInject*/
|
||||
function EntityAliasSelect($compile, $templateCache, $mdConstant) {
|
||||
function EntityAliasSelect($compile, $templateCache, $mdConstant, entityService) {
|
||||
|
||||
var linker = function (scope, element, attrs, ngModelCtrl) {
|
||||
var template = $templateCache.get(entityAliasSelectTemplate);
|
||||
@ -49,19 +49,18 @@ function EntityAliasSelect($compile, $templateCache, $mdConstant) {
|
||||
ngModelCtrl.$setValidity('entityAlias', valid);
|
||||
};
|
||||
|
||||
scope.$watch('entityAliases', function () {
|
||||
scope.$watch('aliasController', function () {
|
||||
scope.entityAliasList = [];
|
||||
for (var aliasId in scope.entityAliases) {
|
||||
var entityAliases = scope.aliasController.getEntityAliases();
|
||||
for (var aliasId in entityAliases) {
|
||||
if (scope.allowedEntityTypes) {
|
||||
if (scope.allowedEntityTypes.indexOf(scope.entityAliases[aliasId].entityType) === -1) {
|
||||
if (!entityService.filterAliasByEntityTypes(entityAliases[aliasId], scope.allowedEntityTypes)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
var entityAlias = {id: aliasId, alias: scope.entityAliases[aliasId].alias,
|
||||
entityType: scope.entityAliases[aliasId].entityType, entityId: scope.entityAliases[aliasId].entityId};
|
||||
scope.entityAliasList.push(entityAlias);
|
||||
scope.entityAliasList.push(entityAliases[aliasId]);
|
||||
}
|
||||
}, true);
|
||||
});
|
||||
|
||||
scope.$watch('entityAlias', function () {
|
||||
scope.updateView();
|
||||
@ -141,7 +140,7 @@ function EntityAliasSelect($compile, $templateCache, $mdConstant) {
|
||||
link: linker,
|
||||
scope: {
|
||||
tbRequired: '=?',
|
||||
entityAliases: '=',
|
||||
aliasController: '=',
|
||||
allowedEntityTypes: '=?',
|
||||
onCreateEntityAlias: '&'
|
||||
}
|
||||
|
||||
@ -128,13 +128,9 @@ function WidgetConfig($compile, $templateCache, $rootScope, $timeout, types, uti
|
||||
} else if (scope.widgetType === types.widgetType.rpc.value && scope.isDataEnabled) {
|
||||
if (config.targetDeviceAliasIds && config.targetDeviceAliasIds.length > 0) {
|
||||
var aliasId = config.targetDeviceAliasIds[0];
|
||||
if (scope.entityAliases[aliasId]) {
|
||||
scope.targetDeviceAlias.value = {
|
||||
id: aliasId,
|
||||
alias: scope.entityAliases[aliasId].alias,
|
||||
entityType: scope.entityAliases[aliasId].entityType,
|
||||
entityId: scope.entityAliases[aliasId].entityId
|
||||
};
|
||||
var entityAliases = scope.aliasController.getEntityAliases();
|
||||
if (entityAliases[aliasId]) {
|
||||
scope.targetDeviceAlias.value = entityAliases[aliasId];
|
||||
} else {
|
||||
scope.targetDeviceAlias.value = null;
|
||||
}
|
||||
@ -395,7 +391,7 @@ function WidgetConfig($compile, $templateCache, $rootScope, $timeout, types, uti
|
||||
widgetType: '=',
|
||||
widgetSettingsSchema: '=',
|
||||
datakeySettingsSchema: '=',
|
||||
entityAliases: '=',
|
||||
aliasController: '=',
|
||||
functionsOnly: '=',
|
||||
fetchEntityKeys: '&',
|
||||
onCreateEntityAlias: '&',
|
||||
|
||||
@ -60,7 +60,7 @@
|
||||
style="padding: 0 0 0 10px; margin: 5px;">
|
||||
<tb-datasource flex ng-model="datasource.value"
|
||||
widget-type="widgetType"
|
||||
entity-aliases="entityAliases"
|
||||
alias-controller="aliasController"
|
||||
functions-only="functionsOnly"
|
||||
datakey-settings-schema="datakeySettingsSchema"
|
||||
generate-data-key="generateDataKey(chip,type)"
|
||||
@ -104,7 +104,7 @@
|
||||
<v-pane-content style="padding: 0 5px;">
|
||||
<tb-entity-alias-select flex
|
||||
tb-required="widgetType === types.widgetType.rpc.value && !widgetEditMode"
|
||||
entity-aliases="entityAliases"
|
||||
alias-controller="aliasController"
|
||||
allowed-entity-types="[types.entityType.device]"
|
||||
ng-model="targetDeviceAlias.value"
|
||||
on-create-entity-alias="onCreateEntityAlias({event: event, alias: alias, allowedEntityTypes: allowedEntityTypes})">
|
||||
|
||||
@ -22,7 +22,7 @@ import Subscription from '../api/subscription';
|
||||
/*@ngInject*/
|
||||
export default function WidgetController($scope, $timeout, $window, $element, $q, $log, $injector, $filter, tbRaf, types, utils, timeService,
|
||||
datasourceService, entityService, deviceService, visibleRect, isEdit, stDiff, dashboardTimewindow,
|
||||
dashboardTimewindowApi, widget, aliasesInfo, stateController, widgetType) {
|
||||
dashboardTimewindowApi, widget, aliasController, stateController, widgetType) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
@ -37,6 +37,7 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
|
||||
$scope.executingRpcRequest = false;
|
||||
|
||||
var gridsterItemInited = false;
|
||||
var subscriptionInited = false;
|
||||
|
||||
var cafs = {};
|
||||
|
||||
@ -149,7 +150,7 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
|
||||
dashboardTimewindowApi: dashboardTimewindowApi,
|
||||
types: types,
|
||||
stDiff: stDiff,
|
||||
aliasesInfo: aliasesInfo
|
||||
aliasController: aliasController
|
||||
};
|
||||
|
||||
var widgetTypeInstance;
|
||||
@ -203,8 +204,13 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
|
||||
|
||||
vm.gridsterItemInitialized = gridsterItemInitialized;
|
||||
|
||||
initialize();
|
||||
|
||||
initialize().then(
|
||||
function(){
|
||||
if (checkSize()) {
|
||||
onInit();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/*
|
||||
options = {
|
||||
@ -233,28 +239,42 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
|
||||
}
|
||||
}
|
||||
|
||||
entityService.createDatasoucesFromSubscriptionsInfo(subscriptionsInfo).then(
|
||||
entityService.createDatasourcesFromSubscriptionsInfo(subscriptionsInfo).then(
|
||||
function (datasources) {
|
||||
options.datasources = datasources;
|
||||
var subscription = createSubscription(options, subscribe);
|
||||
if (useDefaultComponents) {
|
||||
defaultSubscriptionOptions(subscription, options);
|
||||
}
|
||||
deferred.resolve(subscription);
|
||||
createSubscription(options, subscribe).then(
|
||||
function success(subscription) {
|
||||
if (useDefaultComponents) {
|
||||
defaultSubscriptionOptions(subscription, options);
|
||||
}
|
||||
deferred.resolve(subscription);
|
||||
},
|
||||
function fail() {
|
||||
deferred.reject();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function createSubscription(options, subscribe) {
|
||||
var deferred = $q.defer();
|
||||
options.dashboardTimewindow = dashboardTimewindow;
|
||||
var subscription =
|
||||
new Subscription(subscriptionContext, options);
|
||||
widgetContext.subscriptions[subscription.id] = subscription;
|
||||
if (subscribe) {
|
||||
subscription.subscribe();
|
||||
}
|
||||
return subscription;
|
||||
new Subscription(subscriptionContext, options).then(
|
||||
function success(subscription) {
|
||||
widgetContext.subscriptions[subscription.id] = subscription;
|
||||
if (subscribe) {
|
||||
subscription.subscribe();
|
||||
}
|
||||
deferred.resolve(subscription);
|
||||
},
|
||||
function fail() {
|
||||
deferred.reject();
|
||||
}
|
||||
);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function defaultComponentsOptions(options) {
|
||||
@ -310,8 +330,8 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
|
||||
}
|
||||
|
||||
function createDefaultSubscription() {
|
||||
var subscription;
|
||||
var options;
|
||||
var deferred = $q.defer();
|
||||
if (widget.type !== types.widgetType.rpc.value && widget.type !== types.widgetType.static.value) {
|
||||
options = {
|
||||
type: widget.type,
|
||||
@ -319,16 +339,23 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
|
||||
};
|
||||
defaultComponentsOptions(options);
|
||||
|
||||
subscription = createSubscription(options);
|
||||
createSubscription(options).then(
|
||||
function success(subscription) {
|
||||
defaultSubscriptionOptions(subscription, options);
|
||||
|
||||
defaultSubscriptionOptions(subscription, options);
|
||||
// backward compatibility
|
||||
|
||||
// backward compatibility
|
||||
|
||||
widgetContext.datasources = subscription.datasources;
|
||||
widgetContext.data = subscription.data;
|
||||
widgetContext.hiddenData = subscription.hiddenData;
|
||||
widgetContext.timeWindow = subscription.timeWindow;
|
||||
widgetContext.datasources = subscription.datasources;
|
||||
widgetContext.data = subscription.data;
|
||||
widgetContext.hiddenData = subscription.hiddenData;
|
||||
widgetContext.timeWindow = subscription.timeWindow;
|
||||
widgetContext.defaultSubscription = subscription;
|
||||
deferred.resolve();
|
||||
},
|
||||
function fail() {
|
||||
deferred.reject();
|
||||
}
|
||||
);
|
||||
|
||||
} else if (widget.type === types.widgetType.rpc.value) {
|
||||
$scope.loadingData = false;
|
||||
@ -356,24 +383,27 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
|
||||
$scope.rpcRejection = null;
|
||||
}
|
||||
}
|
||||
subscription = createSubscription(options);
|
||||
createSubscription(options).then(
|
||||
function success(subscription) {
|
||||
widgetContext.defaultSubscription = subscription;
|
||||
deferred.resolve();
|
||||
},
|
||||
function fail() {
|
||||
deferred.reject();
|
||||
}
|
||||
);
|
||||
} else if (widget.type === types.widgetType.static.value) {
|
||||
$scope.loadingData = false;
|
||||
deferred.resolve();
|
||||
} else {
|
||||
deferred.resolve();
|
||||
}
|
||||
if (subscription) {
|
||||
widgetContext.defaultSubscription = subscription;
|
||||
}
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
|
||||
function initialize() {
|
||||
|
||||
if (!vm.useCustomDatasources) {
|
||||
createDefaultSubscription();
|
||||
} else {
|
||||
$scope.loadingData = false;
|
||||
}
|
||||
|
||||
$scope.$on('toggleDashboardEditMode', function (event, isEdit) {
|
||||
onEditModeChanged(isEdit);
|
||||
});
|
||||
@ -398,11 +428,14 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
|
||||
onMobileModeChanged(newIsMobile);
|
||||
});
|
||||
|
||||
$scope.$on('entityAliasListChanged', function (event, aliasesInfo) {
|
||||
subscriptionContext.aliasesInfo = aliasesInfo;
|
||||
$scope.$on('entityAliasesChanged', function (event, aliasIds) {
|
||||
var subscriptionChanged = false;
|
||||
for (var id in widgetContext.subscriptions) {
|
||||
var subscription = widgetContext.subscriptions[id];
|
||||
subscription.onAliasesChanged();
|
||||
subscriptionChanged = subscriptionChanged || subscription.onAliasesChanged(aliasIds);
|
||||
}
|
||||
if (subscriptionChanged && !vm.useCustomDatasources) {
|
||||
reInit();
|
||||
}
|
||||
});
|
||||
|
||||
@ -410,6 +443,44 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
|
||||
removeResizeListener(widgetContext.$containerParent[0], onResize); // eslint-disable-line no-undef
|
||||
onDestroy();
|
||||
});
|
||||
|
||||
var deferred = $q.defer();
|
||||
if (!vm.useCustomDatasources) {
|
||||
createDefaultSubscription().then(
|
||||
function success() {
|
||||
subscriptionInited = true;
|
||||
deferred.resolve();
|
||||
},
|
||||
function fail() {
|
||||
subscriptionInited = true;
|
||||
deferred.reject();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$scope.loadingData = false;
|
||||
subscriptionInited = true;
|
||||
deferred.resolve();
|
||||
}
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function reInit() {
|
||||
onDestroy();
|
||||
if (!vm.useCustomDatasources) {
|
||||
createDefaultSubscription().then(
|
||||
function success() {
|
||||
subscriptionInited = true;
|
||||
onInit();
|
||||
},
|
||||
function fail() {
|
||||
subscriptionInited = true;
|
||||
onInit();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
subscriptionInited = true;
|
||||
onInit();
|
||||
}
|
||||
}
|
||||
|
||||
function handleWidgetException(e) {
|
||||
@ -418,7 +489,9 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
|
||||
}
|
||||
|
||||
function onInit() {
|
||||
if (!widgetContext.inited) {
|
||||
if (!widgetContext.inited &&
|
||||
subscriptionInited &&
|
||||
gridsterItemInited) {
|
||||
widgetContext.inited = true;
|
||||
try {
|
||||
widgetTypeInstance.onInit();
|
||||
@ -462,7 +535,7 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
|
||||
handleWidgetException(e);
|
||||
}
|
||||
});
|
||||
} else if (gridsterItemInited) {
|
||||
} else {
|
||||
onInit();
|
||||
}
|
||||
}
|
||||
@ -544,6 +617,7 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
|
||||
var subscription = widgetContext.subscriptions[id];
|
||||
subscription.destroy();
|
||||
}
|
||||
subscriptionInited = false;
|
||||
widgetContext.subscriptions = [];
|
||||
if (widgetContext.inited) {
|
||||
widgetContext.inited = false;
|
||||
|
||||
@ -20,12 +20,13 @@ import entityAliasesTemplate from '../entity/entity-aliases.tpl.html';
|
||||
/* eslint-enable import/no-unresolved, import/default */
|
||||
|
||||
/*@ngInject*/
|
||||
export default function AddWidgetController($scope, widgetService, entityService, $mdDialog, $q, $document, types, dashboard, aliasesInfo, widget, widgetInfo) {
|
||||
export default function AddWidgetController($scope, widgetService, entityService, $mdDialog, $q, $document, types, dashboard,
|
||||
aliasController, widget, widgetInfo) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.dashboard = dashboard;
|
||||
vm.aliasesInfo = aliasesInfo;
|
||||
vm.aliasController = aliasController;
|
||||
vm.widget = widget;
|
||||
vm.widgetInfo = widgetInfo;
|
||||
|
||||
@ -85,7 +86,7 @@ export default function AddWidgetController($scope, widgetService, entityService
|
||||
}
|
||||
|
||||
function cancel () {
|
||||
$mdDialog.cancel({aliasesInfo: vm.aliasesInfo});
|
||||
$mdDialog.cancel();
|
||||
}
|
||||
|
||||
function add () {
|
||||
@ -94,23 +95,39 @@ export default function AddWidgetController($scope, widgetService, entityService
|
||||
vm.widget.config = vm.widgetConfig.config;
|
||||
vm.widget.config.mobileOrder = vm.widgetConfig.layout.mobileOrder;
|
||||
vm.widget.config.mobileHeight = vm.widgetConfig.layout.mobileHeight;
|
||||
$mdDialog.hide({widget: vm.widget, aliasesInfo: vm.aliasesInfo});
|
||||
$mdDialog.hide({widget: vm.widget});
|
||||
}
|
||||
}
|
||||
|
||||
function fetchEntityKeys (entityAliasId, query, type) {
|
||||
var entityAlias = vm.aliasesInfo.entityAliases[entityAliasId];
|
||||
if (entityAlias && entityAlias.entityId) {
|
||||
return entityService.getEntityKeys(entityAlias.entityType, entityAlias.entityId, query, type);
|
||||
} else {
|
||||
return $q.when([]);
|
||||
}
|
||||
var deferred = $q.defer();
|
||||
vm.aliasController.getAliasInfo(entityAliasId).then(
|
||||
function success(aliasInfo) {
|
||||
var entity = aliasInfo.currentEntity;
|
||||
if (entity) {
|
||||
entityService.getEntityKeys(entity.entityType, entity.id, query, type).then(
|
||||
function success(keys) {
|
||||
deferred.resolve(keys);
|
||||
},
|
||||
function fail() {
|
||||
deferred.resolve([]);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
deferred.resolve([]);
|
||||
}
|
||||
},
|
||||
function fail() {
|
||||
deferred.resolve([]);
|
||||
}
|
||||
);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function createEntityAlias (event, alias, allowedEntityTypes) {
|
||||
|
||||
var deferred = $q.defer();
|
||||
var singleEntityAlias = {id: null, alias: alias, entityType: types.entityType.device, entityFilter: null};
|
||||
var singleEntityAlias = {id: null, alias: alias, filter: {}};
|
||||
|
||||
$mdDialog.show({
|
||||
controller: 'EntityAliasesController',
|
||||
@ -130,16 +147,9 @@ export default function AddWidgetController($scope, widgetService, entityService
|
||||
skipHide: true,
|
||||
targetEvent: event
|
||||
}).then(function (singleEntityAlias) {
|
||||
vm.dashboard.configuration.entityAliases[singleEntityAlias.id] =
|
||||
{ alias: singleEntityAlias.alias, entityType: singleEntityAlias.entityType, entityFilter: singleEntityAlias.entityFilter };
|
||||
entityService.processEntityAliases(vm.dashboard.configuration.entityAliases).then(
|
||||
function(resolution) {
|
||||
if (!resolution.error) {
|
||||
vm.aliasesInfo = resolution.aliasesInfo;
|
||||
}
|
||||
deferred.resolve(singleEntityAlias);
|
||||
}
|
||||
);
|
||||
vm.dashboard.configuration.entityAliases[singleEntityAlias.id] = singleEntityAlias;
|
||||
vm.aliasController.updateEntityAliases(vm.dashboard.configuration.entityAliases);
|
||||
deferred.resolve(singleEntityAlias);
|
||||
}, function () {
|
||||
deferred.reject();
|
||||
});
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
ng-model="vm.widgetConfig"
|
||||
widget-settings-schema="vm.settingsSchema"
|
||||
datakey-settings-schema="vm.dataKeySettingsSchema"
|
||||
entity-aliases="vm.aliasesInfo.entityAliases"
|
||||
alias-controller="vm.aliasController"
|
||||
functions-only="vm.functionsOnly"
|
||||
fetch-entity-keys="vm.fetchEntityKeys(entityAliasId, query, type)"
|
||||
on-create-entity-alias="vm.createEntityAlias(event, alias, allowedEntityTypes)"
|
||||
|
||||
@ -24,8 +24,10 @@ import selectTargetLayoutTemplate from './layouts/select-target-layout.tpl.html'
|
||||
|
||||
/* eslint-enable import/no-unresolved, import/default */
|
||||
|
||||
import AliasController from '../api/alias-controller';
|
||||
|
||||
/*@ngInject*/
|
||||
export default function DashboardController(types, dashboardUtils, widgetService, userService,
|
||||
export default function DashboardController(types, utils, dashboardUtils, widgetService, userService,
|
||||
dashboardService, timeService, entityService, itembuffer, importExport, hotkeys, $window, $rootScope,
|
||||
$scope, $element, $state, $stateParams, $mdDialog, $mdMedia, $timeout, $document, $q, $translate, $filter) {
|
||||
|
||||
@ -349,7 +351,13 @@ export default function DashboardController(types, dashboardUtils, widgetService
|
||||
dashboardService.getDashboard($stateParams.dashboardId)
|
||||
.then(function success(dashboard) {
|
||||
vm.dashboard = dashboardUtils.validateAndUpdateDashboard(dashboard);
|
||||
entityService.processEntityAliases(vm.dashboard.configuration.entityAliases)
|
||||
vm.dashboardConfiguration = vm.dashboard.configuration;
|
||||
vm.dashboardCtx.dashboard = vm.dashboard;
|
||||
vm.dashboardCtx.dashboardTimewindow = vm.dashboardConfiguration.timewindow;
|
||||
vm.dashboardCtx.aliasController = new AliasController($scope, $q, $filter, utils,
|
||||
types, entityService, vm.dashboardCtx.stateController, vm.dashboardConfiguration.entityAliases);
|
||||
|
||||
/* entityService.processEntityAliases(vm.dashboard.configuration.entityAliases)
|
||||
.then(
|
||||
function(resolution) {
|
||||
if (resolution.error && !isTenantAdmin()) {
|
||||
@ -362,7 +370,7 @@ export default function DashboardController(types, dashboardUtils, widgetService
|
||||
vm.dashboardCtx.dashboardTimewindow = vm.dashboardConfiguration.timewindow;
|
||||
}
|
||||
}
|
||||
);
|
||||
);*/
|
||||
}, function fail() {
|
||||
vm.configurationError = true;
|
||||
});
|
||||
@ -373,6 +381,7 @@ export default function DashboardController(types, dashboardUtils, widgetService
|
||||
var layoutsData = dashboardUtils.getStateLayoutsData(vm.dashboard, state);
|
||||
if (layoutsData) {
|
||||
vm.dashboardCtx.state = state;
|
||||
vm.dashboardCtx.aliasController.dashboardStateChanged();
|
||||
var layoutVisibilityChanged = false;
|
||||
for (var l in vm.layouts) {
|
||||
var layout = vm.layouts[l];
|
||||
@ -916,7 +925,7 @@ export default function DashboardController(types, dashboardUtils, widgetService
|
||||
templateUrl: addWidgetTemplate,
|
||||
locals: {
|
||||
dashboard: vm.dashboard,
|
||||
aliasesInfo: vm.dashboardCtx.aliasesInfo,
|
||||
aliasController: vm.dashboardCtx.aliasController,
|
||||
widget: newWidget,
|
||||
widgetInfo: widgetTypeInfo
|
||||
},
|
||||
@ -930,10 +939,8 @@ export default function DashboardController(types, dashboardUtils, widgetService
|
||||
}
|
||||
}).then(function (result) {
|
||||
var widget = result.widget;
|
||||
vm.dashboardCtx.aliasesInfo = result.aliasesInfo;
|
||||
addWidget(widget);
|
||||
}, function (rejection) {
|
||||
vm.dashboardCtx.aliasesInfo = rejection.aliasesInfo;
|
||||
}, function () {
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1025,7 +1032,7 @@ export default function DashboardController(types, dashboardUtils, widgetService
|
||||
notifyDashboardUpdated();
|
||||
}
|
||||
|
||||
function showAliasesResolutionError(error) {
|
||||
/* function showAliasesResolutionError(error) {
|
||||
var alert = $mdDialog.alert()
|
||||
.parent(angular.element($document[0].body))
|
||||
.clickOutsideToClose(true)
|
||||
@ -1037,20 +1044,10 @@ export default function DashboardController(types, dashboardUtils, widgetService
|
||||
alert._options.fullscreen = true;
|
||||
|
||||
$mdDialog.show(alert);
|
||||
}
|
||||
}*/
|
||||
|
||||
function entityAliasesUpdated() {
|
||||
var deferred = $q.defer();
|
||||
entityService.processEntityAliases(vm.dashboard.configuration.entityAliases)
|
||||
.then(
|
||||
function(resolution) {
|
||||
if (resolution.aliasesInfo) {
|
||||
vm.dashboardCtx.aliasesInfo = resolution.aliasesInfo;
|
||||
}
|
||||
deferred.resolve();
|
||||
}
|
||||
);
|
||||
return deferred.promise;
|
||||
vm.dashboardCtx.aliasController.updateEntityAliases(vm.dashboard.configuration.entityAliases);
|
||||
}
|
||||
|
||||
function notifyDashboardUpdated() {
|
||||
|
||||
@ -57,8 +57,7 @@
|
||||
</tb-timewindow>
|
||||
<tb-aliases-entity-select ng-show="!vm.isEdit && vm.displayEntitiesSelect()"
|
||||
tooltip-direction="bottom"
|
||||
ng-model="vm.dashboardCtx.aliasesInfo.entityAliases"
|
||||
entity-aliases-info="vm.dashboardCtx.aliasesInfo.entityAliasesInfo">
|
||||
alias-controller="vm.dashboardCtx.aliasController">
|
||||
</tb-aliases-entity-select>
|
||||
<md-button ng-show="vm.isEdit" aria-label="{{ 'entity.aliases' | translate }}" class="md-icon-button"
|
||||
ng-click="vm.openEntityAliases($event)">
|
||||
@ -179,7 +178,7 @@
|
||||
<form name="vm.widgetForm" ng-if="vm.isEditingWidget">
|
||||
<tb-edit-widget
|
||||
dashboard="vm.dashboard"
|
||||
aliases-info="vm.dashboardCtx.aliasesInfo"
|
||||
alias-controller="vm.dashboardCtx.aliasController"
|
||||
widget="vm.editingWidget"
|
||||
widget-layout="vm.editingWidgetLayout"
|
||||
the-form="vm.widgetForm">
|
||||
|
||||
@ -68,18 +68,34 @@ export default function EditWidgetDirective($compile, $templateCache, types, wid
|
||||
});
|
||||
|
||||
scope.fetchEntityKeys = function (entityAliasId, query, type) {
|
||||
var entityAlias = scope.aliasesInfo.entityAliases[entityAliasId];
|
||||
if (entityAlias && entityAlias.entityId) {
|
||||
return entityService.getEntityKeys(entityAlias.entityType, entityAlias.entityId, query, type);
|
||||
} else {
|
||||
return $q.when([]);
|
||||
}
|
||||
var deferred = $q.defer();
|
||||
scope.aliasController.getAliasInfo(entityAliasId).then(
|
||||
function success(aliasInfo) {
|
||||
var entity = aliasInfo.currentEntity;
|
||||
if (entity) {
|
||||
entityService.getEntityKeys(entity.entityType, entity.id, query, type).then(
|
||||
function success(keys) {
|
||||
deferred.resolve(keys);
|
||||
},
|
||||
function fail() {
|
||||
deferred.resolve([]);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
deferred.resolve([]);
|
||||
}
|
||||
},
|
||||
function fail() {
|
||||
deferred.resolve([]);
|
||||
}
|
||||
);
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
scope.createEntityAlias = function (event, alias, allowedEntityTypes) {
|
||||
|
||||
var deferred = $q.defer();
|
||||
var singleEntityAlias = {id: null, alias: alias, entityType: types.entityType.device, entityFilter: null};
|
||||
var singleEntityAlias = {id: null, alias: alias, filter: {}};
|
||||
|
||||
$mdDialog.show({
|
||||
controller: 'EntityAliasesController',
|
||||
@ -99,16 +115,9 @@ export default function EditWidgetDirective($compile, $templateCache, types, wid
|
||||
skipHide: true,
|
||||
targetEvent: event
|
||||
}).then(function (singleEntityAlias) {
|
||||
scope.dashboard.configuration.entityAliases[singleEntityAlias.id] =
|
||||
{ alias: singleEntityAlias.alias, entityType: singleEntityAlias.entityType, entityFilter: singleEntityAlias.entityFilter };
|
||||
entityService.processEntityAliases(scope.dashboard.configuration.entityAliases).then(
|
||||
function(resolution) {
|
||||
if (!resolution.error) {
|
||||
scope.aliasesInfo = resolution.aliasesInfo;
|
||||
}
|
||||
deferred.resolve(singleEntityAlias);
|
||||
}
|
||||
);
|
||||
scope.dashboard.configuration.entityAliases[singleEntityAlias.id] = singleEntityAlias;
|
||||
scope.aliasController.updateEntityAliases(scope.dashboard.configuration.entityAliases);
|
||||
deferred.resolve(singleEntityAlias);
|
||||
}, function () {
|
||||
deferred.reject();
|
||||
});
|
||||
@ -124,7 +133,7 @@ export default function EditWidgetDirective($compile, $templateCache, types, wid
|
||||
link: linker,
|
||||
scope: {
|
||||
dashboard: '=',
|
||||
aliasesInfo: '=',
|
||||
aliasController: '=',
|
||||
widget: '=',
|
||||
widgetLayout: '=',
|
||||
theForm: '='
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
is-data-enabled="isDataEnabled"
|
||||
widget-settings-schema="settingsSchema"
|
||||
datakey-settings-schema="dataKeySettingsSchema"
|
||||
entity-aliases="aliasesInfo.entityAliases"
|
||||
alias-controller="aliasController"
|
||||
functions-only="functionsOnly"
|
||||
fetch-entity-keys="fetchEntityKeys(entityAliasId, query, type)"
|
||||
on-create-entity-alias="createEntityAlias(event, alias, allowedEntityTypes)"
|
||||
|
||||
@ -45,7 +45,7 @@
|
||||
widget-layouts="vm.layoutCtx.widgetLayouts"
|
||||
columns="vm.layoutCtx.gridSettings.columns"
|
||||
margins="vm.layoutCtx.gridSettings.margins"
|
||||
aliases-info="vm.dashboardCtx.aliasesInfo"
|
||||
alias-controller="vm.dashboardCtx.aliasController"
|
||||
state-controller="vm.dashboardCtx.stateController"
|
||||
dashboard-timewindow="vm.dashboardCtx.dashboardTimewindow"
|
||||
is-edit="vm.isEdit"
|
||||
|
||||
@ -15,17 +15,30 @@
|
||||
*/
|
||||
|
||||
/*@ngInject*/
|
||||
export default function AliasesEntitySelectPanelController(mdPanelRef, $scope, types, entityAliases, entityAliasesInfo, onEntityAliasesUpdate) {
|
||||
export default function AliasesEntitySelectPanelController(mdPanelRef, $scope, types, aliasController, onEntityAliasesUpdate) {
|
||||
|
||||
var vm = this;
|
||||
vm._mdPanelRef = mdPanelRef;
|
||||
vm.entityAliases = entityAliases;
|
||||
vm.entityAliasesInfo = entityAliasesInfo;
|
||||
vm.aliasController = aliasController;
|
||||
vm.onEntityAliasesUpdate = onEntityAliasesUpdate;
|
||||
vm.entityAliases = {};
|
||||
vm.entityAliasesInfo = {};
|
||||
|
||||
$scope.$watch('vm.entityAliases', function () {
|
||||
if (onEntityAliasesUpdate) {
|
||||
onEntityAliasesUpdate(vm.entityAliases);
|
||||
vm.currentAliasEntityChanged = currentAliasEntityChanged;
|
||||
|
||||
var allEntityAliases = vm.aliasController.getEntityAliases();
|
||||
for (var aliasId in allEntityAliases) {
|
||||
var aliasInfo = vm.aliasController.getInstantAliasInfo(aliasId);
|
||||
if (aliasInfo && !aliasInfo.resolveMultiple && aliasInfo.currentEntity) {
|
||||
vm.entityAliasesInfo[aliasId] = angular.copy(aliasInfo);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
function currentAliasEntityChanged(aliasId, currentEntity) {
|
||||
vm.aliasController.updateCurrentAliasEntity(aliasId, currentEntity);
|
||||
if (onEntityAliasesUpdate) {
|
||||
onEntityAliasesUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -18,12 +18,12 @@
|
||||
<md-content flex layout="column">
|
||||
<section flex layout="column">
|
||||
<md-content flex class="md-padding" layout="column">
|
||||
<div flex layout="row" ng-repeat="(aliasId, entityAlias) in vm.entityAliases">
|
||||
<div flex layout="row" ng-repeat="(aliasId, entityAliasInfo) in vm.entityAliasesInfo">
|
||||
<md-input-container flex>
|
||||
<label>{{entityAlias.alias}}</label>
|
||||
<md-select ng-model="vm.entityAliases[aliasId].entityId">
|
||||
<md-option ng-repeat="entityInfo in vm.entityAliasesInfo[aliasId]" ng-value="entityInfo.id">
|
||||
{{entityInfo.name}}
|
||||
<label>{{entityAliasInfo.alias}}</label>
|
||||
<md-select ng-model="entityAliasInfo.currentEntity" ng-change="vm.currentAliasEntityChanged(aliasId, entityAliasInfo.currentEntity)">
|
||||
<md-option ng-repeat="resolvedEntity in entityAliasInfo.resolvedEntities" ng-value="resolvedEntity">
|
||||
{{resolvedEntity.name}}
|
||||
</md-option>
|
||||
</md-select>
|
||||
</md-input-container>
|
||||
|
||||
@ -29,7 +29,7 @@ import aliasesEntitySelectPanelTemplate from './aliases-entity-select-panel.tpl.
|
||||
/*@ngInject*/
|
||||
export default function AliasesEntitySelectDirective($compile, $templateCache, $mdMedia, types, $mdPanel, $document, $translate) {
|
||||
|
||||
var linker = function (scope, element, attrs, ngModelCtrl) {
|
||||
var linker = function (scope, element, attrs) {
|
||||
|
||||
/* tbAliasesEntitySelect (ng-model)
|
||||
* {
|
||||
@ -81,10 +81,8 @@ export default function AliasesEntitySelectDirective($compile, $templateCache, $
|
||||
position: position,
|
||||
fullscreen: false,
|
||||
locals: {
|
||||
'entityAliases': angular.copy(scope.model),
|
||||
'entityAliasesInfo': scope.entityAliasesInfo,
|
||||
'onEntityAliasesUpdate': function (entityAliases) {
|
||||
scope.model = entityAliases;
|
||||
'aliasController': scope.aliasController,
|
||||
'onEntityAliasesUpdate': function () {
|
||||
scope.updateView();
|
||||
}
|
||||
},
|
||||
@ -97,40 +95,31 @@ export default function AliasesEntitySelectDirective($compile, $templateCache, $
|
||||
}
|
||||
|
||||
scope.updateView = function () {
|
||||
var value = angular.copy(scope.model);
|
||||
ngModelCtrl.$setViewValue(value);
|
||||
updateDisplayValue();
|
||||
}
|
||||
|
||||
ngModelCtrl.$render = function () {
|
||||
if (ngModelCtrl.$viewValue) {
|
||||
var value = ngModelCtrl.$viewValue;
|
||||
scope.model = angular.copy(value);
|
||||
updateDisplayValue();
|
||||
}
|
||||
}
|
||||
|
||||
function updateDisplayValue() {
|
||||
var displayValue;
|
||||
var singleValue = true;
|
||||
var currentAliasId;
|
||||
for (var aliasId in scope.model) {
|
||||
if (!currentAliasId) {
|
||||
currentAliasId = aliasId;
|
||||
} else {
|
||||
singleValue = false;
|
||||
break;
|
||||
var entityAliases = scope.aliasController.getEntityAliases();
|
||||
for (var aliasId in entityAliases) {
|
||||
var entityAlias = entityAliases[aliasId];
|
||||
if (!entityAlias.filter.resolveMultiple) {
|
||||
var resolvedAlias = scope.aliasController.getInstantAliasInfo(aliasId);
|
||||
if (resolvedAlias && resolvedAlias.currentEntity) {
|
||||
if (!currentAliasId) {
|
||||
currentAliasId = aliasId;
|
||||
} else {
|
||||
singleValue = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (singleValue && currentAliasId) {
|
||||
var entityId = scope.model[currentAliasId].entityId;
|
||||
var entitiesInfo = scope.entityAliasesInfo[currentAliasId];
|
||||
for (var i=0;i<entitiesInfo.length;i++) {
|
||||
if (entitiesInfo[i].id === entityId) {
|
||||
displayValue = entitiesInfo[i].name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
var aliasInfo = scope.aliasController.getInstantAliasInfo(currentAliasId);
|
||||
displayValue = aliasInfo.currentEntity.name;
|
||||
} else {
|
||||
displayValue = $translate.instant('entity.entities');
|
||||
}
|
||||
@ -142,9 +131,8 @@ export default function AliasesEntitySelectDirective($compile, $templateCache, $
|
||||
|
||||
return {
|
||||
restrict: "E",
|
||||
require: "^ngModel",
|
||||
scope: {
|
||||
entityAliasesInfo:'='
|
||||
aliasController:'='
|
||||
},
|
||||
link: linker
|
||||
};
|
||||
|
||||
@ -85,32 +85,29 @@ export default function EntityAliasesController(utils, entityService, toast, $sc
|
||||
|
||||
for (aliasId in config.entityAliases) {
|
||||
var entityAlias = config.entityAliases[aliasId];
|
||||
var result = {id: aliasId, alias: entityAlias.alias, entityType: entityAlias.entityType, entityFilter: entityAlias.entityFilter, changed: true};
|
||||
var result = {id: aliasId, alias: entityAlias.alias, filter: entityAlias.filter, changed: true};
|
||||
checkEntityAlias(result);
|
||||
vm.entityAliases.push(result);
|
||||
}
|
||||
}
|
||||
|
||||
function checkEntityAlias(entityAlias) {
|
||||
if (!entityAlias.entityType) {
|
||||
entityAlias.entityType = types.entityType.device;
|
||||
}
|
||||
if (!entityAlias.entityFilter || entityAlias.entityFilter == null) {
|
||||
entityAlias.entityFilter = {
|
||||
useFilter: false,
|
||||
entityNameFilter: '',
|
||||
entityList: [],
|
||||
};
|
||||
if (!entityAlias.filter || entityAlias.filter == null) {
|
||||
entityAlias.filter = {};
|
||||
}
|
||||
}
|
||||
|
||||
function onFilterEntityChanged(entity, entityAlias) {
|
||||
function onFilterEntityChanged(entity, stateEntity, entityAlias) {
|
||||
if (entityAlias) {
|
||||
if (!entityAlias.alias || entityAlias.alias.length == 0) {
|
||||
entityAlias.changed = false;
|
||||
}
|
||||
if (!entityAlias.changed && entity && entityAlias.entityType) {
|
||||
entityAlias.alias = entity.name;
|
||||
if (!entityAlias.changed && entityAlias.filter && entityAlias.filter.type) {
|
||||
if (stateEntity) {
|
||||
entityAlias.alias = $translate.instant('alias.state-entity');
|
||||
} else {
|
||||
entityAlias.alias = entity.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -121,8 +118,7 @@ export default function EntityAliasesController(utils, entityService, toast, $sc
|
||||
aliasId = Math.max(vm.entityAliases[a].id, aliasId);
|
||||
}
|
||||
aliasId++;
|
||||
var entityAlias = {id: aliasId, alias: '', entityType: types.entityType.device,
|
||||
entityFilter: {useFilter: false, entityNameFilter: '', entityList: []}, changed: false};
|
||||
var entityAlias = {id: aliasId, alias: '', filter: {}, changed: false};
|
||||
vm.entityAliases.push(entityAlias);
|
||||
}
|
||||
|
||||
@ -160,15 +156,6 @@ export default function EntityAliasesController(utils, entityService, toast, $sc
|
||||
$mdDialog.cancel();
|
||||
}
|
||||
|
||||
function cleanupEntityFilter(entityFilter) {
|
||||
if (entityFilter.useFilter) {
|
||||
entityFilter.entityList = [];
|
||||
} else {
|
||||
entityFilter.entityNameFilter = '';
|
||||
}
|
||||
return entityFilter;
|
||||
}
|
||||
|
||||
function save() {
|
||||
|
||||
var entityAliases = {};
|
||||
@ -181,7 +168,6 @@ export default function EntityAliasesController(utils, entityService, toast, $sc
|
||||
|
||||
if (vm.isSingleEntityAlias) {
|
||||
maxAliasId = 0;
|
||||
vm.singleEntityAlias.entityFilter = cleanupEntityFilter(vm.singleEntityAlias.entityFilter);
|
||||
for (i = 0; i < vm.entityAliases.length; i ++) {
|
||||
aliasId = vm.entityAliases[i].id;
|
||||
alias = vm.entityAliases[i].alias;
|
||||
@ -199,7 +185,7 @@ export default function EntityAliasesController(utils, entityService, toast, $sc
|
||||
alias = vm.entityAliases[i].alias;
|
||||
if (!uniqueAliasList[alias]) {
|
||||
uniqueAliasList[alias] = alias;
|
||||
entityAliases[aliasId] = {alias: alias, entityType: vm.entityAliases[i].entityType, entityFilter: cleanupEntityFilter(vm.entityAliases[i].entityFilter)};
|
||||
entityAliases[aliasId] = {id: aliasId, alias: alias, filter: vm.entityAliases[i].filter};
|
||||
} else {
|
||||
valid = false;
|
||||
break;
|
||||
|
||||
@ -32,20 +32,15 @@
|
||||
<div class="md-dialog-content">
|
||||
<fieldset ng-disabled="loading">
|
||||
<div ng-show="vm.isSingleEntityAlias" layout="row">
|
||||
<tb-entity-type-select style="min-width: 100px;"
|
||||
ng-model="vm.singleEntityAlias.entityType"
|
||||
allowed-entity-types="vm.allowedEntityTypes">
|
||||
</tb-entity-type-select>
|
||||
<tb-entity-filter flex entity-type="vm.singleEntityAlias.entityType" ng-model="vm.singleEntityAlias.entityFilter">
|
||||
<tb-entity-filter flex allowed-entity-types="vm.allowedEntityTypes" ng-model="vm.singleEntityAlias.filter">
|
||||
</tb-entity-filter>
|
||||
</div>
|
||||
<div ng-show="!vm.isSingleEntityAlias" flex layout="row" layout-align="start center">
|
||||
<span flex="5"></span>
|
||||
<div flex layout="row" layout-align="start center"
|
||||
style="padding: 0 0 0 10px; margin: 5px;">
|
||||
<span translate flex="20" style="min-width: 100px;">entity.alias</span>
|
||||
<span translate flex="20" style="min-width: 100px;">entity.type</span>
|
||||
<span translate flex="60" style="min-width: 190px; padding-left: 10px;">entity.entities</span>
|
||||
<span translate flex="20" style="min-width: 150px;">entity.alias</span>
|
||||
<span translate flex="80" style="min-width: 240px; padding-left: 10px;">alias.entity-filter</span>
|
||||
<span style="min-width: 40px;"></span>
|
||||
</div>
|
||||
</div>
|
||||
@ -53,23 +48,17 @@
|
||||
<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: 100px;" md-no-float class="md-block">
|
||||
<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>
|
||||
<section flex="20" layout="column" style="min-width: 100px;" >
|
||||
<tb-entity-type-select hide-label style="padding-left: 10px;"
|
||||
ng-model="entityAlias.entityType"
|
||||
allowed-entity-types="vm.allowedEntityTypes">
|
||||
</tb-entity-type-select>
|
||||
</section>
|
||||
<section flex="60" layout="column">
|
||||
<section flex="80" layout="column">
|
||||
<tb-entity-filter style="padding-left: 10px;"
|
||||
entity-type="entityAlias.entityType"
|
||||
ng-model="entityAlias.entityFilter"
|
||||
on-matching-entity-change="vm.onFilterEntityChanged(entity, entityAlias)">
|
||||
allowed-entity-types="vm.allowedEntityTypes"
|
||||
ng-model="entityAlias.filter"
|
||||
on-matching-entity-change="vm.onFilterEntityChanged(entity, stateEntity, entityAlias)">
|
||||
</tb-entity-filter>
|
||||
</section>
|
||||
<md-button ng-disabled="loading" class="md-icon-button md-primary" style="min-width: 40px;"
|
||||
|
||||
104
ui/src/app/entity/entity-filter-dialog.controller.js
Normal file
104
ui/src/app/entity/entity-filter-dialog.controller.js
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*@ngInject*/
|
||||
export default function EntityFilterDialogController($scope, $mdDialog, $q, entityService, types, isAdd, allowedEntityTypes, filter) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.types = types;
|
||||
vm.isAdd = isAdd;
|
||||
vm.allowedEntityTypes = allowedEntityTypes;
|
||||
vm.filter = filter;
|
||||
|
||||
vm.cancel = cancel;
|
||||
vm.save = save;
|
||||
|
||||
$scope.$watch('vm.filter.type', function (newType, prevType) {
|
||||
if (newType && newType != prevType) {
|
||||
updateFilter();
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$watch('theForm.$pristine', function() {
|
||||
if ($scope.theForm && !$scope.theForm.$pristine) {
|
||||
$scope.theForm.$setValidity('entityFilter', true);
|
||||
}
|
||||
});
|
||||
|
||||
function updateFilter() {
|
||||
var filter = {};
|
||||
filter.type = vm.filter.type;
|
||||
filter.resolveMultiple = vm.filter.resolveMultiple;
|
||||
switch (filter.type) {
|
||||
case types.aliasFilterType.entityList.value:
|
||||
filter.entityType = null;
|
||||
filter.entityList = [];
|
||||
filter.stateEntity = false;
|
||||
break;
|
||||
case types.aliasFilterType.entityName.value:
|
||||
filter.entityType = null;
|
||||
filter.entityNameFilter = '';
|
||||
break;
|
||||
//TODO:
|
||||
}
|
||||
vm.filter = filter;
|
||||
}
|
||||
|
||||
function validate() {
|
||||
var deferred = $q.defer();
|
||||
var validationResult = {
|
||||
entity: null,
|
||||
stateEntity: false
|
||||
}
|
||||
entityService.resolveAliasFilter(vm.filter).then(
|
||||
function success(result) {
|
||||
validationResult.stateEntity = result.stateEntity;
|
||||
var entities = result.entities;
|
||||
if (entities.length) {
|
||||
validationResult.entity = entities[0];
|
||||
}
|
||||
deferred.resolve(validationResult);
|
||||
},
|
||||
function fail() {
|
||||
deferred.reject();
|
||||
}
|
||||
);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
$mdDialog.cancel();
|
||||
}
|
||||
|
||||
function save() {
|
||||
$scope.theForm.$setPristine();
|
||||
validate().then(
|
||||
function success(validationResult) {
|
||||
$mdDialog.hide({
|
||||
filter: vm.filter,
|
||||
entity: validationResult.entity,
|
||||
stateEntity: validationResult.stateEntity
|
||||
});
|
||||
},
|
||||
function fail() {
|
||||
$scope.theForm.$setValidity('entityFilter', false);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
100
ui/src/app/entity/entity-filter-dialog.tpl.html
Normal file
100
ui/src/app/entity/entity-filter-dialog.tpl.html
Normal file
@ -0,0 +1,100 @@
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<md-dialog class="tb-entity-filter-dialog" style="width: 600px;" aria-label="{{ 'alias.entity-filter' | translate }}">
|
||||
<form name="theForm" ng-submit="vm.save()">
|
||||
<md-toolbar>
|
||||
<div class="md-toolbar-tools">
|
||||
<h2>{{ (vm.isAdd ? 'alias.create-entity-filter' : 'alias.edit-entity-filter') | 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>
|
||||
</md-button>
|
||||
</div>
|
||||
</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>
|
||||
<md-dialog-content>
|
||||
<div class="md-dialog-content">
|
||||
<fieldset ng-disabled="loading">
|
||||
<div flex layout="column">
|
||||
<md-input-container>
|
||||
<label>{{ 'alias.filter-type' | translate }}</label>
|
||||
<md-select required name="filterType"
|
||||
ng-model="vm.filter.type" aria-label="{{ 'alias.filter-type' | translate }}">
|
||||
<md-option ng-repeat="type in vm.types.aliasFilterType" 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="vm.filter.type == vm.types.aliasFilterType.entityList.value" id="entityListFilter">
|
||||
<md-checkbox flex aria-label="{{ 'alias.use-state-entity' | translate }}"
|
||||
ng-model="vm.filter.stateEntity">{{ 'alias.use-state-entity' | translate }}
|
||||
</md-checkbox>
|
||||
<tb-entity-type-select
|
||||
ng-if="!vm.filter.stateEntity"
|
||||
ng-model="vm.filter.entityType"
|
||||
the-form="theForm"
|
||||
ng-disabled="vm.filter.stateEntity"
|
||||
tb-required="!vm.filter.stateEntity"
|
||||
allowed-entity-types="vm.allowedEntityTypes">
|
||||
</tb-entity-type-select>
|
||||
<tb-entity-list
|
||||
ng-if="!vm.filter.stateEntity"
|
||||
ng-model="vm.filter.entityList"
|
||||
ng-disabled="vm.filter.stateEntity"
|
||||
tb-required="!vm.filter.stateEntity"
|
||||
entity-type="vm.filter.entityType">
|
||||
</tb-entity-list>
|
||||
</section>
|
||||
<section flex layout="column" ng-if="vm.filter.type == vm.types.aliasFilterType.entityName.value" id="entityNameFilter">
|
||||
<tb-entity-type-select
|
||||
ng-model="vm.filter.entityType"
|
||||
the-form="theForm"
|
||||
tb-required="true"
|
||||
allowed-entity-types="vm.allowedEntityTypes">
|
||||
</tb-entity-type-select>
|
||||
<md-input-container flex>
|
||||
<label translate>entity.name-starts-with</label>
|
||||
<input required name="entityNameFilter"
|
||||
ng-model="vm.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>
|
||||
<div class="tb-error-messages" ng-messages="theForm.$error" role="alert">
|
||||
<div translate ng-message="entityFilter" class="tb-error-message">alias.entity-filter-no-entity-matched</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</md-dialog-content>
|
||||
<md-dialog-actions layout="row">
|
||||
<span flex></span>
|
||||
<md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary">
|
||||
{{ 'action.save' | translate }}
|
||||
</md-button>
|
||||
<md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button>
|
||||
</md-dialog-actions>
|
||||
</form>
|
||||
</md-dialog>
|
||||
@ -17,13 +17,16 @@
|
||||
/* 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, entityService) {
|
||||
export default function EntityFilterDirective($compile, $templateCache, $q, $document, $mdDialog, types) {
|
||||
|
||||
var linker = function (scope, element, attrs, ngModelCtrl) {
|
||||
|
||||
@ -31,8 +34,9 @@ export default function EntityFilterDirective($compile, $templateCache, $q, enti
|
||||
element.html(template);
|
||||
|
||||
scope.ngModelCtrl = ngModelCtrl;
|
||||
scope.types = types;
|
||||
|
||||
scope.fetchEntities = function(searchText, limit) {
|
||||
/* scope.fetchEntities = function(searchText, limit) {
|
||||
var deferred = $q.defer();
|
||||
entityService.getEntitiesByNameFilter(scope.entityType, searchText, limit).then(function success(result) {
|
||||
if (result) {
|
||||
@ -44,13 +48,13 @@ export default function EntityFilterDirective($compile, $templateCache, $q, enti
|
||||
deferred.reject();
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
}*/
|
||||
|
||||
scope.updateValidity = function() {
|
||||
if (ngModelCtrl.$viewValue) {
|
||||
var value = ngModelCtrl.$viewValue;
|
||||
var valid;
|
||||
if (value.useFilter) {
|
||||
ngModelCtrl.$setValidity('filter', value.type ? true : false);
|
||||
/*if (value.useFilter) {
|
||||
ngModelCtrl.$setValidity('entityList', true);
|
||||
if (angular.isDefined(value.entityNameFilter) && value.entityNameFilter.length > 0) {
|
||||
ngModelCtrl.$setValidity('entityNameFilter', true);
|
||||
@ -64,18 +68,22 @@ export default function EntityFilterDirective($compile, $templateCache, $q, enti
|
||||
ngModelCtrl.$setValidity('entityNameFilterDeviceMatch', true);
|
||||
valid = angular.isDefined(value.entityList) && value.entityList.length > 0;
|
||||
ngModelCtrl.$setValidity('entityList', valid);
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ngModelCtrl.$render = function () {
|
||||
destroyWatchers();
|
||||
scope.model = {
|
||||
useFilter: false,
|
||||
entityList: [],
|
||||
entityNameFilter: ''
|
||||
}
|
||||
//destroyWatchers();
|
||||
if (ngModelCtrl.$viewValue) {
|
||||
scope.model = angular.copy(ngModelCtrl.$viewValue);
|
||||
} else {
|
||||
scope.model = {
|
||||
type: null,
|
||||
resolveMultiple: false
|
||||
}
|
||||
}
|
||||
/* if (ngModelCtrl.$viewValue) {
|
||||
var value = ngModelCtrl.$viewValue;
|
||||
var model = scope.model;
|
||||
model.useFilter = value.useFilter === true ? true: false;
|
||||
@ -96,10 +104,52 @@ export default function EntityFilterDirective($compile, $templateCache, $q, enti
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
function updateMatchingEntity() {
|
||||
scope.$watch('model.resolveMultiple', function () {
|
||||
if (ngModelCtrl.$viewValue) {
|
||||
var value = ngModelCtrl.$viewValue;
|
||||
value.resolveMultiple = scope.model.resolveMultiple;
|
||||
ngModelCtrl.$setViewValue(value);
|
||||
scope.updateValidity();
|
||||
}
|
||||
});
|
||||
|
||||
scope.editFilter = function($event) {
|
||||
openEntityFilterDialog($event, false);
|
||||
}
|
||||
|
||||
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});
|
||||
}
|
||||
}, function () {
|
||||
});
|
||||
}
|
||||
|
||||
/* function updateMatchingEntity() {
|
||||
if (scope.model.useFilter) {
|
||||
scope.model.matchingEntity = scope.model.matchingFilterEntity;
|
||||
} else {
|
||||
@ -206,7 +256,7 @@ export default function EntityFilterDirective($compile, $templateCache, $q, enti
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}*/
|
||||
|
||||
$compile(element.contents())(scope);
|
||||
|
||||
@ -217,8 +267,7 @@ export default function EntityFilterDirective($compile, $templateCache, $q, enti
|
||||
require: "^ngModel",
|
||||
link: linker,
|
||||
scope: {
|
||||
entityType: '=',
|
||||
isEdit: '=',
|
||||
allowedEntityTypes: '=?',
|
||||
onMatchingEntityChange: '&'
|
||||
}
|
||||
};
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
-->
|
||||
<section layout='column' class="tb-entity-filter">
|
||||
<section layout='row'>
|
||||
<section layout="column" flex ng-show="!model.useFilter">
|
||||
<!--section layout="column" flex ng-show="!model.useFilter">
|
||||
<md-chips flex
|
||||
id="entity_list_chips"
|
||||
ng-required="!useFilter"
|
||||
@ -51,17 +51,44 @@
|
||||
<label translate>entity.name-starts-with</label>
|
||||
<input ng-model="model.entityNameFilter" aria-label="{{ 'entity.name-starts-with' | translate }}">
|
||||
</md-input-container>
|
||||
</section-->
|
||||
<section layout="row" flex layout-align="start center">
|
||||
<div flex ng-if="model.type">{{ types.aliasFilterType[model.type].name | translate }}</div>
|
||||
<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 ng-if="!model.type" layout="row" layout-align="center start">
|
||||
<md-button ng-disabled="loading" class="md-primary md-raised"
|
||||
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>
|
||||
</div>
|
||||
</section>
|
||||
<section class="tb-filter-switch" layout="column" layout-align="center center">
|
||||
<label class="tb-small filter-label" translate>entity.use-entity-name-filter</label>
|
||||
<md-switch class="filter-switch" ng-model="model.useFilter" aria-label="use-filter-switcher">
|
||||
<label 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>
|
||||
</section>
|
||||
<div class="tb-error-messages" ng-messages="ngModelCtrl.$error" role="alert">
|
||||
<div translate ng-message="entityList" class="tb-error-message">entity.entity-list-empty</div>
|
||||
<div translate ng-message="filter" class="tb-error-message">alias.entity-filter-required</div>
|
||||
<!--div translate ng-message="entityList" class="tb-error-message">entity.entity-list-empty</div>
|
||||
<div translate ng-message="entityNameFilter" class="tb-error-message">entity.entity-name-filter-required</div>
|
||||
<div translate translate-values='{ entity: model.entityNameFilter }' ng-message="entityNameFilterEntityMatch"
|
||||
class="tb-error-message">entity.entity-name-filter-no-entity-matched</div>
|
||||
class="tb-error-message">entity.entity-name-filter-no-entity-matched</div-->
|
||||
</div>
|
||||
</section>
|
||||
130
ui/src/app/entity/entity-list.directive.js
Normal file
130
ui/src/app/entity/entity-list.directive.js
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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 entityListTemplate from './entity-list.tpl.html';
|
||||
|
||||
/* eslint-enable import/no-unresolved, import/default */
|
||||
|
||||
import './entity-list.scss';
|
||||
|
||||
/*@ngInject*/
|
||||
export default function EntityListDirective($compile, $templateCache, $q, $mdUtil, entityService) {
|
||||
|
||||
var linker = function (scope, element, attrs, ngModelCtrl) {
|
||||
|
||||
var template = $templateCache.get(entityListTemplate);
|
||||
element.html(template);
|
||||
|
||||
scope.ngModelCtrl = ngModelCtrl;
|
||||
|
||||
scope.$watch('tbRequired', function () {
|
||||
scope.updateValidity();
|
||||
});
|
||||
|
||||
scope.fetchEntities = function(searchText, limit) {
|
||||
var deferred = $q.defer();
|
||||
entityService.getEntitiesByNameFilter(scope.entityType, searchText, limit).then(
|
||||
function success(result) {
|
||||
if (result) {
|
||||
deferred.resolve(result);
|
||||
} else {
|
||||
deferred.resolve([]);
|
||||
}
|
||||
},
|
||||
function fail() {
|
||||
deferred.reject();
|
||||
}
|
||||
);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
scope.updateValidity = function() {
|
||||
var value = ngModelCtrl.$viewValue;
|
||||
var valid = !scope.tbRequired || value && value.length > 0;
|
||||
ngModelCtrl.$setValidity('entityList', valid);
|
||||
}
|
||||
|
||||
ngModelCtrl.$render = function () {
|
||||
destroyWatchers();
|
||||
var value = ngModelCtrl.$viewValue;
|
||||
scope.entityList = [];
|
||||
if (value && value.length > 0) {
|
||||
entityService.getEntities(scope.entityType, value).then(function (entities) {
|
||||
scope.entityList = entities;
|
||||
initWatchers();
|
||||
});
|
||||
} else {
|
||||
initWatchers();
|
||||
}
|
||||
}
|
||||
|
||||
function initWatchers() {
|
||||
scope.entityTypeDeregistration = scope.$watch('entityType', function (newEntityType, prevEntityType) {
|
||||
if (!angular.equals(newEntityType, prevEntityType)) {
|
||||
scope.entityList = [];
|
||||
}
|
||||
});
|
||||
scope.entityListDeregistration = scope.$watch('entityList', function () {
|
||||
var ids = [];
|
||||
if (scope.entityList && scope.entityList.length > 0) {
|
||||
for (var i=0;i<scope.entityList.length;i++) {
|
||||
ids.push(scope.entityList[i].id.id);
|
||||
}
|
||||
}
|
||||
var value = ngModelCtrl.$viewValue;
|
||||
if (!angular.equals(ids, value)) {
|
||||
ngModelCtrl.$setViewValue(ids);
|
||||
}
|
||||
scope.updateValidity();
|
||||
}, true);
|
||||
}
|
||||
|
||||
function destroyWatchers() {
|
||||
if (scope.entityTypeDeregistration) {
|
||||
scope.entityTypeDeregistration();
|
||||
scope.entityTypeDeregistration = null;
|
||||
}
|
||||
if (scope.entityListDeregistration) {
|
||||
scope.entityListDeregistration();
|
||||
scope.entityListDeregistration = null;
|
||||
}
|
||||
}
|
||||
|
||||
$compile(element.contents())(scope);
|
||||
|
||||
$mdUtil.nextTick(function(){
|
||||
var inputElement = angular.element('input', element);
|
||||
inputElement.on('blur', function() {
|
||||
scope.inputTouched = true;
|
||||
} );
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
restrict: "E",
|
||||
require: "^ngModel",
|
||||
link: linker,
|
||||
scope: {
|
||||
disabled:'=ngDisabled',
|
||||
tbRequired: '=?',
|
||||
entityType: '='
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
30
ui/src/app/entity/entity-list.scss
Normal file
30
ui/src/app/entity/entity-list.scss
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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-list {
|
||||
#entity_list_chips {
|
||||
.md-chips {
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
}
|
||||
.tb-error-messages {
|
||||
margin-top: -11px;
|
||||
height: 35px;
|
||||
.tb-error-message {
|
||||
padding-left: 1px;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
52
ui/src/app/entity/entity-list.tpl.html
Normal file
52
ui/src/app/entity/entity-list.tpl.html
Normal file
@ -0,0 +1,52 @@
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
|
||||
<section flex layout='column' class="tb-entity-list">
|
||||
<md-chips flex
|
||||
readonly="disabled"
|
||||
id="entity_list_chips"
|
||||
ng-required="tbRequired"
|
||||
ng-model="entityList"
|
||||
md-autocomplete-snap
|
||||
md-require-match="true">
|
||||
<md-autocomplete
|
||||
md-no-cache="true"
|
||||
id="entity"
|
||||
md-selected-item="selectedEntity"
|
||||
md-search-text="entitySearchText"
|
||||
md-items="item in fetchEntities(entitySearchText, 10)"
|
||||
md-item-text="item.name"
|
||||
md-min-length="0"
|
||||
placeholder="{{ 'entity.entity-list' | translate }}">
|
||||
<md-item-template>
|
||||
<span md-highlight-text="entitySearchText" md-highlight-flags="^i">{{item.name}}</span>
|
||||
</md-item-template>
|
||||
<md-not-found>
|
||||
<span translate translate-values='{ entity: entitySearchText }'>entity.no-entities-matching</span>
|
||||
</md-not-found>
|
||||
</md-autocomplete>
|
||||
<md-chip-template>
|
||||
<span>
|
||||
<strong>{{$chip.name}}</strong>
|
||||
</span>
|
||||
</md-chip-template>
|
||||
</md-chips>
|
||||
<div class="tb-error-messages" ng-messages="ngModelCtrl.$error" ng-if="inputTouched" role="alert">
|
||||
<div translate ng-message="entityList" class="tb-error-message">entity.entity-list-empty</div>
|
||||
</div>
|
||||
</section>
|
||||
@ -19,6 +19,7 @@ import EntityTypeSelectDirective from './entity-type-select.directive';
|
||||
import EntitySubtypeSelectDirective from './entity-subtype-select.directive';
|
||||
import EntitySubtypeAutocompleteDirective from './entity-subtype-autocomplete.directive';
|
||||
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 AliasesEntitySelectPanelController from './aliases-entity-select-panel.controller';
|
||||
@ -38,6 +39,7 @@ export default angular.module('thingsboard.entity', [])
|
||||
.directive('tbEntitySubtypeSelect', EntitySubtypeSelectDirective)
|
||||
.directive('tbEntitySubtypeAutocomplete', EntitySubtypeAutocompleteDirective)
|
||||
.directive('tbEntityAutocomplete', EntityAutocompleteDirective)
|
||||
.directive('tbEntityList', EntityListDirective)
|
||||
.directive('tbEntitySelect', EntitySelectDirective)
|
||||
.directive('tbEntityFilter', EntityFilterDirective)
|
||||
.directive('tbAliasesEntitySelect', AliasesEntitySelectDirective)
|
||||
|
||||
@ -112,6 +112,25 @@ export default angular.module('thingsboard.locale', [])
|
||||
"no-alarms-matching": "No alarms matching '{{entity}}' were found.",
|
||||
"alarm-required": "Alarm is required"
|
||||
},
|
||||
"alias": {
|
||||
"filter-type-entity-list": "Entity list",
|
||||
"filter-type-entity-name": "Entity name",
|
||||
"filter-type-asset-type": "Asset type",
|
||||
"filter-type-device-type": "Device type",
|
||||
"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": "Multiple",
|
||||
"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.",
|
||||
},
|
||||
"asset": {
|
||||
"asset": "Asset",
|
||||
"assets": "Assets",
|
||||
|
||||
@ -264,14 +264,9 @@ function ItemBuffer($q, bufferStore, types, utils, dashboardUtils) {
|
||||
}
|
||||
dashboardUtils.addWidgetToLayout(theDashboard, targetState, targetLayout, widget, originalColumns, originalSize, row, column);
|
||||
if (callAliasUpdateFunction) {
|
||||
onAliasesUpdateFunction().then(
|
||||
function() {
|
||||
deferred.resolve(theDashboard);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
deferred.resolve(theDashboard);
|
||||
onAliasesUpdateFunction();
|
||||
}
|
||||
deferred.resolve(theDashboard);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user