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 19 import org.springframework.http.HttpStatus;
20 20 import org.springframework.security.access.prepost.PreAuthorize;
21 21 import org.springframework.web.bind.annotation.*;
  22 +import org.thingsboard.server.common.data.EntitySubtype;
22 23 import org.thingsboard.server.common.data.EntityType;
23 24 import org.thingsboard.server.common.data.EntityView;
24 25 import org.thingsboard.server.common.data.audit.ActionType;
  26 +import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
25 27 import org.thingsboard.server.common.data.exception.ThingsboardException;
26   -import org.thingsboard.server.common.data.id.CustomerId;
27 28 import org.thingsboard.server.common.data.id.EntityViewId;
28 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 32 import org.thingsboard.server.service.security.model.SecurityUser;
30 33
31 34 import java.util.ArrayList;
32 35 import java.util.List;
  36 +import java.util.stream.Collectors;
33 37
34 38 /**
35 39 * Created by Victor Basanets on 8/28/2017.
... ... @@ -41,7 +45,7 @@ public class EntityViewController extends BaseController {
41 45 public static final String ENTITY_VIEW_ID = "entityViewId";
42 46
43 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 49 @ResponseBody
46 50 public EntityView getEntityViewById(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId)
47 51 throws ThingsboardException {
... ... @@ -56,7 +60,7 @@ public class EntityViewController extends BaseController {
56 60 }
57 61
58 62 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
59   - @RequestMapping(value = "/entity-view", method = RequestMethod.POST)
  63 + @RequestMapping(value = "/entityView", method = RequestMethod.POST)
60 64 @ResponseBody
61 65 public EntityView saveEntityView(@RequestBody EntityView entityView) throws ThingsboardException {
62 66 try {
... ... @@ -76,7 +80,7 @@ public class EntityViewController extends BaseController {
76 80 }
77 81
78 82 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
79   - @RequestMapping(value = "/entity-view/{entityViewId}", method = RequestMethod.DELETE)
  83 + @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.DELETE)
80 84 @ResponseStatus(value = HttpStatus.OK)
81 85 public void deleteEntityView(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
82 86 checkParameter(ENTITY_VIEW_ID, strEntityViewId);
... ... @@ -95,4 +99,44 @@ public class EntityViewController extends BaseController {
95 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 16 package org.thingsboard.server.dao.entityview;
17 17
18 18 import org.thingsboard.server.common.data.EntityView;
19   -import org.thingsboard.server.common.data.id.EntityId;
20 19 import org.thingsboard.server.common.data.page.TextPageLink;
21 20 import org.thingsboard.server.dao.Dao;
22 21
... ... @@ -92,5 +91,4 @@ public interface EntityViewDao extends Dao<EntityView> {
92 91 UUID customerId,
93 92 UUID entityId,
94 93 TextPageLink pageLink);
95   -
96 94 }
... ...
... ... @@ -16,12 +16,18 @@
16 16 package org.thingsboard.server.dao.entityview;
17 17
18 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 21 import org.thingsboard.server.common.data.EntityType;
20 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 25 import org.thingsboard.server.common.data.id.*;
22 26 import org.thingsboard.server.common.data.page.TextPageData;
23 27 import org.thingsboard.server.common.data.page.TextPageLink;
24 28
  29 +import java.util.List;
  30 +
25 31 /**
26 32 * Created by Victor Basanets on 8/27/2017.
27 33 */
... ... @@ -57,4 +63,6 @@ public interface EntityViewService {
57 63 void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId);
58 64
59 65 ListenableFuture<EntityView> findEntityViewByIdAsync(EntityViewId entityViewId);
  66 +
  67 + ListenableFuture<List<EntityView>> findEntityViewsByQuery(EntityViewSearchQuery query);
60 68 }
... ...
... ... @@ -15,6 +15,8 @@
15 15 */
16 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 20 import com.google.common.util.concurrent.ListenableFuture;
19 21 import lombok.extern.slf4j.Slf4j;
20 22 import org.apache.commons.lang3.StringUtils;
... ... @@ -25,14 +27,22 @@ import org.springframework.cache.annotation.CacheEvict;
25 27 import org.springframework.cache.annotation.Cacheable;
26 28 import org.springframework.stereotype.Service;
27 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 33 import org.thingsboard.server.common.data.EntityView;
29 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 37 import org.thingsboard.server.common.data.id.CustomerId;
  38 +import org.thingsboard.server.common.data.id.DeviceId;
