Commit 5bf9528ee8878f80dbe5dadf6787a9086208779c

Authored by Volodymyr Babak
1 parent 009da885

Fixes for entity view

@@ -19,17 +19,21 @@ import com.google.common.util.concurrent.ListenableFuture; @@ -19,17 +19,21 @@ import com.google.common.util.concurrent.ListenableFuture;
19 import org.springframework.http.HttpStatus; 19 import org.springframework.http.HttpStatus;
20 import org.springframework.security.access.prepost.PreAuthorize; 20 import org.springframework.security.access.prepost.PreAuthorize;
21 import org.springframework.web.bind.annotation.*; 21 import org.springframework.web.bind.annotation.*;
  22 +import org.thingsboard.server.common.data.EntitySubtype;
22 import org.thingsboard.server.common.data.EntityType; 23 import org.thingsboard.server.common.data.EntityType;
23 import org.thingsboard.server.common.data.EntityView; 24 import org.thingsboard.server.common.data.EntityView;
24 import org.thingsboard.server.common.data.audit.ActionType; 25 import org.thingsboard.server.common.data.audit.ActionType;
  26 +import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
25 import org.thingsboard.server.common.data.exception.ThingsboardException; 27 import org.thingsboard.server.common.data.exception.ThingsboardException;
26 -import org.thingsboard.server.common.data.id.CustomerId;  
27 import org.thingsboard.server.common.data.id.EntityViewId; 28 import org.thingsboard.server.common.data.id.EntityViewId;
28 import org.thingsboard.server.common.data.id.TenantId; 29 import org.thingsboard.server.common.data.id.TenantId;
  30 +import org.thingsboard.server.common.data.page.TextPageData;
  31 +import org.thingsboard.server.common.data.page.TextPageLink;
29 import org.thingsboard.server.service.security.model.SecurityUser; 32 import org.thingsboard.server.service.security.model.SecurityUser;
30 33
31 import java.util.ArrayList; 34 import java.util.ArrayList;
32 import java.util.List; 35 import java.util.List;
  36 +import java.util.stream.Collectors;
33 37
34 /** 38 /**
35 * Created by Victor Basanets on 8/28/2017. 39 * Created by Victor Basanets on 8/28/2017.
@@ -41,7 +45,7 @@ public class EntityViewController extends BaseController { @@ -41,7 +45,7 @@ public class EntityViewController extends BaseController {
41 public static final String ENTITY_VIEW_ID = "entityViewId"; 45 public static final String ENTITY_VIEW_ID = "entityViewId";
42 46
43 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 47 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
44 - @RequestMapping(value = "/entity-view/{entityViewId}", method = RequestMethod.GET) 48 + @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.GET)
45 @ResponseBody 49 @ResponseBody
46 public EntityView getEntityViewById(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) 50 public EntityView getEntityViewById(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId)
47 throws ThingsboardException { 51 throws ThingsboardException {
@@ -56,7 +60,7 @@ public class EntityViewController extends BaseController { @@ -56,7 +60,7 @@ public class EntityViewController extends BaseController {
56 } 60 }
57 61
58 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 62 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
59 - @RequestMapping(value = "/entity-view", method = RequestMethod.POST) 63 + @RequestMapping(value = "/entityView", method = RequestMethod.POST)
60 @ResponseBody 64 @ResponseBody
61 public EntityView saveEntityView(@RequestBody EntityView entityView) throws ThingsboardException { 65 public EntityView saveEntityView(@RequestBody EntityView entityView) throws ThingsboardException {
62 try { 66 try {
@@ -76,7 +80,7 @@ public class EntityViewController extends BaseController { @@ -76,7 +80,7 @@ public class EntityViewController extends BaseController {
76 } 80 }
77 81
78 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 82 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
79 - @RequestMapping(value = "/entity-view/{entityViewId}", method = RequestMethod.DELETE) 83 + @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.DELETE)
80 @ResponseStatus(value = HttpStatus.OK) 84 @ResponseStatus(value = HttpStatus.OK)
81 public void deleteEntityView(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { 85 public void deleteEntityView(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
82 checkParameter(ENTITY_VIEW_ID, strEntityViewId); 86 checkParameter(ENTITY_VIEW_ID, strEntityViewId);
@@ -95,4 +99,44 @@ public class EntityViewController extends BaseController { @@ -95,4 +99,44 @@ public class EntityViewController extends BaseController {
95 throw handleException(e); 99 throw handleException(e);
96 } 100 }
97 } 101 }
  102 +
  103 + @PreAuthorize("hasAuthority('TENANT_ADMIN')")
  104 + @RequestMapping(value = "/tenant/entityViews", params = {"limit"}, method = RequestMethod.GET)
  105 + @ResponseBody
  106 + public TextPageData<EntityView> getTenantEntityViews(
  107 + @RequestParam int limit,
  108 + @RequestParam(required = false) String textSearch,
  109 + @RequestParam(required = false) String idOffset,
  110 + @RequestParam(required = false) String textOffset) throws ThingsboardException {
  111 + try {
  112 + TenantId tenantId = getCurrentUser().getTenantId();
  113 + TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
  114 + return checkNotNull(entityViewService.findEntityViewByTenantId(tenantId, pageLink));
  115 + } catch (Exception e) {
  116 + throw handleException(e);
  117 + }
  118 + }
  119 +
  120 + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
  121 + @RequestMapping(value = "/entityViews", method = RequestMethod.POST)
  122 + @ResponseBody
  123 + public List<EntityView> findByQuery(@RequestBody EntityViewSearchQuery query) throws ThingsboardException {
  124 + checkNotNull(query);
  125 + checkNotNull(query.getParameters());
  126 + checkEntityId(query.getParameters().getEntityId());
  127 + try {
  128 + List<EntityView> entityViews = checkNotNull(entityViewService.findEntityViewsByQuery(query).get());
  129 + entityViews = entityViews.stream().filter(entityView -> {
  130 + try {
  131 + checkEntityView(entityView);
  132 + return true;
  133 + } catch (ThingsboardException e) {
  134 + return false;
  135 + }
  136 + }).collect(Collectors.toList());
  137 + return entityViews;
  138 + } catch (Exception e) {
  139 + throw handleException(e);
  140 + }
  141 + }
98 } 142 }
  1 +/**
  2 + * Copyright © 2016-2018 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.entityview;
  17 +
  18 +import lombok.Data;
  19 +import org.thingsboard.server.common.data.EntityType;
  20 +import org.thingsboard.server.common.data.relation.EntityRelation;
  21 +import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
  22 +import org.thingsboard.server.common.data.relation.EntityTypeFilter;
  23 +import org.thingsboard.server.common.data.relation.RelationsSearchParameters;
  24 +
  25 +import java.util.Collections;
  26 +import java.util.List;
  27 +
  28 +@Data
  29 +public class EntityViewSearchQuery {
  30 +
  31 + private RelationsSearchParameters parameters;
  32 + private String relationType;
  33 +
  34 + public EntityRelationsQuery toEntitySearchQuery() {
  35 + EntityRelationsQuery query = new EntityRelationsQuery();
  36 + query.setParameters(parameters);
  37 + query.setFilters(
  38 + Collections.singletonList(new EntityTypeFilter(relationType == null ? EntityRelation.CONTAINS_TYPE : relationType,
  39 + Collections.singletonList(EntityType.ENTITY_VIEW))));
  40 + return query;
  41 + }
  42 +}
@@ -16,7 +16,6 @@ @@ -16,7 +16,6 @@
16 package org.thingsboard.server.dao.entityview; 16 package org.thingsboard.server.dao.entityview;
17 17
18 import org.thingsboard.server.common.data.EntityView; 18 import org.thingsboard.server.common.data.EntityView;
19 -import org.thingsboard.server.common.data.id.EntityId;  
20 import org.thingsboard.server.common.data.page.TextPageLink; 19 import org.thingsboard.server.common.data.page.TextPageLink;
21 import org.thingsboard.server.dao.Dao; 20 import org.thingsboard.server.dao.Dao;
22 21
@@ -92,5 +91,4 @@ public interface EntityViewDao extends Dao<EntityView> { @@ -92,5 +91,4 @@ public interface EntityViewDao extends Dao<EntityView> {
92 UUID customerId, 91 UUID customerId,
93 UUID entityId, 92 UUID entityId,
94 TextPageLink pageLink); 93 TextPageLink pageLink);
95 -  
96 } 94 }
@@ -16,12 +16,18 @@ @@ -16,12 +16,18 @@
16 package org.thingsboard.server.dao.entityview; 16 package org.thingsboard.server.dao.entityview;
17 17
18 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
  19 +import org.thingsboard.server.common.data.Device;
  20 +import org.thingsboard.server.common.data.EntitySubtype;
19 import org.thingsboard.server.common.data.EntityType; 21 import org.thingsboard.server.common.data.EntityType;
20 import org.thingsboard.server.common.data.EntityView; 22 import org.thingsboard.server.common.data.EntityView;
  23 +import org.thingsboard.server.common.data.device.DeviceSearchQuery;
  24 +import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
21 import org.thingsboard.server.common.data.id.*; 25 import org.thingsboard.server.common.data.id.*;
22 import org.thingsboard.server.common.data.page.TextPageData; 26 import org.thingsboard.server.common.data.page.TextPageData;
23 import org.thingsboard.server.common.data.page.TextPageLink; 27 import org.thingsboard.server.common.data.page.TextPageLink;
24 28
  29 +import java.util.List;
  30 +
25 /** 31 /**
26 * Created by Victor Basanets on 8/27/2017. 32 * Created by Victor Basanets on 8/27/2017.
27 */ 33 */
@@ -57,4 +63,6 @@ public interface EntityViewService { @@ -57,4 +63,6 @@ public interface EntityViewService {
57 void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId); 63 void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId);
58 64
59 ListenableFuture<EntityView> findEntityViewByIdAsync(EntityViewId entityViewId); 65 ListenableFuture<EntityView> findEntityViewByIdAsync(EntityViewId entityViewId);
  66 +
  67 + ListenableFuture<List<EntityView>> findEntityViewsByQuery(EntityViewSearchQuery query);
