Showing
20 changed files
with
226 additions
and
67 deletions
... | ... | @@ -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 | } | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/entityview/EntityViewSearchQuery.java
0 → 100644
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 | } | ... | ... |