Browse Source

implemented alarm types api

pull/8825/head
YevhenBondarenko 3 years ago
parent
commit
2d22e8e8a8
  1. 12
      application/src/main/java/org/thingsboard/server/controller/AlarmController.java
  2. 7
      application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java
  3. 28
      application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java
  4. 4
      common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java
  5. 14
      dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java
  6. 3
      dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java
  7. 15
      dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java
  8. 3
      dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java
  9. 8
      dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java
  10. 16
      dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java
  11. 17
      dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java
  12. 17
      dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaEdgeDao.java
  13. 17
      dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java
  14. 9
      rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java
  15. 4
      rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleEngineAlarmService.java
  16. 5
      ui-ngx/src/app/core/http/alarm.service.ts
  17. 17
      ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.html
  18. 33
      ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.ts
  19. 15
      ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts
  20. 6
      ui-ngx/src/assets/locale/locale.constant-en_US.json

12
application/src/main/java/org/thingsboard/server/controller/AlarmController.java

@ -15,6 +15,7 @@
*/ */
package org.thingsboard.server.controller; package org.thingsboard.server.controller;
import com.google.common.util.concurrent.ListenableFuture;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor; 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.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController; 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.StringUtils;
import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmInfo;
@ -498,4 +500,14 @@ public class AlarmController extends BaseController {
alarmStatus, assigneeId); 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<EntitySubtype> getAlarmTypes() throws ThingsboardException, ExecutionException, InterruptedException {
ListenableFuture<List<EntitySubtype>> alarmTypes = alarmService.findAlarmTypesByTenantId(getTenantId());
return checkNotNull(alarmTypes.get());
}
} }