60 } 68 }
@@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
15 */ 15 */
16 package org.thingsboard.server.dao.entityview; 16 package org.thingsboard.server.dao.entityview;
17 17
  18 +import com.google.common.base.Function;
  19 +import com.google.common.util.concurrent.Futures;
18 import com.google.common.util.concurrent.ListenableFuture; 20 import com.google.common.util.concurrent.ListenableFuture;
19 import lombok.extern.slf4j.Slf4j; 21 import lombok.extern.slf4j.Slf4j;
20 import org.apache.commons.lang3.StringUtils; 22 import org.apache.commons.lang3.StringUtils;
@@ -25,14 +27,22 @@ import org.springframework.cache.annotation.CacheEvict; @@ -25,14 +27,22 @@ import org.springframework.cache.annotation.CacheEvict;
25 import org.springframework.cache.annotation.Cacheable; 27 import org.springframework.cache.annotation.Cacheable;
26 import org.springframework.stereotype.Service; 28 import org.springframework.stereotype.Service;
27 import org.thingsboard.server.common.data.Customer; 29 import org.thingsboard.server.common.data.Customer;
  30 +import org.thingsboard.server.common.data.Device;
  31 +import org.thingsboard.server.common.data.EntitySubtype;
  32 +import org.thingsboard.server.common.data.EntityType;
28 import org.thingsboard.server.common.data.EntityView; 33 import org.thingsboard.server.common.data.EntityView;
29 import org.thingsboard.server.common.data.Tenant; 34 import org.thingsboard.server.common.data.Tenant;
  35 +import org.thingsboard.server.common.data.device.DeviceSearchQuery;
  36 +import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
30 import org.thingsboard.server.common.data.id.CustomerId; 37 import org.thingsboard.server.common.data.id.CustomerId;
  38 +import org.thingsboard.server.common.data.id.DeviceId;
31 import org.thingsboard.server.common.data.id.EntityId; 39 import org.thingsboard.server.common.data.id.EntityId;
32 import org.thingsboard.server.common.data.id.EntityViewId; 40 import org.thingsboard.server.common.data.id.EntityViewId;
33 import org.thingsboard.server.common.data.id.TenantId; 41 import org.thingsboard.server.common.data.id.TenantId;
34 import org.thingsboard.server.common.data.page.TextPageData; 42 import org.thingsboard.server.common.data.page.TextPageData;
35 import org.thingsboard.server.common.data.page.TextPageLink; 43 import org.thingsboard.server.common.data.page.TextPageLink;
  44 +import org.thingsboard.server.common.data.relation.EntityRelation;
  45 +import org.thingsboard.server.common.data.relation.EntitySearchDirection;
