diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java index 44263d19bd..9287ed515e 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.controller; +import com.google.common.util.concurrent.ListenableFuture; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; @@ -29,6 +30,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; +import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmInfo; @@ -498,4 +500,14 @@ public class AlarmController extends BaseController { alarmStatus, assigneeId); } + @ApiOperation(value = "Get Alarm Types (getAlarmTypes)", + notes = "Returns a set of unique alarm types based on alarms that are either owned by the tenant or assigned to the customer which user is performing the request.", produces = MediaType.APPLICATION_JSON_VALUE) + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") + @RequestMapping(value = "/alarm/types", method = RequestMethod.GET) + @ResponseBody + public List getAlarmTypes() throws ThingsboardException, ExecutionException, InterruptedException { + ListenableFuture> alarmTypes = alarmService.findAlarmTypesByTenantId(getTenantId()); + return checkNotNull(alarmTypes.get()); + } + } diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java index 1603d33bfd..dd52403bcd 100644 --- a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java @@ -25,6 +25,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.springframework.stereotype.Service; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.ApiUsageRecordKey; +import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmApiCallResult; import org.thingsboard.server.common.data.alarm.AlarmComment; @@ -58,6 +59,7 @@ import org.thingsboard.server.service.entitiy.alarm.TbAlarmCommentService; import org.thingsboard.server.service.subscription.TbSubscriptionUtils; import java.util.Collection; +import java.util.List; /** * Created by ashvayka on 27.03.18. @@ -235,6 +237,11 @@ public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService }); } + @Override + public ListenableFuture> findAlarmTypesByTenantId(TenantId tenantId) { + return alarmService.findAlarmTypesByTenantId(tenantId); + } + private void onAlarmUpdated(AlarmApiCallResult result) { wsCallBackExecutor.submit(() -> { AlarmInfo alarm = result.getAlarm(); diff --git a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java index 05030f0091..7e2e3d4d15 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java @@ -31,6 +31,7 @@ import org.springframework.context.annotation.Primary; import org.springframework.test.context.ContextConfiguration; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmInfo; @@ -42,8 +43,12 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.dao.alarm.AlarmDao; import org.thingsboard.server.dao.service.DaoSqlTest; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.stream.Collectors; import static org.hamcrest.Matchers.containsString; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -691,4 +696,27 @@ public class AlarmControllerTest extends AbstractControllerTest { doPost("/api/alarm", alarm).andExpect(status().isForbidden()); } + @Test + public void testGetAlarmTypes() throws Exception { + loginTenantAdmin(); + + Mockito.reset(tbClusterService, auditLogService); + + List types = new ArrayList<>(); + + for (int i = 1; i < 13; i++) { + types.add(createAlarm(TEST_ALARM_TYPE + i).getType()); + } + + List foundTypes = doGetTyped("/api/alarm/types", new TypeReference>() {}) + .stream() + .map(EntitySubtype::getType) + .collect(Collectors.toList()); + + Collections.sort(types); + Collections.sort(foundTypes); + + Assert.assertEquals(types, foundTypes); + } + } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java index fbf8892bd5..89feae53b8 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.alarm; import com.fasterxml.jackson.databind.JsonNode; import com.google.common.util.concurrent.ListenableFuture; +import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmApiCallResult; import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest; @@ -39,6 +40,7 @@ import org.thingsboard.server.common.data.query.AlarmDataQuery; import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.Collection; +import java.util.List; public interface AlarmService extends EntityDaoService { @@ -121,4 +123,6 @@ public interface AlarmService extends EntityDaoService { void deleteEntityAlarmRelations(TenantId tenantId, EntityId entityId); long countAlarmsByQuery(TenantId tenantId, CustomerId customerId, AlarmCountQuery query); + + ListenableFuture> findAlarmTypesByTenantId(TenantId tenantId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java b/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java index 63b13bca66..4b407cb669 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java +++ b/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java @@ -18,6 +18,9 @@ package org.thingsboard.server.dao; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.thingsboard.server.common.data.EntitySubtype; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UUIDBased; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; @@ -142,4 +145,15 @@ public abstract class DaoUtil { return null; } } + + public static List convertTenantEntityTypesToDto(UUID tenantId, EntityType entityType, List types) { + List list = Collections.emptyList(); + if (types != null && !types.isEmpty()) { + list = new ArrayList<>(); + for (String type : types) { + list.add(new EntitySubtype(TenantId.fromUUID(tenantId), entityType, type)); + } + } + return list; + } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java index 745861c6c8..df680bada0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.alarm; import com.fasterxml.jackson.databind.JsonNode; import com.google.common.util.concurrent.ListenableFuture; +import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmApiCallResult; import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest; @@ -97,4 +98,6 @@ public interface AlarmDao extends Dao { long countAlarmsByQuery(TenantId tenantId, CustomerId customerId, AlarmCountQuery query); + ListenableFuture> findTenantAlarmTypesAsync(UUID tenantId); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java index 96342aca2f..f40be0378d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java @@ -20,11 +20,13 @@ import com.fasterxml.jackson.databind.JsonNode; import com.google.common.base.Function; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; +import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmApiCallResult; @@ -64,6 +66,7 @@ import org.thingsboard.server.dao.tenant.TenantService; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; @@ -376,6 +379,18 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ return alarmDao.countAlarmsByQuery(tenantId, customerId, query); } + @Override + public ListenableFuture> findAlarmTypesByTenantId(TenantId tenantId) { + log.trace("Executing findAlarmTypesByTenantId, tenantId [{}]", tenantId); + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); + ListenableFuture> tenantAssetTypes = alarmDao.findTenantAlarmTypesAsync(tenantId.getId()); + return Futures.transform(tenantAssetTypes, + assetTypes -> { + assetTypes.sort(Comparator.comparing(EntitySubtype::getType)); + return assetTypes; + }, MoreExecutors.directExecutor()); + } + private Alarm merge(Alarm existing, Alarm alarm) { if (alarm.getStartTs() > existing.getEndTs()) { existing.setEndTs(alarm.getStartTs()); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java index 92537dc850..81d9068f11 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java @@ -345,4 +345,7 @@ public interface AlarmRepository extends JpaRepository { @Query(value = "SELECT unassign_alarm(:t_id, :a_id, :a_ts)", nativeQuery = true) String unassignAlarm(@Param("t_id") UUID tenantId, @Param("a_id") UUID alarmId, @Param("a_ts") long unassignTime); + + @Query("SELECT DISTINCT a.type FROM AlarmEntity a WHERE a.tenantId = :tenantId") + List findTenantAlarmTypes(@Param("tenantId") UUID tenantId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java index 8dfdaf8a3e..d721996e0b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java @@ -24,6 +24,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.alarm.Alarm; @@ -67,6 +68,8 @@ import java.util.Optional; import java.util.Set; import java.util.UUID; +import static org.thingsboard.server.dao.DaoUtil.convertTenantEntityTypesToDto; + /** * Created by Valerii Sosliuk on 5/19/2017. */ @@ -366,6 +369,11 @@ public class JpaAlarmDao extends JpaAbstractDao implements A return alarmQueryRepository.countAlarmsByQuery(tenantId, customerId, query); } + @Override + public ListenableFuture> findTenantAlarmTypesAsync(UUID tenantId) { + return service.submit(() -> convertTenantEntityTypesToDto(tenantId, EntityType.ALARM, alarmRepository.findTenantAlarmTypes(tenantId))); + } + private static String getPropagationTypes(AlarmPropagationInfo ap) { String propagateRelationTypes; if (!CollectionUtils.isEmpty(ap.getPropagateRelationTypes())) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java index ec5a8318f8..4c83815d19 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java @@ -37,14 +37,13 @@ import org.thingsboard.server.dao.model.sql.AssetInfoEntity; import org.thingsboard.server.dao.sql.JpaAbstractDao; import org.thingsboard.server.dao.util.SqlDao; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.UUID; +import static org.thingsboard.server.dao.DaoUtil.convertTenantEntityTypesToDto; import static org.thingsboard.server.dao.asset.BaseAssetService.TB_SERVICE_QUEUE; /** @@ -194,7 +193,7 @@ public class JpaAssetDao extends JpaAbstractDao implements A @Override public ListenableFuture> findTenantAssetTypesAsync(UUID tenantId) { - return service.submit(() -> convertTenantAssetTypesToDto(tenantId, assetRepository.findTenantAssetTypes(tenantId))); + return service.submit(() -> convertTenantEntityTypesToDto(tenantId, EntityType.ASSET, assetRepository.findTenantAssetTypes(tenantId))); } @Override @@ -212,17 +211,6 @@ public class JpaAssetDao extends JpaAbstractDao implements A DaoUtil.toPageable(pageLink))); } - private List convertTenantAssetTypesToDto(UUID tenantId, List types) { - List list = Collections.emptyList(); - if (types != null && !types.isEmpty()) { - list = new ArrayList<>(); - for (String type : types) { - list.add(new EntitySubtype(TenantId.fromUUID(tenantId), EntityType.ASSET, type)); - } - } - return list; - } - @Override public PageData findAssetsByTenantIdAndEdgeId(UUID tenantId, UUID edgeId, PageLink pageLink) { log.debug("Try to find assets by tenantId [{}], edgeId [{}] and pageLink [{}]", tenantId, edgeId, pageLink); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java index d1ea342bd2..9b63e945ea 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java @@ -43,13 +43,13 @@ import org.thingsboard.server.dao.model.sql.DeviceEntity; import org.thingsboard.server.dao.sql.JpaAbstractDao; import org.thingsboard.server.dao.util.SqlDao; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.UUID; +import static org.thingsboard.server.dao.DaoUtil.convertTenantEntityTypesToDto; + /** * Created by Valerii Sosliuk on 5/6/2017. */ @@ -217,7 +217,7 @@ public class JpaDeviceDao extends JpaAbstractDao implement @Override public ListenableFuture> findTenantDeviceTypesAsync(UUID tenantId) { - return service.submit(() -> convertTenantDeviceTypesToDto(tenantId, deviceRepository.findTenantDeviceTypes(tenantId))); + return service.submit(() -> convertTenantEntityTypesToDto(tenantId, EntityType.DEVICE, deviceRepository.findTenantDeviceTypes(tenantId))); } @Override @@ -240,17 +240,6 @@ public class JpaDeviceDao extends JpaAbstractDao implement return deviceRepository.countByTenantId(tenantId.getId()); } - private List convertTenantDeviceTypesToDto(UUID tenantId, List types) { - List list = Collections.emptyList(); - if (types != null && !types.isEmpty()) { - list = new ArrayList<>(); - for (String type : types) { - list.add(new EntitySubtype(TenantId.fromUUID(tenantId), EntityType.DEVICE, type)); - } - } - return list; - } - @Override public PageData findDevicesByTenantIdAndEdgeId(UUID tenantId, UUID edgeId, PageLink pageLink) { log.debug("Try to find devices by tenantId [{}], edgeId [{}] and pageLink [{}]", tenantId, edgeId, pageLink); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaEdgeDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaEdgeDao.java index c40ca2ca6d..29a9719b7d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaEdgeDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaEdgeDao.java @@ -34,13 +34,13 @@ import org.thingsboard.server.dao.model.sql.EdgeInfoEntity; import org.thingsboard.server.dao.sql.JpaAbstractDao; import org.thingsboard.server.dao.util.SqlDao; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.UUID; +import static org.thingsboard.server.dao.DaoUtil.convertTenantEntityTypesToDto; + @Component @Slf4j @SqlDao @@ -144,7 +144,7 @@ public class JpaEdgeDao extends JpaAbstractDao implements Edge @Override public ListenableFuture> findTenantEdgeTypesAsync(UUID tenantId) { - return service.submit(() -> convertTenantEdgeTypesToDto(tenantId, edgeRepository.findTenantEdgeTypes(tenantId))); + return service.submit(() -> convertTenantEntityTypesToDto(tenantId, EntityType.EDGE, edgeRepository.findTenantEdgeTypes(tenantId))); } @Override @@ -184,17 +184,6 @@ public class JpaEdgeDao extends JpaAbstractDao implements Edge DaoUtil.toPageable(pageLink))); } - private List convertTenantEdgeTypesToDto(UUID tenantId, List types) { - List list = Collections.emptyList(); - if (types != null && !types.isEmpty()) { - list = new ArrayList<>(); - for (String type : types) { - list.add(new EntitySubtype(TenantId.fromUUID(tenantId), EntityType.EDGE, type)); - } - } - return list; - } - @Override public EntityType getEntityType() { return EntityType.EDGE; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java index f3f82d34da..e3e9edf80d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java @@ -35,13 +35,13 @@ import org.thingsboard.server.dao.model.sql.EntityViewInfoEntity; import org.thingsboard.server.dao.sql.JpaAbstractDao; import org.thingsboard.server.dao.util.SqlDao; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.UUID; +import static org.thingsboard.server.dao.DaoUtil.convertTenantEntityTypesToDto; + /** * Created by Victor Basanets on 8/31/2017. */ @@ -167,18 +167,7 @@ public class JpaEntityViewDao extends JpaAbstractDao> findTenantEntityViewTypesAsync(UUID tenantId) { - return service.submit(() -> convertTenantEntityViewTypesToDto(tenantId, entityViewRepository.findTenantEntityViewTypes(tenantId))); - } - - private List convertTenantEntityViewTypesToDto(UUID tenantId, List types) { - List list = Collections.emptyList(); - if (types != null && !types.isEmpty()) { - list = new ArrayList<>(); - for (String type : types) { - list.add(new EntitySubtype(TenantId.fromUUID(tenantId), EntityType.ENTITY_VIEW, type)); - } - } - return list; + return service.submit(() -> convertTenantEntityTypesToDto(tenantId, EntityType.ENTITY_VIEW, entityViewRepository.findTenantEntityViewTypes(tenantId))); } @Override diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java index 51eb446d70..635d5357b2 100644 --- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java +++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java @@ -499,6 +499,15 @@ public class RestClient implements Closeable { return restTemplate.postForEntity(baseURL + "/api/alarm", alarm, Alarm.class).getBody(); } + public List getAlarmTypes() { + return restTemplate.exchange( + baseURL + "/api/alarm/types", + HttpMethod.GET, + HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }).getBody(); + } + public AlarmComment saveAlarmComment(AlarmId alarmId, AlarmComment alarmComment) { return restTemplate.postForEntity(baseURL + "/api/alarm/{alarmId}/comment", alarmComment, AlarmComment.class, alarmId.getId()).getBody(); } diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleEngineAlarmService.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleEngineAlarmService.java index 05e9bf164f..ce069a92bb 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleEngineAlarmService.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleEngineAlarmService.java @@ -18,6 +18,7 @@ package org.thingsboard.rule.engine.api; import com.fasterxml.jackson.databind.JsonNode; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmApiCallResult; import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest; @@ -39,6 +40,7 @@ import org.thingsboard.server.common.data.query.AlarmDataQuery; import org.thingsboard.server.dao.alarm.AlarmOperationResult; import java.util.Collection; +import java.util.List; /** * Created by ashvayka on 02.04.18. @@ -110,4 +112,6 @@ public interface RuleEngineAlarmService { AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, AlarmStatus alarmStatus, String assigneeId); PageData findAlarmDataByQueryForEntities(TenantId tenantId, AlarmDataQuery query, Collection orderedEntityIds); + + ListenableFuture> findAlarmTypesByTenantId(TenantId tenantId); } diff --git a/ui-ngx/src/app/core/http/alarm.service.ts b/ui-ngx/src/app/core/http/alarm.service.ts index e03e9ab783..f81a7b17e6 100644 --- a/ui-ngx/src/app/core/http/alarm.service.ts +++ b/ui-ngx/src/app/core/http/alarm.service.ts @@ -29,6 +29,7 @@ import { AlarmStatus } from '@shared/models/alarm.models'; import { UtilsService } from '@core/services/utils.service'; +import { EntitySubtype } from "@shared/models/entity-type.models"; @Injectable({ providedIn: 'root' @@ -108,4 +109,8 @@ export class AlarmService { defaultHttpOptionsFromConfig(config)); } + public getAlarmTypes(config?: RequestConfig): Observable> { + return this.http.get>('/api/alarm/types', defaultHttpOptionsFromConfig(config)); + } + } diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.html b/ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.html index a2a0c158a5..21c2688da6 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.html +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.html @@ -72,21 +72,8 @@
- - alarm.alarm-type-list - - - {{type}} - cancel - - - - + +
diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.ts b/ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.ts index b46fbf506c..9594042e03 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.ts @@ -42,6 +42,7 @@ import { import { MatChipInputEvent } from '@angular/material/chips'; import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; import { TranslateService } from '@ngx-translate/core'; +import { EntityType } from "@shared/models/entity-type.models"; export const ALARM_FILTER_CONFIG_DATA = new InjectionToken('AlarmFilterConfigData'); @@ -107,6 +108,8 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal panelResult: AlarmFilterConfig = null; + entityType = EntityType; + private alarmFilterConfig: AlarmFilterConfig; private propagateChange = (_: any) => {}; @@ -240,36 +243,6 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal return this.alarmFilterConfigForm.get('typeList').value; } - public removeAlarmType(type: string): void { - const types: string[] = this.alarmFilterConfigForm.get('typeList').value; - const index = types.indexOf(type); - if (index >= 0) { - types.splice(index, 1); - this.alarmFilterConfigForm.get('typeList').setValue(types); - this.alarmFilterConfigForm.get('typeList').markAsDirty(); - } - } - - public addAlarmType(event: MatChipInputEvent): void { - const input = event.chipInput.inputElement; - const value = event.value; - - let types: string[] = this.alarmFilterConfigForm.get('typeList').value; - - if ((value || '').trim()) { - if (!types) { - types = []; - } - types.push(value.trim()); - this.alarmFilterConfigForm.get('typeList').setValue(types); - this.alarmFilterConfigForm.get('typeList').markAsDirty(); - } - - if (input) { - input.value = ''; - } - } - private updateAlarmConfigForm(alarmFilterConfig?: AlarmFilterConfig) { this.alarmFilterConfigForm.patchValue({ statusList: alarmFilterConfig?.statusList, diff --git a/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts b/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts index 1442b44cfd..bc416010c9 100644 --- a/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts +++ b/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts @@ -31,6 +31,7 @@ import { EdgeService } from '@core/http/edge.service'; import { EntityViewService } from '@core/http/entity-view.service'; import { BroadcastService } from '@core/services/broadcast.service'; import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; +import { AlarmService } from "@core/http/alarm.service"; @Component({ selector: 'tb-entity-subtype-list', @@ -102,6 +103,7 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, private deviceService: DeviceService, private edgeService: EdgeService, private entityViewService: EntityViewService, + private alarmService: AlarmService, private fb: UntypedFormBuilder) { this.entitySubtypeListFormGroup = this.fb.group({ entitySubtypeList: [this.entitySubtypeList, this.required ? [Validators.required] : []], @@ -164,6 +166,16 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, this.entitySubtypes = null; }); break; + case EntityType.ALARM: + this.placeholder = this.required ? this.translate.instant('alarm.enter-alarm-type') + : this.translate.instant('alarm.any-type'); + this.secondaryPlaceholder = '+' + this.translate.instant('alarm.alarm-type'); + this.noSubtypesMathingText = 'alarm.no-alarm-types-matching'; + this.subtypeListEmptyText = 'alarm.alarm-type-list-empty'; + this.broadcastSubscription = this.broadcast.on('alarmSaved', () => { + this.entitySubtypes = null; + }); + break; } this.filteredEntitySubtypeList = this.entitySubtypeListFormGroup.get('entitySubtype').valueChanges @@ -283,6 +295,9 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, case EntityType.ENTITY_VIEW: subTypesObservable = this.entityViewService.getEntityViewTypes({ignoreLoading: true}); break; + case EntityType.ALARM: + subTypesObservable = this.alarmService.getAlarmTypes({ignoreLoading: true}); + break; } if (subTypesObservable) { this.entitySubtypes = subTypesObservable.pipe( diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 341408a615..35a472f853 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -535,7 +535,11 @@ "search-propagated-alarms": "Search propagated alarms", "comments": "Alarm comments", "show-more": "Show more", - "additional-info": "Additional info" + "additional-info": "Additional info", + "alarm-type": "Alarm type", + "enter-alarm-type": "Enter alarm type", + "no-alarm-types-matching": "No alarm types matching '{{entitySubtype}}' were found.", + "alarm-type-list-empty": "No alarm types selected." }, "alarm-activity": { "add": "Add a comment...",