Commit 83ea3f083686a9de050ca6d54fe55ccea25e51e6
1 parent
43596ec5
Move from device type to device profile
Showing
17 changed files
with
229 additions
and
44 deletions
@@ -47,6 +47,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | @@ -47,6 +47,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | ||
47 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 47 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
48 | import org.thingsboard.server.common.data.id.CustomerId; | 48 | import org.thingsboard.server.common.data.id.CustomerId; |
49 | import org.thingsboard.server.common.data.id.DeviceId; | 49 | import org.thingsboard.server.common.data.id.DeviceId; |
50 | +import org.thingsboard.server.common.data.id.DeviceProfileId; | ||
50 | import org.thingsboard.server.common.data.id.TenantId; | 51 | import org.thingsboard.server.common.data.id.TenantId; |
51 | import org.thingsboard.server.common.data.page.PageData; | 52 | import org.thingsboard.server.common.data.page.PageData; |
52 | import org.thingsboard.server.common.data.page.PageLink; | 53 | import org.thingsboard.server.common.data.page.PageLink; |
@@ -315,6 +316,7 @@ public class DeviceController extends BaseController { | @@ -315,6 +316,7 @@ public class DeviceController extends BaseController { | ||
315 | @RequestParam int pageSize, | 316 | @RequestParam int pageSize, |
316 | @RequestParam int page, | 317 | @RequestParam int page, |
317 | @RequestParam(required = false) String type, | 318 | @RequestParam(required = false) String type, |
319 | + @RequestParam(required = false) String deviceProfileId, | ||
318 | @RequestParam(required = false) String textSearch, | 320 | @RequestParam(required = false) String textSearch, |
319 | @RequestParam(required = false) String sortProperty, | 321 | @RequestParam(required = false) String sortProperty, |
320 | @RequestParam(required = false) String sortOrder) throws ThingsboardException { | 322 | @RequestParam(required = false) String sortOrder) throws ThingsboardException { |
@@ -323,6 +325,9 @@ public class DeviceController extends BaseController { | @@ -323,6 +325,9 @@ public class DeviceController extends BaseController { | ||
323 | PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); | 325 | PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
324 | if (type != null && type.trim().length() > 0) { | 326 | if (type != null && type.trim().length() > 0) { |
325 | return checkNotNull(deviceService.findDeviceInfosByTenantIdAndType(tenantId, type, pageLink)); | 327 | return checkNotNull(deviceService.findDeviceInfosByTenantIdAndType(tenantId, type, pageLink)); |
328 | + } else if (deviceProfileId != null && deviceProfileId.length() > 0) { | ||
329 | + DeviceProfileId profileId = new DeviceProfileId(toUUID(deviceProfileId)); | ||
330 | + return checkNotNull(deviceService.findDeviceInfosByTenantIdAndDeviceProfileId(tenantId, profileId, pageLink)); | ||
326 | } else { | 331 | } else { |
327 | return checkNotNull(deviceService.findDeviceInfosByTenantId(tenantId, pageLink)); | 332 | return checkNotNull(deviceService.findDeviceInfosByTenantId(tenantId, pageLink)); |
328 | } | 333 | } |
@@ -379,6 +384,7 @@ public class DeviceController extends BaseController { | @@ -379,6 +384,7 @@ public class DeviceController extends BaseController { | ||
379 | @RequestParam int pageSize, | 384 | @RequestParam int pageSize, |
380 | @RequestParam int page, | 385 | @RequestParam int page, |
381 | @RequestParam(required = false) String type, | 386 | @RequestParam(required = false) String type, |
387 | + @RequestParam(required = false) String deviceProfileId, | ||
382 | @RequestParam(required = false) String textSearch, | 388 | @RequestParam(required = false) String textSearch, |
383 | @RequestParam(required = false) String sortProperty, | 389 | @RequestParam(required = false) String sortProperty, |
384 | @RequestParam(required = false) String sortOrder) throws ThingsboardException { | 390 | @RequestParam(required = false) String sortOrder) throws ThingsboardException { |
@@ -390,6 +396,9 @@ public class DeviceController extends BaseController { | @@ -390,6 +396,9 @@ public class DeviceController extends BaseController { | ||
390 | PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); | 396 | PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
391 | if (type != null && type.trim().length() > 0) { | 397 | if (type != null && type.trim().length() > 0) { |
392 | return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); | 398 | return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); |
399 | + } else if (deviceProfileId != null && deviceProfileId.length() > 0) { | ||
400 | + DeviceProfileId profileId = new DeviceProfileId(toUUID(deviceProfileId)); | ||
401 | + return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(tenantId, customerId, profileId, pageLink)); | ||
393 | } else { | 402 | } else { |
394 | return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink)); | 403 | return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink)); |
395 | } | 404 | } |
application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
@@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.AdminSettings; | @@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.AdminSettings; | ||
27 | import org.thingsboard.server.common.data.Customer; | 27 | import org.thingsboard.server.common.data.Customer; |
28 | import org.thingsboard.server.common.data.DataConstants; | 28 | import org.thingsboard.server.common.data.DataConstants; |
29 | import org.thingsboard.server.common.data.Device; | 29 | import org.thingsboard.server.common.data.Device; |
30 | +import org.thingsboard.server.common.data.DeviceProfile; | ||
30 | import org.thingsboard.server.common.data.Tenant; | 31 | import org.thingsboard.server.common.data.Tenant; |
31 | import org.thingsboard.server.common.data.TenantProfile; | 32 | import org.thingsboard.server.common.data.TenantProfile; |
32 | import org.thingsboard.server.common.data.TenantProfileData; | 33 | import org.thingsboard.server.common.data.TenantProfileData; |
@@ -34,6 +35,7 @@ import org.thingsboard.server.common.data.User; | @@ -34,6 +35,7 @@ import org.thingsboard.server.common.data.User; | ||
34 | import org.thingsboard.server.common.data.asset.Asset; | 35 | import org.thingsboard.server.common.data.asset.Asset; |
35 | import org.thingsboard.server.common.data.id.CustomerId; | 36 | import org.thingsboard.server.common.data.id.CustomerId; |
36 | import org.thingsboard.server.common.data.id.DeviceId; | 37 | import org.thingsboard.server.common.data.id.DeviceId; |
38 | +import org.thingsboard.server.common.data.id.DeviceProfileId; | ||
37 | import org.thingsboard.server.common.data.id.TenantId; | 39 | import org.thingsboard.server.common.data.id.TenantId; |
38 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; | 40 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; |
39 | import org.thingsboard.server.common.data.kv.BooleanDataEntry; | 41 | import org.thingsboard.server.common.data.kv.BooleanDataEntry; |
@@ -48,6 +50,7 @@ import org.thingsboard.server.dao.asset.AssetService; | @@ -48,6 +50,7 @@ import org.thingsboard.server.dao.asset.AssetService; | ||
48 | import org.thingsboard.server.dao.attributes.AttributesService; | 50 | import org.thingsboard.server.dao.attributes.AttributesService; |
49 | import org.thingsboard.server.dao.customer.CustomerService; | 51 | import org.thingsboard.server.dao.customer.CustomerService; |
50 | import org.thingsboard.server.dao.device.DeviceCredentialsService; | 52 | import org.thingsboard.server.dao.device.DeviceCredentialsService; |
53 | +import org.thingsboard.server.dao.device.DeviceProfileService; | ||
51 | import org.thingsboard.server.dao.device.DeviceService; | 54 | import org.thingsboard.server.dao.device.DeviceService; |
52 | import org.thingsboard.server.dao.exception.DataValidationException; | 55 | import org.thingsboard.server.dao.exception.DataValidationException; |
53 | import org.thingsboard.server.dao.relation.RelationService; | 56 | import org.thingsboard.server.dao.relation.RelationService; |
@@ -102,6 +105,9 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | @@ -102,6 +105,9 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | ||
102 | private DeviceService deviceService; | 105 | private DeviceService deviceService; |
103 | 106 | ||
104 | @Autowired | 107 | @Autowired |
108 | + private DeviceProfileService deviceProfileService; | ||
109 | + | ||
110 | + @Autowired | ||
105 | private AttributesService attributesService; | 111 | private AttributesService attributesService; |
106 | 112 | ||
107 | @Autowired | 113 | @Autowired |
@@ -213,16 +219,18 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | @@ -213,16 +219,18 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | ||
213 | createUser(Authority.CUSTOMER_USER, demoTenant.getId(), customerB.getId(), "customerB@thingsboard.org", CUSTOMER_CRED); | 219 | createUser(Authority.CUSTOMER_USER, demoTenant.getId(), customerB.getId(), "customerB@thingsboard.org", CUSTOMER_CRED); |
214 | createUser(Authority.CUSTOMER_USER, demoTenant.getId(), customerC.getId(), "customerC@thingsboard.org", CUSTOMER_CRED); | 220 | createUser(Authority.CUSTOMER_USER, demoTenant.getId(), customerC.getId(), "customerC@thingsboard.org", CUSTOMER_CRED); |
215 | 221 | ||
216 | - createDevice(demoTenant.getId(), customerA.getId(), DEFAULT_DEVICE_TYPE, "Test Device A1", "A1_TEST_TOKEN", null); | ||
217 | - createDevice(demoTenant.getId(), customerA.getId(), DEFAULT_DEVICE_TYPE, "Test Device A2", "A2_TEST_TOKEN", null); | ||
218 | - createDevice(demoTenant.getId(), customerA.getId(), DEFAULT_DEVICE_TYPE, "Test Device A3", "A3_TEST_TOKEN", null); | ||
219 | - createDevice(demoTenant.getId(), customerB.getId(), DEFAULT_DEVICE_TYPE, "Test Device B1", "B1_TEST_TOKEN", null); | ||
220 | - createDevice(demoTenant.getId(), customerC.getId(), DEFAULT_DEVICE_TYPE, "Test Device C1", "C1_TEST_TOKEN", null); | 222 | + DeviceProfile defaultDeviceProfile = this.deviceProfileService.findOrCreateDeviceProfile(demoTenant.getId(), DEFAULT_DEVICE_TYPE); |
221 | 223 | ||
222 | - createDevice(demoTenant.getId(), null, DEFAULT_DEVICE_TYPE, "DHT11 Demo Device", "DHT11_DEMO_TOKEN", "Demo device that is used in sample " + | 224 | + createDevice(demoTenant.getId(), customerA.getId(), defaultDeviceProfile.getId(), "Test Device A1", "A1_TEST_TOKEN", null); |
225 | + createDevice(demoTenant.getId(), customerA.getId(), defaultDeviceProfile.getId(), "Test Device A2", "A2_TEST_TOKEN", null); | ||
226 | + createDevice(demoTenant.getId(), customerA.getId(), defaultDeviceProfile.getId(), "Test Device A3", "A3_TEST_TOKEN", null); | ||
227 | + createDevice(demoTenant.getId(), customerB.getId(), defaultDeviceProfile.getId(), "Test Device B1", "B1_TEST_TOKEN", null); | ||
228 | + createDevice(demoTenant.getId(), customerC.getId(), defaultDeviceProfile.getId(), "Test Device C1", "C1_TEST_TOKEN", null); | ||
229 | + | ||
230 | + createDevice(demoTenant.getId(), null, defaultDeviceProfile.getId(), "DHT11 Demo Device", "DHT11_DEMO_TOKEN", "Demo device that is used in sample " + | ||
223 | "applications that upload data from DHT11 temperature and humidity sensor"); | 231 | "applications that upload data from DHT11 temperature and humidity sensor"); |
224 | 232 | ||
225 | - createDevice(demoTenant.getId(), null, DEFAULT_DEVICE_TYPE, "Raspberry Pi Demo Device", "RASPBERRY_PI_DEMO_TOKEN", "Demo device that is used in " + | 233 | + createDevice(demoTenant.getId(), null, defaultDeviceProfile.getId(), "Raspberry Pi Demo Device", "RASPBERRY_PI_DEMO_TOKEN", "Demo device that is used in " + |
226 | "Raspberry Pi GPIO control sample application"); | 234 | "Raspberry Pi GPIO control sample application"); |
227 | 235 | ||
228 | Asset thermostatAlarms = new Asset(); | 236 | Asset thermostatAlarms = new Asset(); |
@@ -231,8 +239,10 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | @@ -231,8 +239,10 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | ||
231 | thermostatAlarms.setType("AlarmPropagationAsset"); | 239 | thermostatAlarms.setType("AlarmPropagationAsset"); |
232 | thermostatAlarms = assetService.saveAsset(thermostatAlarms); | 240 | thermostatAlarms = assetService.saveAsset(thermostatAlarms); |
233 | 241 | ||
234 | - DeviceId t1Id = createDevice(demoTenant.getId(), null, "thermostat", "Thermostat T1", "T1_TEST_TOKEN", "Demo device for Thermostats dashboard").getId(); | ||
235 | - DeviceId t2Id = createDevice(demoTenant.getId(), null, "thermostat", "Thermostat T2", "T2_TEST_TOKEN", "Demo device for Thermostats dashboard").getId(); | 242 | + DeviceProfile thermostatDeviceProfile = this.deviceProfileService.findOrCreateDeviceProfile(demoTenant.getId(), "thermostat"); |
243 | + | ||
244 | + DeviceId t1Id = createDevice(demoTenant.getId(), null, thermostatDeviceProfile.getId(), "Thermostat T1", "T1_TEST_TOKEN", "Demo device for Thermostats dashboard").getId(); | ||
245 | + DeviceId t2Id = createDevice(demoTenant.getId(), null, thermostatDeviceProfile.getId(), "Thermostat T2", "T2_TEST_TOKEN", "Demo device for Thermostats dashboard").getId(); | ||
236 | 246 | ||
237 | relationService.saveRelation(thermostatAlarms.getTenantId(), new EntityRelation(thermostatAlarms.getId(), t1Id, "ToAlarmPropagationAsset")); | 247 | relationService.saveRelation(thermostatAlarms.getTenantId(), new EntityRelation(thermostatAlarms.getId(), t1Id, "ToAlarmPropagationAsset")); |
238 | relationService.saveRelation(thermostatAlarms.getTenantId(), new EntityRelation(thermostatAlarms.getId(), t2Id, "ToAlarmPropagationAsset")); | 248 | relationService.saveRelation(thermostatAlarms.getTenantId(), new EntityRelation(thermostatAlarms.getId(), t2Id, "ToAlarmPropagationAsset")); |
@@ -308,14 +318,14 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | @@ -308,14 +318,14 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | ||
308 | 318 | ||
309 | private Device createDevice(TenantId tenantId, | 319 | private Device createDevice(TenantId tenantId, |
310 | CustomerId customerId, | 320 | CustomerId customerId, |
311 | - String type, | 321 | + DeviceProfileId deviceProfileId, |
312 | String name, | 322 | String name, |
313 | String accessToken, | 323 | String accessToken, |
314 | String description) { | 324 | String description) { |
315 | Device device = new Device(); | 325 | Device device = new Device(); |
316 | device.setTenantId(tenantId); | 326 | device.setTenantId(tenantId); |
317 | device.setCustomerId(customerId); | 327 | device.setCustomerId(customerId); |
318 | - device.setType(type); | 328 | + device.setDeviceProfileId(deviceProfileId); |
319 | device.setName(name); | 329 | device.setName(name); |
320 | if (description != null) { | 330 | if (description != null) { |
321 | ObjectNode additionalInfo = objectMapper.createObjectNode(); | 331 | ObjectNode additionalInfo = objectMapper.createObjectNode(); |
@@ -22,6 +22,7 @@ import org.thingsboard.server.common.data.EntitySubtype; | @@ -22,6 +22,7 @@ import org.thingsboard.server.common.data.EntitySubtype; | ||
22 | import org.thingsboard.server.common.data.device.DeviceSearchQuery; | 22 | import org.thingsboard.server.common.data.device.DeviceSearchQuery; |
23 | import org.thingsboard.server.common.data.id.CustomerId; | 23 | import org.thingsboard.server.common.data.id.CustomerId; |
24 | import org.thingsboard.server.common.data.id.DeviceId; | 24 | import org.thingsboard.server.common.data.id.DeviceId; |
25 | +import org.thingsboard.server.common.data.id.DeviceProfileId; | ||
25 | import org.thingsboard.server.common.data.id.TenantId; | 26 | import org.thingsboard.server.common.data.id.TenantId; |
26 | import org.thingsboard.server.common.data.page.PageData; | 27 | import org.thingsboard.server.common.data.page.PageData; |
27 | import org.thingsboard.server.common.data.page.PageLink; | 28 | import org.thingsboard.server.common.data.page.PageLink; |
@@ -56,6 +57,8 @@ public interface DeviceService { | @@ -56,6 +57,8 @@ public interface DeviceService { | ||
56 | 57 | ||
57 | PageData<DeviceInfo> findDeviceInfosByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink); | 58 | PageData<DeviceInfo> findDeviceInfosByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink); |
58 | 59 | ||
60 | + PageData<DeviceInfo> findDeviceInfosByTenantIdAndDeviceProfileId(TenantId tenantId, DeviceProfileId deviceProfileId, PageLink pageLink); | ||
61 | + | ||
59 | ListenableFuture<List<Device>> findDevicesByTenantIdAndIdsAsync(TenantId tenantId, List<DeviceId> deviceIds); | 62 | ListenableFuture<List<Device>> findDevicesByTenantIdAndIdsAsync(TenantId tenantId, List<DeviceId> deviceIds); |
60 | 63 | ||
61 | void deleteDevicesByTenantId(TenantId tenantId); | 64 | void deleteDevicesByTenantId(TenantId tenantId); |
@@ -68,6 +71,8 @@ public interface DeviceService { | @@ -68,6 +71,8 @@ public interface DeviceService { | ||
68 | 71 | ||
69 | PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, PageLink pageLink); | 72 | PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, PageLink pageLink); |
70 | 73 | ||
74 | + PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(TenantId tenantId, CustomerId customerId, DeviceProfileId deviceProfileId, PageLink pageLink); | ||
75 | + | ||
71 | ListenableFuture<List<Device>> findDevicesByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<DeviceId> deviceIds); | 76 | ListenableFuture<List<Device>> findDevicesByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<DeviceId> deviceIds); |
72 | 77 | ||
73 | void unassignCustomerDevices(TenantId tenantId, CustomerId customerId); | 78 | void unassignCustomerDevices(TenantId tenantId, CustomerId customerId); |
@@ -90,6 +90,16 @@ public interface DeviceDao extends Dao<Device> { | @@ -90,6 +90,16 @@ public interface DeviceDao extends Dao<Device> { | ||
90 | PageData<DeviceInfo> findDeviceInfosByTenantIdAndType(UUID tenantId, String type, PageLink pageLink); | 90 | PageData<DeviceInfo> findDeviceInfosByTenantIdAndType(UUID tenantId, String type, PageLink pageLink); |
91 | 91 | ||
92 | /** | 92 | /** |
93 | + * Find device infos by tenantId, deviceProfileId and page link. | ||
94 | + * | ||
95 | + * @param tenantId the tenantId | ||
96 | + * @param deviceProfileId the deviceProfileId | ||
97 | + * @param pageLink the page link | ||
98 | + * @return the list of device info objects | ||
99 | + */ | ||
100 | + PageData<DeviceInfo> findDeviceInfosByTenantIdAndDeviceProfileId(UUID tenantId, UUID deviceProfileId, PageLink pageLink); | ||
101 | + | ||
102 | + /** | ||
93 | * Find devices by tenantId and devices Ids. | 103 | * Find devices by tenantId and devices Ids. |
94 | * | 104 | * |
95 | * @param tenantId the tenantId | 105 | * @param tenantId the tenantId |
@@ -140,6 +150,16 @@ public interface DeviceDao extends Dao<Device> { | @@ -140,6 +150,16 @@ public interface DeviceDao extends Dao<Device> { | ||
140 | */ | 150 | */ |
141 | PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink); | 151 | PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink); |
142 | 152 | ||
153 | + /** | ||
154 | + * Find device infos by tenantId, customerId, deviceProfileId and page link. | ||
155 | + * | ||
156 | + * @param tenantId the tenantId | ||
157 | + * @param customerId the customerId | ||
158 | + * @param deviceProfileId the deviceProfileId | ||
159 | + * @param pageLink the page link | ||
160 | + * @return the list of device info objects | ||
161 | + */ | ||
162 | + PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(UUID tenantId, UUID customerId, UUID deviceProfileId, PageLink pageLink); | ||
143 | 163 | ||
144 | /** | 164 | /** |
145 | * Find devices by tenantId, customerId and devices Ids. | 165 | * Find devices by tenantId, customerId and devices Ids. |
@@ -87,6 +87,7 @@ import static org.thingsboard.server.dao.service.Validator.validateString; | @@ -87,6 +87,7 @@ import static org.thingsboard.server.dao.service.Validator.validateString; | ||
87 | public class DeviceServiceImpl extends AbstractEntityService implements DeviceService { | 87 | public class DeviceServiceImpl extends AbstractEntityService implements DeviceService { |
88 | 88 | ||
89 | public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; | 89 | public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; |
90 | + public static final String INCORRECT_DEVICE_PROFILE_ID = "Incorrect deviceProfileId "; | ||
90 | public static final String INCORRECT_PAGE_LINK = "Incorrect page link "; | 91 | public static final String INCORRECT_PAGE_LINK = "Incorrect page link "; |
91 | public static final String INCORRECT_CUSTOMER_ID = "Incorrect customerId "; | 92 | public static final String INCORRECT_CUSTOMER_ID = "Incorrect customerId "; |
92 | public static final String INCORRECT_DEVICE_ID = "Incorrect deviceId "; | 93 | public static final String INCORRECT_DEVICE_ID = "Incorrect deviceId "; |
@@ -303,6 +304,15 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | @@ -303,6 +304,15 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | ||
303 | } | 304 | } |
304 | 305 | ||
305 | @Override | 306 | @Override |
307 | + public PageData<DeviceInfo> findDeviceInfosByTenantIdAndDeviceProfileId(TenantId tenantId, DeviceProfileId deviceProfileId, PageLink pageLink) { | ||
308 | + log.trace("Executing findDeviceInfosByTenantIdAndDeviceProfileId, tenantId [{}], deviceProfileId [{}], pageLink [{}]", tenantId, deviceProfileId, pageLink); | ||
309 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | ||
310 | + validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId); | ||
311 | + validatePageLink(pageLink); | ||
312 | + return deviceDao.findDeviceInfosByTenantIdAndDeviceProfileId(tenantId.getId(), deviceProfileId.getId(), pageLink); | ||
313 | + } | ||
314 | + | ||
315 | + @Override | ||
306 | public ListenableFuture<List<Device>> findDevicesByTenantIdAndIdsAsync(TenantId tenantId, List<DeviceId> deviceIds) { | 316 | public ListenableFuture<List<Device>> findDevicesByTenantIdAndIdsAsync(TenantId tenantId, List<DeviceId> deviceIds) { |
307 | log.trace("Executing findDevicesByTenantIdAndIdsAsync, tenantId [{}], deviceIds [{}]", tenantId, deviceIds); | 317 | log.trace("Executing findDevicesByTenantIdAndIdsAsync, tenantId [{}], deviceIds [{}]", tenantId, deviceIds); |
308 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | 318 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
@@ -357,6 +367,16 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | @@ -357,6 +367,16 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | ||
357 | } | 367 | } |
358 | 368 | ||
359 | @Override | 369 | @Override |
370 | + public PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(TenantId tenantId, CustomerId customerId, DeviceProfileId deviceProfileId, PageLink pageLink) { | ||
371 | + log.trace("Executing findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId, tenantId [{}], customerId [{}], deviceProfileId [{}], pageLink [{}]", tenantId, customerId, deviceProfileId, pageLink); | ||
372 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | ||
373 | + validateId(customerId, INCORRECT_CUSTOMER_ID + customerId); | ||
374 | + validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId); | ||
375 | + validatePageLink(pageLink); | ||
376 | + return deviceDao.findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(tenantId.getId(), customerId.getId(), deviceProfileId.getId(), pageLink); | ||
377 | + } | ||
378 | + | ||
379 | + @Override | ||
360 | public ListenableFuture<List<Device>> findDevicesByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<DeviceId> deviceIds) { | 380 | public ListenableFuture<List<Device>> findDevicesByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<DeviceId> deviceIds) { |
361 | log.trace("Executing findDevicesByTenantIdCustomerIdAndIdsAsync, tenantId [{}], customerId [{}], deviceIds [{}]", tenantId, customerId, deviceIds); | 381 | log.trace("Executing findDevicesByTenantIdCustomerIdAndIdsAsync, tenantId [{}], customerId [{}], deviceIds [{}]", tenantId, customerId, deviceIds); |
362 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | 382 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
@@ -106,6 +106,18 @@ public interface DeviceRepository extends PagingAndSortingRepository<DeviceEntit | @@ -106,6 +106,18 @@ public interface DeviceRepository extends PagingAndSortingRepository<DeviceEntit | ||
106 | @Param("textSearch") String textSearch, | 106 | @Param("textSearch") String textSearch, |
107 | Pageable pageable); | 107 | Pageable pageable); |
108 | 108 | ||
109 | + @Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " + | ||
110 | + "FROM DeviceEntity d " + | ||
111 | + "LEFT JOIN CustomerEntity c on c.id = d.customerId " + | ||
112 | + "LEFT JOIN DeviceProfileEntity p on p.id = d.deviceProfileId " + | ||
113 | + "WHERE d.tenantId = :tenantId " + | ||
114 | + "AND d.deviceProfileId = :deviceProfileId " + | ||
115 | + "AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") | ||
116 | + Page<DeviceInfoEntity> findDeviceInfosByTenantIdAndDeviceProfileId(@Param("tenantId") UUID tenantId, | ||
117 | + @Param("deviceProfileId") UUID deviceProfileId, | ||
118 | + @Param("textSearch") String textSearch, | ||
119 | + Pageable pageable); | ||
120 | + | ||
109 | @Query("SELECT d FROM DeviceEntity d WHERE d.tenantId = :tenantId " + | 121 | @Query("SELECT d FROM DeviceEntity d WHERE d.tenantId = :tenantId " + |
110 | "AND d.customerId = :customerId " + | 122 | "AND d.customerId = :customerId " + |
111 | "AND d.type = :type " + | 123 | "AND d.type = :type " + |
@@ -130,6 +142,20 @@ public interface DeviceRepository extends PagingAndSortingRepository<DeviceEntit | @@ -130,6 +142,20 @@ public interface DeviceRepository extends PagingAndSortingRepository<DeviceEntit | ||
130 | @Param("textSearch") String textSearch, | 142 | @Param("textSearch") String textSearch, |
131 | Pageable pageable); | 143 | Pageable pageable); |
132 | 144 | ||
145 | + @Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " + | ||
146 | + "FROM DeviceEntity d " + | ||
147 | + "LEFT JOIN CustomerEntity c on c.id = d.customerId " + | ||
148 | + "LEFT JOIN DeviceProfileEntity p on p.id = d.deviceProfileId " + | ||
149 | + "WHERE d.tenantId = :tenantId " + | ||
150 | + "AND d.customerId = :customerId " + | ||
151 | + "AND d.deviceProfileId = :deviceProfileId " + | ||
152 | + "AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") | ||
153 | + Page<DeviceInfoEntity> findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(@Param("tenantId") UUID tenantId, | ||
154 | + @Param("customerId") UUID customerId, | ||
155 | + @Param("deviceProfileId") UUID deviceProfileId, | ||
156 | + @Param("textSearch") String textSearch, | ||
157 | + Pageable pageable); | ||
158 | + | ||
133 | @Query("SELECT DISTINCT d.type FROM DeviceEntity d WHERE d.tenantId = :tenantId") | 159 | @Query("SELECT DISTINCT d.type FROM DeviceEntity d WHERE d.tenantId = :tenantId") |
134 | List<String> findTenantDeviceTypes(@Param("tenantId") UUID tenantId); | 160 | List<String> findTenantDeviceTypes(@Param("tenantId") UUID tenantId); |
135 | 161 |
@@ -157,6 +157,16 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device> | @@ -157,6 +157,16 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device> | ||
157 | } | 157 | } |
158 | 158 | ||
159 | @Override | 159 | @Override |
160 | + public PageData<DeviceInfo> findDeviceInfosByTenantIdAndDeviceProfileId(UUID tenantId, UUID deviceProfileId, PageLink pageLink) { | ||
161 | + return DaoUtil.toPageData( | ||
162 | + deviceRepository.findDeviceInfosByTenantIdAndDeviceProfileId( | ||
163 | + tenantId, | ||
164 | + deviceProfileId, | ||
165 | + Objects.toString(pageLink.getTextSearch(), ""), | ||
166 | + DaoUtil.toPageable(pageLink, DeviceInfoEntity.deviceInfoColumnMap))); | ||
167 | + } | ||
168 | + | ||
169 | + @Override | ||
160 | public PageData<Device> findDevicesByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink) { | 170 | public PageData<Device> findDevicesByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink) { |
161 | return DaoUtil.toPageData( | 171 | return DaoUtil.toPageData( |
162 | deviceRepository.findByTenantIdAndCustomerIdAndType( | 172 | deviceRepository.findByTenantIdAndCustomerIdAndType( |
@@ -179,6 +189,17 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device> | @@ -179,6 +189,17 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device> | ||
179 | } | 189 | } |
180 | 190 | ||
181 | @Override | 191 | @Override |
192 | + public PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(UUID tenantId, UUID customerId, UUID deviceProfileId, PageLink pageLink) { | ||
193 | + return DaoUtil.toPageData( | ||
194 | + deviceRepository.findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId( | ||
195 | + tenantId, | ||
196 | + customerId, | ||
197 | + deviceProfileId, | ||
198 | + Objects.toString(pageLink.getTextSearch(), ""), | ||
199 | + DaoUtil.toPageable(pageLink, DeviceInfoEntity.deviceInfoColumnMap))); | ||
200 | + } | ||
201 | + | ||
202 | + @Override | ||
182 | public ListenableFuture<List<EntitySubtype>> findTenantDeviceTypesAsync(UUID tenantId) { | 203 | public ListenableFuture<List<EntitySubtype>> findTenantDeviceTypesAsync(UUID tenantId) { |
183 | return service.submit(() -> convertTenantDeviceTypesToDto(tenantId, deviceRepository.findTenantDeviceTypes(tenantId))); | 204 | return service.submit(() -> convertTenantDeviceTypesToDto(tenantId, deviceRepository.findTenantDeviceTypes(tenantId))); |
184 | } | 205 | } |
@@ -46,12 +46,24 @@ export class DeviceService { | @@ -46,12 +46,24 @@ export class DeviceService { | ||
46 | defaultHttpOptionsFromConfig(config)); | 46 | defaultHttpOptionsFromConfig(config)); |
47 | } | 47 | } |
48 | 48 | ||
49 | + public getTenantDeviceInfosByDeviceProfileId(pageLink: PageLink, deviceProfileId: string = '', | ||
50 | + config?: RequestConfig): Observable<PageData<DeviceInfo>> { | ||
51 | + return this.http.get<PageData<DeviceInfo>>(`/api/tenant/deviceInfos${pageLink.toQuery()}&deviceProfileId=${deviceProfileId}`, | ||
52 | + defaultHttpOptionsFromConfig(config)); | ||
53 | + } | ||
54 | + | ||
49 | public getCustomerDeviceInfos(customerId: string, pageLink: PageLink, type: string = '', | 55 | public getCustomerDeviceInfos(customerId: string, pageLink: PageLink, type: string = '', |
50 | config?: RequestConfig): Observable<PageData<DeviceInfo>> { | 56 | config?: RequestConfig): Observable<PageData<DeviceInfo>> { |
51 | return this.http.get<PageData<DeviceInfo>>(`/api/customer/${customerId}/deviceInfos${pageLink.toQuery()}&type=${type}`, | 57 | return this.http.get<PageData<DeviceInfo>>(`/api/customer/${customerId}/deviceInfos${pageLink.toQuery()}&type=${type}`, |
52 | defaultHttpOptionsFromConfig(config)); | 58 | defaultHttpOptionsFromConfig(config)); |
53 | } | 59 | } |
54 | 60 | ||
61 | + public getCustomerDeviceInfosByDeviceProfileId(customerId: string, pageLink: PageLink, deviceProfileId: string = '', | ||
62 | + config?: RequestConfig): Observable<PageData<DeviceInfo>> { | ||
63 | + return this.http.get<PageData<DeviceInfo>>(`/api/customer/${customerId}/deviceInfos${pageLink.toQuery()}&deviceProfileId=${deviceProfileId}`, | ||
64 | + defaultHttpOptionsFromConfig(config)); | ||
65 | + } | ||
66 | + | ||
55 | public getDevice(deviceId: string, config?: RequestConfig): Observable<Device> { | 67 | public getDevice(deviceId: string, config?: RequestConfig): Observable<Device> { |
56 | return this.http.get<Device>(`/api/device/${deviceId}`, defaultHttpOptionsFromConfig(config)); | 68 | return this.http.get<Device>(`/api/device/${deviceId}`, defaultHttpOptionsFromConfig(config)); |
57 | } | 69 | } |
@@ -30,7 +30,7 @@ | @@ -30,7 +30,7 @@ | ||
30 | (click)="clear()"> | 30 | (click)="clear()"> |
31 | <mat-icon class="material-icons">close</mat-icon> | 31 | <mat-icon class="material-icons">close</mat-icon> |
32 | </button> | 32 | </button> |
33 | - <button *ngIf="selectDeviceProfileFormGroup.get('deviceProfile').value && !disabled" | 33 | + <button *ngIf="selectDeviceProfileFormGroup.get('deviceProfile').value && !disabled && editProfileEnabled" |
34 | type="button" | 34 | type="button" |
35 | matSuffix mat-button mat-icon-button aria-label="Edit" | 35 | matSuffix mat-button mat-icon-button aria-label="Edit" |
36 | matTooltip="{{ 'device-profile.edit' | translate }}" | 36 | matTooltip="{{ 'device-profile.edit' | translate }}" |
@@ -40,6 +40,7 @@ | @@ -40,6 +40,7 @@ | ||
40 | </button> | 40 | </button> |
41 | <mat-autocomplete | 41 | <mat-autocomplete |
42 | class="tb-autocomplete" | 42 | class="tb-autocomplete" |
43 | + (closed)="onPanelClosed()" | ||
43 | #deviceProfileAutocomplete="matAutocomplete" | 44 | #deviceProfileAutocomplete="matAutocomplete" |
44 | [displayWith]="displayDeviceProfileFn"> | 45 | [displayWith]="displayDeviceProfileFn"> |
45 | <mat-option *ngFor="let deviceProfile of filteredDeviceProfiles | async" [value]="deviceProfile"> | 46 | <mat-option *ngFor="let deviceProfile of filteredDeviceProfiles | async" [value]="deviceProfile"> |
@@ -14,12 +14,21 @@ | @@ -14,12 +14,21 @@ | ||
14 | /// limitations under the License. | 14 | /// limitations under the License. |
15 | /// | 15 | /// |
16 | 16 | ||
17 | -import { Component, ElementRef, EventEmitter, forwardRef, Input, OnInit, Output, ViewChild } from '@angular/core'; | 17 | +import { |
18 | + Component, | ||
19 | + ElementRef, | ||
20 | + EventEmitter, | ||
21 | + forwardRef, | ||
22 | + Input, NgZone, | ||
23 | + OnInit, | ||
24 | + Output, | ||
25 | + ViewChild | ||
26 | +} from '@angular/core'; | ||
18 | import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; | 27 | import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; |
19 | import { Observable } from 'rxjs'; | 28 | import { Observable } from 'rxjs'; |
20 | import { PageLink } from '@shared/models/page/page-link'; | 29 | import { PageLink } from '@shared/models/page/page-link'; |
21 | import { Direction } from '@shared/models/page/sort-order'; | 30 | import { Direction } from '@shared/models/page/sort-order'; |
22 | -import { map, mergeMap, share, startWith, tap } from 'rxjs/operators'; | 31 | +import { map, mergeMap, share, tap } from 'rxjs/operators'; |
23 | import { Store } from '@ngrx/store'; | 32 | import { Store } from '@ngrx/store'; |
24 | import { AppState } from '@app/core/core.state'; | 33 | import { AppState } from '@app/core/core.state'; |
25 | import { TranslateService } from '@ngx-translate/core'; | 34 | import { TranslateService } from '@ngx-translate/core'; |
@@ -39,6 +48,7 @@ import { | @@ -39,6 +48,7 @@ import { | ||
39 | } from '@shared/models/device.models'; | 48 | } from '@shared/models/device.models'; |
40 | import { DeviceProfileService } from '@core/http/device-profile.service'; | 49 | import { DeviceProfileService } from '@core/http/device-profile.service'; |
41 | import { DeviceProfileDialogComponent, DeviceProfileDialogData } from './device-profile-dialog.component'; | 50 | import { DeviceProfileDialogComponent, DeviceProfileDialogData } from './device-profile-dialog.component'; |
51 | +import { MatAutocomplete } from '@angular/material/autocomplete'; | ||
42 | 52 | ||
43 | @Component({ | 53 | @Component({ |
44 | selector: 'tb-device-profile-autocomplete', | 54 | selector: 'tb-device-profile-autocomplete', |
@@ -59,6 +69,12 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, | @@ -59,6 +69,12 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, | ||
59 | @Input() | 69 | @Input() |
60 | selectDefaultProfile = false; | 70 | selectDefaultProfile = false; |
61 | 71 | ||
72 | + @Input() | ||
73 | + displayAllOnEmpty = false; | ||
74 | + | ||
75 | + @Input() | ||
76 | + editProfileEnabled = true; | ||
77 | + | ||
62 | private requiredValue: boolean; | 78 | private requiredValue: boolean; |
63 | get required(): boolean { | 79 | get required(): boolean { |
64 | return this.requiredValue; | 80 | return this.requiredValue; |
@@ -79,12 +95,23 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, | @@ -79,12 +95,23 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, | ||
79 | 95 | ||
80 | @ViewChild('deviceProfileInput', {static: true}) deviceProfileInput: ElementRef; | 96 | @ViewChild('deviceProfileInput', {static: true}) deviceProfileInput: ElementRef; |
81 | 97 | ||
98 | + @ViewChild('deviceProfileAutocomplete', {static: true}) deviceProfileAutocomplete: MatAutocomplete; | ||
99 | + | ||
82 | filteredDeviceProfiles: Observable<Array<DeviceProfileInfo>>; | 100 | filteredDeviceProfiles: Observable<Array<DeviceProfileInfo>>; |
83 | 101 | ||
84 | searchText = ''; | 102 | searchText = ''; |
85 | 103 | ||
86 | private dirty = false; | 104 | private dirty = false; |
87 | 105 | ||
106 | + private ignoreClosedPanel = false; | ||
107 | + | ||
108 | + private allDeviceProfile: DeviceProfileInfo = { | ||
109 | + name: this.translate.instant('device-profile.all-device-profiles'), | ||
110 | + type: DeviceProfileType.DEFAULT, | ||
111 | + transportType: DeviceTransportType.DEFAULT, | ||
112 | + id: null | ||
113 | + }; | ||
114 | + | ||
88 | private propagateChange = (v: any) => { }; | 115 | private propagateChange = (v: any) => { }; |
89 | 116 | ||
90 | constructor(private store: Store<AppState>, | 117 | constructor(private store: Store<AppState>, |
@@ -92,6 +119,7 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, | @@ -92,6 +119,7 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, | ||
92 | public truncate: TruncatePipe, | 119 | public truncate: TruncatePipe, |
93 | private deviceProfileService: DeviceProfileService, | 120 | private deviceProfileService: DeviceProfileService, |
94 | private fb: FormBuilder, | 121 | private fb: FormBuilder, |
122 | + private zone: NgZone, | ||
95 | private dialog: MatDialog) { | 123 | private dialog: MatDialog) { |
96 | this.selectDeviceProfileFormGroup = this.fb.group({ | 124 | this.selectDeviceProfileFormGroup = this.fb.group({ |
97 | deviceProfile: [null] | 125 | deviceProfile: [null] |
@@ -115,9 +143,25 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, | @@ -115,9 +143,25 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, | ||
115 | } else { | 143 | } else { |
116 | modelValue = value; | 144 | modelValue = value; |
117 | } | 145 | } |
118 | - this.updateView(modelValue); | 146 | + if (!this.displayAllOnEmpty || modelValue) { |
147 | + this.updateView(modelValue); | ||
148 | + } | ||
149 | + }), | ||
150 | + map(value => { | ||
151 | + if (value) { | ||
152 | + if (typeof value === 'string') { | ||
153 | + return value; | ||
154 | + } else { | ||
155 | + if (this.displayAllOnEmpty && value === this.allDeviceProfile) { | ||
156 | + return ''; | ||
157 | + } else { | ||
158 | + return value.name; | ||
159 | + } | ||
160 | + } | ||
161 | + } else { | ||
162 | + return ''; | ||
163 | + } | ||
119 | }), | 164 | }), |
120 | - map(value => value ? (typeof value === 'string' ? value : value.name) : ''), | ||
121 | mergeMap(name => this.fetchDeviceProfiles(name) ), | 165 | mergeMap(name => this.fetchDeviceProfiles(name) ), |
122 | share() | 166 | share() |
123 | ); | 167 | ); |
@@ -150,6 +194,9 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, | @@ -150,6 +194,9 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, | ||
150 | this.deviceProfileChanged.emit(profile); | 194 | this.deviceProfileChanged.emit(profile); |
151 | } | 195 | } |
152 | ); | 196 | ); |
197 | + } else if (this.displayAllOnEmpty) { | ||
198 | + this.modelValue = null; | ||
199 | + this.selectDeviceProfileFormGroup.get('deviceProfile').patchValue(this.allDeviceProfile, {emitEvent: false}); | ||
153 | } else { | 200 | } else { |
154 | this.modelValue = null; | 201 | this.modelValue = null; |
155 | this.selectDeviceProfileFormGroup.get('deviceProfile').patchValue(null, {emitEvent: false}); | 202 | this.selectDeviceProfileFormGroup.get('deviceProfile').patchValue(null, {emitEvent: false}); |
@@ -165,8 +212,20 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, | @@ -165,8 +212,20 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, | ||
165 | } | 212 | } |
166 | } | 213 | } |
167 | 214 | ||
215 | + onPanelClosed() { | ||
216 | + if (this.ignoreClosedPanel) { | ||
217 | + this.ignoreClosedPanel = false; | ||
218 | + } else { | ||
219 | + if (this.displayAllOnEmpty && !this.selectDeviceProfileFormGroup.get('deviceProfile').value) { | ||
220 | + this.zone.run(() => { | ||
221 | + this.selectDeviceProfileFormGroup.get('deviceProfile').patchValue(this.allDeviceProfile, {emitEvent: true}); | ||
222 | + }, 0); | ||
223 | + } | ||
224 | + } | ||
225 | + } | ||
226 | + | ||
168 | updateView(deviceProfile: DeviceProfileInfo | null) { | 227 | updateView(deviceProfile: DeviceProfileInfo | null) { |
169 | - const idValue = deviceProfile ? new DeviceProfileId(deviceProfile.id.id) : null; | 228 | + const idValue = deviceProfile && deviceProfile.id ? new DeviceProfileId(deviceProfile.id.id) : null; |
170 | if (!entityIdEquals(this.modelValue, idValue)) { | 229 | if (!entityIdEquals(this.modelValue, idValue)) { |
171 | this.modelValue = idValue; | 230 | this.modelValue = idValue; |
172 | this.propagateChange(this.modelValue); | 231 | this.propagateChange(this.modelValue); |
@@ -186,12 +245,17 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, | @@ -186,12 +245,17 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, | ||
186 | }); | 245 | }); |
187 | return this.deviceProfileService.getDeviceProfileInfos(pageLink, {ignoreLoading: true}).pipe( | 246 | return this.deviceProfileService.getDeviceProfileInfos(pageLink, {ignoreLoading: true}).pipe( |
188 | map(pageData => { | 247 | map(pageData => { |
189 | - return pageData.data; | 248 | + let data = pageData.data; |
249 | + if (this.displayAllOnEmpty) { | ||
250 | + data = [this.allDeviceProfile, ...data]; | ||
251 | + } | ||
252 | + return data; | ||
190 | }) | 253 | }) |
191 | ); | 254 | ); |
192 | } | 255 | } |
193 | 256 | ||
194 | clear() { | 257 | clear() { |
258 | + this.ignoreClosedPanel = true; | ||
195 | this.selectDeviceProfileFormGroup.get('deviceProfile').patchValue(null, {emitEvent: true}); | 259 | this.selectDeviceProfileFormGroup.get('deviceProfile').patchValue(null, {emitEvent: true}); |
196 | setTimeout(() => { | 260 | setTimeout(() => { |
197 | this.deviceProfileInput.nativeElement.blur(); | 261 | this.deviceProfileInput.nativeElement.blur(); |
@@ -204,7 +268,7 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, | @@ -204,7 +268,7 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, | ||
204 | } | 268 | } |
205 | 269 | ||
206 | deviceProfileEnter($event: KeyboardEvent) { | 270 | deviceProfileEnter($event: KeyboardEvent) { |
207 | - if ($event.keyCode === ENTER) { | 271 | + if (this.editProfileEnabled && $event.keyCode === ENTER) { |
208 | $event.preventDefault(); | 272 | $event.preventDefault(); |
209 | if (!this.modelValue) { | 273 | if (!this.modelValue) { |
210 | this.createDeviceProfile($event, this.searchText); | 274 | this.createDeviceProfile($event, this.searchText); |
@@ -15,9 +15,9 @@ | @@ -15,9 +15,9 @@ | ||
15 | limitations under the License. | 15 | limitations under the License. |
16 | 16 | ||
17 | --> | 17 | --> |
18 | -<tb-entity-subtype-select | ||
19 | - [showLabel]="true" | ||
20 | - [entityType]="entityType.DEVICE" | ||
21 | - [ngModel]="entitiesTableConfig.componentsData.deviceType" | ||
22 | - (ngModelChange)="deviceTypeChanged($event)"> | ||
23 | -</tb-entity-subtype-select> | 18 | +<tb-device-profile-autocomplete |
19 | + [ngModel]="entitiesTableConfig.componentsData.deviceProfileId" | ||
20 | + (ngModelChange)="deviceProfileChanged($event)" | ||
21 | + [displayAllOnEmpty]="true" | ||
22 | + [editProfileEnabled]="false"> | ||
23 | +</tb-device-profile-autocomplete> |
@@ -20,6 +20,7 @@ import { AppState } from '@core/core.state'; | @@ -20,6 +20,7 @@ import { AppState } from '@core/core.state'; | ||
20 | import { EntityTableHeaderComponent } from '../../components/entity/entity-table-header.component'; | 20 | import { EntityTableHeaderComponent } from '../../components/entity/entity-table-header.component'; |
21 | import { DeviceInfo } from '@app/shared/models/device.models'; | 21 | import { DeviceInfo } from '@app/shared/models/device.models'; |
22 | import { EntityType } from '@shared/models/entity-type.models'; | 22 | import { EntityType } from '@shared/models/entity-type.models'; |
23 | +import { DeviceProfileId } from '../../../../shared/models/id/device-profile-id'; | ||
23 | 24 | ||
24 | @Component({ | 25 | @Component({ |
25 | selector: 'tb-device-table-header', | 26 | selector: 'tb-device-table-header', |
@@ -34,8 +35,8 @@ export class DeviceTableHeaderComponent extends EntityTableHeaderComponent<Devic | @@ -34,8 +35,8 @@ export class DeviceTableHeaderComponent extends EntityTableHeaderComponent<Devic | ||
34 | super(store); | 35 | super(store); |
35 | } | 36 | } |
36 | 37 | ||
37 | - deviceTypeChanged(deviceType: string) { | ||
38 | - this.entitiesTableConfig.componentsData.deviceType = deviceType; | 38 | + deviceProfileChanged(deviceProfileId: DeviceProfileId) { |
39 | + this.entitiesTableConfig.componentsData.deviceProfileId = deviceProfileId; | ||
39 | this.entitiesTableConfig.table.resetSortAndFilter(true); | 40 | this.entitiesTableConfig.table.resetSortAndFilter(true); |
40 | } | 41 | } |
41 | 42 |
@@ -90,12 +90,6 @@ | @@ -90,12 +90,6 @@ | ||
90 | (deviceProfileUpdated)="onDeviceProfileUpdated()" | 90 | (deviceProfileUpdated)="onDeviceProfileUpdated()" |
91 | (deviceProfileChanged)="onDeviceProfileChanged($event)"> | 91 | (deviceProfileChanged)="onDeviceProfileChanged($event)"> |
92 | </tb-device-profile-autocomplete> | 92 | </tb-device-profile-autocomplete> |
93 | - <tb-entity-subtype-autocomplete | ||
94 | - formControlName="type" | ||
95 | - [required]="true" | ||
96 | - [entityType]="entityType.DEVICE" | ||
97 | - > | ||
98 | - </tb-entity-subtype-autocomplete> | ||
99 | <mat-form-field class="mat-block"> | 93 | <mat-form-field class="mat-block"> |
100 | <mat-label translate>device.label</mat-label> | 94 | <mat-label translate>device.label</mat-label> |
101 | <input matInput formControlName="label"> | 95 | <input matInput formControlName="label"> |
@@ -80,7 +80,6 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> { | @@ -80,7 +80,6 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> { | ||
80 | { | 80 | { |
81 | name: [entity ? entity.name : '', [Validators.required]], | 81 | name: [entity ? entity.name : '', [Validators.required]], |
82 | deviceProfileId: [entity ? entity.deviceProfileId : null, [Validators.required]], | 82 | deviceProfileId: [entity ? entity.deviceProfileId : null, [Validators.required]], |
83 | - type: [entity ? entity.type : null, [Validators.required]], | ||
84 | label: [entity ? entity.label : ''], | 83 | label: [entity ? entity.label : ''], |
85 | deviceData: [entity ? entity.deviceData : null, [Validators.required]], | 84 | deviceData: [entity ? entity.deviceData : null, [Validators.required]], |
86 | additionalInfo: this.fb.group( | 85 | additionalInfo: this.fb.group( |
@@ -96,7 +95,6 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> { | @@ -96,7 +95,6 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> { | ||
96 | updateForm(entity: DeviceInfo) { | 95 | updateForm(entity: DeviceInfo) { |
97 | this.entityForm.patchValue({name: entity.name}); | 96 | this.entityForm.patchValue({name: entity.name}); |
98 | this.entityForm.patchValue({deviceProfileId: entity.deviceProfileId}); | 97 | this.entityForm.patchValue({deviceProfileId: entity.deviceProfileId}); |
99 | - this.entityForm.patchValue({type: entity.type}); | ||
100 | this.entityForm.patchValue({label: entity.label}); | 98 | this.entityForm.patchValue({label: entity.label}); |
101 | this.entityForm.patchValue({deviceData: entity.deviceData}); | 99 | this.entityForm.patchValue({deviceData: entity.deviceData}); |
102 | this.entityForm.patchValue({additionalInfo: | 100 | this.entityForm.patchValue({additionalInfo: |
@@ -113,7 +113,7 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev | @@ -113,7 +113,7 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev | ||
113 | const routeParams = route.params; | 113 | const routeParams = route.params; |
114 | this.config.componentsData = { | 114 | this.config.componentsData = { |
115 | deviceScope: route.data.devicesType, | 115 | deviceScope: route.data.devicesType, |
116 | - deviceType: '' | 116 | + deviceProfileId: null |
117 | }; | 117 | }; |
118 | this.customerId = routeParams.customerId; | 118 | this.customerId = routeParams.customerId; |
119 | return this.store.pipe(select(selectAuthUser), take(1)).pipe( | 119 | return this.store.pipe(select(selectAuthUser), take(1)).pipe( |
@@ -152,14 +152,13 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev | @@ -152,14 +152,13 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev | ||
152 | configureColumns(deviceScope: string): Array<EntityTableColumn<DeviceInfo>> { | 152 | configureColumns(deviceScope: string): Array<EntityTableColumn<DeviceInfo>> { |
153 | const columns: Array<EntityTableColumn<DeviceInfo>> = [ | 153 | const columns: Array<EntityTableColumn<DeviceInfo>> = [ |
154 | new DateEntityTableColumn<DeviceInfo>('createdTime', 'common.created-time', this.datePipe, '150px'), | 154 | new DateEntityTableColumn<DeviceInfo>('createdTime', 'common.created-time', this.datePipe, '150px'), |
155 | - new EntityTableColumn<DeviceInfo>('name', 'device.name', '20%'), | ||
156 | - new EntityTableColumn<DeviceInfo>('deviceProfileName', 'device-profile.device-profile', '20%'), | ||
157 | - new EntityTableColumn<DeviceInfo>('type', 'device.device-type', '20%'), | ||
158 | - new EntityTableColumn<DeviceInfo>('label', 'device.label', '20%') | 155 | + new EntityTableColumn<DeviceInfo>('name', 'device.name', '25%'), |
156 | + new EntityTableColumn<DeviceInfo>('deviceProfileName', 'device-profile.device-profile', '25%'), | ||
157 | + new EntityTableColumn<DeviceInfo>('label', 'device.label', '25%') | ||
159 | ]; | 158 | ]; |
160 | if (deviceScope === 'tenant') { | 159 | if (deviceScope === 'tenant') { |
161 | columns.push( | 160 | columns.push( |
162 | - new EntityTableColumn<DeviceInfo>('customerTitle', 'customer.customer', '20%'), | 161 | + new EntityTableColumn<DeviceInfo>('customerTitle', 'customer.customer', '25%'), |
163 | new EntityTableColumn<DeviceInfo>('customerIsPublic', 'device.public', '60px', | 162 | new EntityTableColumn<DeviceInfo>('customerIsPublic', 'device.public', '60px', |
164 | entity => { | 163 | entity => { |
165 | return checkBoxCell(entity.customerIsPublic); | 164 | return checkBoxCell(entity.customerIsPublic); |
@@ -178,11 +177,15 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev | @@ -178,11 +177,15 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev | ||
178 | configureEntityFunctions(deviceScope: string): void { | 177 | configureEntityFunctions(deviceScope: string): void { |
179 | if (deviceScope === 'tenant') { | 178 | if (deviceScope === 'tenant') { |
180 | this.config.entitiesFetchFunction = pageLink => | 179 | this.config.entitiesFetchFunction = pageLink => |
181 | - this.deviceService.getTenantDeviceInfos(pageLink, this.config.componentsData.deviceType); | 180 | + this.deviceService.getTenantDeviceInfosByDeviceProfileId(pageLink, |
181 | + this.config.componentsData.deviceProfileId !== null ? | ||
182 | + this.config.componentsData.deviceProfileId.id : ''); | ||
182 | this.config.deleteEntity = id => this.deviceService.deleteDevice(id.id); | 183 | this.config.deleteEntity = id => this.deviceService.deleteDevice(id.id); |
183 | } else { | 184 | } else { |
184 | this.config.entitiesFetchFunction = pageLink => | 185 | this.config.entitiesFetchFunction = pageLink => |
185 | - this.deviceService.getCustomerDeviceInfos(this.customerId, pageLink, this.config.componentsData.deviceType); | 186 | + this.deviceService.getCustomerDeviceInfosByDeviceProfileId(this.customerId, pageLink, |
187 | + this.config.componentsData.deviceProfileId !== null ? | ||
188 | + this.config.componentsData.deviceProfileId.id : ''); | ||
186 | this.config.deleteEntity = id => this.deviceService.unassignDeviceFromCustomer(id.id); | 189 | this.config.deleteEntity = id => this.deviceService.unassignDeviceFromCustomer(id.id); |
187 | } | 190 | } |
188 | } | 191 | } |
@@ -755,6 +755,7 @@ | @@ -755,6 +755,7 @@ | ||
755 | "device-profile": { | 755 | "device-profile": { |
756 | "device-profile": "Device profile", | 756 | "device-profile": "Device profile", |
757 | "device-profiles": "Device profiles", | 757 | "device-profiles": "Device profiles", |
758 | + "all-device-profiles": "All", | ||
758 | "add": "Add device profile", | 759 | "add": "Add device profile", |
759 | "edit": "Edit device profile", | 760 | "edit": "Edit device profile", |
760 | "device-profile-details": "Device profile details", | 761 | "device-profile-details": "Device profile details", |