Commit d5b640d6021d4a3b57ae1b70cb1706084809a0af
1 parent
89c1743f
Add image fields for dashboard and device profile entities. Introduce getAllAlar…
…ms and getCustomerAlarms API
Showing
31 changed files
with
257 additions
and
32 deletions
@@ -78,7 +78,11 @@ CREATE TABLE IF NOT EXISTS firmware ( | @@ -78,7 +78,11 @@ CREATE TABLE IF NOT EXISTS firmware ( | ||
78 | CONSTRAINT firmware_tenant_title_version_unq_key UNIQUE (tenant_id, title, version) | 78 | CONSTRAINT firmware_tenant_title_version_unq_key UNIQUE (tenant_id, title, version) |
79 | ); | 79 | ); |
80 | 80 | ||
81 | +ALTER TABLE dashboard | ||
82 | + ADD COLUMN IF NOT EXISTS image varchar(1000000); | ||
83 | + | ||
81 | ALTER TABLE device_profile | 84 | ALTER TABLE device_profile |
85 | + ADD COLUMN IF NOT EXISTS image varchar(1000000), | ||
82 | ADD COLUMN IF NOT EXISTS firmware_id uuid, | 86 | ADD COLUMN IF NOT EXISTS firmware_id uuid, |
83 | ADD COLUMN IF NOT EXISTS software_id uuid; | 87 | ADD COLUMN IF NOT EXISTS software_id uuid; |
84 | 88 |
@@ -197,6 +197,41 @@ public class AlarmController extends BaseController { | @@ -197,6 +197,41 @@ public class AlarmController extends BaseController { | ||
197 | } | 197 | } |
198 | 198 | ||
199 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 199 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
200 | + @RequestMapping(value = "/alarms", method = RequestMethod.GET) | ||
201 | + @ResponseBody | ||
202 | + public PageData<AlarmInfo> getAllAlarms( | ||
203 | + @RequestParam(required = false) String searchStatus, | ||
204 | + @RequestParam(required = false) String status, | ||
205 | + @RequestParam int pageSize, | ||
206 | + @RequestParam int page, | ||
207 | + @RequestParam(required = false) String textSearch, | ||
208 | + @RequestParam(required = false) String sortProperty, | ||
209 | + @RequestParam(required = false) String sortOrder, | ||
210 | + @RequestParam(required = false) Long startTime, | ||
211 | + @RequestParam(required = false) Long endTime, | ||
212 | + @RequestParam(required = false) Boolean fetchOriginator | ||
213 | + ) throws ThingsboardException { | ||
214 | + accessControlService.checkPermission(getCurrentUser(), Resource.ALARM, Operation.READ); | ||
215 | + AlarmSearchStatus alarmSearchStatus = StringUtils.isEmpty(searchStatus) ? null : AlarmSearchStatus.valueOf(searchStatus); | ||
216 | + AlarmStatus alarmStatus = StringUtils.isEmpty(status) ? null : AlarmStatus.valueOf(status); | ||
217 | + if (alarmSearchStatus != null && alarmStatus != null) { | ||
218 | + throw new ThingsboardException("Invalid alarms search query: Both parameters 'searchStatus' " + | ||
219 | + "and 'status' can't be specified at the same time!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); | ||
220 | + } | ||
221 | + TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); | ||
222 | + | ||
223 | + try { | ||
224 | + if (getCurrentUser().isCustomerUser()) { | ||
225 | + return checkNotNull(alarmService.findCustomerAlarms(getCurrentUser().getTenantId(), getCurrentUser().getCustomerId(), new AlarmQuery(null, pageLink, alarmSearchStatus, alarmStatus, fetchOriginator)).get()); | ||
226 | + } else { | ||
227 | + return checkNotNull(alarmService.findAlarms(getCurrentUser().getTenantId(), new AlarmQuery(null, pageLink, alarmSearchStatus, alarmStatus, fetchOriginator)).get()); | ||
228 | + } | ||
229 | + } catch (Exception e) { | ||
230 | + throw handleException(e); | ||
231 | + } | ||
232 | + } | ||
233 | + | ||
234 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | ||
200 | @RequestMapping(value = "/alarm/highestSeverity/{entityType}/{entityId}", method = RequestMethod.GET) | 235 | @RequestMapping(value = "/alarm/highestSeverity/{entityType}/{entityId}", method = RequestMethod.GET) |
201 | @ResponseBody | 236 | @ResponseBody |
202 | public AlarmSeverity getHighestAlarmSeverity( | 237 | public AlarmSeverity getHighestAlarmSeverity( |
@@ -128,6 +128,11 @@ public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService | @@ -128,6 +128,11 @@ public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService | ||
128 | } | 128 | } |
129 | 129 | ||
130 | @Override | 130 | @Override |
131 | + public ListenableFuture<PageData<AlarmInfo>> findCustomerAlarms(TenantId tenantId, CustomerId customerId, AlarmQuery query) { | ||
132 | + return alarmService.findCustomerAlarms(tenantId, customerId, query); | ||
133 | + } | ||
134 | + | ||
135 | + @Override | ||
131 | public AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, AlarmStatus alarmStatus) { | 136 | public AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, AlarmStatus alarmStatus) { |
132 | return alarmService.findHighestAlarmSeverity(tenantId, entityId, alarmSearchStatus, alarmStatus); | 137 | return alarmService.findHighestAlarmSeverity(tenantId, entityId, alarmSearchStatus, alarmStatus); |
133 | } | 138 | } |
@@ -313,7 +313,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | @@ -313,7 +313,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | ||
313 | Collections.sort(loadedDeviceProfileInfos, deviceProfileInfoIdComparator); | 313 | Collections.sort(loadedDeviceProfileInfos, deviceProfileInfoIdComparator); |
314 | 314 | ||
315 | List<DeviceProfileInfo> deviceProfileInfos = deviceProfiles.stream().map(deviceProfile -> new DeviceProfileInfo(deviceProfile.getId(), | 315 | List<DeviceProfileInfo> deviceProfileInfos = deviceProfiles.stream().map(deviceProfile -> new DeviceProfileInfo(deviceProfile.getId(), |
316 | - deviceProfile.getName(), deviceProfile.getType(), deviceProfile.getTransportType())).collect(Collectors.toList()); | 316 | + deviceProfile.getName(), deviceProfile.getImage(), deviceProfile.getType(), deviceProfile.getTransportType())).collect(Collectors.toList()); |
317 | 317 | ||
318 | Assert.assertEquals(deviceProfileInfos, loadedDeviceProfileInfos); | 318 | Assert.assertEquals(deviceProfileInfos, loadedDeviceProfileInfos); |
319 | 319 |
@@ -53,6 +53,8 @@ public interface AlarmService { | @@ -53,6 +53,8 @@ public interface AlarmService { | ||
53 | 53 | ||
54 | ListenableFuture<PageData<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query); | 54 | ListenableFuture<PageData<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query); |
55 | 55 | ||
56 | + ListenableFuture<PageData<AlarmInfo>> findCustomerAlarms(TenantId tenantId, CustomerId customerId, AlarmQuery query); | ||
57 | + | ||
56 | AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, | 58 | AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, |
57 | AlarmStatus alarmStatus); | 59 | AlarmStatus alarmStatus); |
58 | 60 |
@@ -30,6 +30,7 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa | @@ -30,6 +30,7 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa | ||
30 | private TenantId tenantId; | 30 | private TenantId tenantId; |
31 | @NoXss | 31 | @NoXss |
32 | private String title; | 32 | private String title; |
33 | + private String image; | ||
33 | @Valid | 34 | @Valid |
34 | private Set<ShortCustomerInfo> assignedCustomers; | 35 | private Set<ShortCustomerInfo> assignedCustomers; |
35 | 36 | ||
@@ -45,6 +46,7 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa | @@ -45,6 +46,7 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa | ||
45 | super(dashboardInfo); | 46 | super(dashboardInfo); |
46 | this.tenantId = dashboardInfo.getTenantId(); | 47 | this.tenantId = dashboardInfo.getTenantId(); |
47 | this.title = dashboardInfo.getTitle(); | 48 | this.title = dashboardInfo.getTitle(); |
49 | + this.image = dashboardInfo.getImage(); | ||
48 | this.assignedCustomers = dashboardInfo.getAssignedCustomers(); | 50 | this.assignedCustomers = dashboardInfo.getAssignedCustomers(); |
49 | } | 51 | } |
50 | 52 | ||
@@ -64,6 +66,14 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa | @@ -64,6 +66,14 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa | ||
64 | this.title = title; | 66 | this.title = title; |
65 | } | 67 | } |
66 | 68 | ||
69 | + public String getImage() { | ||
70 | + return image; | ||
71 | + } | ||
72 | + | ||
73 | + public void setImage(String image) { | ||
74 | + this.image = image; | ||
75 | + } | ||
76 | + | ||
67 | public Set<ShortCustomerInfo> getAssignedCustomers() { | 77 | public Set<ShortCustomerInfo> getAssignedCustomers() { |
68 | return assignedCustomers; | 78 | return assignedCustomers; |
69 | } | 79 | } |
@@ -43,6 +43,7 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H | @@ -43,6 +43,7 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H | ||
43 | private String name; | 43 | private String name; |
44 | @NoXss | 44 | @NoXss |
45 | private String description; | 45 | private String description; |
46 | + private String image; | ||
46 | private boolean isDefault; | 47 | private boolean isDefault; |
47 | private DeviceProfileType type; | 48 | private DeviceProfileType type; |
48 | private DeviceTransportType transportType; | 49 | private DeviceTransportType transportType; |
@@ -74,6 +75,7 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H | @@ -74,6 +75,7 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H | ||
74 | this.tenantId = deviceProfile.getTenantId(); | 75 | this.tenantId = deviceProfile.getTenantId(); |
75 | this.name = deviceProfile.getName(); | 76 | this.name = deviceProfile.getName(); |
76 | this.description = deviceProfile.getDescription(); | 77 | this.description = deviceProfile.getDescription(); |
78 | + this.image = deviceProfile.getImage(); | ||
77 | this.isDefault = deviceProfile.isDefault(); | 79 | this.isDefault = deviceProfile.isDefault(); |
78 | this.defaultRuleChainId = deviceProfile.getDefaultRuleChainId(); | 80 | this.defaultRuleChainId = deviceProfile.getDefaultRuleChainId(); |
79 | this.defaultQueueName = deviceProfile.getDefaultQueueName(); | 81 | this.defaultQueueName = deviceProfile.getDefaultQueueName(); |
@@ -30,21 +30,25 @@ import java.util.UUID; | @@ -30,21 +30,25 @@ import java.util.UUID; | ||
30 | @ToString(callSuper = true) | 30 | @ToString(callSuper = true) |
31 | public class DeviceProfileInfo extends EntityInfo { | 31 | public class DeviceProfileInfo extends EntityInfo { |
32 | 32 | ||
33 | + private final String image; | ||
33 | private final DeviceProfileType type; | 34 | private final DeviceProfileType type; |
34 | private final DeviceTransportType transportType; | 35 | private final DeviceTransportType transportType; |
35 | 36 | ||
36 | @JsonCreator | 37 | @JsonCreator |
37 | public DeviceProfileInfo(@JsonProperty("id") EntityId id, | 38 | public DeviceProfileInfo(@JsonProperty("id") EntityId id, |
38 | @JsonProperty("name") String name, | 39 | @JsonProperty("name") String name, |
40 | + @JsonProperty("image") String image, | ||
39 | @JsonProperty("type") DeviceProfileType type, | 41 | @JsonProperty("type") DeviceProfileType type, |
40 | @JsonProperty("transportType") DeviceTransportType transportType) { | 42 | @JsonProperty("transportType") DeviceTransportType transportType) { |
41 | super(id, name); | 43 | super(id, name); |
44 | + this.image = image; | ||
42 | this.type = type; | 45 | this.type = type; |
43 | this.transportType = transportType; | 46 | this.transportType = transportType; |
44 | } | 47 | } |
45 | 48 | ||
46 | - public DeviceProfileInfo(UUID uuid, String name, DeviceProfileType type, DeviceTransportType transportType) { | 49 | + public DeviceProfileInfo(UUID uuid, String name, String image, DeviceProfileType type, DeviceTransportType transportType) { |
47 | super(EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE_PROFILE, uuid), name); | 50 | super(EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE_PROFILE, uuid), name); |
51 | + this.image = image; | ||
48 | this.type = type; | 52 | this.type = type; |
49 | this.transportType = transportType; | 53 | this.transportType = transportType; |
50 | } | 54 | } |
@@ -48,6 +48,8 @@ public interface AlarmDao extends Dao<Alarm> { | @@ -48,6 +48,8 @@ public interface AlarmDao extends Dao<Alarm> { | ||
48 | 48 | ||
49 | PageData<AlarmInfo> findAlarms(TenantId tenantId, AlarmQuery query); | 49 | PageData<AlarmInfo> findAlarms(TenantId tenantId, AlarmQuery query); |
50 | 50 | ||
51 | + PageData<AlarmInfo> findCustomerAlarms(TenantId tenantId, CustomerId customerId, AlarmQuery query); | ||
52 | + | ||
51 | PageData<AlarmData> findAlarmDataByQueryForEntities(TenantId tenantId, CustomerId customerId, | 53 | PageData<AlarmData> findAlarmDataByQueryForEntities(TenantId tenantId, CustomerId customerId, |
52 | AlarmDataQuery query, Collection<EntityId> orderedEntityIds); | 54 | AlarmDataQuery query, Collection<EntityId> orderedEntityIds); |
53 | 55 |
@@ -292,26 +292,39 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | @@ -292,26 +292,39 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | ||
292 | public ListenableFuture<PageData<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query) { | 292 | public ListenableFuture<PageData<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query) { |
293 | PageData<AlarmInfo> alarms = alarmDao.findAlarms(tenantId, query); | 293 | PageData<AlarmInfo> alarms = alarmDao.findAlarms(tenantId, query); |
294 | if (query.getFetchOriginator() != null && query.getFetchOriginator().booleanValue()) { | 294 | if (query.getFetchOriginator() != null && query.getFetchOriginator().booleanValue()) { |
295 | - List<ListenableFuture<AlarmInfo>> alarmFutures = new ArrayList<>(alarms.getData().size()); | ||
296 | - for (AlarmInfo alarmInfo : alarms.getData()) { | ||
297 | - alarmFutures.add(Futures.transform( | ||
298 | - entityService.fetchEntityNameAsync(tenantId, alarmInfo.getOriginator()), originatorName -> { | ||
299 | - if (originatorName == null) { | ||
300 | - originatorName = "Deleted"; | ||
301 | - } | ||
302 | - alarmInfo.setOriginatorName(originatorName); | ||
303 | - return alarmInfo; | ||
304 | - }, MoreExecutors.directExecutor() | ||
305 | - )); | ||
306 | - } | ||
307 | - return Futures.transform(Futures.successfulAsList(alarmFutures), | ||
308 | - alarmInfos -> new PageData<>(alarmInfos, alarms.getTotalPages(), alarms.getTotalElements(), | ||
309 | - alarms.hasNext()), MoreExecutors.directExecutor()); | 295 | + return fetchAlarmsOriginators(tenantId, alarms); |
310 | } | 296 | } |
311 | return Futures.immediateFuture(alarms); | 297 | return Futures.immediateFuture(alarms); |
312 | } | 298 | } |
313 | 299 | ||
314 | @Override | 300 | @Override |
301 | + public ListenableFuture<PageData<AlarmInfo>> findCustomerAlarms(TenantId tenantId, CustomerId customerId, AlarmQuery query) { | ||
302 | + PageData<AlarmInfo> alarms = alarmDao.findCustomerAlarms(tenantId, customerId, query); | ||
303 | + if (query.getFetchOriginator() != null && query.getFetchOriginator().booleanValue()) { | ||
304 | + return fetchAlarmsOriginators(tenantId, alarms); | ||
305 | + } | ||
306 | + return Futures.immediateFuture(alarms); | ||
307 | + } | ||
308 | + | ||
309 | + private ListenableFuture<PageData<AlarmInfo>> fetchAlarmsOriginators(TenantId tenantId, PageData<AlarmInfo> alarms) { | ||
310 | + List<ListenableFuture<AlarmInfo>> alarmFutures = new ArrayList<>(alarms.getData().size()); | ||
311 | + for (AlarmInfo alarmInfo : alarms.getData()) { | ||
312 | + alarmFutures.add(Futures.transform( | ||
313 | + entityService.fetchEntityNameAsync(tenantId, alarmInfo.getOriginator()), originatorName -> { | ||
314 | + if (originatorName == null) { | ||
315 | + originatorName = "Deleted"; | ||
316 | + } | ||
317 | + alarmInfo.setOriginatorName(originatorName); | ||
318 | + return alarmInfo; | ||
319 | + }, MoreExecutors.directExecutor() | ||
320 | + )); | ||
321 | + } | ||
322 | + return Futures.transform(Futures.successfulAsList(alarmFutures), | ||
323 | + alarmInfos -> new PageData<>(alarmInfos, alarms.getTotalPages(), alarms.getTotalElements(), | ||
324 | + alarms.hasNext()), MoreExecutors.directExecutor()); | ||
325 | + } | ||
326 | + | ||
327 | + @Override | ||
315 | public AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, | 328 | public AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, |
316 | AlarmStatus alarmStatus) { | 329 | AlarmStatus alarmStatus) { |
317 | Set<AlarmStatus> statusList = null; | 330 | Set<AlarmStatus> statusList = null; |
@@ -170,6 +170,7 @@ public class ModelConstants { | @@ -170,6 +170,7 @@ public class ModelConstants { | ||
170 | public static final String DEVICE_PROFILE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; | 170 | public static final String DEVICE_PROFILE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; |
171 | public static final String DEVICE_PROFILE_NAME_PROPERTY = "name"; | 171 | public static final String DEVICE_PROFILE_NAME_PROPERTY = "name"; |
172 | public static final String DEVICE_PROFILE_TYPE_PROPERTY = "type"; | 172 | public static final String DEVICE_PROFILE_TYPE_PROPERTY = "type"; |
173 | + public static final String DEVICE_PROFILE_IMAGE_PROPERTY = "image"; | ||
173 | public static final String DEVICE_PROFILE_TRANSPORT_TYPE_PROPERTY = "transport_type"; | 174 | public static final String DEVICE_PROFILE_TRANSPORT_TYPE_PROPERTY = "transport_type"; |
174 | public static final String DEVICE_PROFILE_PROVISION_TYPE_PROPERTY = "provision_type"; | 175 | public static final String DEVICE_PROFILE_PROVISION_TYPE_PROPERTY = "provision_type"; |
175 | public static final String DEVICE_PROFILE_PROFILE_DATA_PROPERTY = "profile_data"; | 176 | public static final String DEVICE_PROFILE_PROFILE_DATA_PROPERTY = "profile_data"; |
@@ -333,6 +334,7 @@ public class ModelConstants { | @@ -333,6 +334,7 @@ public class ModelConstants { | ||
333 | public static final String DASHBOARD_COLUMN_FAMILY_NAME = "dashboard"; | 334 | public static final String DASHBOARD_COLUMN_FAMILY_NAME = "dashboard"; |
334 | public static final String DASHBOARD_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; | 335 | public static final String DASHBOARD_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; |
335 | public static final String DASHBOARD_TITLE_PROPERTY = TITLE_PROPERTY; | 336 | public static final String DASHBOARD_TITLE_PROPERTY = TITLE_PROPERTY; |
337 | + public static final String DASHBOARD_IMAGE_PROPERTY = "image"; | ||
336 | public static final String DASHBOARD_CONFIGURATION_PROPERTY = "configuration"; | 338 | public static final String DASHBOARD_CONFIGURATION_PROPERTY = "configuration"; |
337 | public static final String DASHBOARD_ASSIGNED_CUSTOMERS_PROPERTY = "assigned_customers"; | 339 | public static final String DASHBOARD_ASSIGNED_CUSTOMERS_PROPERTY = "assigned_customers"; |
338 | 340 |
@@ -58,7 +58,10 @@ public final class DashboardEntity extends BaseSqlEntity<Dashboard> implements S | @@ -58,7 +58,10 @@ public final class DashboardEntity extends BaseSqlEntity<Dashboard> implements S | ||
58 | 58 | ||
59 | @Column(name = ModelConstants.DASHBOARD_TITLE_PROPERTY) | 59 | @Column(name = ModelConstants.DASHBOARD_TITLE_PROPERTY) |
60 | private String title; | 60 | private String title; |
61 | - | 61 | + |
62 | + @Column(name = ModelConstants.DASHBOARD_IMAGE_PROPERTY) | ||
63 | + private String image; | ||
64 | + | ||
62 | @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY) | 65 | @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY) |
63 | private String searchText; | 66 | private String searchText; |
64 | 67 | ||
@@ -82,6 +85,7 @@ public final class DashboardEntity extends BaseSqlEntity<Dashboard> implements S | @@ -82,6 +85,7 @@ public final class DashboardEntity extends BaseSqlEntity<Dashboard> implements S | ||
82 | this.tenantId = dashboard.getTenantId().getId(); | 85 | this.tenantId = dashboard.getTenantId().getId(); |
83 | } | 86 | } |
84 | this.title = dashboard.getTitle(); | 87 | this.title = dashboard.getTitle(); |
88 | + this.image = dashboard.getImage(); | ||
85 | if (dashboard.getAssignedCustomers() != null) { | 89 | if (dashboard.getAssignedCustomers() != null) { |
86 | try { | 90 | try { |
87 | this.assignedCustomers = objectMapper.writeValueAsString(dashboard.getAssignedCustomers()); | 91 | this.assignedCustomers = objectMapper.writeValueAsString(dashboard.getAssignedCustomers()); |
@@ -110,6 +114,7 @@ public final class DashboardEntity extends BaseSqlEntity<Dashboard> implements S | @@ -110,6 +114,7 @@ public final class DashboardEntity extends BaseSqlEntity<Dashboard> implements S | ||
110 | dashboard.setTenantId(new TenantId(tenantId)); | 114 | dashboard.setTenantId(new TenantId(tenantId)); |
111 | } | 115 | } |
112 | dashboard.setTitle(title); | 116 | dashboard.setTitle(title); |
117 | + dashboard.setImage(image); | ||
113 | if (!StringUtils.isEmpty(assignedCustomers)) { | 118 | if (!StringUtils.isEmpty(assignedCustomers)) { |
114 | try { | 119 | try { |
115 | dashboard.setAssignedCustomers(objectMapper.readValue(assignedCustomers, assignedCustomersType)); | 120 | dashboard.setAssignedCustomers(objectMapper.readValue(assignedCustomers, assignedCustomersType)); |
@@ -54,6 +54,9 @@ public class DashboardInfoEntity extends BaseSqlEntity<DashboardInfo> implements | @@ -54,6 +54,9 @@ public class DashboardInfoEntity extends BaseSqlEntity<DashboardInfo> implements | ||
54 | @Column(name = ModelConstants.DASHBOARD_TITLE_PROPERTY) | 54 | @Column(name = ModelConstants.DASHBOARD_TITLE_PROPERTY) |
55 | private String title; | 55 | private String title; |
56 | 56 | ||
57 | + @Column(name = ModelConstants.DASHBOARD_IMAGE_PROPERTY) | ||
58 | + private String image; | ||
59 | + | ||
57 | @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY) | 60 | @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY) |
58 | private String searchText; | 61 | private String searchText; |
59 | 62 | ||
@@ -73,6 +76,7 @@ public class DashboardInfoEntity extends BaseSqlEntity<DashboardInfo> implements | @@ -73,6 +76,7 @@ public class DashboardInfoEntity extends BaseSqlEntity<DashboardInfo> implements | ||
73 | this.tenantId = dashboardInfo.getTenantId().getId(); | 76 | this.tenantId = dashboardInfo.getTenantId().getId(); |
74 | } | 77 | } |
75 | this.title = dashboardInfo.getTitle(); | 78 | this.title = dashboardInfo.getTitle(); |
79 | + this.image = dashboardInfo.getImage(); | ||
76 | if (dashboardInfo.getAssignedCustomers() != null) { | 80 | if (dashboardInfo.getAssignedCustomers() != null) { |
77 | try { | 81 | try { |
78 | this.assignedCustomers = objectMapper.writeValueAsString(dashboardInfo.getAssignedCustomers()); | 82 | this.assignedCustomers = objectMapper.writeValueAsString(dashboardInfo.getAssignedCustomers()); |
@@ -104,6 +108,7 @@ public class DashboardInfoEntity extends BaseSqlEntity<DashboardInfo> implements | @@ -104,6 +108,7 @@ public class DashboardInfoEntity extends BaseSqlEntity<DashboardInfo> implements | ||
104 | dashboardInfo.setTenantId(new TenantId(tenantId)); | 108 | dashboardInfo.setTenantId(new TenantId(tenantId)); |
105 | } | 109 | } |
106 | dashboardInfo.setTitle(title); | 110 | dashboardInfo.setTitle(title); |
111 | + dashboardInfo.setImage(image); | ||
107 | if (!StringUtils.isEmpty(assignedCustomers)) { | 112 | if (!StringUtils.isEmpty(assignedCustomers)) { |
108 | try { | 113 | try { |
109 | dashboardInfo.setAssignedCustomers(objectMapper.readValue(assignedCustomers, assignedCustomersType)); | 114 | dashboardInfo.setAssignedCustomers(objectMapper.readValue(assignedCustomers, assignedCustomersType)); |
@@ -60,6 +60,9 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl | @@ -60,6 +60,9 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl | ||
60 | @Column(name = ModelConstants.DEVICE_PROFILE_TYPE_PROPERTY) | 60 | @Column(name = ModelConstants.DEVICE_PROFILE_TYPE_PROPERTY) |
61 | private DeviceProfileType type; | 61 | private DeviceProfileType type; |
62 | 62 | ||
63 | + @Column(name = ModelConstants.DEVICE_PROFILE_IMAGE_PROPERTY) | ||
64 | + private String image; | ||
65 | + | ||
63 | @Enumerated(EnumType.STRING) | 66 | @Enumerated(EnumType.STRING) |
64 | @Column(name = ModelConstants.DEVICE_PROFILE_TRANSPORT_TYPE_PROPERTY) | 67 | @Column(name = ModelConstants.DEVICE_PROFILE_TRANSPORT_TYPE_PROPERTY) |
65 | private DeviceTransportType transportType; | 68 | private DeviceTransportType transportType; |
@@ -110,6 +113,7 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl | @@ -110,6 +113,7 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl | ||
110 | this.setCreatedTime(deviceProfile.getCreatedTime()); | 113 | this.setCreatedTime(deviceProfile.getCreatedTime()); |
111 | this.name = deviceProfile.getName(); | 114 | this.name = deviceProfile.getName(); |
112 | this.type = deviceProfile.getType(); | 115 | this.type = deviceProfile.getType(); |
116 | + this.image = deviceProfile.getImage(); | ||
113 | this.transportType = deviceProfile.getTransportType(); | 117 | this.transportType = deviceProfile.getTransportType(); |
114 | this.provisionType = deviceProfile.getProvisionType(); | 118 | this.provisionType = deviceProfile.getProvisionType(); |
115 | this.description = deviceProfile.getDescription(); | 119 | this.description = deviceProfile.getDescription(); |
@@ -151,6 +155,7 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl | @@ -151,6 +155,7 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl | ||
151 | } | 155 | } |
152 | deviceProfile.setName(name); | 156 | deviceProfile.setName(name); |
153 | deviceProfile.setType(type); | 157 | deviceProfile.setType(type); |
158 | + deviceProfile.setImage(image); | ||
154 | deviceProfile.setTransportType(transportType); | 159 | deviceProfile.setTransportType(transportType); |
155 | deviceProfile.setProvisionType(provisionType); | 160 | deviceProfile.setProvisionType(provisionType); |
156 | deviceProfile.setDescription(description); | 161 | deviceProfile.setDescription(description); |
@@ -94,6 +94,70 @@ public interface AlarmRepository extends CrudRepository<AlarmEntity, UUID> { | @@ -94,6 +94,70 @@ public interface AlarmRepository extends CrudRepository<AlarmEntity, UUID> { | ||
94 | @Param("searchText") String searchText, | 94 | @Param("searchText") String searchText, |
95 | Pageable pageable); | 95 | Pageable pageable); |
96 | 96 | ||
97 | + @Query(value = "SELECT new org.thingsboard.server.dao.model.sql.AlarmInfoEntity(a) FROM AlarmEntity a " + | ||
98 | + "WHERE a.tenantId = :tenantId " + | ||
99 | + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + | ||
100 | + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + | ||
101 | + "AND ((:alarmStatuses) IS NULL OR a.status in (:alarmStatuses)) " + | ||
102 | + "AND (LOWER(a.type) LIKE LOWER(CONCAT(:searchText, '%')) " + | ||
103 | + " OR LOWER(a.severity) LIKE LOWER(CONCAT(:searchText, '%')) " + | ||
104 | + " OR LOWER(a.status) LIKE LOWER(CONCAT(:searchText, '%'))) ", | ||
105 | + countQuery = "" + | ||
106 | + "SELECT count(a) " + | ||
107 | + "FROM AlarmEntity a " + | ||
108 | + "WHERE a.tenantId = :tenantId " + | ||
109 | + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + | ||
110 | + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + | ||
111 | + "AND ((:alarmStatuses) IS NULL OR a.status in (:alarmStatuses)) " + | ||
112 | + "AND (LOWER(a.type) LIKE LOWER(CONCAT(:searchText, '%')) " + | ||
113 | + " OR LOWER(a.severity) LIKE LOWER(CONCAT(:searchText, '%')) " + | ||
114 | + " OR LOWER(a.status) LIKE LOWER(CONCAT(:searchText, '%'))) ") | ||
115 | + Page<AlarmInfoEntity> findAllAlarms(@Param("tenantId") UUID tenantId, | ||
116 | + @Param("startTime") Long startTime, | ||
117 | + @Param("endTime") Long endTime, | ||
118 | + @Param("alarmStatuses") Set<AlarmStatus> alarmStatuses, | ||
119 | + @Param("searchText") String searchText, | ||
120 | + Pageable pageable); | ||
121 | + | ||
122 | + @Query(value = "SELECT new org.thingsboard.server.dao.model.sql.AlarmInfoEntity(a) FROM AlarmEntity a " + | ||
123 | + "WHERE a.tenantId = :tenantId " + | ||
124 | + "AND (" + | ||
125 | + "a.originatorId IN (SELECT d.id from DeviceEntity d WHERE d.customerId = :customerId) " + | ||
126 | + "OR a.originatorId IN (SELECT asset.id from AssetEntity asset WHERE asset.customerId = :customerId) " + | ||
127 | + "OR a.originatorId IN (SELECT u.id from UserEntity u WHERE u.customerId = :customerId) " + | ||
128 | + "OR a.originatorId = :customerId" + | ||
129 | + ") " + | ||
130 | + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + | ||
131 | + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + | ||
132 | + "AND ((:alarmStatuses) IS NULL OR a.status in (:alarmStatuses)) " + | ||
133 | + "AND (LOWER(a.type) LIKE LOWER(CONCAT(:searchText, '%')) " + | ||
134 | + " OR LOWER(a.severity) LIKE LOWER(CONCAT(:searchText, '%')) " + | ||
135 | + " OR LOWER(a.status) LIKE LOWER(CONCAT(:searchText, '%'))) " | ||
136 | + , | ||
137 | + countQuery = "" + | ||
138 | + "SELECT count(a) " + | ||
139 | + "FROM AlarmEntity a " + | ||
140 | + "WHERE a.tenantId = :tenantId " + | ||
141 | + "AND (" + | ||
142 | + "a.originatorId IN (SELECT d.id from DeviceEntity d WHERE d.customerId = :customerId) " + | ||
143 | + "OR a.originatorId IN (SELECT asset.id from AssetEntity asset WHERE asset.customerId = :customerId) " + | ||
144 | + "OR a.originatorId IN (SELECT u.id from UserEntity u WHERE u.customerId = :customerId) " + | ||
145 | + "OR a.originatorId = :customerId" + | ||
146 | + ") " + | ||
147 | + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + | ||
148 | + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + | ||
149 | + "AND ((:alarmStatuses) IS NULL OR a.status in (:alarmStatuses)) " + | ||
150 | + "AND (LOWER(a.type) LIKE LOWER(CONCAT(:searchText, '%')) " + | ||
151 | + " OR LOWER(a.severity) LIKE LOWER(CONCAT(:searchText, '%')) " + | ||
152 | + " OR LOWER(a.status) LIKE LOWER(CONCAT(:searchText, '%'))) ") | ||
153 | + Page<AlarmInfoEntity> findCustomerAlarms(@Param("tenantId") UUID tenantId, | ||
154 | + @Param("customerId") UUID customerId, | ||
155 | + @Param("startTime") Long startTime, | ||
156 | + @Param("endTime") Long endTime, | ||
157 | + @Param("alarmStatuses") Set<AlarmStatus> alarmStatuses, | ||
158 | + @Param("searchText") String searchText, | ||
159 | + Pageable pageable); | ||
160 | + | ||
97 | @Query(value = "SELECT a.severity FROM AlarmEntity a " + | 161 | @Query(value = "SELECT a.severity FROM AlarmEntity a " + |
98 | "LEFT JOIN RelationEntity re ON a.id = re.toId " + | 162 | "LEFT JOIN RelationEntity re ON a.id = re.toId " + |
99 | "AND re.relationTypeGroup = 'ALARM' " + | 163 | "AND re.relationTypeGroup = 'ALARM' " + |
@@ -103,11 +103,46 @@ public class JpaAlarmDao extends JpaAbstractDao<AlarmEntity, Alarm> implements A | @@ -103,11 +103,46 @@ public class JpaAlarmDao extends JpaAbstractDao<AlarmEntity, Alarm> implements A | ||
103 | } else if (query.getStatus() != null) { | 103 | } else if (query.getStatus() != null) { |
104 | statusSet = Collections.singleton(query.getStatus()); | 104 | statusSet = Collections.singleton(query.getStatus()); |
105 | } | 105 | } |
106 | + if (affectedEntity != null) { | ||
107 | + return DaoUtil.toPageData( | ||
108 | + alarmRepository.findAlarms( | ||
109 | + tenantId.getId(), | ||
110 | + affectedEntity.getId(), | ||
111 | + affectedEntity.getEntityType().name(), | ||
112 | + query.getPageLink().getStartTime(), | ||
113 | + query.getPageLink().getEndTime(), | ||
114 | + statusSet, | ||
115 | + Objects.toString(query.getPageLink().getTextSearch(), ""), | ||
116 | + DaoUtil.toPageable(query.getPageLink()) | ||
117 | + ) | ||
118 | + ); | ||
119 | + } else { | ||
120 | + return DaoUtil.toPageData( | ||
121 | + alarmRepository.findAllAlarms( | ||
122 | + tenantId.getId(), | ||
123 | + query.getPageLink().getStartTime(), | ||
124 | + query.getPageLink().getEndTime(), | ||
125 | + statusSet, | ||
126 | + Objects.toString(query.getPageLink().getTextSearch(), ""), | ||
127 | + DaoUtil.toPageable(query.getPageLink()) | ||
128 | + ) | ||
129 | + ); | ||
130 | + } | ||
131 | + } | ||
132 | + | ||
133 | + @Override | ||
134 | + public PageData<AlarmInfo> findCustomerAlarms(TenantId tenantId, CustomerId customerId, AlarmQuery query) { | ||
135 | + log.trace("Try to find customer alarms by status [{}] and pageLink [{}]", query.getStatus(), query.getPageLink()); | ||
136 | + Set<AlarmStatus> statusSet = null; | ||
137 | + if (query.getSearchStatus() != null) { | ||
138 | + statusSet = query.getSearchStatus().getStatuses(); | ||
139 | + } else if (query.getStatus() != null) { | ||
140 | + statusSet = Collections.singleton(query.getStatus()); | ||
141 | + } | ||
106 | return DaoUtil.toPageData( | 142 | return DaoUtil.toPageData( |
107 | - alarmRepository.findAlarms( | 143 | + alarmRepository.findCustomerAlarms( |
108 | tenantId.getId(), | 144 | tenantId.getId(), |
109 | - affectedEntity.getId(), | ||
110 | - affectedEntity.getEntityType().name(), | 145 | + customerId.getId(), |
111 | query.getPageLink().getStartTime(), | 146 | query.getPageLink().getStartTime(), |
112 | query.getPageLink().getEndTime(), | 147 | query.getPageLink().getEndTime(), |
113 | statusSet, | 148 | statusSet, |
@@ -28,7 +28,7 @@ import java.util.UUID; | @@ -28,7 +28,7 @@ import java.util.UUID; | ||
28 | 28 | ||
29 | public interface DeviceProfileRepository extends PagingAndSortingRepository<DeviceProfileEntity, UUID> { | 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.type, d.transportType) " + | 31 | + @Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.name, d.image, d.type, d.transportType) " + |
32 | "FROM DeviceProfileEntity d " + | 32 | "FROM DeviceProfileEntity d " + |
33 | "WHERE d.id = :deviceProfileId") | 33 | "WHERE d.id = :deviceProfileId") |
34 | DeviceProfileInfo findDeviceProfileInfoById(@Param("deviceProfileId") UUID deviceProfileId); | 34 | DeviceProfileInfo findDeviceProfileInfoById(@Param("deviceProfileId") UUID deviceProfileId); |
@@ -39,14 +39,14 @@ public interface DeviceProfileRepository extends PagingAndSortingRepository<Devi | @@ -39,14 +39,14 @@ public interface DeviceProfileRepository extends PagingAndSortingRepository<Devi | ||
39 | @Param("textSearch") String textSearch, | 39 | @Param("textSearch") String textSearch, |
40 | Pageable pageable); | 40 | Pageable pageable); |
41 | 41 | ||
42 | - @Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.name, d.type, d.transportType) " + | 42 | + @Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.name, d.image, d.type, d.transportType) " + |
43 | "FROM DeviceProfileEntity d WHERE " + | 43 | "FROM DeviceProfileEntity d WHERE " + |
44 | "d.tenantId = :tenantId AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") | 44 | "d.tenantId = :tenantId AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") |
45 | Page<DeviceProfileInfo> findDeviceProfileInfos(@Param("tenantId") UUID tenantId, | 45 | Page<DeviceProfileInfo> findDeviceProfileInfos(@Param("tenantId") UUID tenantId, |
46 | @Param("textSearch") String textSearch, | 46 | @Param("textSearch") String textSearch, |
47 | Pageable pageable); | 47 | Pageable pageable); |
48 | 48 | ||
49 | - @Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.name, d.type, d.transportType) " + | 49 | + @Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.name, d.image, d.type, d.transportType) " + |
50 | "FROM DeviceProfileEntity d WHERE " + | 50 | "FROM DeviceProfileEntity d WHERE " + |
51 | "d.tenantId = :tenantId AND d.transportType = :transportType AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") | 51 | "d.tenantId = :tenantId AND d.transportType = :transportType AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") |
52 | Page<DeviceProfileInfo> findDeviceProfileInfos(@Param("tenantId") UUID tenantId, | 52 | Page<DeviceProfileInfo> findDeviceProfileInfos(@Param("tenantId") UUID tenantId, |
@@ -58,7 +58,7 @@ public interface DeviceProfileRepository extends PagingAndSortingRepository<Devi | @@ -58,7 +58,7 @@ public interface DeviceProfileRepository extends PagingAndSortingRepository<Devi | ||
58 | "WHERE d.tenantId = :tenantId AND d.isDefault = true") | 58 | "WHERE d.tenantId = :tenantId AND d.isDefault = true") |
59 | DeviceProfileEntity findByDefaultTrueAndTenantId(@Param("tenantId") UUID tenantId); | 59 | DeviceProfileEntity findByDefaultTrueAndTenantId(@Param("tenantId") UUID tenantId); |
60 | 60 | ||
61 | - @Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.name, d.type, d.transportType) " + | 61 | + @Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.name, d.image, d.type, d.transportType) " + |
62 | "FROM DeviceProfileEntity d " + | 62 | "FROM DeviceProfileEntity d " + |
63 | "WHERE d.tenantId = :tenantId AND d.isDefault = true") | 63 | "WHERE d.tenantId = :tenantId AND d.isDefault = true") |
64 | DeviceProfileInfo findDefaultDeviceProfileInfo(@Param("tenantId") UUID tenantId); | 64 | DeviceProfileInfo findDefaultDeviceProfileInfo(@Param("tenantId") UUID tenantId); |
@@ -118,7 +118,8 @@ CREATE TABLE IF NOT EXISTS dashboard ( | @@ -118,7 +118,8 @@ CREATE TABLE IF NOT EXISTS dashboard ( | ||
118 | assigned_customers varchar(1000000), | 118 | assigned_customers varchar(1000000), |
119 | search_text varchar(255), | 119 | search_text varchar(255), |
120 | tenant_id uuid, | 120 | tenant_id uuid, |
121 | - title varchar(255) | 121 | + title varchar(255), |
122 | + image varchar(1000000) | ||
122 | ); | 123 | ); |
123 | 124 | ||
124 | CREATE TABLE IF NOT EXISTS rule_chain ( | 125 | CREATE TABLE IF NOT EXISTS rule_chain ( |
@@ -182,6 +183,7 @@ CREATE TABLE IF NOT EXISTS device_profile ( | @@ -182,6 +183,7 @@ CREATE TABLE IF NOT EXISTS device_profile ( | ||
182 | created_time bigint NOT NULL, | 183 | created_time bigint NOT NULL, |
183 | name varchar(255), | 184 | name varchar(255), |
184 | type varchar(255), | 185 | type varchar(255), |
186 | + image varchar(1000000), | ||
185 | transport_type varchar(255), | 187 | transport_type varchar(255), |
186 | provision_type varchar(255), | 188 | provision_type varchar(255), |
187 | profile_data jsonb, | 189 | profile_data jsonb, |
@@ -136,7 +136,8 @@ CREATE TABLE IF NOT EXISTS dashboard ( | @@ -136,7 +136,8 @@ CREATE TABLE IF NOT EXISTS dashboard ( | ||
136 | assigned_customers varchar(1000000), | 136 | assigned_customers varchar(1000000), |
137 | search_text varchar(255), | 137 | search_text varchar(255), |
138 | tenant_id uuid, | 138 | tenant_id uuid, |
139 | - title varchar(255) | 139 | + title varchar(255), |
140 | + image varchar(1000000) | ||
140 | ); | 141 | ); |
141 | 142 | ||
142 | CREATE TABLE IF NOT EXISTS rule_chain ( | 143 | CREATE TABLE IF NOT EXISTS rule_chain ( |
@@ -201,6 +202,7 @@ CREATE TABLE IF NOT EXISTS device_profile ( | @@ -201,6 +202,7 @@ CREATE TABLE IF NOT EXISTS device_profile ( | ||
201 | created_time bigint NOT NULL, | 202 | created_time bigint NOT NULL, |
202 | name varchar(255), | 203 | name varchar(255), |
203 | type varchar(255), | 204 | type varchar(255), |
205 | + image varchar(1000000), | ||
204 | transport_type varchar(255), | 206 | transport_type varchar(255), |
205 | provision_type varchar(255), | 207 | provision_type varchar(255), |
206 | profile_data jsonb, | 208 | profile_data jsonb, |
@@ -333,7 +333,7 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest { | @@ -333,7 +333,7 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest { | ||
333 | 333 | ||
334 | List<DeviceProfileInfo> deviceProfileInfos = deviceProfiles.stream() | 334 | List<DeviceProfileInfo> deviceProfileInfos = deviceProfiles.stream() |
335 | .map(deviceProfile -> new DeviceProfileInfo(deviceProfile.getId(), | 335 | .map(deviceProfile -> new DeviceProfileInfo(deviceProfile.getId(), |
336 | - deviceProfile.getName(), deviceProfile.getType(), deviceProfile.getTransportType())).collect(Collectors.toList()); | 336 | + deviceProfile.getName(), deviceProfile.getImage(), deviceProfile.getType(), deviceProfile.getTransportType())).collect(Collectors.toList()); |
337 | 337 | ||
338 | Assert.assertEquals(deviceProfileInfos, loadedDeviceProfileInfos); | 338 | Assert.assertEquals(deviceProfileInfos, loadedDeviceProfileInfos); |
339 | 339 |
@@ -57,6 +57,8 @@ public interface RuleEngineAlarmService { | @@ -57,6 +57,8 @@ public interface RuleEngineAlarmService { | ||
57 | 57 | ||
58 | ListenableFuture<PageData<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query); | 58 | ListenableFuture<PageData<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query); |
59 | 59 | ||
60 | + ListenableFuture<PageData<AlarmInfo>> findCustomerAlarms(TenantId tenantId, CustomerId customerId, AlarmQuery query); | ||
61 | + | ||
60 | AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, AlarmStatus alarmStatus); | 62 | AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, AlarmStatus alarmStatus); |
61 | 63 | ||
62 | PageData<AlarmData> findAlarmDataByQueryForEntities(TenantId tenantId, CustomerId customerId, AlarmDataQuery query, Collection<EntityId> orderedEntityIds); | 64 | PageData<AlarmData> findAlarmDataByQueryForEntities(TenantId tenantId, CustomerId customerId, AlarmDataQuery query, Collection<EntityId> orderedEntityIds); |
@@ -60,6 +60,11 @@ | @@ -60,6 +60,11 @@ | ||
60 | {{ 'device-profile.type-required' | translate }} | 60 | {{ 'device-profile.type-required' | translate }} |
61 | </mat-error> | 61 | </mat-error> |
62 | </mat-form-field> | 62 | </mat-form-field> |
63 | + <tb-image-input fxFlex | ||
64 | + label="{{'device-profile.image' | translate}}" | ||
65 | + maxSizeByte="524288" | ||
66 | + formControlName="image"> | ||
67 | + </tb-image-input> | ||
63 | <mat-form-field class="mat-block"> | 68 | <mat-form-field class="mat-block"> |
64 | <mat-label translate>device-profile.description</mat-label> | 69 | <mat-label translate>device-profile.description</mat-label> |
65 | <textarea matInput formControlName="description" rows="2"></textarea> | 70 | <textarea matInput formControlName="description" rows="2"></textarea> |
@@ -106,6 +106,7 @@ export class AddDeviceProfileDialogComponent extends | @@ -106,6 +106,7 @@ export class AddDeviceProfileDialogComponent extends | ||
106 | { | 106 | { |
107 | name: [data.deviceProfileName, [Validators.required]], | 107 | name: [data.deviceProfileName, [Validators.required]], |
108 | type: [DeviceProfileType.DEFAULT, [Validators.required]], | 108 | type: [DeviceProfileType.DEFAULT, [Validators.required]], |
109 | + image: [null, []], | ||
109 | defaultRuleChainId: [null, []], | 110 | defaultRuleChainId: [null, []], |
110 | defaultQueueName: ['', []], | 111 | defaultQueueName: ['', []], |
111 | description: ['', []] | 112 | description: ['', []] |
@@ -183,6 +184,7 @@ export class AddDeviceProfileDialogComponent extends | @@ -183,6 +184,7 @@ export class AddDeviceProfileDialogComponent extends | ||
183 | const deviceProfile: DeviceProfile = { | 184 | const deviceProfile: DeviceProfile = { |
184 | name: this.deviceProfileDetailsFormGroup.get('name').value, | 185 | name: this.deviceProfileDetailsFormGroup.get('name').value, |
185 | type: this.deviceProfileDetailsFormGroup.get('type').value, | 186 | type: this.deviceProfileDetailsFormGroup.get('type').value, |
187 | + image: this.deviceProfileDetailsFormGroup.get('image').value, | ||
186 | transportType: this.transportConfigFormGroup.get('transportType').value, | 188 | transportType: this.transportConfigFormGroup.get('transportType').value, |
187 | provisionType: deviceProvisionConfiguration.type, | 189 | provisionType: deviceProvisionConfiguration.type, |
188 | provisionDeviceKey, | 190 | provisionDeviceKey, |
@@ -86,6 +86,11 @@ | @@ -86,6 +86,11 @@ | ||
86 | {{ 'device-profile.type-required' | translate }} | 86 | {{ 'device-profile.type-required' | translate }} |
87 | </mat-error> | 87 | </mat-error> |
88 | </mat-form-field> | 88 | </mat-form-field> |
89 | + <tb-image-input fxFlex | ||
90 | + label="{{'device-profile.image' | translate}}" | ||
91 | + maxSizeByte="524288" | ||
92 | + formControlName="image"> | ||
93 | + </tb-image-input> | ||
89 | <mat-form-field class="mat-block"> | 94 | <mat-form-field class="mat-block"> |
90 | <mat-label translate>device-profile.description</mat-label> | 95 | <mat-label translate>device-profile.description</mat-label> |
91 | <textarea matInput formControlName="description" rows="2"></textarea> | 96 | <textarea matInput formControlName="description" rows="2"></textarea> |
@@ -103,6 +103,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> { | @@ -103,6 +103,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> { | ||
103 | { | 103 | { |
104 | name: [entity ? entity.name : '', [Validators.required]], | 104 | name: [entity ? entity.name : '', [Validators.required]], |
105 | type: [entity ? entity.type : null, [Validators.required]], | 105 | type: [entity ? entity.type : null, [Validators.required]], |
106 | + image: [entity ? entity.image : null], | ||
106 | transportType: [entity ? entity.transportType : null, [Validators.required]], | 107 | transportType: [entity ? entity.transportType : null, [Validators.required]], |
107 | profileData: this.fb.group({ | 108 | profileData: this.fb.group({ |
108 | configuration: [entity && !this.isAdd ? entity.profileData?.configuration : {}, Validators.required], | 109 | configuration: [entity && !this.isAdd ? entity.profileData?.configuration : {}, Validators.required], |
@@ -178,6 +179,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> { | @@ -178,6 +179,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> { | ||
178 | }; | 179 | }; |
179 | this.entityForm.patchValue({name: entity.name}); | 180 | this.entityForm.patchValue({name: entity.name}); |
180 | this.entityForm.patchValue({type: entity.type}, {emitEvent: false}); | 181 | this.entityForm.patchValue({type: entity.type}, {emitEvent: false}); |
182 | + this.entityForm.patchValue({image: entity.image}, {emitEvent: false}); | ||
181 | this.entityForm.patchValue({transportType: entity.transportType}, {emitEvent: false}); | 183 | this.entityForm.patchValue({transportType: entity.transportType}, {emitEvent: false}); |
182 | this.entityForm.patchValue({provisionType: entity.provisionType}, {emitEvent: false}); | 184 | this.entityForm.patchValue({provisionType: entity.provisionType}, {emitEvent: false}); |
183 | this.entityForm.patchValue({provisionDeviceKey: entity.provisionDeviceKey}, {emitEvent: false}); | 185 | this.entityForm.patchValue({provisionDeviceKey: entity.provisionDeviceKey}, {emitEvent: false}); |
@@ -105,6 +105,11 @@ | @@ -105,6 +105,11 @@ | ||
105 | {{ 'dashboard.title-required' | translate }} | 105 | {{ 'dashboard.title-required' | translate }} |
106 | </mat-error> | 106 | </mat-error> |
107 | </mat-form-field> | 107 | </mat-form-field> |
108 | + <tb-image-input fxFlex | ||
109 | + label="{{'dashboard.image' | translate}}" | ||
110 | + maxSizeByte="524288" | ||
111 | + formControlName="image"> | ||
112 | + </tb-image-input> | ||
108 | <div formGroupName="configuration" fxLayout="column"> | 113 | <div formGroupName="configuration" fxLayout="column"> |
109 | <mat-form-field class="mat-block"> | 114 | <mat-form-field class="mat-block"> |
110 | <mat-label translate>dashboard.description</mat-label> | 115 | <mat-label translate>dashboard.description</mat-label> |
@@ -80,6 +80,7 @@ export class DashboardFormComponent extends EntityComponent<Dashboard> { | @@ -80,6 +80,7 @@ export class DashboardFormComponent extends EntityComponent<Dashboard> { | ||
80 | return this.fb.group( | 80 | return this.fb.group( |
81 | { | 81 | { |
82 | title: [entity ? entity.title : '', [Validators.required]], | 82 | title: [entity ? entity.title : '', [Validators.required]], |
83 | + image: [entity ? entity.image : null], | ||
83 | configuration: this.fb.group( | 84 | configuration: this.fb.group( |
84 | { | 85 | { |
85 | description: [entity && entity.configuration ? entity.configuration.description : ''], | 86 | description: [entity && entity.configuration ? entity.configuration.description : ''], |
@@ -92,6 +93,7 @@ export class DashboardFormComponent extends EntityComponent<Dashboard> { | @@ -92,6 +93,7 @@ export class DashboardFormComponent extends EntityComponent<Dashboard> { | ||
92 | updateForm(entity: Dashboard) { | 93 | updateForm(entity: Dashboard) { |
93 | this.updateFields(entity); | 94 | this.updateFields(entity); |
94 | this.entityForm.patchValue({title: entity.title}); | 95 | this.entityForm.patchValue({title: entity.title}); |
96 | + this.entityForm.patchValue({image: entity.image}); | ||
95 | this.entityForm.patchValue({configuration: {description: entity.configuration ? entity.configuration.description : ''}}); | 97 | this.entityForm.patchValue({configuration: {description: entity.configuration ? entity.configuration.description : ''}}); |
96 | } | 98 | } |
97 | 99 |
@@ -21,10 +21,10 @@ | @@ -21,10 +21,10 @@ | ||
21 | [flowConfig]="{singleFile: true, allowDuplicateUploads: true}"> | 21 | [flowConfig]="{singleFile: true, allowDuplicateUploads: true}"> |
22 | <div class="tb-image-select-container"> | 22 | <div class="tb-image-select-container"> |
23 | <div *ngIf="showPreview" class="tb-image-preview-container"> | 23 | <div *ngIf="showPreview" class="tb-image-preview-container"> |
24 | - <div *ngIf="!safeImageUrl;else elseBlock" translate>dashboard.no-image</div> | 24 | + <div *ngIf="!safeImageUrl; else elseBlock">{{ (disabled ? 'dashboard.empty-image' : 'dashboard.no-image') | translate }}</div> |
25 | <ng-template #elseBlock><img class="tb-image-preview" [src]="safeImageUrl" /></ng-template> | 25 | <ng-template #elseBlock><img class="tb-image-preview" [src]="safeImageUrl" /></ng-template> |
26 | </div> | 26 | </div> |
27 | - <div *ngIf="showClearButton" class="tb-image-clear-container"> | 27 | + <div *ngIf="showClearButton && !disabled" class="tb-image-clear-container"> |
28 | <button mat-button mat-icon-button color="primary" | 28 | <button mat-button mat-icon-button color="primary" |
29 | type="button" | 29 | type="button" |
30 | (click)="clearImage()" | 30 | (click)="clearImage()" |
@@ -34,7 +34,7 @@ | @@ -34,7 +34,7 @@ | ||
34 | <mat-icon>close</mat-icon> | 34 | <mat-icon>close</mat-icon> |
35 | </button> | 35 | </button> |
36 | </div> | 36 | </div> |
37 | - <div class="drop-area tb-flow-drop" | 37 | + <div *ngIf="!disabled" class="drop-area tb-flow-drop" |
38 | flowDrop | 38 | flowDrop |
39 | [flow]="flow.flowJs"> | 39 | [flow]="flow.flowJs"> |
40 | <label for="{{inputId}}" translate>dashboard.drop-image</label> | 40 | <label for="{{inputId}}" translate>dashboard.drop-image</label> |
@@ -42,5 +42,5 @@ | @@ -42,5 +42,5 @@ | ||
42 | </div> | 42 | </div> |
43 | </div> | 43 | </div> |
44 | </ng-container> | 44 | </ng-container> |
45 | - <div class="tb-hint" *ngIf="maxSizeByte" translate [translateParams]="{ size: maxSizeByte | fileSize}">dashboard.maximum-upload-file-size</div> | 45 | + <div class="tb-hint" *ngIf="maxSizeByte && !disabled" translate [translateParams]="{ size: maxSizeByte | fileSize}">dashboard.maximum-upload-file-size</div> |
46 | </div> | 46 | </div> |
@@ -26,6 +26,7 @@ import { Filters } from '@shared/models/query/query.models'; | @@ -26,6 +26,7 @@ import { Filters } from '@shared/models/query/query.models'; | ||
26 | export interface DashboardInfo extends BaseData<DashboardId> { | 26 | export interface DashboardInfo extends BaseData<DashboardId> { |
27 | tenantId?: TenantId; | 27 | tenantId?: TenantId; |
28 | title?: string; | 28 | title?: string; |
29 | + image?: string; | ||
29 | assignedCustomers?: Array<ShortCustomerInfo>; | 30 | assignedCustomers?: Array<ShortCustomerInfo>; |
30 | } | 31 | } |
31 | 32 |
@@ -492,6 +492,7 @@ export interface DeviceProfile extends BaseData<DeviceProfileId> { | @@ -492,6 +492,7 @@ export interface DeviceProfile extends BaseData<DeviceProfileId> { | ||
492 | description?: string; | 492 | description?: string; |
493 | default?: boolean; | 493 | default?: boolean; |
494 | type: DeviceProfileType; | 494 | type: DeviceProfileType; |
495 | + image?: string; | ||
495 | transportType: DeviceTransportType; | 496 | transportType: DeviceTransportType; |
496 | provisionType: DeviceProvisionType; | 497 | provisionType: DeviceProvisionType; |
497 | provisionDeviceKey?: string; | 498 | provisionDeviceKey?: string; |
@@ -666,6 +666,7 @@ | @@ -666,6 +666,7 @@ | ||
666 | "no-widgets": "No widgets configured", | 666 | "no-widgets": "No widgets configured", |
667 | "add-widget": "Add new widget", | 667 | "add-widget": "Add new widget", |
668 | "title": "Title", | 668 | "title": "Title", |
669 | + "image": "Dashboard image", | ||
669 | "select-widget-title": "Select widget", | 670 | "select-widget-title": "Select widget", |
670 | "select-widget-value": "{{title}}: select widget", | 671 | "select-widget-value": "{{title}}: select widget", |
671 | "select-widget-subtitle": "List of available widget types", | 672 | "select-widget-subtitle": "List of available widget types", |
@@ -712,6 +713,7 @@ | @@ -712,6 +713,7 @@ | ||
712 | "background-image": "Background image", | 713 | "background-image": "Background image", |
713 | "background-size-mode": "Background size mode", | 714 | "background-size-mode": "Background size mode", |
714 | "no-image": "No image selected", | 715 | "no-image": "No image selected", |
716 | + "empty-image": "No image", | ||
715 | "drop-image": "Drop an image or click to select a file to upload.", | 717 | "drop-image": "Drop an image or click to select a file to upload.", |
716 | "maximum-upload-file-size": "Maximum upload file size: {{ size }}", | 718 | "maximum-upload-file-size": "Maximum upload file size: {{ size }}", |
717 | "cannot-upload-file": "Cannot upload file", | 719 | "cannot-upload-file": "Cannot upload file", |
@@ -1028,6 +1030,7 @@ | @@ -1028,6 +1030,7 @@ | ||
1028 | "type": "Profile type", | 1030 | "type": "Profile type", |
1029 | "type-required": "Profile type is required.", | 1031 | "type-required": "Profile type is required.", |
1030 | "type-default": "Default", | 1032 | "type-default": "Default", |
1033 | + "image": "Device profile image", | ||
1031 | "transport-type": "Transport type", | 1034 | "transport-type": "Transport type", |
1032 | "transport-type-required": "Transport type is required.", | 1035 | "transport-type-required": "Transport type is required.", |
1033 | "transport-type-default": "Default", | 1036 | "transport-type-default": "Default", |