Create new dataKey type entityField (#2282)

* Add support import label

* Create new dataKey type entityField

* Add translate to entityField
This commit is contained in:
Vladyslav 2019-12-23 17:35:04 +02:00 committed by Igor Kulikov
parent 825406690c
commit 6ba0b943e8
14 changed files with 268 additions and 19 deletions

View File

@ -848,7 +848,50 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
return deferred.promise;
}
function getEntityFieldKeys (entityType, searchText) {
let entityFieldKeys = [];
let query = searchText.toLowerCase();
switch(entityType) {
case types.entityType.user:
entityFieldKeys.push(types.entityField.name.keyName);
entityFieldKeys.push(types.entityField.email.keyName);
entityFieldKeys.push(types.entityField.firstName.keyName);
entityFieldKeys.push(types.entityField.lastName.keyName);
break;
case types.entityType.tenant:
case types.entityType.customer:
entityFieldKeys.push(types.entityField.title.keyName);
entityFieldKeys.push(types.entityField.email.keyName);
entityFieldKeys.push(types.entityField.country.keyName);
entityFieldKeys.push(types.entityField.state.keyName);
entityFieldKeys.push(types.entityField.city.keyName);
entityFieldKeys.push(types.entityField.address.keyName);
entityFieldKeys.push(types.entityField.address2.keyName);
entityFieldKeys.push(types.entityField.zip.keyName);
entityFieldKeys.push(types.entityField.phone.keyName);
break;
case types.entityType.entityView:
entityFieldKeys.push(types.entityField.name.keyName);
entityFieldKeys.push(types.entityField.type.keyName);
break;
case types.entityType.device:
case types.entityType.asset:
entityFieldKeys.push(types.entityField.name.keyName);
entityFieldKeys.push(types.entityField.type.keyName);
entityFieldKeys.push(types.entityField.label.keyName);
break;
case types.entityType.dashboard:
entityFieldKeys.push(types.entityField.title.keyName);
break;
}
return query ? entityFieldKeys.filter((entityField) => entityField.toLowerCase().indexOf(query) === 0) : entityFieldKeys;
}
function getEntityKeys(entityType, entityId, query, type, config) {
if (type === types.dataKeyType.entityField) {
return $q.when(getEntityFieldKeys(entityType, query));
}
var deferred = $q.defer();
var url = '/api/plugins/telemetry/' + entityType + '/' + entityId + '/keys/';
if (type === types.dataKeyType.timeseries) {

View File

@ -350,6 +350,11 @@ export default class Subscription {
dataKey: dataKey,
data: []
};
if (dataKey.type === this.ctx.types.dataKeyType.entityField) {
if(datasource.entity && datasource.entity[this.ctx.types.entityField[dataKey.name].value]){
datasourceData.data.push([Date.now(), datasource.entity[this.ctx.types.entityField[dataKey.name].value]]);
}
}
this.data.push(datasourceData);
this.hiddenData.push({data: []});
if (this.displayLegend) {
@ -878,8 +883,14 @@ export default class Subscription {
};
}
var entityFieldKey = false;
for (var a = 0; a < datasource.dataKeys.length; a++) {
this.data[index + a].data = [];
if (datasource.dataKeys[a].type !== this.ctx.types.dataKeyType.entityField) {
this.data[index + a].data = [];
} else {
entityFieldKey = true;
}
}
index += datasource.dataKeys.length;
@ -891,7 +902,7 @@ export default class Subscription {
}
var forceUpdate = false;
if (datasource.unresolvedStateEntity ||
if (datasource.unresolvedStateEntity || entityFieldKey ||
!datasource.dataKeys.length ||
(datasource.type === this.ctx.types.datasourceType.entity && !datasource.entityId)
) {

View File

@ -78,7 +78,8 @@ export default function AppConfig($provide,
$mdIconProvider.iconSet('mdi', mdiIconSet);
ngMdIconServiceProvider
.addShape('alpha-a-circle-outline', '<path d="M11,7H13A2,2 0 0,1 15,9V17H13V13H11V17H9V9A2,2 0 0,1 11,7M11,9V11H13V9H11M12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2Z" />');
.addShape('alpha-a-circle-outline', '<path d="M11,7H13A2,2 0 0,1 15,9V17H13V13H11V17H9V9A2,2 0 0,1 11,7M11,9V11H13V9H11M12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2Z" />')
.addShape('alpha-e-circle-outline', '<path d="M9,7H15V9H11V11H15V13H11V15H15V17H9V7M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z" />');
configureTheme();
@ -170,4 +171,4 @@ export default function AppConfig($provide,
return aliases;
}
}
}

View File

@ -322,7 +322,8 @@ export default angular.module('thingsboard.types', [])
timeseries: "timeseries",
attribute: "attribute",
function: "function",
alarm: "alarm"
alarm: "alarm",
entityField: "entityField"
},
contentType: {
"JSON": {
@ -467,6 +468,84 @@ export default angular.module('thingsboard.types', [])
list: 'entity.type-current-customer'
}
},
entityField: {
createdTime: {
keyName: 'createdTime',
name: 'entity-field.created-time',
value: 'createdTime',
time: true
},
name: {
keyName: 'name',
name: 'entity-field.name',
value: 'name'
},
type: {
keyName: 'type',
name: 'entity-field.type',
value: 'type'
},
firstName: {
keyName: 'firstName',
name: 'entity-field.first-name',
value: 'firstName'
},
lastName: {
keyName: 'lastName',
name: 'entity-field.last-name',
value: 'lastName'
},
email: {
keyName: 'email',
name: 'entity-field.email',
value: 'email'
},
title: {
keyName: 'title',
name: 'entity-field.title',
value: 'title'
},
country: {
keyName: 'country',
name: 'entity-field.country',
value: 'country'
},
state: {
keyName: 'state',
name: 'entity-field.state',
value: 'state'
},
city: {
keyName: 'city',
name: 'entity-field.city',
value: 'city'
},
address: {
keyName: 'address',
name: 'entity-field.address',
value: 'address'
},
address2: {
keyName: 'address2',
name: 'entity-field.address2',
value: 'address2'
},
zip: {
keyName: 'zip',
name: 'entity-field.zip',
value: 'zip'
},
phone: {
keyName: 'phone',
name: 'entity-field.phone',
value: 'phone'
},
label: {
keyName: 'label',
name: 'entity-field.label',
value: 'label'
}
},
entitySearchDirection: {
from: "FROM",
to: "TO"

View File

@ -16,9 +16,7 @@
-->
<md-content class="md-padding" layout="column">
<md-autocomplete ng-if="model.type === types.dataKeyType.timeseries ||
model.type === types.dataKeyType.attribute ||
model.type === types.dataKeyType.alarm"
<md-autocomplete ng-if="model.type !== types.dataKeyType.function"
style="padding-bottom: 8px;"
ng-required="true"
md-no-cache="true"
@ -87,4 +85,4 @@
prevOrigValue - {{ 'datakey.prev-orig-value-description' | translate }}
</label>
</section>
</md-content>
</md-content>

View File

@ -124,7 +124,7 @@ function DatasourceEntity($compile, $templateCache, $q, $mdDialog, $window, $doc
var alarmDataKeys = [];
for (var d in ngModelCtrl.$viewValue.dataKeys) {
var dataKey = ngModelCtrl.$viewValue.dataKeys[d];
if ((dataKey.type === types.dataKeyType.timeseries) || (dataKey.type === types.dataKeyType.attribute)) {
if ((dataKey.type === types.dataKeyType.timeseries) || (dataKey.type === types.dataKeyType.attribute) || (dataKey.type === types.dataKeyType.entityField)) {
dataKeys.push(dataKey);
} else if (dataKey.type === types.dataKeyType.alarm) {
alarmDataKeys.push(dataKey);
@ -219,7 +219,7 @@ function DatasourceEntity($compile, $templateCache, $q, $mdDialog, $window, $doc
w.triggerHandler('resize');
}
}).then(function (newDataKey) {
if ((newDataKey.type === types.dataKeyType.timeseries) || (newDataKey.type === types.dataKeyType.attribute)) {
if ((newDataKey.type === types.dataKeyType.timeseries) || (newDataKey.type === types.dataKeyType.attribute) || (newDataKey.type === types.dataKeyType.entityField)) {
let index = scope.dataKeys.indexOf(dataKey);
scope.dataKeys[index] = newDataKey;
} else if (newDataKey.type === types.dataKeyType.alarm) {
@ -246,10 +246,16 @@ function DatasourceEntity($compile, $templateCache, $q, $mdDialog, $window, $doc
items.push({ name: dataKeys[i], type: types.dataKeyType.timeseries });
}
if (scope.widgetType == types.widgetType.latest.value) {
scope.fetchEntityKeys({entityAliasId: scope.entityAlias.id, query: searchText, type: types.dataKeyType.attribute})
.then(function (dataKeys) {
var keysType = [types.dataKeyType.attribute, types.dataKeyType.entityField];
var promises = [];
keysType.forEach((type) => {
promises.push(scope.fetchEntityKeys({entityAliasId: scope.entityAlias.id, query: searchText, type: type}));
});
$q.all(promises).then(function (dataKeys) {
for (var i = 0; i < dataKeys.length; i++) {
items.push({ name: dataKeys[i], type: types.dataKeyType.attribute });
for (var j = 0; j < dataKeys[i].length; j++) {
items.push({name: dataKeys[i][j], type: keysType[i]});
}
}
deferred.resolve(items);
}, function (e) {

View File

@ -43,6 +43,10 @@
<md-tooltip>{{'datakey.attributes' | translate }}</md-tooltip>
<ng-md-icon size="16" icon="alpha-a-circle-outline"></ng-md-icon>
</span>
<span ng-show="item.type==types.dataKeyType.entityField">
<md-tooltip>{{'datakey.entityField' | translate }}</md-tooltip>
<ng-md-icon size="16" icon="alpha-e-circle-outline"></ng-md-icon>
</span>
<span ng-show="item.type==types.dataKeyType.timeseries">
<md-tooltip>{{'datakey.timeseries' | translate }}</md-tooltip>
<ng-md-icon size="16" icon="timeline"></ng-md-icon>
@ -60,6 +64,10 @@
<md-tooltip>{{'datakey.attributes' | translate }}</md-tooltip>
<ng-md-icon size="16" icon="alpha-a-circle-outline" ng-click="createKey($event, types.dataKeyType.attribute, '#datakey_chips')"></ng-md-icon>
</span>
<span ng-show="widgetType == types.widgetType.latest.value">
<md-tooltip>{{'datakey.entityField' | translate }}</md-tooltip>
<ng-md-icon size="16" icon="alpha-e-circle-outline" ng-click="createKey($event, types.dataKeyType.entityField, '#datakey_chips')"></ng-md-icon>
</span>
<span>
<md-tooltip>{{'datakey.timeseries' | translate }}</md-tooltip>
<ng-md-icon size="16" icon="timeline" ng-click="createKey($event, types.dataKeyType.timeseries, '#datakey_chips')"></ng-md-icon>
@ -81,6 +89,10 @@
<span ng-show="$chip.type==types.dataKeyType.attribute">
<md-tooltip>{{'datakey.attributes' | translate }}</md-tooltip>
<ng-md-icon size="20" icon="alpha-a-circle-outline"></ng-md-icon>
</span>
<span ng-show="$chip.type==types.dataKeyType.entityField">
<md-tooltip>{{'datakey.entityField' | translate }}</md-tooltip>
<ng-md-icon size="20" icon="alpha-e-circle-outline"></ng-md-icon>
</span>
<span ng-show="$chip.type==types.dataKeyType.timeseries">
<md-tooltip>{{'datakey.timeseries' | translate }}</md-tooltip>

View File

@ -423,10 +423,10 @@ function WidgetConfig($compile, $templateCache, $rootScope, $translate, $timeout
}
var label = chip;
if (type === types.dataKeyType.alarm) {
var alarmField = types.alarmFields[chip];
if (alarmField) {
label = $translate.instant(alarmField.name)+'';
if (type === types.dataKeyType.alarm || type === types.dataKeyType.entityField) {
var keyField = type === types.dataKeyType.alarm ? types.alarmFields[chip] : types.entityField[chip];
if (keyField) {
label = $translate.instant(keyField.name)+'';
}
}
label = scope.genNextLabel(label);

View File

@ -1102,6 +1102,22 @@
"copyId": "Αντιγραφή ID ομάδας οντοτήτων",
"idCopiedMessage": "Το ID της ομάδας οντοτήτων έχει αντιγραφεί στο πρόχειρο"
},
"entity-field": {
"created-time": "Δημιουργήθηκε",
"name": "Όνομα",
"type": "Τύπος",
"first-name": "Όνομα",
"last-name": "Επίθετο",
"email": "Email",
"title": "Τίτλος",
"country": "Χώρα",
"state": "Νομός",
"city": "Πόλη",
"address": "Διεύθυνση",
"address2": "Διεύθυνση 2",
"zip": "Τ.Κ.",
"phone": "Τηλέφωνο"
},
"entity-view": {
"entity-view": "Όψη Οντότητας",
"entity-view-required": "Απαιτείται προβολή οντότητας.",
@ -2603,4 +2619,4 @@
"el_GR": "Ελληνικά"
}
}
}
}

View File

@ -815,6 +815,23 @@
"no-data": "No data to display",
"columns-to-display": "Columns to Display"
},
"entity-field": {
"created-time": "Created time",
"name": "Name",
"type": "Type",
"first-name": "First name",
"last-name": "Last name",
"email": "Email",
"title": "Title",
"country": "Country",
"state": "State",
"city": "City",
"address": "Address",
"address2": "Address 2",
"zip": "Zip",
"phone": "Phone",
"label": "Label"
},
"entity-view": {
"entity-view": "Entity View",
"entity-view-required": "Entity view is required.",

View File

@ -808,6 +808,22 @@
"no-data": "No hay datos para mostrar",
"columns-to-display": "Columnas a mostrar"
},
"entity-field": {
"created-time": "Tiempo de creación",
"name": "Nombre",
"type": "Tipo",
"first-name": "Nombre",
"last-name": "Apellido",
"email": "Correo electrónico",
"title": "Título",
"country": "País",
"state": "Estado",
"city": "Ciudad",
"address": "Dirección",
"address2": "Dirección 2",
"zip": "Código postal",
"phone": "Teléfono"
},
"entity-view": {
"entity-view": "Vista de entidad",
"entity-view-required": "Vista de entidad es requerido.",

View File

@ -809,6 +809,22 @@
"use-entity-name-filter": "Utiliser un filtre",
"user-name-starts-with": "Utilisateurs dont les noms commencent par '{{prefix}}'"
},
"entity-field": {
"address": "Adresse",
"address2": "Adresse 2",
"city": "Ville",
"country": "Pays",
"created-time": "Heure de création",
"email": "Email",
"first-name": "Prénom",
"last-name": "Nom de famille",
"name": "Nom",
"phone": "Téléphone",
"state": "Prov",
"title": "Titre",
"type": "Type",
"zip": "Code postal"
},
"entity-view": {
"add": "Ajouter une vue d'entité",
"add-alias": "Ajouter un alias de vue d'entité",

View File

@ -814,6 +814,23 @@
"no-data": "Нет данных для отображения",
"columns-to-display": "Отобразить следующие колонки"
},
"entity-field": {
"created-time": "Время создания",
"name": "Название",
"type": "Тип",
"first-name": "Имя",
"last-name": "Фамилия",
"email": "Электронная почта",
"title": "Название",
"country": "Страна",
"state": "Штат/Область",
"city": "Город",
"address": "Адрес",
"address2": "Адрес 2",
"zip": "Индекс",
"phone": "Телефон",
"label": "Метка"
},
"entity-view": {
"entity-view": "Представление Объекта",
"entity-view-required": "Представление объекта обязательно.",

View File

@ -956,6 +956,23 @@
"list-of-integrations": "{ count, plural, 1 {Одна інтеграція} other {Список # інтеграцій} }",
"integration-name-starts-with": "Інтеграції, імена яких починаються з '{{prefix}}'"
},
"entity-field": {
"created-time": "Час створення",
"name": "Ім'я",
"type": "Тип",
"first-name": "Ім'я",
"last-name": "Прізвище",
"email": "Електронна пошта",
"title": "Назва",
"country": "Країна",
"state": "Штат",
"city": "Місто",
"address": "Адреса",
"address2": "Адреса 2",
"zip": "Zip",
"phone": "Телефон",
"label": "Мітка"
},
"entity-group": {
"entity-group": "Група сутності",
"details": "Деталі",