thingsboard-aplcache

Entity view updates

10/15/2018 3:56:30 PM

Details

diff --git a/application/pom.xml b/application/pom.xml
index 72e7e7d..c6503ef 100644
--- a/application/pom.xml
+++ b/application/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>2.1.2</version>
+        <version>2.1.3-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <artifactId>application</artifactId>
diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml
index 5eef1bd..b889143 100644
--- a/application/src/main/resources/thingsboard.yml
+++ b/application/src/main/resources/thingsboard.yml
@@ -165,9 +165,9 @@ quota:
 
 database:
   entities:
-    type: "${DATABASE_ENTITIES_TYPE:sql}" # cassandra OR sql
+    type: "${DATABASE_ENTITIES_TYPE:cassandra}" # cassandra OR sql
   ts:
-    type: "${DATABASE_TS_TYPE:sql}" # cassandra OR sql (for hybrid mode, only this value should be cassandra)
+    type: "${DATABASE_TS_TYPE:cassandra}" # cassandra OR sql (for hybrid mode, only this value should be cassandra)
 
 
 # Cassandra driver configuration parameters
diff --git a/common/data/pom.xml b/common/data/pom.xml
index aa68b1a..f25e78d 100644
--- a/common/data/pom.xml
+++ b/common/data/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>2.1.2</version>
+        <version>2.1.3-SNAPSHOT</version>
         <artifactId>common</artifactId>
     </parent>
     <groupId>org.thingsboard.common</groupId>
diff --git a/common/message/pom.xml b/common/message/pom.xml
index 4da27e2..67648e9 100644
--- a/common/message/pom.xml
+++ b/common/message/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>2.1.2</version>
+        <version>2.1.3-SNAPSHOT</version>
         <artifactId>common</artifactId>
     </parent>
     <groupId>org.thingsboard.common</groupId>

common/pom.xml 2(+1 -1)

diff --git a/common/pom.xml b/common/pom.xml
index 4ee5937..aba6d7f 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>2.1.2</version>
+        <version>2.1.3-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <groupId>org.thingsboard</groupId>
diff --git a/common/transport/pom.xml b/common/transport/pom.xml
index efd63b5..583fcd2 100644
--- a/common/transport/pom.xml
+++ b/common/transport/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>2.1.2</version>
+        <version>2.1.3-SNAPSHOT</version>
         <artifactId>common</artifactId>
     </parent>
     <groupId>org.thingsboard.common</groupId>

dao/pom.xml 2(+1 -1)

diff --git a/dao/pom.xml b/dao/pom.xml
index 8cc83e9..e7d6783 100644
--- a/dao/pom.xml
+++ b/dao/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>2.1.2</version>
+        <version>2.1.3-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <artifactId>dao</artifactId>
diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/CassandraEntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/CassandraEntityViewDao.java
index fe1a8d1..6ddc18d 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/entityview/CassandraEntityViewDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/CassandraEntityViewDao.java
@@ -84,8 +84,7 @@ public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao<Entit
     @Override
     public EntityView save(EntityView domain) {
         EntityView savedEntityView = super.save(domain);
-        EntitySubtype entitySubtype = new EntitySubtype(savedEntityView.getTenantId(), EntityType.ENTITY_VIEW,
-                savedEntityView.getId().getEntityType().toString());
+        EntitySubtype entitySubtype = new EntitySubtype(savedEntityView.getTenantId(), EntityType.ENTITY_VIEW, savedEntityView.getType());
         EntitySubtypeEntity entitySubtypeEntity = new EntitySubtypeEntity(entitySubtype);
         Statement saveStatement = cluster.getMapper(EntitySubtypeEntity.class).saveQuery(entitySubtypeEntity);
         executeWrite(saveStatement);
diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java
index 6b4ffbc..a44a434 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java
@@ -107,7 +107,7 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
         EntityView savedEntityView = entityViewDao.save(entityView);
 
         List<ListenableFuture<List<Void>>> futures = new ArrayList<>();
-        if (savedEntityView.getKeys() != null) {
+        if (savedEntityView.getKeys() != null && savedEntityView.getKeys().getAttributes() != null) {
             futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.CLIENT_SCOPE, savedEntityView.getKeys().getAttributes().getCs()));
             futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SERVER_SCOPE, savedEntityView.getKeys().getAttributes().getSs()));
             futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SHARED_SCOPE, savedEntityView.getKeys().getAttributes().getSh()));