36 import org.thingsboard.server.dao.customer.CustomerDao; 46 import org.thingsboard.server.dao.customer.CustomerDao;
37 import org.thingsboard.server.dao.entity.AbstractEntityService; 47 import org.thingsboard.server.dao.entity.AbstractEntityService;
38 import org.thingsboard.server.dao.exception.DataValidationException; 48 import org.thingsboard.server.dao.exception.DataValidationException;
@@ -40,8 +50,12 @@ import org.thingsboard.server.dao.service.DataValidator; @@ -40,8 +50,12 @@ import org.thingsboard.server.dao.service.DataValidator;
40 import org.thingsboard.server.dao.service.PaginatedRemover; 50 import org.thingsboard.server.dao.service.PaginatedRemover;
41 import org.thingsboard.server.dao.tenant.TenantDao; 51 import org.thingsboard.server.dao.tenant.TenantDao;
42 52
  53 +import javax.annotation.Nullable;
43 import java.util.ArrayList; 54 import java.util.ArrayList;
  55 +import java.util.Collections;
  56 +import java.util.Comparator;
44 import java.util.List; 57 import java.util.List;
  58 +import java.util.stream.Collectors;
45 59
46 import static org.thingsboard.server.common.data.CacheConstants.DEVICE_CACHE; 60 import static org.thingsboard.server.common.data.CacheConstants.DEVICE_CACHE;
47 import static org.thingsboard.server.common.data.CacheConstants.ENTITY_VIEW_CACHE; 61 import static org.thingsboard.server.common.data.CacheConstants.ENTITY_VIEW_CACHE;
@@ -55,8 +69,7 @@ import static org.thingsboard.server.dao.service.Validator.validateString; @@ -55,8 +69,7 @@ import static org.thingsboard.server.dao.service.Validator.validateString;
55 */ 69 */
56 @Service 70 @Service
57 @Slf4j 71 @Slf4j
58 -public class EntityViewServiceImpl extends AbstractEntityService  
59 - implements EntityViewService { 72 +public class EntityViewServiceImpl extends AbstractEntityService implements EntityViewService {
60 73
61 public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; 74 public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
62 public static final String INCORRECT_PAGE_LINK = "Incorrect page link "; 75 public static final String INCORRECT_PAGE_LINK = "Incorrect page link ";
@@ -75,7 +88,7 @@ public class EntityViewServiceImpl extends AbstractEntityService @@ -75,7 +88,7 @@ public class EntityViewServiceImpl extends AbstractEntityService
75 @Autowired 88 @Autowired
76 private CacheManager cacheManager; 89 private CacheManager cacheManager;
77 90
78 - @Cacheable(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityViewId}") 91 +// @Cacheable(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityViewId}")
79 @Override 92 @Override
80 public EntityView findEntityViewById(EntityViewId entityViewId) { 93 public EntityView findEntityViewById(EntityViewId entityViewId) {
81 log.trace("Executing findEntityViewById [{}]", entityViewId); 94 log.trace("Executing findEntityViewById [{}]", entityViewId);
@@ -91,7 +104,7 @@ public class EntityViewServiceImpl extends AbstractEntityService @@ -91,7 +104,7 @@ public class EntityViewServiceImpl extends AbstractEntityService
91 .orElse(null); 104 .orElse(null);
92 } 105 }
93 106
94 - @CacheEvict(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityView.id}") 107 +// @CacheEvict(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityView.id}")
95 @Override 108 @Override
96 public EntityView saveEntityView(EntityView entityView) { 109 public EntityView saveEntityView(EntityView entityView) {
97 log.trace("Executing save entity view [{}]", entityView); 110 log.trace("Executing save entity view [{}]", entityView);
@@ -136,7 +149,7 @@ public class EntityViewServiceImpl extends AbstractEntityService @@ -136,7 +149,7 @@ public class EntityViewServiceImpl extends AbstractEntityService
136 return new TextPageData<>(entityViews, pageLink); 149 return new TextPageData<>(entityViews, pageLink);
137 } 150 }
138 151
139 - @Cacheable(cacheNames = ENTITY_VIEW_CACHE, key = "{#tenantId, #entityId, #pageLink}") 152 +// @Cacheable(cacheNames = ENTITY_VIEW_CACHE, key = "{#tenantId, #entityId, #pageLink}")
140 @Override 153 @Override
141 public TextPageData<EntityView> findEntityViewByTenantIdAndEntityId(TenantId tenantId, EntityId entityId, 154 public TextPageData<EntityView> findEntityViewByTenantIdAndEntityId(TenantId tenantId, EntityId entityId,
142 TextPageLink pageLink) { 155 TextPageLink pageLink) {
@@ -176,7 +189,7 @@ public class EntityViewServiceImpl extends AbstractEntityService @@ -176,7 +189,7 @@ public class EntityViewServiceImpl extends AbstractEntityService
176 return new TextPageData<>(entityViews, pageLink); 189 return new TextPageData<>(entityViews, pageLink);
177 } 190 }
178 191
179 - @Cacheable(cacheNames = ENTITY_VIEW_CACHE, key = "{#tenantId, #customerId, #entityId, #pageLink}") 192 +// @Cacheable(cacheNames = ENTITY_VIEW_CACHE, key = "{#tenantId, #customerId, #entityId, #pageLink}")
180 @Override 193 @Override
181 public TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerIdAndEntityId(TenantId tenantId, 194 public TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerIdAndEntityId(TenantId tenantId,
182 CustomerId customerId, 195 CustomerId customerId,
@@ -211,6 +224,24 @@ public class EntityViewServiceImpl extends AbstractEntityService @@ -211,6 +224,24 @@ public class EntityViewServiceImpl extends AbstractEntityService
211 return entityViewDao.findByIdAsync(entityViewId.getId()); 224 return entityViewDao.findByIdAsync(entityViewId.getId());
212 } 225 }
213 226
  227 + @Override
  228 + public ListenableFuture<List<EntityView>> findEntityViewsByQuery(EntityViewSearchQuery query) {
  229 + ListenableFuture<List<EntityRelation>> relations = relationService.findByQuery(query.toEntitySearchQuery());
  230 + ListenableFuture<List<EntityView>> entityViews = Futures.transformAsync(relations, r -> {
  231 + EntitySearchDirection direction = query.toEntitySearchQuery().getParameters().getDirection();
  232 + List<ListenableFuture<EntityView>> futures = new ArrayList<>();
  233 + for (EntityRelation relation : r) {
  234 + EntityId entityId = direction == EntitySearchDirection.FROM ? relation.getTo() : relation.getFrom();
  235 + if (entityId.getEntityType() == EntityType.ENTITY_VIEW) {
  236 + futures.add(findEntityViewByIdAsync(new EntityViewId(entityId.getId())));
  237 + }
  238 + }
  239 + return Futures.successfulAsList(futures);
  240 + });
  241 +
  242 + return entityViews;
  243 + }
  244 +
