Merge branch 'master' into fix/3969-LwM2M-resource-title-read-only
This commit is contained in:
commit
b1cc582691
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -18,7 +18,6 @@ package org.thingsboard.server.edge;
|
||||
import com.google.protobuf.AbstractMessage;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.thingsboard.common.util.JacksonUtil;
|
||||
import org.thingsboard.server.common.data.StringUtils;
|
||||
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
|
||||
|
||||
@ -59,12 +59,7 @@ public class OAuth2EdgeTest extends AbstractEdgeTest {
|
||||
oAuth2Info.setEnabled(false);
|
||||
oAuth2Info.setEdgeEnabled(false);
|
||||
doPost("/api/oauth2/config", oAuth2Info, OAuth2Info.class);
|
||||
Assert.assertTrue(edgeImitator.waitForMessages());
|
||||
latestMessage = edgeImitator.getLatestMessage();
|
||||
Assert.assertTrue(latestMessage instanceof OAuth2UpdateMsg);
|
||||
oAuth2UpdateMsg = (OAuth2UpdateMsg) latestMessage;
|
||||
result = JacksonUtil.fromString(oAuth2UpdateMsg.getEntity(), OAuth2Info.class, true);
|
||||
Assert.assertEquals(oAuth2Info, result);
|
||||
Assert.assertFalse(edgeImitator.waitForMessages(5));
|
||||
|
||||
edgeImitator.ignoreType(OAuth2UpdateMsg.class);
|
||||
loginTenantAdmin();
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.thingsboard.server.cache;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@ -22,7 +23,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.thingsboard.server.common.data.CacheConstants;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.Map;
|
||||
|
||||
@Configuration
|
||||
|
||||
@ -29,7 +29,6 @@ import org.springframework.data.redis.core.types.Expiration;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import org.thingsboard.server.common.data.FstStatsService;
|
||||
import redis.clients.jedis.Connection;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
import redis.clients.jedis.util.JedisClusterCRC16;
|
||||
@ -40,6 +39,8 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Slf4j
|
||||
public abstract class RedisTbTransactionalCache<K extends Serializable, V extends Serializable> implements TbTransactionalCache<K, V> {
|
||||
@ -57,6 +58,7 @@ public abstract class RedisTbTransactionalCache<K extends Serializable, V extend
|
||||
private final TbRedisSerializer<K, V> valueSerializer;
|
||||
private final Expiration evictExpiration;
|
||||
private final Expiration cacheTtl;
|
||||
private final boolean cacheEnabled;
|
||||
|
||||
public RedisTbTransactionalCache(String cacheName,
|
||||
CacheSpecsMap cacheSpecsMap,
|
||||
@ -73,10 +75,19 @@ public abstract class RedisTbTransactionalCache<K extends Serializable, V extend
|
||||
.map(CacheSpecs::getTimeToLiveInMinutes)
|
||||
.map(t -> Expiration.from(t, TimeUnit.MINUTES))
|
||||
.orElseGet(Expiration::persistent);
|
||||
this.cacheEnabled = Optional.ofNullable(cacheSpecsMap)
|
||||
.map(CacheSpecsMap::getSpecs)
|
||||
.map(x -> x.get(cacheName))
|
||||
.map(CacheSpecs::getMaxSize)
|
||||
.map(size -> size > 0)
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TbCacheValueWrapper<V> get(K key) {
|
||||
if (!cacheEnabled) {
|
||||
return null;
|
||||
}
|
||||
try (var connection = connectionFactory.getConnection()) {
|
||||
byte[] rawKey = getRawKey(key);
|
||||
byte[] rawValue = connection.get(rawKey);
|
||||
@ -98,6 +109,9 @@ public abstract class RedisTbTransactionalCache<K extends Serializable, V extend
|
||||
|
||||
@Override
|
||||
public void put(K key, V value) {
|
||||
if (!cacheEnabled) {
|
||||
return;
|
||||
}
|
||||
try (var connection = connectionFactory.getConnection()) {
|
||||
put(connection, key, value, RedisStringCommands.SetOption.UPSERT);
|
||||
}
|
||||
@ -105,6 +119,9 @@ public abstract class RedisTbTransactionalCache<K extends Serializable, V extend
|
||||
|
||||
@Override
|
||||
public void putIfAbsent(K key, V value) {
|
||||
if (!cacheEnabled) {
|
||||
return;
|
||||
}
|
||||
try (var connection = connectionFactory.getConnection()) {
|
||||
put(connection, key, value, RedisStringCommands.SetOption.SET_IF_ABSENT);
|
||||
}
|
||||
@ -112,6 +129,9 @@ public abstract class RedisTbTransactionalCache<K extends Serializable, V extend
|
||||
|
||||
@Override
|
||||
public void evict(K key) {
|
||||
if (!cacheEnabled) {
|
||||
return;
|
||||
}
|
||||
try (var connection = connectionFactory.getConnection()) {
|
||||
connection.del(getRawKey(key));
|
||||
}
|
||||
@ -119,6 +139,9 @@ public abstract class RedisTbTransactionalCache<K extends Serializable, V extend
|
||||
|
||||
@Override
|
||||
public void evict(Collection<K> keys) {
|
||||
if (!cacheEnabled) {
|
||||
return;
|
||||
}
|
||||
//Redis expects at least 1 key to delete. Otherwise - ERR wrong number of arguments for 'del' command
|
||||
if (keys.isEmpty()) {
|
||||
return;
|
||||
@ -130,6 +153,9 @@ public abstract class RedisTbTransactionalCache<K extends Serializable, V extend
|
||||
|
||||
@Override
|
||||
public void evictOrPut(K key, V value) {
|
||||
if (!cacheEnabled) {
|
||||
return;
|
||||
}
|
||||
try (var connection = connectionFactory.getConnection()) {
|
||||
var rawKey = getRawKey(key);
|
||||
var records = connection.del(rawKey);
|
||||
@ -153,6 +179,14 @@ public abstract class RedisTbTransactionalCache<K extends Serializable, V extend
|
||||
return new RedisTbCacheTransaction<>(this, connection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R getAndPutInTransaction(K key, Supplier<R> dbCall, Function<V, R> cacheValueToResult, Function<R, V> dbValueToCacheValue, boolean cacheNullValue) {
|
||||
if (!cacheEnabled) {
|
||||
return dbCall.get();
|
||||
}
|
||||
return TbTransactionalCache.super.getAndPutInTransaction(key, dbCall, cacheValueToResult, dbValueToCacheValue, cacheNullValue);
|
||||
}
|
||||
|
||||
private RedisConnection getConnection(byte[] rawKey) {
|
||||
if (!connectionFactory.isRedisClusterAware()) {
|
||||
return connectionFactory.getConnection();
|
||||
@ -214,6 +248,9 @@ public abstract class RedisTbTransactionalCache<K extends Serializable, V extend
|
||||
}
|
||||
|
||||
public void put(RedisConnection connection, K key, V value, RedisStringCommands.SetOption setOption) {
|
||||
if (!cacheEnabled) {
|
||||
return;
|
||||
}
|
||||
byte[] rawKey = getRawKey(key);
|
||||
byte[] rawValue = getRawValue(value);
|
||||
connection.set(rawKey, rawValue, cacheTtl, setOption);
|
||||
|
||||
@ -60,15 +60,20 @@ public interface TbTransactionalCache<K extends Serializable, V extends Serializ
|
||||
}
|
||||
|
||||
default V getAndPutInTransaction(K key, Supplier<V> dbCall, boolean cacheNullValue) {
|
||||
return getAndPutInTransaction(key, dbCall, Function.identity(), Function.identity(), cacheNullValue);
|
||||
}
|
||||
|
||||
default <R> R getAndPutInTransaction(K key, Supplier<R> dbCall, Function<V, R> cacheValueToResult, Function<R, V> dbValueToCacheValue, boolean cacheNullValue) {
|
||||
TbCacheValueWrapper<V> cacheValueWrapper = get(key);
|
||||
if (cacheValueWrapper != null) {
|
||||
return cacheValueWrapper.get();
|
||||
V cacheValue = cacheValueWrapper.get();
|
||||
return cacheValue != null ? cacheValueToResult.apply(cacheValue) : null;
|
||||
}
|
||||
var cacheTransaction = newTransactionForKey(key);
|
||||
try {
|
||||
V dbValue = dbCall.get();
|
||||
R dbValue = dbCall.get();
|
||||
if (dbValue != null || cacheNullValue) {
|
||||
cacheTransaction.putIfAbsent(key, dbValue);
|
||||
cacheTransaction.putIfAbsent(key, dbValueToCacheValue.apply(dbValue));
|
||||
cacheTransaction.commit();
|
||||
return dbValue;
|
||||
} else {
|
||||
@ -94,27 +99,4 @@ public interface TbTransactionalCache<K extends Serializable, V extends Serializ
|
||||
}
|
||||
}
|
||||
|
||||
default <R> R getAndPutInTransaction(K key, Supplier<R> dbCall, Function<V, R> cacheValueToResult, Function<R, V> dbValueToCacheValue, boolean cacheNullValue) {
|
||||
TbCacheValueWrapper<V> cacheValueWrapper = get(key);
|
||||
if (cacheValueWrapper != null) {
|
||||
var cacheValue = cacheValueWrapper.get();
|
||||
return cacheValue == null ? null : cacheValueToResult.apply(cacheValue);
|
||||
}
|
||||
var cacheTransaction = newTransactionForKey(key);
|
||||
try {
|
||||
R dbValue = dbCall.get();
|
||||
if (dbValue != null || cacheNullValue) {
|
||||
cacheTransaction.putIfAbsent(key, dbValueToCacheValue.apply(dbValue));
|
||||
cacheTransaction.commit();
|
||||
return dbValue;
|
||||
} else {
|
||||
cacheTransaction.rollback();
|
||||
return null;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
cacheTransaction.rollback();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -62,4 +62,5 @@ public class CacheSpecsMapTest {
|
||||
public void givenCacheConfig_whenCacheManagerReady_thenVerifyNonExistedCaches() {
|
||||
assertThat(cacheManager.getCache("rainbows_and_unicorns")).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
import org.thingsboard.server.common.data.id.AlarmId;
|
||||
import org.thingsboard.server.common.data.id.CustomerId;
|
||||
import org.thingsboard.server.common.data.id.EntityId;
|
||||
@ -53,9 +54,12 @@ public class AlarmCreateOrUpdateActiveRequest implements AlarmModificationReques
|
||||
private long startTs;
|
||||
@Schema(description = "Timestamp of the alarm end time(last time update), in milliseconds", example = "1634111163522")
|
||||
private long endTs;
|
||||
|
||||
@ToString.Exclude
|
||||
@NoXss
|
||||
@Schema(description = "JSON object with alarm details")
|
||||
private JsonNode details;
|
||||
|
||||
@Valid
|
||||
@Schema(description = "JSON object with propagation details")
|
||||
private AlarmPropagationInfo propagation;
|
||||
|
||||
@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
import org.thingsboard.server.common.data.id.AlarmId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.id.UserId;
|
||||
@ -47,9 +48,12 @@ public class AlarmUpdateRequest implements AlarmModificationRequest {
|
||||
private long startTs;
|
||||
@Schema(description = "Timestamp of the alarm end time(last time update), in milliseconds", example = "1634111163522")
|
||||
private long endTs;
|
||||
|
||||
@ToString.Exclude
|
||||
@NoXss
|
||||
@Schema(description = "JSON object with alarm details")
|
||||
private JsonNode details;
|
||||
|
||||
@Valid
|
||||
@Schema(description = "JSON object with propagation details")
|
||||
private AlarmPropagationInfo propagation;
|
||||
|
||||
@ -342,9 +342,12 @@ public class JpaAlarmDao extends JpaAbstractDao<AlarmEntity, Alarm> implements A
|
||||
|
||||
@Override
|
||||
public AlarmApiCallResult createOrUpdateActiveAlarm(AlarmCreateOrUpdateActiveRequest request, boolean alarmCreationEnabled) {
|
||||
UUID tenantUUID = request.getTenantId().getId();
|
||||
log.debug("[{}] createOrUpdateActiveAlarm [{}] {}", tenantUUID, alarmCreationEnabled, request);
|
||||
|
||||
AlarmPropagationInfo ap = getSafePropagationInfo(request.getPropagation());
|
||||
return toAlarmApiResult(alarmRepository.createOrUpdateActiveAlarm(
|
||||
request.getTenantId().getId(),
|
||||
tenantUUID,
|
||||
request.getCustomerId() != null ? request.getCustomerId().getId() : CustomerId.NULL_UUID,
|
||||
request.getEdgeAlarmId() != null ? request.getEdgeAlarmId().getId() : UUID.randomUUID(),
|
||||
System.currentTimeMillis(),
|
||||
@ -364,10 +367,14 @@ public class JpaAlarmDao extends JpaAbstractDao<AlarmEntity, Alarm> implements A
|
||||
|
||||
@Override
|
||||
public AlarmApiCallResult updateAlarm(AlarmUpdateRequest request) {
|
||||
UUID tenantUUID = request.getTenantId().getId();
|
||||
UUID alarmUUID = request.getAlarmId().getId();
|
||||
log.debug("[{}][{}] updateAlarm {}", tenantUUID, alarmUUID, request);
|
||||
|
||||
AlarmPropagationInfo ap = getSafePropagationInfo(request.getPropagation());
|
||||
return toAlarmApiResult(alarmRepository.updateAlarm(
|
||||
request.getTenantId().getId(),
|
||||
request.getAlarmId().getId(),
|
||||
tenantUUID,
|
||||
alarmUUID,
|
||||
request.getSeverity().name(),
|
||||
request.getStartTs(), request.getEndTs(),
|
||||
getDetailsAsString(request.getDetails()),
|
||||
@ -380,11 +387,13 @@ public class JpaAlarmDao extends JpaAbstractDao<AlarmEntity, Alarm> implements A
|
||||
|
||||
@Override
|
||||
public AlarmApiCallResult acknowledgeAlarm(TenantId tenantId, AlarmId id, long ackTs) {
|
||||
log.debug("[{}][{}] acknowledgeAlarm [{}]", tenantId, id, ackTs);
|
||||
return toAlarmApiResult(alarmRepository.acknowledgeAlarm(tenantId.getId(), id.getId(), ackTs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlarmApiCallResult clearAlarm(TenantId tenantId, AlarmId id, long clearTs, JsonNode details) {
|
||||
log.debug("[{}][{}] clearAlarm [{}]", tenantId, id, clearTs);
|
||||
return toAlarmApiResult(alarmRepository.clearAlarm(tenantId.getId(), id.getId(), clearTs, details != null ? getDetailsAsString(details) : null));
|
||||
}
|
||||
|
||||
|
||||
82
dao/src/test/java/org/thingsboard/server/dao/cache/RedisTbTransactionalCacheTest.java
vendored
Normal file
82
dao/src/test/java/org/thingsboard/server/dao/cache/RedisTbTransactionalCacheTest.java
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Copyright © 2016-2024 The Thingsboard Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.thingsboard.server.dao.cache;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.thingsboard.server.cache.CacheSpecsMap;
|
||||
import org.thingsboard.server.cache.RedisSslCredentials;
|
||||
import org.thingsboard.server.cache.TBRedisCacheConfiguration;
|
||||
import org.thingsboard.server.common.data.id.DeviceId;
|
||||
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
|
||||
import org.thingsboard.server.dao.relation.RelationCacheKey;
|
||||
import org.thingsboard.server.dao.relation.RelationRedisCache;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = {RelationRedisCache.class, CacheSpecsMap.class, TBRedisCacheConfiguration.class})
|
||||
@TestPropertySource(properties = {
|
||||
"cache.type=redis",
|
||||
"cache.specs.relations.timeToLiveInMinutes=1440",
|
||||
"cache.specs.relations.maxSize=0",
|
||||
})
|
||||
@Slf4j
|
||||
public class RedisTbTransactionalCacheTest {
|
||||
|
||||
@MockBean
|
||||
private RelationRedisCache relationRedisCache;
|
||||
@MockBean
|
||||
private RedisConnectionFactory connectionFactory;
|
||||
@MockBean
|
||||
private RedisConnection redisConnection;
|
||||
@MockBean
|
||||
private RedisSslCredentials redisSslCredentials;
|
||||
|
||||
@Test
|
||||
public void testNoOpWhenCacheDisabled() {
|
||||
when(connectionFactory.getConnection()).thenReturn(redisConnection);
|
||||
|
||||
relationRedisCache.put(createRelationCacheKey(), null);
|
||||
relationRedisCache.putIfAbsent(createRelationCacheKey(), null);
|
||||
relationRedisCache.evict(createRelationCacheKey());
|
||||
relationRedisCache.evict(List.of(createRelationCacheKey()));
|
||||
relationRedisCache.getAndPutInTransaction(createRelationCacheKey(), null, false);
|
||||
relationRedisCache.getAndPutInTransaction(createRelationCacheKey(), null, null, null, false);
|
||||
relationRedisCache.getOrFetchFromDB(createRelationCacheKey(), null, false, false);
|
||||
|
||||
verify(connectionFactory, never()).getConnection();
|
||||
verifyNoInteractions(redisConnection);
|
||||
}
|
||||
|
||||
private RelationCacheKey createRelationCacheKey() {
|
||||
return new RelationCacheKey(new DeviceId(UUID.randomUUID()), new DeviceId(UUID.randomUUID()), null, RelationTypeGroup.COMMON);
|
||||
}
|
||||
|
||||
}
|
||||
@ -58,7 +58,6 @@ import org.thingsboard.server.dao.device.DeviceService;
|
||||
import org.thingsboard.server.dao.relation.RelationService;
|
||||
import org.thingsboard.server.dao.user.UserService;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@ -245,8 +244,8 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
// Check child relation
|
||||
PageData<AlarmInfo> alarms = alarmService.findAlarmsV2(tenantId, AlarmQueryV2.builder()
|
||||
.affectedEntityId(childId)
|
||||
.severityList(Arrays.asList(AlarmSeverity.CRITICAL))
|
||||
.statusList(Arrays.asList(AlarmSearchStatus.ACTIVE, AlarmSearchStatus.UNACK)).pageLink(
|
||||
.severityList(List.of(AlarmSeverity.CRITICAL))
|
||||
.statusList(List.of(AlarmSearchStatus.ACTIVE, AlarmSearchStatus.UNACK)).pageLink(
|
||||
new TimePageLink(1, 0, "",
|
||||
new SortOrder("createdTime", SortOrder.Direction.DESC), 0L, System.currentTimeMillis())
|
||||
).build());
|
||||
@ -257,8 +256,8 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
// Check parent relation
|
||||
alarms = alarmService.findAlarmsV2(tenantId, AlarmQueryV2.builder()
|
||||
.affectedEntityId(parentId)
|
||||
.severityList(Arrays.asList(AlarmSeverity.CRITICAL))
|
||||
.statusList(Arrays.asList(AlarmSearchStatus.ACTIVE, AlarmSearchStatus.UNACK)).pageLink(
|
||||
.severityList(List.of(AlarmSeverity.CRITICAL))
|
||||
.statusList(List.of(AlarmSearchStatus.ACTIVE, AlarmSearchStatus.UNACK)).pageLink(
|
||||
new TimePageLink(1, 0, "",
|
||||
new SortOrder("createdTime", SortOrder.Direction.DESC), 0L, System.currentTimeMillis())
|
||||
).build());
|
||||
@ -272,8 +271,8 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
// Check child relation
|
||||
alarms = alarmService.findAlarmsV2(tenantId, AlarmQueryV2.builder()
|
||||
.affectedEntityId(childId)
|
||||
.severityList(Arrays.asList(AlarmSeverity.CRITICAL))
|
||||
.statusList(Arrays.asList(AlarmSearchStatus.ACTIVE, AlarmSearchStatus.UNACK)).pageLink(
|
||||
.severityList(List.of(AlarmSeverity.CRITICAL))
|
||||
.statusList(List.of(AlarmSearchStatus.ACTIVE, AlarmSearchStatus.UNACK)).pageLink(
|
||||
new TimePageLink(1, 0, "",
|
||||
new SortOrder("createdTime", SortOrder.Direction.DESC), 0L, System.currentTimeMillis())
|
||||
).build());
|
||||
@ -284,8 +283,8 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
// Check parent relation
|
||||
alarms = alarmService.findAlarmsV2(tenantId, AlarmQueryV2.builder()
|
||||
.affectedEntityId(parentId)
|
||||
.severityList(Arrays.asList(AlarmSeverity.CRITICAL))
|
||||
.statusList(Arrays.asList(AlarmSearchStatus.ACTIVE, AlarmSearchStatus.UNACK)).pageLink(
|
||||
.severityList(List.of(AlarmSeverity.CRITICAL))
|
||||
.statusList(List.of(AlarmSearchStatus.ACTIVE, AlarmSearchStatus.UNACK)).pageLink(
|
||||
new TimePageLink(1, 0, "",
|
||||
new SortOrder("createdTime", SortOrder.Direction.DESC), 0L, System.currentTimeMillis())
|
||||
).build());
|
||||
@ -298,8 +297,8 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
|
||||
alarms = alarmService.findAlarmsV2(tenantId, AlarmQueryV2.builder()
|
||||
.affectedEntityId(childId)
|
||||
.severityList(Arrays.asList(AlarmSeverity.CRITICAL))
|
||||
.statusList(Arrays.asList(AlarmSearchStatus.ACTIVE, AlarmSearchStatus.ACK)).pageLink(
|
||||
.severityList(List.of(AlarmSeverity.CRITICAL))
|
||||
.statusList(List.of(AlarmSearchStatus.ACTIVE, AlarmSearchStatus.ACK)).pageLink(
|
||||
new TimePageLink(1, 0, "",
|
||||
new SortOrder("createdTime", SortOrder.Direction.DESC), 0L, System.currentTimeMillis())
|
||||
).build());
|
||||
@ -310,8 +309,8 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
// Check not existing relation
|
||||
alarms = alarmService.findAlarmsV2(tenantId, AlarmQueryV2.builder()
|
||||
.affectedEntityId(childId)
|
||||
.severityList(Arrays.asList(AlarmSeverity.CRITICAL))
|
||||
.statusList(Arrays.asList(AlarmSearchStatus.ACTIVE, AlarmSearchStatus.UNACK)).pageLink(
|
||||
.severityList(List.of(AlarmSeverity.CRITICAL))
|
||||
.statusList(List.of(AlarmSearchStatus.ACTIVE, AlarmSearchStatus.UNACK)).pageLink(
|
||||
new TimePageLink(1, 0, "",
|
||||
new SortOrder("createdTime", SortOrder.Direction.DESC), 0L, System.currentTimeMillis())
|
||||
).build());
|
||||
@ -323,8 +322,8 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
|
||||
alarms = alarmService.findAlarmsV2(tenantId, AlarmQueryV2.builder()
|
||||
.affectedEntityId(childId)
|
||||
.severityList(Arrays.asList(AlarmSeverity.CRITICAL))
|
||||
.statusList(Arrays.asList(AlarmSearchStatus.CLEARED, AlarmSearchStatus.ACK)).pageLink(
|
||||
.severityList(List.of(AlarmSeverity.CRITICAL))
|
||||
.statusList(List.of(AlarmSearchStatus.CLEARED, AlarmSearchStatus.ACK)).pageLink(
|
||||
new TimePageLink(1, 0, "",
|
||||
new SortOrder("createdTime", SortOrder.Direction.DESC), 0L, System.currentTimeMillis())
|
||||
).build());
|
||||
@ -334,7 +333,7 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindAssignedAlarm() throws ExecutionException, InterruptedException {
|
||||
public void testFindAssignedAlarm() {
|
||||
|
||||
AssetId parentId = new AssetId(Uuids.timeBased());
|
||||
AssetId childId = new AssetId(Uuids.timeBased());
|
||||
@ -368,7 +367,6 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
|
||||
PageData<AlarmInfo> alarms = alarmService.findAlarms(tenantId, AlarmQuery.builder()
|
||||
.assigneeId(tenantUser.getId())
|
||||
.fetchOriginator(true)
|
||||
.pageLink(new TimePageLink(1, 0, "",
|
||||
new SortOrder("createdTime", SortOrder.Direction.DESC), 0L, System.currentTimeMillis())
|
||||
).build());
|
||||
@ -405,7 +403,7 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindCustomerAlarm() throws ExecutionException, InterruptedException {
|
||||
public void testFindCustomerAlarm() {
|
||||
Customer customer = new Customer();
|
||||
customer.setTitle("TestCustomer");
|
||||
customer.setTenantId(tenantId);
|
||||
@ -451,10 +449,10 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
pageLink.setStartTs(0L);
|
||||
pageLink.setEndTs(System.currentTimeMillis());
|
||||
pageLink.setSearchPropagatedAlarms(true);
|
||||
pageLink.setSeverityList(Arrays.asList(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(Arrays.asList(AlarmSearchStatus.ACTIVE));
|
||||
pageLink.setSeverityList(List.of(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(List.of(AlarmSearchStatus.ACTIVE));
|
||||
|
||||
PageData<AlarmData> tenantAlarms = alarmService.findAlarmDataByQueryForEntities(tenantId, toQuery(pageLink), Arrays.asList(tenantDevice.getId(), customerDevice.getId()));
|
||||
PageData<AlarmData> tenantAlarms = alarmService.findAlarmDataByQueryForEntities(tenantId, toQuery(pageLink), List.of(tenantDevice.getId(), customerDevice.getId()));
|
||||
Assert.assertEquals(2, tenantAlarms.getData().size());
|
||||
|
||||
PageData<AlarmData> customerAlarms = alarmService.findAlarmDataByQueryForEntities(tenantId, toQuery(pageLink), Collections.singletonList(customerDevice.getId()));
|
||||
@ -473,7 +471,7 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindPropagatedCustomerAssetAlarm() throws ExecutionException, InterruptedException {
|
||||
public void testFindPropagatedCustomerAssetAlarm() {
|
||||
Customer customer = new Customer();
|
||||
customer.setTitle("TestCustomer");
|
||||
customer.setTenantId(tenantId);
|
||||
@ -525,8 +523,8 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
pageLink.setStartTs(0L);
|
||||
pageLink.setEndTs(System.currentTimeMillis());
|
||||
pageLink.setSearchPropagatedAlarms(true);
|
||||
pageLink.setSeverityList(Arrays.asList(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(Arrays.asList(AlarmSearchStatus.ACTIVE));
|
||||
pageLink.setSeverityList(List.of(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(List.of(AlarmSearchStatus.ACTIVE));
|
||||
|
||||
//TEST that propagated alarms are visible on the asset level.
|
||||
PageData<AlarmData> customerAlarms = alarmService.findAlarmDataByQueryForEntities(tenantId, toQuery(pageLink), Collections.singletonList(customerAsset.getId()));
|
||||
@ -576,7 +574,7 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
pageLink.setStartTs(0L);
|
||||
pageLink.setEndTs(System.currentTimeMillis());
|
||||
pageLink.setSearchPropagatedAlarms(true);
|
||||
pageLink.setSeverityList(Arrays.asList(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setSeverityList(List.of(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(Collections.singletonList(AlarmSearchStatus.ACTIVE));
|
||||
|
||||
//TEST that propagated alarms are visible on the asset level.
|
||||
@ -599,7 +597,7 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindHighestAlarmSeverity() throws ExecutionException, InterruptedException {
|
||||
public void testFindHighestAlarmSeverity() {
|
||||
Customer customer = new Customer();
|
||||
customer.setTitle("TestCustomer");
|
||||
customer.setTenantId(tenantId);
|
||||
@ -679,8 +677,8 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
pageLink.setStartTs(0L);
|
||||
pageLink.setEndTs(System.currentTimeMillis());
|
||||
pageLink.setSearchPropagatedAlarms(false);
|
||||
pageLink.setSeverityList(Arrays.asList(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(Arrays.asList(AlarmSearchStatus.ACTIVE));
|
||||
pageLink.setSeverityList(List.of(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(List.of(AlarmSearchStatus.ACTIVE));
|
||||
|
||||
PageData<AlarmData> alarms = alarmService.findAlarmDataByQueryForEntities(tenantId, toQuery(pageLink), Collections.singletonList(childId));
|
||||
|
||||
@ -695,8 +693,8 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
pageLink.setStartTs(0L);
|
||||
pageLink.setEndTs(System.currentTimeMillis());
|
||||
pageLink.setSearchPropagatedAlarms(false);
|
||||
pageLink.setSeverityList(Arrays.asList(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(Arrays.asList(AlarmSearchStatus.ACTIVE));
|
||||
pageLink.setSeverityList(List.of(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(List.of(AlarmSearchStatus.ACTIVE));
|
||||
|
||||
alarms = alarmService.findAlarmDataByQueryForEntities(tenantId, toQuery(pageLink), Collections.singletonList(childId));
|
||||
Assert.assertNotNull(alarms.getData());
|
||||
@ -722,8 +720,8 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
pageLink.setStartTs(0L);
|
||||
pageLink.setEndTs(System.currentTimeMillis());
|
||||
pageLink.setSearchPropagatedAlarms(true);
|
||||
pageLink.setSeverityList(Arrays.asList(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(Arrays.asList(AlarmSearchStatus.ACTIVE));
|
||||
pageLink.setSeverityList(List.of(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(List.of(AlarmSearchStatus.ACTIVE));
|
||||
|
||||
alarms = alarmService.findAlarmDataByQueryForEntities(tenantId, toQuery(pageLink), Collections.singletonList(childId));
|
||||
Assert.assertNotNull(alarms.getData());
|
||||
@ -738,8 +736,8 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
pageLink.setStartTs(0L);
|
||||
pageLink.setEndTs(System.currentTimeMillis());
|
||||
pageLink.setSearchPropagatedAlarms(true);
|
||||
pageLink.setSeverityList(Arrays.asList(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(Arrays.asList(AlarmSearchStatus.ACTIVE));
|
||||
pageLink.setSeverityList(List.of(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(List.of(AlarmSearchStatus.ACTIVE));
|
||||
|
||||
alarms = alarmService.findAlarmDataByQueryForEntities(tenantId, toQuery(pageLink), Collections.singletonList(parentId));
|
||||
Assert.assertNotNull(alarms.getData());
|
||||
@ -748,7 +746,6 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
|
||||
PageData<AlarmInfo> alarmsInfoData = alarmService.findAlarms(tenantId, AlarmQuery.builder()
|
||||
.affectedEntityId(childId)
|
||||
.fetchOriginator(true)
|
||||
.status(AlarmStatus.ACTIVE_UNACK).pageLink(
|
||||
new TimePageLink(10, 0, "",
|
||||
new SortOrder("createdTime", SortOrder.Direction.DESC), 0L, System.currentTimeMillis())
|
||||
@ -759,7 +756,6 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
|
||||
alarmsInfoData = alarmService.findAlarms(tenantId, AlarmQuery.builder()
|
||||
.affectedEntityId(parentId)
|
||||
.fetchOriginator(true)
|
||||
.status(AlarmStatus.ACTIVE_UNACK).pageLink(
|
||||
new TimePageLink(10, 0, "",
|
||||
new SortOrder("createdTime", SortOrder.Direction.DESC), 0L, System.currentTimeMillis())
|
||||
@ -770,7 +766,6 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
|
||||
alarmsInfoData = alarmService.findAlarms(tenantId, AlarmQuery.builder()
|
||||
.affectedEntityId(parentId2)
|
||||
.fetchOriginator(true)
|
||||
.status(AlarmStatus.ACTIVE_UNACK).pageLink(
|
||||
new TimePageLink(10, 0, "",
|
||||
new SortOrder("createdTime", SortOrder.Direction.DESC), 0L, System.currentTimeMillis())
|
||||
@ -786,8 +781,8 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
pageLink.setStartTs(0L);
|
||||
pageLink.setEndTs(System.currentTimeMillis());
|
||||
pageLink.setSearchPropagatedAlarms(true);
|
||||
pageLink.setSeverityList(Arrays.asList(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(Arrays.asList(AlarmSearchStatus.ACTIVE));
|
||||
pageLink.setSeverityList(List.of(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(List.of(AlarmSearchStatus.ACTIVE));
|
||||
|
||||
alarms = alarmService.findAlarmDataByQueryForEntities(tenantId, toQuery(pageLink), Collections.singletonList(parentId));
|
||||
Assert.assertNotNull(alarms.getData());
|
||||
@ -803,8 +798,8 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
pageLink.setStartTs(0L);
|
||||
pageLink.setEndTs(System.currentTimeMillis());
|
||||
pageLink.setSearchPropagatedAlarms(true);
|
||||
pageLink.setSeverityList(Arrays.asList(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(Arrays.asList(AlarmSearchStatus.ACTIVE));
|
||||
pageLink.setSeverityList(List.of(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING));
|
||||
pageLink.setStatusList(List.of(AlarmSearchStatus.ACTIVE));
|
||||
|
||||
alarms = alarmService.findAlarmDataByQueryForEntities(tenantId, toQuery(pageLink), Collections.singletonList(childId));
|
||||
Assert.assertNotNull(alarms.getData());
|
||||
@ -813,7 +808,7 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountAlarmsUsingAlarmDataQuery() throws ExecutionException, InterruptedException {
|
||||
public void testCountAlarmsUsingAlarmDataQuery() {
|
||||
AssetId childId = new AssetId(Uuids.timeBased());
|
||||
|
||||
long ts = System.currentTimeMillis();
|
||||
@ -829,7 +824,7 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
.startTs(0L)
|
||||
.endTs(System.currentTimeMillis())
|
||||
.searchPropagatedAlarms(false)
|
||||
.severityList(Arrays.asList(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING))
|
||||
.severityList(List.of(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING))
|
||||
.statusList(List.of(AlarmSearchStatus.ACTIVE))
|
||||
.build();
|
||||
|
||||
@ -841,7 +836,7 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
.startTs(0L)
|
||||
.endTs(System.currentTimeMillis())
|
||||
.searchPropagatedAlarms(true)
|
||||
.severityList(Arrays.asList(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING))
|
||||
.severityList(List.of(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING))
|
||||
.statusList(List.of(AlarmSearchStatus.ACTIVE))
|
||||
.build();
|
||||
|
||||
@ -866,7 +861,7 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
.startTs(0L)
|
||||
.endTs(System.currentTimeMillis())
|
||||
.searchPropagatedAlarms(true)
|
||||
.severityList(Arrays.asList(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING))
|
||||
.severityList(List.of(AlarmSeverity.CRITICAL, AlarmSeverity.WARNING))
|
||||
.statusList(List.of(AlarmSearchStatus.ACTIVE, AlarmSearchStatus.CLEARED))
|
||||
.build();
|
||||
|
||||
@ -939,6 +934,6 @@ public class AlarmServiceTest extends AbstractServiceTest {
|
||||
).build());
|
||||
Assert.assertNotNull(alarms.getData());
|
||||
Assert.assertEquals(0, alarms.getData().size());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -27,10 +27,10 @@ import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
import org.springframework.web.client.RestClientResponseException;
|
||||
import org.springframework.web.reactive.function.BodyInserters;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import org.springframework.web.reactive.function.client.WebClient.RequestBodySpec;
|
||||
import org.springframework.web.reactive.function.client.WebClientResponseException;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import org.thingsboard.common.util.JacksonUtil;
|
||||
import org.thingsboard.rule.engine.api.TbContext;
|
||||
@ -132,6 +132,7 @@ public class TbHttpClient {
|
||||
|
||||
this.webClient = WebClient.builder()
|
||||
.clientConnector(new ReactorClientHttpConnector(httpClient))
|
||||
.defaultHeader(HttpHeaders.CONNECTION, "close") //In previous realization this header was present! (Added for hotfix "Connection reset")
|
||||
.build();
|
||||
} catch (SSLException e) {
|
||||
throw new TbNodeException(e);
|
||||
@ -170,7 +171,7 @@ public class TbHttpClient {
|
||||
BiConsumer<TbMsg, Throwable> onFailure) {
|
||||
try {
|
||||
if (semaphore != null && !semaphore.tryAcquire(config.getReadTimeoutMs(), TimeUnit.MILLISECONDS)) {
|
||||
ctx.tellFailure(msg, new RuntimeException("Timeout during waiting for reply!"));
|
||||
onFailure.accept(msg, new RuntimeException("Timeout during waiting for reply!"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -183,10 +184,10 @@ public class TbHttpClient {
|
||||
.uri(uri)
|
||||
.headers(headers -> prepareHeaders(headers, msg));
|
||||
|
||||
if (HttpMethod.POST.equals(method) || HttpMethod.PUT.equals(method) ||
|
||||
HttpMethod.PATCH.equals(method) || HttpMethod.DELETE.equals(method) ||
|
||||
if ((HttpMethod.POST.equals(method) || HttpMethod.PUT.equals(method) ||
|
||||
HttpMethod.PATCH.equals(method) || HttpMethod.DELETE.equals(method)) &&
|
||||
!config.isIgnoreRequestBody()) {
|
||||
request.body(BodyInserters.fromValue(getData(msg, config.isIgnoreRequestBody(), config.isParseToPlainText())));
|
||||
request.body(BodyInserters.fromValue(getData(msg, config.isParseToPlainText())));
|
||||
}
|
||||
|
||||
request
|
||||
@ -236,11 +237,9 @@ public class TbHttpClient {
|
||||
return uri;
|
||||
}
|
||||
|
||||
private String getData(TbMsg tbMsg, boolean ignoreBody, boolean parseToPlainText) {
|
||||
if (!ignoreBody && parseToPlainText) {
|
||||
return JacksonUtil.toPlainText(tbMsg.getData());
|
||||
}
|
||||
return tbMsg.getData();
|
||||
private Object getData(TbMsg tbMsg, boolean parseToPlainText) {
|
||||
String data = tbMsg.getData();
|
||||
return parseToPlainText ? JacksonUtil.toPlainText(data) : JacksonUtil.toJsonNode(data);
|
||||
}
|
||||
|
||||
private TbMsg processResponse(TbContext ctx, TbMsg origMsg, ResponseEntity<String> response) {
|
||||
@ -283,10 +282,9 @@ public class TbHttpClient {
|
||||
private TbMsg processException(TbMsg origMsg, Throwable e) {
|
||||
TbMsgMetaData metaData = origMsg.getMetaData();
|
||||
metaData.putValue(ERROR, e.getClass() + ": " + e.getMessage());
|
||||
if (e instanceof RestClientResponseException) {
|
||||
RestClientResponseException restClientResponseException = (RestClientResponseException) e;
|
||||
if (e instanceof WebClientResponseException restClientResponseException) {
|
||||
metaData.putValue(STATUS, restClientResponseException.getStatusText());
|
||||
metaData.putValue(STATUS_CODE, restClientResponseException.getRawStatusCode() + "");
|
||||
metaData.putValue(STATUS_CODE, restClientResponseException.getStatusCode().value() + "");
|
||||
metaData.putValue(ERROR_BODY, restClientResponseException.getResponseBodyAsString());
|
||||
}
|
||||
return TbMsg.transformMsgMetadata(origMsg, metaData);
|
||||
|
||||
@ -168,7 +168,7 @@ public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest {
|
||||
try {
|
||||
assertEquals(path, request.getRequestLine().getUri(), "Request path matches");
|
||||
assertTrue(request.containsHeader("Content-Type"), "Content-Type included");
|
||||
assertEquals("text/plain;charset=UTF-8",
|
||||
assertEquals("application/json",
|
||||
request.getFirstHeader("Content-Type").getValue(), "Content-Type value");
|
||||
assertTrue(request.containsHeader("Content-Length"), "Content-Length included");
|
||||
assertEquals("2",
|
||||
|
||||
@ -456,6 +456,10 @@ export class UtilsService {
|
||||
return isDefined(value);
|
||||
}
|
||||
|
||||
public isDefinedAndNotNull(value: any): boolean {
|
||||
return isDefinedAndNotNull(value);
|
||||
}
|
||||
|
||||
public defaultValue(value: any, defaultValue: any): any {
|
||||
if (isDefinedAndNotNull(value)) {
|
||||
return value;
|
||||
|
||||
@ -160,7 +160,7 @@
|
||||
</div>
|
||||
<tb-chart-fill-settings
|
||||
formControlName="barBackgroundSettings"
|
||||
title="widgets.chart.background"
|
||||
titleText="widgets.chart.background"
|
||||
fillNoneTitle="widgets.chart.fill-type-solid">
|
||||
</tb-chart-fill-settings>
|
||||
<tb-time-series-no-aggregation-bar-width-settings
|
||||
|
||||
@ -203,23 +203,29 @@ export class UnreadNotificationWidgetComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
markAsRead(id: string) {
|
||||
const cmd = NotificationSubscriber.createMarkAsReadCommand(this.notificationWsService, [id]);
|
||||
cmd.subscribe();
|
||||
if (!this.ctx.isEdit && !this.ctx.isPreview) {
|
||||
const cmd = NotificationSubscriber.createMarkAsReadCommand(this.notificationWsService, [id]);
|
||||
cmd.subscribe();
|
||||
}
|
||||
}
|
||||
|
||||
markAsAllRead($event: Event) {
|
||||
if ($event) {
|
||||
$event.stopPropagation();
|
||||
if (!this.ctx.isEdit && !this.ctx.isPreview) {
|
||||
if ($event) {
|
||||
$event.stopPropagation();
|
||||
}
|
||||
const cmd = NotificationSubscriber.createMarkAllAsReadCommand(this.notificationWsService);
|
||||
cmd.subscribe();
|
||||
}
|
||||
const cmd = NotificationSubscriber.createMarkAllAsReadCommand(this.notificationWsService);
|
||||
cmd.subscribe();
|
||||
}
|
||||
|
||||
viewAll($event: Event) {
|
||||
if ($event) {
|
||||
$event.stopPropagation();
|
||||
if (!this.ctx.isEdit && !this.ctx.isPreview) {
|
||||
if ($event) {
|
||||
$event.stopPropagation();
|
||||
}
|
||||
this.router.navigateByUrl(this.router.parseUrl('/notification/inbox')).then(() => {});
|
||||
}
|
||||
this.router.navigateByUrl(this.router.parseUrl('/notification/inbox')).then(() => {});
|
||||
}
|
||||
|
||||
trackById(index: number, item: NotificationRequest): string {
|
||||
|
||||
@ -169,6 +169,6 @@ export class TimeSeriesChartWidgetComponent implements OnInit, OnDestroy, AfterV
|
||||
}
|
||||
|
||||
public toggleLegendKey(legendKey: LegendKey) {
|
||||
this.timeSeriesChart.toggleKey(legendKey.dataKey);
|
||||
this.timeSeriesChart.toggleKey(legendKey.dataKey, legendKey.dataIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,7 +56,14 @@ import {
|
||||
measureAxisNameSize
|
||||
} from '@home/components/widget/lib/chart/echarts-widget.models';
|
||||
import { DateFormatProcessor, ValueSourceType } from '@shared/models/widget-settings.models';
|
||||
import { formattedDataFormDatasourceData, formatValue, isDefinedAndNotNull, isEqual, mergeDeep } from '@core/utils';
|
||||
import {
|
||||
formattedDataFormDatasourceData,
|
||||
formatValue,
|
||||
isDefined,
|
||||
isDefinedAndNotNull,
|
||||
isEqual,
|
||||
mergeDeep
|
||||
} from '@core/utils';
|
||||
import { DataKey, Datasource, DatasourceType, FormattedData, widgetType } from '@shared/models/widget.models';
|
||||
import * as echarts from 'echarts/core';
|
||||
import { CallbackDataParams, PiecewiseVisualMapOption } from 'echarts/types/dist/shared';
|
||||
@ -300,7 +307,7 @@ export class TbTimeSeriesChart {
|
||||
}
|
||||
}
|
||||
|
||||
public toggleKey(dataKey: DataKey): void {
|
||||
public toggleKey(dataKey: DataKey, dataIndex?: number): void {
|
||||
const enable = dataKey.hidden;
|
||||
const dataItem = this.dataItems.find(d => d.dataKey === dataKey);
|
||||
if (dataItem) {
|
||||
@ -320,6 +327,9 @@ export class TbTimeSeriesChart {
|
||||
this.timeSeriesChart.setOption(this.timeSeriesChartOptions, this.stackMode ? {notMerge: true} : {replaceMerge: mergeList});
|
||||
this.updateAxes();
|
||||
dataKey.hidden = !enable;
|
||||
if (isDefined(dataIndex)) {
|
||||
this.ctx.defaultSubscription.updateDataVisibility(dataIndex);
|
||||
}
|
||||
if (enable) {
|
||||
this.timeSeriesChart.dispatchAction({
|
||||
type: 'highlight',
|
||||
|
||||
@ -79,7 +79,7 @@
|
||||
</div>
|
||||
<tb-chart-fill-settings
|
||||
formControlName="barBackgroundSettings"
|
||||
title="widgets.chart.background"
|
||||
titleText="widgets.chart.background"
|
||||
fillNoneTitle="widgets.chart.fill-type-solid">
|
||||
</tb-chart-fill-settings>
|
||||
<tb-time-series-no-aggregation-bar-width-settings
|
||||
|
||||
@ -77,7 +77,7 @@
|
||||
</div>
|
||||
<tb-chart-fill-settings
|
||||
formControlName="backgroundSettings"
|
||||
title="widgets.chart.background"
|
||||
titleText="widgets.chart.background"
|
||||
fillNoneTitle="widgets.chart.fill-type-solid">
|
||||
</tb-chart-fill-settings>
|
||||
</ng-container>
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
<ng-container [formGroup]="fillSettingsFormGroup">
|
||||
<div class="tb-form-row column">
|
||||
<div class="tb-form-row no-border no-padding space-between">
|
||||
<div>{{ title | translate }}</div>
|
||||
<div>{{ titleText | translate }}</div>
|
||||
<tb-toggle-select formControlName="type">
|
||||
<tb-toggle-option *ngFor="let type of chartFillTypes" [value]="type">{{ chartFillTypeTranslationMap.get(type) | translate }}</tb-toggle-option>
|
||||
</tb-toggle-select>
|
||||
|
||||
@ -55,7 +55,7 @@ export class ChartFillSettingsComponent implements OnInit, ControlValueAccessor
|
||||
disabled: boolean;
|
||||
|
||||
@Input()
|
||||
title = 'widgets.chart.fill';
|
||||
titleText = 'widgets.chart.fill';
|
||||
|
||||
@Input()
|
||||
fillNoneTitle = 'widgets.chart.fill-type-none';
|
||||
|
||||
@ -487,6 +487,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
|
||||
}
|
||||
if (!this.widgetContext.inited && this.isReady()) {
|
||||
this.widgetContext.inited = true;
|
||||
this.widgetContext.destroyed = false;
|
||||
this.dashboardWidget.updateWidgetParams();
|
||||
this.widgetContext.detectContainerChanges();
|
||||
if (this.cafs.init) {
|
||||
|
||||
@ -449,6 +449,8 @@ export class WidgetContext {
|
||||
labelPattern.destroy();
|
||||
}
|
||||
this.labelPatterns.clear();
|
||||
this.width = undefined;
|
||||
this.height = undefined;
|
||||
this.destroyed = true;
|
||||
}
|
||||
|
||||
|
||||
@ -25,11 +25,17 @@ import {
|
||||
SimpleChanges,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import { ControlValueAccessor, UntypedFormBuilder, UntypedFormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
|
||||
import {
|
||||
ControlValueAccessor,
|
||||
NG_VALIDATORS,
|
||||
NG_VALUE_ACCESSOR,
|
||||
UntypedFormBuilder,
|
||||
UntypedFormGroup,
|
||||
ValidationErrors,
|
||||
Validators
|
||||
} from '@angular/forms';
|
||||
import { Observable } from 'rxjs';
|
||||
import { filter, map, mergeMap, share, tap } from 'rxjs/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from '@app/core/core.state';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { EntityType } from '@shared/models/entity-type.models';
|
||||
import { BaseData } from '@shared/models/base-data';
|
||||
@ -49,6 +55,11 @@ import { SubscriptSizing } from '@angular/material/form-field';
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: forwardRef(() => EntityListComponent),
|
||||
multi: true
|
||||
},
|
||||
{
|
||||
provide: NG_VALIDATORS,
|
||||
useExisting: forwardRef(() => EntityListComponent),
|
||||
multi: true
|
||||
}
|
||||
]
|
||||
})
|
||||
@ -56,7 +67,7 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
|
||||
|
||||
entityListFormGroup: UntypedFormGroup;
|
||||
|
||||
modelValue: Array<string> | null;
|
||||
private modelValue: Array<string> | null;
|
||||
|
||||
@Input()
|
||||
entityType: EntityType;
|
||||
@ -108,17 +119,16 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
|
||||
|
||||
private propagateChange = (v: any) => { };
|
||||
|
||||
constructor(private store: Store<AppState>,
|
||||
public translate: TranslateService,
|
||||
constructor(public translate: TranslateService,
|
||||
private entityService: EntityService,
|
||||
private fb: UntypedFormBuilder) {
|
||||
this.entityListFormGroup = this.fb.group({
|
||||
entities: [this.entities, this.required ? [Validators.required] : []],
|
||||
entities: [this.entities],
|
||||
entity: [null]
|
||||
});
|
||||
}
|
||||
|
||||
updateValidators() {
|
||||
private updateValidators() {
|
||||
this.entityListFormGroup.get('entities').setValidators(this.required ? [Validators.required] : []);
|
||||
this.entityListFormGroup.get('entities').updateValueAndValidity();
|
||||
}
|
||||
@ -189,7 +199,13 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
|
||||
this.dirty = true;
|
||||
}
|
||||
|
||||
reset() {
|
||||
validate(): ValidationErrors | null {
|
||||
return this.entityListFormGroup.valid ? null : {
|
||||
entities: {valid: false}
|
||||
};
|
||||
}
|
||||
|
||||
private reset() {
|
||||
this.entities = [];
|
||||
this.entityListFormGroup.get('entities').setValue(this.entities);
|
||||
this.modelValue = null;
|
||||
@ -201,7 +217,7 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
|
||||
this.dirty = true;
|
||||
}
|
||||
|
||||
add(entity: BaseData<EntityId>): void {
|
||||
private add(entity: BaseData<EntityId>): void {
|
||||
if (!this.modelValue || this.modelValue.indexOf(entity.id.id) === -1) {
|
||||
if (!this.modelValue) {
|
||||
this.modelValue = [];
|
||||
@ -214,7 +230,7 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
|
||||
this.clear();
|
||||
}
|
||||
|
||||
remove(entity: BaseData<EntityId>) {
|
||||
public remove(entity: BaseData<EntityId>) {
|
||||
let index = this.entities.indexOf(entity);
|
||||
if (index >= 0) {
|
||||
this.entities.splice(index, 1);
|
||||
@ -229,11 +245,11 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
|
||||
}
|
||||
}
|
||||
|
||||
displayEntityFn(entity?: BaseData<EntityId>): string | undefined {
|
||||
public displayEntityFn(entity?: BaseData<EntityId>): string | undefined {
|
||||
return entity ? entity.name : undefined;
|
||||
}
|
||||
|
||||
fetchEntities(searchText?: string): Observable<Array<BaseData<EntityId>>> {
|
||||
private fetchEntities(searchText?: string): Observable<Array<BaseData<EntityId>>> {
|
||||
this.searchText = searchText;
|
||||
|
||||
return this.entityService.getEntitiesByNameFilter(this.entityType, searchText,
|
||||
@ -241,14 +257,14 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
|
||||
map((data) => data ? data : []));
|
||||
}
|
||||
|
||||
onFocus() {
|
||||
public onFocus() {
|
||||
if (this.dirty) {
|
||||
this.entityListFormGroup.get('entity').updateValueAndValidity({onlySelf: true, emitEvent: true});
|
||||
this.dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
clear(value: string = '') {
|
||||
private clear(value: string = '') {
|
||||
this.entityInput.nativeElement.value = value;
|
||||
this.entityListFormGroup.get('entity').patchValue(value, {emitEvent: true});
|
||||
setTimeout(() => {
|
||||
@ -257,8 +273,7 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
|
||||
}, 0);
|
||||
}
|
||||
|
||||
textIsNotEmpty(text: string): boolean {
|
||||
public textIsNotEmpty(text: string): boolean {
|
||||
return (text && text.length > 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user