Commit 5cc3a93cb9b45fd3c65fd7eec1aab1586bdd3194
1 parent
6a237b84
Introduce default dashboard for device profile
Showing
21 changed files
with
108 additions
and
12 deletions
... | ... | @@ -84,7 +84,8 @@ ALTER TABLE dashboard |
84 | 84 | ALTER TABLE device_profile |
85 | 85 | ADD COLUMN IF NOT EXISTS image varchar(1000000), |
86 | 86 | ADD COLUMN IF NOT EXISTS firmware_id uuid, |
87 | - ADD COLUMN IF NOT EXISTS software_id uuid; | |
87 | + ADD COLUMN IF NOT EXISTS software_id uuid, | |
88 | + ADD COLUMN IF NOT EXISTS default_dashboard_id uuid; | |
88 | 89 | |
89 | 90 | ALTER TABLE device |
90 | 91 | ADD COLUMN IF NOT EXISTS firmware_id uuid, |
... | ... | @@ -109,6 +110,12 @@ DO $$ |
109 | 110 | FOREIGN KEY (firmware_id) REFERENCES firmware(id); |
110 | 111 | END IF; |
111 | 112 | |
113 | + IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_default_dashboard_device_profile') THEN | |
114 | + ALTER TABLE device_profile | |
115 | + ADD CONSTRAINT fk_default_dashboard_device_profile | |
116 | + FOREIGN KEY (default_dashboard_id) REFERENCES dashboard(id); | |
117 | + END IF; | |
118 | + | |
112 | 119 | IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_firmware_device') THEN |
113 | 120 | ALTER TABLE device |
114 | 121 | ADD CONSTRAINT fk_firmware_device | ... | ... |
... | ... | @@ -313,7 +313,8 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController |
313 | 313 | Collections.sort(loadedDeviceProfileInfos, deviceProfileInfoIdComparator); |
314 | 314 | |
315 | 315 | List<DeviceProfileInfo> deviceProfileInfos = deviceProfiles.stream().map(deviceProfile -> new DeviceProfileInfo(deviceProfile.getId(), |
316 | - deviceProfile.getName(), deviceProfile.getImage(), deviceProfile.getType(), deviceProfile.getTransportType())).collect(Collectors.toList()); | |
316 | + deviceProfile.getName(), deviceProfile.getImage(), deviceProfile.getDefaultDashboardId(), | |
317 | + deviceProfile.getType(), deviceProfile.getTransportType())).collect(Collectors.toList()); | |
317 | 318 | |
318 | 319 | Assert.assertEquals(deviceProfileInfos, loadedDeviceProfileInfos); |
319 | 320 | ... | ... |
... | ... | @@ -21,6 +21,7 @@ import lombok.Data; |
21 | 21 | import lombok.EqualsAndHashCode; |
22 | 22 | import lombok.extern.slf4j.Slf4j; |
23 | 23 | import org.thingsboard.server.common.data.device.profile.DeviceProfileData; |
24 | +import org.thingsboard.server.common.data.id.DashboardId; | |
24 | 25 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
25 | 26 | import org.thingsboard.server.common.data.id.FirmwareId; |
26 | 27 | import org.thingsboard.server.common.data.id.RuleChainId; |
... | ... | @@ -49,6 +50,7 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H |
49 | 50 | private DeviceTransportType transportType; |
50 | 51 | private DeviceProfileProvisionType provisionType; |
51 | 52 | private RuleChainId defaultRuleChainId; |
53 | + private DashboardId defaultDashboardId; | |
52 | 54 | @NoXss |
53 | 55 | private String defaultQueueName; |
54 | 56 | @Valid |
... | ... | @@ -78,6 +80,7 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H |
78 | 80 | this.image = deviceProfile.getImage(); |
79 | 81 | this.isDefault = deviceProfile.isDefault(); |
80 | 82 | this.defaultRuleChainId = deviceProfile.getDefaultRuleChainId(); |
83 | + this.defaultDashboardId = deviceProfile.getDefaultDashboardId(); | |
81 | 84 | this.defaultQueueName = deviceProfile.getDefaultQueueName(); |
82 | 85 | this.setProfileData(deviceProfile.getProfileData()); |
83 | 86 | this.provisionDeviceKey = deviceProfile.getProvisionDeviceKey(); | ... | ... |
... | ... | @@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; |
20 | 20 | import lombok.EqualsAndHashCode; |
21 | 21 | import lombok.ToString; |
22 | 22 | import lombok.Value; |
23 | +import org.thingsboard.server.common.data.id.DashboardId; | |
23 | 24 | import org.thingsboard.server.common.data.id.EntityId; |
24 | 25 | import org.thingsboard.server.common.data.id.EntityIdFactory; |
25 | 26 | |
... | ... | @@ -31,6 +32,7 @@ import java.util.UUID; |
31 | 32 | public class DeviceProfileInfo extends EntityInfo { |
32 | 33 | |
33 | 34 | private final String image; |
35 | + private final DashboardId defaultDashboardId; | |
34 | 36 | private final DeviceProfileType type; |
35 | 37 | private final DeviceTransportType transportType; |
36 | 38 | |
... | ... | @@ -38,17 +40,20 @@ public class DeviceProfileInfo extends EntityInfo { |
38 | 40 | public DeviceProfileInfo(@JsonProperty("id") EntityId id, |
39 | 41 | @JsonProperty("name") String name, |
40 | 42 | @JsonProperty("image") String image, |
43 | + @JsonProperty("defaultDashboardId") DashboardId defaultDashboardId, | |
41 | 44 | @JsonProperty("type") DeviceProfileType type, |
42 | 45 | @JsonProperty("transportType") DeviceTransportType transportType) { |
43 | 46 | super(id, name); |
44 | 47 | this.image = image; |
48 | + this.defaultDashboardId = defaultDashboardId; | |
45 | 49 | this.type = type; |
46 | 50 | this.transportType = transportType; |
47 | 51 | } |
48 | 52 | |
49 | - public DeviceProfileInfo(UUID uuid, String name, String image, DeviceProfileType type, DeviceTransportType transportType) { | |
53 | + public DeviceProfileInfo(UUID uuid, String name, String image, UUID defaultDashboardId, DeviceProfileType type, DeviceTransportType transportType) { | |
50 | 54 | super(EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE_PROFILE, uuid), name); |
51 | 55 | this.image = image; |
56 | + this.defaultDashboardId = defaultDashboardId != null ? new DashboardId(defaultDashboardId) : null; | |
52 | 57 | this.type = type; |
53 | 58 | this.transportType = transportType; |
54 | 59 | } | ... | ... |
... | ... | @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.dashboard; |
18 | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | 19 | import lombok.extern.slf4j.Slf4j; |
20 | 20 | import org.apache.commons.lang3.StringUtils; |
21 | +import org.hibernate.exception.ConstraintViolationException; | |
21 | 22 | import org.springframework.beans.factory.annotation.Autowired; |
22 | 23 | import org.springframework.context.annotation.Lazy; |
23 | 24 | import org.springframework.stereotype.Service; |
... | ... | @@ -166,7 +167,16 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb |
166 | 167 | log.trace("Executing deleteDashboard [{}]", dashboardId); |
167 | 168 | Validator.validateId(dashboardId, INCORRECT_DASHBOARD_ID + dashboardId); |
168 | 169 | deleteEntityRelations(tenantId, dashboardId); |
169 | - dashboardDao.removeById(tenantId, dashboardId.getId()); | |
170 | + try { | |
171 | + dashboardDao.removeById(tenantId, dashboardId.getId()); | |
172 | + } catch (Exception t) { | |
173 | + ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); | |
174 | + if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_default_dashboard_device_profile")) { | |
175 | + throw new DataValidationException("The dashboard referenced by the device profiles cannot be deleted!"); | |
176 | + } else { | |
177 | + throw t; | |
178 | + } | |
179 | + } | |
170 | 180 | } |
171 | 181 | |
172 | 182 | @Override | ... | ... |
... | ... | @@ -36,6 +36,7 @@ import org.springframework.cache.CacheManager; |
36 | 36 | import org.springframework.cache.annotation.Cacheable; |
37 | 37 | import org.springframework.stereotype.Service; |
38 | 38 | import org.springframework.util.CollectionUtils; |
39 | +import org.thingsboard.server.common.data.DashboardInfo; | |
39 | 40 | import org.thingsboard.server.common.data.Device; |
40 | 41 | import org.thingsboard.server.common.data.DeviceProfile; |
41 | 42 | import org.thingsboard.server.common.data.DeviceProfileInfo; |
... | ... | @@ -61,9 +62,12 @@ import org.thingsboard.server.common.data.id.DeviceProfileId; |
61 | 62 | import org.thingsboard.server.common.data.id.TenantId; |
62 | 63 | import org.thingsboard.server.common.data.page.PageData; |
63 | 64 | import org.thingsboard.server.common.data.page.PageLink; |
65 | +import org.thingsboard.server.common.data.rule.RuleChain; | |
66 | +import org.thingsboard.server.dao.dashboard.DashboardService; | |
64 | 67 | import org.thingsboard.server.dao.entity.AbstractEntityService; |
65 | 68 | import org.thingsboard.server.dao.exception.DataValidationException; |
66 | 69 | import org.thingsboard.server.dao.firmware.FirmwareService; |
70 | +import org.thingsboard.server.dao.rule.RuleChainService; | |
67 | 71 | import org.thingsboard.server.dao.service.DataValidator; |
68 | 72 | import org.thingsboard.server.dao.service.PaginatedRemover; |
69 | 73 | import org.thingsboard.server.dao.service.Validator; |
... | ... | @@ -117,6 +121,12 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
117 | 121 | @Autowired |
118 | 122 | private FirmwareService firmwareService; |
119 | 123 | |
124 | + @Autowired | |
125 | + private RuleChainService ruleChainService; | |
126 | + | |
127 | + @Autowired | |
128 | + private DashboardService dashboardService; | |
129 | + | |
120 | 130 | private final Lock findOrCreateLock = new ReentrantLock(); |
121 | 131 | |
122 | 132 | @Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{#deviceProfileId.id}") |
... | ... | @@ -336,7 +346,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
336 | 346 | } |
337 | 347 | |
338 | 348 | private DataValidator<DeviceProfile> deviceProfileValidator = |
339 | - new DataValidator<DeviceProfile>() { | |
349 | + new DataValidator<>() { | |
340 | 350 | @Override |
341 | 351 | protected void validateDataImpl(TenantId tenantId, DeviceProfile deviceProfile) { |
342 | 352 | if (StringUtils.isEmpty(deviceProfile.getName())) { |
... | ... | @@ -402,6 +412,20 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
402 | 412 | } |
403 | 413 | } |
404 | 414 | |
415 | + if (deviceProfile.getDefaultRuleChainId() != null) { | |
416 | + RuleChain ruleChain = ruleChainService.findRuleChainById(tenantId, deviceProfile.getDefaultRuleChainId()); | |
417 | + if (ruleChain == null) { | |
418 | + throw new DataValidationException("Can't assign non-existent rule chain!"); | |
419 | + } | |
420 | + } | |
421 | + | |
422 | + if (deviceProfile.getDefaultDashboardId() != null) { | |
423 | + DashboardInfo dashboard = dashboardService.findDashboardInfoById(tenantId, deviceProfile.getDefaultDashboardId()); | |
424 | + if (dashboard == null) { | |
425 | + throw new DataValidationException("Can't assign non-existent dashboard!"); | |
426 | + } | |
427 | + } | |
428 | + | |
405 | 429 | if (deviceProfile.getFirmwareId() != null) { |
406 | 430 | Firmware firmware = firmwareService.findFirmwareById(tenantId, deviceProfile.getFirmwareId()); |
407 | 431 | if (firmware == null) { | ... | ... |
... | ... | @@ -177,6 +177,7 @@ public class ModelConstants { |
177 | 177 | public static final String DEVICE_PROFILE_DESCRIPTION_PROPERTY = "description"; |
178 | 178 | public static final String DEVICE_PROFILE_IS_DEFAULT_PROPERTY = "is_default"; |
179 | 179 | public static final String DEVICE_PROFILE_DEFAULT_RULE_CHAIN_ID_PROPERTY = "default_rule_chain_id"; |
180 | + public static final String DEVICE_PROFILE_DEFAULT_DASHBOARD_ID_PROPERTY = "default_dashboard_id"; | |
180 | 181 | public static final String DEVICE_PROFILE_DEFAULT_QUEUE_NAME_PROPERTY = "default_queue_name"; |
181 | 182 | public static final String DEVICE_PROFILE_PROVISION_DEVICE_KEY = "provision_device_key"; |
182 | 183 | public static final String DEVICE_PROFILE_FIRMWARE_ID_PROPERTY = "firmware_id"; | ... | ... |
... | ... | @@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.DeviceProfileProvisionType; |
27 | 27 | import org.thingsboard.server.common.data.DeviceProfileType; |
28 | 28 | import org.thingsboard.server.common.data.DeviceTransportType; |
29 | 29 | import org.thingsboard.server.common.data.device.profile.DeviceProfileData; |
30 | +import org.thingsboard.server.common.data.id.DashboardId; | |
30 | 31 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
31 | 32 | import org.thingsboard.server.common.data.id.FirmwareId; |
32 | 33 | import org.thingsboard.server.common.data.id.RuleChainId; |
... | ... | @@ -83,6 +84,9 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl |
83 | 84 | @Column(name = ModelConstants.DEVICE_PROFILE_DEFAULT_RULE_CHAIN_ID_PROPERTY, columnDefinition = "uuid") |
84 | 85 | private UUID defaultRuleChainId; |
85 | 86 | |
87 | + @Column(name = ModelConstants.DEVICE_PROFILE_DEFAULT_DASHBOARD_ID_PROPERTY) | |
88 | + private UUID defaultDashboardId; | |
89 | + | |
86 | 90 | @Column(name = ModelConstants.DEVICE_PROFILE_DEFAULT_QUEUE_NAME_PROPERTY) |
87 | 91 | private String defaultQueueName; |
88 | 92 | |
... | ... | @@ -122,6 +126,9 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl |
122 | 126 | if (deviceProfile.getDefaultRuleChainId() != null) { |
123 | 127 | this.defaultRuleChainId = deviceProfile.getDefaultRuleChainId().getId(); |
124 | 128 | } |
129 | + if (deviceProfile.getDefaultDashboardId() != null) { | |
130 | + this.defaultDashboardId = deviceProfile.getDefaultDashboardId().getId(); | |
131 | + } | |
125 | 132 | this.defaultQueueName = deviceProfile.getDefaultQueueName(); |
126 | 133 | this.provisionDeviceKey = deviceProfile.getProvisionDeviceKey(); |
127 | 134 | if (deviceProfile.getFirmwareId() != null) { |
... | ... | @@ -164,6 +171,9 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl |
164 | 171 | if (defaultRuleChainId != null) { |
165 | 172 | deviceProfile.setDefaultRuleChainId(new RuleChainId(defaultRuleChainId)); |
166 | 173 | } |
174 | + if (defaultDashboardId != null) { | |
175 | + deviceProfile.setDefaultDashboardId(new DashboardId(defaultDashboardId)); | |
176 | + } | |
167 | 177 | deviceProfile.setDefaultQueueName(defaultQueueName); |
168 | 178 | deviceProfile.setProvisionDeviceKey(provisionDeviceKey); |
169 | 179 | ... | ... |
... | ... | @@ -28,7 +28,7 @@ import java.util.UUID; |
28 | 28 | |
29 | 29 | public interface DeviceProfileRepository extends PagingAndSortingRepository<DeviceProfileEntity, UUID> { |
30 | 30 | |
31 | - @Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.name, d.image, d.type, d.transportType) " + | |
31 | + @Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.name, d.image, d.defaultDashboardId, d.type, d.transportType) " + | |
32 | 32 | "FROM DeviceProfileEntity d " + |
33 | 33 | "WHERE d.id = :deviceProfileId") |
34 | 34 | DeviceProfileInfo findDeviceProfileInfoById(@Param("deviceProfileId") UUID deviceProfileId); |
... | ... | @@ -39,14 +39,14 @@ public interface DeviceProfileRepository extends PagingAndSortingRepository<Devi |
39 | 39 | @Param("textSearch") String textSearch, |
40 | 40 | Pageable pageable); |
41 | 41 | |
42 | - @Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.name, d.image, d.type, d.transportType) " + | |
42 | + @Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.name, d.image, d.defaultDashboardId, d.type, d.transportType) " + | |
43 | 43 | "FROM DeviceProfileEntity d WHERE " + |
44 | 44 | "d.tenantId = :tenantId AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") |
45 | 45 | Page<DeviceProfileInfo> findDeviceProfileInfos(@Param("tenantId") UUID tenantId, |
46 | 46 | @Param("textSearch") String textSearch, |
47 | 47 | Pageable pageable); |
48 | 48 | |
49 | - @Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.name, d.image, d.type, d.transportType) " + | |
49 | + @Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.name, d.image, d.defaultDashboardId, d.type, d.transportType) " + | |
50 | 50 | "FROM DeviceProfileEntity d WHERE " + |
51 | 51 | "d.tenantId = :tenantId AND d.transportType = :transportType AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") |
52 | 52 | Page<DeviceProfileInfo> findDeviceProfileInfos(@Param("tenantId") UUID tenantId, |
... | ... | @@ -58,7 +58,7 @@ public interface DeviceProfileRepository extends PagingAndSortingRepository<Devi |
58 | 58 | "WHERE d.tenantId = :tenantId AND d.isDefault = true") |
59 | 59 | DeviceProfileEntity findByDefaultTrueAndTenantId(@Param("tenantId") UUID tenantId); |
60 | 60 | |
61 | - @Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.name, d.image, d.type, d.transportType) " + | |
61 | + @Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.name, d.image, d.defaultDashboardId, d.type, d.transportType) " + | |
62 | 62 | "FROM DeviceProfileEntity d " + |
63 | 63 | "WHERE d.tenantId = :tenantId AND d.isDefault = true") |
64 | 64 | DeviceProfileInfo findDefaultDeviceProfileInfo(@Param("tenantId") UUID tenantId); | ... | ... |
... | ... | @@ -87,7 +87,9 @@ public class AlarmDataAdapter { |
87 | 87 | alarm.setSeverity(AlarmSeverity.valueOf(row.get(ModelConstants.ALARM_SEVERITY_PROPERTY).toString())); |
88 | 88 | alarm.setStatus(AlarmStatus.valueOf(row.get(ModelConstants.ALARM_STATUS_PROPERTY).toString())); |
89 | 89 | alarm.setTenantId(new TenantId((UUID) row.get(ModelConstants.TENANT_ID_PROPERTY))); |
90 | - alarm.setCustomerId(new CustomerId((UUID) row.get(ModelConstants.CUSTOMER_ID_PROPERTY))); | |
90 | + Object customerIdObj = row.get(ModelConstants.CUSTOMER_ID_PROPERTY); | |
91 | + CustomerId customerId = customerIdObj != null ? new CustomerId((UUID) customerIdObj) : null; | |
92 | + alarm.setCustomerId(customerId); | |
91 | 93 | if (row.get(ModelConstants.ALARM_PROPAGATE_RELATION_TYPES) != null) { |
92 | 94 | String propagateRelationTypes = row.get(ModelConstants.ALARM_PROPAGATE_RELATION_TYPES).toString(); |
93 | 95 | if (!StringUtils.isEmpty(propagateRelationTypes)) { | ... | ... |
... | ... | @@ -140,11 +140,11 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe |
140 | 140 | Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
141 | 141 | customerService.deleteCustomersByTenantId(tenantId); |
142 | 142 | widgetsBundleService.deleteWidgetsBundlesByTenantId(tenantId); |
143 | - dashboardService.deleteDashboardsByTenantId(tenantId); | |
144 | 143 | entityViewService.deleteEntityViewsByTenantId(tenantId); |
145 | 144 | assetService.deleteAssetsByTenantId(tenantId); |
146 | 145 | deviceService.deleteDevicesByTenantId(tenantId); |
147 | 146 | deviceProfileService.deleteDeviceProfilesByTenantId(tenantId); |
147 | + dashboardService.deleteDashboardsByTenantId(tenantId); | |
148 | 148 | edgeService.deleteEdgesByTenantId(tenantId); |
149 | 149 | userService.deleteTenantAdmins(tenantId); |
150 | 150 | ruleChainService.deleteRuleChainsByTenantId(tenantId); | ... | ... |
... | ... | @@ -195,11 +195,13 @@ CREATE TABLE IF NOT EXISTS device_profile ( |
195 | 195 | firmware_id uuid, |
196 | 196 | software_id uuid, |
197 | 197 | default_rule_chain_id uuid, |
198 | + default_dashboard_id uuid, | |
198 | 199 | default_queue_name varchar(255), |
199 | 200 | provision_device_key varchar, |
200 | 201 | CONSTRAINT device_profile_name_unq_key UNIQUE (tenant_id, name), |
201 | 202 | CONSTRAINT device_provision_key_unq_key UNIQUE (provision_device_key), |
202 | 203 | CONSTRAINT fk_default_rule_chain_device_profile FOREIGN KEY (default_rule_chain_id) REFERENCES rule_chain(id), |
204 | + CONSTRAINT fk_default_dashboard_device_profile FOREIGN KEY (default_dashboard_id) REFERENCES dashboard(id), | |
203 | 205 | CONSTRAINT fk_firmware_device_profile FOREIGN KEY (firmware_id) REFERENCES firmware(id), |
204 | 206 | CONSTRAINT fk_software_device_profile FOREIGN KEY (software_id) REFERENCES firmware(id) |
205 | 207 | ); | ... | ... |
... | ... | @@ -214,11 +214,13 @@ CREATE TABLE IF NOT EXISTS device_profile ( |
214 | 214 | firmware_id uuid, |
215 | 215 | software_id uuid, |
216 | 216 | default_rule_chain_id uuid, |
217 | + default_dashboard_id uuid, | |
217 | 218 | default_queue_name varchar(255), |
218 | 219 | provision_device_key varchar, |
219 | 220 | CONSTRAINT device_profile_name_unq_key UNIQUE (tenant_id, name), |
220 | 221 | CONSTRAINT device_provision_key_unq_key UNIQUE (provision_device_key), |
221 | 222 | CONSTRAINT fk_default_rule_chain_device_profile FOREIGN KEY (default_rule_chain_id) REFERENCES rule_chain(id), |
223 | + CONSTRAINT fk_default_dashboard_device_profile FOREIGN KEY (default_dashboard_id) REFERENCES dashboard(id), | |
222 | 224 | CONSTRAINT fk_firmware_device_profile FOREIGN KEY (firmware_id) REFERENCES firmware(id), |
223 | 225 | CONSTRAINT fk_software_device_profile FOREIGN KEY (software_id) REFERENCES firmware(id) |
224 | 226 | ); | ... | ... |
... | ... | @@ -333,7 +333,8 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest { |
333 | 333 | |
334 | 334 | List<DeviceProfileInfo> deviceProfileInfos = deviceProfiles.stream() |
335 | 335 | .map(deviceProfile -> new DeviceProfileInfo(deviceProfile.getId(), |
336 | - deviceProfile.getName(), deviceProfile.getImage(), deviceProfile.getType(), deviceProfile.getTransportType())).collect(Collectors.toList()); | |
336 | + deviceProfile.getName(), deviceProfile.getImage(), deviceProfile.getDefaultDashboardId(), | |
337 | + deviceProfile.getType(), deviceProfile.getTransportType())).collect(Collectors.toList()); | |
337 | 338 | |
338 | 339 | Assert.assertEquals(deviceProfileInfos, loadedDeviceProfileInfos); |
339 | 340 | ... | ... |
... | ... | @@ -45,6 +45,10 @@ |
45 | 45 | labelText="device-profile.default-rule-chain" |
46 | 46 | formControlName="defaultRuleChainId"> |
47 | 47 | </tb-rule-chain-autocomplete> |
48 | + <tb-dashboard-autocomplete | |
49 | + placeholder="{{'device-profile.default-dashboard' | translate}}" | |
50 | + formControlName="defaultDashboardId"> | |
51 | + </tb-dashboard-autocomplete> | |
48 | 52 | <tb-queue-type-list |
49 | 53 | [queueType]="serviceType" |
50 | 54 | formControlName="defaultQueueName"> | ... | ... |
... | ... | @@ -49,6 +49,7 @@ import { RuleChainId } from '@shared/models/id/rule-chain-id'; |
49 | 49 | import { StepperSelectionEvent } from '@angular/cdk/stepper'; |
50 | 50 | import { deepTrim } from '@core/utils'; |
51 | 51 | import { ServiceType } from '@shared/models/queue.models'; |
52 | +import { DashboardId } from '@shared/models/id/dashboard-id'; | |
52 | 53 | |
53 | 54 | export interface AddDeviceProfileDialogData { |
54 | 55 | deviceProfileName: string; |
... | ... | @@ -108,6 +109,7 @@ export class AddDeviceProfileDialogComponent extends |
108 | 109 | type: [DeviceProfileType.DEFAULT, [Validators.required]], |
109 | 110 | image: [null, []], |
110 | 111 | defaultRuleChainId: [null, []], |
112 | + defaultDashboardId: [null, []], | |
111 | 113 | defaultQueueName: ['', []], |
112 | 114 | description: ['', []] |
113 | 115 | } |
... | ... | @@ -199,6 +201,9 @@ export class AddDeviceProfileDialogComponent extends |
199 | 201 | if (this.deviceProfileDetailsFormGroup.get('defaultRuleChainId').value) { |
200 | 202 | deviceProfile.defaultRuleChainId = new RuleChainId(this.deviceProfileDetailsFormGroup.get('defaultRuleChainId').value); |
201 | 203 | } |
204 | + if (this.deviceProfileDetailsFormGroup.get('defaultDashboardId').value) { | |
205 | + deviceProfile.defaultDashboardId = new DashboardId(this.deviceProfileDetailsFormGroup.get('defaultDashboardId').value); | |
206 | + } | |
202 | 207 | this.deviceProfileService.saveDeviceProfile(deepTrim(deviceProfile)).subscribe( |
203 | 208 | (savedDeviceProfile) => { |
204 | 209 | this.dialogRef.close(savedDeviceProfile); | ... | ... |
... | ... | @@ -59,6 +59,10 @@ |
59 | 59 | labelText="device-profile.default-rule-chain" |
60 | 60 | formControlName="defaultRuleChainId"> |
61 | 61 | </tb-rule-chain-autocomplete> |
62 | + <tb-dashboard-autocomplete | |
63 | + placeholder="{{'device-profile.default-dashboard' | translate}}" | |
64 | + formControlName="defaultDashboardId"> | |
65 | + </tb-dashboard-autocomplete> | |
62 | 66 | <tb-queue-type-list |
63 | 67 | [queueType]="serviceType" |
64 | 68 | formControlName="defaultQueueName"> | ... | ... |
... | ... | @@ -41,6 +41,7 @@ import { RuleChainId } from '@shared/models/id/rule-chain-id'; |
41 | 41 | import { ServiceType } from '@shared/models/queue.models'; |
42 | 42 | import { EntityId } from '@shared/models/id/entity-id'; |
43 | 43 | import { FirmwareType } from '@shared/models/firmware.models'; |
44 | +import { DashboardId } from '@shared/models/id/dashboard-id'; | |
44 | 45 | |
45 | 46 | @Component({ |
46 | 47 | selector: 'tb-device-profile', |
... | ... | @@ -112,6 +113,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> { |
112 | 113 | provisionConfiguration: [deviceProvisionConfiguration, Validators.required] |
113 | 114 | }), |
114 | 115 | defaultRuleChainId: [entity && entity.defaultRuleChainId ? entity.defaultRuleChainId.id : null, []], |
116 | + defaultDashboardId: [entity && entity.defaultDashboardId ? entity.defaultDashboardId.id : null, []], | |
115 | 117 | defaultQueueName: [entity ? entity.defaultQueueName : '', []], |
116 | 118 | firmwareId: [entity ? entity.firmwareId : null], |
117 | 119 | softwareId: [entity ? entity.softwareId : null], |
... | ... | @@ -190,6 +192,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> { |
190 | 192 | provisionConfiguration: deviceProvisionConfiguration |
191 | 193 | }}, {emitEvent: false}); |
192 | 194 | this.entityForm.patchValue({defaultRuleChainId: entity.defaultRuleChainId ? entity.defaultRuleChainId.id : null}, {emitEvent: false}); |
195 | + this.entityForm.patchValue({defaultDashboardId: entity.defaultDashboardId ? entity.defaultDashboardId.id : null}, {emitEvent: false}); | |
193 | 196 | this.entityForm.patchValue({defaultQueueName: entity.defaultQueueName}, {emitEvent: false}); |
194 | 197 | this.entityForm.patchValue({firmwareId: entity.firmwareId}, {emitEvent: false}); |
195 | 198 | this.entityForm.patchValue({softwareId: entity.softwareId}, {emitEvent: false}); |
... | ... | @@ -200,6 +203,9 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> { |
200 | 203 | if (formValue.defaultRuleChainId) { |
201 | 204 | formValue.defaultRuleChainId = new RuleChainId(formValue.defaultRuleChainId); |
202 | 205 | } |
206 | + if (formValue.defaultDashboardId) { | |
207 | + formValue.defaultDashboardId = new DashboardId(formValue.defaultDashboardId); | |
208 | + } | |
203 | 209 | const deviceProvisionConfiguration: DeviceProvisionConfiguration = formValue.profileData.provisionConfiguration; |
204 | 210 | formValue.provisionType = deviceProvisionConfiguration.type; |
205 | 211 | formValue.provisionDeviceKey = deviceProvisionConfiguration.provisionDeviceKey; | ... | ... |
... | ... | @@ -139,6 +139,11 @@ export class DashboardAutocompleteComponent implements ControlValueAccessor, OnI |
139 | 139 | |
140 | 140 | setDisabledState(isDisabled: boolean): void { |
141 | 141 | this.disabled = isDisabled; |
142 | + if (this.disabled) { | |
143 | + this.selectDashboardFormGroup.disable({emitEvent: false}); | |
144 | + } else { | |
145 | + this.selectDashboardFormGroup.enable({emitEvent: false}); | |
146 | + } | |
142 | 147 | } |
143 | 148 | |
144 | 149 | writeValue(value: DashboardInfo | string | null): void { | ... | ... |
... | ... | @@ -28,6 +28,7 @@ import { TimeUnit } from '@shared/models/time/time.models'; |
28 | 28 | import * as _moment from 'moment'; |
29 | 29 | import { AbstractControl, ValidationErrors } from '@angular/forms'; |
30 | 30 | import { FirmwareId } from '@shared/models/id/firmware-id'; |
31 | +import { DashboardId } from '@shared/models/id/dashboard-id'; | |
31 | 32 | |
32 | 33 | export enum DeviceProfileType { |
33 | 34 | DEFAULT = 'DEFAULT', |
... | ... | @@ -497,6 +498,7 @@ export interface DeviceProfile extends BaseData<DeviceProfileId> { |
497 | 498 | provisionType: DeviceProvisionType; |
498 | 499 | provisionDeviceKey?: string; |
499 | 500 | defaultRuleChainId?: RuleChainId; |
501 | + defaultDashboardId?: DashboardId; | |
500 | 502 | defaultQueueName?: string; |
501 | 503 | firmwareId?: FirmwareId; |
502 | 504 | softwareId?: FirmwareId; |
... | ... | @@ -507,6 +509,7 @@ export interface DeviceProfileInfo extends EntityInfoData { |
507 | 509 | type: DeviceProfileType; |
508 | 510 | transportType: DeviceTransportType; |
509 | 511 | image?: string; |
512 | + defaultDashboardId?: DashboardId; | |
510 | 513 | } |
511 | 514 | |
512 | 515 | export interface DefaultDeviceConfiguration { | ... | ... |
... | ... | @@ -1048,6 +1048,7 @@ |
1048 | 1048 | "profile-configuration": "Profile configuration", |
1049 | 1049 | "transport-configuration": "Transport configuration", |
1050 | 1050 | "default-rule-chain": "Default rule chain", |
1051 | + "default-dashboard": "Default dashboard", | |
1051 | 1052 | "select-queue-hint": "Select from a drop-down list or add a custom name.", |
1052 | 1053 | "delete-device-profile-title": "Are you sure you want to delete the device profile '{{deviceProfileName}}'?", |
1053 | 1054 | "delete-device-profile-text": "Be careful, after the confirmation the device profile and all related data will become unrecoverable.", | ... | ... |