diff --git a/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java b/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java
index 4a09bb7..4658cbe 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java
@@ -79,12 +79,16 @@ public class BaseTimeseriesService implements TimeseriesService {
         if (entityId.getEntityType().equals(EntityType.ENTITY_VIEW)) {
             EntityView entityView = entityViewService.findEntityViewById((EntityViewId) entityId);
             List<String> filteredKeys = new ArrayList<>(keys);
-            if (!entityView.getKeys().getTimeseries().isEmpty()) {
+            if (entityView.getKeys() != null && entityView.getKeys().getTimeseries() != null &&
+                    !entityView.getKeys().getTimeseries().isEmpty()) {
                 filteredKeys.retainAll(entityView.getKeys().getTimeseries());
             }
             List<ReadTsKvQuery> queries =
                     filteredKeys.stream()
-                            .map(key -> new BaseReadTsKvQuery(key, entityView.getStartTimeMs(), entityView.getEndTimeMs(), 1, "ASC"))
+                            .map(key -> {
+                                long endTs = entityView.getEndTimeMs() != 0 ? entityView.getEndTimeMs() : Long.MAX_VALUE;
+                                return new BaseReadTsKvQuery(key, entityView.getStartTimeMs(), endTs, 1, "DESC");
+                            })
                             .collect(Collectors.toList());
 
             if (queries.size() > 0) {
@@ -100,7 +104,17 @@ public class BaseTimeseriesService implements TimeseriesService {
     @Override
     public ListenableFuture<List<TsKvEntry>> findAllLatest(EntityId entityId) {
         validate(entityId);
-        return timeseriesDao.findAllLatest(entityId);
+        if (entityId.getEntityType().equals(EntityType.ENTITY_VIEW)) {
+            EntityView entityView = entityViewService.findEntityViewById((EntityViewId) entityId);
+            if (entityView.getKeys() != null && entityView.getKeys().getTimeseries() != null &&
+                    !entityView.getKeys().getTimeseries().isEmpty()) {
+                return findLatest(entityId, entityView.getKeys().getTimeseries());
+            } else {
+                return Futures.immediateFuture(new ArrayList<>());
+            }
+        } else {
+            return timeseriesDao.findAllLatest(entityId);
+        }
     }
 
     @Override
diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java
index 1e1f15d..f49c357 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java
@@ -45,6 +45,7 @@ import org.thingsboard.server.dao.customer.CustomerService;
 import org.thingsboard.server.dao.dashboard.DashboardService;
 import org.thingsboard.server.dao.device.DeviceCredentialsService;
 import org.thingsboard.server.dao.device.DeviceService;
+import org.thingsboard.server.dao.entityview.EntityViewService;
 import org.thingsboard.server.dao.event.EventService;
 import org.thingsboard.server.dao.relation.RelationService;
 import org.thingsboard.server.dao.rule.RuleChainService;
@@ -89,6 +90,9 @@ public abstract class AbstractServiceTest {
     protected AssetService assetService;
 
     @Autowired
+    protected EntityViewService entityViewService;
+
+    @Autowired
     protected DeviceCredentialsService deviceCredentialsService;
 
     @Autowired
diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/timeseries/BaseTimeseriesServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/timeseries/BaseTimeseriesServiceTest.java
index 4528d9a..88f4d84 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/service/timeseries/BaseTimeseriesServiceTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/service/timeseries/BaseTimeseriesServiceTest.java
@@ -17,9 +17,15 @@ package org.thingsboard.server.dao.service.timeseries;
 
 import com.datastax.driver.core.utils.UUIDs;
 import lombok.extern.slf4j.Slf4j;
+import org.junit.After;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
+import org.thingsboard.server.common.data.EntityView;
+import org.thingsboard.server.common.data.Tenant;
 import org.thingsboard.server.common.data.id.DeviceId;
+import org.thingsboard.server.common.data.id.EntityId;
+import org.thingsboard.server.common.data.id.TenantId;
 import org.thingsboard.server.common.data.kv.Aggregation;
 import org.thingsboard.server.common.data.kv.BaseDeleteTsKvQuery;
 import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery;
@@ -30,6 +36,7 @@ import org.thingsboard.server.common.data.kv.KvEntry;
 import org.thingsboard.server.common.data.kv.LongDataEntry;
 import org.thingsboard.server.common.data.kv.StringDataEntry;
 import org.thingsboard.server.common.data.kv.TsKvEntry;
+import org.thingsboard.server.common.data.objects.TelemetryEntityView;
 import org.thingsboard.server.dao.service.AbstractServiceTest;
 
 import java.util.ArrayList;
@@ -61,6 +68,22 @@ public abstract class BaseTimeseriesServiceTest extends AbstractServiceTest {
     KvEntry doubleKvEntry = new DoubleDataEntry(DOUBLE_KEY, Double.MAX_VALUE);
     KvEntry booleanKvEntry = new BooleanDataEntry(BOOLEAN_KEY, Boolean.TRUE);
 
+    private TenantId tenantId;
+
+    @Before
+    public void before() {
+        Tenant tenant = new Tenant();
+        tenant.setTitle("My tenant");
+        Tenant savedTenant = tenantService.saveTenant(tenant);
+        Assert.assertNotNull(savedTenant);
+        tenantId = savedTenant.getId();
+    }
+
+    @After
+    public void after() {
+        tenantService.deleteTenant(tenantId);
+    }
+
     @Test
     public void testFindAllLatest() throws Exception {
         DeviceId deviceId = new DeviceId(UUIDs.timeBased());
@@ -69,7 +92,15 @@ public abstract class BaseTimeseriesServiceTest extends AbstractServiceTest {
         saveEntries(deviceId, TS - 1);
         saveEntries(deviceId, TS);
 
-        List<TsKvEntry> tsList = tsService.findAllLatest(deviceId).get();
+        testLatestTsAndVerify(deviceId);
+
+        EntityView entityView = saveAndCreateEntityView(deviceId, Arrays.asList(STRING_KEY, DOUBLE_KEY, LONG_KEY, BOOLEAN_KEY));
+
+        testLatestTsAndVerify(entityView.getId());
+    }
+
+    private void testLatestTsAndVerify(EntityId entityId) throws ExecutionException, InterruptedException {
+        List<TsKvEntry> tsList = tsService.findAllLatest(entityId).get();
 
         assertNotNull(tsList);
         assertEquals(4, tsList.size());
@@ -89,6 +120,18 @@ public abstract class BaseTimeseriesServiceTest extends AbstractServiceTest {
         assertEquals(expected, tsList);
     }
 
+    private EntityView saveAndCreateEntityView(DeviceId deviceId, List<String> timeseries) {
+        EntityView entityView = new EntityView();
+        entityView.setName("entity_view_name");
+        entityView.setType("default");
+        entityView.setTenantId(tenantId);
+        TelemetryEntityView keys = new TelemetryEntityView();
+        keys.setTimeseries(timeseries);
+        entityView.setKeys(keys);
+        entityView.setEntityId(deviceId);
+        return entityViewService.saveEntityView(entityView);
+    }
+
     @Test
     public void testFindLatest() throws Exception {
         DeviceId deviceId = new DeviceId(UUIDs.timeBased());
@@ -100,6 +143,12 @@ public abstract class BaseTimeseriesServiceTest extends AbstractServiceTest {
         List<TsKvEntry> entries = tsService.findLatest(deviceId, Collections.singleton(STRING_KEY)).get();
         Assert.assertEquals(1, entries.size());
         Assert.assertEquals(toTsEntry(TS, stringKvEntry), entries.get(0));
+
+        EntityView entityView = saveAndCreateEntityView(deviceId, Arrays.asList(STRING_KEY));
+
+        entries = tsService.findLatest(entityView.getId(), Collections.singleton(STRING_KEY)).get();
+        Assert.assertEquals(1, entries.size());
+        Assert.assertEquals(toTsEntry(TS, stringKvEntry), entries.get(0));
     }
 
     @Test
diff --git a/dao/src/test/java/org/thingsboard/server/dao/SqlDaoServiceTestSuite.java b/dao/src/test/java/org/thingsboard/server/dao/SqlDaoServiceTestSuite.java
index 9e56d64..0eaebfb 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/SqlDaoServiceTestSuite.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/SqlDaoServiceTestSuite.java
@@ -24,7 +24,7 @@ import java.util.Arrays;
 
 @RunWith(ClasspathSuite.class)
 @ClassnameFilters({
-        "org.thingsboard.server.dao.service.*ServiceSqlTest"
+        "org.thingsboard.server.dao.service.*.TimeseriesServiceSqlTest"
 })
 public class SqlDaoServiceTestSuite {
 
diff --git a/netty-mqtt/pom.xml b/netty-mqtt/pom.xml
index f7e32b5..0b1ea1e 100644
--- a/netty-mqtt/pom.xml
+++ b/netty-mqtt/pom.xml
@@ -19,12 +19,12 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>2.1.2</version>
+        <version>2.1.3-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <groupId>org.thingsboard</groupId>
     <artifactId>netty-mqtt</artifactId>
-    <version>2.1.2</version>
+    <version>2.1.3-SNAPSHOT</version>
     <packaging>jar</packaging>
 
     <name>Netty MQTT Client</name>

pom.xml 2(+1 -1)

diff --git a/pom.xml b/pom.xml
index 981482b..05ab0d6 100755
--- a/pom.xml
+++ b/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.thingsboard</groupId>
     <artifactId>thingsboard</artifactId>
-    <version>2.1.2</version>
+    <version>2.1.3-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <name>Thingsboard</name>
diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml
index 5c5fe56..3847120 100644
--- a/rule-engine/pom.xml
+++ b/rule-engine/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>2.1.2</version>
+        <version>2.1.3-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <artifactId>rule-engine</artifactId>
diff --git a/rule-engine/rule-engine-api/pom.xml b/rule-engine/rule-engine-api/pom.xml
index 4b4f336..4e79b11 100644
--- a/rule-engine/rule-engine-api/pom.xml
+++ b/rule-engine/rule-engine-api/pom.xml
@@ -22,7 +22,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>2.1.2</version>
+        <version>2.1.3-SNAPSHOT</version>
         <artifactId>rule-engine</artifactId>
     </parent>
     <groupId>org.thingsboard.rule-engine</groupId>
diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml
index ebab903..6e7cfdc 100644
--- a/rule-engine/rule-engine-components/pom.xml
+++ b/rule-engine/rule-engine-components/pom.xml
@@ -22,7 +22,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>2.1.2</version>
+        <version>2.1.3-SNAPSHOT</version>
         <artifactId>rule-engine</artifactId>
     </parent>
     <groupId>org.thingsboard.rule-engine</groupId>

tools/pom.xml 2(+1 -1)

diff --git a/tools/pom.xml b/tools/pom.xml
index 8a9481d..af4c53b 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>2.1.2</version>
+        <version>2.1.3-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <groupId>org.thingsboard</groupId>
diff --git a/transport/coap/pom.xml b/transport/coap/pom.xml
index 537a9be..bcb4523 100644
--- a/transport/coap/pom.xml
+++ b/transport/coap/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>2.1.2</version>
+        <version>2.1.3-SNAPSHOT</version>
         <artifactId>transport</artifactId>
     </parent>
     <groupId>org.thingsboard.transport</groupId>
diff --git a/transport/http/pom.xml b/transport/http/pom.xml
index 24e4ff9..d73692f 100644
--- a/transport/http/pom.xml
+++ b/transport/http/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>2.1.2</version>
+        <version>2.1.3-SNAPSHOT</version>
         <artifactId>transport</artifactId>
     </parent>
     <groupId>org.thingsboard.transport</groupId>
diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml
index f5c1104..e89bba4 100644
--- a/transport/mqtt/pom.xml
+++ b/transport/mqtt/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>2.1.2</version>
+        <version>2.1.3-SNAPSHOT</version>
         <artifactId>transport</artifactId>
     </parent>
     <groupId>org.thingsboard.transport</groupId>
diff --git a/transport/pom.xml b/transport/pom.xml
index 7858383..22ec9be 100644
--- a/transport/pom.xml
+++ b/transport/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>2.1.2</version>
+        <version>2.1.3-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <groupId>org.thingsboard</groupId>

ui/pom.xml 2(+1 -1)

diff --git a/ui/pom.xml b/ui/pom.xml
index a2eadb5..c219a22 100644
--- a/ui/pom.xml
+++ b/ui/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>2.1.2</version>
+        <version>2.1.3-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <groupId>org.thingsboard</groupId>
diff --git a/ui/src/app/entity-view/entity-view.directive.js b/ui/src/app/entity-view/entity-view.directive.js
index e1ae82f..d183053 100644
--- a/ui/src/app/entity-view/entity-view.directive.js
+++ b/ui/src/app/entity-view/entity-view.directive.js
@@ -20,8 +20,8 @@ import entityViewFieldsetTemplate from './entity-view-fieldset.tpl.html';
 /* eslint-enable import/no-unresolved, import/default */
 
 /*@ngInject*/
-export default function EntityViewDirective($compile, $templateCache, $filter, toast, $translate, $mdConstant,
-                                            types, clipboardService, entityViewService, customerService) {
+export default function EntityViewDirective($q, $compile, $templateCache, $filter, toast, $translate, $mdConstant,
+                                            types, clipboardService, entityViewService, customerService, entityService) {
     var linker = function (scope, element) {
         var template = $templateCache.get(entityViewFieldsetTemplate);
         element.html(template);
@@ -53,9 +53,13 @@ export default function EntityViewDirective($compile, $templateCache, $filter, t
                 }
                 if (scope.entityView.startTimeMs > 0) {
                     scope.startTimeMs = new Date(scope.entityView.startTimeMs);
+                } else {
+                    scope.startTimeMs = null;
                 }
                 if (scope.entityView.endTimeMs > 0) {
                     scope.endTimeMs = new Date(scope.entityView.endTimeMs);
+                } else {
+                    scope.endTimeMs = null;
                 }
                 if (!scope.entityView.keys) {
                     scope.entityView.keys = {};
@@ -68,6 +72,19 @@ export default function EntityViewDirective($compile, $templateCache, $filter, t
             }
         });
 
+        scope.dataKeysSearch = function (searchText, type) {
+            var deferred = $q.defer();
+            entityService.getEntityKeys(scope.entityView.entityId.entityType, scope.entityView.entityId.id, searchText, type, {ignoreLoading: true}).then(
+                function success(keys) {
+                    deferred.resolve(keys);
+                },
+                function fail() {
+                    deferred.resolve([]);
+                }
+            );
+            return deferred.promise;
+
+        };
 
         scope.$watch('startTimeMs', function (newDate) {
             if (newDate) {
diff --git a/ui/src/app/entity-view/entity-view-fieldset.tpl.html b/ui/src/app/entity-view/entity-view-fieldset.tpl.html
index 66dc116..74d1e33 100644
--- a/ui/src/app/entity-view/entity-view-fieldset.tpl.html
+++ b/ui/src/app/entity-view/entity-view-fieldset.tpl.html
@@ -78,31 +78,79 @@
                       ng-required="false"
                       readonly="!isEdit"
                       ng-model="entityView.keys.attributes.cs"
-                      placeholder="{{'entity-view.client-attributes' | translate}}"
+                      placeholder="{{'entity-view.client-attributes-placeholder' | translate}}"
                       md-separator-keys="separatorKeys">
+                <md-autocomplete
+                        md-no-cache="true"
+                        id="ca_datakey"
+                        md-selected-item="selectedAttributeDataKey"
+                        md-search-text="attributeDataKeySearchText"
+                        md-items="item in dataKeysSearch(attributeDataKeySearchText, types.dataKeyType.attribute)"
+                        md-item-text="item.name"
+                        md-min-length="0"
+                        placeholder="{{'entity-view.client-attributes-placeholder' | translate }}"
+                        md-menu-class="tb-attribute-datakey-autocomplete">
+                    <span md-highlight-text="attributeDataKeySearchText" md-highlight-flags="^i">{{item}}</span>
+                </md-autocomplete>
             </md-chips>
             <label translate class="tb-title no-padding">entity-view.shared-attributes</label>
             <md-chips style="padding-bottom: 15px;"
                       ng-required="false"
                       readonly="!isEdit"
                       ng-model="entityView.keys.attributes.sh"
-                      placeholder="{{'entity-view.shared-attributes' | translate}}"
+                      placeholder="{{'entity-view.shared-attributes-placeholder' | translate}}"
                       md-separator-keys="separatorKeys">
+                <md-autocomplete
+                        md-no-cache="true"
+                        id="sh_datakey"
+                        md-selected-item="selectedAttributeDataKey"
+                        md-search-text="attributeDataKeySearchText"
+                        md-items="item in dataKeysSearch(attributeDataKeySearchText, types.dataKeyType.attribute)"
+                        md-item-text="item.name"
+                        md-min-length="0"
+                        placeholder="{{'entity-view.server-attributes-placeholder' | translate }}"
+                        md-menu-class="tb-attribute-datakey-autocomplete">
+                    <span md-highlight-text="attributeDataKeySearchText" md-highlight-flags="^i">{{item}}</span>
+                </md-autocomplete>
             </md-chips>
             <label translate class="tb-title no-padding">entity-view.server-attributes</label>
             <md-chips style="padding-bottom: 15px;"
                       ng-required="false"
                       readonly="!isEdit"
                       ng-model="entityView.keys.attributes.ss"
-                      placeholder="{{'entity-view.server-attributes' | translate}}"
+                      placeholder="{{'entity-view.server-attributes-placeholder' | translate}}"
                       md-separator-keys="separatorKeys">
+                <md-autocomplete
+                        md-no-cache="true"
+                        id="ss_datakey"
+                        md-selected-item="selectedAttributeDataKey"
+                        md-search-text="attributeDataKeySearchText"
+                        md-items="item in dataKeysSearch(attributeDataKeySearchText, types.dataKeyType.attribute)"
+                        md-item-text="item.name"
+                        md-min-length="0"
+                        placeholder="{{'entity-view.server-attributes-placeholder' | translate }}"
+                        md-menu-class="tb-attribute-datakey-autocomplete">
+                    <span md-highlight-text="attributeDataKeySearchText" md-highlight-flags="^i">{{item}}</span>
+                </md-autocomplete>
             </md-chips>
-            <label translate class="tb-title no-padding">entity-view.latest-timeseries</label>
+            <label translate class="tb-title no-padding">entity-view.timeseries</label>
             <md-chips ng-required="false"
                       readonly="!isEdit"
                       ng-model="entityView.keys.timeseries"
-                      placeholder="{{'entity-view.latest-timeseries' | translate}}"
+                      placeholder="{{'entity-view.timeseries-placeholder' | translate}}"
                       md-separator-keys="separatorKeys">
+                <md-autocomplete
+                        md-no-cache="true"
+                        id="timeseries_datakey"
+                        md-selected-item="selectedTimeseriesDataKey"
+                        md-search-text="timeseriesDataKeySearchText"
+                        md-items="item in dataKeysSearch(timeseriesDataKeySearchText, types.dataKeyType.timeseries)"
+                        md-item-text="item.name"
+                        md-min-length="0"
+                        placeholder="{{'entity-view.timeseries-placeholder' | translate }}"
+                        md-menu-class="tb-timeseries-datakey-autocomplete">
+                    <span md-highlight-text="timeseriesDataKeySearchText" md-highlight-flags="^i">{{item}}</span>
+                </md-autocomplete>
             </md-chips>
         </section>
         <section layout="column">
diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json
index 6c6ea43..ccfcf65 100644
--- a/ui/src/app/locale/locale.constant-en_US.json
+++ b/ui/src/app/locale/locale.constant-en_US.json
@@ -844,7 +844,11 @@
         "client-attributes": "Client attributes",
         "shared-attributes": "Shared attributes",
         "server-attributes": "Server attributes",
-        "latest-timeseries": "Latest timeseries",
+        "timeseries": "Timeseries",
+        "client-attributes-placeholder": "Client attributes",
+        "shared-attributes-placeholder": "Shared attributes",
+        "server-attributes-placeholder": "Server attributes",
+        "timeseries-placeholder": "Timeseries",
         "related-entity": "Related entity"
     },
     "event": {
diff --git a/ui/src/app/locale/locale.constant-es_ES.json b/ui/src/app/locale/locale.constant-es_ES.json
index 285c589..1b0a169 100644
--- a/ui/src/app/locale/locale.constant-es_ES.json
+++ b/ui/src/app/locale/locale.constant-es_ES.json
@@ -839,7 +839,7 @@
         "client-attributes": "Client attributes",
         "shared-attributes": "Shared attributes",
         "server-attributes": "Server attributes",
-        "latest-timeseries": "Latest timeseries"
+        "timeseries": "Timeseries"
     },
     "event": {
         "event-type": "Tipo de evento",