7
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.springframework.stereotype.Service;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.ApiUsageRecordKey; 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.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmApiCallResult; import org.thingsboard.server.common.data.alarm.AlarmApiCallResult;
import org.thingsboard.server.common.data.alarm.AlarmComment; 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 org.thingsboard.server.service.subscription.TbSubscriptionUtils;
import java.util.Collection; import java.util.Collection;
import java.util.List;
/** /**
* Created by ashvayka on 27.03.18. * Created by ashvayka on 27.03.18.
@ -235,6 +237,11 @@ public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService
}); });
} }
@Override
public ListenableFuture<List<EntitySubtype>> findAlarmTypesByTenantId(TenantId tenantId) {
return alarmService.findAlarmTypesByTenantId(tenantId);
}
private void onAlarmUpdated(AlarmApiCallResult result) { private void onAlarmUpdated(AlarmApiCallResult result) {
wsCallBackExecutor.submit(() -> { wsCallBackExecutor.submit(() -> {
AlarmInfo alarm = result.getAlarm(); AlarmInfo alarm = result.getAlarm();

28
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.springframework.test.context.ContextConfiguration;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.Device; 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.EntityType;
import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmInfo; 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.alarm.AlarmDao;
import org.thingsboard.server.dao.service.DaoSqlTest; 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.LinkedList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 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()); doPost("/api/alarm", alarm).andExpect(status().isForbidden());
} }
@Test
public void testGetAlarmTypes() throws Exception {
loginTenantAdmin();
Mockito.reset(tbClusterService, auditLogService);
List<String> types = new ArrayList<>();
for (int i = 1; i < 13; i++) {
types.add(createAlarm(TEST_ALARM_TYPE + i).getType());
}
List<String> foundTypes = doGetTyped("/api/alarm/types", new TypeReference<List<EntitySubtype>>() {})
.stream()
.map(EntitySubtype::getType)
.collect(Collectors.toList());
Collections.sort(types);
Collections.sort(foundTypes);
Assert.assertEquals(types, foundTypes);
}
} }

4
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.fasterxml.jackson.databind.JsonNode;
import com.google.common.util.concurrent.ListenableFuture; 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.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmApiCallResult; import org.thingsboard.server.common.data.alarm.AlarmApiCallResult;
import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest; 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 org.thingsboard.server.dao.entity.EntityDaoService;
import java.util.Collection; import java.util.Collection;
import java.util.List;
public interface AlarmService extends EntityDaoService { public interface AlarmService extends EntityDaoService {
@ -121,4 +123,6 @@ public interface AlarmService extends EntityDaoService {
void deleteEntityAlarmRelations(TenantId tenantId, EntityId entityId); void deleteEntityAlarmRelations(TenantId tenantId, EntityId entityId);
long countAlarmsByQuery(TenantId tenantId, CustomerId customerId, AlarmCountQuery query); long countAlarmsByQuery(TenantId tenantId, CustomerId customerId, AlarmCountQuery query);
ListenableFuture<List<EntitySubtype>> findAlarmTypesByTenantId(TenantId tenantId);
} }

14
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.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; 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.id.UUIDBased;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
@ -142,4 +145,15 @@ public abstract class DaoUtil {
return null; return null;
} }
} }
public static List<EntitySubtype> convertTenantEntityTypesToDto(UUID tenantId, EntityType entityType, List<String> types) {
List<EntitySubtype> 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;
}
} }

3
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.fasterxml.jackson.databind.JsonNode;
import com.google.common.util.concurrent.ListenableFuture; 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.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmApiCallResult; import org.thingsboard.server.common.data.alarm.AlarmApiCallResult;
import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest; import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest;
@ -97,4 +98,6 @@ public interface AlarmDao extends Dao<Alarm> {
long countAlarmsByQuery(TenantId tenantId, CustomerId customerId, AlarmCountQuery query); long countAlarmsByQuery(TenantId tenantId, CustomerId customerId, AlarmCountQuery query);
ListenableFuture<List<EntitySubtype>> findTenantAlarmTypesAsync(UUID tenantId);
} }

15
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.base.Function;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; 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.EntityType;
import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmApiCallResult; 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.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -376,6 +379,18 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
return alarmDao.countAlarmsByQuery(tenantId, customerId, query); return alarmDao.countAlarmsByQuery(tenantId, customerId, query);
} }
@Override
public ListenableFuture<List<EntitySubtype>> findAlarmTypesByTenantId(TenantId tenantId) {
log.trace("Executing findAlarmTypesByTenantId, tenantId [{}]", tenantId);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
ListenableFuture<List<EntitySubtype>> 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) { private Alarm merge(Alarm existing, Alarm alarm) {
if (alarm.getStartTs() > existing.getEndTs()) { if (alarm.getStartTs() > existing.getEndTs()) {
existing.setEndTs(alarm.getStartTs()); existing.setEndTs(alarm.getStartTs());

3
dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java

@ -345,4 +345,7 @@ public interface AlarmRepository extends JpaRepository<AlarmEntity, UUID> {
@Query(value = "SELECT unassign_alarm(:t_id, :a_id, :a_ts)", nativeQuery = true) @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); 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<String> findTenantAlarmTypes(@Param("tenantId") UUID tenantId);
} }

8
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.stereotype.Component;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.thingsboard.common.util.JacksonUtil; 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.EntityType;
import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.Alarm;
@ -67,6 +68,8 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import static org.thingsboard.server.dao.DaoUtil.convertTenantEntityTypesToDto;
/** /**
* Created by Valerii Sosliuk on 5/19/2017. * Created by Valerii Sosliuk on 5/19/2017.
*/ */
@ -366,6 +369,11 @@ public class JpaAlarmDao extends JpaAbstractDao<AlarmEntity, Alarm> implements A
return alarmQueryRepository.countAlarmsByQuery(tenantId, customerId, query); return alarmQueryRepository.countAlarmsByQuery(tenantId, customerId, query);
} }
@Override
public ListenableFuture<List<EntitySubtype>> findTenantAlarmTypesAsync(UUID tenantId) {
return service.submit(() -> convertTenantEntityTypesToDto(tenantId, EntityType.ALARM, alarmRepository.findTenantAlarmTypes(tenantId)));
}
private static String getPropagationTypes(AlarmPropagationInfo ap) { private static String getPropagationTypes(AlarmPropagationInfo ap) {
String propagateRelationTypes; String propagateRelationTypes;
if (!CollectionUtils.isEmpty(ap.getPropagateRelationTypes())) { if (!CollectionUtils.isEmpty(ap.getPropagateRelationTypes())) {

16
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.sql.JpaAbstractDao;
import org.thingsboard.server.dao.util.SqlDao; import org.thingsboard.server.dao.util.SqlDao;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import static org.thingsboard.server.dao.DaoUtil.convertTenantEntityTypesToDto;
import static org.thingsboard.server.dao.asset.BaseAssetService.TB_SERVICE_QUEUE; import static org.thingsboard.server.dao.asset.BaseAssetService.TB_SERVICE_QUEUE;
/** /**
@ -194,7 +193,7 @@ public class JpaAssetDao extends JpaAbstractDao<AssetEntity, Asset> implements A
@Override @Override
public ListenableFuture<List<EntitySubtype>> findTenantAssetTypesAsync(UUID tenantId) { public ListenableFuture<List<EntitySubtype>> findTenantAssetTypesAsync(UUID tenantId) {
return service.submit(() -> convertTenantAssetTypesToDto(tenantId, assetRepository.findTenantAssetTypes(tenantId))); return service.submit(() -> convertTenantEntityTypesToDto(tenantId, EntityType.ASSET, assetRepository.findTenantAssetTypes(tenantId)));
} }
@Override @Override
@ -212,17 +211,6 @@ public class JpaAssetDao extends JpaAbstractDao<AssetEntity, Asset> implements A
DaoUtil.toPageable(pageLink))); DaoUtil.toPageable(pageLink)));
} }
private List<EntitySubtype> convertTenantAssetTypesToDto(UUID tenantId, List<String> types) {
List<EntitySubtype> 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 @Override
public PageData<Asset> findAssetsByTenantIdAndEdgeId(UUID tenantId, UUID edgeId, PageLink pageLink) { public PageData<Asset> findAssetsByTenantIdAndEdgeId(UUID tenantId, UUID edgeId, PageLink pageLink) {
log.debug("Try to find assets by tenantId [{}], edgeId [{}] and pageLink [{}]", tenantId, edgeId, pageLink); log.debug("Try to find assets by tenantId [{}], edgeId [{}] and pageLink [{}]", tenantId, edgeId, pageLink);

17
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.sql.JpaAbstractDao;
import org.thingsboard.server.dao.util.SqlDao; import org.thingsboard.server.dao.util.SqlDao;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import static org.thingsboard.server.dao.DaoUtil.convertTenantEntityTypesToDto;
/** /**
* Created by Valerii Sosliuk on 5/6/2017. * Created by Valerii Sosliuk on 5/6/2017.
*/ */
@ -217,7 +217,7 @@ public class JpaDeviceDao extends JpaAbstractDao<DeviceEntity, Device> implement
@Override @Override
public ListenableFuture<List<EntitySubtype>> findTenantDeviceTypesAsync(UUID tenantId) { public ListenableFuture<List<EntitySubtype>> findTenantDeviceTypesAsync(UUID tenantId) {
return service.submit(() -> convertTenantDeviceTypesToDto(tenantId, deviceRepository.findTenantDeviceTypes(tenantId))); return service.submit(() -> convertTenantEntityTypesToDto(tenantId, EntityType.DEVICE, deviceRepository.findTenantDeviceTypes(tenantId)));
} }
@Override @Override
@ -240,17 +240,6 @@ public class JpaDeviceDao extends JpaAbstractDao<DeviceEntity, Device> implement
return deviceRepository.countByTenantId(tenantId.getId()); return deviceRepository.countByTenantId(tenantId.getId());
} }
private List<EntitySubtype> convertTenantDeviceTypesToDto(UUID tenantId, List<String> types) {
List<EntitySubtype> 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 @Override
public PageData<Device> findDevicesByTenantIdAndEdgeId(UUID tenantId, UUID edgeId, PageLink pageLink) { public PageData<Device> findDevicesByTenantIdAndEdgeId(UUID tenantId, UUID edgeId, PageLink pageLink) {
log.debug("Try to find devices by tenantId [{}], edgeId [{}] and pageLink [{}]", tenantId, edgeId, pageLink); log.debug("Try to find devices by tenantId [{}], edgeId [{}] and pageLink [{}]", tenantId, edgeId, pageLink);

17
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.sql.JpaAbstractDao;
import org.thingsboard.server.dao.util.SqlDao; import org.thingsboard.server.dao.util.SqlDao;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import static org.thingsboard.server.dao.DaoUtil.convertTenantEntityTypesToDto;
@Component @Component
@Slf4j @Slf4j
@SqlDao @SqlDao
@ -144,7 +144,7 @@ public class JpaEdgeDao extends JpaAbstractDao<EdgeEntity, Edge> implements Edge
@Override @Override
public ListenableFuture<List<EntitySubtype>> findTenantEdgeTypesAsync(UUID tenantId) { public ListenableFuture<List<EntitySubtype>> findTenantEdgeTypesAsync(UUID tenantId) {
return service.submit(() -> convertTenantEdgeTypesToDto(tenantId, edgeRepository.findTenantEdgeTypes(tenantId))); return service.submit(() -> convertTenantEntityTypesToDto(tenantId, EntityType.EDGE, edgeRepository.findTenantEdgeTypes(tenantId)));
} }
@Override @Override
@ -184,17 +184,6 @@ public class JpaEdgeDao extends JpaAbstractDao<EdgeEntity, Edge> implements Edge
DaoUtil.toPageable(pageLink))); DaoUtil.toPageable(pageLink)));
} }
private List<EntitySubtype> convertTenantEdgeTypesToDto(UUID tenantId, List<String> types) {
List<EntitySubtype> 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 @Override
public EntityType getEntityType() { public EntityType getEntityType() {
return EntityType.EDGE; return EntityType.EDGE;

17
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.sql.JpaAbstractDao;
import org.thingsboard.server.dao.util.SqlDao; import org.thingsboard.server.dao.util.SqlDao;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import static org.thingsboard.server.dao.DaoUtil.convertTenantEntityTypesToDto;
/** /**
* Created by Victor Basanets on 8/31/2017. * Created by Victor Basanets on 8/31/2017.
*/ */
@ -167,18 +167,7 @@ public class JpaEntityViewDao extends JpaAbstractDao<EntityViewEntity, EntityVie
@Override @Override
public ListenableFuture<List<EntitySubtype>> findTenantEntityViewTypesAsync(UUID tenantId) { public ListenableFuture<List<EntitySubtype>> findTenantEntityViewTypesAsync(UUID tenantId) {
return service.submit(() -> convertTenantEntityViewTypesToDto(tenantId, entityViewRepository.findTenantEntityViewTypes(tenantId))); return service.submit(() -> convertTenantEntityTypesToDto(tenantId, EntityType.ENTITY_VIEW, entityViewRepository.findTenantEntityViewTypes(tenantId)));
}
private List<EntitySubtype> convertTenantEntityViewTypesToDto(UUID tenantId, List<String> types) {
List<EntitySubtype> 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;
} }
@Override @Override

9
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(); return restTemplate.postForEntity(baseURL + "/api/alarm", alarm, Alarm.class).getBody();
} }
public List<EntitySubtype> getAlarmTypes() {
return restTemplate.exchange(
baseURL + "/api/alarm/types",
HttpMethod.GET,
HttpEntity.EMPTY,
new ParameterizedTypeReference<List<EntitySubtype>>() {
}).getBody();
}
public AlarmComment saveAlarmComment(AlarmId alarmId, AlarmComment alarmComment) { public AlarmComment saveAlarmComment(AlarmId alarmId, AlarmComment alarmComment) {
return restTemplate.postForEntity(baseURL + "/api/alarm/{alarmId}/comment", alarmComment, AlarmComment.class, alarmId.getId()).getBody(); return restTemplate.postForEntity(baseURL + "/api/alarm/{alarmId}/comment", alarmComment, AlarmComment.class, alarmId.getId()).getBody();
} }

4
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.fasterxml.jackson.databind.JsonNode;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; 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.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmApiCallResult; import org.thingsboard.server.common.data.alarm.AlarmApiCallResult;
import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest; 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 org.thingsboard.server.dao.alarm.AlarmOperationResult;
import java.util.Collection; import java.util.Collection;
import java.util.List;
/** /**
* Created by ashvayka on 02.04.18. * 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); AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, AlarmStatus alarmStatus, String assigneeId);
PageData<AlarmData> findAlarmDataByQueryForEntities(TenantId tenantId, AlarmDataQuery query, Collection<EntityId> orderedEntityIds); PageData<AlarmData> findAlarmDataByQueryForEntities(TenantId tenantId, AlarmDataQuery query, Collection<EntityId> orderedEntityIds);
ListenableFuture<List<EntitySubtype>> findAlarmTypesByTenantId(TenantId tenantId);
} }

5
ui-ngx/src/app/core/http/alarm.service.ts

@ -29,6 +29,7 @@ import {
AlarmStatus AlarmStatus
} from '@shared/models/alarm.models'; } from '@shared/models/alarm.models';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
import { EntitySubtype } from "@shared/models/entity-type.models";
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -108,4 +109,8 @@ export class AlarmService {
defaultHttpOptionsFromConfig(config)); defaultHttpOptionsFromConfig(config));
} }
public getAlarmTypes(config?: RequestConfig): Observable<Array<EntitySubtype>> {
return this.http.get<Array<EntitySubtype>>('/api/alarm/types', defaultHttpOptionsFromConfig(config));
}
} }

17
ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.html

@ -72,21 +72,8 @@
</div> </div>
<div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start start" <div fxLayout="column" fxLayoutAlign="center" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start start"
fxLayoutGap.gt-xs="8px"> fxLayoutGap.gt-xs="8px">
<mat-form-field fxFlex class="mat-block" floatLabel="always"> <tb-entity-subtype-list fxFlex class="mat-block" floatLabel="always" [entityType]="entityType.ALARM" formControlName="typeList">
<mat-label translate>alarm.alarm-type-list</mat-label> </tb-entity-subtype-list>
<mat-chip-grid #alarmTypeChipList formControlName="typeList">
<mat-chip-row *ngFor="let type of alarmTypeList()"
[removable]="true" (removed)="removeAlarmType(type)">
{{type}}
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip-row>
<input placeholder="{{ !alarmFilterConfigForm.get('typeList').value?.length ? ('alarm.any-type' | translate) : '' }}"
[matChipInputFor]="alarmTypeChipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
matChipInputAddOnBlur
(matChipInputTokenEnd)="addAlarmType($event)">
</mat-chip-grid>
</mat-form-field>
</div> </div>
<div fxLayout="column" fxLayoutGap="16px"> <div fxLayout="column" fxLayoutGap="16px">
<mat-slide-toggle *ngIf="propagatedFilter" formControlName="searchPropagatedAlarms"> <mat-slide-toggle *ngIf="propagatedFilter" formControlName="searchPropagatedAlarms">

33
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 { MatChipInputEvent } from '@angular/material/chips';
import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { EntityType } from "@shared/models/entity-type.models";
export const ALARM_FILTER_CONFIG_DATA = new InjectionToken<any>('AlarmFilterConfigData'); export const ALARM_FILTER_CONFIG_DATA = new InjectionToken<any>('AlarmFilterConfigData');
@ -107,6 +108,8 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
panelResult: AlarmFilterConfig = null; panelResult: AlarmFilterConfig = null;
entityType = EntityType;
private alarmFilterConfig: AlarmFilterConfig; private alarmFilterConfig: AlarmFilterConfig;
private propagateChange = (_: any) => {}; private propagateChange = (_: any) => {};
@ -240,36 +243,6 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
return this.alarmFilterConfigForm.get('typeList').value; 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) { private updateAlarmConfigForm(alarmFilterConfig?: AlarmFilterConfig) {
this.alarmFilterConfigForm.patchValue({ this.alarmFilterConfigForm.patchValue({
statusList: alarmFilterConfig?.statusList, statusList: alarmFilterConfig?.statusList,

15
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 { EntityViewService } from '@core/http/entity-view.service';
import { BroadcastService } from '@core/services/broadcast.service'; import { BroadcastService } from '@core/services/broadcast.service';
import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes';
import { AlarmService } from "@core/http/alarm.service";
@Component({ @Component({
selector: 'tb-entity-subtype-list', selector: 'tb-entity-subtype-list',
@ -102,6 +103,7 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit,
private deviceService: DeviceService, private deviceService: DeviceService,
private edgeService: EdgeService, private edgeService: EdgeService,
private entityViewService: EntityViewService, private entityViewService: EntityViewService,
private alarmService: AlarmService,
private fb: UntypedFormBuilder) { private fb: UntypedFormBuilder) {
this.entitySubtypeListFormGroup = this.fb.group({ this.entitySubtypeListFormGroup = this.fb.group({
entitySubtypeList: [this.entitySubtypeList, this.required ? [Validators.required] : []], entitySubtypeList: [this.entitySubtypeList, this.required ? [Validators.required] : []],
@ -164,6 +166,16 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit,
this.entitySubtypes = null; this.entitySubtypes = null;
}); });
break; 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 this.filteredEntitySubtypeList = this.entitySubtypeListFormGroup.get('entitySubtype').valueChanges
@ -283,6 +295,9 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit,
case EntityType.ENTITY_VIEW: case EntityType.ENTITY_VIEW:
subTypesObservable = this.entityViewService.getEntityViewTypes({ignoreLoading: true}); subTypesObservable = this.entityViewService.getEntityViewTypes({ignoreLoading: true});
break; break;
case EntityType.ALARM:
subTypesObservable = this.alarmService.getAlarmTypes({ignoreLoading: true});
break;
} }
if (subTypesObservable) { if (subTypesObservable) {
this.entitySubtypes = subTypesObservable.pipe( this.entitySubtypes = subTypesObservable.pipe(

6
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -535,7 +535,11 @@
"search-propagated-alarms": "Search propagated alarms", "search-propagated-alarms": "Search propagated alarms",
"comments": "Alarm comments", "comments": "Alarm comments",
"show-more": "Show more", "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": { "alarm-activity": {
"add": "Add a comment...", "add": "Add a comment...",

Loading…
Cancel
Save