31 39 import org.thingsboard.server.common.data.id.EntityId;
32 40 import org.thingsboard.server.common.data.id.EntityViewId;
33 41 import org.thingsboard.server.common.data.id.TenantId;
34 42 import org.thingsboard.server.common.data.page.TextPageData;
35 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 46 import org.thingsboard.server.dao.customer.CustomerDao;
37 47 import org.thingsboard.server.dao.entity.AbstractEntityService;
38 48 import org.thingsboard.server.dao.exception.DataValidationException;
... ... @@ -40,8 +50,12 @@ import org.thingsboard.server.dao.service.DataValidator;
40 50 import org.thingsboard.server.dao.service.PaginatedRemover;
41 51 import org.thingsboard.server.dao.tenant.TenantDao;
42 52
  53 +import javax.annotation.Nullable;
43 54 import java.util.ArrayList;
  55 +import java.util.Collections;
  56 +import java.util.Comparator;
44 57 import java.util.List;
  58 +import java.util.stream.Collectors;
45 59
46 60 import static org.thingsboard.server.common.data.CacheConstants.DEVICE_CACHE;
47 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 69 */
56 70 @Service
57 71 @Slf4j
58   -public class EntityViewServiceImpl extends AbstractEntityService
59   - implements EntityViewService {
  72 +public class EntityViewServiceImpl extends AbstractEntityService implements EntityViewService {
60 73
61 74 public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
62 75 public static final String INCORRECT_PAGE_LINK = "Incorrect page link ";
... ... @@ -75,7 +88,7 @@ public class EntityViewServiceImpl extends AbstractEntityService
75 88 @Autowired
76 89 private CacheManager cacheManager;
77 90
78   - @Cacheable(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityViewId}")
  91 +// @Cacheable(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityViewId}")
79 92 @Override
80 93 public EntityView findEntityViewById(EntityViewId entityViewId) {
81 94 log.trace("Executing findEntityViewById [{}]", entityViewId);
... ... @@ -91,7 +104,7 @@ public class EntityViewServiceImpl extends AbstractEntityService
91 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 108 @Override
96 109 public EntityView saveEntityView(EntityView entityView) {
97 110 log.trace("Executing save entity view [{}]", entityView);
... ... @@ -136,7 +149,7 @@ public class EntityViewServiceImpl extends AbstractEntityService
136 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 153 @Override
141 154 public TextPageData<EntityView> findEntityViewByTenantIdAndEntityId(TenantId tenantId, EntityId entityId,
142 155 TextPageLink pageLink) {
... ... @@ -176,7 +189,7 @@ public class EntityViewServiceImpl extends AbstractEntityService
176 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 193 @Override
181 194 public TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerIdAndEntityId(TenantId tenantId,
182 195 CustomerId customerId,
... ... @@ -211,6 +224,24 @@ public class EntityViewServiceImpl extends AbstractEntityService
211 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 245 private DataValidator<EntityView> entityViewValidator =
215 246 new DataValidator<EntityView>() {
216 247
... ...
... ... @@ -151,6 +151,7 @@ public class ModelConstants {
151 151 public static final String ENTITY_VIEW_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
152 152 public static final String ENTITY_VIEW_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY;
153 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 155 public static final String ENTITY_VIEW_TENANT_AND_NAME_VIEW_NAME = "entity_view_by_tenant_and_name";
155 156 public static final String ENTITY_VIEW_KEYS_PROPERTY = "keys";
156 157 public static final String ENTITY_VIEW_TS_BEGIN_PROPERTY = "ts_begin";
... ...
... ... @@ -16,6 +16,7 @@
16 16 package org.thingsboard.server.dao.model.nosql;
17 17
18 18 import com.datastax.driver.core.utils.UUIDs;
  19 +import com.datastax.driver.mapping.annotations.Column;
19 20 import com.datastax.driver.mapping.annotations.PartitionKey;
20 21 import com.datastax.driver.mapping.annotations.Table;
21 22 import com.fasterxml.jackson.databind.JsonNode;
... ... @@ -31,10 +32,8 @@ import org.thingsboard.server.common.data.objects.TelemetryEntityView;
31 32 import org.thingsboard.server.dao.model.ModelConstants;
32 33 import org.thingsboard.server.dao.model.SearchTextEntity;
33 34
34   -import javax.persistence.Column;
35 35 import javax.persistence.EnumType;
36 36 import javax.persistence.Enumerated;
37   -
38 37 import java.io.IOException;
39 38 import java.util.UUID;
40 39
... ... @@ -55,22 +54,21 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> {
55 54 @Column(name = ID_PROPERTY)
56 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 57 @Enumerated(EnumType.STRING)
63 58 @Column(name = ENTITY_TYPE_PROPERTY)
64 59 private EntityType entityType;
65 60
66   - @PartitionKey(value = 2)
  61 + @PartitionKey(value = 1)
67 62 @Column(name = ModelConstants.ENTITY_VIEW_TENANT_ID_PROPERTY)
68 63 private UUID tenantId;
69 64
70   - @PartitionKey(value = 3)
  65 + @PartitionKey(value = 2)
71 66 @Column(name = ModelConstants.ENTITY_VIEW_CUSTOMER_ID_PROPERTY)
72 67 private UUID customerId;
73 68
  69 + @Column(name = ModelConstants.ENTITY_VIEW_ENTITY_ID_PROPERTY)
  70 + private UUID entityId;
  71 +
74 72 @Column(name = ModelConstants.ENTITY_VIEW_NAME_PROPERTY)
75 73 private String name;
76 74
... ...
... ... @@ -15,12 +15,16 @@
15 15 */
16 16 package org.thingsboard.server.dao.sql.entityview;
17 17
  18 +import com.google.common.util.concurrent.ListenableFuture;
18 19 import org.springframework.beans.factory.annotation.Autowired;
19 20 import org.springframework.data.domain.PageRequest;
20 21 import org.springframework.data.repository.CrudRepository;
21 22 import org.springframework.stereotype.Component;
  23 +import org.thingsboard.server.common.data.EntitySubtype;
  24 +import org.thingsboard.server.common.data.EntityType;
22 25 import org.thingsboard.server.common.data.EntityView;
23 26 import org.thingsboard.server.common.data.id.EntityId;
  27 +import org.thingsboard.server.common.data.id.TenantId;
24 28 import org.thingsboard.server.common.data.page.TextPageLink;
25 29 import org.thingsboard.server.dao.DaoUtil;
26 30 import org.thingsboard.server.dao.entityview.EntityViewDao;
... ... @@ -28,6 +32,8 @@ import org.thingsboard.server.dao.model.sql.EntityViewEntity;
28 32 import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
29 33 import org.thingsboard.server.dao.util.SqlDao;
30 34
  35 +import java.util.ArrayList;
  36 +import java.util.Collections;
31 37 import java.util.List;
32 38 import java.util.Objects;
33 39 import java.util.Optional;
... ...
... ... @@ -651,7 +651,7 @@ CREATE TABLE IF NOT EXISTS thingsboard.entity_views (
651 651 ts_end bigint,
652 652 search_text text,
653 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 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 155 function saveEntityView(entityView) {
156 156 var deferred = $q.defer();
157 157 var url = '/api/entityView';
  158 +
  159 + entityView.keys = {};
  160 + entityView.keys.timeseries = ['a', 'b'];
  161 +
158 162 $http.post(url, entityView).then(function success(response) {
159 163 deferred.resolve(response.data);
160 164 }, function fail() {
... ...
... ... @@ -328,7 +328,7 @@ export default angular.module('thingsboard.types', [])
328 328 alarm: "ALARM",
329 329 rulechain: "RULE_CHAIN",
330 330 rulenode: "RULE_NODE",
331   - entityview: "ENTITY_VIEW"
  331 + entityView: "ENTITY_VIEW"
332 332 },
333 333 aliasEntityType: {
334 334 current_customer: "CURRENT_CUSTOMER"
... ...
... ... @@ -15,6 +15,9 @@
15 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 21 <md-button ng-click="onAssignToCustomer({event: $event})"
19 22 ng-show="!isEdit && entityViewScope === 'tenant' && !isAssignedToCustomer"
20 23 class="md-raised md-primary">{{ 'entity-view.assign-to-customer' | translate }}</md-button>
... ... @@ -49,13 +52,6 @@
49 52 <div translate ng-message="required">entity-view.name-required</div>
50 53 </div>
51 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 55 <md-input-container class="md-block">
60 56 <label translate>entity-view.description</label>
61 57 <textarea ng-model="entityView.additionalInfo.description" rows="2"></textarea>
... ...
... ... @@ -194,7 +194,7 @@ export function EntityViewController($rootScope, userService, entityViewService,
194 194 entityViewGroupActionsList.push(
195 195 {
196 196 onAction: function ($event, items) {
197   - assignEntiyViewsToCustomer($event, items);
  197 + assignEntityViewsToCustomer($event, items);
198 198 },
199 199 name: function() { return $translate.instant('entity-view.assign-entity-views') },
200 200 details: function(selectedCount) {
... ... @@ -221,10 +221,10 @@ export function EntityViewController($rootScope, userService, entityViewService,
221 221 fetchEntityViewsFunction = function (pageLink, entityViewType) {
222 222 return entityViewService.getCustomerEntityViews(customerId, pageLink, true, null, entityViewType);
223 223 };
224   - deleteentityViewFunction = function (entityViewId) {
  224 + deleteEntityViewFunction = function (entityViewId) {
225 225 return entityViewService.unassignEntityViewFromCustomer(entityViewId);
226 226 };
227   - refreshentityViewsParamsFunction = function () {
  227 + refreshEntityViewsParamsFunction = function () {
228 228 return {"customerId": customerId, "topIndex": vm.topIndex};
229 229 };
230 230
... ... @@ -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 27
28 28 scope.types = types;
29 29 scope.isAssignedToCustomer = false;
  30 + scope.isPublic = false;
30 31 scope.assignedCustomer = null;
31 32
32 33 scope.$watch('entityView', function(newVal) {
... ... @@ -36,10 +37,12 @@ export default function EntityViewDirective($compile, $templateCache, toast, $tr
36 37 customerService.getShortCustomerInfo(scope.entityView.customerId.id).then(
37 38 function success(customer) {
38 39 scope.assignedCustomer = customer;
  40 + scope.isPublic = customer.isPublic;
39 41 }
40 42 );
41 43 } else {
42 44 scope.isAssignedToCustomer = false;
  45 + scope.isPublic = false;
43 46 scope.assignedCustomer = null;
44 47 }
45 48 }
... ... @@ -60,6 +63,7 @@ export default function EntityViewDirective($compile, $templateCache, toast, $tr
60 63 entityViewScope: '=',
61 64 theForm: '=',
62 65 onAssignToCustomer: '&',
  66 + onMakePublic: '&',
63 67 onUnassignFromCustomer: '&',
64 68 onDeleteEntityView: '&'
65 69 }
... ...
... ... @@ -35,14 +35,14 @@ export default function EntityViewRoutes($stateProvider, types) {
35 35 }
36 36 },
37 37 data: {
38   - entityViewsTypes: 'tenant',
  38 + entityViewsType: 'tenant',
39 39 searchEnabled: true,
40 40 searchByEntitySubtype: true,
41 41 searchEntityType: types.entityType.entityview,
42   - pageTitle: 'entity-views.entity-views'
  42 + pageTitle: 'entity-view.entity-views'
43 43 },
44 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 48 .state('home.customers.entityViews', {
... ... @@ -58,14 +58,14 @@ export default function EntityViewRoutes($stateProvider, types) {
58 58 }
59 59 },
60 60 data: {
61   - entityViewsTypes: 'customer',
  61 + entityViewsType: 'customer',
62 62 searchEnabled: true,
63 63 searchByEntitySubtype: true,
64 64 searchEntityType: types.entityType.entityview,
65 65 pageTitle: 'customer.entity-views'
66 66 },
67 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 29 on-assign-to-customer="vm.assignToCustomer(event, [ vm.grid.detailsConfig.currentItem.id.id ])"
30 30 on-make-public="vm.makePublic(event, vm.grid.detailsConfig.currentItem)"
31 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 32 on-delete-entity-view="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"></tb-entity-view>
34 33 </md-tab>
35 34 <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.attributes' | translate }}">
36 35 <tb-attribute-table flex
37 36 entity-id="vm.grid.operatingItem().id.id"
38   - entity-type="{{vm.types.entityType.entityview}}"
  37 + entity-type="{{vm.types.entityType.entityView}}"
39 38 entity-name="vm.grid.operatingItem().name"
40 39 default-attribute-scope="{{vm.types.attributesScope.client.value}}">
41 40 </tb-attribute-table>
... ... @@ -43,19 +42,19 @@
43 42 <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.latest-telemetry' | translate }}">
44 43 <tb-attribute-table flex
45 44 entity-id="vm.grid.operatingItem().id.id"
46   - entity-type="{{vm.types.entityType.entityview}}"
  45 + entity-type="{{vm.types.entityType.entityView}}"
47 46 entity-name="vm.grid.operatingItem().name"
48 47 default-attribute-scope="{{vm.types.latestTelemetry.value}}"
49 48 disable-attribute-scope-selection="true">
50 49 </tb-attribute-table>
51 50 </md-tab>
52 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 53 entity-id="vm.grid.operatingItem().id.id">
55 54 </tb-alarm-table>
56 55 </md-tab>
57 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 58 entity-id="vm.grid.operatingItem().id.id"
60 59 tenant-id="vm.grid.operatingItem().tenantId.id"
61 60 default-event-type="{{vm.types.eventType.error.value}}">
... ... @@ -64,18 +63,11 @@
64 63 <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'relation.relations' | translate }}">
65 64 <tb-relation-table flex
66 65 entity-id="vm.grid.operatingItem().id.id"
67   - entity-type="{{vm.types.entityType.entityview}}">
  66 + entity-type="{{vm.types.entityType.entityView}}">
68 67 </tb-relation-table>
69 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 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 71 entity-id="vm.grid.operatingItem().id.id"
80 72 audit-log-mode="{{vm.types.auditLogMode.entity}}">
81 73 </tb-audit-log-table>
... ...
... ... @@ -20,7 +20,7 @@ import thingsboardApiEntityView from '../api/entity-view.service';
20 20 import thingsboardApiCustomer from '../api/customer.service';
21 21
22 22 import EntityViewRoutes from './entity-view.routes';
23   -import EntityViewCardController from './entity-view.controller';
  23 +import {EntityViewController, EntityViewCardController} from './entity-view.controller';
24 24 import AssignEntityViewToCustomerController from './assign-to-customer.controller';
25 25 import AddEntityViewsToCustomerController from './add-entity-views-to-customer.controller';
26 26 import EntityViewDirective from './entity-view.directive';
... ... @@ -33,7 +33,7 @@ export default angular.module('thingsboard.entityView', [
33 33 thingsboardApiCustomer
34 34 ])
35 35 .config(EntityViewRoutes)
36   - .controller('EntityViewController', EntityViewCardController)
  36 + .controller('EntityViewController', EntityViewController)
37 37 .controller('EntityViewCardController', EntityViewCardController)
38 38 .controller('AssignEntityViewToCustomerController', AssignEntityViewToCustomerController)
39 39 .controller('AddEntityViewsToCustomerController', AddEntityViewsToCustomerController)
... ...
... ... @@ -48,6 +48,7 @@ import thingsboardAdmin from '../admin';
48 48 import thingsboardProfile from '../profile';
49 49 import thingsboardAsset from '../asset';
50 50 import thingsboardDevice from '../device';
  51 +import thingsboardEntityView from '../entity-view';
51 52 import thingsboardWidgetLibrary from '../widget';
52 53 import thingsboardDashboard from '../dashboard';
53 54 import thingsboardRuleChain from '../rulechain';
... ... @@ -79,6 +80,7 @@ export default angular.module('thingsboard.home', [
79 80 thingsboardProfile,
80 81 thingsboardAsset,
81 82 thingsboardDevice,
  83 + thingsboardEntityView,
82 84 thingsboardWidgetLibrary,
83 85 thingsboardDashboard,
84 86 thingsboardRuleChain,
... ...
... ... @@ -821,7 +821,8 @@
821 821 "assignedToCustomer": "Assigned to customer",
822 822 "unable-entity-view-device-alias-title": "Unable to delete entity view alias",
823 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 827 "event": {
827 828 "event-type": "Event type",
... ...
... ... @@ -168,6 +168,12 @@ function Menu(userService, $state, $rootScope) {
168 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 177 name: 'widget.widget-library',
172 178 type: 'link',
173 179 state: 'home.widgets-bundles',
... ... @@ -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 247 name: 'dashboard.management',
232 248 places: [
233 249 {
... ... @@ -274,6 +290,12 @@ function Menu(userService, $state, $rootScope) {
274 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 299 name: 'dashboard.dashboards',
278 300 type: 'link',
279 301 state: 'home.dashboards',
... ... @@ -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 }
... ...