214 private DataValidator<EntityView> entityViewValidator = 245 private DataValidator<EntityView> entityViewValidator =
215 new DataValidator<EntityView>() { 246 new DataValidator<EntityView>() {
216 247
@@ -151,6 +151,7 @@ public class ModelConstants { @@ -151,6 +151,7 @@ public class ModelConstants {
151 public static final String ENTITY_VIEW_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; 151 public static final String ENTITY_VIEW_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
152 public static final String ENTITY_VIEW_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY; 152 public static final String ENTITY_VIEW_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY;
153 public static final String ENTITY_VIEW_NAME_PROPERTY = DEVICE_NAME_PROPERTY; 153 public static final String ENTITY_VIEW_NAME_PROPERTY = DEVICE_NAME_PROPERTY;
  154 + public static final String ENTITY_VIEW_TYPE_PROPERTY = DEVICE_TYPE_PROPERTY;
154 public static final String ENTITY_VIEW_TENANT_AND_NAME_VIEW_NAME = "entity_view_by_tenant_and_name"; 155 public static final String ENTITY_VIEW_TENANT_AND_NAME_VIEW_NAME = "entity_view_by_tenant_and_name";
155 public static final String ENTITY_VIEW_KEYS_PROPERTY = "keys"; 156 public static final String ENTITY_VIEW_KEYS_PROPERTY = "keys";
156 public static final String ENTITY_VIEW_TS_BEGIN_PROPERTY = "ts_begin"; 157 public static final String ENTITY_VIEW_TS_BEGIN_PROPERTY = "ts_begin";
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 package org.thingsboard.server.dao.model.nosql; 16 package org.thingsboard.server.dao.model.nosql;
17 17
18 import com.datastax.driver.core.utils.UUIDs; 18 import com.datastax.driver.core.utils.UUIDs;
  19 +import com.datastax.driver.mapping.annotations.Column;
19 import com.datastax.driver.mapping.annotations.PartitionKey; 20 import com.datastax.driver.mapping.annotations.PartitionKey;
20 import com.datastax.driver.mapping.annotations.Table; 21 import com.datastax.driver.mapping.annotations.Table;
21 import com.fasterxml.jackson.databind.JsonNode; 22 import com.fasterxml.jackson.databind.JsonNode;
@@ -31,10 +32,8 @@ import org.thingsboard.server.common.data.objects.TelemetryEntityView; @@ -31,10 +32,8 @@ import org.thingsboard.server.common.data.objects.TelemetryEntityView;
31 import org.thingsboard.server.dao.model.ModelConstants; 32 import org.thingsboard.server.dao.model.ModelConstants;
32 import org.thingsboard.server.dao.model.SearchTextEntity; 33 import org.thingsboard.server.dao.model.SearchTextEntity;
33 34
34 -import javax.persistence.Column;  
35 import javax.persistence.EnumType; 35 import javax.persistence.EnumType;
36 import javax.persistence.Enumerated; 36 import javax.persistence.Enumerated;
37 -  
38 import java.io.IOException; 37 import java.io.IOException;
39 import java.util.UUID; 38 import java.util.UUID;
40 39
@@ -55,22 +54,21 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> { @@ -55,22 +54,21 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> {
55 @Column(name = ID_PROPERTY) 54 @Column(name = ID_PROPERTY)
56 private UUID id; 55 private UUID id;
57 56
58 - @PartitionKey(value = 1)  
59 - @Column(name = ModelConstants.ENTITY_VIEW_ENTITY_ID_PROPERTY)  
60 - private UUID entityId;  
61 -  
62 @Enumerated(EnumType.STRING) 57 @Enumerated(EnumType.STRING)
63 @Column(name = ENTITY_TYPE_PROPERTY) 58 @Column(name = ENTITY_TYPE_PROPERTY)
64 private EntityType entityType; 59 private EntityType entityType;
65 60
66 - @PartitionKey(value = 2) 61 + @PartitionKey(value = 1)
67 @Column(name = ModelConstants.ENTITY_VIEW_TENANT_ID_PROPERTY) 62 @Column(name = ModelConstants.ENTITY_VIEW_TENANT_ID_PROPERTY)
68 private UUID tenantId; 63 private UUID tenantId;
69 64
70 - @PartitionKey(value = 3) 65 + @PartitionKey(value = 2)
71 @Column(name = ModelConstants.ENTITY_VIEW_CUSTOMER_ID_PROPERTY) 66 @Column(name = ModelConstants.ENTITY_VIEW_CUSTOMER_ID_PROPERTY)
72 private UUID customerId; 67 private UUID customerId;
73 68
  69 + @Column(name = ModelConstants.ENTITY_VIEW_ENTITY_ID_PROPERTY)
  70 + private UUID entityId;
  71 +
74 @Column(name = ModelConstants.ENTITY_VIEW_NAME_PROPERTY) 72 @Column(name = ModelConstants.ENTITY_VIEW_NAME_PROPERTY)
75 private String name; 73 private String name;
76 74
@@ -15,12 +15,16 @@ @@ -15,12 +15,16 @@
15 */ 15 */
16 package org.thingsboard.server.dao.sql.entityview; 16 package org.thingsboard.server.dao.sql.entityview;
17 17
  18 +import com.google.common.util.concurrent.ListenableFuture;
18 import org.springframework.beans.factory.annotation.Autowired; 19 import org.springframework.beans.factory.annotation.Autowired;
19 import org.springframework.data.domain.PageRequest; 20 import org.springframework.data.domain.PageRequest;
20 import org.springframework.data.repository.CrudRepository; 21 import org.springframework.data.repository.CrudRepository;
21 import org.springframework.stereotype.Component; 22 import org.springframework.stereotype.Component;
  23 +import org.thingsboard.server.common.data.EntitySubtype;
  24 +import org.thingsboard.server.common.data.EntityType;
22 import org.thingsboard.server.common.data.EntityView; 25 import org.thingsboard.server.common.data.EntityView;
23 import org.thingsboard.server.common.data.id.EntityId; 26 import org.thingsboard.server.common.data.id.EntityId;
  27 +import org.thingsboard.server.common.data.id.TenantId;
24 import org.thingsboard.server.common.data.page.TextPageLink; 28 import org.thingsboard.server.common.data.page.TextPageLink;
25 import org.thingsboard.server.dao.DaoUtil; 29 import org.thingsboard.server.dao.DaoUtil;
26 import org.thingsboard.server.dao.entityview.EntityViewDao; 30 import org.thingsboard.server.dao.entityview.EntityViewDao;
@@ -28,6 +32,8 @@ import org.thingsboard.server.dao.model.sql.EntityViewEntity; @@ -28,6 +32,8 @@ import org.thingsboard.server.dao.model.sql.EntityViewEntity;
28 import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; 32 import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
29 import org.thingsboard.server.dao.util.SqlDao; 33 import org.thingsboard.server.dao.util.SqlDao;
30 34
  35 +import java.util.ArrayList;
  36 +import java.util.Collections;
31 import java.util.List; 37 import java.util.List;
32 import java.util.Objects; 38 import java.util.Objects;
33 import java.util.Optional; 39 import java.util.Optional;
@@ -651,7 +651,7 @@ CREATE TABLE IF NOT EXISTS thingsboard.entity_views ( @@ -651,7 +651,7 @@ CREATE TABLE IF NOT EXISTS thingsboard.entity_views (
651 ts_end bigint, 651 ts_end bigint,
652 search_text text, 652 search_text text,
653 additional_info text, 653 additional_info text,
654 - PRIMARY KEY (id, entity_id, tenant_id, customer_id) 654 + PRIMARY KEY (id, tenant_id, customer_id)
655 ); 655 );
656 656
657 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_views_by_tenant_and_name AS 657 CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_views_by_tenant_and_name AS
@@ -155,6 +155,10 @@ function EntityViewService($http, $q, $window, userService, attributeService, cu @@ -155,6 +155,10 @@ function EntityViewService($http, $q, $window, userService, attributeService, cu
155 function saveEntityView(entityView) { 155 function saveEntityView(entityView) {
156 var deferred = $q.defer(); 156 var deferred = $q.defer();
157 var url = '/api/entityView'; 157 var url = '/api/entityView';
  158 +
  159 + entityView.keys = {};
  160 + entityView.keys.timeseries = ['a', 'b'];
  161 +
158 $http.post(url, entityView).then(function success(response) { 162 $http.post(url, entityView).then(function success(response) {
159 deferred.resolve(response.data); 163 deferred.resolve(response.data);
160 }, function fail() { 164 }, function fail() {
@@ -328,7 +328,7 @@ export default angular.module('thingsboard.types', []) @@ -328,7 +328,7 @@ export default angular.module('thingsboard.types', [])
328 alarm: "ALARM", 328 alarm: "ALARM",
329 rulechain: "RULE_CHAIN", 329 rulechain: "RULE_CHAIN",
330 rulenode: "RULE_NODE", 330 rulenode: "RULE_NODE",
331 - entityview: "ENTITY_VIEW" 331 + entityView: "ENTITY_VIEW"
332 }, 332 },
333 aliasEntityType: { 333 aliasEntityType: {
334 current_customer: "CURRENT_CUSTOMER" 334 current_customer: "CURRENT_CUSTOMER"
@@ -15,6 +15,9 @@ @@ -15,6 +15,9 @@
15 limitations under the License. 15 limitations under the License.
16 16
17 --> 17 -->
  18 +<md-button ng-click="onMakePublic({event: $event})"
  19 + ng-show="!isEdit && entityViewScope === 'tenant' && !isAssignedToCustomer && !isPublic"
  20 + class="md-raised md-primary">{{ 'entity-view.make-public' | translate }}</md-button>
18 <md-button ng-click="onAssignToCustomer({event: $event})" 21 <md-button ng-click="onAssignToCustomer({event: $event})"
19 ng-show="!isEdit && entityViewScope === 'tenant' && !isAssignedToCustomer" 22 ng-show="!isEdit && entityViewScope === 'tenant' && !isAssignedToCustomer"
20 class="md-raised md-primary">{{ 'entity-view.assign-to-customer' | translate }}</md-button> 23 class="md-raised md-primary">{{ 'entity-view.assign-to-customer' | translate }}</md-button>
@@ -49,13 +52,6 @@ @@ -49,13 +52,6 @@
49 <div translate ng-message="required">entity-view.name-required</div> 52 <div translate ng-message="required">entity-view.name-required</div>
50 </div> 53 </div>
51 </md-input-container> 54 </md-input-container>
52 - <tb-entity-subtype-autocomplete  
53 - ng-disabled="$root.loading || !isEdit"  
54 - tb-required="true"  
55 - the-form="theForm"  
56 - ng-model="entityView.type"  
57 - entity-type="types.entityType.entityview">  
58 - </tb-entity-subtype-autocomplete>  
59 <md-input-container class="md-block"> 55 <md-input-container class="md-block">
60 <label translate>entity-view.description</label> 56 <label translate>entity-view.description</label>
61 <textarea ng-model="entityView.additionalInfo.description" rows="2"></textarea> 57 <textarea ng-model="entityView.additionalInfo.description" rows="2"></textarea>
@@ -194,7 +194,7 @@ export function EntityViewController($rootScope, userService, entityViewService, @@ -194,7 +194,7 @@ export function EntityViewController($rootScope, userService, entityViewService,
194 entityViewGroupActionsList.push( 194 entityViewGroupActionsList.push(
195 { 195 {
196 onAction: function ($event, items) { 196 onAction: function ($event, items) {
197 - assignEntiyViewsToCustomer($event, items); 197 + assignEntityViewsToCustomer($event, items);
198 }, 198 },
199 name: function() { return $translate.instant('entity-view.assign-entity-views') }, 199 name: function() { return $translate.instant('entity-view.assign-entity-views') },
200 details: function(selectedCount) { 200 details: function(selectedCount) {
@@ -221,10 +221,10 @@ export function EntityViewController($rootScope, userService, entityViewService, @@ -221,10 +221,10 @@ export function EntityViewController($rootScope, userService, entityViewService,
221 fetchEntityViewsFunction = function (pageLink, entityViewType) { 221 fetchEntityViewsFunction = function (pageLink, entityViewType) {
222 return entityViewService.getCustomerEntityViews(customerId, pageLink, true, null, entityViewType); 222 return entityViewService.getCustomerEntityViews(customerId, pageLink, true, null, entityViewType);
223 }; 223 };
224 - deleteentityViewFunction = function (entityViewId) { 224 + deleteEntityViewFunction = function (entityViewId) {
225 return entityViewService.unassignEntityViewFromCustomer(entityViewId); 225 return entityViewService.unassignEntityViewFromCustomer(entityViewId);
226 }; 226 };
227 - refreshentityViewsParamsFunction = function () { 227 + refreshEntityViewsParamsFunction = function () {
228 return {"customerId": customerId, "topIndex": vm.topIndex}; 228 return {"customerId": customerId, "topIndex": vm.topIndex};
229 }; 229 };
230 230
@@ -271,9 +271,9 @@ export function EntityViewController($rootScope, userService, entityViewService, @@ -271,9 +271,9 @@ export function EntityViewController($rootScope, userService, entityViewService,
271 } 271 }
272 } 272 }
273 273
274 - vm.entityViewGridConfig.refreshParamsFunc = refreshentityViewsParamsFunction;  
275 - vm.entityViewGridConfig.fetchItemsFunc = fetchentityViewsFunction;  
276 - vm.entityViewGridConfig.deleteItemFunc = deleteentityViewFunction; 274 + vm.entityViewGridConfig.refreshParamsFunc = refreshEntityViewsParamsFunction;
  275 + vm.entityViewGridConfig.fetchItemsFunc = fetchEntityViewsFunction;
  276 + vm.entityViewGridConfig.deleteItemFunc = deleteEntityViewFunction;
277 277
278 } 278 }
279 279
@@ -27,6 +27,7 @@ export default function EntityViewDirective($compile, $templateCache, toast, $tr @@ -27,6 +27,7 @@ export default function EntityViewDirective($compile, $templateCache, toast, $tr
27 27
28 scope.types = types; 28 scope.types = types;
29 scope.isAssignedToCustomer = false; 29 scope.isAssignedToCustomer = false;
  30 + scope.isPublic = false;
30 scope.assignedCustomer = null; 31 scope.assignedCustomer = null;
31 32
32 scope.$watch('entityView', function(newVal) { 33 scope.$watch('entityView', function(newVal) {
@@ -36,10 +37,12 @@ export default function EntityViewDirective($compile, $templateCache, toast, $tr @@ -36,10 +37,12 @@ export default function EntityViewDirective($compile, $templateCache, toast, $tr
36 customerService.getShortCustomerInfo(scope.entityView.customerId.id).then( 37 customerService.getShortCustomerInfo(scope.entityView.customerId.id).then(
37 function success(customer) { 38 function success(customer) {
38 scope.assignedCustomer = customer; 39 scope.assignedCustomer = customer;
  40 + scope.isPublic = customer.isPublic;
39 } 41 }
40 ); 42 );
41 } else { 43 } else {
42 scope.isAssignedToCustomer = false; 44 scope.isAssignedToCustomer = false;
  45 + scope.isPublic = false;
43 scope.assignedCustomer = null; 46 scope.assignedCustomer = null;
44 } 47 }
45 } 48 }
@@ -60,6 +63,7 @@ export default function EntityViewDirective($compile, $templateCache, toast, $tr @@ -60,6 +63,7 @@ export default function EntityViewDirective($compile, $templateCache, toast, $tr
60 entityViewScope: '=', 63 entityViewScope: '=',
61 theForm: '=', 64 theForm: '=',
62 onAssignToCustomer: '&', 65 onAssignToCustomer: '&',
  66 + onMakePublic: '&',
63 onUnassignFromCustomer: '&', 67 onUnassignFromCustomer: '&',
64 onDeleteEntityView: '&' 68 onDeleteEntityView: '&'
65 } 69 }
@@ -35,14 +35,14 @@ export default function EntityViewRoutes($stateProvider, types) { @@ -35,14 +35,14 @@ export default function EntityViewRoutes($stateProvider, types) {
35 } 35 }
36 }, 36 },
37 data: { 37 data: {
38 - entityViewsTypes: 'tenant', 38 + entityViewsType: 'tenant',
39 searchEnabled: true, 39 searchEnabled: true,
40 searchByEntitySubtype: true, 40 searchByEntitySubtype: true,
41 searchEntityType: types.entityType.entityview, 41 searchEntityType: types.entityType.entityview,
42 - pageTitle: 'entity-views.entity-views' 42 + pageTitle: 'entity-view.entity-views'
43 }, 43 },
44 ncyBreadcrumb: { 44 ncyBreadcrumb: {
45 - label: '{"icon": "devices_other", "label": "entity-view.entity-views"}' 45 + label: '{"icon": "view_stream", "label": "entity-view.entity-views"}'
46 } 46 }
47 }) 47 })
48 .state('home.customers.entityViews', { 48 .state('home.customers.entityViews', {
@@ -58,14 +58,14 @@ export default function EntityViewRoutes($stateProvider, types) { @@ -58,14 +58,14 @@ export default function EntityViewRoutes($stateProvider, types) {
58 } 58 }
59 }, 59 },
60 data: { 60 data: {
61 - entityViewsTypes: 'customer', 61 + entityViewsType: 'customer',
62 searchEnabled: true, 62 searchEnabled: true,
63 searchByEntitySubtype: true, 63 searchByEntitySubtype: true,
64 searchEntityType: types.entityType.entityview, 64 searchEntityType: types.entityType.entityview,
65 pageTitle: 'customer.entity-views' 65 pageTitle: 'customer.entity-views'
66 }, 66 },
67 ncyBreadcrumb: { 67 ncyBreadcrumb: {
68 - label: '{"icon": "devices_other", "label": "{{ vm.customerEntityViewsTitle }}", "translate": "false"}' 68 + label: '{"icon": "view_stream", "label": "{{ vm.customerEntityViewsTitle }}", "translate": "false"}'
69 } 69 }
70 }); 70 });
71 71
@@ -29,13 +29,12 @@ @@ -29,13 +29,12 @@
29 on-assign-to-customer="vm.assignToCustomer(event, [ vm.grid.detailsConfig.currentItem.id.id ])" 29 on-assign-to-customer="vm.assignToCustomer(event, [ vm.grid.detailsConfig.currentItem.id.id ])"
30 on-make-public="vm.makePublic(event, vm.grid.detailsConfig.currentItem)" 30 on-make-public="vm.makePublic(event, vm.grid.detailsConfig.currentItem)"
31 on-unassign-from-customer="vm.unassignFromCustomer(event, vm.grid.detailsConfig.currentItem, isPublic)" 31 on-unassign-from-customer="vm.unassignFromCustomer(event, vm.grid.detailsConfig.currentItem, isPublic)"
32 - on-manage-credentials="vm.manageCredentials(event, vm.grid.detailsConfig.currentItem)"  
33 on-delete-entity-view="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"></tb-entity-view> 32 on-delete-entity-view="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"></tb-entity-view>
34 </md-tab> 33 </md-tab>
35 <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.attributes' | translate }}"> 34 <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.attributes' | translate }}">
36 <tb-attribute-table flex 35 <tb-attribute-table flex
37 entity-id="vm.grid.operatingItem().id.id" 36 entity-id="vm.grid.operatingItem().id.id"
38 - entity-type="{{vm.types.entityType.entityview}}" 37 + entity-type="{{vm.types.entityType.entityView}}"
39 entity-name="vm.grid.operatingItem().name" 38 entity-name="vm.grid.operatingItem().name"
40 default-attribute-scope="{{vm.types.attributesScope.client.value}}"> 39 default-attribute-scope="{{vm.types.attributesScope.client.value}}">
41 </tb-attribute-table> 40 </tb-attribute-table>
@@ -43,19 +42,19 @@ @@ -43,19 +42,19 @@
43 <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.latest-telemetry' | translate }}"> 42 <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.latest-telemetry' | translate }}">
44 <tb-attribute-table flex 43 <tb-attribute-table flex
45 entity-id="vm.grid.operatingItem().id.id" 44 entity-id="vm.grid.operatingItem().id.id"
46 - entity-type="{{vm.types.entityType.entityview}}" 45 + entity-type="{{vm.types.entityType.entityView}}"
47 entity-name="vm.grid.operatingItem().name" 46 entity-name="vm.grid.operatingItem().name"
48 default-attribute-scope="{{vm.types.latestTelemetry.value}}" 47 default-attribute-scope="{{vm.types.latestTelemetry.value}}"
49 disable-attribute-scope-selection="true"> 48 disable-attribute-scope-selection="true">
50 </tb-attribute-table> 49 </tb-attribute-table>
51 </md-tab> 50 </md-tab>
52 <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'alarm.alarms' | translate }}"> 51 <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'alarm.alarms' | translate }}">
53 - <tb-alarm-table flex entity-type="vm.types.entityType.entityview" 52 + <tb-alarm-table flex entity-type="vm.types.entityType.entityView"
54 entity-id="vm.grid.operatingItem().id.id"> 53 entity-id="vm.grid.operatingItem().id.id">
55 </tb-alarm-table> 54 </tb-alarm-table>
56 </md-tab> 55 </md-tab>
57 <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'entity-view.events' | translate }}"> 56 <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'entity-view.events' | translate }}">
58 - <tb-event-table flex entity-type="vm.types.entityType.entityview" 57 + <tb-event-table flex entity-type="vm.types.entityType.entityView"
59 entity-id="vm.grid.operatingItem().id.id" 58 entity-id="vm.grid.operatingItem().id.id"
60 tenant-id="vm.grid.operatingItem().tenantId.id" 59 tenant-id="vm.grid.operatingItem().tenantId.id"
61 default-event-type="{{vm.types.eventType.error.value}}"> 60 default-event-type="{{vm.types.eventType.error.value}}">
@@ -64,18 +63,11 @@ @@ -64,18 +63,11 @@
64 <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'relation.relations' | translate }}"> 63 <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'relation.relations' | translate }}">
65 <tb-relation-table flex 64 <tb-relation-table flex
66 entity-id="vm.grid.operatingItem().id.id" 65 entity-id="vm.grid.operatingItem().id.id"
67 - entity-type="{{vm.types.entityType.entityview}}"> 66 + entity-type="{{vm.types.entityType.entityView}}">
68 </tb-relation-table> 67 </tb-relation-table>
69 </md-tab> 68 </md-tab>
70 - <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.grid.operatingItem().additionalInfo.gateway" md-on-select="vm.grid.triggerResize()" label="{{ 'extension.extensions' | translate }}">  
71 - <tb-extension-table flex  
72 - entity-id="vm.grid.operatingItem().id.id"  
73 - entity-name="vm.grid.operatingItem().name"  
74 - entity-type="{{vm.types.entityType.entityview}}">  
75 - </tb-extension-table>  
76 - </md-tab>  
77 <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.grid.isTenantAdmin()" md-on-select="vm.grid.triggerResize()" label="{{ 'audit-log.audit-logs' | translate }}"> 69 <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.grid.isTenantAdmin()" md-on-select="vm.grid.triggerResize()" label="{{ 'audit-log.audit-logs' | translate }}">
78 - <tb-audit-log-table flex entity-type="vm.types.entityType.entityview" 70 + <tb-audit-log-table flex entity-type="vm.types.entityType.entityView"
79 entity-id="vm.grid.operatingItem().id.id" 71 entity-id="vm.grid.operatingItem().id.id"
80 audit-log-mode="{{vm.types.auditLogMode.entity}}"> 72 audit-log-mode="{{vm.types.auditLogMode.entity}}">
81 </tb-audit-log-table> 73 </tb-audit-log-table>
@@ -20,7 +20,7 @@ import thingsboardApiEntityView from '../api/entity-view.service'; @@ -20,7 +20,7 @@ import thingsboardApiEntityView from '../api/entity-view.service';
20 import thingsboardApiCustomer from '../api/customer.service'; 20 import thingsboardApiCustomer from '../api/customer.service';
21 21
22 import EntityViewRoutes from './entity-view.routes'; 22 import EntityViewRoutes from './entity-view.routes';
23 -import EntityViewCardController from './entity-view.controller'; 23 +import {EntityViewController, EntityViewCardController} from './entity-view.controller';
24 import AssignEntityViewToCustomerController from './assign-to-customer.controller'; 24 import AssignEntityViewToCustomerController from './assign-to-customer.controller';
25 import AddEntityViewsToCustomerController from './add-entity-views-to-customer.controller'; 25 import AddEntityViewsToCustomerController from './add-entity-views-to-customer.controller';
26 import EntityViewDirective from './entity-view.directive'; 26 import EntityViewDirective from './entity-view.directive';
@@ -33,7 +33,7 @@ export default angular.module('thingsboard.entityView', [ @@ -33,7 +33,7 @@ export default angular.module('thingsboard.entityView', [
33 thingsboardApiCustomer 33 thingsboardApiCustomer
34 ]) 34 ])
35 .config(EntityViewRoutes) 35 .config(EntityViewRoutes)
36 - .controller('EntityViewController', EntityViewCardController) 36 + .controller('EntityViewController', EntityViewController)
37 .controller('EntityViewCardController', EntityViewCardController) 37 .controller('EntityViewCardController', EntityViewCardController)
38 .controller('AssignEntityViewToCustomerController', AssignEntityViewToCustomerController) 38 .controller('AssignEntityViewToCustomerController', AssignEntityViewToCustomerController)
39 .controller('AddEntityViewsToCustomerController', AddEntityViewsToCustomerController) 39 .controller('AddEntityViewsToCustomerController', AddEntityViewsToCustomerController)
@@ -48,6 +48,7 @@ import thingsboardAdmin from '../admin'; @@ -48,6 +48,7 @@ import thingsboardAdmin from '../admin';
48 import thingsboardProfile from '../profile'; 48 import thingsboardProfile from '../profile';
49 import thingsboardAsset from '../asset'; 49 import thingsboardAsset from '../asset';
50 import thingsboardDevice from '../device'; 50 import thingsboardDevice from '../device';
  51 +import thingsboardEntityView from '../entity-view';
51 import thingsboardWidgetLibrary from '../widget'; 52 import thingsboardWidgetLibrary from '../widget';
52 import thingsboardDashboard from '../dashboard'; 53 import thingsboardDashboard from '../dashboard';
53 import thingsboardRuleChain from '../rulechain'; 54 import thingsboardRuleChain from '../rulechain';
@@ -79,6 +80,7 @@ export default angular.module('thingsboard.home', [ @@ -79,6 +80,7 @@ export default angular.module('thingsboard.home', [
79 thingsboardProfile, 80 thingsboardProfile,
80 thingsboardAsset, 81 thingsboardAsset,
81 thingsboardDevice, 82 thingsboardDevice,
  83 + thingsboardEntityView,
82 thingsboardWidgetLibrary, 84 thingsboardWidgetLibrary,
83 thingsboardDashboard, 85 thingsboardDashboard,
84 thingsboardRuleChain, 86 thingsboardRuleChain,
@@ -821,7 +821,8 @@ @@ -821,7 +821,8 @@
821 "assignedToCustomer": "Assigned to customer", 821 "assignedToCustomer": "Assigned to customer",
822 "unable-entity-view-device-alias-title": "Unable to delete entity view alias", 822 "unable-entity-view-device-alias-title": "Unable to delete entity view alias",
823 "unable-entity-view-device-alias-text": "Device alias '{{entityViewAlias}}' can't be deleted as it used by the following widget(s):<br/>{{widgetsList}}", 823 "unable-entity-view-device-alias-text": "Device alias '{{entityViewAlias}}' can't be deleted as it used by the following widget(s):<br/>{{widgetsList}}",
824 - "select-entity-view": "Select entity view" 824 + "select-entity-view": "Select entity view",
  825 + "make-public": "Make entity view public"
825 }, 826 },
826 "event": { 827 "event": {
827 "event-type": "Event type", 828 "event-type": "Event type",
@@ -168,6 +168,12 @@ function Menu(userService, $state, $rootScope) { @@ -168,6 +168,12 @@ function Menu(userService, $state, $rootScope) {
168 icon: 'devices_other' 168 icon: 'devices_other'
169 }, 169 },
170 { 170 {
  171 + name: 'entity-view.entity-views',
  172 + type: 'link',
  173 + state: 'home.entityViews',
  174 + icon: 'view_stream'
  175 + },
  176 + {
171 name: 'widget.widget-library', 177 name: 'widget.widget-library',
172 type: 'link', 178 type: 'link',
173 state: 'home.widgets-bundles', 179 state: 'home.widgets-bundles',
@@ -228,6 +234,16 @@ function Menu(userService, $state, $rootScope) { @@ -228,6 +234,16 @@ function Menu(userService, $state, $rootScope) {
228 ] 234 ]
229 }, 235 },
230 { 236 {
  237 + name: 'entity-view.management',
  238 + places: [
  239 + {
  240 + name: 'entity-view.entity-views',
  241 + icon: 'view_stream',
  242 + state: 'home.entityViews'
  243 + }
  244 + ]
  245 + },
  246 + {
231 name: 'dashboard.management', 247 name: 'dashboard.management',
232 places: [ 248 places: [
233 { 249 {
@@ -274,6 +290,12 @@ function Menu(userService, $state, $rootScope) { @@ -274,6 +290,12 @@ function Menu(userService, $state, $rootScope) {
274 icon: 'devices_other' 290 icon: 'devices_other'
275 }, 291 },
276 { 292 {
  293 + name: 'entity-view.entity-views',
  294 + type: 'link',
  295 + state: 'home.entityViews',
  296 + icon: 'view_stream'
  297 + },
  298 + {
277 name: 'dashboard.dashboards', 299 name: 'dashboard.dashboards',
278 type: 'link', 300 type: 'link',
279 state: 'home.dashboards', 301 state: 'home.dashboards',
@@ -301,16 +323,26 @@ function Menu(userService, $state, $rootScope) { @@ -301,16 +323,26 @@ function Menu(userService, $state, $rootScope) {
301 } 323 }
302 ] 324 ]
303 }, 325 },
304 - {  
305 - name: 'dashboard.view-dashboards',  
306 - places: [  
307 - {  
308 - name: 'dashboard.dashboards',  
309 - icon: 'dashboard',  
310 - state: 'home.dashboards'  
311 - }  
312 - ]  
313 - }]; 326 + {
  327 + name: 'entity-view.management',
  328 + places: [
  329 + {
  330 + name: 'entity-view.entity-views',
  331 + icon: 'view_stream',
  332 + state: 'home.entityViews'
  333 + }
  334 + ]
  335 + },
  336 + {
  337 + name: 'dashboard.view-dashboards',
  338 + places: [
  339 + {
  340 + name: 'dashboard.dashboards',
  341 + icon: 'dashboard',
  342 + state: 'home.dashboards'
  343 + }
  344 + ]
  345 + }];
314 } 346 }
315 } 347 }
316 } 348 }