Showing
20 changed files
with
226 additions
and
67 deletions
@@ -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 | } |
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,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 | } |