From 827f63ea9ff22783f7753078a0cc200abece1eab Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Tue, 28 Oct 2025 15:32:49 +0200 Subject: [PATCH 001/742] Add tests for rule engine consumer loop --- ...faultTbCalculatedFieldConsumerService.java | 6 +- .../queue/DefaultTbCoreConsumerService.java | 6 +- .../queue/DefaultTbEdgeConsumerService.java | 6 +- .../DefaultTbRuleEngineConsumerService.java | 6 +- .../TbMsgPackProcessingContextFactory.java | 35 +++ .../processing/AbstractConsumerService.java | 6 +- .../AbstractTbRuleEngineSubmitStrategy.java | 12 +- .../BatchTbRuleEngineSubmitStrategy.java | 2 +- .../BurstTbRuleEngineSubmitStrategy.java | 2 +- .../service/queue/processing/IdMsgPair.java | 14 +- ...lByEntityIdTbRuleEngineSubmitStrategy.java | 10 +- .../SequentialTbRuleEngineSubmitStrategy.java | 6 +- .../TbRuleEngineQueueConsumerManager.java | 8 +- .../src/main/resources/thingsboard.yml | 3 + .../queue/TbMsgPackProcessingContextTest.java | 260 ++++++++++++++-- .../RuleEngineConsumerLoopTest.java | 281 ++++++++++++++++++ 16 files changed, 595 insertions(+), 68 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/service/queue/TbMsgPackProcessingContextFactory.java create mode 100644 application/src/test/java/org/thingsboard/server/service/queue/ruleengine/RuleEngineConsumerLoopTest.java diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCalculatedFieldConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCalculatedFieldConsumerService.java index acb36449e8..91981cf86f 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCalculatedFieldConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCalculatedFieldConsumerService.java @@ -146,15 +146,15 @@ public class DefaultTbCalculatedFieldConsumerService extends AbstractPartitionBa private void processMsgs(List> msgs, TbQueueConsumer> consumer, Object consumerKey, QueueConfig config) throws Exception { List> orderedMsgList = msgs.stream().map(msg -> new IdMsgPair<>(UUID.randomUUID(), msg)).toList(); ConcurrentMap> pendingMap = orderedMsgList.stream().collect( - Collectors.toConcurrentMap(IdMsgPair::getUuid, IdMsgPair::getMsg)); + Collectors.toConcurrentMap(IdMsgPair::uuid, IdMsgPair::msg)); CountDownLatch processingTimeoutLatch = new CountDownLatch(1); TbPackProcessingContext> ctx = new TbPackProcessingContext<>( processingTimeoutLatch, pendingMap, new ConcurrentHashMap<>()); PendingMsgHolder pendingMsgHolder = new PendingMsgHolder<>(); Future packSubmitFuture = consumersExecutor.submit(() -> { orderedMsgList.forEach((element) -> { - UUID id = element.getUuid(); - TbProtoQueueMsg msg = element.getMsg(); + UUID id = element.uuid(); + TbProtoQueueMsg msg = element.msg(); log.trace("[{}] Creating main callback for message: {}", id, msg.getValue()); TbCallback callback = new TbPackCallback<>(id, ctx); try { diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java index 9ab5a062eb..57a7018310 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java @@ -260,15 +260,15 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService> msgs, TbQueueConsumer> consumer, Object consumerKey, QueueConfig config) throws Exception { List> orderedMsgList = msgs.stream().map(msg -> new IdMsgPair<>(UUID.randomUUID(), msg)).toList(); ConcurrentMap> pendingMap = orderedMsgList.stream().collect( - Collectors.toConcurrentMap(IdMsgPair::getUuid, IdMsgPair::getMsg)); + Collectors.toConcurrentMap(IdMsgPair::uuid, IdMsgPair::msg)); CountDownLatch processingTimeoutLatch = new CountDownLatch(1); TbPackProcessingContext> ctx = new TbPackProcessingContext<>( processingTimeoutLatch, pendingMap, new ConcurrentHashMap<>()); PendingMsgHolder pendingMsgHolder = new PendingMsgHolder<>(); Future packSubmitFuture = consumersExecutor.submit(() -> { orderedMsgList.forEach((element) -> { - UUID id = element.getUuid(); - TbProtoQueueMsg msg = element.getMsg(); + UUID id = element.uuid(); + TbProtoQueueMsg msg = element.msg(); log.trace("[{}] Creating main callback for message: {}", id, msg.getValue()); TbCallback callback = new TbPackCallback<>(id, ctx); try { diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbEdgeConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbEdgeConsumerService.java index 40ef9bfeca..71dacdbdaf 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbEdgeConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbEdgeConsumerService.java @@ -129,15 +129,15 @@ public class DefaultTbEdgeConsumerService extends AbstractConsumerService> msgs, TbQueueConsumer> consumer, Object consumerKey, QueueConfig edgeQueueConfig) throws InterruptedException { List> orderedMsgList = msgs.stream().map(msg -> new IdMsgPair<>(UUID.randomUUID(), msg)).toList(); ConcurrentMap> pendingMap = orderedMsgList.stream().collect( - Collectors.toConcurrentMap(IdMsgPair::getUuid, IdMsgPair::getMsg)); + Collectors.toConcurrentMap(IdMsgPair::uuid, IdMsgPair::msg)); CountDownLatch processingTimeoutLatch = new CountDownLatch(1); TbPackProcessingContext> ctx = new TbPackProcessingContext<>( processingTimeoutLatch, pendingMap, new ConcurrentHashMap<>()); PendingMsgHolder pendingMsgHolder = new PendingMsgHolder<>(); Future submitFuture = consumersExecutor.submit(() -> { orderedMsgList.forEach((element) -> { - UUID id = element.getUuid(); - TbProtoQueueMsg msg = element.getMsg(); + UUID id = element.uuid(); + TbProtoQueueMsg msg = element.msg(); TbCallback callback = new TbPackCallback<>(id, ctx); try { ToEdgeMsg toEdgeMsg = msg.getValue(); diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java index a809f2bb11..d2a8e7a441 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java @@ -70,6 +70,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractPartitionBasedCo private final TbRuleEngineConsumerContext ctx; private final QueueService queueService; private final TbRuleEngineDeviceRpcService tbDeviceRpcService; + private final TbMsgPackProcessingContextFactory packProcessingContextFactory; private final ConcurrentMap consumers = new ConcurrentHashMap<>(); @@ -85,11 +86,13 @@ public class DefaultTbRuleEngineConsumerService extends AbstractPartitionBasedCo PartitionService partitionService, ApplicationEventPublisher eventPublisher, JwtSettingsService jwtSettingsService, - CalculatedFieldCache calculatedFieldCache) { + CalculatedFieldCache calculatedFieldCache, + TbMsgPackProcessingContextFactory packProcessingContextFactory) { super(actorContext, tenantProfileCache, deviceProfileCache, assetProfileCache, tbResourceDataCache, calculatedFieldCache, apiUsageStateService, partitionService, eventPublisher, jwtSettingsService); this.ctx = ctx; this.tbDeviceRpcService = tbDeviceRpcService; this.queueService = queueService; + this.packProcessingContextFactory = packProcessingContextFactory; } @Override @@ -255,6 +258,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractPartitionBasedCo .consumerExecutor(consumersExecutor) .scheduler(scheduler) .taskExecutor(mgmtExecutor) + .packProcessingContextFactory(packProcessingContextFactory) .build(); consumers.put(queueKey, consumer); consumer.init(queue); diff --git a/application/src/main/java/org/thingsboard/server/service/queue/TbMsgPackProcessingContextFactory.java b/application/src/main/java/org/thingsboard/server/service/queue/TbMsgPackProcessingContextFactory.java new file mode 100644 index 0000000000..ff804ad304 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/queue/TbMsgPackProcessingContextFactory.java @@ -0,0 +1,35 @@ +/** + * Copyright © 2016-2025 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.service.queue; + +import org.springframework.stereotype.Component; +import org.thingsboard.server.service.queue.processing.TbRuleEngineSubmitStrategy; + +public interface TbMsgPackProcessingContextFactory { + + TbMsgPackProcessingContext create(String queueName, TbRuleEngineSubmitStrategy submitStrategy, boolean skipTimeouts); + + @Component + class DefaultTbMsgPackProcessingContextFactory implements TbMsgPackProcessingContextFactory { + + @Override + public TbMsgPackProcessingContext create(String queueName, TbRuleEngineSubmitStrategy submitStrategy, boolean skipTimeouts) { + return new TbMsgPackProcessingContext(queueName, submitStrategy, skipTimeouts); + } + + } + +} diff --git a/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java index e18cc0b09e..7e9ada0e75 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java @@ -134,13 +134,13 @@ public abstract class AbstractConsumerService> msgs, TbQueueConsumer> consumer) throws Exception { List> orderedMsgList = msgs.stream().map(msg -> new IdMsgPair<>(UUID.randomUUID(), msg)).toList(); ConcurrentMap> pendingMap = orderedMsgList.stream().collect( - Collectors.toConcurrentMap(IdMsgPair::getUuid, IdMsgPair::getMsg)); + Collectors.toConcurrentMap(IdMsgPair::uuid, IdMsgPair::msg)); CountDownLatch processingTimeoutLatch = new CountDownLatch(1); TbPackProcessingContext> ctx = new TbPackProcessingContext<>( processingTimeoutLatch, pendingMap, new ConcurrentHashMap<>()); orderedMsgList.forEach(element -> { - UUID id = element.getUuid(); - TbProtoQueueMsg msg = element.getMsg(); + UUID id = element.uuid(); + TbProtoQueueMsg msg = element.msg(); log.trace("[{}] Creating notification callback for message: {}", id, msg.getValue()); TbCallback callback = new TbPackCallback<>(id, ctx); try { diff --git a/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractTbRuleEngineSubmitStrategy.java b/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractTbRuleEngineSubmitStrategy.java index 019573631a..5a1bdae13a 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractTbRuleEngineSubmitStrategy.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractTbRuleEngineSubmitStrategy.java @@ -44,21 +44,21 @@ public abstract class AbstractTbRuleEngineSubmitStrategy implements TbRuleEngine @Override public ConcurrentMap> getPendingMap() { - return orderedMsgList.stream().collect(Collectors.toConcurrentMap(pair -> pair.uuid, pair -> pair.msg)); + return orderedMsgList.stream().collect(Collectors.toConcurrentMap(pair -> pair.uuid(), pair -> pair.msg())); } @Override public void update(ConcurrentMap> reprocessMap) { List> newOrderedMsgList = new ArrayList<>(reprocessMap.size()); for (IdMsgPair pair : orderedMsgList) { - if (reprocessMap.containsKey(pair.uuid)) { - if (StringUtils.isNotEmpty(pair.getMsg().getValue().getFailureMessage())) { - var toRuleEngineMsg = TransportProtos.ToRuleEngineMsg.newBuilder(pair.getMsg().getValue()) + if (reprocessMap.containsKey(pair.uuid())) { + if (StringUtils.isNotEmpty(pair.msg().getValue().getFailureMessage())) { + var toRuleEngineMsg = TransportProtos.ToRuleEngineMsg.newBuilder(pair.msg().getValue()) .clearFailureMessage() .clearRelationTypes() .build(); - var newMsg = new TbProtoQueueMsg<>(pair.getMsg().getKey(), toRuleEngineMsg, pair.getMsg().getHeaders()); - newOrderedMsgList.add(new IdMsgPair<>(pair.getUuid(), newMsg)); + var newMsg = new TbProtoQueueMsg<>(pair.msg().getKey(), toRuleEngineMsg, pair.msg().getHeaders()); + newOrderedMsgList.add(new IdMsgPair<>(pair.uuid(), newMsg)); } else { newOrderedMsgList.add(pair); } diff --git a/application/src/main/java/org/thingsboard/server/service/queue/processing/BatchTbRuleEngineSubmitStrategy.java b/application/src/main/java/org/thingsboard/server/service/queue/processing/BatchTbRuleEngineSubmitStrategy.java index 93478eab18..a47c43422b 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/processing/BatchTbRuleEngineSubmitStrategy.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/processing/BatchTbRuleEngineSubmitStrategy.java @@ -73,7 +73,7 @@ public class BatchTbRuleEngineSubmitStrategy extends AbstractTbRuleEngineSubmitS pendingPack.clear(); for (int i = startIdx; i < endIdx; i++) { IdMsgPair pair = orderedMsgList.get(i); - pendingPack.put(pair.uuid, pair.msg); + pendingPack.put(pair.uuid(), pair.msg()); } tmpPack = new LinkedHashMap<>(pendingPack); } diff --git a/application/src/main/java/org/thingsboard/server/service/queue/processing/BurstTbRuleEngineSubmitStrategy.java b/application/src/main/java/org/thingsboard/server/service/queue/processing/BurstTbRuleEngineSubmitStrategy.java index af465686e9..9f9dd0a60f 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/processing/BurstTbRuleEngineSubmitStrategy.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/processing/BurstTbRuleEngineSubmitStrategy.java @@ -34,7 +34,7 @@ public class BurstTbRuleEngineSubmitStrategy extends AbstractTbRuleEngineSubmitS if (log.isDebugEnabled()) { log.debug("[{}] submitting [{}] messages to rule engine", queueName, orderedMsgList.size()); } - orderedMsgList.forEach(pair -> msgConsumer.accept(pair.uuid, pair.msg)); + orderedMsgList.forEach(pair -> msgConsumer.accept(pair.uuid(), pair.msg())); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/queue/processing/IdMsgPair.java b/application/src/main/java/org/thingsboard/server/service/queue/processing/IdMsgPair.java index e74362699b..6795b2822f 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/processing/IdMsgPair.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/processing/IdMsgPair.java @@ -15,19 +15,9 @@ */ package org.thingsboard.server.service.queue.processing; -import lombok.Getter; +import com.google.protobuf.GeneratedMessageV3; import org.thingsboard.server.queue.common.TbProtoQueueMsg; import java.util.UUID; -public class IdMsgPair { - @Getter - final UUID uuid; - @Getter - final TbProtoQueueMsg msg; - - public IdMsgPair(UUID uuid, TbProtoQueueMsg msg) { - this.uuid = uuid; - this.msg = msg; - } -} +public record IdMsgPair(UUID uuid, TbProtoQueueMsg msg) {} diff --git a/application/src/main/java/org/thingsboard/server/service/queue/processing/SequentialByEntityIdTbRuleEngineSubmitStrategy.java b/application/src/main/java/org/thingsboard/server/service/queue/processing/SequentialByEntityIdTbRuleEngineSubmitStrategy.java index c72f1274e7..1aa1b20284 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/processing/SequentialByEntityIdTbRuleEngineSubmitStrategy.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/processing/SequentialByEntityIdTbRuleEngineSubmitStrategy.java @@ -51,7 +51,7 @@ public abstract class SequentialByEntityIdTbRuleEngineSubmitStrategy extends Abs entityIdToListMap.forEach((entityId, queue) -> { IdMsgPair msg = queue.peek(); if (msg != null) { - msgConsumer.accept(msg.uuid, msg.msg); + msgConsumer.accept(msg.uuid(), msg.msg()); } }); } @@ -71,13 +71,13 @@ public abstract class SequentialByEntityIdTbRuleEngineSubmitStrategy extends Abs IdMsgPair next = null; synchronized (queue) { IdMsgPair expected = queue.peek(); - if (expected != null && expected.uuid.equals(id)) { + if (expected != null && expected.uuid().equals(id)) { queue.poll(); next = queue.peek(); } } if (next != null) { - msgConsumer.accept(next.uuid, next.msg); + msgConsumer.accept(next.uuid(), next.msg()); } } } @@ -87,9 +87,9 @@ public abstract class SequentialByEntityIdTbRuleEngineSubmitStrategy extends Abs msgToEntityIdMap.clear(); entityIdToListMap.clear(); for (IdMsgPair pair : orderedMsgList) { - EntityId entityId = getEntityId(pair.msg.getValue()); + EntityId entityId = getEntityId(pair.msg().getValue()); if (entityId != null) { - msgToEntityIdMap.put(pair.uuid, entityId); + msgToEntityIdMap.put(pair.uuid(), entityId); entityIdToListMap.computeIfAbsent(entityId, id -> new LinkedList<>()).add(pair); } } diff --git a/application/src/main/java/org/thingsboard/server/service/queue/processing/SequentialTbRuleEngineSubmitStrategy.java b/application/src/main/java/org/thingsboard/server/service/queue/processing/SequentialTbRuleEngineSubmitStrategy.java index be97853310..c048f42ee0 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/processing/SequentialTbRuleEngineSubmitStrategy.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/processing/SequentialTbRuleEngineSubmitStrategy.java @@ -60,11 +60,11 @@ public class SequentialTbRuleEngineSubmitStrategy extends AbstractTbRuleEngineSu int idx = msgIdx.get(); if (idx < listSize) { IdMsgPair pair = orderedMsgList.get(idx); - expectedMsgId = pair.uuid; + expectedMsgId = pair.uuid(); if (log.isDebugEnabled()) { - log.debug("[{}] submitting [{}] message to rule engine", queueName, pair.msg); + log.debug("[{}] submitting [{}] message to rule engine", queueName, pair.msg()); } - msgConsumer.accept(pair.uuid, pair.msg); + msgConsumer.accept(pair.uuid(), pair.msg()); } } diff --git a/application/src/main/java/org/thingsboard/server/service/queue/ruleengine/TbRuleEngineQueueConsumerManager.java b/application/src/main/java/org/thingsboard/server/service/queue/ruleengine/TbRuleEngineQueueConsumerManager.java index d067be49a0..a6f7e34208 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/ruleengine/TbRuleEngineQueueConsumerManager.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/ruleengine/TbRuleEngineQueueConsumerManager.java @@ -41,6 +41,7 @@ import org.thingsboard.server.queue.common.consumer.TbQueueConsumerTask; import org.thingsboard.server.queue.discovery.QueueKey; import org.thingsboard.server.service.queue.TbMsgPackCallback; import org.thingsboard.server.service.queue.TbMsgPackProcessingContext; +import org.thingsboard.server.service.queue.TbMsgPackProcessingContextFactory; import org.thingsboard.server.service.queue.TbRuleEngineConsumerStats; import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingDecision; import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingResult; @@ -66,13 +67,15 @@ public class TbRuleEngineQueueConsumerManager extends MainQueueConsumerManager { Integer partitionId = tpi != null ? tpi.getPartition().orElse(-1) : null; @@ -81,6 +84,7 @@ public class TbRuleEngineQueueConsumerManager extends MainQueueConsumerManager submitMessage(packCtx, id, msg)); final boolean timeout = !packCtx.await(queue.getPackProcessingTimeout(), TimeUnit.MILLISECONDS); diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 61b797515a..aa0b5d7920 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -1889,6 +1889,9 @@ queue: print-interval-ms: "${TB_QUEUE_RULE_ENGINE_STATS_PRINT_INTERVAL_MS:60000}" # Max length of the error message that is printed by statistics max-error-message-length: "${TB_QUEUE_RULE_ENGINE_MAX_ERROR_MESSAGE_LENGTH:4096}" + prometheus-stats: + # Enable/disable Prometheus statistics for individual Rule Engine message processing (records time in ms for success/failure). + enabled: "${TB_QUEUE_RULE_ENGINE_PROMETHEUS_STATS_ENABLED:true}" # After a queue is deleted (or the profile's isolation option was disabled), Rule Engine will continue reading related topics during this period before deleting the actual topics topic-deletion-delay: "${TB_QUEUE_RULE_ENGINE_TOPIC_DELETION_DELAY_SEC:15}" # Size of the thread pool that handles such operations as partition changes, config updates, queue deletion diff --git a/application/src/test/java/org/thingsboard/server/service/queue/TbMsgPackProcessingContextTest.java b/application/src/test/java/org/thingsboard/server/service/queue/TbMsgPackProcessingContextTest.java index ef1febfa6c..b5d65ea035 100644 --- a/application/src/test/java/org/thingsboard/server/service/queue/TbMsgPackProcessingContextTest.java +++ b/application/src/test/java/org/thingsboard/server/service/queue/TbMsgPackProcessingContextTest.java @@ -15,14 +15,17 @@ */ package org.thingsboard.server.service.queue; -import lombok.extern.slf4j.Slf4j; -import org.junit.After; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; +import com.google.common.util.concurrent.MoreExecutors; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.server.common.data.DataConstants; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.msg.queue.RuleEngineException; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.service.queue.processing.TbRuleEngineSubmitStrategy; @@ -35,30 +38,241 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import static org.junit.Assert.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@Slf4j -@RunWith(MockitoJUnitRunner.class) -public class TbMsgPackProcessingContextTest { +@ExtendWith(MockitoExtension.class) +class TbMsgPackProcessingContextTest { + + TenantId tenantId = TenantId.fromUUID(UUID.randomUUID()); + + @Mock + TbRuleEngineSubmitStrategy submitStrategy; + @Mock + TbProtoQueueMsg mockMsg; + + ConcurrentMap> pendingMap; - public static final int TIMEOUT = 10; ExecutorService executorService; - @After - public void tearDown() { + @BeforeEach + void setup() { + pendingMap = new ConcurrentHashMap<>(); + lenient().when(submitStrategy.getPendingMap()).thenReturn(pendingMap); + } + + @AfterEach + void tearDown() { if (executorService != null) { - executorService.shutdownNow(); + MoreExecutors.shutdownAndAwaitTermination(executorService, 5, TimeUnit.SECONDS); } } @Test - public void testHighConcurrencyCase() throws InterruptedException { - //log.warn("preparing the test..."); + void testAwait_shouldReturnTrue_whenOnSuccessIsCalledBeforeTimeout() throws InterruptedException { + // GIVEN - a context with one pending message + executorService = Executors.newSingleThreadExecutor(); + + UUID msgId = UUID.randomUUID(); + pendingMap.put(msgId, mockMsg); + var context = new TbMsgPackProcessingContext("test-queue", submitStrategy, false); + + // WHEN - onSuccess() is called in another thread before timeout + executorService.submit(() -> { + try { + Thread.sleep(100); + context.onSuccess(msgId); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + + // THEN - await() should return true (successful completion) + boolean result = context.await(5000, TimeUnit.MILLISECONDS); + assertThat(result).as("await() should return true when latch is counted down before timeout").isTrue(); + + // Verify the message was moved to success map + assertThat(context.getSuccessMap()).containsKey(msgId); + assertThat(context.getPendingMap()).isEmpty(); + assertThat(context.getExceptionsMap()).isEmpty(); + + + // Verify submit strategy was notified about successful message processing + then(submitStrategy).should().onSuccess(msgId); + } + + @Test + void testAwait_shouldReturnTrue_whenOnFailureIsCalledBeforeTimeout() throws InterruptedException { + // GIVEN - a context with one pending message + executorService = Executors.newSingleThreadExecutor(); + + UUID msgId = UUID.randomUUID(); + pendingMap.put(msgId, mockMsg); + var context = new TbMsgPackProcessingContext("test-queue", submitStrategy, false); + + var exception = new RuleEngineException("Test exception"); + + // WHEN - onFailure() is called in another thread before timeout + executorService.submit(() -> { + try { + Thread.sleep(100); + context.onFailure(tenantId, msgId, exception); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + + // THEN - await() should return true (successful completion, even if message processing failed) + boolean result = context.await(5000, TimeUnit.MILLISECONDS); + assertThat(result).as("await() should return true when latch is counted down before timeout").isTrue(); + + // Verify the exception was added to exceptions map + assertThat(context.getSuccessMap()).isEmpty(); + assertThat(context.getPendingMap()).isEmpty(); + assertThat(context.getExceptionsMap()).containsEntry(tenantId, exception); + } + + @Test + void testAwait_shouldReturnFalse_whenTimeoutOccurs() throws InterruptedException { + // GIVEN - a context with one pending message and no processing + UUID msgId = UUID.randomUUID(); + pendingMap.put(msgId, mockMsg); + var context = new TbMsgPackProcessingContext("test-queue", submitStrategy, false); + + // WHEN - await() is called with short timeout and no message processing happens + long startTime = System.nanoTime(); + boolean result = context.await(100, TimeUnit.MILLISECONDS); + long elapsedTime = System.nanoTime() - startTime; + + // THEN - await() should return false (timeout occurred) + assertThat(result).as("await() should return false when timeout occurs").isFalse(); + assertThat(elapsedTime).as("await() should wait for at least the timeout duration").isGreaterThanOrEqualTo(100L); + + // Message should still be in pending map + assertThat(context.getSuccessMap()).isEmpty(); + assertThat(context.getPendingMap()).containsKey(msgId); + assertThat(context.getExceptionsMap()).isEmpty(); + } + + @Test + void testAwait_shouldHandleMultiplePendingMessages() throws InterruptedException { + // GIVEN - a context with multiple pending messages + executorService = Executors.newSingleThreadExecutor(); + + UUID msgId1 = UUID.randomUUID(); + UUID msgId2 = UUID.randomUUID(); + UUID msgId3 = UUID.randomUUID(); + + pendingMap.put(msgId1, mockMsg); + pendingMap.put(msgId2, mockMsg); + pendingMap.put(msgId3, mockMsg); + + var context = new TbMsgPackProcessingContext("test-queue", submitStrategy, false); + + // WHEN - messages are processed one by one + executorService.submit(() -> { + try { + Thread.sleep(50); + context.onSuccess(msgId1); + Thread.sleep(50); + context.onSuccess(msgId2); + Thread.sleep(50); + context.onSuccess(msgId3); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + + // THEN - await() should return true only after all messages are processed + boolean result = context.await(5000, TimeUnit.MILLISECONDS); + assertThat(result).as("await() should return true after all messages are processed").isTrue(); + + // All messages should be in success map + assertThat(context.getSuccessMap()).containsKeys(msgId1, msgId2, msgId3); + assertThat(context.getPendingMap()).isEmpty(); + assertThat(context.getExceptionsMap()).isEmpty(); + } + + @Test + void testAwait_shouldNotCountDownPrematurely_withMultipleMessages() throws InterruptedException { + // GIVEN - a context with multiple pending messages + executorService = Executors.newSingleThreadExecutor(); + + UUID msgId1 = UUID.randomUUID(); + UUID msgId2 = UUID.randomUUID(); + + pendingMap.put(msgId1, mockMsg); + pendingMap.put(msgId2, mockMsg); + + var context = new TbMsgPackProcessingContext("test-queue", submitStrategy, false); + + // WHEN - only one message is processed + executorService.submit(() -> { + try { + Thread.sleep(100); + context.onSuccess(msgId1); + // msgId2 still in processing + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + + // THEN: await should timeout because not all messages were processed + boolean result = context.await(2000, TimeUnit.MILLISECONDS); + assertThat(result).as("await() should timeout when not all messages are processed").isFalse(); + + // One message in success, one still pending + assertThat(context.getSuccessMap()).containsOnlyKeys(msgId1); + assertThat(context.getPendingMap()).containsOnlyKeys(msgId2); + assertThat(context.getExceptionsMap()).isEmpty(); + } + + @Test + void testAwait_shouldHandleMixedSuccessAndFailure() throws InterruptedException { + // GIVEN - multiple messages + executorService = Executors.newSingleThreadExecutor(); + + UUID msgId1 = UUID.randomUUID(); + UUID msgId2 = UUID.randomUUID(); + + pendingMap.put(msgId1, mockMsg); + pendingMap.put(msgId2, mockMsg); + + var context = new TbMsgPackProcessingContext("test-queue", submitStrategy, false); + + var exception = new RuleEngineException("Test exception"); + + // WHEN - one succeeds, one fails + executorService.submit(() -> { + try { + Thread.sleep(50); + context.onSuccess(msgId1); + Thread.sleep(50); + context.onFailure(tenantId, msgId2, exception); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + + // THEN - await() should complete successfully + boolean result = context.await(5000, TimeUnit.MILLISECONDS); + assertThat(result).as("await() should return true when all messages are processed").isTrue(); + + assertThat(context.getSuccessMap()).containsOnlyKeys(msgId1); + assertThat(context.getPendingMap()).isEmpty(); + assertThat(context.getExceptionsMap()).containsEntry(tenantId, exception); + } + + @Test + void testHighConcurrencyCase() throws InterruptedException { int msgCount = 1000; int parallelCount = 5; executorService = Executors.newFixedThreadPool(parallelCount, ThingsBoardThreadFactory.forName(getClass().getSimpleName() + "-test-scope")); @@ -76,28 +290,24 @@ public class TbMsgPackProcessingContextTest { final CountDownLatch startLatch = new CountDownLatch(1); final CountDownLatch finishLatch = new CountDownLatch(parallelCount); for (int i = 0; i < parallelCount; i++) { - //final String taskName = "" + uuid + " " + i; executorService.submit(() -> { - //log.warn("ready {}", taskName); readyLatch.countDown(); try { startLatch.await(); } catch (InterruptedException e) { - Assert.fail("failed to await"); + fail("failed to await"); } - //log.warn("go {}", taskName); - context.onSuccess(uuid); - finishLatch.countDown(); }); } - assertTrue(readyLatch.await(TIMEOUT, TimeUnit.SECONDS)); + assertTrue(readyLatch.await(10, TimeUnit.SECONDS)); Thread.yield(); startLatch.countDown(); //run all-at-once submitted tasks - assertTrue(finishLatch.await(TIMEOUT, TimeUnit.SECONDS)); + assertTrue(finishLatch.await(10, TimeUnit.SECONDS)); } - assertTrue(context.await(TIMEOUT, TimeUnit.SECONDS)); + assertTrue(context.await(10, TimeUnit.SECONDS)); verify(strategyMock, times(msgCount)).onSuccess(any(UUID.class)); } + } diff --git a/application/src/test/java/org/thingsboard/server/service/queue/ruleengine/RuleEngineConsumerLoopTest.java b/application/src/test/java/org/thingsboard/server/service/queue/ruleengine/RuleEngineConsumerLoopTest.java new file mode 100644 index 0000000000..1619283586 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/service/queue/ruleengine/RuleEngineConsumerLoopTest.java @@ -0,0 +1,281 @@ +/** + * Copyright © 2016-2025 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.service.queue.ruleengine; + +import com.google.common.util.concurrent.MoreExecutors; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.thingsboard.common.util.ThingsBoardExecutors; +import org.thingsboard.common.util.ThingsBoardThreadFactory; +import org.thingsboard.server.actors.ActorSystemContext; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.msg.TbMsgType; +import org.thingsboard.server.common.data.queue.ProcessingStrategy; +import org.thingsboard.server.common.data.queue.ProcessingStrategyType; +import org.thingsboard.server.common.data.queue.Queue; +import org.thingsboard.server.common.data.queue.SubmitStrategy; +import org.thingsboard.server.common.data.queue.SubmitStrategyType; +import org.thingsboard.server.common.msg.TbMsg; +import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.common.msg.queue.ServiceType; +import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; +import org.thingsboard.server.common.stats.StatsFactory; +import org.thingsboard.server.gen.transport.TransportProtos; +import org.thingsboard.server.queue.TbQueueAdmin; +import org.thingsboard.server.queue.TbQueueConsumer; +import org.thingsboard.server.queue.TbQueueMsg; +import org.thingsboard.server.queue.common.DefaultTbQueueMsgHeaders; +import org.thingsboard.server.queue.common.TbProtoQueueMsg; +import org.thingsboard.server.queue.discovery.PartitionService; +import org.thingsboard.server.queue.discovery.QueueKey; +import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; +import org.thingsboard.server.queue.memory.DefaultInMemoryStorage; +import org.thingsboard.server.queue.memory.InMemoryStorage; +import org.thingsboard.server.queue.memory.InMemoryTbQueueConsumer; +import org.thingsboard.server.queue.provider.TbQueueProducerProvider; +import org.thingsboard.server.queue.provider.TbRuleEngineQueueFactory; +import org.thingsboard.server.service.queue.TbMsgPackProcessingContext; +import org.thingsboard.server.service.queue.TbMsgPackProcessingContextFactory; +import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingStrategyFactory; +import org.thingsboard.server.service.queue.processing.TbRuleEngineSubmitStrategy; +import org.thingsboard.server.service.queue.processing.TbRuleEngineSubmitStrategyFactory; +import org.thingsboard.server.service.stats.RuleEngineStatisticsService; + +import java.time.Duration; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class RuleEngineConsumerLoopTest { + + TenantId tenantId = TenantId.fromUUID(UUID.randomUUID()); + DeviceId deviceId = new DeviceId(UUID.randomUUID()); + + InMemoryStorage storage; + + @Mock + ActorSystemContext actorContext; + @Mock + StatsFactory statsFactory; + @Mock + TbRuleEngineQueueFactory queueFactory; + @Mock + RuleEngineStatisticsService statisticsService; + @Mock + TbServiceInfoProvider serviceInfoProvider; + @Mock + PartitionService partitionService; + @Mock + TbQueueProducerProvider producerProvider; + @Mock + TbQueueAdmin queueAdmin; + @Mock + TbMsgPackProcessingContextFactory packProcessingContextFactory; + @Mock + TbMsgPackProcessingContext packCtx; + + Queue mainQueue; + + TbQueueConsumer> consumer; + + TbRuleEngineConsumerContext ruleEngineConsumerContext; + TbRuleEngineQueueConsumerManager consumerManager; + + ExecutorService consumersExecutor; + ScheduledExecutorService scheduler; + ExecutorService mgmtExecutor; + + @BeforeEach + void setup() throws InterruptedException { + consumersExecutor = Executors.newCachedThreadPool(ThingsBoardThreadFactory.forName("tb-rule-engine-consumer")); + scheduler = ThingsBoardExecutors.newSingleThreadScheduledExecutor("tb-rule-engine-consumer-scheduler"); + mgmtExecutor = ThingsBoardExecutors.newWorkStealingPool(1, "tb-rule-engine-mgmt"); + + mainQueue = new Queue(); + mainQueue.setTenantId(TenantId.SYS_TENANT_ID); + mainQueue.setName("Main"); + mainQueue.setTopic("tb_rule_engine.main"); + mainQueue.setPollInterval(25); + mainQueue.setPartitions(1); + mainQueue.setConsumerPerPartition(false); + mainQueue.setPackProcessingTimeout(2000L); + + var submitStrategy = new SubmitStrategy(); + submitStrategy.setType(SubmitStrategyType.BURST); + submitStrategy.setBatchSize(1000); + mainQueue.setSubmitStrategy(submitStrategy); + + var processingStrategy = new ProcessingStrategy(); + processingStrategy.setType(ProcessingStrategyType.SKIP_ALL_FAILURES); + processingStrategy.setRetries(3); + processingStrategy.setFailurePercentage(0.0); + processingStrategy.setPauseBetweenRetries(3); + processingStrategy.setMaxPauseBetweenRetries(3); + mainQueue.setProcessingStrategy(processingStrategy); + + storage = new DefaultInMemoryStorage(); + + consumer = spy(new InMemoryTbQueueConsumer<>(storage, mainQueue.getTopic())); + given(queueFactory.createToRuleEngineMsgConsumer(eq(mainQueue), isNull())).willReturn(consumer); + + ruleEngineConsumerContext = new TbRuleEngineConsumerContext( + actorContext, statsFactory, new TbRuleEngineSubmitStrategyFactory(), new TbRuleEngineProcessingStrategyFactory(), + queueFactory, statisticsService, serviceInfoProvider, partitionService, producerProvider, queueAdmin + ); + ruleEngineConsumerContext.setPollDuration(25); + ruleEngineConsumerContext.setPackProcessingTimeout(2000); + ruleEngineConsumerContext.setStatsEnabled(false); // true by default + ruleEngineConsumerContext.setPrometheusStatsEnabled(false); + ruleEngineConsumerContext.setTopicDeletionDelayInSec(15); + ruleEngineConsumerContext.setMgmtThreadPoolSize(12); + + // Tell the (mock) context factory to return (mock) message pack context + given(packProcessingContextFactory.create( + eq(mainQueue.getName()), + any(TbRuleEngineSubmitStrategy.class), + eq(false) + )).willAnswer(invocation -> { + TbRuleEngineSubmitStrategy realStrategy = invocation.getArgument(1); + when(packCtx.getPendingMap()).thenAnswer(i -> realStrategy.getPendingMap()); + when(packCtx.getFailedMap()).thenReturn(new ConcurrentHashMap<>()); + return packCtx; + }); + + // Tell the (mock) context's await() to return 'false' (always timeout) immediately + given(packCtx.await(anyLong(), any(TimeUnit.class))).willReturn(false); + + consumerManager = TbRuleEngineQueueConsumerManager.create() + .ctx(ruleEngineConsumerContext) + .queueKey(new QueueKey(ServiceType.TB_RULE_ENGINE, mainQueue)) + .consumerExecutor(consumersExecutor) + .scheduler(scheduler) + .taskExecutor(mgmtExecutor) + .packProcessingContextFactory(packProcessingContextFactory) + .build(); + } + + @AfterEach + void destroy() { + MoreExecutors.shutdownAndAwaitTermination(scheduler, Duration.ofSeconds(30)); + MoreExecutors.shutdownAndAwaitTermination(mgmtExecutor, Duration.ofSeconds(30)); + MoreExecutors.shutdownAndAwaitTermination(consumersExecutor, Duration.ofSeconds(30)); + } + + @Test + void consumerLoopTest_verifyOperationsOrder() throws InterruptedException { + // Create partition + var partition = TopicPartitionInfo.builder() + .tenantId(TenantId.SYS_TENANT_ID) + .topic(mainQueue.getTopic()) + .partition(0) + .myPartition(true) + .useInternalPartition(false) + .build(); + + // Put 10k messages to the queue + for (int i = 0; i < 10_000; i++) { + var tbMsg = TbMsg.newMsg() + .type(TbMsgType.POST_TELEMETRY_REQUEST) + .originator(deviceId) + .data("{\"temperature\":123}") + .metaData(TbMsgMetaData.EMPTY) + .build(); + + var toRuleEngineMsg = TransportProtos.ToRuleEngineMsg.newBuilder() + .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) + .setTenantIdMSB(tenantId.getId().getMostSignificantBits()) + .setTbMsgProto(TbMsg.toProto(tbMsg)) + .addAllRelationTypes(Set.of("Success")) + .build(); + + storage.put(partition.getFullTopicName(), new TbProtoQueueMsg<>(UUID.randomUUID(), toRuleEngineMsg, new DefaultTbQueueMsgHeaders())); + } + + // Count how many polls were made + var totalPolls = new AtomicInteger(0); + var emptyPolls = new AtomicInteger(0); + doAnswer(invocation -> { + totalPolls.incrementAndGet(); + @SuppressWarnings("unchecked") + var messages = (List) invocation.callRealMethod(); + if (messages.isEmpty()) { + emptyPolls.incrementAndGet(); + } + return messages; + }).when(consumer).poll(mainQueue.getPollInterval()); + + // Count how many commits were made + var totalCommits = new AtomicInteger(0); + doAnswer(invocation -> { + totalCommits.incrementAndGet(); + return invocation.callRealMethod(); + }).when(consumer).commit(); + + // Initialize consumer + consumerManager.init(mainQueue); + + // Assign partition to the consumer + consumerManager.update(Set.of(partition)); + + // Give some time for the consumer to get all messages + await().atMost(Duration.ofSeconds(10L)).until(() -> storage.getLagTotal() == 0); + + // Stop consumer + consumerManager.stop(); + consumerManager.awaitStop(); + + // Determine number of non-empty consumer iterations made, since polling does not stop immediately after consuming all messages and may do a few empty polls + int nonEmptyPolls = totalPolls.get() - emptyPolls.get(); + + // Verify that there is 10 polls and 10 matching commits + // Each poll consumes 1k messages and queue has 10k total, so that means 10k total msgs / 1k msgs per poll = 10 polls + assertThat(nonEmptyPolls).isEqualTo(10).isEqualTo(totalCommits.get()); + + // Verify that poll-await-commit cycle happened in order with correct await timeout + InOrder inOrder = inOrder(consumer, packCtx); + for (int i = 0; i < nonEmptyPolls; i++) { + inOrder.verify(consumer).poll(mainQueue.getPollInterval()); + inOrder.verify(packCtx).await(mainQueue.getPackProcessingTimeout(), TimeUnit.MILLISECONDS); + inOrder.verify(consumer).commit(); + } + } + +} From 56a83b6cfec7794a92cae6889722d0bb5e565d0d Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Tue, 28 Oct 2025 16:19:05 +0200 Subject: [PATCH 002/742] Fix existing test --- .../queue/ruleengine/TbRuleEngineQueueConsumerManagerTest.java | 2 ++ .../service/queue/ruleengine/TbRuleEngineStrategyTest.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/application/src/test/java/org/thingsboard/server/service/queue/ruleengine/TbRuleEngineQueueConsumerManagerTest.java b/application/src/test/java/org/thingsboard/server/service/queue/ruleengine/TbRuleEngineQueueConsumerManagerTest.java index bcbe52b5c9..3c54d421e4 100644 --- a/application/src/test/java/org/thingsboard/server/service/queue/ruleengine/TbRuleEngineQueueConsumerManagerTest.java +++ b/application/src/test/java/org/thingsboard/server/service/queue/ruleengine/TbRuleEngineQueueConsumerManagerTest.java @@ -59,6 +59,7 @@ import org.thingsboard.server.queue.provider.KafkaMonolithQueueFactory; import org.thingsboard.server.queue.provider.KafkaTbRuleEngineQueueFactory; import org.thingsboard.server.queue.provider.TbQueueProducerProvider; import org.thingsboard.server.queue.provider.TbRuleEngineQueueFactory; +import org.thingsboard.server.service.queue.TbMsgPackProcessingContextFactory; import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingStrategyFactory; import org.thingsboard.server.service.queue.processing.TbRuleEngineSubmitStrategyFactory; import org.thingsboard.server.service.stats.RuleEngineStatisticsService; @@ -194,6 +195,7 @@ public class TbRuleEngineQueueConsumerManagerTest { .consumerExecutor(consumersExecutor) .scheduler(scheduler) .taskExecutor(mgmtExecutor) + .packProcessingContextFactory(new TbMsgPackProcessingContextFactory.DefaultTbMsgPackProcessingContextFactory()) .build(); } diff --git a/application/src/test/java/org/thingsboard/server/service/queue/ruleengine/TbRuleEngineStrategyTest.java b/application/src/test/java/org/thingsboard/server/service/queue/ruleengine/TbRuleEngineStrategyTest.java index 1106fad5b6..c27a03619a 100644 --- a/application/src/test/java/org/thingsboard/server/service/queue/ruleengine/TbRuleEngineStrategyTest.java +++ b/application/src/test/java/org/thingsboard/server/service/queue/ruleengine/TbRuleEngineStrategyTest.java @@ -44,6 +44,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.queue.TbQueueConsumer; import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.queue.discovery.QueueKey; +import org.thingsboard.server.service.queue.TbMsgPackProcessingContextFactory; import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingStrategyFactory; import org.thingsboard.server.service.queue.processing.TbRuleEngineSubmitStrategyFactory; @@ -194,6 +195,7 @@ public class TbRuleEngineStrategyTest { var consumerManager = TbRuleEngineQueueConsumerManager.create() .ctx(ruleEngineConsumerContext) .queueKey(queueKey) + .packProcessingContextFactory(new TbMsgPackProcessingContextFactory.DefaultTbMsgPackProcessingContextFactory()) .build(); consumerManager.init(queue); From cb2bd954b6a99e32596efc9be84d16040d18fab8 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Wed, 3 Dec 2025 13:20:15 +0200 Subject: [PATCH 003/742] Fix default value for Prometheus rule engine stats --- application/src/main/resources/thingsboard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 2ee0d23502..2cb53a8a4b 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -1913,7 +1913,7 @@ queue: max-error-message-length: "${TB_QUEUE_RULE_ENGINE_MAX_ERROR_MESSAGE_LENGTH:4096}" prometheus-stats: # Enable/disable Prometheus statistics for individual Rule Engine message processing (records time in ms for success/failure). - enabled: "${TB_QUEUE_RULE_ENGINE_PROMETHEUS_STATS_ENABLED:true}" + enabled: "${TB_QUEUE_RULE_ENGINE_PROMETHEUS_STATS_ENABLED:false}" # After a queue is deleted (or the profile's isolation option was disabled), Rule Engine will continue reading related topics during this period before deleting the actual topics topic-deletion-delay: "${TB_QUEUE_RULE_ENGINE_TOPIC_DELETION_DELAY_SEC:15}" # Size of the thread pool that handles such operations as partition changes, config updates, queue deletion From 3a098ef815bf55709ee8712ba3c1e3001a3e4c50 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Mon, 8 Dec 2025 16:56:35 +0200 Subject: [PATCH 004/742] REST API call node: better URL encoding # Conflicts: # common/data/src/main/java/org/thingsboard/server/common/data/util/CollectionsUtil.java --- .../common/data/util/CollectionsUtil.java | 10 + rule-engine/rule-engine-components/pom.xml | 4 + .../rule/engine/rest/TbHttpClient.java | 58 +- .../rule/engine/rest/TbRestApiCallNode.java | 13 +- .../rest/TbRestApiCallNodeConfiguration.java | 26 + .../rule/engine/rest/TbHttpClientTest.java | 498 +++++++++++++++--- .../engine/rest/TbRestApiCallNodeTest.java | 114 ++++ 7 files changed, 641 insertions(+), 82 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/util/CollectionsUtil.java b/common/data/src/main/java/org/thingsboard/server/common/data/util/CollectionsUtil.java index 082be9b71f..bdc4430387 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/util/CollectionsUtil.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/util/CollectionsUtil.java @@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.util; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -72,6 +73,15 @@ public class CollectionsUtil { return map; } + @SafeVarargs + public static LinkedHashMap orderedMapOf(Map.Entry... entries) { + LinkedHashMap map = new LinkedHashMap<>(); + for (Map.Entry entry : entries) { + map.put(entry.getKey(), entry.getValue()); + } + return map; + } + public static boolean emptyOrContains(Collection collection, V element) { return isEmpty(collection) || collection.contains(element); } diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml index 90e6a87e52..45e37d03f9 100644 --- a/rule-engine/rule-engine-components/pom.xml +++ b/rule-engine/rule-engine-components/pom.xml @@ -161,6 +161,10 @@ org.thingsboard.langchain4j langchain4j + + org.apache.httpcomponents.core5 + httpcore5 + diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index 63b4b70303..a16b3f5fb5 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -15,12 +15,14 @@ */ package org.thingsboard.rule.engine.rest; +import com.google.common.collect.Maps; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.handler.ssl.SslContext; import io.netty.handler.timeout.ReadTimeoutHandler; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.apache.hc.core5.net.URIBuilder; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; @@ -47,6 +49,7 @@ import reactor.netty.transport.ProxyProvider; import javax.net.ssl.SSLException; import java.net.URI; +import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.List; @@ -213,8 +216,21 @@ public class TbHttpClient { } String endpointUrl = TbNodeUtils.processPattern(config.getRestEndpointUrlPattern(), msg); + + Map processedQueryParams; + if (config.isUseNewEncoding()) { + processedQueryParams = Maps.newHashMapWithExpectedSize(config.getQueryParams().size()); + config.getQueryParams().forEach((name, value) -> { + var processedParamName = TbNodeUtils.processPattern(name, msg); + var processedParamValue = TbNodeUtils.processPattern(value, msg); + processedQueryParams.put(processedParamName, processedParamValue); + }); + } else { + processedQueryParams = null; + } + HttpMethod method = HttpMethod.valueOf(config.getRequestMethod()); - URI uri = buildEncodedUri(endpointUrl); + URI uri = buildEncodedUri(endpointUrl, processedQueryParams); RequestBodySpec request = webClient .method(method) @@ -262,7 +278,7 @@ public class TbHttpClient { return origin; } - public URI buildEncodedUri(String endpointUrl) { + public URI buildEncodedUri(String endpointUrl, Map queryParams) { if (endpointUrl == null) { throw new RuntimeException("Url string cannot be null!"); } @@ -270,7 +286,13 @@ public class TbHttpClient { throw new RuntimeException("Url string cannot be empty!"); } - URI uri = UriComponentsBuilder.fromUriString(endpointUrl).build().encode().toUri(); + URI uri; + if (queryParams != null) { + uri = buildEncodedUriNew(endpointUrl, queryParams); + } else { + uri = buildEncodedUriLegacy(endpointUrl); + } + if (uri.getScheme() == null || uri.getScheme().isEmpty()) { throw new RuntimeException("Transport scheme(protocol) must be provided!"); } @@ -284,6 +306,36 @@ public class TbHttpClient { return uri; } + private URI buildEncodedUriNew(String endpointUrl, Map queryParams) { + try { + URIBuilder builder = new URIBuilder(endpointUrl); + queryParams.forEach(builder::addParameter); + return builder.build(); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(""" + Invalid REST endpoint URL: '%s'. The URL must be valid and properly encoded. + If the path contains special characters (e.g., spaces, braces), they must be percent-encoded (e.g., '/my file/' should be '/my%%20file/', '/path/{id}/' should be '/path/%%7Bid%%7D/'). + Query parameters should be configured separately and will be encoded automatically.""".formatted(endpointUrl), e); + } + } + + /** + * @deprecated Query params embedded in the URL string are not encoded correctly. + *

+ * In query strings, {@code +} is interpreted as a space (URL form encoding), + * so {@code email=user+tag@test.com} becomes {@code email=user tag@test.com} on the server. + *

+ * Pre-encoding the URL (e.g., {@code email=user%2Btag@test.com}) doesn't help + * because {@code .encode()} will double-encode it to {@code email=user%252Btag@test.com}. + *

+ * Use {@link #buildEncodedUriNew} with a separate query params map, + * where values are encoded exactly once: {@code +} → {@code %2B}, {@code @} → {@code %40}. + */ + @Deprecated(since = "4.2.1.2", forRemoval = true) // fixme: remove in major 5.0 + private URI buildEncodedUriLegacy(String endpointUrl) { + return UriComponentsBuilder.fromUriString(endpointUrl).build().encode().toUri(); + } + private Object getData(TbMsg tbMsg, boolean parseToPlainText) { String data = tbMsg.getData(); return parseToPlainText ? JacksonUtil.toPlainText(data) : JacksonUtil.toJsonNode(data); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java index a2290a4eda..3e9b034693 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java @@ -26,9 +26,12 @@ import org.thingsboard.rule.engine.external.TbAbstractExternalNode; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.util.TbPair; import org.thingsboard.server.common.msg.TbMsg; +import org.thingsboard.server.dao.exception.DataValidationException; import java.util.List; +import static org.thingsboard.server.dao.service.ConstraintValidator.validateFields; + @RuleNode( type = ComponentType.EXTERNAL, name = "rest api call", @@ -57,7 +60,15 @@ public class TbRestApiCallNode extends TbAbstractExternalNode { @Override public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { super.init(ctx); - TbRestApiCallNodeConfiguration config = TbNodeUtils.convert(configuration, TbRestApiCallNodeConfiguration.class); + + var config = TbNodeUtils.convert(configuration, TbRestApiCallNodeConfiguration.class); + String errorPrefix = "'" + ctx.getSelf().getName() + "' node configuration is invalid: "; + try { + validateFields(config, errorPrefix); + } catch (DataValidationException e) { + throw new TbNodeException(e, true); + } + httpClient = new TbHttpClient(config, ctx.getSharedEventLoop()); } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java index 43ed0c597e..c896dea324 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java @@ -15,7 +15,10 @@ */ package org.thingsboard.rule.engine.rest; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.NotNull; import lombok.Data; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; @@ -32,6 +35,8 @@ public class TbRestApiCallNodeConfiguration implements NodeConfiguration queryParams; private Map headers; private boolean useSimpleClientHttpFactory; private int readTimeoutMs; @@ -48,12 +53,32 @@ public class TbRestApiCallNodeConfiguration implements NodeConfiguration client.buildEncodedUri(url)); + assertThatThrownBy(() -> client.buildEncodedUri(url, null)); } @Test public void testBuildInvalidUri() { - Mockito.when(client.buildEncodedUri(any())).thenCallRealMethod(); + Mockito.when(client.buildEncodedUri(any(), any())).thenCallRealMethod(); String url = "aaa"; - assertThatThrownBy(() -> client.buildEncodedUri(url)); + assertThatThrownBy(() -> client.buildEncodedUri(url, null)); } @Test public void testBuildUriWithSpecialSymbols() { - Mockito.when(client.buildEncodedUri(any())).thenCallRealMethod(); + Mockito.when(client.buildEncodedUri(any(), any())).thenCallRealMethod(); String url = "http://192.168.1.1/data?d={\"a\": 12}"; String expected = "http://192.168.1.1/data?d=%7B%22a%22:%2012%7D"; - URI uri = client.buildEncodedUri(url); + URI uri = client.buildEncodedUri(url, null); Assertions.assertEquals(expected, uri.toString()); } + @Test + public void testProcessMessageWithQueryParamsPatternProcessing() throws Exception { + // GIVEN + String path = "/api/notify"; + try (var server = startClientAndServer("localhost", 0)) { + server.when( + request() + .withMethod("GET") + .withPath(path) + .withQueryStringParameter("email", "user+tag@test.com") + .withQueryStringParameter("device", "sensor-1") + .withQueryStringParameter("custom-header", "header-value") + .withQueryStringParameter("temp", "25.5") + .withQueryStringParameter("location", "room-1/zone-A") + ).respond( + response().withStatusCode(200) + ); + + var config = new TbRestApiCallNodeConfiguration().defaultConfiguration(); + config.setRestEndpointUrlPattern("http://localhost:" + server.getPort() + path); + config.setRequestMethod("GET"); + config.setUseSimpleClientHttpFactory(true); + config.setUseNewEncoding(true); + config.setQueryParams(Map.of( + "email", "${userEmail}", // ${} from metadata + "device", "${deviceName}", // ${} from metadata + "${dynamicParam}", "${dynamicValue}", // ${} in both key and value + "temp", "$[temperature]", // $[] from data + "location", "$[sensor.location]" // $[] from nested data + )); + + var metaData = new TbMsgMetaData(); + metaData.putValue("userEmail", "user+tag@test.com"); + metaData.putValue("deviceName", "sensor-1"); + metaData.putValue("dynamicParam", "custom-header"); + metaData.putValue("dynamicValue", "header-value"); + + var msg = TbMsg.newMsg() + .type(TbMsgType.POST_TELEMETRY_REQUEST) + .originator(new DeviceId(EntityId.NULL_UUID)) + .metaData(metaData) + .data(""" + {"temperature": 25.5, "sensor": {"location": "room-1/zone-A"}} + """) + .build(); + + // WHEN-THEN + processMessageAndWait(config, msg); + } + } + @Test public void testProcessMessageWithJsonInUrlVariable() throws Exception { - String host = "localhost"; + // GIVEN String path = "/api"; - String paramKey = "data"; - String paramVal = "[{\"test\":\"test\"}]"; - String successResponseBody = "SUCCESS"; - - var server = setUpDummyServer(host, path, paramKey, paramVal, successResponseBody); - - String endpointUrl = String.format( - "http://%s:%d%s?%s=%s", - host, server.getPort(), path, paramKey, paramVal - ); - String method = "GET"; - - - var config = new TbRestApiCallNodeConfiguration() - .defaultConfiguration(); - config.setRequestMethod(method); - config.setRestEndpointUrlPattern(endpointUrl); - config.setUseSimpleClientHttpFactory(true); + String paramValue = "[{\"test\":\"test\"}]"; + + try (var server = startClientAndServer("localhost", 0)) { + server.when( + request() + .withMethod("GET") + .withPath(path) + .withQueryStringParameter("data", paramValue) + ).respond( + response().withStatusCode(200) + ); + + var config = new TbRestApiCallNodeConfiguration().defaultConfiguration(); + config.setRestEndpointUrlPattern("http://localhost:" + server.getPort() + path + "?data=" + paramValue); + config.setRequestMethod("GET"); + config.setUseNewEncoding(false); + config.setQueryParams(null); + + var msg = TbMsg.newMsg() + .type(TbMsgType.POST_TELEMETRY_REQUEST) + .originator(new DeviceId(UUID.randomUUID())) + .metaData(new TbMsgMetaData()) + .data(TbMsg.EMPTY_JSON_OBJECT) + .build(); + + // WHEN-THEN + processMessageAndWait(config, msg); + } + } + private void processMessageAndWait(TbRestApiCallNodeConfiguration config, TbMsg msg) throws Exception { var httpClient = new TbHttpClient(config, eventLoop); - - var msg = TbMsg.newMsg() - .type(TbMsgType.POST_TELEMETRY_REQUEST) - .originator(new DeviceId(EntityId.NULL_UUID)) - .copyMetaData(TbMsgMetaData.EMPTY) - .data(TbMsg.EMPTY_JSON_OBJECT) - .build(); - var successMsg = TbMsg.newMsg() - .type(TbMsgType.POST_TELEMETRY_REQUEST) - .originator(msg.getOriginator()) - .copyMetaData(msg.getMetaData()) - .data(msg.getData()) - .build(); - var ctx = mock(TbContext.class); - when(ctx.transformMsg( - eq(msg), - eq(msg.getMetaData()), - eq(msg.getData()) - )).thenReturn(successMsg); - - var capturedData = ArgumentCaptor.forClass(String.class); + when(ctx.transformMsg(eq(msg), any(), any())).thenReturn(msg); - when(ctx.transformMsg( - eq(msg), - any(), - capturedData.capture() - )).thenReturn(successMsg); - - CountDownLatch latch = new CountDownLatch(1); + var latch = new CountDownLatch(1); + var error = new AtomicReference(); httpClient.processMessage(ctx, msg, m -> { - ctx.tellSuccess(msg); + ctx.tellSuccess(m); latch.countDown(); }, (m, t) -> { ctx.tellFailure(m, t); + error.set(t); latch.countDown(); }); - latch.await(5, TimeUnit.SECONDS); + assertTrue(latch.await(5, TimeUnit.SECONDS), "Request should complete within timeout"); + assertNull(error.get(), "Request should succeed, but got: " + error.get()); - verify(ctx, times(1)).tellSuccess(any()); - verify(ctx, times(0)).tellFailure(any(), any()); - Assertions.assertEquals(successResponseBody, capturedData.getValue()); + verify(ctx).tellSuccess(any()); + verify(ctx, never()).tellFailure(any(), any()); } - private ClientAndServer setUpDummyServer(String host, String path, String paramKey, String paramVal, String successResponseBody) { - var server = startClientAndServer(host, 1080); - createGetMethodExpectations(server, path, paramKey, paramVal, successResponseBody); - return server; + + @ParameterizedTest(name = "{0}") + @MethodSource + public void testQueryParamsEncoding(String endpointUrl, Map queryParams, String expectedEncodedUrl) { + // GIVEN + Mockito.when(client.buildEncodedUri(any(), any())).thenCallRealMethod(); + + // WHEN + URI uri = client.buildEncodedUri(endpointUrl, queryParams); + + // THEN + Assertions.assertEquals(expectedEncodedUrl, uri.toASCIIString()); } - private void createGetMethodExpectations(ClientAndServer server, String path, String paramKey, String paramVal, String successResponseBody) { - server.when( - request() - .withMethod("GET") - .withPath(path) - .withQueryStringParameter(paramKey, paramVal) - ).respond( - response() - .withStatusCode(200) - .withBody(successResponseBody) + private static Stream testQueryParamsEncoding() { + return Stream.of( + Arguments.of( + Named.named("ISO 8601 date-time in value", "http://somecompany/api/data/fetch"), + Map.of("ts", "2016-08-01T09:06:06.0+02:00"), + "http://somecompany/api/data/fetch?ts=2016-08-01T09%3A06%3A06.0%2B02%3A00" + ), + Arguments.of( + Named.named("email with plus sign in value", "http://localhost:8080/api/user/sendActivationMail"), + Map.of("email", "someperson+test1289@thingsboard.io"), + "http://localhost:8080/api/user/sendActivationMail?email=someperson%2Btest1289%40thingsboard.io" + ), + Arguments.of( + Named.named("plus mixed with spaces in value", "http://url/api"), + Map.of("q", "a + b"), + "http://url/api?q=a%20%2B%20b" + ), + Arguments.of( + Named.named("colon in value", "http://url/api"), + Map.of("time", "12:00"), + "http://url/api?time=12%3A00" + ), + Arguments.of( + Named.named("slash in value", "http://url"), + Map.of("ref", "/home/user"), + "http://url?ref=%2Fhome%2Fuser" + ), + Arguments.of( + Named.named("comma and semicolon in value", "http://url"), + Map.of("l", "a,b;c"), + "http://url?l=a%2Cb%3Bc" + ), + Arguments.of( + Named.named("ampersand and equals in value", "http://url"), + Map.of("q", "key1=value1&key2=value2"), + "http://url?q=key1%3Dvalue1%26key2%3Dvalue2" + ), + Arguments.of( + Named.named("JSON in value", "http://url"), + Map.of("json", """ + { + "string": "hello", + "integer": 42, + "float": 3.14, + "boolTrue": true, + "boolFalse": false, + "null": null, + "array": [ + 1, + "two", + true, + null + ], + "object": { + "nested": "value" + } + }"""), + "http://url?json=%7B%0A%20%20%20%20%22string%22%3A%20%22hello%22%2C%0A%20%20%20%20%22integer%22%3A%2042%2C%0A%20%20%20%20%22float%22%3A%203.14%2C%0A%20%20%20%20%22boolTrue%22%3A%20true%2C%0A%20%20%20%20%22boolFalse%22%3A%20false%2C%0A%20%20%20%20%22null%22%3A%20null%2C%0A%20%20%20%20%22array%22%3A%20%5B%0A%20%20%20%20%20%20%20%201%2C%0A%20%20%20%20%20%20%20%20%22two%22%2C%0A%20%20%20%20%20%20%20%20true%2C%0A%20%20%20%20%20%20%20%20null%0A%20%20%20%20%5D%2C%0A%20%20%20%20%22object%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22nested%22%3A%20%22value%22%0A%20%20%20%20%7D%0A%7D" + ), + Arguments.of( + Named.named("UTF-8 in query", "http://url/cafes"), + orderedMapOf( + entry("nom", "Le Goût Moderne"), + entry("назва", "У Миколи \uD83D\uDE0B") + ), + "http://url/cafes?nom=Le%20Go%C3%BBt%20Moderne&%D0%BD%D0%B0%D0%B7%D0%B2%D0%B0=%D0%A3%20%D0%9C%D0%B8%D0%BA%D0%BE%D0%BB%D0%B8%20%F0%9F%98%8B" + ), + Arguments.of( + Named.named("empty value", "http://url/empty"), + Map.of("name", ""), + "http://url/empty?name=" + ), + Arguments.of( + Named.named("blank value (spaces)", "http://url/empty"), + Map.of("name", " "), + "http://url/empty?name=%20%20" + ), + Arguments.of( + Named.named("empty key", "http://url/empty"), + Map.of("", "value"), + "http://url/empty?=value" + ), + Arguments.of( + Named.named("blank key (spaces)", "http://url/empty"), + Map.of(" ", "value"), + "http://url/empty?%20%20=value" + ), + Arguments.of( + Named.named("blank key with value that needs to be encoded", "http://url/empty"), + Map.of(" ", "value1+value2"), + "http://url/empty?%20%20=value1%2Bvalue2" + ), + Arguments.of( + Named.named("blank key and value", "http://url/empty"), + Map.of(" ", " "), + "http://url/empty?%20%20=%20%20" + ), + Arguments.of( + Named.named("fragment with query params", "http://url#frag"), + Map.of("docs", "مستندات عقدة القاعدة\n"), + "http://url?docs=%D9%85%D8%B3%D8%AA%D9%86%D8%AF%D8%A7%D8%AA%20%D8%B9%D9%82%D8%AF%D8%A9%20%D8%A7%D9%84%D9%82%D8%A7%D8%B9%D8%AF%D8%A9%0A#frag" + ), + Arguments.of( + Named.named("fragment only", "http://url#frag"), + Collections.emptyMap(), + "http://url#frag" + ), + Arguments.of( + Named.named("multiple query params (ordered)", "http://url/api"), + orderedMapOf( + entry("param1", "value1"), + entry("param2", "value2"), + entry("param3", "value3") + ), + "http://url/api?param1=value1¶m2=value2¶m3=value3" + ), + Arguments.of( + Named.named("hash (#) in value", "http://url/api"), + Map.of("color", "#ff0000"), + "http://url/api?color=%23ff0000" + ), + Arguments.of( + Named.named("question mark (?) in value", "http://url/api"), + Map.of("query", "what?"), + "http://url/api?query=what%3F" + ), + Arguments.of( + Named.named("percent sign (%) in value", "http://url/api"), + Map.of("discount", "50%"), + "http://url/api?discount=50%25" + ), + Arguments.of( + Named.named("already encoded string - double encoding", "http://url/api"), + Map.of("encoded", "%20"), + "http://url/api?encoded=%2520" + ), + Arguments.of( + Named.named("URL with port number", "http://localhost:8080/api/v1/data"), + Map.of("key", "value"), + "http://localhost:8080/api/v1/data?key=value" + ), + Arguments.of( + Named.named("URL with userinfo (auth)", "http://user:password@hostname/path"), + Map.of("secure", "true"), + "http://user:password@hostname/path?secure=true" + ), + Arguments.of( + Named.named("IPv4 address in URL", "http://192.168.1.100:9090/endpoint"), + Map.of("ip", "test"), + "http://192.168.1.100:9090/endpoint?ip=test" + ), + Arguments.of( + Named.named("IPv6 address in URL", "http://[::1]:8080/api"), + Map.of("ipv6", "true"), + "http://[::1]:8080/api?ipv6=true" + ), + Arguments.of( + Named.named("HTTPS protocol", "https://secure.example.com/api"), + Map.of("token", "abc123"), + "https://secure.example.com/api?token=abc123" + ), + Arguments.of( + Named.named("pipe (|) in value", "http://url/api"), + Map.of("filter", "a|b|c"), + "http://url/api?filter=a%7Cb%7Cc" + ), + Arguments.of( + Named.named("caret (^) and backtick (`) in value", "http://url/api"), + Map.of("special", "a^b`c"), + "http://url/api?special=a%5Eb%60c" + ), + Arguments.of( + Named.named("tab character in value", "http://url/api"), + Map.of("data", "col1\tcol2\tcol3"), + "http://url/api?data=col1%09col2%09col3" + ), + Arguments.of( + Named.named("CRLF in value", "http://url/api"), + Map.of("text", "line1\r\nline2"), + "http://url/api?text=line1%0D%0Aline2" + ), + Arguments.of( + Named.named("square brackets in value", "http://url/api"), + Map.of("array", "[1,2,3]"), + "http://url/api?array=%5B1%2C2%2C3%5D" + ), + Arguments.of( + Named.named("single and double quotes in value", "http://url/api"), + Map.of("quoted", "He said \"Hello\" and 'Hi'"), + "http://url/api?quoted=He%20said%20%22Hello%22%20and%20%27Hi%27" + ), + Arguments.of( + Named.named("angle brackets in value (XSS test)", "http://url/api"), + Map.of("html", ""), + "http://url/api?html=%3Cscript%3Ealert%28%27xss%27%29%3C%2Fscript%3E" + ), + Arguments.of( + Named.named("backslash in value", "http://url/api"), + Map.of("path", "C:\\Users\\test"), + "http://url/api?path=C%3A%5CUsers%5Ctest" + ), + Arguments.of( + Named.named("at sign (@) in value", "http://url/api"), + Map.of("contact", "user@domain.com"), + "http://url/api?contact=user%40domain.com" + ), + Arguments.of( + Named.named("URL as value", "http://url/api"), + Map.of("redirect", "https://example.com/path?foo=bar"), + "http://url/api?redirect=https%3A%2F%2Fexample.com%2Fpath%3Ffoo%3Dbar" + ), + Arguments.of( + Named.named("empty map (not null)", "http://url/api"), + Collections.emptyMap(), + "http://url/api" + ), + Arguments.of( + Named.named("underscore and hyphen in key/value", "http://url/api"), + Map.of("my-key_name", "my-value_data"), + "http://url/api?my-key_name=my-value_data" + ), + Arguments.of( + Named.named("dots in key and value", "http://url/api"), + Map.of("version.major", "1.2.3"), + "http://url/api?version.major=1.2.3" + ), + Arguments.of( + Named.named("multiple reserved chars combined", "http://url/api"), + Map.of("complex", "a=1&b=2#section?query"), + "http://url/api?complex=a%3D1%26b%3D2%23section%3Fquery" + ), + Arguments.of( + Named.named("trailing slash in URL", "http://url/api/"), + Map.of("param", "value"), + "http://url/api/?param=value" + ), + Arguments.of( + Named.named("long value (1000 chars)", "http://url/api"), + Map.of("long", "a".repeat(1000)), + "http://url/api?long=" + "a".repeat(1000) + ), + Arguments.of( + Named.named("Chinese characters in value", "http://url/api"), + Map.of("greeting", "你好世界"), + "http://url/api?greeting=%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C" + ), + Arguments.of( + Named.named("Japanese characters in value", "http://url/api"), + Map.of("text", "こんにちは"), + "http://url/api?text=%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF" + ), + Arguments.of( + Named.named("existing query params in URL", "http://url/api?existing=param"), + Map.of("new", "value"), + "http://url/api?existing=param&new=value" + ), + Arguments.of( + Named.named("existing query and fragment in URL", "http://url/api?existing=param#section"), + Map.of("additional", "data"), + "http://url/api?existing=param&additional=data#section" + ), + Arguments.of( + Named.named("null byte in value", "http://url/api"), + Map.of("data", "before\u0000after"), + "http://url/api?data=before%00after" + ), + Arguments.of( + Named.named("form feed and vertical tab in value", "http://url/api"), + Map.of("whitespace", "a\fb\u000Bc"), + "http://url/api?whitespace=a%0Cb%0Bc" + ), + Arguments.of( + Named.named("tilde (unreserved, not encoded)", "http://url/api"), + Map.of("pattern", "~user"), + "http://url/api?pattern=~user" + ), + Arguments.of( + Named.named("asterisk in value", "http://url/api"), + Map.of("wildcard", "*.txt"), + "http://url/api?wildcard=%2A.txt" + ), + Arguments.of( + Named.named("curly braces in key", "http://url/api"), + Map.of("{key}", "value"), + "http://url/api?%7Bkey%7D=value" + ), + Arguments.of( + Named.named("curly braces in value", "http://url/api"), + Map.of("data", "{value}"), + "http://url/api?data=%7Bvalue%7D" + ), + Arguments.of( + Named.named("curly braces in both key and value", "http://url/api"), + Map.of("{param}", "{data}"), + "http://url/api?%7Bparam%7D=%7Bdata%7D" + ) ); } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java index 9c3121f790..8c3654bdc5 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java @@ -25,6 +25,7 @@ import org.apache.http.impl.bootstrap.ServerBootstrap; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpRequestHandler; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.provider.Arguments; @@ -43,24 +44,34 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.msg.TbMsgType; +import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgDataType; import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.dao.exception.DataValidationException; import java.io.IOException; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.verify; @ExtendWith(MockitoExtension.class) public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest { + private RuleNode ruleNode; + @Spy private TbRestApiCallNode restNode; @@ -94,6 +105,14 @@ public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest { } } + @BeforeEach + public void setup() { + ruleNode = new RuleNode(); + ruleNode.setId(ruleNodeId); + ruleNode.setName("Test REST API call node"); + lenient().when(ctx.getSelf()).thenReturn(ruleNode); + } + @AfterEach public void teardown() { if (server != null) { @@ -101,6 +120,101 @@ public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest { } } + @Test + public void shouldNotAllowNullQueryParamValues() { + // GIVEN + var config = new TbRestApiCallNodeConfiguration().defaultConfiguration(); + config.setUseNewEncoding(true); + var params = new HashMap(); + params.put("key", null); + config.setQueryParams(params); + + // WHEN-THEN + assertThatThrownBy(() -> new TbRestApiCallNode().init(ctx, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) + .isInstanceOf(TbNodeException.class) + .matches(e -> ((TbNodeException) e).isUnrecoverable()) + .rootCause() + .isInstanceOf(DataValidationException.class) + .hasMessageContaining("query parameter values must be non-null"); + } + + @Test + public void shouldAllowOnlyNullQueryParamsIfOldEncodingIsUsed() { + // GIVEN + var config = new TbRestApiCallNodeConfiguration().defaultConfiguration(); + config.setUseNewEncoding(false); + config.setQueryParams(Map.of("key", "value")); + + // WHEN-THEN + assertThatThrownBy(() -> new TbRestApiCallNode().init(ctx, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) + .isInstanceOf(TbNodeException.class) + .hasRootCauseInstanceOf(DataValidationException.class) + .hasRootCauseMessage("'" + ruleNode.getName() + "' node configuration is invalid: query parameters must be null if old encoding is used") + .matches(e -> ((TbNodeException) e).isUnrecoverable()); + } + + @Test + public void shouldNotAllowNullQueryParamsIfNewEncodingIsUsed() { + // GIVEN + var config = new TbRestApiCallNodeConfiguration().defaultConfiguration(); + config.setUseNewEncoding(true); + config.setQueryParams(null); + + // WHEN-THEN + assertThatThrownBy(() -> new TbRestApiCallNode().init(ctx, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) + .isInstanceOf(TbNodeException.class) + .hasRootCauseInstanceOf(DataValidationException.class) + .hasRootCauseMessage("'" + ruleNode.getName() + "' node configuration is invalid: query parameters must be non-null if new encoding is used") + .matches(e -> ((TbNodeException) e).isUnrecoverable()); + } + + @Test + public void shouldUseNewEncodingForNewNodesByDefault() { + // GIVEN-WHEN + var defaultConfig = new TbRestApiCallNodeConfiguration().defaultConfiguration(); + + // THEN + assertTrue(defaultConfig.isUseNewEncoding()); + assertEquals(Collections.emptyMap(), defaultConfig.getQueryParams()); + } + + @Test + public void shouldDefaultToOldEncodingForLegacyConfigs() { + // GIVEN + String configJson = """ + { + "restEndpointUrlPattern": "http://url?param=value", + "requestMethod": "GET", + "useSimpleClientHttpFactory": false, + "parseToPlainText": false, + "ignoreRequestBody": false, + "enableProxy": false, + "useSystemProxyProperties": false, + "proxyScheme": null, + "proxyHost": null, + "proxyPort": 0, + "proxyUser": null, + "proxyPassword": null, + "readTimeoutMs": 0, + "maxParallelRequestsCount": 0, + "headers": { + "Content-Type": "application/json", + "X-Authorization": "Bearer eyJhbGciOi...." + }, + "credentials": { + "type": "anonymous" + }, + "maxInMemoryBufferSizeInKb": 256 + }"""; + + // WHEN + var config = JacksonUtil.fromString(configJson, TbRestApiCallNodeConfiguration.class); + + // THEN + assertFalse(config.isUseNewEncoding()); + assertNull(config.getQueryParams()); + } + @Test public void deleteRequestWithoutBody() throws IOException, InterruptedException { final CountDownLatch latch = new CountDownLatch(1); From a36749b228a9bc044367bb087fd3d82d6f1bf8f8 Mon Sep 17 00:00:00 2001 From: Nikita Mazurenko Date: Tue, 16 Dec 2025 13:54:10 +0200 Subject: [PATCH 005/742] Refactor EdgeGrpcService, EdgeGrpcSession and related Postgres & Kafka event processing --- .../service/edge/EdgeContextComponent.java | 19 +- .../edge/rpc/DownlinkMessageMapper.java | 79 ++ .../service/edge/rpc/EdgeGrpcService.java | 711 ------------- .../service/edge/rpc/EdgeGrpcSession.java | 994 ------------------ .../service/edge/rpc/EdgeRpcService.java | 1 - .../service/edge/rpc/EdgeSessionState.java | 57 +- .../edge/rpc/EdgeUplinkMessageDispatcher.java | 223 ++++ .../server/service/edge/rpc/GrpcServer.java | 103 ++ .../edge/rpc/KafkaEdgeGrpcSession.java | 184 ---- .../edge/rpc/PostgresEdgeGrpcSession.java | 46 - .../rpc/processor/EdgeEventsDispatcher.java | 23 + .../PostgresGeneralEdgeEventsDispatcher.java | 218 ++++ .../edge/rpc/service/EdgeRpcServiceImpl.java | 386 +++++++ .../edge/rpc/session/BaseEdgeSession.java | 604 +++++++++++ .../DefaultZombieSessionCleanupService.java | 122 +++ .../session/EdgeAttributeSaveCallback.java | 49 + .../rpc/session/EdgeGrpcSessionDelegate.java | 34 + .../service/edge/rpc/session/EdgeSession.java | 43 + .../edge/rpc/session/EdgeSessionsHolder.java | 74 ++ .../session/ZombieSessionCleanupService.java | 23 + .../AbstractEdgeGrpcSessionManager.java | 128 +++ .../manager/EdgeGrpcSessionManager.java | 47 + .../KafkaBasedEdgeGrpcSessionManager.java | 282 +++++ .../PostgresBasedEdgeGrpcSessionManager.java | 180 ++++ .../src/test/resources/logback-test.xml | 3 - 25 files changed, 2690 insertions(+), 1943 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/DownlinkMessageMapper.java delete mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java delete mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeUplinkMessageDispatcher.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/GrpcServer.java delete mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/KafkaEdgeGrpcSession.java delete mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/PostgresEdgeGrpcSession.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/EdgeEventsDispatcher.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/PostgresGeneralEdgeEventsDispatcher.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/service/EdgeRpcServiceImpl.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/session/BaseEdgeSession.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/session/DefaultZombieSessionCleanupService.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeAttributeSaveCallback.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeGrpcSessionDelegate.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeSession.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeSessionsHolder.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/session/ZombieSessionCleanupService.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/AbstractEdgeGrpcSessionManager.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/EdgeGrpcSessionManager.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/KafkaBasedEdgeGrpcSessionManager.java create mode 100644 application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/PostgresBasedEdgeGrpcSessionManager.java diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java index ec4a43310b..163758fa4b 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java @@ -15,11 +15,14 @@ */ package org.thingsboard.server.service.edge; +import jakarta.annotation.PreDestroy; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; +import org.thingsboard.common.util.ThingsBoardExecutors; import org.thingsboard.server.cache.limits.RateLimitService; import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.common.data.edge.EdgeEventType; @@ -83,6 +86,8 @@ import java.util.EnumMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; @Lazy @Data @@ -91,8 +96,13 @@ import java.util.Optional; @TbCoreComponent public class EdgeContextComponent { + @Value("${edges.scheduler_pool_size}") + private int schedulerPoolSize; + private final Map processorMap = new EnumMap<>(EdgeEventType.class); + private ScheduledExecutorService edgeEventProcessingExecutorService; + @Autowired public EdgeContextComponent(List processors) { processors.forEach(processor -> { @@ -101,6 +111,14 @@ public class EdgeContextComponent { processorMap.put(eventType, processor); } }); + this.edgeEventProcessingExecutorService = ThingsBoardExecutors.newScheduledThreadPool(schedulerPoolSize, "edge-event-check-scheduler"); + } + + @PreDestroy + private void destroy() { + if (edgeEventProcessingExecutorService != null && !edgeEventProcessingExecutorService.isShutdown()) { + edgeEventProcessingExecutorService.shutdownNow(); + } } // services @@ -206,7 +224,6 @@ public class EdgeContextComponent { @Autowired private Optional statsCounterService; - // processors @Autowired private AlarmProcessor alarmProcessor; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/DownlinkMessageMapper.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/DownlinkMessageMapper.java new file mode 100644 index 0000000000..3204d6901b --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/DownlinkMessageMapper.java @@ -0,0 +1,79 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.edge.EdgeEventType; +import org.thingsboard.server.gen.edge.v1.DownlinkMsg; +import org.thingsboard.server.gen.edge.v1.EdgeVersion; +import org.thingsboard.server.service.edge.EdgeContextComponent; +import org.thingsboard.server.service.edge.rpc.utils.EdgeVersionUtils; + +import java.util.ArrayList; +import java.util.List; + +@Component +@Slf4j +@RequiredArgsConstructor +public class DownlinkMessageMapper { + + private final EdgeContextComponent ctx; + + public List convertToDownlinkMsgsPack(EdgeSessionState state, List edgeEvents) { + List result = new ArrayList<>(); + for (EdgeEvent edgeEvent : edgeEvents) { + log.trace("[{}][{}] converting edge event to downlink msg [{}]", state.getTenantId(), state.getEdgeId(), edgeEvent); + DownlinkMsg downlinkMsg = null; + try { + switch (edgeEvent.getAction()) { + case UPDATED, ADDED, DELETED, ASSIGNED_TO_EDGE, UNASSIGNED_FROM_EDGE, ALARM_ACK, ALARM_CLEAR, + ALARM_DELETE, CREDENTIALS_UPDATED, RELATION_ADD_OR_UPDATE, RELATION_DELETED, RPC_CALL, + ASSIGNED_TO_CUSTOMER, UNASSIGNED_FROM_CUSTOMER, ADDED_COMMENT, UPDATED_COMMENT, DELETED_COMMENT -> { + downlinkMsg = convertEntityEventToDownlink(state, edgeEvent); + if (downlinkMsg != null && downlinkMsg.getWidgetTypeUpdateMsgCount() > 0) { + log.trace("[{}][{}] widgetTypeUpdateMsg message processed, downlinkMsgId = {}", + state.getTenantId(), state.getEdgeId(), downlinkMsg.getDownlinkMsgId()); + } else { + log.trace("[{}][{}] entity message processed [{}]", state.getTenantId(), state.getEdgeId(), downlinkMsg); + } + } + case ATTRIBUTES_UPDATED, POST_ATTRIBUTES, ATTRIBUTES_DELETED, TIMESERIES_UPDATED -> + downlinkMsg = ctx.getTelemetryProcessor().convertTelemetryEventToDownlink(state.getEdge(), edgeEvent); + default -> log.warn("[{}][{}] Unsupported action type [{}]", state.getTenantId(), state.getEdgeId(), edgeEvent.getAction()); + } + } catch (Exception e) { + log.trace("[{}][{}] Exception during converting edge event to downlink msg", state.getTenantId(), state.getEdgeId(), e); + } + if (downlinkMsg != null) { + result.add(downlinkMsg); + } + } + return result; + } + + protected DownlinkMsg convertEntityEventToDownlink(EdgeSessionState state, EdgeEvent edgeEvent) { + log.trace("[{}] Executing convertEntityEventToDownlink, edgeEvent [{}], action [{}]", edgeEvent.getTenantId(), edgeEvent, edgeEvent.getAction()); + if ((EdgeEventType.OAUTH2_CLIENT.equals(edgeEvent.getType()) || EdgeEventType.DOMAIN.equals(edgeEvent.getType())) && + (EdgeVersionUtils.isEdgeVersionOlderThan(state.getEdgeVersion(), EdgeVersion.V_3_8_0))) { + return null; + } + + return ctx.getProcessor(edgeEvent.getType()).convertEdgeEventToDownlink(edgeEvent, state.getEdgeVersion()); + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java deleted file mode 100644 index 1827b986fd..0000000000 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java +++ /dev/null @@ -1,711 +0,0 @@ -/** - * Copyright © 2016-2025 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.service.edge.rpc; - -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; -import io.grpc.Server; -import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; -import io.grpc.stub.StreamObserver; -import jakarta.annotation.Nullable; -import jakarta.annotation.PreDestroy; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Service; -import org.thingsboard.common.util.JacksonUtil; -import org.thingsboard.common.util.ThingsBoardExecutors; -import org.thingsboard.rule.engine.api.AttributesSaveRequest; -import org.thingsboard.rule.engine.api.TimeseriesSaveRequest; -import org.thingsboard.server.cache.TbTransactionalCache; -import org.thingsboard.server.cluster.TbClusterService; -import org.thingsboard.server.common.data.AttributeScope; -import org.thingsboard.server.common.data.DataConstants; -import org.thingsboard.server.common.data.ResourceUtils; -import org.thingsboard.server.common.data.edge.Edge; -import org.thingsboard.server.common.data.edge.EdgeEvent; -import org.thingsboard.server.common.data.id.EdgeId; -import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.data.kv.BooleanDataEntry; -import org.thingsboard.server.common.data.kv.LongDataEntry; -import org.thingsboard.server.common.data.msg.TbMsgType; -import org.thingsboard.server.common.data.notification.rule.trigger.EdgeConnectionTrigger; -import org.thingsboard.server.common.msg.TbMsg; -import org.thingsboard.server.common.msg.TbMsgDataType; -import org.thingsboard.server.common.msg.TbMsgMetaData; -import org.thingsboard.server.common.msg.edge.EdgeEventUpdateMsg; -import org.thingsboard.server.common.msg.edge.EdgeHighPriorityMsg; -import org.thingsboard.server.common.msg.edge.EdgeSessionMsg; -import org.thingsboard.server.common.msg.edge.FromEdgeSyncResponse; -import org.thingsboard.server.common.msg.edge.ToEdgeSyncRequest; -import org.thingsboard.server.gen.edge.v1.EdgeRpcServiceGrpc; -import org.thingsboard.server.gen.edge.v1.RequestMsg; -import org.thingsboard.server.gen.edge.v1.ResponseMsg; -import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; -import org.thingsboard.server.queue.discovery.TopicService; -import org.thingsboard.server.queue.kafka.KafkaAdmin; -import org.thingsboard.server.queue.provider.TbCoreQueueFactory; -import org.thingsboard.server.queue.util.AfterStartUp; -import org.thingsboard.server.queue.util.TbCoreComponent; -import org.thingsboard.server.service.edge.EdgeContextComponent; -import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Consumer; -import java.util.function.Function; - -import static org.thingsboard.server.service.state.DefaultDeviceStateService.ACTIVITY_STATE; -import static org.thingsboard.server.service.state.DefaultDeviceStateService.LAST_CONNECT_TIME; -import static org.thingsboard.server.service.state.DefaultDeviceStateService.LAST_DISCONNECT_TIME; - -@Service -@Slf4j -@ConditionalOnProperty(prefix = "edges", value = "enabled", havingValue = "true") -@TbCoreComponent -public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase implements EdgeRpcService { - - private final ConcurrentMap sessions = new ConcurrentHashMap<>(); - private final ConcurrentMap sessionsById = new ConcurrentHashMap<>(); - private final ConcurrentMap sessionNewEventsLocks = new ConcurrentHashMap<>(); - private final Map sessionNewEvents = new HashMap<>(); - private final ConcurrentMap> sessionEdgeEventChecks = new ConcurrentHashMap<>(); - private final ConcurrentMap> localSyncEdgeRequests = new ConcurrentHashMap<>(); - private final ConcurrentMap edgeEventsMigrationProcessed = new ConcurrentHashMap<>(); - private final List zombieSessions = new ArrayList<>(); - - @Value("${edges.rpc.port}") - private int rpcPort; - @Value("${edges.rpc.ssl.enabled}") - private boolean sslEnabled; - @Value("${edges.rpc.ssl.cert}") - private String certFileResource; - @Value("${edges.rpc.ssl.private_key}") - private String privateKeyResource; - @Value("${edges.state.persistToTelemetry:false}") - private boolean persistToTelemetry; - @Value("${edges.rpc.client_max_keep_alive_time_sec:1}") - private int clientMaxKeepAliveTimeSec; - @Value("${edges.rpc.max_inbound_message_size:4194304}") - private int maxInboundMessageSize; - @Value("${edges.rpc.keep_alive_time_sec:10}") - private int keepAliveTimeSec; - @Value("${edges.rpc.keep_alive_timeout_sec:5}") - private int keepAliveTimeoutSec; - @Value("${edges.scheduler_pool_size}") - private int schedulerPoolSize; - - @Value("${edges.send_scheduler_pool_size}") - private int sendSchedulerPoolSize; - - @Value("${edges.max_high_priority_queue_size_per_session:10000}") - private int maxHighPriorityQueueSizePerSession; - - @Autowired - @Lazy - private EdgeContextComponent ctx; - - @Autowired - private TelemetrySubscriptionService tsSubService; - - @Autowired - private TbClusterService clusterService; - - @Autowired - private TbServiceInfoProvider serviceInfoProvider; - - @Autowired - private TbTransactionalCache edgeIdServiceIdCache; - - @Autowired - private TopicService topicService; - - @Autowired - private TbCoreQueueFactory tbCoreQueueFactory; - - @Autowired - private Optional kafkaAdmin; - - private Server server; - - private ScheduledExecutorService edgeEventProcessingExecutorService; - - private ScheduledExecutorService sendDownlinkExecutorService; - - private ScheduledExecutorService executorService; - - @AfterStartUp(order = AfterStartUp.REGULAR_SERVICE) - public void onStartUp() { - log.info("Initializing Edge RPC service!"); - NettyServerBuilder builder = NettyServerBuilder.forPort(rpcPort) - .permitKeepAliveTime(clientMaxKeepAliveTimeSec, TimeUnit.SECONDS) - .keepAliveTime(keepAliveTimeSec, TimeUnit.SECONDS) - .keepAliveTimeout(keepAliveTimeoutSec, TimeUnit.SECONDS) - .permitKeepAliveWithoutCalls(true) - .maxInboundMessageSize(maxInboundMessageSize) - .addService(this); - if (sslEnabled) { - try { - InputStream certFileIs = ResourceUtils.getInputStream(this, certFileResource); - InputStream privateKeyFileIs = ResourceUtils.getInputStream(this, privateKeyResource); - builder.useTransportSecurity(certFileIs, privateKeyFileIs); - } catch (Exception e) { - log.error("Unable to set up SSL context. Reason: " + e.getMessage(), e); - throw new RuntimeException("Unable to set up SSL context!", e); - } - } - server = builder.build(); - log.info("Going to start Edge RPC server using port: {}", rpcPort); - try { - server.start(); - } catch (IOException e) { - log.error("Failed to start Edge RPC server!", e); - throw new RuntimeException("Failed to start Edge RPC server!"); - } - this.edgeEventProcessingExecutorService = ThingsBoardExecutors.newScheduledThreadPool(schedulerPoolSize, "edge-event-check-scheduler"); - this.sendDownlinkExecutorService = ThingsBoardExecutors.newScheduledThreadPool(sendSchedulerPoolSize, "edge-send-scheduler"); - this.executorService = ThingsBoardExecutors.newSingleThreadScheduledExecutor("edge-service"); - this.executorService.scheduleAtFixedRate(this::cleanupZombieSessions, 60, 60, TimeUnit.SECONDS); - log.info("Edge RPC service initialized!"); - } - - @PreDestroy - public void destroy() { - if (server != null) { - server.shutdownNow(); - } - for (Map.Entry> entry : sessionEdgeEventChecks.entrySet()) { - EdgeId edgeId = entry.getKey(); - ScheduledFuture sessionEdgeEventCheck = entry.getValue(); - if (sessionEdgeEventCheck != null && !sessionEdgeEventCheck.isCancelled() && !sessionEdgeEventCheck.isDone()) { - sessionEdgeEventCheck.cancel(true); - sessionEdgeEventChecks.remove(edgeId); - } - } - if (edgeEventProcessingExecutorService != null) { - edgeEventProcessingExecutorService.shutdownNow(); - } - if (sendDownlinkExecutorService != null) { - sendDownlinkExecutorService.shutdownNow(); - } - if (executorService != null) { - executorService.shutdownNow(); - } - } - - @Override - public StreamObserver handleMsgs(StreamObserver outputStream) { - EdgeGrpcSession session = createEdgeGrpcSession(outputStream); - return session.getInputStream(); - } - - private EdgeGrpcSession createEdgeGrpcSession(StreamObserver outputStream) { - return kafkaAdmin.isPresent() - ? new KafkaEdgeGrpcSession(ctx, topicService, tbCoreQueueFactory, kafkaAdmin.get(), outputStream, this::onEdgeConnect, this::onEdgeDisconnect, - sendDownlinkExecutorService, maxInboundMessageSize, maxHighPriorityQueueSizePerSession) - : new PostgresEdgeGrpcSession(ctx, outputStream, this::onEdgeConnect, this::onEdgeDisconnect, - sendDownlinkExecutorService, maxInboundMessageSize, maxHighPriorityQueueSizePerSession); - } - - @Override - public void onToEdgeSessionMsg(TenantId tenantId, EdgeSessionMsg msg) { - switch (msg.getMsgType()) { - case EDGE_HIGH_PRIORITY_TO_EDGE_SESSION_MSG -> { - EdgeHighPriorityMsg edgeHighPriorityMsg = (EdgeHighPriorityMsg) msg; - log.trace("[{}] edgeEventMsg [{}]", tenantId, msg); - onEdgeHighPriorityEvent(edgeHighPriorityMsg); - } - case EDGE_EVENT_UPDATE_TO_EDGE_SESSION_MSG -> { - EdgeEventUpdateMsg edgeEventUpdateMsg = (EdgeEventUpdateMsg) msg; - log.trace("[{}] onToEdgeEventUpdateMsg [{}]", tenantId, msg); - onEdgeEventUpdate(tenantId, edgeEventUpdateMsg.getEdgeId()); - } - case EDGE_SYNC_REQUEST_TO_EDGE_SESSION_MSG -> { - ToEdgeSyncRequest toEdgeSyncRequest = (ToEdgeSyncRequest) msg; - log.trace("[{}] toEdgeSyncRequest [{}]", tenantId, msg); - startSyncProcess(tenantId, toEdgeSyncRequest.getEdgeId(), toEdgeSyncRequest.getId(), toEdgeSyncRequest.getServiceId()); - } - case EDGE_SYNC_RESPONSE_FROM_EDGE_SESSION_MSG -> { - FromEdgeSyncResponse fromEdgeSyncResponse = (FromEdgeSyncResponse) msg; - log.trace("[{}] fromEdgeSyncResponse [{}]", tenantId, msg); - processSyncResponse(fromEdgeSyncResponse); - } - } - } - - @Override - public void updateEdge(TenantId tenantId, Edge edge) { - if (edge == null) { - log.warn("[{}] Edge is null - edge is removed and outdated notification is in process!", tenantId); - return; - } - EdgeGrpcSession session = sessions.get(edge.getId()); - if (session != null && session.isConnected()) { - log.debug("[{}] Updating configuration for edge [{}] [{}]", tenantId, edge.getName(), edge.getId()); - session.onConfigurationUpdate(edge); - } else { - log.debug("[{}] Session doesn't exist for edge [{}] [{}]", tenantId, edge.getName(), edge.getId()); - } - } - - @Override - public void deleteEdge(TenantId tenantId, EdgeId edgeId) { - EdgeGrpcSession session = sessions.get(edgeId); - if (session != null && session.isConnected()) { - log.info("[{}] Closing and removing session for edge [{}]", tenantId, edgeId); - destroySession(session); - session.cleanUp(); - sessions.remove(edgeId); - sessionsById.remove(session.getSessionId()); - final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock()); - newEventLock.lock(); - try { - sessionNewEvents.remove(edgeId); - } finally { - newEventLock.unlock(); - } - cancelScheduleEdgeEventsCheck(edgeId); - } - } - - private void onEdgeEventUpdate(TenantId tenantId, EdgeId edgeId) { - EdgeGrpcSession session = sessions.get(edgeId); - if (session != null && session.isConnected()) { - log.trace("[{}] onEdgeEventUpdate [{}]", tenantId, edgeId.getId()); - updateSessionEventsFlag(tenantId, edgeId); - } - } - - private void onEdgeHighPriorityEvent(EdgeHighPriorityMsg msg) { - TenantId tenantId = msg.getTenantId(); - EdgeEvent edgeEvent = msg.getEdgeEvent(); - EdgeId edgeId = edgeEvent.getEdgeId(); - EdgeGrpcSession session = sessions.get(edgeId); - if (session != null && session.isConnected()) { - log.trace("[{}] onEdgeEvent [{}]", tenantId, edgeId); - session.addEventToHighPriorityQueue(edgeEvent); - updateSessionEventsFlag(tenantId, edgeId); - } - } - - private void updateSessionEventsFlag(TenantId tenantId, EdgeId edgeId) { - final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock()); - newEventLock.lock(); - try { - if (Boolean.FALSE.equals(sessionNewEvents.get(edgeId))) { - log.trace("[{}] set session new events flag to true [{}]", tenantId, edgeId.getId()); - sessionNewEvents.put(edgeId, true); - } - } finally { - newEventLock.unlock(); - } - } - - private void onEdgeConnect(EdgeId edgeId, EdgeGrpcSession edgeGrpcSession) { - Edge edge = edgeGrpcSession.getEdge(); - TenantId tenantId = edge.getTenantId(); - log.info("[{}][{}] edge [{}] connected successfully.", tenantId, edgeGrpcSession.getSessionId(), edgeId); - if (sessions.containsKey(edgeId)) { - EdgeGrpcSession existing = sessions.get(edgeId); - if (existing != null) { - log.info("[{}][{}] Replacing existing session [{}] for edge [{}]", tenantId, edgeGrpcSession.getSessionId(), existing.getSessionId(), edgeId); - destroySession(existing); - sessionsById.remove(existing.getSessionId()); - } - } - sessions.put(edgeId, edgeGrpcSession); - sessionsById.put(edgeGrpcSession.getSessionId(), edgeGrpcSession); - final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock()); - newEventLock.lock(); - try { - sessionNewEvents.put(edgeId, true); - } finally { - newEventLock.unlock(); - } - save(tenantId, edgeId, ACTIVITY_STATE, true); - long lastConnectTs = System.currentTimeMillis(); - save(tenantId, edgeId, LAST_CONNECT_TIME, lastConnectTs); - edgeIdServiceIdCache.put(edgeId, serviceInfoProvider.getServiceId()); - pushRuleEngineMessage(tenantId, edge, lastConnectTs, TbMsgType.CONNECT_EVENT); - cancelScheduleEdgeEventsCheck(edgeId); - edgeEventsMigrationProcessed.putIfAbsent(edgeId, Boolean.FALSE); - scheduleEdgeEventsCheck(edgeGrpcSession); - } - - private void startSyncProcess(TenantId tenantId, EdgeId edgeId, UUID requestId, String requestServiceId) { - EdgeGrpcSession session = sessions.get(edgeId); - if (session != null) { - if (session.isSyncInProgress()) { - clusterService.pushEdgeSyncResponseToCore(new FromEdgeSyncResponse(requestId, tenantId, edgeId, false, "Sync process is active at the moment"), requestServiceId); - } else { - boolean success = false; - if (session.isConnected()) { - session.startSyncProcess(true); - success = true; - } - clusterService.pushEdgeSyncResponseToCore(new FromEdgeSyncResponse(requestId, tenantId, edgeId, success, ""), requestServiceId); - } - } - } - - @Override - public void processSyncRequest(TenantId tenantId, EdgeId edgeId, Consumer responseConsumer) { - ToEdgeSyncRequest request = new ToEdgeSyncRequest(UUID.randomUUID(), tenantId, edgeId, serviceInfoProvider.getServiceId()); - - UUID requestId = request.getId(); - EdgeGrpcSession session = sessions.get(request.getEdgeId()); - if (session != null && session.isSyncInProgress()) { - responseConsumer.accept(new FromEdgeSyncResponse(requestId, request.getTenantId(), request.getEdgeId(), false, "Sync process is active at the moment")); - } else { - log.trace("[{}][{}] Processing sync edge request [{}], serviceId [{}]", request.getTenantId(), request.getId(), request.getEdgeId(), request.getServiceId()); - localSyncEdgeRequests.put(requestId, responseConsumer); - clusterService.pushEdgeSyncRequestToEdge(request); - scheduleSyncRequestTimeout(request, requestId); - } - } - - private void scheduleSyncRequestTimeout(ToEdgeSyncRequest request, UUID requestId) { - log.trace("[{}] scheduling sync edge request", requestId); - executorService.schedule(() -> { - log.trace("[{}] checking if sync edge request is not processed...", requestId); - Consumer consumer = localSyncEdgeRequests.remove(requestId); - if (consumer != null) { - log.trace("[{}] timeout for processing sync edge request.", requestId); - consumer.accept(new FromEdgeSyncResponse(requestId, request.getTenantId(), request.getEdgeId(), false, "Edge is not connected")); - } - }, 20, TimeUnit.SECONDS); - } - - private void processSyncResponse(FromEdgeSyncResponse response) { - log.trace("[{}] Received response from sync service: [{}]", response.getId(), response); - UUID requestId = response.getId(); - Consumer consumer = localSyncEdgeRequests.remove(requestId); - if (consumer != null) { - consumer.accept(response); - } else { - log.trace("[{}] Unknown or stale sync response received [{}]", requestId, response); - } - } - - private void scheduleEdgeEventsCheck(EdgeGrpcSession session) { - EdgeId edgeId = session.getEdge().getId(); - TenantId tenantId = session.getEdge().getTenantId(); - - cancelScheduleEdgeEventsCheck(edgeId); - - if (sessions.containsKey(edgeId)) { - ScheduledFuture edgeEventCheckTask = edgeEventProcessingExecutorService.schedule(() -> { - try { - final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock()); - newEventLock.lock(); - try { - if (Boolean.TRUE.equals(sessionNewEvents.get(edgeId))) { - log.trace("[{}][{}] set session new events flag to false", tenantId, edgeId.getId()); - sessionNewEvents.put(edgeId, false); - session.processHighPriorityEvents(); - processEdgeEventMigrationIfNeeded(session, edgeId); - if (Boolean.TRUE.equals(edgeEventsMigrationProcessed.get(edgeId))) { - Futures.addCallback(session.processEdgeEvents(), new FutureCallback<>() { - @Override - public void onSuccess(Boolean newEventsAdded) { - if (Boolean.TRUE.equals(newEventsAdded)) { - log.trace("[{}][{}] new events added. set session new events flag to true", tenantId, edgeId.getId()); - sessionNewEvents.put(edgeId, true); - } - scheduleEdgeEventsCheck(session); - } - - @Override - public void onFailure(Throwable t) { - log.warn("[{}] Failed to process edge events for edge [{}]!", tenantId, session.getEdge().getId().getId(), t); - scheduleEdgeEventsCheck(session); - } - }, ctx.getGrpcCallbackExecutorService()); - } else { - scheduleEdgeEventsCheck(session); - } - } else { - scheduleEdgeEventsCheck(session); - } - } finally { - newEventLock.unlock(); - } - } catch (Exception e) { - log.warn("[{}] Failed to process edge events for edge [{}]!", tenantId, session.getEdge().getId().getId(), e); - } - }, ctx.getEdgeEventStorageSettings().getNoRecordsSleepInterval(), TimeUnit.MILLISECONDS); - sessionEdgeEventChecks.put(edgeId, edgeEventCheckTask); - log.trace("[{}] Check edge event scheduled for edge [{}]", tenantId, edgeId.getId()); - } else { - log.debug("[{}] Session was removed and edge event check schedule must not be started [{}]", - tenantId, edgeId.getId()); - } - } - - private void processEdgeEventMigrationIfNeeded(EdgeGrpcSession session, EdgeId edgeId) throws Exception { - boolean isMigrationProcessed = edgeEventsMigrationProcessed.getOrDefault(edgeId, Boolean.FALSE); - if (!isMigrationProcessed) { - log.info("Starting edge event migration for edge [{}]", edgeId.getId()); - Boolean eventsExist = session.migrateEdgeEvents().get(); - if (Boolean.TRUE.equals(eventsExist)) { - log.info("Migration still in progress for edge [{}]", edgeId.getId()); - sessionNewEvents.put(edgeId, true); - scheduleEdgeEventsCheck(session); - } else if (Boolean.FALSE.equals(eventsExist)) { - log.info("Migration completed for edge [{}]", edgeId.getId()); - edgeEventsMigrationProcessed.put(edgeId, true); - } - } - } - - private void cancelScheduleEdgeEventsCheck(EdgeId edgeId) { - log.trace("[{}] cancelling edge event check for edge", edgeId); - if (sessionEdgeEventChecks.containsKey(edgeId)) { - ScheduledFuture sessionEdgeEventCheck = sessionEdgeEventChecks.get(edgeId); - if (sessionEdgeEventCheck != null && !sessionEdgeEventCheck.isCancelled() && !sessionEdgeEventCheck.isDone()) { - sessionEdgeEventCheck.cancel(true); - sessionEdgeEventChecks.remove(edgeId); - } - } - } - - private void onEdgeDisconnect(Edge edge, UUID sessionId) { - EdgeId edgeId = edge.getId(); - log.info("[{}][{}] edge disconnected!", edgeId, sessionId); - EdgeGrpcSession current = sessions.get(edgeId); - if (current != null && current.getSessionId().equals(sessionId)) { - EdgeGrpcSession toRemove = sessions.remove(edgeId); - final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock()); - newEventLock.lock(); - try { - sessionNewEvents.remove(edgeId); - } finally { - newEventLock.unlock(); - } - destroySession(toRemove); - sessionsById.remove(sessionId); - TenantId tenantId = toRemove.getEdge().getTenantId(); - save(tenantId, edgeId, ACTIVITY_STATE, false); - long lastDisconnectTs = System.currentTimeMillis(); - save(tenantId, edgeId, LAST_DISCONNECT_TIME, lastDisconnectTs); - pushRuleEngineMessage(toRemove.getEdge().getTenantId(), edge, lastDisconnectTs, TbMsgType.DISCONNECT_EVENT); - cancelScheduleEdgeEventsCheck(edgeId); - } else { - log.info("[{}] edge session [{}] is not current anymore. Attempting to destroy it by sessionId.", edgeId, sessionId); - EdgeGrpcSession stale = sessionsById.remove(sessionId); - if (stale != null) { - try { - destroySession(stale); - log.info("[{}][{}] Successfully destroyed stale session for edge [{}]", stale.getTenantId(), sessionId, edgeId); - } catch (Exception e) { - log.warn("[{}][{}] Failed to destroy stale session for edge [{}]", stale.getTenantId(), sessionId, edgeId, e); - } - } else { - log.debug("[{}] No session found by sessionId [{}] to destroy", edgeId, sessionId); - } - } - edgeIdServiceIdCache.evict(edgeId); - } - - private void destroySession(EdgeGrpcSession session) { - try (session) { - if (!session.destroy()) { - log.warn("[{}][{}] Session destroy failed for edge [{}] with session id [{}]. Adding to zombie queue for later cleanup.", - session.getTenantId(), session.getEdge().getId(), session.getEdge().getName(), session.getSessionId()); - zombieSessions.add(session); - } - } catch (Exception e) { - log.warn("[{}][{}] Exception during session destroy for edge [{}] with session id [{}]", - session.getTenantId(), session.getEdge().getId(), session.getEdge().getName(), session.getSessionId(), e); - } - } - - private void save(TenantId tenantId, EdgeId edgeId, String key, long value) { - log.debug("[{}][{}] Updating long edge telemetry [{}] [{}]", tenantId, edgeId, key, value); - if (persistToTelemetry) { - tsSubService.saveTimeseries(TimeseriesSaveRequest.builder() - .tenantId(tenantId) - .entityId(edgeId) - .entry(new LongDataEntry(key, value)) - .callback(new AttributeSaveCallback(tenantId, edgeId, key, value)) - .build()); - } else { - tsSubService.saveAttributes(AttributesSaveRequest.builder() - .tenantId(tenantId) - .entityId(edgeId) - .scope(AttributeScope.SERVER_SCOPE) - .entry(new LongDataEntry(key, value)) - .callback(new AttributeSaveCallback(tenantId, edgeId, key, value)) - .build()); - } - } - - private void save(TenantId tenantId, EdgeId edgeId, String key, boolean value) { - log.debug("[{}][{}] Updating boolean edge telemetry [{}] [{}]", tenantId, edgeId, key, value); - if (persistToTelemetry) { - tsSubService.saveTimeseries(TimeseriesSaveRequest.builder() - .tenantId(tenantId) - .entityId(edgeId) - .entry(new BooleanDataEntry(key, value)) - .callback(new AttributeSaveCallback(tenantId, edgeId, key, value)) - .build()); - } else { - tsSubService.saveAttributes(AttributesSaveRequest.builder() - .tenantId(tenantId) - .entityId(edgeId) - .scope(AttributeScope.SERVER_SCOPE) - .entry(new BooleanDataEntry(key, value)) - .callback(new AttributeSaveCallback(tenantId, edgeId, key, value)) - .build()); - } - } - - private static class AttributeSaveCallback implements FutureCallback { - - private final TenantId tenantId; - private final EdgeId edgeId; - private final String key; - private final Object value; - - AttributeSaveCallback(TenantId tenantId, EdgeId edgeId, String key, Object value) { - this.tenantId = tenantId; - this.edgeId = edgeId; - this.key = key; - this.value = value; - } - - @Override - public void onSuccess(@Nullable Void result) { - log.trace("[{}][{}] Successfully updated attribute [{}] with value [{}]", tenantId, edgeId, key, value); - } - - @Override - public void onFailure(Throwable t) { - log.warn("[{}][{}] Failed to update attribute [{}] with value [{}]", tenantId, edgeId, key, value, t); - } - - } - - private void pushRuleEngineMessage(TenantId tenantId, Edge edge, long ts, TbMsgType msgType) { - try { - EdgeId edgeId = edge.getId(); - ObjectNode edgeState = JacksonUtil.newObjectNode(); - boolean isConnected = TbMsgType.CONNECT_EVENT.equals(msgType); - if (isConnected) { - edgeState.put(ACTIVITY_STATE, true); - edgeState.put(LAST_CONNECT_TIME, ts); - } else { - edgeState.put(ACTIVITY_STATE, false); - edgeState.put(LAST_DISCONNECT_TIME, ts); - } - ctx.getRuleProcessor().process(EdgeConnectionTrigger.builder() - .tenantId(tenantId) - .customerId(edge.getCustomerId()) - .edgeId(edgeId) - .edgeName(edge.getName()) - .connected(isConnected).build()); - String data = JacksonUtil.toString(edgeState); - TbMsgMetaData md = new TbMsgMetaData(); - if (!persistToTelemetry) { - md.putValue(DataConstants.SCOPE, DataConstants.SERVER_SCOPE); - md.putValue("edgeName", edge.getName()); - md.putValue("edgeType", edge.getType()); - } - TbMsg tbMsg = TbMsg.newMsg() - .type(msgType) - .originator(edgeId) - .copyMetaData(md) - .dataType(TbMsgDataType.JSON) - .data(data) - .build(); - clusterService.pushMsgToRuleEngine(tenantId, edgeId, tbMsg, null); - } catch (Exception e) { - log.warn("[{}][{}] Failed to push {}", tenantId, edge.getId(), msgType, e); - } - } - - private void cleanupZombieSessions() { - try { - tryToDestroyZombieSessions(getZombieSessions(sessions.values()), s -> sessions.remove(s.getEdge().getId())); - tryToDestroyZombieSessions(getZombieSessions(sessionsById.values()), s -> sessionsById.remove(s.getSessionId())); - - zombieSessions.removeIf(zombie -> { - if (zombie.destroy()) { - log.info("[{}][{}] Successfully cleaned up zombie session [{}] for edge [{}].", - zombie.getTenantId(), zombie.getEdge().getId(), zombie.getSessionId(), zombie.getEdge().getName()); - return true; - } else { - log.warn("[{}][{}] Failed to remove zombie session [{}] for edge [{}].", - zombie.getTenantId(), zombie.getEdge().getId(), zombie.getSessionId(), zombie.getEdge().getName()); - return false; - } - }); - } catch (Exception e) { - log.warn("Failed to cleanup kafka sessions", e); - } - } - - private List getZombieSessions(Collection sessions) { - List result = new ArrayList<>(); - for (EdgeGrpcSession session : sessions) { - if (isKafkaSessionAndZombie(session)) { - result.add(session); - } - } - return result; - } - - private void tryToDestroyZombieSessions(List sessionsToRemove, Function removeFunc) { - for (EdgeGrpcSession toRemove : sessionsToRemove) { - log.info("[{}] Destroying session for edge because edge is not connected", toRemove.getEdge().getId()); - if (toRemove.destroy()) { - removeFunc.apply(toRemove); - } - } - } - - private boolean isKafkaSessionAndZombie(EdgeGrpcSession session) { - if (session instanceof KafkaEdgeGrpcSession kafkaSession) { - log.debug("[{}] kafkaSession.isConnected() = {}, kafkaSession.getConsumer().getConsumer().isStopped() = {}", - kafkaSession.getEdge().getId(), - kafkaSession.isConnected(), - kafkaSession.getConsumer() != null ? kafkaSession.getConsumer().getConsumer() != null ? kafkaSession.getConsumer().getConsumer().isStopped() : null : null); - return !kafkaSession.isConnected() && - kafkaSession.getConsumer() != null && - kafkaSession.getConsumer().getConsumer() != null && - !kafkaSession.getConsumer().getConsumer().isStopped(); - } - return false; - } - -} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java deleted file mode 100644 index 14c1b5e30a..0000000000 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ /dev/null @@ -1,994 +0,0 @@ -/** - * Copyright © 2016-2025 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.service.edge.rpc; - -import com.datastax.oss.driver.api.core.uuid.Uuids; -import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.SettableFuture; -import io.grpc.stub.StreamObserver; -import lombok.Data; -import lombok.extern.slf4j.Slf4j; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.springframework.data.util.Pair; -import org.thingsboard.server.common.data.AttributeScope; -import org.thingsboard.server.common.data.DataConstants; -import org.thingsboard.server.common.data.EdgeUtils; -import org.thingsboard.server.common.data.StringUtils; -import org.thingsboard.server.common.data.edge.Edge; -import org.thingsboard.server.common.data.edge.EdgeEvent; -import org.thingsboard.server.common.data.edge.EdgeEventType; -import org.thingsboard.server.common.data.id.EdgeId; -import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.data.kv.AttributeKvEntry; -import org.thingsboard.server.common.data.kv.AttributesSaveResult; -import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; -import org.thingsboard.server.common.data.kv.LongDataEntry; -import org.thingsboard.server.common.data.kv.StringDataEntry; -import org.thingsboard.server.common.data.limit.LimitedApi; -import org.thingsboard.server.common.data.notification.rule.trigger.EdgeCommunicationFailureTrigger; -import org.thingsboard.server.common.data.page.PageData; -import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.common.data.page.TimePageLink; -import org.thingsboard.server.common.msg.edge.EdgeEventUpdateMsg; -import org.thingsboard.server.dao.edge.stats.EdgeStatsKey; -import org.thingsboard.server.gen.edge.v1.AiModelUpdateMsg; -import org.thingsboard.server.gen.edge.v1.AlarmCommentUpdateMsg; -import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg; -import org.thingsboard.server.gen.edge.v1.AssetProfileUpdateMsg; -import org.thingsboard.server.gen.edge.v1.AssetUpdateMsg; -import org.thingsboard.server.gen.edge.v1.AttributesRequestMsg; -import org.thingsboard.server.gen.edge.v1.CalculatedFieldRequestMsg; -import org.thingsboard.server.gen.edge.v1.CalculatedFieldUpdateMsg; -import org.thingsboard.server.gen.edge.v1.ConnectRequestMsg; -import org.thingsboard.server.gen.edge.v1.ConnectResponseCode; -import org.thingsboard.server.gen.edge.v1.ConnectResponseMsg; -import org.thingsboard.server.gen.edge.v1.DashboardUpdateMsg; -import org.thingsboard.server.gen.edge.v1.DeviceCredentialsRequestMsg; -import org.thingsboard.server.gen.edge.v1.DeviceCredentialsUpdateMsg; -import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg; -import org.thingsboard.server.gen.edge.v1.DeviceRpcCallMsg; -import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg; -import org.thingsboard.server.gen.edge.v1.DownlinkMsg; -import org.thingsboard.server.gen.edge.v1.DownlinkResponseMsg; -import org.thingsboard.server.gen.edge.v1.EdgeConfiguration; -import org.thingsboard.server.gen.edge.v1.EdgeUpdateMsg; -import org.thingsboard.server.gen.edge.v1.EdgeVersion; -import org.thingsboard.server.gen.edge.v1.EntityDataProto; -import org.thingsboard.server.gen.edge.v1.EntityViewUpdateMsg; -import org.thingsboard.server.gen.edge.v1.EntityViewsRequestMsg; -import org.thingsboard.server.gen.edge.v1.RelationRequestMsg; -import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg; -import org.thingsboard.server.gen.edge.v1.RequestMsg; -import org.thingsboard.server.gen.edge.v1.RequestMsgType; -import org.thingsboard.server.gen.edge.v1.ResourceUpdateMsg; -import org.thingsboard.server.gen.edge.v1.ResponseMsg; -import org.thingsboard.server.gen.edge.v1.RuleChainMetadataRequestMsg; -import org.thingsboard.server.gen.edge.v1.RuleChainMetadataUpdateMsg; -import org.thingsboard.server.gen.edge.v1.RuleChainUpdateMsg; -import org.thingsboard.server.gen.edge.v1.SyncCompletedMsg; -import org.thingsboard.server.gen.edge.v1.UplinkMsg; -import org.thingsboard.server.gen.edge.v1.UplinkResponseMsg; -import org.thingsboard.server.gen.edge.v1.UserCredentialsRequestMsg; -import org.thingsboard.server.gen.edge.v1.UserCredentialsUpdateMsg; -import org.thingsboard.server.gen.edge.v1.UserUpdateMsg; -import org.thingsboard.server.gen.edge.v1.WidgetBundleTypesRequestMsg; -import org.thingsboard.server.service.edge.EdgeContextComponent; -import org.thingsboard.server.service.edge.EdgeMsgConstructorUtils; -import org.thingsboard.server.service.edge.rpc.fetch.EdgeEventFetcher; -import org.thingsboard.server.service.edge.rpc.fetch.GeneralEdgeEventFetcher; -import org.thingsboard.server.service.edge.rpc.utils.EdgeVersionUtils; - -import java.io.Closeable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.BiConsumer; - -@Slf4j -@Data -public abstract class EdgeGrpcSession implements Closeable { - - private static final String QUEUE_START_TS_ATTR_KEY = "queueStartTs"; - private static final String QUEUE_START_SEQ_ID_ATTR_KEY = "queueStartSeqId"; - - private static final int MAX_DOWNLINK_ATTEMPTS = 3; - private static final String RATE_LIMIT_REACHED = "Rate limit reached"; - - protected static final ConcurrentLinkedQueue highPriorityQueue = new ConcurrentLinkedQueue<>(); - - protected UUID sessionId; - private BiConsumer sessionOpenListener; - private BiConsumer sessionCloseListener; - - private final EdgeSessionState sessionState = new EdgeSessionState(); - private final ReentrantLock downlinkMsgLock = new ReentrantLock(); - private final Lock sequenceDependencyLock = new ReentrantLock(); - - protected EdgeContextComponent ctx; - protected Edge edge; - protected TenantId tenantId; - - private Long newStartTs; - private Long previousStartTs; - private Long newStartSeqId; - private Long previousStartSeqId; - - private StreamObserver inputStream; - private StreamObserver outputStream; - - private volatile boolean connected; - private volatile boolean syncInProgress; - - private EdgeVersion edgeVersion; - private int maxInboundMessageSize; - private int clientMaxInboundMessageSize; - private int maxHighPriorityQueueSizePerSession; - - private ScheduledExecutorService sendDownlinkExecutorService; - - public EdgeGrpcSession(EdgeContextComponent ctx, StreamObserver outputStream, - BiConsumer sessionOpenListener, - BiConsumer sessionCloseListener, - ScheduledExecutorService sendDownlinkExecutorService, - int maxInboundMessageSize, int maxHighPriorityQueueSizePerSession) { - this.sessionId = UUID.randomUUID(); - this.ctx = ctx; - this.outputStream = outputStream; - this.sessionOpenListener = sessionOpenListener; - this.sessionCloseListener = sessionCloseListener; - this.sendDownlinkExecutorService = sendDownlinkExecutorService; - this.maxInboundMessageSize = maxInboundMessageSize; - this.maxHighPriorityQueueSizePerSession = maxHighPriorityQueueSizePerSession; - initInputStream(); - } - - protected abstract ListenableFuture migrateEdgeEvents() throws Exception; - - public void initInputStream() { - inputStream = new StreamObserver<>() { - @Override - public void onNext(RequestMsg requestMsg) { - if (!connected && requestMsg.getMsgType().equals(RequestMsgType.CONNECT_RPC_MESSAGE)) { - ConnectResponseMsg responseMsg = processConnect(requestMsg.getConnectRequestMsg()); - outputStream.onNext(ResponseMsg.newBuilder() - .setConnectResponseMsg(responseMsg) - .build()); - if (ConnectResponseCode.ACCEPTED != responseMsg.getResponseCode()) { - outputStream.onError(new RuntimeException(responseMsg.getErrorMsg())); - } else { - if (requestMsg.getConnectRequestMsg().hasMaxInboundMessageSize()) { - log.debug("[{}][{}] Client max inbound message size: {}", tenantId, sessionId, requestMsg.getConnectRequestMsg().getMaxInboundMessageSize()); - clientMaxInboundMessageSize = requestMsg.getConnectRequestMsg().getMaxInboundMessageSize(); - } - connected = true; - } - } - if (connected) { - if (requestMsg.getMsgType().equals(RequestMsgType.SYNC_REQUEST_RPC_MESSAGE)) { - if (requestMsg.hasSyncRequestMsg()) { - boolean fullSync = false; - if (requestMsg.getSyncRequestMsg().hasFullSync()) { - fullSync = requestMsg.getSyncRequestMsg().getFullSync(); - } - startSyncProcess(fullSync); - } else { - syncInProgress = false; - } - } - if (requestMsg.getMsgType().equals(RequestMsgType.UPLINK_RPC_MESSAGE)) { - if (requestMsg.hasUplinkMsg()) { - onUplinkMsg(requestMsg.getUplinkMsg()); - } - if (requestMsg.hasDownlinkResponseMsg()) { - onDownlinkResponse(requestMsg.getDownlinkResponseMsg()); - } - } - } - } - - @Override - public void onError(Throwable t) { - log.trace("[{}][{}] Stream was terminated due to error:", tenantId, sessionId, t); - closeSession(); - } - - @Override - public void onCompleted() { - log.info("[{}][{}] Stream was closed and completed successfully!", tenantId, sessionId); - closeSession(); - } - - private void closeSession() { - connected = false; - if (edge != null) { - try { - sessionCloseListener.accept(edge, sessionId); - } catch (Exception ignored) { - } - } - try { - outputStream.onCompleted(); - } catch (Exception ignored) { - } - } - }; - } - - public void onConfigurationUpdate(Edge edge) { - log.debug("[{}] onConfigurationUpdate [{}]", sessionId, edge); - this.tenantId = edge.getTenantId(); - this.edge = edge; - EdgeUpdateMsg edgeConfig = EdgeUpdateMsg.newBuilder() - .setConfiguration(EdgeMsgConstructorUtils.constructEdgeConfiguration(edge)).build(); - ResponseMsg edgeConfigMsg = ResponseMsg.newBuilder() - .setEdgeUpdateMsg(edgeConfig) - .build(); - sendDownlinkMsg(edgeConfigMsg); - } - - public void startSyncProcess(boolean fullSync) { - if (!syncInProgress) { - log.info("[{}][{}][{}] Staring edge sync process", tenantId, edge.getId(), sessionId); - syncInProgress = true; - interruptGeneralProcessingOnSync(); - doSync(new EdgeSyncCursor(ctx, edge, fullSync)); - } else { - log.info("[{}][{}][{}] Sync is already started, skipping starting it now", tenantId, edge.getId(), sessionId); - } - } - - private void doSync(EdgeSyncCursor cursor) { - if (cursor.hasNext()) { - EdgeEventFetcher next = cursor.getNext(); - log.debug("[{}][{}] starting sync process, cursor current idx = {}, class = {}", - tenantId, edge.getId(), cursor.getCurrentIdx(), next.getClass().getSimpleName()); - ListenableFuture> future = startProcessingEdgeEvents(next); - Futures.addCallback(future, new FutureCallback<>() { - @Override - public void onSuccess(@Nullable Pair result) { - doSync(cursor); - } - - @Override - public void onFailure(Throwable t) { - log.error("[{}][{}] Exception during sync process", tenantId, edge.getId(), t); - } - }, ctx.getGrpcCallbackExecutorService()); - } else { - log.info("[{}][{}] sync process completed", tenantId, edge.getId()); - DownlinkMsg syncCompleteDownlinkMsg = DownlinkMsg.newBuilder() - .setDownlinkMsgId(EdgeUtils.nextPositiveInt()) - .setSyncCompletedMsg(SyncCompletedMsg.newBuilder().build()) - .build(); - Futures.addCallback(sendDownlinkMsgsPack(Collections.singletonList(syncCompleteDownlinkMsg)), new FutureCallback<>() { - @Override - public void onSuccess(Boolean isInterrupted) { - markSyncCompletedSendEdgeEventUpdate(); - } - - @Override - public void onFailure(Throwable t) { - log.error("[{}][{}] Exception during sending sync complete", tenantId, edge.getId(), t); - markSyncCompletedSendEdgeEventUpdate(); - } - }, ctx.getGrpcCallbackExecutorService()); - } - } - - protected void processEdgeEvents(EdgeEventFetcher fetcher, PageLink pageLink, SettableFuture> result) { - try { - log.trace("[{}] Start processing edge events, fetcher = {}, pageLink = {}", edge.getId(), fetcher.getClass().getSimpleName(), pageLink); - processHighPriorityEvents(); - PageData pageData = fetcher.fetchEdgeEvents(edge.getTenantId(), edge, pageLink); - if (isConnected() && !pageData.getData().isEmpty()) { - if (fetcher instanceof GeneralEdgeEventFetcher) { - long queueSize = pageData.getTotalElements() - ((long) pageLink.getPageSize() * pageLink.getPage()); - ctx.getStatsCounterService().ifPresent(statsCounterService -> statsCounterService.setDownlinkMsgsLag(edge.getTenantId(), edge.getId(), queueSize)); - } - log.trace("[{}][{}][{}] event(s) are going to be processed.", tenantId, edge.getId(), pageData.getData().size()); - List downlinkMsgsPack = convertToDownlinkMsgsPack(pageData.getData()); - Futures.addCallback(sendDownlinkMsgsPack(downlinkMsgsPack), new FutureCallback<>() { - @Override - public void onSuccess(@Nullable Boolean isInterrupted) { - if (Boolean.TRUE.equals(isInterrupted)) { - log.debug("[{}][{}][{}] Send downlink messages task was interrupted", tenantId, edge.getId(), sessionId); - result.set(null); - } else { - if (isConnected() && pageData.hasNext()) { - processEdgeEvents(fetcher, pageLink.nextPageLink(), result); - } else { - EdgeEvent latestEdgeEvent = pageData.getData().get(pageData.getData().size() - 1); - UUID idOffset = latestEdgeEvent.getUuidId(); - if (idOffset != null) { - Long newStartTs = Uuids.unixTimestamp(idOffset); - long newStartSeqId = latestEdgeEvent.getSeqId(); - result.set(Pair.of(newStartTs, newStartSeqId)); - } else { - result.set(null); - } - } - } - } - - @Override - public void onFailure(Throwable t) { - log.error("[{}] Failed to send downlink msgs pack", edge.getId(), t); - result.setException(t); - } - }, ctx.getGrpcCallbackExecutorService()); - } else { - log.trace("[{}] no event(s) found. Stop processing edge events, fetcher = {}, pageLink = {}", edge.getId(), fetcher.getClass().getSimpleName(), pageLink); - result.set(null); - } - } catch (Exception e) { - log.error("[{}] Failed to fetch edge events", edge.getId(), e); - result.setException(e); - } - } - - private ConnectResponseMsg processConnect(ConnectRequestMsg request) { - log.trace("[{}] processConnect [{}]", sessionId, request); - Optional optional = ctx.getEdgeService().findEdgeByRoutingKey(TenantId.SYS_TENANT_ID, request.getEdgeRoutingKey()); - if (optional.isPresent()) { - edge = optional.get(); - tenantId = edge.getTenantId(); - try { - if (edge.getSecret().equals(request.getEdgeSecret())) { - sessionOpenListener.accept(edge.getId(), this); - edgeVersion = request.getEdgeVersion(); - processSaveEdgeVersionAsAttribute(request.getEdgeVersion().name()); - return ConnectResponseMsg.newBuilder() - .setResponseCode(ConnectResponseCode.ACCEPTED) - .setErrorMsg("") - .setConfiguration(EdgeMsgConstructorUtils.constructEdgeConfiguration(edge)) - .setMaxInboundMessageSize(maxInboundMessageSize) - .build(); - } - String error = "Failed to validate the edge!"; - String failureMsg = String.format("%s Provided request secret: %s", error, request.getEdgeSecret()); - ctx.getRuleProcessor().process(EdgeCommunicationFailureTrigger.builder().tenantId(tenantId).edgeId(edge.getId()) - .customerId(edge.getCustomerId()).edgeName(edge.getName()).failureMsg(failureMsg).error(error).build()); - return ConnectResponseMsg.newBuilder() - .setResponseCode(ConnectResponseCode.BAD_CREDENTIALS) - .setErrorMsg(failureMsg) - .setConfiguration(EdgeConfiguration.getDefaultInstance()).build(); - } catch (Exception e) { - String failureMsg = "Failed to process edge connection!"; - ctx.getRuleProcessor().process(EdgeCommunicationFailureTrigger.builder().tenantId(tenantId).edgeId(edge.getId()) - .customerId(edge.getCustomerId()).edgeName(edge.getName()).failureMsg(failureMsg).error(e.getMessage()).build()); - log.error(failureMsg, e); - return ConnectResponseMsg.newBuilder() - .setResponseCode(ConnectResponseCode.SERVER_UNAVAILABLE) - .setErrorMsg(failureMsg) - .setConfiguration(EdgeConfiguration.getDefaultInstance()).build(); - } - } - return ConnectResponseMsg.newBuilder() - .setResponseCode(ConnectResponseCode.BAD_CREDENTIALS) - .setErrorMsg("Failed to find the edge! Routing key: " + request.getEdgeRoutingKey()) - .setConfiguration(EdgeConfiguration.getDefaultInstance()).build(); - } - - private void processSaveEdgeVersionAsAttribute(String edgeVersion) { - AttributeKvEntry attributeKvEntry = new BaseAttributeKvEntry(new StringDataEntry(DataConstants.EDGE_VERSION_ATTR_KEY, edgeVersion), System.currentTimeMillis()); - ctx.getAttributesService().save(tenantId, edge.getId(), AttributeScope.SERVER_SCOPE, attributeKvEntry); - } - - private void interruptGeneralProcessingOnSync() { - log.debug("[{}][{}][{}] Sync process started. General processing interrupted!", tenantId, edge.getId(), sessionId); - stopCurrentSendDownlinkMsgsTask(true); - } - - protected ListenableFuture sendDownlinkMsgsPack(List downlinkMsgsPack) { - interruptPreviousSendDownlinkMsgsTask(); - - sessionState.setSendDownlinkMsgsFuture(SettableFuture.create()); - sessionState.getPendingMsgsMap().clear(); - - downlinkMsgsPack.forEach(msg -> sessionState.getPendingMsgsMap().put(msg.getDownlinkMsgId(), msg)); - scheduleDownlinkMsgsPackSend(1); - - return sessionState.getSendDownlinkMsgsFuture(); - } - - private void interruptPreviousSendDownlinkMsgsTask() { - if (sessionState.getSendDownlinkMsgsFuture() != null && !sessionState.getSendDownlinkMsgsFuture().isDone() - || sessionState.getScheduledSendDownlinkTask() != null && !sessionState.getScheduledSendDownlinkTask().isCancelled()) { - log.debug("[{}][{}][{}] Previous send downlink future was not properly completed, stopping it now!", tenantId, edge.getId(), sessionId); - stopCurrentSendDownlinkMsgsTask(true); - } else { - log.trace("[{}][{}][{}] Previous send downlink future is not active", tenantId, edge.getId(), sessionId); - } - } - - private void onUplinkMsg(UplinkMsg uplinkMsg) { - if (isRateLimitViolated(uplinkMsg)) { - return; - } - ListenableFuture> future = processUplinkMsg(uplinkMsg); - Futures.addCallback(future, new FutureCallback<>() { - @Override - public void onSuccess(@Nullable List result) { - sendResponseMessage(uplinkMsg.getUplinkMsgId(), true, null); - } - - @Override - public void onFailure(Throwable t) { - String errorMsg = EdgeUtils.createErrorMsgFromRootCauseAndStackTrace(t); - sendResponseMessage(uplinkMsg.getUplinkMsgId(), false, errorMsg); - } - }, ctx.getGrpcCallbackExecutorService()); - } - - private boolean isRateLimitViolated(UplinkMsg uplinkMsg) { - if (!ctx.getRateLimitService().checkRateLimit(LimitedApi.EDGE_UPLINK_MESSAGES, tenantId) || - !ctx.getRateLimitService().checkRateLimit(LimitedApi.EDGE_UPLINK_MESSAGES_PER_EDGE, tenantId, edge.getId())) { - String errorMsg = String.format("Failed to process uplink message. %s", RATE_LIMIT_REACHED); - sendResponseMessage(uplinkMsg.getUplinkMsgId(), false, errorMsg); - return true; - } - return false; - } - - private void scheduleDownlinkMsgsPackSend(int attempt) { - Runnable sendDownlinkMsgsTask = () -> { - try { - if (!isConnected()) { - stopCurrentSendDownlinkMsgsTask(true); - return; - } - if (!sessionState.getPendingMsgsMap().values().isEmpty()) { - List copy = new ArrayList<>(sessionState.getPendingMsgsMap().values()); - if (attempt > 1) { - String error = "Failed to deliver the batch"; - String failureMsg = String.format("{%s} (size: {%s})", error, copy.size()); - if (attempt == 2) { - // Send a failure notification only on the second attempt. - // This ensures that failure alerts are sent just once to avoid redundant notifications. - ctx.getRuleProcessor().process(EdgeCommunicationFailureTrigger.builder().tenantId(tenantId) - .edgeId(edge.getId()).customerId(edge.getCustomerId()).edgeName(edge.getName()).failureMsg(failureMsg).error(error).build()); - } - ctx.getStatsCounterService().ifPresent(statsCounterService -> - statsCounterService.recordEvent(EdgeStatsKey.DOWNLINK_MSGS_TMP_FAILED, edge.getTenantId(), edge.getId(), 1)); - log.warn("[{}][{}] {} on attempt {}", tenantId, edge.getId(), failureMsg, attempt); - log.debug("[{}][{}] entities in failed batch: {}", tenantId, edge.getId(), copy); - } - log.trace("[{}][{}][{}] downlink msg(s) are going to be send.", tenantId, edge.getId(), copy.size()); - for (DownlinkMsg downlinkMsg : copy) { - if (clientMaxInboundMessageSize != 0 && downlinkMsg.getSerializedSize() > clientMaxInboundMessageSize) { - String error = String.format("Client max inbound message size %s is exceeded. Please increase value of CLOUD_RPC_MAX_INBOUND_MESSAGE_SIZE " + - "env variable on the edge and restart it.", clientMaxInboundMessageSize); - String message = String.format("Downlink msg size %s exceeds client max inbound message size %s. " + - "Please increase value of CLOUD_RPC_MAX_INBOUND_MESSAGE_SIZE env variable on the edge and restart it.", downlinkMsg.getSerializedSize(), clientMaxInboundMessageSize); - log.error("[{}][{}][{}] {} Message {}", tenantId, edge.getId(), sessionId, message, downlinkMsg); - ctx.getRuleProcessor().process(EdgeCommunicationFailureTrigger.builder().tenantId(tenantId) - .edgeId(edge.getId()).customerId(edge.getCustomerId()).edgeName(edge.getName()).failureMsg(message).error(error).build()); - ctx.getStatsCounterService().ifPresent(statsCounterService -> - statsCounterService.recordEvent(EdgeStatsKey.DOWNLINK_MSGS_PERMANENTLY_FAILED, edge.getTenantId(), edge.getId(), 1)); - sessionState.getPendingMsgsMap().remove(downlinkMsg.getDownlinkMsgId()); - } else { - sendDownlinkMsg(ResponseMsg.newBuilder() - .setDownlinkMsg(downlinkMsg) - .build()); - } - } - if (attempt < MAX_DOWNLINK_ATTEMPTS) { - scheduleDownlinkMsgsPackSend(attempt + 1); - } else { - String failureMsg = String.format("Failed to deliver messages: %s", copy); - log.warn("[{}][{}] Failed to deliver the batch after {} attempts. Next messages are going to be discarded {}", - tenantId, edge.getId(), MAX_DOWNLINK_ATTEMPTS, copy); - ctx.getRuleProcessor().process(EdgeCommunicationFailureTrigger.builder().tenantId(tenantId).edgeId(edge.getId()) - .customerId(edge.getCustomerId()).edgeName(edge.getName()).failureMsg(failureMsg) - .error("Failed to deliver messages after " + MAX_DOWNLINK_ATTEMPTS + " attempts").build()); - ctx.getStatsCounterService().ifPresent(statsCounterService -> statsCounterService.recordEvent(EdgeStatsKey.DOWNLINK_MSGS_PERMANENTLY_FAILED, edge.getTenantId(), edge.getId(), copy.size())); - stopCurrentSendDownlinkMsgsTask(false); - } - } else { - stopCurrentSendDownlinkMsgsTask(false); - } - } catch (Exception e) { - log.warn("[{}][{}] Failed to send downlink msgs. Error msg {}", tenantId, edge.getId(), e.getMessage(), e); - stopCurrentSendDownlinkMsgsTask(true); - } - }; - - if (attempt == 1) { - sendDownlinkExecutorService.submit(sendDownlinkMsgsTask); - } else { - sessionState.setScheduledSendDownlinkTask( - sendDownlinkExecutorService.schedule( - sendDownlinkMsgsTask, - ctx.getEdgeEventStorageSettings().getSleepIntervalBetweenBatches(), - TimeUnit.MILLISECONDS) - ); - } - } - - private void sendResponseMessage(int uplinkMsgId, boolean success, String errorMsg) { - UplinkResponseMsg.Builder responseBuilder = UplinkResponseMsg.newBuilder() - .setUplinkMsgId(uplinkMsgId) - .setSuccess(success); - if (errorMsg != null) { - responseBuilder.setErrorMsg(errorMsg); - } - sendDownlinkMsg(ResponseMsg.newBuilder() - .setUplinkResponseMsg(responseBuilder.build()) - .build()); - } - - private void onDownlinkResponse(DownlinkResponseMsg msg) { - try { - if (msg.getSuccess()) { - sessionState.getPendingMsgsMap().remove(msg.getDownlinkMsgId()); - ctx.getStatsCounterService().ifPresent(statsCounterService -> statsCounterService.recordEvent(EdgeStatsKey.DOWNLINK_MSGS_PUSHED, edge.getTenantId(), edge.getId(), 1)); - log.debug("[{}][{}][{}] Msg has been processed successfully! Msg Id: [{}], Msg: {}", tenantId, edge.getId(), sessionId, msg.getDownlinkMsgId(), msg); - } else { - log.debug("[{}][{}][{}] Msg processing failed! Msg Id: [{}], Error msg: {}", tenantId, edge.getId(), sessionId, msg.getDownlinkMsgId(), msg.getErrorMsg()); - DownlinkMsg downlinkMsg = sessionState.getPendingMsgsMap().get(msg.getDownlinkMsgId()); - // if NOT timeseries or attributes failures - ack failed downlink - if (downlinkMsg.getEntityDataCount() == 0) { - sessionState.getPendingMsgsMap().remove(msg.getDownlinkMsgId()); - } - } - if (sessionState.getPendingMsgsMap().isEmpty()) { - log.debug("[{}][{}][{}] Pending msgs map is empty. Stopping current iteration", tenantId, edge.getId(), sessionId); - stopCurrentSendDownlinkMsgsTask(false); - } - } catch (Exception e) { - log.error("[{}][{}] Can't process downlink response message [{}]", tenantId, edge.getId(), msg, e); - } - } - - public void processHighPriorityEvents() { - try { - if (isConnected() && !isSyncInProgress()) { - if (highPriorityQueue.isEmpty()) { - return; - } - List highPriorityEvents = new ArrayList<>(); - EdgeEvent event; - while ((event = highPriorityQueue.poll()) != null) { - highPriorityEvents.add(event); - } - log.trace("[{}][{}] Sending high priority events {}", tenantId, edge.getId(), highPriorityEvents.size()); - List downlinkMsgsPack = convertToDownlinkMsgsPack(highPriorityEvents); - sendDownlinkMsgsPack(downlinkMsgsPack).get(); - } - } catch (Exception e) { - log.error("[{}] Failed to process high priority events", edge.getId(), e); - } - } - - public ListenableFuture processEdgeEvents() throws Exception { - SettableFuture result = SettableFuture.create(); - if (isConnected() && !isSyncInProgress()) { - Pair startTsAndSeqId = getQueueStartTsAndSeqId().get(); - previousStartTs = startTsAndSeqId.getFirst(); - previousStartSeqId = startTsAndSeqId.getSecond(); - GeneralEdgeEventFetcher fetcher = new GeneralEdgeEventFetcher( - previousStartTs, - previousStartSeqId, - false, - Integer.toUnsignedLong(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount()), - ctx.getEdgeEventService(), - ctx.getEdgeEventStorageSettings().getMisorderingCompensationMillis()); - log.trace("[{}][{}] starting processing edge events, previousStartTs = {}, previousStartSeqId = {}", - tenantId, edge.getId(), previousStartTs, previousStartSeqId); - Futures.addCallback(startProcessingEdgeEvents(fetcher), new FutureCallback<>() { - @Override - public void onSuccess(@Nullable Pair newStartTsAndSeqId) { - if (newStartTsAndSeqId != null) { - ListenableFuture updateFuture = updateQueueStartTsAndSeqId(newStartTsAndSeqId); - Futures.addCallback(updateFuture, new FutureCallback<>() { - @Override - public void onSuccess(@Nullable AttributesSaveResult saveResult) { - log.debug("[{}][{}] queue offset was updated [{}]", tenantId, edge.getId(), newStartTsAndSeqId); - boolean newEventsAvailable; - if (fetcher.isSeqIdNewCycleStarted()) { - newEventsAvailable = isNewEdgeEventsAvailable(); - } else { - newEventsAvailable = isSeqIdStartedNewCycle(); - if (!newEventsAvailable) { - newEventsAvailable = isNewEdgeEventsAvailable(); - } - } - result.set(newEventsAvailable); - } - - @Override - public void onFailure(Throwable t) { - log.error("[{}][{}] Failed to update queue offset [{}]", tenantId, edge.getId(), newStartTsAndSeqId, t); - result.setException(t); - } - }, ctx.getGrpcCallbackExecutorService()); - } else { - log.trace("[{}][{}] newStartTsAndSeqId is null. Skipping iteration without db update", tenantId, edge.getId()); - result.set(Boolean.FALSE); - } - } - - @Override - public void onFailure(Throwable t) { - log.error("[{}][{}] Failed to process events", tenantId, edge.getId(), t); - result.setException(t); - } - }, ctx.getGrpcCallbackExecutorService()); - } else { - if (isSyncInProgress()) { - log.trace("[{}][{}] edge sync is not completed yet. Skipping iteration", tenantId, edge.getId()); - result.set(Boolean.TRUE); - } else { - log.trace("[{}][{}] edge is not connected. Skipping iteration", tenantId, edge.getId()); - result.set(null); - } - } - return result; - } - - protected List convertToDownlinkMsgsPack(List edgeEvents) { - List result = new ArrayList<>(); - for (EdgeEvent edgeEvent : edgeEvents) { - log.trace("[{}][{}] converting edge event to downlink msg [{}]", tenantId, edge.getId(), edgeEvent); - DownlinkMsg downlinkMsg = null; - try { - switch (edgeEvent.getAction()) { - case UPDATED, ADDED, DELETED, ASSIGNED_TO_EDGE, UNASSIGNED_FROM_EDGE, ALARM_ACK, ALARM_CLEAR, - ALARM_DELETE, CREDENTIALS_UPDATED, RELATION_ADD_OR_UPDATE, RELATION_DELETED, RPC_CALL, - ASSIGNED_TO_CUSTOMER, UNASSIGNED_FROM_CUSTOMER, ADDED_COMMENT, UPDATED_COMMENT, DELETED_COMMENT -> { - downlinkMsg = convertEntityEventToDownlink(edgeEvent); - if (downlinkMsg != null && downlinkMsg.getWidgetTypeUpdateMsgCount() > 0) { - log.trace("[{}][{}] widgetTypeUpdateMsg message processed, downlinkMsgId = {}", tenantId, edge.getId(), downlinkMsg.getDownlinkMsgId()); - } else { - log.trace("[{}][{}] entity message processed [{}]", tenantId, edge.getId(), downlinkMsg); - } - } - case ATTRIBUTES_UPDATED, POST_ATTRIBUTES, ATTRIBUTES_DELETED, TIMESERIES_UPDATED -> - downlinkMsg = ctx.getTelemetryProcessor().convertTelemetryEventToDownlink(edge, edgeEvent); - default -> log.warn("[{}][{}] Unsupported action type [{}]", tenantId, edge.getId(), edgeEvent.getAction()); - } - } catch (Exception e) { - log.trace("[{}][{}] Exception during converting edge event to downlink msg", tenantId, edge.getId(), e); - } - if (downlinkMsg != null) { - result.add(downlinkMsg); - } - } - return result; - } - - private ListenableFuture> getQueueStartTsAndSeqId() { - ListenableFuture> future = - ctx.getAttributesService().find(edge.getTenantId(), edge.getId(), AttributeScope.SERVER_SCOPE, Arrays.asList(QUEUE_START_TS_ATTR_KEY, QUEUE_START_SEQ_ID_ATTR_KEY)); - return Futures.transform(future, attributeKvEntries -> { - long startTs = 0L; - long startSeqId = 0L; - for (AttributeKvEntry attributeKvEntry : attributeKvEntries) { - if (QUEUE_START_TS_ATTR_KEY.equals(attributeKvEntry.getKey())) { - startTs = attributeKvEntry.getLongValue().isPresent() ? attributeKvEntry.getLongValue().get() : 0L; - } - if (QUEUE_START_SEQ_ID_ATTR_KEY.equals(attributeKvEntry.getKey())) { - startSeqId = attributeKvEntry.getLongValue().isPresent() ? attributeKvEntry.getLongValue().get() : 0L; - } - } - if (startSeqId == 0L) { - startSeqId = findStartSeqIdFromOldestEventIfAny(); - } - return Pair.of(startTs, startSeqId); - }, ctx.getGrpcCallbackExecutorService()); - } - - private boolean isSeqIdStartedNewCycle() { - try { - log.trace("[{}][{}][{}] Checking if seq id started new cycle", tenantId, edge.getId(), sessionId); - TimePageLink pageLink = new TimePageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount(), 0, null, null, newStartTs, System.currentTimeMillis()); - PageData edgeEvents = ctx.getEdgeEventService().findEdgeEvents(edge.getTenantId(), edge.getId(), 0L, previousStartSeqId == 0 ? null : previousStartSeqId - 1, pageLink); - boolean result = !edgeEvents.getData().isEmpty(); - log.trace("[{}][{}][{}] Result of check if seq id started new cycle, result = {}", tenantId, edge.getId(), sessionId, result); - return result; - } catch (Exception e) { - log.error("[{}][{}][{}] Failed to execute isSeqIdStartedNewCycle", tenantId, edge.getId(), sessionId, e); - } - return false; - } - - private boolean isNewEdgeEventsAvailable() { - try { - log.trace("[{}][{}][{}] Checking if new edge events available", tenantId, edge.getId(), sessionId); - TimePageLink pageLink = new TimePageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount(), 0, null, null, newStartTs, System.currentTimeMillis()); - PageData edgeEvents = ctx.getEdgeEventService().findEdgeEvents(edge.getTenantId(), edge.getId(), newStartSeqId, null, pageLink); - boolean result = !edgeEvents.getData().isEmpty() || !highPriorityQueue.isEmpty(); - log.trace("[{}][{}][{}] Result of check if new edge events available, result = {}", tenantId, edge.getId(), sessionId, result); - return result; - } catch (Exception e) { - log.error("[{}][{}][{}] Failed to execute isNewEdgeEventsAvailable", tenantId, edge.getId(), sessionId, e); - } - return false; - } - - private long findStartSeqIdFromOldestEventIfAny() { - long startSeqId = 0L; - try { - TimePageLink pageLink = new TimePageLink(1, 0, null, null, null, null); - PageData edgeEvents = ctx.getEdgeEventService().findEdgeEvents(edge.getTenantId(), edge.getId(), null, null, pageLink); - if (!edgeEvents.getData().isEmpty()) { - startSeqId = edgeEvents.getData().get(0).getSeqId() - 1; - } - } catch (Exception e) { - log.error("[{}][{}][{}] Failed to execute findStartSeqIdFromOldestEventIfAny", tenantId, edge.getId(), sessionId, e); - } - return startSeqId; - } - - private ListenableFuture updateQueueStartTsAndSeqId(Pair pair) { - newStartTs = pair.getFirst(); - newStartSeqId = pair.getSecond(); - log.trace("[{}] updateQueueStartTsAndSeqId [{}][{}][{}]", sessionId, edge.getId(), newStartTs, newStartSeqId); - List attributes = List.of( - new BaseAttributeKvEntry(new LongDataEntry(QUEUE_START_TS_ATTR_KEY, newStartTs), System.currentTimeMillis()), - new BaseAttributeKvEntry(new LongDataEntry(QUEUE_START_SEQ_ID_ATTR_KEY, newStartSeqId), System.currentTimeMillis()) - ); - return ctx.getAttributesService().save(edge.getTenantId(), edge.getId(), AttributeScope.SERVER_SCOPE, attributes); - } - - protected ListenableFuture> startProcessingEdgeEvents(EdgeEventFetcher fetcher) { - SettableFuture> result = SettableFuture.create(); - PageLink pageLink = fetcher.getPageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount()); - processEdgeEvents(fetcher, pageLink, result); - return result; - } - - private void markSyncCompletedSendEdgeEventUpdate() { - syncInProgress = false; - ctx.getClusterService().onEdgeEventUpdate(new EdgeEventUpdateMsg(edge.getTenantId(), edge.getId())); - } - - private void stopCurrentSendDownlinkMsgsTask(Boolean isInterrupted) { - if (sessionState.getSendDownlinkMsgsFuture() != null && !sessionState.getSendDownlinkMsgsFuture().isDone()) { - sessionState.getSendDownlinkMsgsFuture().set(isInterrupted); - } - if (sessionState.getScheduledSendDownlinkTask() != null) { - sessionState.getScheduledSendDownlinkTask().cancel(true); - } - } - - private void sendDownlinkMsg(ResponseMsg responseMsg) { - if (isConnected()) { - String responseMsgStr = StringUtils.truncate(responseMsg.toString(), 10000); - log.trace("[{}][{}] Sending downlink msg [{}]", tenantId, edge.getId(), responseMsgStr); - downlinkMsgLock.lock(); - String downlinkMsgStr = responseMsg.hasDownlinkMsg() ? String.valueOf(responseMsg.getDownlinkMsg().getDownlinkMsgId()) : responseMsgStr; - try { - outputStream.onNext(responseMsg); - } catch (Exception e) { - log.trace("[{}][{}] Failed to send downlink message [{}]", tenantId, edge.getId(), downlinkMsgStr, e); - connected = false; - sessionCloseListener.accept(edge, sessionId); - } finally { - downlinkMsgLock.unlock(); - } - log.trace("[{}][{}] downlink msg successfully sent [{}]", tenantId, edge.getId(), downlinkMsgStr); - } - } - - protected DownlinkMsg convertEntityEventToDownlink(EdgeEvent edgeEvent) { - log.trace("[{}] Executing convertEntityEventToDownlink, edgeEvent [{}], action [{}]", edgeEvent.getTenantId(), edgeEvent, edgeEvent.getAction()); - if ((EdgeEventType.OAUTH2_CLIENT.equals(edgeEvent.getType()) || EdgeEventType.DOMAIN.equals(edgeEvent.getType())) && - (EdgeVersionUtils.isEdgeVersionOlderThan(edgeVersion, EdgeVersion.V_3_8_0))) { - return null; - } - - return ctx.getProcessor(edgeEvent.getType()).convertEdgeEventToDownlink(edgeEvent, edgeVersion); - } - - public void addEventToHighPriorityQueue(EdgeEvent edgeEvent) { - while (highPriorityQueue.size() > maxHighPriorityQueueSizePerSession) { - EdgeEvent oldestHighPriority = highPriorityQueue.poll(); - if (oldestHighPriority != null) { - log.warn("[{}][{}][{}] High priority queue is full. Removing oldest high priority event from queue {}", - tenantId, edge.getId(), sessionId, oldestHighPriority); - } - } - highPriorityQueue.add(edgeEvent); - ctx.getStatsCounterService().ifPresent(statsCounterService -> statsCounterService.recordEvent(EdgeStatsKey.DOWNLINK_MSGS_ADDED, edge.getTenantId(), edgeEvent.getEdgeId(), 1)); - } - - protected ListenableFuture> processUplinkMsg(UplinkMsg uplinkMsg) { - List> result = new ArrayList<>(); - try { - if (uplinkMsg.getDeviceProfileUpdateMsgCount() > 0) { - for (DeviceProfileUpdateMsg deviceProfileUpdateMsg : uplinkMsg.getDeviceProfileUpdateMsgList()) { - result.add(ctx.getDeviceProfileProcessor().processDeviceProfileMsgFromEdge(edge.getTenantId(), edge, deviceProfileUpdateMsg)); - } - } - if (uplinkMsg.getDeviceUpdateMsgCount() > 0) { - for (DeviceUpdateMsg deviceUpdateMsg : uplinkMsg.getDeviceUpdateMsgList()) { - result.add(ctx.getDeviceProcessor().processDeviceMsgFromEdge(edge.getTenantId(), edge, deviceUpdateMsg)); - } - } - if (uplinkMsg.getDeviceCredentialsUpdateMsgCount() > 0) { - for (DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg : uplinkMsg.getDeviceCredentialsUpdateMsgList()) { - result.add(ctx.getDeviceProcessor().processDeviceCredentialsMsgFromEdge(edge.getTenantId(), edge.getId(), deviceCredentialsUpdateMsg)); - } - } - if (uplinkMsg.getAssetProfileUpdateMsgCount() > 0) { - for (AssetProfileUpdateMsg assetProfileUpdateMsg : uplinkMsg.getAssetProfileUpdateMsgList()) { - result.add(ctx.getAssetProfileProcessor().processAssetProfileMsgFromEdge(edge.getTenantId(), edge, assetProfileUpdateMsg)); - } - } - if (uplinkMsg.getAssetUpdateMsgCount() > 0) { - for (AssetUpdateMsg assetUpdateMsg : uplinkMsg.getAssetUpdateMsgList()) { - result.add(ctx.getAssetProcessor().processAssetMsgFromEdge(edge.getTenantId(), edge, assetUpdateMsg)); - } - } - if (uplinkMsg.getRuleChainUpdateMsgCount() > 0) { - for (RuleChainUpdateMsg ruleChainUpdateMsg : uplinkMsg.getRuleChainUpdateMsgList()) { - result.add(ctx.getRuleChainProcessor().processRuleChainMsgFromEdge(edge.getTenantId(), edge, ruleChainUpdateMsg)); - } - } - if (uplinkMsg.getRuleChainMetadataUpdateMsgCount() > 0) { - for (RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg : uplinkMsg.getRuleChainMetadataUpdateMsgList()) { - result.add(ctx.getRuleChainProcessor().processRuleChainMetadataMsgFromEdge(edge.getTenantId(), edge, ruleChainMetadataUpdateMsg)); - } - } - if (uplinkMsg.getEntityViewUpdateMsgCount() > 0) { - for (EntityViewUpdateMsg entityViewUpdateMsg : uplinkMsg.getEntityViewUpdateMsgList()) { - result.add(ctx.getEntityViewProcessor().processEntityViewMsgFromEdge(edge.getTenantId(), edge, entityViewUpdateMsg)); - } - } - if (uplinkMsg.getEntityDataCount() > 0) { - for (EntityDataProto entityData : uplinkMsg.getEntityDataList()) { - result.addAll(ctx.getTelemetryProcessor().processTelemetryMsg(edge.getTenantId(), entityData)); - } - } - if (uplinkMsg.getAlarmUpdateMsgCount() > 0) { - for (AlarmUpdateMsg alarmUpdateMsg : uplinkMsg.getAlarmUpdateMsgList()) { - result.add(ctx.getAlarmProcessor().processAlarmMsgFromEdge(edge.getTenantId(), edge.getId(), alarmUpdateMsg)); - } - } - if (uplinkMsg.getAlarmCommentUpdateMsgCount() > 0) { - for (AlarmCommentUpdateMsg alarmCommentUpdateMsg : uplinkMsg.getAlarmCommentUpdateMsgList()) { - result.add(ctx.getAlarmCommentProcessor().processAlarmCommentMsgFromEdge(edge.getTenantId(), edge.getId(), alarmCommentUpdateMsg)); - } - } - if (uplinkMsg.getRelationUpdateMsgCount() > 0) { - for (RelationUpdateMsg relationUpdateMsg : uplinkMsg.getRelationUpdateMsgList()) { - result.add(ctx.getRelationProcessor().processRelationMsgFromEdge(edge.getTenantId(), edge, relationUpdateMsg)); - } - } - if (uplinkMsg.getDashboardUpdateMsgCount() > 0) { - for (DashboardUpdateMsg dashboardUpdateMsg : uplinkMsg.getDashboardUpdateMsgList()) { - result.add(ctx.getDashboardProcessor().processDashboardMsgFromEdge(edge.getTenantId(), edge, dashboardUpdateMsg)); - } - } - if (uplinkMsg.getResourceUpdateMsgCount() > 0) { - for (ResourceUpdateMsg resourceUpdateMsg : uplinkMsg.getResourceUpdateMsgList()) { - result.add(ctx.getResourceProcessor().processResourceMsgFromEdge(edge.getTenantId(), edge, resourceUpdateMsg)); - } - } - if (uplinkMsg.getRuleChainMetadataRequestMsgCount() > 0) { - for (RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg : uplinkMsg.getRuleChainMetadataRequestMsgList()) { - result.add(ctx.getEdgeRequestsService().processRuleChainMetadataRequestMsg(edge.getTenantId(), edge, ruleChainMetadataRequestMsg)); - } - } - if (uplinkMsg.getAttributesRequestMsgCount() > 0) { - for (AttributesRequestMsg attributesRequestMsg : uplinkMsg.getAttributesRequestMsgList()) { - result.add(ctx.getEdgeRequestsService().processAttributesRequestMsg(edge.getTenantId(), edge, attributesRequestMsg)); - } - } - if (uplinkMsg.getRelationRequestMsgCount() > 0) { - for (RelationRequestMsg relationRequestMsg : uplinkMsg.getRelationRequestMsgList()) { - result.add(ctx.getEdgeRequestsService().processRelationRequestMsg(edge.getTenantId(), edge, relationRequestMsg)); - } - } - if (uplinkMsg.getCalculatedFieldRequestMsgCount() > 0) { - for (CalculatedFieldRequestMsg calculatedFieldRequestMsg : uplinkMsg.getCalculatedFieldRequestMsgList()) { - result.add(ctx.getEdgeRequestsService().processCalculatedFieldRequestMsg(edge.getTenantId(), edge, calculatedFieldRequestMsg)); - } - } - if (uplinkMsg.getUserCredentialsRequestMsgCount() > 0) { - for (UserCredentialsRequestMsg userCredentialsRequestMsg : uplinkMsg.getUserCredentialsRequestMsgList()) { - result.add(ctx.getEdgeRequestsService().processUserCredentialsRequestMsg(edge.getTenantId(), edge, userCredentialsRequestMsg)); - } - } - if (uplinkMsg.getDeviceCredentialsRequestMsgCount() > 0) { - for (DeviceCredentialsRequestMsg deviceCredentialsRequestMsg : uplinkMsg.getDeviceCredentialsRequestMsgList()) { - result.add(ctx.getEdgeRequestsService().processDeviceCredentialsRequestMsg(edge.getTenantId(), edge, deviceCredentialsRequestMsg)); - } - } - if (uplinkMsg.getDeviceRpcCallMsgCount() > 0) { - for (DeviceRpcCallMsg deviceRpcCallMsg : uplinkMsg.getDeviceRpcCallMsgList()) { - result.add(ctx.getDeviceProcessor().processDeviceRpcCallFromEdge(edge.getTenantId(), edge, deviceRpcCallMsg)); - } - } - if (uplinkMsg.getWidgetBundleTypesRequestMsgCount() > 0) { - for (WidgetBundleTypesRequestMsg widgetBundleTypesRequestMsg : uplinkMsg.getWidgetBundleTypesRequestMsgList()) { - result.add(ctx.getEdgeRequestsService().processWidgetBundleTypesRequestMsg(edge.getTenantId(), edge, widgetBundleTypesRequestMsg)); - } - } - if (uplinkMsg.getEntityViewsRequestMsgCount() > 0) { - for (EntityViewsRequestMsg entityViewRequestMsg : uplinkMsg.getEntityViewsRequestMsgList()) { - result.add(ctx.getEdgeRequestsService().processEntityViewsRequestMsg(edge.getTenantId(), edge, entityViewRequestMsg)); - } - } - if (uplinkMsg.getCalculatedFieldUpdateMsgCount() > 0) { - for (CalculatedFieldUpdateMsg calculatedFieldUpdateMsg : uplinkMsg.getCalculatedFieldUpdateMsgList()) { - result.add(ctx.getCalculatedFieldProcessor().processCalculatedFieldMsgFromEdge(edge.getTenantId(), edge, calculatedFieldUpdateMsg)); - } - } - if (uplinkMsg.getAiModelUpdateMsgCount() > 0) { - for (AiModelUpdateMsg aiModelUpdateMsg : uplinkMsg.getAiModelUpdateMsgList()) { - result.add(ctx.getAiModelProcessor().processAiModelMsgFromEdge(edge.getTenantId(), edge, aiModelUpdateMsg)); - } - } - if (uplinkMsg.getUserUpdateMsgCount() > 0) { - for (UserUpdateMsg userUpdateMsg : uplinkMsg.getUserUpdateMsgList()) { - sequenceDependencyLock.lock(); - try { - result.add(ctx.getUserProcessor().processUserMsgFromEdge(edge.getTenantId(), edge, userUpdateMsg)); - } finally { - sequenceDependencyLock.unlock(); - } - } - } - if (uplinkMsg.getUserCredentialsUpdateMsgCount() > 0) { - for (UserCredentialsUpdateMsg userCredentialsUpdateMsg : uplinkMsg.getUserCredentialsUpdateMsgList()) { - sequenceDependencyLock.lock(); - try { - result.add(ctx.getUserProcessor().processUserCredentialsMsgFromEdge(edge.getTenantId(), edge, userCredentialsUpdateMsg)); - } finally { - sequenceDependencyLock.unlock(); - } - } - } - } catch (Exception e) { - String failureMsg = String.format("Can't process uplink msg [%s] from edge", uplinkMsg); - log.trace("[{}][{}] Can't process uplink msg [{}]", tenantId, edge.getId(), uplinkMsg, e); - ctx.getRuleProcessor().process(EdgeCommunicationFailureTrigger.builder().tenantId(tenantId).edgeId(edge.getId()) - .customerId(edge.getCustomerId()).edgeName(edge.getName()).failureMsg(failureMsg).error(e.getMessage()).build()); - return Futures.immediateFailedFuture(e); - } - return Futures.allAsList(result); - } - - protected boolean destroy() { - return true; - } - - protected void cleanUp() {} - - @Override - public void close() { - log.debug("[{}][{}] Closing session", tenantId, sessionId); - connected = false; - try { - outputStream.onCompleted(); - } catch (Exception e) { - log.debug("[{}][{}] Failed to close output stream: {}", tenantId, sessionId, e.getMessage()); - } - } - -} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeRpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeRpcService.java index 3907dfeb7f..aae6c7ad75 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeRpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeRpcService.java @@ -20,7 +20,6 @@ import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.msg.edge.EdgeSessionMsg; import org.thingsboard.server.common.msg.edge.FromEdgeSyncResponse; -import org.thingsboard.server.common.msg.edge.ToEdgeSyncRequest; import java.util.function.Consumer; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSessionState.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSessionState.java index f9071183d6..bc7883feae 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSessionState.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSessionState.java @@ -16,19 +16,70 @@ package org.thingsboard.server.service.edge.rpc; import com.google.common.util.concurrent.SettableFuture; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.gen.edge.v1.DownlinkMsg; +import org.thingsboard.server.gen.edge.v1.EdgeVersion; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; +import java.util.UUID; import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; -@Data +@Getter public class EdgeSessionState { - private final Map pendingMsgsMap = Collections.synchronizedMap(new LinkedHashMap<>()); + @Setter private SettableFuture sendDownlinkMsgsFuture; + @Setter private ScheduledFuture scheduledSendDownlinkTask; + @Setter + private volatile boolean connected; + @Setter + private EdgeVersion edgeVersion; + private final UUID sessionId = UUID.randomUUID(); + private final Map pendingMsgsMap = Collections.synchronizedMap(new LinkedHashMap<>()); + private final Lock sequenceDependencyLock = new ReentrantLock(); + private final AtomicBoolean syncInProgress = new AtomicBoolean(false); + private TenantId tenantId; + private Edge edge; + + public void setEdge(Edge edge) { + if (edge == null) { + return; + } + this.edge = edge; + this.tenantId = edge.getTenantId(); + } + + public EdgeId getEdgeId() { + return edge != null ? edge.getId() : null; + } + + public boolean tryStartSync() { + return syncInProgress.compareAndSet(false, true); + } + + public void finishSync() { + syncInProgress.set(false); + } + + public boolean isSyncInProgress() { + return syncInProgress.get(); + } + + public void lockSequenceDependency() { + sequenceDependencyLock.lock(); + } + public void unlockSequenceDependency() { + sequenceDependencyLock.unlock(); + } } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeUplinkMessageDispatcher.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeUplinkMessageDispatcher.java new file mode 100644 index 0000000000..83628396df --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeUplinkMessageDispatcher.java @@ -0,0 +1,223 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc; + +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.notification.rule.trigger.EdgeCommunicationFailureTrigger; +import org.thingsboard.server.gen.edge.v1.AiModelUpdateMsg; +import org.thingsboard.server.gen.edge.v1.AlarmCommentUpdateMsg; +import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg; +import org.thingsboard.server.gen.edge.v1.AssetProfileUpdateMsg; +import org.thingsboard.server.gen.edge.v1.AssetUpdateMsg; +import org.thingsboard.server.gen.edge.v1.AttributesRequestMsg; +import org.thingsboard.server.gen.edge.v1.CalculatedFieldRequestMsg; +import org.thingsboard.server.gen.edge.v1.CalculatedFieldUpdateMsg; +import org.thingsboard.server.gen.edge.v1.DashboardUpdateMsg; +import org.thingsboard.server.gen.edge.v1.DeviceCredentialsRequestMsg; +import org.thingsboard.server.gen.edge.v1.DeviceCredentialsUpdateMsg; +import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg; +import org.thingsboard.server.gen.edge.v1.DeviceRpcCallMsg; +import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg; +import org.thingsboard.server.gen.edge.v1.EntityDataProto; +import org.thingsboard.server.gen.edge.v1.EntityViewUpdateMsg; +import org.thingsboard.server.gen.edge.v1.EntityViewsRequestMsg; +import org.thingsboard.server.gen.edge.v1.RelationRequestMsg; +import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg; +import org.thingsboard.server.gen.edge.v1.ResourceUpdateMsg; +import org.thingsboard.server.gen.edge.v1.RuleChainMetadataRequestMsg; +import org.thingsboard.server.gen.edge.v1.RuleChainMetadataUpdateMsg; +import org.thingsboard.server.gen.edge.v1.RuleChainUpdateMsg; +import org.thingsboard.server.gen.edge.v1.UplinkMsg; +import org.thingsboard.server.gen.edge.v1.UserCredentialsRequestMsg; +import org.thingsboard.server.gen.edge.v1.UserCredentialsUpdateMsg; +import org.thingsboard.server.gen.edge.v1.UserUpdateMsg; +import org.thingsboard.server.gen.edge.v1.WidgetBundleTypesRequestMsg; +import org.thingsboard.server.service.edge.EdgeContextComponent; + +import java.util.ArrayList; +import java.util.List; + +@Service +@Slf4j +@RequiredArgsConstructor +public class EdgeUplinkMessageDispatcher { + + private final EdgeContextComponent ctx; + + public ListenableFuture> processUplinkMsg(EdgeSessionState state, UplinkMsg uplinkMsg) { + Edge edge = state.getEdge(); + List> result = new ArrayList<>(); + try { + if (uplinkMsg.getDeviceProfileUpdateMsgCount() > 0) { + for (DeviceProfileUpdateMsg deviceProfileUpdateMsg : uplinkMsg.getDeviceProfileUpdateMsgList()) { + result.add(ctx.getDeviceProfileProcessor().processDeviceProfileMsgFromEdge(edge.getTenantId(), edge, deviceProfileUpdateMsg)); + } + } + if (uplinkMsg.getDeviceUpdateMsgCount() > 0) { + for (DeviceUpdateMsg deviceUpdateMsg : uplinkMsg.getDeviceUpdateMsgList()) { + result.add(ctx.getDeviceProcessor().processDeviceMsgFromEdge(edge.getTenantId(), edge, deviceUpdateMsg)); + } + } + if (uplinkMsg.getDeviceCredentialsUpdateMsgCount() > 0) { + for (DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg : uplinkMsg.getDeviceCredentialsUpdateMsgList()) { + result.add(ctx.getDeviceProcessor().processDeviceCredentialsMsgFromEdge(edge.getTenantId(), edge.getId(), deviceCredentialsUpdateMsg)); + } + } + if (uplinkMsg.getAssetProfileUpdateMsgCount() > 0) { + for (AssetProfileUpdateMsg assetProfileUpdateMsg : uplinkMsg.getAssetProfileUpdateMsgList()) { + result.add(ctx.getAssetProfileProcessor().processAssetProfileMsgFromEdge(edge.getTenantId(), edge, assetProfileUpdateMsg)); + } + } + if (uplinkMsg.getAssetUpdateMsgCount() > 0) { + for (AssetUpdateMsg assetUpdateMsg : uplinkMsg.getAssetUpdateMsgList()) { + result.add(ctx.getAssetProcessor().processAssetMsgFromEdge(edge.getTenantId(), edge, assetUpdateMsg)); + } + } + if (uplinkMsg.getRuleChainUpdateMsgCount() > 0) { + for (RuleChainUpdateMsg ruleChainUpdateMsg : uplinkMsg.getRuleChainUpdateMsgList()) { + result.add(ctx.getRuleChainProcessor().processRuleChainMsgFromEdge(edge.getTenantId(), edge, ruleChainUpdateMsg)); + } + } + if (uplinkMsg.getRuleChainMetadataUpdateMsgCount() > 0) { + for (RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg : uplinkMsg.getRuleChainMetadataUpdateMsgList()) { + result.add(ctx.getRuleChainProcessor().processRuleChainMetadataMsgFromEdge(edge.getTenantId(), edge, ruleChainMetadataUpdateMsg)); + } + } + if (uplinkMsg.getEntityViewUpdateMsgCount() > 0) { + for (EntityViewUpdateMsg entityViewUpdateMsg : uplinkMsg.getEntityViewUpdateMsgList()) { + result.add(ctx.getEntityViewProcessor().processEntityViewMsgFromEdge(edge.getTenantId(), edge, entityViewUpdateMsg)); + } + } + if (uplinkMsg.getEntityDataCount() > 0) { + for (EntityDataProto entityData : uplinkMsg.getEntityDataList()) { + result.addAll(ctx.getTelemetryProcessor().processTelemetryMsg(edge.getTenantId(), entityData)); + } + } + if (uplinkMsg.getAlarmUpdateMsgCount() > 0) { + for (AlarmUpdateMsg alarmUpdateMsg : uplinkMsg.getAlarmUpdateMsgList()) { + result.add(ctx.getAlarmProcessor().processAlarmMsgFromEdge(edge.getTenantId(), edge.getId(), alarmUpdateMsg)); + } + } + if (uplinkMsg.getAlarmCommentUpdateMsgCount() > 0) { + for (AlarmCommentUpdateMsg alarmCommentUpdateMsg : uplinkMsg.getAlarmCommentUpdateMsgList()) { + result.add(ctx.getAlarmCommentProcessor().processAlarmCommentMsgFromEdge(edge.getTenantId(), edge.getId(), alarmCommentUpdateMsg)); + } + } + if (uplinkMsg.getRelationUpdateMsgCount() > 0) { + for (RelationUpdateMsg relationUpdateMsg : uplinkMsg.getRelationUpdateMsgList()) { + result.add(ctx.getRelationProcessor().processRelationMsgFromEdge(edge.getTenantId(), edge, relationUpdateMsg)); + } + } + if (uplinkMsg.getDashboardUpdateMsgCount() > 0) { + for (DashboardUpdateMsg dashboardUpdateMsg : uplinkMsg.getDashboardUpdateMsgList()) { + result.add(ctx.getDashboardProcessor().processDashboardMsgFromEdge(edge.getTenantId(), edge, dashboardUpdateMsg)); + } + } + if (uplinkMsg.getResourceUpdateMsgCount() > 0) { + for (ResourceUpdateMsg resourceUpdateMsg : uplinkMsg.getResourceUpdateMsgList()) { + result.add(ctx.getResourceProcessor().processResourceMsgFromEdge(edge.getTenantId(), edge, resourceUpdateMsg)); + } + } + if (uplinkMsg.getRuleChainMetadataRequestMsgCount() > 0) { + for (RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg : uplinkMsg.getRuleChainMetadataRequestMsgList()) { + result.add(ctx.getEdgeRequestsService().processRuleChainMetadataRequestMsg(edge.getTenantId(), edge, ruleChainMetadataRequestMsg)); + } + } + if (uplinkMsg.getAttributesRequestMsgCount() > 0) { + for (AttributesRequestMsg attributesRequestMsg : uplinkMsg.getAttributesRequestMsgList()) { + result.add(ctx.getEdgeRequestsService().processAttributesRequestMsg(edge.getTenantId(), edge, attributesRequestMsg)); + } + } + if (uplinkMsg.getRelationRequestMsgCount() > 0) { + for (RelationRequestMsg relationRequestMsg : uplinkMsg.getRelationRequestMsgList()) { + result.add(ctx.getEdgeRequestsService().processRelationRequestMsg(edge.getTenantId(), edge, relationRequestMsg)); + } + } + if (uplinkMsg.getCalculatedFieldRequestMsgCount() > 0) { + for (CalculatedFieldRequestMsg calculatedFieldRequestMsg : uplinkMsg.getCalculatedFieldRequestMsgList()) { + result.add(ctx.getEdgeRequestsService().processCalculatedFieldRequestMsg(edge.getTenantId(), edge, calculatedFieldRequestMsg)); + } + } + if (uplinkMsg.getUserCredentialsRequestMsgCount() > 0) { + for (UserCredentialsRequestMsg userCredentialsRequestMsg : uplinkMsg.getUserCredentialsRequestMsgList()) { + result.add(ctx.getEdgeRequestsService().processUserCredentialsRequestMsg(edge.getTenantId(), edge, userCredentialsRequestMsg)); + } + } + if (uplinkMsg.getDeviceCredentialsRequestMsgCount() > 0) { + for (DeviceCredentialsRequestMsg deviceCredentialsRequestMsg : uplinkMsg.getDeviceCredentialsRequestMsgList()) { + result.add(ctx.getEdgeRequestsService().processDeviceCredentialsRequestMsg(edge.getTenantId(), edge, deviceCredentialsRequestMsg)); + } + } + if (uplinkMsg.getDeviceRpcCallMsgCount() > 0) { + for (DeviceRpcCallMsg deviceRpcCallMsg : uplinkMsg.getDeviceRpcCallMsgList()) { + result.add(ctx.getDeviceProcessor().processDeviceRpcCallFromEdge(edge.getTenantId(), edge, deviceRpcCallMsg)); + } + } + if (uplinkMsg.getWidgetBundleTypesRequestMsgCount() > 0) { + for (WidgetBundleTypesRequestMsg widgetBundleTypesRequestMsg : uplinkMsg.getWidgetBundleTypesRequestMsgList()) { + result.add(ctx.getEdgeRequestsService().processWidgetBundleTypesRequestMsg(edge.getTenantId(), edge, widgetBundleTypesRequestMsg)); + } + } + if (uplinkMsg.getEntityViewsRequestMsgCount() > 0) { + for (EntityViewsRequestMsg entityViewRequestMsg : uplinkMsg.getEntityViewsRequestMsgList()) { + result.add(ctx.getEdgeRequestsService().processEntityViewsRequestMsg(edge.getTenantId(), edge, entityViewRequestMsg)); + } + } + if (uplinkMsg.getCalculatedFieldUpdateMsgCount() > 0) { + for (CalculatedFieldUpdateMsg calculatedFieldUpdateMsg : uplinkMsg.getCalculatedFieldUpdateMsgList()) { + result.add(ctx.getCalculatedFieldProcessor().processCalculatedFieldMsgFromEdge(edge.getTenantId(), edge, calculatedFieldUpdateMsg)); + } + } + if (uplinkMsg.getAiModelUpdateMsgCount() > 0) { + for (AiModelUpdateMsg aiModelUpdateMsg : uplinkMsg.getAiModelUpdateMsgList()) { + result.add(ctx.getAiModelProcessor().processAiModelMsgFromEdge(edge.getTenantId(), edge, aiModelUpdateMsg)); + } + } + if (uplinkMsg.getUserUpdateMsgCount() > 0) { + for (UserUpdateMsg userUpdateMsg : uplinkMsg.getUserUpdateMsgList()) { + state.lockSequenceDependency(); + try { + result.add(ctx.getUserProcessor().processUserMsgFromEdge(edge.getTenantId(), edge, userUpdateMsg)); + } finally { + state.unlockSequenceDependency(); + } + } + } + if (uplinkMsg.getUserCredentialsUpdateMsgCount() > 0) { + for (UserCredentialsUpdateMsg userCredentialsUpdateMsg : uplinkMsg.getUserCredentialsUpdateMsgList()) { + state.lockSequenceDependency(); + try { + result.add(ctx.getUserProcessor().processUserCredentialsMsgFromEdge(edge.getTenantId(), edge, userCredentialsUpdateMsg)); + } finally { + state.unlockSequenceDependency(); + } + } + } + } catch (Exception e) { + String failureMsg = String.format("Can't process uplink msg [%s] from edge", uplinkMsg); + log.trace("[{}][{}] Can't process uplink msg [{}]", edge.getTenantId(), edge.getId(), uplinkMsg, e); + ctx.getRuleProcessor().process(EdgeCommunicationFailureTrigger.builder().tenantId(edge.getTenantId()).edgeId(edge.getId()) + .customerId(edge.getCustomerId()).edgeName(edge.getName()).failureMsg(failureMsg).error(e.getMessage()).build()); + return Futures.immediateFailedFuture(e); + } + return Futures.allAsList(result); + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/GrpcServer.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/GrpcServer.java new file mode 100644 index 0000000000..7da0aecc70 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/GrpcServer.java @@ -0,0 +1,103 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc; + +import io.grpc.Server; +import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; +import jakarta.annotation.PreDestroy; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.ResourceUtils; +import org.thingsboard.server.gen.edge.v1.EdgeRpcServiceGrpc; +import org.thingsboard.server.gen.edge.v1.EdgeRpcServiceGrpc.EdgeRpcServiceImplBase; +import org.thingsboard.server.queue.util.AfterStartUp; +import org.thingsboard.server.service.edge.rpc.service.EdgeRpcServiceImpl; + +import java.io.IOException; +import java.io.InputStream; +import java.util.concurrent.TimeUnit; + +@Component +@Slf4j +@RequiredArgsConstructor +public class GrpcServer { + + @Value("${edges.rpc.port}") + private int rpcPort; + @Value("${edges.rpc.ssl.enabled}") + private boolean sslEnabled; + @Value("${edges.rpc.ssl.cert}") + private String certFileResource; + @Value("${edges.rpc.ssl.private_key}") + private String privateKeyResource; + @Value("${edges.rpc.client_max_keep_alive_time_sec:1}") + private int clientMaxKeepAliveTimeSec; + @Value("${edges.rpc.max_inbound_message_size:4194304}") + private int maxInboundMessageSize; + @Value("${edges.rpc.keep_alive_time_sec:10}") + private int keepAliveTimeSec; + @Value("${edges.rpc.keep_alive_timeout_sec:5}") + private int keepAliveTimeoutSec; + + private final EdgeRpcServiceImplBase edgeGrpcService; + + private Server server; + + @AfterStartUp(order = AfterStartUp.REGULAR_SERVICE) + public void onStartUp() { + log.info("Initializing Edge RPC server!"); + NettyServerBuilder serverBuilder = NettyServerBuilder.forPort(rpcPort) + .permitKeepAliveTime(clientMaxKeepAliveTimeSec, TimeUnit.SECONDS) + .keepAliveTime(keepAliveTimeSec, TimeUnit.SECONDS) + .keepAliveTimeout(keepAliveTimeoutSec, TimeUnit.SECONDS) + .permitKeepAliveWithoutCalls(true) + .maxInboundMessageSize(maxInboundMessageSize) + .addService(edgeGrpcService); + + if (sslEnabled) { + addSslConfiguration(serverBuilder); + } + server = serverBuilder.build(); + log.info("Going to start Edge RPC server using port: {}", rpcPort); + try { + server.start(); + } catch (IOException e) { + log.error("Failed to start Edge RPC server!", e); + throw new RuntimeException("Failed to start Edge RPC server!"); + } + log.info("Edge RPC server initialized!"); + } + + private void addSslConfiguration(NettyServerBuilder serverBuilder) { + try { + InputStream certFileIs = ResourceUtils.getInputStream(this, certFileResource); + InputStream privateKeyFileIs = ResourceUtils.getInputStream(this, privateKeyResource); + serverBuilder.useTransportSecurity(certFileIs, privateKeyFileIs); + } catch (Exception e) { + log.error("Unable to set up SSL context. Reason: " + e.getMessage(), e); + throw new RuntimeException("Unable to set up SSL context!", e); + } + } + + @PreDestroy + public void destroy() { + if (server != null) { + server.shutdownNow(); + } + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/KafkaEdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/KafkaEdgeGrpcSession.java deleted file mode 100644 index 63669a8e3d..0000000000 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/KafkaEdgeGrpcSession.java +++ /dev/null @@ -1,184 +0,0 @@ -/** - * Copyright © 2016-2025 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.service.edge.rpc; - -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import io.grpc.stub.StreamObserver; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.thingsboard.common.util.ThingsBoardThreadFactory; -import org.thingsboard.server.common.data.edge.Edge; -import org.thingsboard.server.common.data.edge.EdgeEvent; -import org.thingsboard.server.common.data.id.EdgeId; -import org.thingsboard.server.common.util.ProtoUtils; -import org.thingsboard.server.gen.edge.v1.DownlinkMsg; -import org.thingsboard.server.gen.edge.v1.ResponseMsg; -import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeEventNotificationMsg; -import org.thingsboard.server.queue.TbQueueConsumer; -import org.thingsboard.server.queue.common.TbProtoQueueMsg; -import org.thingsboard.server.queue.common.consumer.QueueConsumerManager; -import org.thingsboard.server.queue.discovery.TopicService; -import org.thingsboard.server.queue.kafka.KafkaAdmin; -import org.thingsboard.server.queue.provider.TbCoreQueueFactory; -import org.thingsboard.server.service.edge.EdgeContextComponent; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.function.BiConsumer; - -@Slf4j -public class KafkaEdgeGrpcSession extends EdgeGrpcSession { - - private final TopicService topicService; - private final TbCoreQueueFactory tbCoreQueueFactory; - private final KafkaAdmin kafkaAdmin; - - private volatile boolean isHighPriorityProcessing; - - @Getter - private QueueConsumerManager> consumer; - - private ExecutorService consumerExecutor; - - public KafkaEdgeGrpcSession(EdgeContextComponent ctx, TopicService topicService, TbCoreQueueFactory tbCoreQueueFactory, - KafkaAdmin kafkaAdmin, StreamObserver outputStream, - BiConsumer sessionOpenListener, BiConsumer sessionCloseListener, - ScheduledExecutorService sendDownlinkExecutorService, int maxInboundMessageSize, int maxHighPriorityQueueSizePerSession) { - super(ctx, outputStream, sessionOpenListener, sessionCloseListener, sendDownlinkExecutorService, maxInboundMessageSize, maxHighPriorityQueueSizePerSession); - this.topicService = topicService; - this.tbCoreQueueFactory = tbCoreQueueFactory; - this.kafkaAdmin = kafkaAdmin; - } - - private void processMsgs(List> msgs, TbQueueConsumer> consumer) { - log.trace("[{}][{}] starting processing edge events", tenantId, edge.getId()); - if (!isConnected() || isSyncInProgress() || isHighPriorityProcessing) { - log.debug("[{}][{}] edge not connected, edge sync is not completed or high priority processing in progress, " + - "connected = {}, sync in progress = {}, high priority in progress = {}. Skipping iteration", - tenantId, edge.getId(), isConnected(), isSyncInProgress(), isHighPriorityProcessing); - return; - } - List edgeEvents = new ArrayList<>(); - for (TbProtoQueueMsg msg : msgs) { - EdgeEvent edgeEvent = ProtoUtils.fromProto(msg.getValue().getEdgeEventMsg()); - edgeEvents.add(edgeEvent); - } - List downlinkMsgsPack = convertToDownlinkMsgsPack(edgeEvents); - try { - boolean isInterrupted = sendDownlinkMsgsPack(downlinkMsgsPack).get(); - if (isInterrupted) { - log.debug("[{}][{}] Send downlink messages task was interrupted", tenantId, edge.getId()); - } else { - consumer.commit(); - } - } catch (Exception e) { - log.error("[{}][{}] Failed to process downlink messages", tenantId, edge.getId(), e); - } - } - - @Override - public ListenableFuture migrateEdgeEvents() throws Exception { - return super.processEdgeEvents(); - } - - @Override - public ListenableFuture processEdgeEvents() { - if (!isConnected() || isSyncInProgress() || isHighPriorityProcessing) { - log.warn("[{}][{}] Session is not ready (connected={}, syncInProgress={}, highPriority={}), skip starting edge event consumer", - tenantId, edge != null ? edge.getId() : null, isConnected(), isSyncInProgress(), isHighPriorityProcessing); - return Futures.immediateFuture(Boolean.FALSE); - } - if (consumer == null || (consumer.getConsumer() != null && consumer.getConsumer().isStopped())) { - try { - if (consumerExecutor != null && !consumerExecutor.isShutdown()) { - try { - consumerExecutor.shutdown(); - awaitConsumerTermination(); - } catch (Exception e) { - log.warn("[{}][{}] Failed to shutdown previous consumer executor", tenantId, edge.getId(), e); - } - } - this.consumerExecutor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("edge-event-consumer")); - this.consumer = QueueConsumerManager.>builder() - .name("TB Edge events [" + edge.getId() + "]") - .msgPackProcessor(this::processMsgs) - .pollInterval(ctx.getEdgeEventStorageSettings().getNoRecordsSleepInterval()) - .consumerCreator(() -> tbCoreQueueFactory.createEdgeEventMsgConsumer(tenantId, edge.getId())) - .consumerExecutor(consumerExecutor) - .threadPrefix("edge-events-" + edge.getId()) - .build(); - consumer.subscribe(); - consumer.launch(); - } catch (Exception e) { - destroy(); - log.warn("[{}][{}] Failed to start edge event consumer", sessionId, edge.getId(), e); - } - } - return Futures.immediateFuture(Boolean.FALSE); - } - - @Override - public void processHighPriorityEvents() { - isHighPriorityProcessing = true; - super.processHighPriorityEvents(); - isHighPriorityProcessing = false; - } - - @Override - public boolean destroy() { - try { - if (consumer != null) { - log.info("[{}][{}] Stopping edge event consumer...", tenantId, edge != null ? edge.getId() : null); - consumer.stop(); - } - } catch (Exception e) { - log.warn("[{}][{}] Failed to stop edge event consumer", tenantId, edge.getId(), e); - return false; - } - consumer = null; - try { - if (consumerExecutor != null && !consumerExecutor.isShutdown()) { - consumerExecutor.shutdown(); - awaitConsumerTermination(); - } - } catch (Exception e) { - log.warn("[{}][{}] Failed to shutdown edge event consumer executor", tenantId, edge.getId(), e); - return false; - } - return true; - } - - private void awaitConsumerTermination() { - try { - consumerExecutor.awaitTermination(5, java.util.concurrent.TimeUnit.SECONDS); - } catch (InterruptedException ie) { - log.warn("[{}][{}] Interrupted while awaiting consumer executor termination", tenantId, edge.getId()); - } - } - - @Override - public void cleanUp() { - String topic = topicService.buildEdgeEventNotificationsTopicPartitionInfo(tenantId, edge.getId()).getTopic(); - kafkaAdmin.deleteTopic(topic); - kafkaAdmin.deleteConsumerGroup(topic); - } - -} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/PostgresEdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/PostgresEdgeGrpcSession.java deleted file mode 100644 index 4cd5bb43e2..0000000000 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/PostgresEdgeGrpcSession.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright © 2016-2025 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.service.edge.rpc; - -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import io.grpc.stub.StreamObserver; -import lombok.extern.slf4j.Slf4j; -import org.thingsboard.server.common.data.edge.Edge; -import org.thingsboard.server.common.data.id.EdgeId; -import org.thingsboard.server.gen.edge.v1.ResponseMsg; -import org.thingsboard.server.service.edge.EdgeContextComponent; - -import java.util.UUID; -import java.util.concurrent.ScheduledExecutorService; -import java.util.function.BiConsumer; - -@Slf4j -public class PostgresEdgeGrpcSession extends EdgeGrpcSession { - - PostgresEdgeGrpcSession(EdgeContextComponent ctx, StreamObserver outputStream, - BiConsumer sessionOpenListener, - BiConsumer sessionCloseListener, ScheduledExecutorService sendDownlinkExecutorService, - int maxInboundMessageSize, int maxHighPriorityQueueSizePerSession) { - super(ctx, outputStream, sessionOpenListener, sessionCloseListener, sendDownlinkExecutorService, maxInboundMessageSize, maxHighPriorityQueueSizePerSession); - } - - @Override - public ListenableFuture migrateEdgeEvents() { - return Futures.immediateFuture(Boolean.FALSE); - } - -} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/EdgeEventsDispatcher.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/EdgeEventsDispatcher.java new file mode 100644 index 0000000000..8669737b3b --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/EdgeEventsDispatcher.java @@ -0,0 +1,23 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc.processor; + +import com.google.common.util.concurrent.ListenableFuture; + +public interface EdgeEventsDispatcher { + + ListenableFuture processNewEvents() throws Exception; +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/PostgresGeneralEdgeEventsDispatcher.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/PostgresGeneralEdgeEventsDispatcher.java new file mode 100644 index 0000000000..c2cd54e5d2 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/PostgresGeneralEdgeEventsDispatcher.java @@ -0,0 +1,218 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc.processor; + +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.SettableFuture; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.springframework.data.util.Pair; +import org.thingsboard.server.common.data.AttributeScope; +import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.kv.AttributeKvEntry; +import org.thingsboard.server.common.data.kv.AttributesSaveResult; +import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; +import org.thingsboard.server.common.data.kv.LongDataEntry; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.service.edge.EdgeContextComponent; +import org.thingsboard.server.service.edge.rpc.EdgeSessionState; +import org.thingsboard.server.service.edge.rpc.fetch.GeneralEdgeEventFetcher; +import org.thingsboard.server.service.edge.rpc.session.EdgeSession; + +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +@Slf4j +@RequiredArgsConstructor +public class PostgresGeneralEdgeEventsDispatcher implements EdgeEventsDispatcher { + + private static final String QUEUE_START_TS_ATTR_KEY = "queueStartTs"; + private static final String QUEUE_START_SEQ_ID_ATTR_KEY = "queueStartSeqId"; + + private final EdgeSession session; + private final EdgeContextComponent ctx; + + private Long newStartTs; + private Long previousStartTs; + private Long newStartSeqId; + private Long previousStartSeqId; + + @Override + public ListenableFuture processNewEvents() throws Exception { + EdgeSessionState state = session.getState(); + TenantId tenantId = state.getTenantId(); + EdgeId edgeId = state.getEdgeId(); + UUID sessionId = state.getSessionId(); + + SettableFuture result = SettableFuture.create(); + if (state.isConnected() && !state.isSyncInProgress()) { + setLocalPrevStartTsAndSeqId(tenantId, edgeId, sessionId); + GeneralEdgeEventFetcher fetcher = initGeneralEdgeEventFetcher(); + log.trace("[{}][{}] starting processing edge events, previousStartTs = {}, previousStartSeqId = {}", + tenantId, edgeId, previousStartTs, previousStartSeqId); + + Futures.addCallback(session.fetchAndSendEdgeEvents(fetcher), new FutureCallback<>() { + @Override + public void onSuccess(@Nullable Pair newStartTsAndSeqId) { + if (newStartTsAndSeqId != null) { + Futures.addCallback(updateQueueStartTsAndSeqId(tenantId, edgeId, newStartTsAndSeqId), new FutureCallback<>() { + @Override + public void onSuccess(@Nullable AttributesSaveResult saveResult) { + log.debug("[{}][{}] queue offset was updated [{}]", tenantId, edgeId, newStartTsAndSeqId); + boolean newEventsAvailable; + if (fetcher.isSeqIdNewCycleStarted()) { + newEventsAvailable = isNewEdgeEventsAvailable(tenantId, edgeId, sessionId); + } else { + newEventsAvailable = isSeqIdStartedNewCycle(tenantId, edgeId, sessionId); + if (!newEventsAvailable) { + newEventsAvailable = isNewEdgeEventsAvailable(tenantId, edgeId, sessionId); + } + } + result.set(newEventsAvailable); + } + + @Override + public void onFailure(Throwable t) { + log.error("[{}][{}] Failed to update queue offset [{}]", tenantId, edgeId, newStartTsAndSeqId, t); + result.setException(t); + } + }, ctx.getGrpcCallbackExecutorService()); + } else { + log.trace("[{}][{}] newStartTsAndSeqId is null. Skipping iteration without db update", tenantId, edgeId); + result.set(Boolean.FALSE); + } + } + + @Override + public void onFailure(Throwable t) { + log.error("[{}][{}] Failed to process events", tenantId, edgeId, t); + result.setException(t); + } + }, ctx.getGrpcCallbackExecutorService()); + } else { + if (state.isSyncInProgress()) { + log.trace("[{}][{}] edge sync is not completed yet. Skipping iteration", tenantId, edgeId); + result.set(Boolean.TRUE); + } else { + log.trace("[{}][{}] edge is not connected. Skipping iteration", tenantId, edgeId); + result.set(null); + } + } + return result; + } + + private boolean isSeqIdStartedNewCycle(TenantId tenantId, EdgeId edgeId, UUID sessionId) { + try { + log.trace("[{}][{}][{}] Checking if seq id started new cycle", tenantId, edgeId, sessionId); + TimePageLink pageLink = new TimePageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount(), 0, null, null, newStartTs, System.currentTimeMillis()); + PageData edgeEvents = ctx.getEdgeEventService() + .findEdgeEvents(tenantId, edgeId, 0L, previousStartSeqId == 0 ? null : previousStartSeqId - 1, pageLink); + + boolean result = !edgeEvents.getData().isEmpty(); + log.trace("[{}][{}][{}] Result of check if seq id started new cycle, result = {}", tenantId, edgeId, sessionId, result); + return result; + } catch (Exception e) { + log.error("[{}][{}][{}] Failed to execute isSeqIdStartedNewCycle", tenantId, edgeId, sessionId, e); + } + return false; + } + + private boolean isNewEdgeEventsAvailable(TenantId tenantId, EdgeId edgeId, UUID sessionId) { + try { + log.trace("[{}][{}][{}] Checking if new edge events available", tenantId, edgeId, sessionId); + TimePageLink pageLink = new TimePageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount(), 0, null, null, newStartTs, System.currentTimeMillis()); + PageData edgeEvents = ctx.getEdgeEventService().findEdgeEvents(tenantId, edgeId, newStartSeqId, null, pageLink); + boolean available = !edgeEvents.getData().isEmpty() || session.hasHighPriorityEvents(); + log.trace("[{}][{}][{}] Result of check if new edge events available, result = {}", tenantId, edgeId, sessionId, available); + return available; + } catch (Exception e) { + log.error("[{}][{}][{}] Failed to execute isNewEdgeEventsAvailable", tenantId, edgeId, sessionId, e); + } + return false; + } + + private ListenableFuture updateQueueStartTsAndSeqId(TenantId tenantId, EdgeId edgeId, Pair pair) { + newStartTs = pair.getFirst(); + newStartSeqId = pair.getSecond(); + log.trace("[{}] updateQueueStartTsAndSeqId [{}][{}][{}]", session.getState().getSessionId(), edgeId, newStartTs, newStartSeqId); + List attributes = List.of( + new BaseAttributeKvEntry(new LongDataEntry(QUEUE_START_TS_ATTR_KEY, newStartTs), System.currentTimeMillis()), + new BaseAttributeKvEntry(new LongDataEntry(QUEUE_START_SEQ_ID_ATTR_KEY, newStartSeqId), System.currentTimeMillis()) + ); + return ctx.getAttributesService().save(tenantId, edgeId, AttributeScope.SERVER_SCOPE, attributes); + } + + private GeneralEdgeEventFetcher initGeneralEdgeEventFetcher() { + return new GeneralEdgeEventFetcher( + previousStartTs, + previousStartSeqId, + false, + Integer.toUnsignedLong(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount()), + ctx.getEdgeEventService(), + ctx.getEdgeEventStorageSettings().getMisorderingCompensationMillis()); + } + + private void setLocalPrevStartTsAndSeqId(TenantId tenantId, EdgeId edgeId, UUID sessionId) throws InterruptedException, ExecutionException { + Pair startTsAndSeqId = getQueueStartTsAndSeqId(tenantId, edgeId, sessionId).get(); + previousStartTs = startTsAndSeqId.getFirst(); + previousStartSeqId = startTsAndSeqId.getSecond(); + } + + private ListenableFuture> getQueueStartTsAndSeqId(TenantId tenantId, EdgeId edgeId, UUID sessionId) { + ListenableFuture> future = ctx.getAttributesService() + .find(tenantId, edgeId, AttributeScope.SERVER_SCOPE, Arrays.asList(QUEUE_START_TS_ATTR_KEY, QUEUE_START_SEQ_ID_ATTR_KEY)); + + return Futures.transform(future, attributeKvEntries -> { + long startTs = 0L; + long startSeqId = 0L; + for (AttributeKvEntry attributeKvEntry : attributeKvEntries) { + if (QUEUE_START_TS_ATTR_KEY.equals(attributeKvEntry.getKey())) { + startTs = attributeKvEntry.getLongValue().isPresent() ? attributeKvEntry.getLongValue().get() : 0L; + } + if (QUEUE_START_SEQ_ID_ATTR_KEY.equals(attributeKvEntry.getKey())) { + startSeqId = attributeKvEntry.getLongValue().isPresent() ? attributeKvEntry.getLongValue().get() : 0L; + } + } + if (startSeqId == 0L) { + startSeqId = findStartSeqIdFromOldestEventIfAny(tenantId, edgeId, sessionId); + } + return Pair.of(startTs, startSeqId); + }, ctx.getGrpcCallbackExecutorService()); + } + + private long findStartSeqIdFromOldestEventIfAny(TenantId tenantId, EdgeId edgeId, UUID sessionId) { + long startSeqId = 0L; + try { + TimePageLink pageLink = new TimePageLink(1, 0, null, null, null, null); + PageData edgeEvents = ctx.getEdgeEventService() + .findEdgeEvents(tenantId, edgeId, null, null, pageLink); + if (!edgeEvents.getData().isEmpty()) { + startSeqId = edgeEvents.getData().get(0).getSeqId() - 1; + } + } catch (Exception e) { + log.error("[{}][{}][{}] Failed to execute findStartSeqIdFromOldestEventIfAny", tenantId, edgeId, sessionId, e); + } + return startSeqId; + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/service/EdgeRpcServiceImpl.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/service/EdgeRpcServiceImpl.java new file mode 100644 index 0000000000..14054adbd3 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/service/EdgeRpcServiceImpl.java @@ -0,0 +1,386 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc.service; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import io.grpc.stub.StreamObserver; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.common.util.ThingsBoardExecutors; +import org.thingsboard.rule.engine.api.AttributesSaveRequest; +import org.thingsboard.rule.engine.api.TimeseriesSaveRequest; +import org.thingsboard.server.cache.TbTransactionalCache; +import org.thingsboard.server.cluster.TbClusterService; +import org.thingsboard.server.common.data.AttributeScope; +import org.thingsboard.server.common.data.DataConstants; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.kv.BooleanDataEntry; +import org.thingsboard.server.common.data.kv.LongDataEntry; +import org.thingsboard.server.common.data.msg.TbMsgType; +import org.thingsboard.server.common.data.notification.rule.trigger.EdgeConnectionTrigger; +import org.thingsboard.server.common.msg.TbMsg; +import org.thingsboard.server.common.msg.TbMsgDataType; +import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.common.msg.edge.EdgeEventUpdateMsg; +import org.thingsboard.server.common.msg.edge.EdgeHighPriorityMsg; +import org.thingsboard.server.common.msg.edge.EdgeSessionMsg; +import org.thingsboard.server.common.msg.edge.FromEdgeSyncResponse; +import org.thingsboard.server.common.msg.edge.ToEdgeSyncRequest; +import org.thingsboard.server.gen.edge.v1.EdgeRpcServiceGrpc; +import org.thingsboard.server.gen.edge.v1.RequestMsg; +import org.thingsboard.server.gen.edge.v1.ResponseMsg; +import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; +import org.thingsboard.server.service.edge.EdgeContextComponent; +import org.thingsboard.server.service.edge.rpc.EdgeRpcService; +import org.thingsboard.server.service.edge.rpc.EdgeSessionState; +import org.thingsboard.server.service.edge.rpc.session.EdgeAttributeSaveCallback; +import org.thingsboard.server.service.edge.rpc.session.EdgeSessionsHolder; +import org.thingsboard.server.service.edge.rpc.session.manager.EdgeGrpcSessionManager; +import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; + +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +import static org.thingsboard.server.service.state.DefaultDeviceStateService.ACTIVITY_STATE; +import static org.thingsboard.server.service.state.DefaultDeviceStateService.LAST_CONNECT_TIME; +import static org.thingsboard.server.service.state.DefaultDeviceStateService.LAST_DISCONNECT_TIME; + +@Service +@Slf4j +@RequiredArgsConstructor +public class EdgeRpcServiceImpl extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase implements EdgeRpcService { + + @Value("${edges.send_scheduler_pool_size}") + private int sendSchedulerPoolSize; + + @Value("${edges.state.persistToTelemetry:false}") + private boolean persistToTelemetry; + + @Autowired + @Lazy + private EdgeContextComponent ctx; + + private final EdgeSessionsHolder sessions; + private final ApplicationContext applicationContext; + private final TbClusterService clusterService; + private final TbServiceInfoProvider serviceInfoProvider; + private final TelemetrySubscriptionService tsSubService; + private final TbTransactionalCache edgeIdServiceIdCache; + + private final ConcurrentMap> localSyncEdgeRequests = new ConcurrentHashMap<>(); + private ScheduledExecutorService executorService; + private ScheduledExecutorService sendDownlinkExecutorService; + + @PostConstruct + public void onStartUp() { + this.executorService = ThingsBoardExecutors.newSingleThreadScheduledExecutor("edge-service"); + this.sendDownlinkExecutorService = ThingsBoardExecutors.newScheduledThreadPool(sendSchedulerPoolSize, "edge-send-scheduler"); + } + + @PreDestroy + private void preDestroy() { + shutdownExecutorSafely(executorService); + shutdownExecutorSafely(sendDownlinkExecutorService); + sessions.forEach(EdgeGrpcSessionManager::onEdgeDisconnect); + } + + @Override + public StreamObserver handleMsgs(StreamObserver outputStream) { + EdgeGrpcSessionManager sessionManager = applicationContext.getBean(EdgeGrpcSessionManager.class); + return sessionManager.initInputStream(outputStream, this::onEdgeConnect, this::onEdgeDisconnect, sendDownlinkExecutorService); + } + + @Override + public void onToEdgeSessionMsg(TenantId tenantId, EdgeSessionMsg msg) { + switch (msg.getMsgType()) { + case EDGE_HIGH_PRIORITY_TO_EDGE_SESSION_MSG -> { + EdgeHighPriorityMsg edgeHighPriorityMsg = (EdgeHighPriorityMsg) msg; + log.trace("[{}] edgeEventMsg [{}]", tenantId, msg); + onEdgeHighPriorityEvent(edgeHighPriorityMsg); + } + case EDGE_EVENT_UPDATE_TO_EDGE_SESSION_MSG -> { + EdgeEventUpdateMsg edgeEventUpdateMsg = (EdgeEventUpdateMsg) msg; + log.trace("[{}] onToEdgeEventUpdateMsg [{}]", tenantId, msg); + onEdgeEventUpdate(tenantId, edgeEventUpdateMsg.getEdgeId()); + } + case EDGE_SYNC_REQUEST_TO_EDGE_SESSION_MSG -> { + ToEdgeSyncRequest toEdgeSyncRequest = (ToEdgeSyncRequest) msg; + log.trace("[{}] toEdgeSyncRequest [{}]", tenantId, msg); + startSyncProcess(tenantId, toEdgeSyncRequest.getEdgeId(), toEdgeSyncRequest.getId(), toEdgeSyncRequest.getServiceId()); + } + case EDGE_SYNC_RESPONSE_FROM_EDGE_SESSION_MSG -> { + FromEdgeSyncResponse fromEdgeSyncResponse = (FromEdgeSyncResponse) msg; + log.trace("[{}] fromEdgeSyncResponse [{}]", tenantId, msg); + processSyncResponse(fromEdgeSyncResponse); + } + } + } + + @Override + public void updateEdge(TenantId tenantId, Edge edge) { + if (edge == null) { + log.warn("[{}] Edge is null - edge is removed and outdated notification is in process!", tenantId); + return; + } + EdgeGrpcSessionManager session = sessions.getByEdgeId(edge.getId()); + if (session != null && session.getState().isConnected()) { + log.debug("[{}] Updating configuration for edge [{}] [{}]", tenantId, edge.getName(), edge.getId()); + session.onConfigurationUpdate(edge); + } else { + log.debug("[{}] Session doesn't exist for edge [{}] [{}]", tenantId, edge.getName(), edge.getId()); + } + } + + @Override + public void deleteEdge(TenantId tenantId, EdgeId edgeId) { + EdgeGrpcSessionManager session = sessions.getByEdgeId(edgeId); + if (session != null && session.getState().isConnected()) { + log.info("[{}] Closing and removing session for edge [{}]", tenantId, edgeId); + session.destroyAndMarkAsZombieIfFailed(); + session.onEdgeRemoval(); + sessions.remove(session); + } + } + + @Override + public void processSyncRequest(TenantId tenantId, EdgeId edgeId, Consumer responseConsumer) { + ToEdgeSyncRequest request = new ToEdgeSyncRequest(UUID.randomUUID(), tenantId, edgeId, serviceInfoProvider.getServiceId()); + + UUID requestId = request.getId(); + EdgeGrpcSessionManager session = sessions.getByEdgeId(request.getEdgeId()); + if (session != null && session.getState().isSyncInProgress()) { + responseConsumer.accept(new FromEdgeSyncResponse(requestId, request.getTenantId(), request.getEdgeId(), false, "Sync process is active at the moment")); + } else { + log.trace("[{}][{}] Processing sync edge request [{}], serviceId [{}]", request.getTenantId(), request.getId(), request.getEdgeId(), request.getServiceId()); + localSyncEdgeRequests.put(requestId, responseConsumer); + clusterService.pushEdgeSyncRequestToEdge(request); + scheduleSyncRequestTimeout(request, requestId); + } + } + + private void onEdgeConnect(EdgeId edgeId, EdgeGrpcSessionManager edgeSession) { + EdgeSessionState state = edgeSession.getState(); + Edge edge = state.getEdge(); + TenantId tenantId = state.getTenantId(); + log.info("[{}][{}] edge [{}] connected successfully.", tenantId, state.getSessionId(), edgeId); + if (sessions.hasByEdgeId(edgeId)) { + EdgeGrpcSessionManager existingSession = sessions.getByEdgeId(edgeId); + if (existingSession != null) { + UUID sessionId = existingSession.getState().getSessionId(); + log.info("[{}][{}] Replacing existing session [{}] for edge [{}]", tenantId, state.getSessionId(), sessionId, edgeId); + existingSession.destroyAndMarkAsZombieIfFailed(); + sessions.removeBySessionId(sessionId); + } + } + sessions.put(edgeSession); + save(tenantId, edgeId, ACTIVITY_STATE, true); + long lastConnectTs = System.currentTimeMillis(); + save(tenantId, edgeId, LAST_CONNECT_TIME, lastConnectTs); + edgeIdServiceIdCache.put(edgeId, serviceInfoProvider.getServiceId()); + pushRuleEngineMessage(tenantId, edge, lastConnectTs, TbMsgType.CONNECT_EVENT); + edgeSession.onEdgeConnect(); + } + + private void onEdgeDisconnect(Edge edge, UUID sessionId) { + TenantId tenantId = edge.getTenantId(); + EdgeId edgeId = edge.getId(); + log.info("[{}][{}] edge disconnected!", edgeId, sessionId); + EdgeGrpcSessionManager current = sessions.getByEdgeId(edgeId); + if (current != null && current.getState().getSessionId().equals(sessionId)) { + EdgeGrpcSessionManager toRemove = sessions.removeByEdgeId(edgeId); + toRemove.onEdgeDisconnect(); + toRemove.destroyAndMarkAsZombieIfFailed(); + sessions.removeBySessionId(sessionId); + save(tenantId, edgeId, ACTIVITY_STATE, false); + long lastDisconnectTs = System.currentTimeMillis(); + save(tenantId, edgeId, LAST_DISCONNECT_TIME, lastDisconnectTs); + pushRuleEngineMessage(tenantId, edge, lastDisconnectTs, TbMsgType.DISCONNECT_EVENT); + } else { + log.info("[{}] edge session [{}] is not current anymore. Attempting to destroy it by sessionId.", edgeId, sessionId); + EdgeGrpcSessionManager stale = sessions.removeBySessionId(sessionId); + if (stale != null) { + try { + stale.destroyAndMarkAsZombieIfFailed(); + log.info("[{}][{}] Successfully destroyed stale session for edge [{}]", stale.getState().getTenantId(), sessionId, edgeId); + } catch (Exception e) { + log.warn("[{}][{}] Failed to destroy stale session for edge [{}]", stale.getState().getTenantId(), sessionId, edgeId, e); + } + } else { + log.debug("[{}] No session found by sessionId [{}] to destroy", edgeId, sessionId); + } + } + edgeIdServiceIdCache.evict(edgeId); + } + + private void scheduleSyncRequestTimeout(ToEdgeSyncRequest request, UUID requestId) { + log.trace("[{}] scheduling sync edge request", requestId); + executorService.schedule(() -> { + log.trace("[{}] checking if sync edge request is not processed...", requestId); + Consumer consumer = localSyncEdgeRequests.remove(requestId); + if (consumer != null) { + log.trace("[{}] timeout for processing sync edge request.", requestId); + consumer.accept(new FromEdgeSyncResponse(requestId, request.getTenantId(), request.getEdgeId(), false, "Edge is not connected")); + } + }, 20, TimeUnit.SECONDS); + } + + private void onEdgeHighPriorityEvent(EdgeHighPriorityMsg msg) { + TenantId tenantId = msg.getTenantId(); + EdgeEvent edgeEvent = msg.getEdgeEvent(); + EdgeId edgeId = edgeEvent.getEdgeId(); + EdgeGrpcSessionManager session = sessions.getByEdgeId(edgeId); + if (session != null && session.getState().isConnected()) { + log.trace("[{}] onEdgeEvent [{}]", tenantId, edgeId); + session.addEventToHighPriorityQueue(edgeEvent); + } + } + + private void onEdgeEventUpdate(TenantId tenantId, EdgeId edgeId) { + EdgeGrpcSessionManager session = sessions.getByEdgeId(edgeId); + if (session != null && session.getState().isConnected()) { + log.trace("[{}] onEdgeEventUpdate [{}]", tenantId, edgeId.getId()); + session.onEdgeEventUpdate(); + } + } + + private void startSyncProcess(TenantId tenantId, EdgeId edgeId, UUID requestId, String requestServiceId) { + EdgeGrpcSessionManager session = sessions.getByEdgeId(edgeId); + if (session != null) { + EdgeSessionState sessionState = session.getState(); + if (sessionState.isSyncInProgress()) { + clusterService.pushEdgeSyncResponseToCore(new FromEdgeSyncResponse(requestId, tenantId, edgeId, false, "Sync process is active at the moment"), requestServiceId); + } else { + boolean success = false; + if (sessionState.isConnected()) { + session.startSyncProcess(true); + success = true; + } + clusterService.pushEdgeSyncResponseToCore(new FromEdgeSyncResponse(requestId, tenantId, edgeId, success, ""), requestServiceId); + } + } + } + + private void processSyncResponse(FromEdgeSyncResponse response) { + log.trace("[{}] Received response from sync service: [{}]", response.getId(), response); + UUID requestId = response.getId(); + Consumer consumer = localSyncEdgeRequests.remove(requestId); + if (consumer != null) { + consumer.accept(response); + } else { + log.trace("[{}] Unknown or stale sync response received [{}]", requestId, response); + } + } + + private void pushRuleEngineMessage(TenantId tenantId, Edge edge, long ts, TbMsgType msgType) { + try { + EdgeId edgeId = edge.getId(); + ObjectNode edgeState = JacksonUtil.newObjectNode(); + boolean isConnected = TbMsgType.CONNECT_EVENT.equals(msgType); + if (isConnected) { + edgeState.put(ACTIVITY_STATE, true); + edgeState.put(LAST_CONNECT_TIME, ts); + } else { + edgeState.put(ACTIVITY_STATE, false); + edgeState.put(LAST_DISCONNECT_TIME, ts); + } + ctx.getRuleProcessor().process(EdgeConnectionTrigger.builder() + .tenantId(tenantId) + .customerId(edge.getCustomerId()) + .edgeId(edgeId) + .edgeName(edge.getName()) + .connected(isConnected).build()); + String data = JacksonUtil.toString(edgeState); + TbMsgMetaData md = new TbMsgMetaData(); + if (!persistToTelemetry) { + md.putValue(DataConstants.SCOPE, DataConstants.SERVER_SCOPE); + md.putValue("edgeName", edge.getName()); + md.putValue("edgeType", edge.getType()); + } + TbMsg tbMsg = TbMsg.newMsg() + .type(msgType) + .originator(edgeId) + .copyMetaData(md) + .dataType(TbMsgDataType.JSON) + .data(data) + .build(); + clusterService.pushMsgToRuleEngine(tenantId, edgeId, tbMsg, null); + } catch (Exception e) { + log.warn("[{}][{}] Failed to push {}", tenantId, edge.getId(), msgType, e); + } + } + + private void save(TenantId tenantId, EdgeId edgeId, String key, long value) { + log.debug("[{}][{}] Updating long edge telemetry [{}] [{}]", tenantId, edgeId, key, value); + if (persistToTelemetry) { + tsSubService.saveTimeseries(TimeseriesSaveRequest.builder() + .tenantId(tenantId) + .entityId(edgeId) + .entry(new LongDataEntry(key, value)) + .callback(new EdgeAttributeSaveCallback(tenantId, edgeId, key, value)) + .build()); + } else { + tsSubService.saveAttributes(AttributesSaveRequest.builder() + .tenantId(tenantId) + .entityId(edgeId) + .scope(AttributeScope.SERVER_SCOPE) + .entry(new LongDataEntry(key, value)) + .callback(new EdgeAttributeSaveCallback(tenantId, edgeId, key, value)) + .build()); + } + } + + private void save(TenantId tenantId, EdgeId edgeId, String key, boolean value) { + log.debug("[{}][{}] Updating boolean edge telemetry [{}] [{}]", tenantId, edgeId, key, value); + if (persistToTelemetry) { + tsSubService.saveTimeseries(TimeseriesSaveRequest.builder() + .tenantId(tenantId) + .entityId(edgeId) + .entry(new BooleanDataEntry(key, value)) + .callback(new EdgeAttributeSaveCallback(tenantId, edgeId, key, value)) + .build()); + } else { + tsSubService.saveAttributes(AttributesSaveRequest.builder() + .tenantId(tenantId) + .entityId(edgeId) + .scope(AttributeScope.SERVER_SCOPE) + .entry(new BooleanDataEntry(key, value)) + .callback(new EdgeAttributeSaveCallback(tenantId, edgeId, key, value)) + .build()); + } + } + + private void shutdownExecutorSafely(ExecutorService sendDownlinkExecutorService) { + if (sendDownlinkExecutorService != null && !sendDownlinkExecutorService.isShutdown()) { + sendDownlinkExecutorService.shutdown(); + } + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/BaseEdgeSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/BaseEdgeSession.java new file mode 100644 index 0000000000..6544128c4f --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/BaseEdgeSession.java @@ -0,0 +1,604 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc.session; + +import com.datastax.oss.driver.api.core.uuid.Uuids; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.SettableFuture; +import io.grpc.stub.StreamObserver; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.springframework.data.util.Pair; +import org.thingsboard.server.common.data.AttributeScope; +import org.thingsboard.server.common.data.DataConstants; +import org.thingsboard.server.common.data.EdgeUtils; +import org.thingsboard.server.common.data.StringUtils; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.kv.AttributeKvEntry; +import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; +import org.thingsboard.server.common.data.kv.StringDataEntry; +import org.thingsboard.server.common.data.limit.LimitedApi; +import org.thingsboard.server.common.data.notification.rule.trigger.EdgeCommunicationFailureTrigger; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.common.msg.edge.EdgeEventUpdateMsg; +import org.thingsboard.server.dao.edge.stats.EdgeStatsKey; +import org.thingsboard.server.gen.edge.v1.ConnectRequestMsg; +import org.thingsboard.server.gen.edge.v1.ConnectResponseCode; +import org.thingsboard.server.gen.edge.v1.ConnectResponseMsg; +import org.thingsboard.server.gen.edge.v1.DownlinkMsg; +import org.thingsboard.server.gen.edge.v1.DownlinkResponseMsg; +import org.thingsboard.server.gen.edge.v1.EdgeConfiguration; +import org.thingsboard.server.gen.edge.v1.RequestMsg; +import org.thingsboard.server.gen.edge.v1.RequestMsgType; +import org.thingsboard.server.gen.edge.v1.ResponseMsg; +import org.thingsboard.server.gen.edge.v1.SyncCompletedMsg; +import org.thingsboard.server.gen.edge.v1.UplinkMsg; +import org.thingsboard.server.gen.edge.v1.UplinkResponseMsg; +import org.thingsboard.server.service.edge.EdgeContextComponent; +import org.thingsboard.server.service.edge.EdgeMsgConstructorUtils; +import org.thingsboard.server.service.edge.rpc.DownlinkMessageMapper; +import org.thingsboard.server.service.edge.rpc.EdgeSessionState; +import org.thingsboard.server.service.edge.rpc.EdgeSyncCursor; +import org.thingsboard.server.service.edge.rpc.EdgeUplinkMessageDispatcher; +import org.thingsboard.server.service.edge.rpc.fetch.EdgeEventFetcher; +import org.thingsboard.server.service.edge.rpc.fetch.GeneralEdgeEventFetcher; +import org.thingsboard.server.service.edge.rpc.session.manager.EdgeGrpcSessionManager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.BiConsumer; + +@Slf4j +@RequiredArgsConstructor +public class BaseEdgeSession implements EdgeSession { + + private static final int MAX_DOWNLINK_ATTEMPTS = 3; + private static final String RATE_LIMIT_REACHED = "Rate limit reached"; + + private final EdgeGrpcSessionManager parentManagerRef; + private final EdgeContextComponent ctx; + private final StreamObserver outputStream; + private final DownlinkMessageMapper downlinkMessageMapper; + private final EdgeUplinkMessageDispatcher uplinkMessageDispatcher; + private final BiConsumer sessionOpenListener; + private final BiConsumer sessionCloseListener; + private final ScheduledExecutorService sendDownlinkExecutorService; + private final int maxInboundMessageSize; + private final int maxHighPriorityQueueSizePerSession; + + private final EdgeSessionState state = new EdgeSessionState(); + private final Lock downlinkMsgLock = new ReentrantLock(); + private final ConcurrentLinkedQueue highPriorityQueue = new ConcurrentLinkedQueue<>(); + + private int clientMaxInboundMessageSize; + + @Override + public EdgeSessionState getState() { + return state; + } + + @Override + public StreamObserver initInputStream() { + return new StreamObserver<>() { + @Override + public void onNext(RequestMsg requestMsg) { + if (!state.isConnected() && requestMsg.getMsgType().equals(RequestMsgType.CONNECT_RPC_MESSAGE)) { + ConnectResponseMsg responseMsg = processConnect(requestMsg.getConnectRequestMsg()); + outputStream.onNext(ResponseMsg.newBuilder() + .setConnectResponseMsg(responseMsg) + .build()); + if (ConnectResponseCode.ACCEPTED != responseMsg.getResponseCode()) { + outputStream.onError(new RuntimeException(responseMsg.getErrorMsg())); + } else { + if (requestMsg.getConnectRequestMsg().hasMaxInboundMessageSize()) { + log.debug("[{}][{}] Client max inbound message size: {}", + getTenantId(), getSessionId(), requestMsg.getConnectRequestMsg().getMaxInboundMessageSize()); + clientMaxInboundMessageSize = requestMsg.getConnectRequestMsg().getMaxInboundMessageSize(); + } + state.setConnected(true); + } + } + if (state.isConnected()) { + if (requestMsg.getMsgType().equals(RequestMsgType.SYNC_REQUEST_RPC_MESSAGE)) { + if (requestMsg.hasSyncRequestMsg()) { + boolean fullSync = false; + if (requestMsg.getSyncRequestMsg().hasFullSync()) { + fullSync = requestMsg.getSyncRequestMsg().getFullSync(); + } + startSyncProcess(fullSync); + } else { + state.finishSync(); + } + } + if (requestMsg.getMsgType().equals(RequestMsgType.UPLINK_RPC_MESSAGE)) { + if (requestMsg.hasUplinkMsg()) { + onUplinkMsg(requestMsg.getUplinkMsg()); + } + if (requestMsg.hasDownlinkResponseMsg()) { + onDownlinkResponse(requestMsg.getDownlinkResponseMsg()); + } + } + } + } + + @Override + public void onError(Throwable t) { + log.trace("[{}][{}] Stream was terminated due to error:", getTenantId(), getSessionId(), t); + closeSession(); + } + + @Override + public void onCompleted() { + log.info("[{}][{}] Stream was closed and completed successfully!", getTenantId(), getSessionId()); + closeSession(); + } + + private void closeSession() { + state.setConnected(false); + if (state.getEdge() != null) { + try { + sessionCloseListener.accept(state.getEdge(), getSessionId()); + } catch (Exception ignored) { + } + } + try { + outputStream.onCompleted(); + } catch (Exception ignored) { + } + } + }; + } + + @Override + public void startSyncProcess(boolean fullSync) { + if (state.tryStartSync()) { + log.info("[{}][{}][{}] Staring edge sync process", getTenantId(), getEdgeId(), getSessionId()); + interruptGeneralProcessingOnSync(); + doSync(new EdgeSyncCursor(ctx, state.getEdge(), fullSync)); + } else { + log.info("[{}][{}][{}] Sync is already started, skipping starting it now", getTenantId(), getEdgeId(), getSessionId()); + } + } + + @Override + public void sendDownlinkMsg(ResponseMsg responseMsg) { + if (state.isConnected()) { + String responseMsgStr = StringUtils.truncate(responseMsg.toString(), 10000); + log.trace("[{}][{}] Sending downlink msg [{}]", getTenantId(), getEdgeId(), responseMsgStr); + downlinkMsgLock.lock(); + String downlinkMsgStr = responseMsg.hasDownlinkMsg() ? String.valueOf(responseMsg.getDownlinkMsg().getDownlinkMsgId()) : responseMsgStr; + try { + outputStream.onNext(responseMsg); + } catch (Exception e) { + log.trace("[{}][{}] Failed to send downlink message [{}]", getTenantId(), getEdgeId(), downlinkMsgStr, e); + state.setConnected(false); + sessionCloseListener.accept(state.getEdge(), getSessionId()); + } finally { + downlinkMsgLock.unlock(); + } + log.trace("[{}][{}] downlink msg successfully sent [{}]", getTenantId(), getEdgeId(), downlinkMsgStr); + } + } + + @Override + public void addHighPriorityEvent(EdgeEvent edgeEvent) { + while (highPriorityQueue.size() > maxHighPriorityQueueSizePerSession) { + EdgeEvent oldestHighPriority = highPriorityQueue.poll(); + if (oldestHighPriority != null) { + log.warn("[{}][{}][{}] High priority queue is full. Removing oldest high priority event from queue {}", + state.getTenantId(), state.getEdgeId(), getSessionId(), oldestHighPriority); + } + } + highPriorityQueue.add(edgeEvent); + ctx.getStatsCounterService().ifPresent(statsCounterService -> + statsCounterService.recordEvent(EdgeStatsKey.DOWNLINK_MSGS_ADDED, state.getEdge().getTenantId(), edgeEvent.getEdgeId(), 1)); + } + + @Override + public void processHighPriorityEvents() { + try { + if (state.isConnected() && !state.isSyncInProgress()) { + if (highPriorityQueue.isEmpty()) { + return; + } + List highPriorityEvents = new ArrayList<>(); + EdgeEvent event; + while ((event = highPriorityQueue.poll()) != null) { + highPriorityEvents.add(event); + } + log.trace("[{}][{}] Sending high priority events {}", getTenantId(), getEdgeId(), highPriorityEvents.size()); + List downlinkMsgsPack = downlinkMessageMapper.convertToDownlinkMsgsPack(state, highPriorityEvents); + sendDownlinkMsgsPack(downlinkMsgsPack).get(); + } + } catch (Exception e) { + log.error("[{}] Failed to process high priority events", getEdgeId(), e); + } + } + + @Override + public boolean hasHighPriorityEvents() { + return !highPriorityQueue.isEmpty(); + } + + @Override + public ListenableFuture> fetchAndSendEdgeEvents(EdgeEventFetcher fetcher) { + SettableFuture> result = SettableFuture.create(); + PageLink pageLink = fetcher.getPageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount()); + fetchAndSendEdgeEvents(fetcher, pageLink, result); + return result; + } + + @Override + public ListenableFuture sendDownlinkMsgsPack(List downlinkMsgsPack) { + interruptPreviousSendDownlinkMsgsTask(); + + state.setSendDownlinkMsgsFuture(SettableFuture.create()); + state.getPendingMsgsMap().clear(); + + downlinkMsgsPack.forEach(msg -> state.getPendingMsgsMap().put(msg.getDownlinkMsgId(), msg)); + scheduleDownlinkMsgsPackSend(1); + + return state.getSendDownlinkMsgsFuture(); + } + + @Override + public void close() { + log.debug("[{}][{}] Closing session", getTenantId(), getSessionId()); + state.setConnected(false); + try { + outputStream.onCompleted(); + } catch (Exception e) { + log.debug("[{}][{}] Failed to close output stream: {}", getTenantId(), getSessionId(), e.getMessage()); + } + } + + private void onUplinkMsg(UplinkMsg uplinkMsg) { + if (isRateLimitViolated(uplinkMsg)) { + return; + } + Futures.addCallback(uplinkMessageDispatcher.processUplinkMsg(state, uplinkMsg), new FutureCallback<>() { + @Override + public void onSuccess(@Nullable List result) { + sendResponseMessage(uplinkMsg.getUplinkMsgId(), true, null); + } + + @Override + public void onFailure(Throwable t) { + String errorMsg = EdgeUtils.createErrorMsgFromRootCauseAndStackTrace(t); + sendResponseMessage(uplinkMsg.getUplinkMsgId(), false, errorMsg); + } + }, ctx.getGrpcCallbackExecutorService()); + } + + private boolean isRateLimitViolated(UplinkMsg uplinkMsg) { + if (!ctx.getRateLimitService().checkRateLimit(LimitedApi.EDGE_UPLINK_MESSAGES, getTenantId()) || + !ctx.getRateLimitService().checkRateLimit(LimitedApi.EDGE_UPLINK_MESSAGES_PER_EDGE, getTenantId(), getEdgeId())) { + String errorMsg = String.format("Failed to process uplink message. %s", RATE_LIMIT_REACHED); + sendResponseMessage(uplinkMsg.getUplinkMsgId(), false, errorMsg); + return true; + } + return false; + } + + private void sendResponseMessage(int uplinkMsgId, boolean success, String errorMsg) { + UplinkResponseMsg.Builder responseBuilder = UplinkResponseMsg.newBuilder() + .setUplinkMsgId(uplinkMsgId) + .setSuccess(success); + if (errorMsg != null) { + responseBuilder.setErrorMsg(errorMsg); + } + sendDownlinkMsg(ResponseMsg.newBuilder() + .setUplinkResponseMsg(responseBuilder.build()) + .build()); + } + + private void onDownlinkResponse(DownlinkResponseMsg msg) { + try { + if (msg.getSuccess()) { + state.getPendingMsgsMap().remove(msg.getDownlinkMsgId()); + ctx.getStatsCounterService().ifPresent(statsCounterService -> statsCounterService.recordEvent(EdgeStatsKey.DOWNLINK_MSGS_PUSHED, getTenantId(), getEdgeId(), 1)); + log.debug("[{}][{}][{}] Msg has been processed successfully! Msg Id: [{}], Msg: {}", getTenantId(), getEdgeId(), getSessionId(), msg.getDownlinkMsgId(), msg); + } else { + log.debug("[{}][{}][{}] Msg processing failed! Msg Id: [{}], Error msg: {}", getTenantId(), getEdgeId(), getSessionId(), msg.getDownlinkMsgId(), msg.getErrorMsg()); + DownlinkMsg downlinkMsg = state.getPendingMsgsMap().get(msg.getDownlinkMsgId()); + // if NOT timeseries or attributes failures - ack failed downlink + if (downlinkMsg.getEntityDataCount() == 0) { + state.getPendingMsgsMap().remove(msg.getDownlinkMsgId()); + } + } + if (state.getPendingMsgsMap().isEmpty()) { + log.debug("[{}][{}][{}] Pending msgs map is empty. Stopping current iteration", getTenantId(), getEdgeId(), getSessionId()); + stopCurrentSendDownlinkMsgsTask(false); + } + } catch (Exception e) { + log.error("[{}][{}] Can't process downlink response message [{}]", getTenantId(), getEdgeId(), msg, e); + } + } + + private void interruptGeneralProcessingOnSync() { + log.debug("[{}][{}][{}] Sync process started. General processing interrupted!", getTenantId(), getEdgeId(), getSessionId()); + stopCurrentSendDownlinkMsgsTask(true); + } + + private void doSync(EdgeSyncCursor cursor) { + if (cursor.hasNext()) { + EdgeEventFetcher next = cursor.getNext(); + log.debug("[{}][{}] starting sync process, cursor current idx = {}, class = {}", + getTenantId(), getEdgeId(), cursor.getCurrentIdx(), next.getClass().getSimpleName()); + ListenableFuture> future = fetchAndSendEdgeEvents(next); + Futures.addCallback(future, new FutureCallback<>() { + @Override + public void onSuccess(@Nullable Pair result) { + doSync(cursor); + } + + @Override + public void onFailure(Throwable t) { + log.error("[{}][{}] Exception during sync process", getTenantId(), getEdgeId(), t); + } + }, ctx.getGrpcCallbackExecutorService()); + } else { + log.info("[{}][{}] sync process completed", getTenantId(), getEdgeId()); + DownlinkMsg syncCompleteDownlinkMsg = DownlinkMsg.newBuilder() + .setDownlinkMsgId(EdgeUtils.nextPositiveInt()) + .setSyncCompletedMsg(SyncCompletedMsg.newBuilder().build()) + .build(); + Futures.addCallback(sendDownlinkMsgsPack(Collections.singletonList(syncCompleteDownlinkMsg)), new FutureCallback<>() { + @Override + public void onSuccess(Boolean isInterrupted) { + markSyncCompletedSendEdgeEventUpdate(); + } + + @Override + public void onFailure(Throwable t) { + log.error("[{}][{}] Exception during sending sync complete", getTenantId(), getEdgeId(), t); + markSyncCompletedSendEdgeEventUpdate(); + } + }, ctx.getGrpcCallbackExecutorService()); + } + } + + private void markSyncCompletedSendEdgeEventUpdate() { + state.finishSync(); + ctx.getClusterService().onEdgeEventUpdate(new EdgeEventUpdateMsg(getTenantId(), getEdgeId())); + } + + private void fetchAndSendEdgeEvents(EdgeEventFetcher fetcher, PageLink pageLink, SettableFuture> result) { + Edge edge = state.getEdge(); + TenantId tenantId = getTenantId(); + try { + log.trace("[{}] Start processing edge events, fetcher = {}, pageLink = {}", edge.getId(), fetcher.getClass().getSimpleName(), pageLink); + processHighPriorityEvents(); + PageData pageData = fetcher.fetchEdgeEvents(edge.getTenantId(), edge, pageLink); + if (state.isConnected() && !pageData.getData().isEmpty()) { + if (fetcher instanceof GeneralEdgeEventFetcher) { + long queueSize = pageData.getTotalElements() - ((long) pageLink.getPageSize() * pageLink.getPage()); + ctx.getStatsCounterService().ifPresent(statsCounterService -> statsCounterService.setDownlinkMsgsLag(edge.getTenantId(), edge.getId(), queueSize)); + } + log.trace("[{}][{}][{}] event(s) are going to be processed.", tenantId, edge.getId(), pageData.getData().size()); + List downlinkMsgsPack = downlinkMessageMapper.convertToDownlinkMsgsPack(state, pageData.getData()); + Futures.addCallback(sendDownlinkMsgsPack(downlinkMsgsPack), new FutureCallback<>() { + @Override + public void onSuccess(@Nullable Boolean isInterrupted) { + if (Boolean.TRUE.equals(isInterrupted)) { + log.debug("[{}][{}][{}] Send downlink messages task was interrupted", tenantId, edge.getId(), getSessionId()); + result.set(null); + } else { + if (state.isConnected() && pageData.hasNext()) { + fetchAndSendEdgeEvents(fetcher, pageLink.nextPageLink(), result); + } else { + EdgeEvent latestEdgeEvent = pageData.getData().get(pageData.getData().size() - 1); + UUID idOffset = latestEdgeEvent.getUuidId(); + if (idOffset != null) { + Long newStartTs = Uuids.unixTimestamp(idOffset); + long newStartSeqId = latestEdgeEvent.getSeqId(); + result.set(Pair.of(newStartTs, newStartSeqId)); + } else { + result.set(null); + } + } + } + } + + @Override + public void onFailure(Throwable t) { + log.error("[{}] Failed to send downlink msgs pack", edge.getId(), t); + result.setException(t); + } + }, ctx.getGrpcCallbackExecutorService()); + } else { + log.trace("[{}] no event(s) found. Stop processing edge events, fetcher = {}, pageLink = {}", edge.getId(), fetcher.getClass().getSimpleName(), pageLink); + result.set(null); + } + } catch (Exception e) { + log.error("[{}] Failed to fetch edge events", edge.getId(), e); + result.setException(e); + } + } + + private void scheduleDownlinkMsgsPackSend(int attempt) { + Runnable sendDownlinkMsgsTask = () -> { + try { + if (!state.isConnected()) { + stopCurrentSendDownlinkMsgsTask(true); + return; + } + if (!state.getPendingMsgsMap().values().isEmpty()) { + Edge edge = state.getEdge(); + List copy = new ArrayList<>(state.getPendingMsgsMap().values()); + if (attempt > 1) { + String error = "Failed to deliver the batch"; + String failureMsg = String.format("{%s} (size: {%s})", error, copy.size()); + if (attempt == 2) { + // Send a failure notification only on the second attempt. + // This ensures that failure alerts are sent just once to avoid redundant notifications. + ctx.getRuleProcessor().process(EdgeCommunicationFailureTrigger.builder().tenantId(getTenantId()) + .edgeId(getEdgeId()).customerId(edge.getCustomerId()).edgeName(edge.getName()).failureMsg(failureMsg).error(error).build()); + } + ctx.getStatsCounterService().ifPresent(statsCounterService -> + statsCounterService.recordEvent(EdgeStatsKey.DOWNLINK_MSGS_TMP_FAILED, edge.getTenantId(), getEdgeId(), 1)); + log.warn("[{}][{}] {} on attempt {}", getTenantId(), getEdgeId(), failureMsg, attempt); + log.debug("[{}][{}] entities in failed batch: {}", getTenantId(), getEdgeId(), copy); + } + log.trace("[{}][{}][{}] downlink msg(s) are going to be send.", getTenantId(), getEdgeId(), copy.size()); + for (DownlinkMsg downlinkMsg : copy) { + if (clientMaxInboundMessageSize != 0 && downlinkMsg.getSerializedSize() > clientMaxInboundMessageSize) { + String error = String.format("Client max inbound message size %s is exceeded. Please increase value of CLOUD_RPC_MAX_INBOUND_MESSAGE_SIZE " + + "env variable on the edge and restart it.", clientMaxInboundMessageSize); + String message = String.format("Downlink msg size %s exceeds client max inbound message size %s. " + + "Please increase value of CLOUD_RPC_MAX_INBOUND_MESSAGE_SIZE env variable on the edge and restart it.", downlinkMsg.getSerializedSize(), clientMaxInboundMessageSize); + log.error("[{}][{}][{}] {} Message {}", getTenantId(), getEdgeId(), getSessionId(), message, downlinkMsg); + ctx.getRuleProcessor().process(EdgeCommunicationFailureTrigger.builder().tenantId(getTenantId()) + .edgeId(getEdgeId()).customerId(edge.getCustomerId()).edgeName(edge.getName()).failureMsg(message).error(error).build()); + ctx.getStatsCounterService().ifPresent(statsCounterService -> + statsCounterService.recordEvent(EdgeStatsKey.DOWNLINK_MSGS_PERMANENTLY_FAILED, edge.getTenantId(), getEdgeId(), 1)); + state.getPendingMsgsMap().remove(downlinkMsg.getDownlinkMsgId()); + } else { + sendDownlinkMsg(ResponseMsg.newBuilder() + .setDownlinkMsg(downlinkMsg) + .build()); + } + } + if (attempt < MAX_DOWNLINK_ATTEMPTS) { + scheduleDownlinkMsgsPackSend(attempt + 1); + } else { + String failureMsg = String.format("Failed to deliver messages: %s", copy); + log.warn("[{}][{}] Failed to deliver the batch after {} attempts. Next messages are going to be discarded {}", + getTenantId(), getEdgeId(), MAX_DOWNLINK_ATTEMPTS, copy); + ctx.getRuleProcessor().process(EdgeCommunicationFailureTrigger.builder().tenantId(getTenantId()).edgeId(getEdgeId()) + .customerId(edge.getCustomerId()).edgeName(edge.getName()).failureMsg(failureMsg) + .error("Failed to deliver messages after " + MAX_DOWNLINK_ATTEMPTS + " attempts").build()); + ctx.getStatsCounterService().ifPresent(statsCounterService -> statsCounterService.recordEvent(EdgeStatsKey.DOWNLINK_MSGS_PERMANENTLY_FAILED, edge.getTenantId(), getEdgeId(), copy.size())); + stopCurrentSendDownlinkMsgsTask(false); + } + } else { + stopCurrentSendDownlinkMsgsTask(false); + } + } catch (Exception e) { + log.warn("[{}][{}] Failed to send downlink msgs. Error msg {}", getTenantId(), getEdgeId(), e.getMessage(), e); + stopCurrentSendDownlinkMsgsTask(true); + } + }; + + if (attempt == 1) { + sendDownlinkExecutorService.submit(sendDownlinkMsgsTask); + } else { + state.setScheduledSendDownlinkTask( + sendDownlinkExecutorService.schedule( + sendDownlinkMsgsTask, + ctx.getEdgeEventStorageSettings().getSleepIntervalBetweenBatches(), + TimeUnit.MILLISECONDS) + ); + } + } + + private void interruptPreviousSendDownlinkMsgsTask() { + if (state.getSendDownlinkMsgsFuture() != null && !state.getSendDownlinkMsgsFuture().isDone() + || state.getScheduledSendDownlinkTask() != null && !state.getScheduledSendDownlinkTask().isCancelled()) { + log.debug("[{}][{}][{}] Previous send downlink future was not properly completed, stopping it now!", + getTenantId(), getEdgeId(), getSessionId()); + stopCurrentSendDownlinkMsgsTask(true); + } else { + log.trace("[{}][{}][{}] Previous send downlink future is not active", + getTenantId(), getEdgeId(), getSessionId()); + } + } + + private void stopCurrentSendDownlinkMsgsTask(Boolean isInterrupted) { + if (state.getSendDownlinkMsgsFuture() != null && !state.getSendDownlinkMsgsFuture().isDone()) { + state.getSendDownlinkMsgsFuture().set(isInterrupted); + } + if (state.getScheduledSendDownlinkTask() != null) { + state.getScheduledSendDownlinkTask().cancel(true); + } + } + + private ConnectResponseMsg processConnect(ConnectRequestMsg request) { + log.trace("[{}] processConnect [{}]", getSessionId(), request); + Optional optional = ctx.getEdgeService().findEdgeByRoutingKey(TenantId.SYS_TENANT_ID, request.getEdgeRoutingKey()); + if (optional.isPresent()) { + Edge edge = optional.get(); + TenantId tenantId = edge.getTenantId(); + state.setEdge(edge); + try { + if (edge.getSecret().equals(request.getEdgeSecret())) { + sessionOpenListener.accept(edge.getId(), parentManagerRef); + state.setEdgeVersion(request.getEdgeVersion()); + processSaveEdgeVersionAsAttribute(request.getEdgeVersion().name()); + return ConnectResponseMsg.newBuilder() + .setResponseCode(ConnectResponseCode.ACCEPTED) + .setErrorMsg("") + .setConfiguration(EdgeMsgConstructorUtils.constructEdgeConfiguration(edge)) + .setMaxInboundMessageSize(maxInboundMessageSize) + .build(); + } + String error = "Failed to validate the edge!"; + String failureMsg = String.format("%s Provided request secret: %s", error, request.getEdgeSecret()); + ctx.getRuleProcessor().process(EdgeCommunicationFailureTrigger.builder().tenantId(tenantId).edgeId(edge.getId()) + .customerId(edge.getCustomerId()).edgeName(edge.getName()).failureMsg(failureMsg).error(error).build()); + return ConnectResponseMsg.newBuilder() + .setResponseCode(ConnectResponseCode.BAD_CREDENTIALS) + .setErrorMsg(failureMsg) + .setConfiguration(EdgeConfiguration.getDefaultInstance()).build(); + } catch (Exception e) { + String failureMsg = "Failed to process edge connection!"; + ctx.getRuleProcessor().process(EdgeCommunicationFailureTrigger.builder().tenantId(tenantId).edgeId(edge.getId()) + .customerId(edge.getCustomerId()).edgeName(edge.getName()).failureMsg(failureMsg).error(e.getMessage()).build()); + log.error(failureMsg, e); + return ConnectResponseMsg.newBuilder() + .setResponseCode(ConnectResponseCode.SERVER_UNAVAILABLE) + .setErrorMsg(failureMsg) + .setConfiguration(EdgeConfiguration.getDefaultInstance()).build(); + } + } + return ConnectResponseMsg.newBuilder() + .setResponseCode(ConnectResponseCode.BAD_CREDENTIALS) + .setErrorMsg("Failed to find the edge! Routing key: " + request.getEdgeRoutingKey()) + .setConfiguration(EdgeConfiguration.getDefaultInstance()).build(); + } + + private void processSaveEdgeVersionAsAttribute(String edgeVersion) { + AttributeKvEntry attributeKvEntry = new BaseAttributeKvEntry(new StringDataEntry(DataConstants.EDGE_VERSION_ATTR_KEY, edgeVersion), System.currentTimeMillis()); + ctx.getAttributesService().save(getTenantId(), getEdgeId(), AttributeScope.SERVER_SCOPE, attributeKvEntry); + } + + private TenantId getTenantId() { + return state.getTenantId(); + } + + private EdgeId getEdgeId() { + return state.getEdgeId(); + } + + private UUID getSessionId() { + return state.getSessionId(); + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/DefaultZombieSessionCleanupService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/DefaultZombieSessionCleanupService.java new file mode 100644 index 0000000000..b9367551fe --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/DefaultZombieSessionCleanupService.java @@ -0,0 +1,122 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc.session; + +import jakarta.annotation.PreDestroy; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.thingsboard.common.util.ThingsBoardExecutors; +import org.thingsboard.server.service.edge.rpc.EdgeSessionState; +import org.thingsboard.server.service.edge.rpc.session.manager.EdgeGrpcSessionManager; +import org.thingsboard.server.service.edge.rpc.session.manager.KafkaBasedEdgeGrpcSessionManager; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; + +@Service +@Slf4j +public class DefaultZombieSessionCleanupService implements ZombieSessionCleanupService { + + @Autowired + private EdgeSessionsHolder edgeSessionsHolder; + + private final Queue zombieSessions; + private final ScheduledExecutorService zombieSessionsExecutorService; + + public DefaultZombieSessionCleanupService() { + this.zombieSessions = new ConcurrentLinkedQueue<>(); + this.zombieSessionsExecutorService = ThingsBoardExecutors.newSingleThreadScheduledExecutor("zombie-sessions"); + this.zombieSessionsExecutorService.scheduleAtFixedRate(this::cleanupZombieSessions, 30, 60, TimeUnit.SECONDS); + } + + @PreDestroy + public void destroy() { + if (zombieSessionsExecutorService != null && !zombieSessionsExecutorService.isShutdown()) { + zombieSessionsExecutorService.shutdown(); + } + } + + @Override + public void add(EdgeGrpcSessionManager session) { + zombieSessions.add(session); + } + + private void cleanupZombieSessions() { + try { + tryToDestroyZombieSessions(getZombieSessions(edgeSessionsHolder.getSessions().values()), + s -> edgeSessionsHolder.removeByEdgeId(s.getState().getEdge().getId())); + + tryToDestroyZombieSessions(getZombieSessions(edgeSessionsHolder.getSessionsById().values()), + s -> edgeSessionsHolder.removeBySessionId(s.getState().getSessionId())); + + zombieSessions.removeIf(zombie -> { + EdgeSessionState state = zombie.getState(); + if (zombie.destroy()) { + log.info("[{}][{}] Successfully cleaned up zombie session [{}] for edge [{}].", + state.getTenantId(), state.getEdgeId(), state.getSessionId(), state.getEdge().getName()); + return true; + } else { + log.warn("[{}][{}] Failed to remove zombie session [{}] for edge [{}].", + state.getTenantId(), state.getEdgeId(), state.getSessionId(), state.getEdge().getName()); + return false; + } + }); + } catch (Exception e) { + log.warn("Failed to cleanup kafka sessions", e); + } + } + + private List getZombieSessions(Collection sessions) { + List result = new ArrayList<>(); + for (EdgeGrpcSessionManager session : sessions) { + if (isKafkaSessionAndZombie(session)) { + result.add(session); + } + } + return result; + } + + private boolean isKafkaSessionAndZombie(EdgeGrpcSessionManager session) { + if (session instanceof KafkaBasedEdgeGrpcSessionManager kafkaSession) { + EdgeSessionState sessionState = kafkaSession.getState(); + log.debug("[{}] kafkaSession.isConnected() = {}, kafkaSession.getConsumer().getConsumer().isStopped() = {}", + sessionState.getEdgeId(), + sessionState.isConnected(), + kafkaSession.getConsumer() != null ? kafkaSession.getConsumer().getConsumer() != null ? kafkaSession.getConsumer().getConsumer().isStopped() : null : null); + return !sessionState.isConnected() && + kafkaSession.getConsumer() != null && + kafkaSession.getConsumer().getConsumer() != null && + !kafkaSession.getConsumer().getConsumer().isStopped(); + } + return false; + } + + private void tryToDestroyZombieSessions(List sessionsToRemove, Function removeFunc) { + for (EdgeGrpcSessionManager toRemove : sessionsToRemove) { + log.info("[{}] Destroying session for edge because edge is not connected", toRemove.getState().getEdge().getId()); + if (toRemove.destroy()) { + removeFunc.apply(toRemove); + } + } + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeAttributeSaveCallback.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeAttributeSaveCallback.java new file mode 100644 index 0000000000..c76891db98 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeAttributeSaveCallback.java @@ -0,0 +1,49 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc.session; + +import com.google.common.util.concurrent.FutureCallback; +import jakarta.annotation.Nullable; +import lombok.extern.slf4j.Slf4j; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.TenantId; + +@Slf4j +public class EdgeAttributeSaveCallback implements FutureCallback { + + private final TenantId tenantId; + private final EdgeId edgeId; + private final String key; + private final Object value; + + public EdgeAttributeSaveCallback(TenantId tenantId, EdgeId edgeId, String key, Object value) { + this.tenantId = tenantId; + this.edgeId = edgeId; + this.key = key; + this.value = value; + } + + @Override + public void onSuccess(@Nullable Void result) { + log.trace("[{}][{}] Successfully updated attribute [{}] with value [{}]", tenantId, edgeId, key, value); + } + + @Override + public void onFailure(Throwable t) { + log.warn("[{}][{}] Failed to update attribute [{}] with value [{}]", tenantId, edgeId, key, value, t); + } + +} \ No newline at end of file diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeGrpcSessionDelegate.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeGrpcSessionDelegate.java new file mode 100644 index 0000000000..4386b0ccd7 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeGrpcSessionDelegate.java @@ -0,0 +1,34 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc.session; + +import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.service.edge.rpc.session.manager.EdgeGrpcSessionManager; + +public abstract class EdgeGrpcSessionDelegate implements EdgeGrpcSessionManager { + + protected abstract EdgeSession getSession(); + + @Override + public void addEventToHighPriorityQueue(EdgeEvent edgeEvent) { + getSession().addHighPriorityEvent(edgeEvent); + } + + @Override + public void startSyncProcess(boolean fullSync) { + getSession().startSyncProcess(fullSync); + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeSession.java new file mode 100644 index 0000000000..6bda6baae7 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeSession.java @@ -0,0 +1,43 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc.session; + +import com.google.common.util.concurrent.ListenableFuture; +import io.grpc.stub.StreamObserver; +import org.springframework.data.util.Pair; +import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.gen.edge.v1.DownlinkMsg; +import org.thingsboard.server.gen.edge.v1.RequestMsg; +import org.thingsboard.server.gen.edge.v1.ResponseMsg; +import org.thingsboard.server.service.edge.rpc.EdgeSessionState; +import org.thingsboard.server.service.edge.rpc.fetch.EdgeEventFetcher; + +import java.io.Closeable; +import java.util.List; + +public interface EdgeSession extends Closeable { + + StreamObserver initInputStream(); + EdgeSessionState getState(); + void startSyncProcess(boolean fullSync); + void sendDownlinkMsg(ResponseMsg responseMsg); + void addHighPriorityEvent(EdgeEvent edgeEvent); + void processHighPriorityEvents(); + boolean hasHighPriorityEvents(); + ListenableFuture> fetchAndSendEdgeEvents(EdgeEventFetcher fetcher); + ListenableFuture sendDownlinkMsgsPack(List downlinkMsgsPack); + +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeSessionsHolder.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeSessionsHolder.java new file mode 100644 index 0000000000..5989fd01a1 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeSessionsHolder.java @@ -0,0 +1,74 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc.session; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.service.edge.rpc.EdgeSessionState; +import org.thingsboard.server.service.edge.rpc.session.manager.EdgeGrpcSessionManager; + +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.function.Consumer; + +@Data +@Slf4j +@Component +public class EdgeSessionsHolder { + + private final ConcurrentMap sessions = new ConcurrentHashMap<>(); + private final ConcurrentMap sessionsById = new ConcurrentHashMap<>(); + + public void forEach(Consumer consumer) { + sessions.values().forEach(consumer); + sessionsById.values().forEach(consumer); + } + + public void put(EdgeGrpcSessionManager session) { + UUID sessionId = session.getState().getSessionId(); + EdgeId edgeId = session.getState().getEdgeId(); + sessionsById.put(sessionId, session); + sessions.put(edgeId, session); + } + + public EdgeGrpcSessionManager getByEdgeId(EdgeId id) { + return sessions.get(id); + } + + public boolean hasByEdgeId(EdgeId id) { + return sessions.containsKey(id); + } + + public EdgeGrpcSessionManager removeByEdgeId(EdgeId id) { + return sessions.remove(id); + } + + public EdgeGrpcSessionManager removeBySessionId(UUID sessionId) { + return sessionsById.remove(sessionId); + } + + public void remove(EdgeGrpcSessionManager session) { + if (session == null) { + log.warn("Can't remove session from holder because it's null"); + } + EdgeSessionState sessionState = session.getState(); + removeByEdgeId(sessionState.getEdge().getId()); // todo: react to warnings + removeBySessionId(sessionState.getSessionId()); + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/ZombieSessionCleanupService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/ZombieSessionCleanupService.java new file mode 100644 index 0000000000..de6f1fb2d8 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/ZombieSessionCleanupService.java @@ -0,0 +1,23 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc.session; + +import org.thingsboard.server.service.edge.rpc.session.manager.EdgeGrpcSessionManager; + +public interface ZombieSessionCleanupService { + + void add(EdgeGrpcSessionManager session); +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/AbstractEdgeGrpcSessionManager.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/AbstractEdgeGrpcSessionManager.java new file mode 100644 index 0000000000..bda54d5449 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/AbstractEdgeGrpcSessionManager.java @@ -0,0 +1,128 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc.session.manager; + +import io.grpc.stub.StreamObserver; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Lazy; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.gen.edge.v1.EdgeUpdateMsg; +import org.thingsboard.server.gen.edge.v1.RequestMsg; +import org.thingsboard.server.gen.edge.v1.ResponseMsg; +import org.thingsboard.server.service.edge.EdgeContextComponent; +import org.thingsboard.server.service.edge.EdgeMsgConstructorUtils; +import org.thingsboard.server.service.edge.rpc.DownlinkMessageMapper; +import org.thingsboard.server.service.edge.rpc.EdgeSessionState; +import org.thingsboard.server.service.edge.rpc.EdgeUplinkMessageDispatcher; +import org.thingsboard.server.service.edge.rpc.session.BaseEdgeSession; +import org.thingsboard.server.service.edge.rpc.session.EdgeGrpcSessionDelegate; +import org.thingsboard.server.service.edge.rpc.session.EdgeSession; +import org.thingsboard.server.service.edge.rpc.session.ZombieSessionCleanupService; + +import java.util.UUID; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.BiConsumer; + +@Slf4j +public abstract class AbstractEdgeGrpcSessionManager extends EdgeGrpcSessionDelegate implements EdgeGrpcSessionManager { + + @Value("${edges.max_high_priority_queue_size_per_session:10000}") + protected int maxHighPriorityQueueSizePerSession; + + @Value("${edges.rpc.max_inbound_message_size:4194304}") + protected int maxInboundMessageSize; + + @Autowired + protected ZombieSessionCleanupService zombieSessionCleanupService; + + @Autowired + @Lazy + protected EdgeContextComponent ctx; + + @Autowired + protected DownlinkMessageMapper downlinkMessageMapper; + + @Autowired + protected EdgeUplinkMessageDispatcher uplinkMessageDispatcher; + + @Getter + protected EdgeSession session; + + private final Lock initLock = new ReentrantLock(); + + @Override + public StreamObserver initInputStream(StreamObserver outputStream, + BiConsumer sessionOpenListener, + BiConsumer sessionCloseListener, + ScheduledExecutorService sendDownlinkExecutorService) { + if (session != null) { + throw new IllegalStateException("Session already initialized"); + } + initLock.lock(); + try { + this.session = new BaseEdgeSession( + this, ctx, outputStream, downlinkMessageMapper, uplinkMessageDispatcher, + sessionOpenListener, sessionCloseListener, + sendDownlinkExecutorService, maxInboundMessageSize, maxHighPriorityQueueSizePerSession); + return session.initInputStream(); + } finally { + initLock.unlock(); + } + } + + @Override + public EdgeSessionState getState() { + if (session == null) { + return null; + } + return session.getState(); + } + + @Override + public void onConfigurationUpdate(Edge edge) { + EdgeUpdateMsg edgeConfig = EdgeUpdateMsg.newBuilder() + .setConfiguration(EdgeMsgConstructorUtils.constructEdgeConfiguration(edge)).build(); + + ResponseMsg edgeConfigMsg = ResponseMsg.newBuilder() + .setEdgeUpdateMsg(edgeConfig) + .build(); + + session.sendDownlinkMsg(edgeConfigMsg); + } + + @Override + public void destroyAndMarkAsZombieIfFailed() { + EdgeSessionState state = getState(); + final var finalSession = session; + + try (finalSession) { + if (!destroy()) { + log.warn("[{}][{}] Session destroy failed for edge [{}] with session id [{}]. Adding to zombie queue for later cleanup.", + state.getTenantId(), state.getEdgeId(), state.getEdge().getName(), state.getSessionId()); + zombieSessionCleanupService.add(this); + } + } catch (Exception e) { + log.warn("[{}][{}] Exception during session destroy for edge [{}] with session id [{}]", + state.getTenantId(), state.getEdgeId(), state.getEdge().getName(), state.getSessionId(), e); + } + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/EdgeGrpcSessionManager.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/EdgeGrpcSessionManager.java new file mode 100644 index 0000000000..30f9b7111f --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/EdgeGrpcSessionManager.java @@ -0,0 +1,47 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc.session.manager; + +import io.grpc.stub.StreamObserver; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.gen.edge.v1.RequestMsg; +import org.thingsboard.server.gen.edge.v1.ResponseMsg; +import org.thingsboard.server.service.edge.rpc.EdgeSessionState; + +import java.util.UUID; +import java.util.concurrent.ScheduledExecutorService; +import java.util.function.BiConsumer; + +public interface EdgeGrpcSessionManager { + + StreamObserver initInputStream(StreamObserver outputStream, + BiConsumer sessionOpenListener, + BiConsumer sessionCloseListener, + ScheduledExecutorService sendDownlinkExecutorService); + EdgeSessionState getState(); + void addEventToHighPriorityQueue(EdgeEvent edgeEvent); + void startSyncProcess(boolean fullSync); + void onEdgeConnect(); + void onEdgeEventUpdate(); + void onConfigurationUpdate(Edge edge); + void onEdgeDisconnect(); + void onEdgeRemoval(); + void destroyAndMarkAsZombieIfFailed(); + boolean destroy(); + +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/KafkaBasedEdgeGrpcSessionManager.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/KafkaBasedEdgeGrpcSessionManager.java new file mode 100644 index 0000000000..44b025b5d7 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/KafkaBasedEdgeGrpcSessionManager.java @@ -0,0 +1,282 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc.session.manager; + +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Service; +import org.thingsboard.common.util.ThingsBoardThreadFactory; +import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.util.ProtoUtils; +import org.thingsboard.server.gen.edge.v1.DownlinkMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeEventNotificationMsg; +import org.thingsboard.server.queue.TbQueueConsumer; +import org.thingsboard.server.queue.common.TbProtoQueueMsg; +import org.thingsboard.server.queue.common.consumer.QueueConsumerManager; +import org.thingsboard.server.queue.discovery.TopicService; +import org.thingsboard.server.queue.kafka.KafkaAdmin; +import org.thingsboard.server.queue.provider.TbCoreQueueFactory; +import org.thingsboard.server.queue.util.TbKafkaComponent; +import org.thingsboard.server.service.edge.rpc.DownlinkMessageMapper; +import org.thingsboard.server.service.edge.rpc.EdgeSessionState; +import org.thingsboard.server.service.edge.rpc.processor.PostgresGeneralEdgeEventsDispatcher; +import org.thingsboard.server.service.edge.rpc.session.EdgeSessionsHolder; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +@Service +@Slf4j +@TbKafkaComponent +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +@RequiredArgsConstructor +public class KafkaBasedEdgeGrpcSessionManager extends AbstractEdgeGrpcSessionManager { + + private static final int NO_INITIAL_DELAY_VALUE = 0; + + private final TbCoreQueueFactory tbCoreQueueFactory; + private final DownlinkMessageMapper downlinkMessageMapper; + private final TopicService topicService; + private final KafkaAdmin kafkaAdmin; + private final EdgeSessionsHolder sessions; + + private final AtomicReference> initMigrationAndProcessingFutureRef = new AtomicReference<>(); + private final Lock initLock = new ReentrantLock(); + private volatile boolean migrationProcessed; + private volatile boolean isHighPriorityProcessing; + @Getter + private QueueConsumerManager> consumer; + private PostgresGeneralEdgeEventsDispatcher psqlGeneralEdgeEventsDispatcher; + private ExecutorService consumerExecutor; + + @Override + public void onEdgeConnect() { + scheduleMigrationAndProcessing(); + } + + @Override + public void onEdgeEventUpdate() {} + + @Override + public void onEdgeDisconnect() {} + + @Override + public void onEdgeRemoval() { + EdgeSessionState state = getState(); + String topic = topicService + .buildEdgeEventNotificationsTopicPartitionInfo(state.getTenantId(), state.getEdgeId()) + .getTopic(); + kafkaAdmin.deleteTopic(topic); + kafkaAdmin.deleteConsumerGroup(topic); + } + + @Override + public boolean destroy() { + EdgeSessionState state = getState(); + try { + if (consumer != null) { + log.info("[{}][{}] Stopping edge event consumer...", state.getTenantId(), state.getEdgeId()); + consumer.stop(); + } + } catch (Exception e) { + log.warn("[{}][{}] Failed to stop edge event consumer", state.getTenantId(), state.getEdgeId(), e); + return false; + } + consumer = null; + try { + if (consumerExecutor != null && !consumerExecutor.isShutdown()) { + consumerExecutor.shutdown(); + awaitConsumerTermination(); + } + } catch (Exception e) { + log.warn("[{}][{}] Failed to shutdown edge event consumer executor", state.getTenantId(), state.getEdgeId(), e); + return false; + } + return true; + } + + private void scheduleMigrationAndProcessing() { + cancelScheduleEdgeEventsCheck(); + EdgeSessionState state = getSession().getState(); + TenantId tenantId = state.getTenantId(); + EdgeId edgeId = state.getEdgeId(); + + if (!sessions.hasByEdgeId(edgeId)) { + log.debug("[{}] Session was removed and edge event consumer must not be started [{}]", + tenantId, edgeId.getId()); + return; + } + ScheduledFuture initMigrationAndProcessingTask = ctx.getEdgeEventProcessingExecutorService().schedule(() -> { + log.info("[{}] Edge event processing task started for edge [{}]", tenantId, edgeId); + initLock.lock(); + try { + processRemainingPostgresEventsIfRequired(edgeId); + if (migrationProcessed) { + initAndLaunchConsumerWithCallback(tenantId, edgeId, state); + } + } catch (Exception e) { + log.warn("[{}] Failed to process edge events for edge [{}]!", tenantId, edgeId, e); + } + finally { + initLock.unlock(); + } + }, ctx.getEdgeEventStorageSettings().getNoRecordsSleepInterval(), TimeUnit.MILLISECONDS); + + initMigrationAndProcessingFutureRef.set(initMigrationAndProcessingTask); + } + + private void initAndLaunchConsumerWithCallback(TenantId tenantId, EdgeId edgeId, EdgeSessionState state) { + Futures.transform(initAndLaunchConsumer(tenantId, edgeId, state), success -> { + if (Boolean.FALSE.equals(success)) { + scheduleMigrationAndProcessing(); + } else { + launchProcessingOfHighPriorityEvents(tenantId, edgeId); + } + return null; + }, ctx.getGrpcCallbackExecutorService()); + } + + private void launchProcessingOfHighPriorityEvents(TenantId tenantId, EdgeId edgeId) { + ctx.getEdgeEventProcessingExecutorService().scheduleAtFixedRate(() -> { + try { + isHighPriorityProcessing = true; + session.processHighPriorityEvents(); + isHighPriorityProcessing = false; + } catch (Exception e) { + log.warn("[{}] Failed to process edge events for edge [{}]!", tenantId, edgeId, e); + } + }, NO_INITIAL_DELAY_VALUE, ctx.getEdgeEventStorageSettings().getNoRecordsSleepInterval(), TimeUnit.MILLISECONDS); + } + + private ListenableFuture initAndLaunchConsumer(TenantId tenantId, EdgeId edgeId, EdgeSessionState state) { + if (!state.isConnected() || state.isSyncInProgress() || isHighPriorityProcessing) { + log.warn("[{}][{}] Session is not ready (connected={}, syncInProgress={}, highPriority={}), skip starting edge event consumer", + tenantId, edgeId, state.isConnected(), state.isSyncInProgress(), isHighPriorityProcessing); + return Futures.immediateFuture(Boolean.FALSE); + } + if (consumer == null || (consumer.getConsumer() != null && consumer.getConsumer().isStopped())) { + try { + if (consumerExecutor != null && !consumerExecutor.isShutdown()) { + try { + consumerExecutor.shutdown(); + awaitConsumerTermination(); + } catch (Exception e) { + log.warn("[{}][{}] Failed to shutdown previous consumer executor", tenantId, edgeId, e); + } + } + this.consumerExecutor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("edge-event-consumer")); + this.consumer = QueueConsumerManager.>builder() + .name("TB Edge events [" + edgeId + "]") + .msgPackProcessor(this::processMsgs) + .pollInterval(ctx.getEdgeEventStorageSettings().getNoRecordsSleepInterval()) + .consumerCreator(() -> tbCoreQueueFactory.createEdgeEventMsgConsumer(tenantId, edgeId)) + .consumerExecutor(consumerExecutor) + .threadPrefix("edge-events-" + edgeId) + .build(); + consumer.subscribe(); + consumer.launch(); + } catch (Exception e) { + destroy(); + log.warn("[{}][{}] Failed to start edge event consumer", state.getSessionId(), edgeId, e); + } + } + return Futures.immediateFuture(Boolean.TRUE); + } + + private void processMsgs(List> msgs, TbQueueConsumer> consumer) { + EdgeSessionState state = getSession().getState(); + TenantId tenantId = state.getTenantId(); + EdgeId edgeId = state.getEdgeId(); + + log.trace("[{}][{}] starting processing edge events", tenantId, edgeId); + if (!state.isConnected() || state.isSyncInProgress() || isHighPriorityProcessing) { + log.debug("[{}][{}] edge not connected, edge sync is not completed or high priority processing in progress, " + + "connected = {}, sync in progress = {}, high priority in progress = {}. Skipping iteration", + tenantId, edgeId, state.isConnected(), state.isSyncInProgress(), isHighPriorityProcessing); + return; + } + List edgeEvents = new ArrayList<>(); + for (TbProtoQueueMsg msg : msgs) { + EdgeEvent edgeEvent = ProtoUtils.fromProto(msg.getValue().getEdgeEventMsg()); + edgeEvents.add(edgeEvent); + } + List downlinkMsgsPack = downlinkMessageMapper.convertToDownlinkMsgsPack(state, edgeEvents); + try { + boolean isInterrupted = session.sendDownlinkMsgsPack(downlinkMsgsPack).get(); + if (isInterrupted) { + log.debug("[{}][{}] Send downlink messages task was interrupted", tenantId, edgeId); + } else { + consumer.commit(); + } + } catch (Exception e) { + log.error("[{}][{}] Failed to process downlink messages", tenantId, edgeId, e); + } + } + + private void cancelScheduleEdgeEventsCheck() { + EdgeId edgeId = getState().getEdgeId(); + log.trace("[{}] cancelling edge migration & processing init for edge", edgeId); + + ScheduledFuture sf = initMigrationAndProcessingFutureRef.getAndSet(null); + if (sf != null && !sf.isCancelled() && !sf.isDone()) { + sf.cancel(true); + } + } + + private void processRemainingPostgresEventsIfRequired(EdgeId edgeId) throws Exception { + log.debug("Processing remaining postgres edge events for edge [{}]", edgeId); + + if (psqlGeneralEdgeEventsDispatcher == null) { + psqlGeneralEdgeEventsDispatcher = new PostgresGeneralEdgeEventsDispatcher(session, ctx); + } + if (migrationProcessed) { + return; + } + Boolean hasMorePostgresEvents = psqlGeneralEdgeEventsDispatcher.processNewEvents().get(); + if (Boolean.TRUE.equals(hasMorePostgresEvents)) { + log.info("Migration still in progress for edge [{}]", edgeId.getId()); + scheduleMigrationAndProcessing(); + } else if (Boolean.FALSE.equals(hasMorePostgresEvents)) { + log.info("Migration completed for edge [{}]", edgeId.getId()); + migrationProcessed = true; + } + } + + private void awaitConsumerTermination() { + EdgeSessionState state = getState(); + try { + if (!consumerExecutor.awaitTermination(10, java.util.concurrent.TimeUnit.SECONDS)) { + consumerExecutor.shutdownNow(); // todo: verify it is acceptable + } + } catch (InterruptedException ie) { + log.warn("[{}][{}] Interrupted while awaiting consumer executor termination", state.getTenantId(), state.getEdgeId()); + } + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/PostgresBasedEdgeGrpcSessionManager.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/PostgresBasedEdgeGrpcSessionManager.java new file mode 100644 index 0000000000..616a13ae97 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/PostgresBasedEdgeGrpcSessionManager.java @@ -0,0 +1,180 @@ +/** + * Copyright © 2016-2025 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.service.edge.rpc.session.manager; + +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.service.edge.rpc.processor.PostgresGeneralEdgeEventsDispatcher; +import org.thingsboard.server.service.edge.rpc.session.EdgeSessionsHolder; + +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +@Service +@Slf4j +@ConditionalOnExpression("'${queue.type:null}'!='kafka'") +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +@RequiredArgsConstructor +public class PostgresBasedEdgeGrpcSessionManager extends AbstractEdgeGrpcSessionManager { + + private final EdgeSessionsHolder edgeSessions; + + // todo: verify handled properly + private final Lock newEventsLock = new ReentrantLock(); + private final AtomicReference> edgeEventCheckFutureRef = new AtomicReference<>(); + private PostgresGeneralEdgeEventsDispatcher generalEdgeEventsDispatcher; + private volatile boolean hasNewEvents; + + @Override + public void addEventToHighPriorityQueue(EdgeEvent edgeEvent) { + super.addEventToHighPriorityQueue(edgeEvent); + markHasNewEvents(); + } + + @Override + public void onEdgeConnect() { + markHasNewEvents(); + scheduleEdgeEventsCheck(); + } + + @Override + public void onEdgeEventUpdate() { + markHasNewEvents(); + } + + @Override + public void onEdgeDisconnect() { + markHasNoEvents(); + cancelScheduleEdgeEventsCheck(); + } + + @Override + public void onEdgeRemoval() { + markHasNoEvents(); + cancelScheduleEdgeEventsCheck(); + } + + @Override + public boolean destroy() { + markHasNoEvents(); + cancelScheduleEdgeEventsCheck(); + return true; + } + + private void scheduleEdgeEventsCheck() { + cancelScheduleEdgeEventsCheck(); + EdgeId edgeId = getState().getEdgeId(); + TenantId tenantId = getState().getTenantId(); + + if (!edgeSessions.hasByEdgeId(edgeId)) { + log.debug("[{}] Session was removed and edge event check schedule must not be started [{}]", + tenantId, edgeId.getId()); + return; + } + ScheduledFuture edgeEventCheckTask = ctx.getEdgeEventProcessingExecutorService().schedule(() -> { + try { + newEventsLock.lock(); + try { + if (!hasNewEvents) { + scheduleEdgeEventsCheck(); + return; + } + log.trace("[{}][{}] set session new events flag to false", tenantId, edgeId.getId()); + hasNewEvents = false; + session.processHighPriorityEvents(); + processEdgeEventsWithCallback(tenantId, edgeId); + } finally { + newEventsLock.unlock(); + } + } catch (Exception e) { + log.warn("[{}] Failed to process edge events for edge [{}]!", tenantId, edgeId, e); + } + }, ctx.getEdgeEventStorageSettings().getNoRecordsSleepInterval(), TimeUnit.MILLISECONDS); + + edgeEventCheckFutureRef.set(edgeEventCheckTask); + log.trace("[{}] Check edge event scheduled for edge [{}]", tenantId, edgeId.getId()); + } + + private void processEdgeEventsWithCallback(TenantId tenantId, EdgeId edgeId) throws Exception { + Futures.addCallback(processEdgeEvents(), new FutureCallback<>() { + @Override + public void onSuccess(Boolean newEventsAdded) { + if (Boolean.TRUE.equals(newEventsAdded)) { + log.trace("[{}][{}] new events added. set session new events flag to true", tenantId, edgeId.getId()); + hasNewEvents = true; + } + scheduleEdgeEventsCheck(); + } + + @Override + public void onFailure(Throwable t) { + log.warn("[{}] Failed to process edge events for edge [{}]!", tenantId, edgeId, t); + scheduleEdgeEventsCheck(); + } + }, ctx.getGrpcCallbackExecutorService()); + } + + public ListenableFuture processEdgeEvents() throws Exception { + if (generalEdgeEventsDispatcher == null) { + generalEdgeEventsDispatcher = new PostgresGeneralEdgeEventsDispatcher(session, ctx); + } + return generalEdgeEventsDispatcher.processNewEvents(); + } + + private void cancelScheduleEdgeEventsCheck() { + EdgeId edgeId = getState().getEdgeId(); + log.trace("[{}] cancelling edge event check for edge", edgeId); + + ScheduledFuture sf = edgeEventCheckFutureRef.getAndSet(null); + if (sf != null && !sf.isCancelled() && !sf.isDone()) { + sf.cancel(true); + } + } + + private void markHasNoEvents() { + markHasEvents(false); + } + + private void markHasNewEvents() { + markHasEvents(true); + } + + private void markHasEvents(boolean newEventsPresent) { + newEventsLock.lock(); + try { + if (!hasNewEvents) { + log.trace("[{}] set session new events flag to {} [{}]", getState().getTenantId(), newEventsPresent, getState().getEdgeId()); + hasNewEvents = newEventsPresent; + } + } finally { + newEventsLock.unlock(); + } + } + +} diff --git a/application/src/test/resources/logback-test.xml b/application/src/test/resources/logback-test.xml index 13c93da411..b1c2a35d36 100644 --- a/application/src/test/resources/logback-test.xml +++ b/application/src/test/resources/logback-test.xml @@ -18,9 +18,6 @@ - - - From 6fb7da883ea5b50e9876c150f06713c0e0925621 Mon Sep 17 00:00:00 2001 From: Nikita Mazurenko Date: Tue, 16 Dec 2025 14:41:33 +0200 Subject: [PATCH 006/742] Undo renaming edge session and edge service --- .../org/thingsboard/server/service/edge/rpc/GrpcServer.java | 2 -- .../service/{EdgeRpcServiceImpl.java => EdgeGrpcService.java} | 2 +- .../session/{BaseEdgeSession.java => EdgeGrpcSession.java} | 2 +- .../rpc/session/manager/AbstractEdgeGrpcSessionManager.java | 4 ++-- 4 files changed, 4 insertions(+), 6 deletions(-) rename application/src/main/java/org/thingsboard/server/service/edge/rpc/service/{EdgeRpcServiceImpl.java => EdgeGrpcService.java} (99%) rename application/src/main/java/org/thingsboard/server/service/edge/rpc/session/{BaseEdgeSession.java => EdgeGrpcSession.java} (99%) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/GrpcServer.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/GrpcServer.java index 7da0aecc70..70fcdf1f5a 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/GrpcServer.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/GrpcServer.java @@ -23,10 +23,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.ResourceUtils; -import org.thingsboard.server.gen.edge.v1.EdgeRpcServiceGrpc; import org.thingsboard.server.gen.edge.v1.EdgeRpcServiceGrpc.EdgeRpcServiceImplBase; import org.thingsboard.server.queue.util.AfterStartUp; -import org.thingsboard.server.service.edge.rpc.service.EdgeRpcServiceImpl; import java.io.IOException; import java.io.InputStream; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/service/EdgeRpcServiceImpl.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/service/EdgeGrpcService.java similarity index 99% rename from application/src/main/java/org/thingsboard/server/service/edge/rpc/service/EdgeRpcServiceImpl.java rename to application/src/main/java/org/thingsboard/server/service/edge/rpc/service/EdgeGrpcService.java index 14054adbd3..fea5ef4c82 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/service/EdgeRpcServiceImpl.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/service/EdgeGrpcService.java @@ -77,7 +77,7 @@ import static org.thingsboard.server.service.state.DefaultDeviceStateService.LAS @Service @Slf4j @RequiredArgsConstructor -public class EdgeRpcServiceImpl extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase implements EdgeRpcService { +public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase implements EdgeRpcService { @Value("${edges.send_scheduler_pool_size}") private int sendSchedulerPoolSize; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/BaseEdgeSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeGrpcSession.java similarity index 99% rename from application/src/main/java/org/thingsboard/server/service/edge/rpc/session/BaseEdgeSession.java rename to application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeGrpcSession.java index 6544128c4f..8bb2d36393 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/BaseEdgeSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeGrpcSession.java @@ -78,7 +78,7 @@ import java.util.function.BiConsumer; @Slf4j @RequiredArgsConstructor -public class BaseEdgeSession implements EdgeSession { +public class EdgeGrpcSession implements EdgeSession { private static final int MAX_DOWNLINK_ATTEMPTS = 3; private static final String RATE_LIMIT_REACHED = "Rate limit reached"; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/AbstractEdgeGrpcSessionManager.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/AbstractEdgeGrpcSessionManager.java index bda54d5449..68d5152306 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/AbstractEdgeGrpcSessionManager.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/AbstractEdgeGrpcSessionManager.java @@ -31,7 +31,7 @@ import org.thingsboard.server.service.edge.EdgeMsgConstructorUtils; import org.thingsboard.server.service.edge.rpc.DownlinkMessageMapper; import org.thingsboard.server.service.edge.rpc.EdgeSessionState; import org.thingsboard.server.service.edge.rpc.EdgeUplinkMessageDispatcher; -import org.thingsboard.server.service.edge.rpc.session.BaseEdgeSession; +import org.thingsboard.server.service.edge.rpc.session.EdgeGrpcSession; import org.thingsboard.server.service.edge.rpc.session.EdgeGrpcSessionDelegate; import org.thingsboard.server.service.edge.rpc.session.EdgeSession; import org.thingsboard.server.service.edge.rpc.session.ZombieSessionCleanupService; @@ -79,7 +79,7 @@ public abstract class AbstractEdgeGrpcSessionManager extends EdgeGrpcSessionDele } initLock.lock(); try { - this.session = new BaseEdgeSession( + this.session = new EdgeGrpcSession( this, ctx, outputStream, downlinkMessageMapper, uplinkMessageDispatcher, sessionOpenListener, sessionCloseListener, sendDownlinkExecutorService, maxInboundMessageSize, maxHighPriorityQueueSizePerSession); From 2b16972e8360ac3bc3252a0d821cd0173a88a344 Mon Sep 17 00:00:00 2001 From: Nikita Mazurenko Date: Tue, 16 Dec 2025 15:03:47 +0200 Subject: [PATCH 007/742] Fix onConfigurationUpdate by updating edge in local state --- .../rpc/session/manager/AbstractEdgeGrpcSessionManager.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/AbstractEdgeGrpcSessionManager.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/AbstractEdgeGrpcSessionManager.java index 68d5152306..da502f2584 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/AbstractEdgeGrpcSessionManager.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/AbstractEdgeGrpcSessionManager.java @@ -99,6 +99,10 @@ public abstract class AbstractEdgeGrpcSessionManager extends EdgeGrpcSessionDele @Override public void onConfigurationUpdate(Edge edge) { + EdgeSessionState state = getState(); + if (state != null) { + state.setEdge(edge); + } EdgeUpdateMsg edgeConfig = EdgeUpdateMsg.newBuilder() .setConfiguration(EdgeMsgConstructorUtils.constructEdgeConfiguration(edge)).build(); From 89b461050f7ea207baf5cfd417e4d353e0a82346 Mon Sep 17 00:00:00 2001 From: Nikita Mazurenko Date: Tue, 16 Dec 2025 18:09:17 +0200 Subject: [PATCH 008/742] Refactor KafkaBasedEdgeGrpcSessionManager and introduce highPriorityProcessingFutureRef --- .../KafkaBasedEdgeGrpcSessionManager.java | 107 ++++++++++-------- 1 file changed, 61 insertions(+), 46 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/KafkaBasedEdgeGrpcSessionManager.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/KafkaBasedEdgeGrpcSessionManager.java index 44b025b5d7..95b9b821ec 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/KafkaBasedEdgeGrpcSessionManager.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/KafkaBasedEdgeGrpcSessionManager.java @@ -15,8 +15,6 @@ */ package org.thingsboard.server.service.edge.rpc.session.manager; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -46,6 +44,7 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; @@ -68,6 +67,7 @@ public class KafkaBasedEdgeGrpcSessionManager extends AbstractEdgeGrpcSessionMan private final EdgeSessionsHolder sessions; private final AtomicReference> initMigrationAndProcessingFutureRef = new AtomicReference<>(); + private final AtomicReference> highPriorityProcessingFutureRef = new AtomicReference<>(); private final Lock initLock = new ReentrantLock(); private volatile boolean migrationProcessed; private volatile boolean isHighPriorityProcessing; @@ -99,6 +99,7 @@ public class KafkaBasedEdgeGrpcSessionManager extends AbstractEdgeGrpcSessionMan @Override public boolean destroy() { + cancelHighPriorityProcessing(); EdgeSessionState state = getState(); try { if (consumer != null) { @@ -123,7 +124,7 @@ public class KafkaBasedEdgeGrpcSessionManager extends AbstractEdgeGrpcSessionMan } private void scheduleMigrationAndProcessing() { - cancelScheduleEdgeEventsCheck(); + cancelMigrationAndProcessingInit(); EdgeSessionState state = getSession().getState(); TenantId tenantId = state.getTenantId(); EdgeId edgeId = state.getEdgeId(); @@ -139,7 +140,7 @@ public class KafkaBasedEdgeGrpcSessionManager extends AbstractEdgeGrpcSessionMan try { processRemainingPostgresEventsIfRequired(edgeId); if (migrationProcessed) { - initAndLaunchConsumerWithCallback(tenantId, edgeId, state); + initAndLaunchConsumerOrRetry(tenantId, edgeId, state); } } catch (Exception e) { log.warn("[{}] Failed to process edge events for edge [{}]!", tenantId, edgeId, e); @@ -152,19 +153,17 @@ public class KafkaBasedEdgeGrpcSessionManager extends AbstractEdgeGrpcSessionMan initMigrationAndProcessingFutureRef.set(initMigrationAndProcessingTask); } - private void initAndLaunchConsumerWithCallback(TenantId tenantId, EdgeId edgeId, EdgeSessionState state) { - Futures.transform(initAndLaunchConsumer(tenantId, edgeId, state), success -> { - if (Boolean.FALSE.equals(success)) { - scheduleMigrationAndProcessing(); - } else { - launchProcessingOfHighPriorityEvents(tenantId, edgeId); - } - return null; - }, ctx.getGrpcCallbackExecutorService()); + private void initAndLaunchConsumerOrRetry(TenantId tenantId, EdgeId edgeId, EdgeSessionState state) { + if (initAndLaunchConsumer(tenantId, edgeId, state)) { + launchProcessingOfHighPriorityEvents(tenantId, edgeId); + } else { + scheduleMigrationAndProcessing(); + } } private void launchProcessingOfHighPriorityEvents(TenantId tenantId, EdgeId edgeId) { - ctx.getEdgeEventProcessingExecutorService().scheduleAtFixedRate(() -> { + cancelHighPriorityProcessing(); + ScheduledFuture highPriorityProcessingTask = ctx.getEdgeEventProcessingExecutorService().scheduleAtFixedRate(() -> { try { isHighPriorityProcessing = true; session.processHighPriorityEvents(); @@ -173,41 +172,50 @@ public class KafkaBasedEdgeGrpcSessionManager extends AbstractEdgeGrpcSessionMan log.warn("[{}] Failed to process edge events for edge [{}]!", tenantId, edgeId, e); } }, NO_INITIAL_DELAY_VALUE, ctx.getEdgeEventStorageSettings().getNoRecordsSleepInterval(), TimeUnit.MILLISECONDS); + highPriorityProcessingFutureRef.set(highPriorityProcessingTask); } - private ListenableFuture initAndLaunchConsumer(TenantId tenantId, EdgeId edgeId, EdgeSessionState state) { + private boolean initAndLaunchConsumer(TenantId tenantId, EdgeId edgeId, EdgeSessionState state) { if (!state.isConnected() || state.isSyncInProgress() || isHighPriorityProcessing) { log.warn("[{}][{}] Session is not ready (connected={}, syncInProgress={}, highPriority={}), skip starting edge event consumer", tenantId, edgeId, state.isConnected(), state.isSyncInProgress(), isHighPriorityProcessing); - return Futures.immediateFuture(Boolean.FALSE); + return false; } - if (consumer == null || (consumer.getConsumer() != null && consumer.getConsumer().isStopped())) { - try { - if (consumerExecutor != null && !consumerExecutor.isShutdown()) { - try { - consumerExecutor.shutdown(); - awaitConsumerTermination(); - } catch (Exception e) { - log.warn("[{}][{}] Failed to shutdown previous consumer executor", tenantId, edgeId, e); - } + if (isConsumerInitializationRequired()) { + initConsumerAndExecutor(tenantId, edgeId, state); + } + return true; + } + + private void initConsumerAndExecutor(TenantId tenantId, EdgeId edgeId, EdgeSessionState state) { + try { + if (consumerExecutor != null && !consumerExecutor.isShutdown()) { + try { + consumerExecutor.shutdown(); + awaitConsumerTermination(); + } catch (Exception e) { + log.warn("[{}][{}] Failed to shutdown previous consumer executor", tenantId, edgeId, e); } - this.consumerExecutor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("edge-event-consumer")); - this.consumer = QueueConsumerManager.>builder() - .name("TB Edge events [" + edgeId + "]") - .msgPackProcessor(this::processMsgs) - .pollInterval(ctx.getEdgeEventStorageSettings().getNoRecordsSleepInterval()) - .consumerCreator(() -> tbCoreQueueFactory.createEdgeEventMsgConsumer(tenantId, edgeId)) - .consumerExecutor(consumerExecutor) - .threadPrefix("edge-events-" + edgeId) - .build(); - consumer.subscribe(); - consumer.launch(); - } catch (Exception e) { - destroy(); - log.warn("[{}][{}] Failed to start edge event consumer", state.getSessionId(), edgeId, e); } + this.consumerExecutor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("edge-event-consumer")); + this.consumer = QueueConsumerManager.>builder() + .name("TB Edge events [" + edgeId + "]") + .msgPackProcessor(this::processMsgs) + .pollInterval(ctx.getEdgeEventStorageSettings().getNoRecordsSleepInterval()) + .consumerCreator(() -> tbCoreQueueFactory.createEdgeEventMsgConsumer(tenantId, edgeId)) + .consumerExecutor(consumerExecutor) + .threadPrefix("edge-events-" + edgeId) + .build(); + consumer.subscribe(); + consumer.launch(); + } catch (Exception e) { + destroy(); + log.warn("[{}][{}] Failed to start edge event consumer", state.getSessionId(), edgeId, e); } - return Futures.immediateFuture(Boolean.TRUE); + } + + private boolean isConsumerInitializationRequired() { + return consumer == null || (consumer.getConsumer() != null && consumer.getConsumer().isStopped()); } private void processMsgs(List> msgs, TbQueueConsumer> consumer) { @@ -240,13 +248,20 @@ public class KafkaBasedEdgeGrpcSessionManager extends AbstractEdgeGrpcSessionMan } } - private void cancelScheduleEdgeEventsCheck() { - EdgeId edgeId = getState().getEdgeId(); - log.trace("[{}] cancelling edge migration & processing init for edge", edgeId); + private void cancelMigrationAndProcessingInit() { + log.trace("[{}] cancelling edge migration & processing init for edge", getState().getEdgeId()); + cancelFuture(initMigrationAndProcessingFutureRef); + } + + private void cancelHighPriorityProcessing() { + log.trace("[{}] cancelling high priority processing task for edge", getState().getEdgeId()); + cancelFuture(highPriorityProcessingFutureRef); + } - ScheduledFuture sf = initMigrationAndProcessingFutureRef.getAndSet(null); - if (sf != null && !sf.isCancelled() && !sf.isDone()) { - sf.cancel(true); + private void cancelFuture(AtomicReference> futureReference) { + Future f = futureReference.getAndSet(null); + if (f != null && !f.isCancelled() && !f.isDone()) { + f.cancel(true); } } From 70ba4b03e4f1d8cb81a25c251027a560f15bea6b Mon Sep 17 00:00:00 2001 From: Nikita Mazurenko Date: Tue, 16 Dec 2025 19:01:12 +0200 Subject: [PATCH 009/742] Fix infinite loop on Kafka consumer commit failure --- .../session/manager/KafkaBasedEdgeGrpcSessionManager.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/KafkaBasedEdgeGrpcSessionManager.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/KafkaBasedEdgeGrpcSessionManager.java index 95b9b821ec..cf354b8877 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/KafkaBasedEdgeGrpcSessionManager.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/manager/KafkaBasedEdgeGrpcSessionManager.java @@ -236,16 +236,18 @@ public class KafkaBasedEdgeGrpcSessionManager extends AbstractEdgeGrpcSessionMan edgeEvents.add(edgeEvent); } List downlinkMsgsPack = downlinkMessageMapper.convertToDownlinkMsgsPack(state, edgeEvents); + boolean isInterrupted = true; try { - boolean isInterrupted = session.sendDownlinkMsgsPack(downlinkMsgsPack).get(); + isInterrupted = session.sendDownlinkMsgsPack(downlinkMsgsPack).get(); if (isInterrupted) { log.debug("[{}][{}] Send downlink messages task was interrupted", tenantId, edgeId); - } else { - consumer.commit(); } } catch (Exception e) { log.error("[{}][{}] Failed to process downlink messages", tenantId, edgeId, e); } + if (!isInterrupted) { + consumer.commit(); + } } private void cancelMigrationAndProcessingInit() { From 88299204be6ac0fdfbe1610fa7b15985f89f2694 Mon Sep 17 00:00:00 2001 From: Nikita Mazurenko Date: Wed, 17 Dec 2025 11:44:16 +0200 Subject: [PATCH 010/742] Fix statsCounterService in EdgeGrpcSession after merge --- .../server/service/edge/rpc/session/EdgeGrpcSession.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeGrpcSession.java index 8bb2d36393..64989b8c5a 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/session/EdgeGrpcSession.java @@ -401,7 +401,8 @@ public class EdgeGrpcSession implements EdgeSession { if (state.isConnected() && !pageData.getData().isEmpty()) { if (fetcher instanceof GeneralEdgeEventFetcher) { long queueSize = pageData.getTotalElements() - ((long) pageLink.getPageSize() * pageLink.getPage()); - ctx.getStatsCounterService().ifPresent(statsCounterService -> statsCounterService.setDownlinkMsgsLag(edge.getTenantId(), edge.getId(), queueSize)); + ctx.getStatsCounterService().ifPresent(statsCounterService -> + statsCounterService.recordEvent(EdgeStatsKey.DOWNLINK_MSGS_LAG, tenantId, edge.getId(), queueSize)); } log.trace("[{}][{}][{}] event(s) are going to be processed.", tenantId, edge.getId(), pageData.getData().size()); List downlinkMsgsPack = downlinkMessageMapper.convertToDownlinkMsgsPack(state, pageData.getData()); @@ -496,7 +497,8 @@ public class EdgeGrpcSession implements EdgeSession { ctx.getRuleProcessor().process(EdgeCommunicationFailureTrigger.builder().tenantId(getTenantId()).edgeId(getEdgeId()) .customerId(edge.getCustomerId()).edgeName(edge.getName()).failureMsg(failureMsg) .error("Failed to deliver messages after " + MAX_DOWNLINK_ATTEMPTS + " attempts").build()); - ctx.getStatsCounterService().ifPresent(statsCounterService -> statsCounterService.recordEvent(EdgeStatsKey.DOWNLINK_MSGS_PERMANENTLY_FAILED, edge.getTenantId(), getEdgeId(), copy.size())); + ctx.getStatsCounterService().ifPresent(statsCounterService -> + statsCounterService.recordEvent(EdgeStatsKey.DOWNLINK_MSGS_PERMANENTLY_FAILED, edge.getTenantId(), getEdgeId(), copy.size())); stopCurrentSendDownlinkMsgsTask(false); } } else { From d914dcbf474b9a9b951dd59775efb27881c2137e Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Mon, 29 Dec 2025 18:05:23 +0200 Subject: [PATCH 011/742] Add few missing API endpoints to REST client --- .../server/msa/AbstractContainerTest.java | 20 +- .../msa/connectivity/JavaRestClientTest.java | 176 +++++++++++++++--- rest-client/pom.xml | 4 + .../thingsboard/rest/client/RestClient.java | 63 ++++++- 4 files changed, 217 insertions(+), 46 deletions(-) diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractContainerTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractContainerTest.java index f352171382..fea1ca3eba 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractContainerTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractContainerTest.java @@ -44,7 +44,6 @@ import java.util.Map; import java.util.Random; import java.util.function.Consumer; - @Slf4j @Listeners(TestListener.class) public abstract class AbstractContainerTest { @@ -170,19 +169,14 @@ public abstract class AbstractContainerTest { DeviceProfileProvisionConfiguration provisionConfiguration; String testProvisionDeviceKey = TEST_PROVISION_DEVICE_KEY; deviceProfile.setProvisionType(provisionType); - switch(provisionType) { - case ALLOW_CREATE_NEW_DEVICES: - provisionConfiguration = new AllowCreateNewDevicesDeviceProfileProvisionConfiguration(TEST_PROVISION_DEVICE_SECRET); - break; - case CHECK_PRE_PROVISIONED_DEVICES: - provisionConfiguration = new CheckPreProvisionedDevicesDeviceProfileProvisionConfiguration(TEST_PROVISION_DEVICE_SECRET); - break; - default: - case DISABLED: + provisionConfiguration = switch (provisionType) { + case ALLOW_CREATE_NEW_DEVICES -> new AllowCreateNewDevicesDeviceProfileProvisionConfiguration(TEST_PROVISION_DEVICE_SECRET); + case CHECK_PRE_PROVISIONED_DEVICES -> new CheckPreProvisionedDevicesDeviceProfileProvisionConfiguration(TEST_PROVISION_DEVICE_SECRET); + default -> { testProvisionDeviceKey = null; - provisionConfiguration = new DisabledDeviceProfileProvisionConfiguration(null); - break; - } + yield new DisabledDeviceProfileProvisionConfiguration(null); + } + }; DeviceProfileData deviceProfileData = deviceProfile.getProfileData(); deviceProfileData.setProvisionConfiguration(provisionConfiguration); deviceProfile.setProfileData(deviceProfileData); diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/JavaRestClientTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/JavaRestClientTest.java index 5b98f4859b..dd3140c109 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/JavaRestClientTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/JavaRestClientTest.java @@ -16,6 +16,7 @@ package org.thingsboard.server.msa.connectivity; import com.google.gson.JsonObject; +import org.apache.commons.lang3.RandomStringUtils; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; @@ -26,7 +27,6 @@ import org.apache.hc.client5.http.ssl.NoopHostnameVerifier; import org.apache.hc.core5.ssl.SSLContexts; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; -import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; @@ -34,6 +34,10 @@ import org.testng.annotations.Test; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rest.client.RestClient; import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.DeviceProfile; +import org.thingsboard.server.common.data.DeviceProfileInfo; +import org.thingsboard.server.common.data.DeviceProfileType; +import org.thingsboard.server.common.data.DeviceTransportType; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; @@ -41,6 +45,11 @@ import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; import org.thingsboard.server.common.data.alarm.AlarmSeverity; +import org.thingsboard.server.common.data.asset.AssetProfile; +import org.thingsboard.server.common.data.asset.AssetProfileInfo; +import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; +import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTransportConfiguration; +import org.thingsboard.server.common.data.device.profile.DeviceProfileData; import org.thingsboard.server.common.data.domain.Domain; import org.thingsboard.server.common.data.domain.DomainInfo; import org.thingsboard.server.common.data.id.NotificationTargetId; @@ -94,6 +103,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -109,8 +119,10 @@ public class JavaRestClientTest extends AbstractContainerTest { public static final String DEFAULT_NOTIFICATION_SUBJECT = "Just a test"; public static final NotificationType DEFAULT_NOTIFICATION_TYPE = NotificationType.GENERAL; private RestClient restClient; - private Tenant tenant; - private User user; + private Tenant tenant1; + private Tenant tenant2; + private User tenantAdmin1; + private User tenantAdmin2; @BeforeClass public void beforeClass() throws Exception { @@ -140,31 +152,45 @@ public class JavaRestClientTest extends AbstractContainerTest { public void setUp() throws Exception { restClient.login("sysadmin@thingsboard.org", "sysadmin"); - // create tenant and tenant admin - tenant = new Tenant(); - tenant.setTitle("Java Rest Client Test Tenant " + RandomStringUtils.randomAlphabetic(5)); - tenant = restClient.saveTenant(tenant); + // create tenant 1 and tenant admin 1 + tenant1 = new Tenant(); + tenant1.setTitle("Java Rest Client Test Tenant " + RandomStringUtils.insecure().randomAlphabetic(5)); + tenant1 = restClient.saveTenant(tenant1); - String email = RandomStringUtils.randomAlphabetic(5) + "@gmail.com"; - user = restClient.saveUser(defaultTenantAdmin(tenant.getId(), email), false); - restClient.activateUser(user.getId(), "password123", false); - restClient.login(email, "password123"); + String email1 = RandomStringUtils.insecure().randomAlphabetic(5) + "@gmail.com"; + tenantAdmin1 = restClient.saveUser(defaultTenantAdmin(tenant1.getId(), email1), false); + restClient.activateUser(tenantAdmin1.getId(), "password123", false); + + // create tenant 2 and tenant admin 2 + tenant2 = new Tenant(); + tenant2.setTitle("Java Rest Client Test Tenant " + RandomStringUtils.insecure().randomAlphabetic(5)); + tenant2 = restClient.saveTenant(tenant2); + + String email2 = RandomStringUtils.insecure().randomAlphabetic(5) + "@gmail.com"; + tenantAdmin2 = restClient.saveUser(defaultTenantAdmin(tenant2.getId(), email2), false); + restClient.activateUser(tenantAdmin2.getId(), "password123", false); + + // tenant 1 tenant admin by default + restClient.login(tenantAdmin1.getEmail(), "password123"); } @AfterMethod public void tearDown() { restClient.login("sysadmin@thingsboard.org", "sysadmin"); - if (tenant != null) { - restClient.deleteTenant(tenant.getId()); + if (tenant1 != null) { + restClient.deleteTenant(tenant1.getId()); + } + if (tenant2 != null) { + restClient.deleteTenant(tenant2.getId()); } } @Test public void testGetAlarmsV2() { - Device device = restClient.saveDevice(defaultDevicePrototype(RandomStringUtils.randomAlphabetic(5))); + Device device = restClient.saveDevice(defaultDevicePrototype(RandomStringUtils.insecure().randomAlphabetic(5))); assertThat(device).isNotNull(); - String type = "High temp" + RandomStringUtils.randomAlphabetic(5); + String type = "High temp" + RandomStringUtils.insecure().randomAlphabetic(5); Alarm alarm = Alarm.builder() .originator(device.getId()) .severity(AlarmSeverity.CRITICAL) @@ -202,7 +228,7 @@ public class JavaRestClientTest extends AbstractContainerTest { @Test public void testTimeSeriesByReadTsKvQueries() { - Device device = restClient.saveDevice(defaultDevicePrototype(RandomStringUtils.randomAlphabetic(5))); + Device device = restClient.saveDevice(defaultDevicePrototype(RandomStringUtils.insecure().randomAlphabetic(5))); assertThat(device).isNotNull(); DeviceCredentials deviceCredentials = restClient.getDeviceCredentialsByDeviceId(device.getId()).get(); @@ -230,7 +256,7 @@ public class JavaRestClientTest extends AbstractContainerTest { @Test public void testFindNotifications() { - NotificationTarget notificationTarget = createNotificationTarget(user.getId()); + NotificationTarget notificationTarget = createNotificationTarget(tenantAdmin1.getId()); String notificationText1 = "Notification 1"; NotificationTemplate notificationTemplate = createNotificationTemplate(DEFAULT_NOTIFICATION_TYPE, DEFAULT_NOTIFICATION_SUBJECT, notificationText1, new NotificationDeliveryMethod[]{WEB}); NotificationRequest notificationRequest = submitNotificationRequest(notificationTarget.getId(), notificationTemplate.getId()); @@ -248,7 +274,7 @@ public class JavaRestClientTest extends AbstractContainerTest { NotificationRequestPreview requestPreview = restClient.getNotificationRequestPreview(notificationRequest, 10); assertThat(requestPreview.getTotalRecipientsCount()).isEqualTo(1); - assertThat(requestPreview.getRecipientsPreview()).isEqualTo(List.of(user.getEmail())); + assertThat(requestPreview.getRecipientsPreview()).isEqualTo(List.of(tenantAdmin1.getEmail())); PageData notifications = restClient.getNotifications(false, WEB, new PageLink(30)); assertThat(notifications.getTotalElements()).isEqualTo(2); @@ -316,7 +342,7 @@ public class JavaRestClientTest extends AbstractContainerTest { restClient.login("sysadmin@thingsboard.org", "sysadmin"); Domain domain = new Domain(); - String prefix = RandomStringUtils.randomAlphabetic(5).toLowerCase(); + String prefix = RandomStringUtils.insecure().randomAlphabetic(5).toLowerCase(); domain.setName(prefix + ".test.com"); Domain savedDomain = restClient.saveDomain(domain); assertThat(savedDomain.getName()).isEqualTo(domain.getName()); @@ -330,10 +356,10 @@ public class JavaRestClientTest extends AbstractContainerTest { restClient.login("sysadmin@thingsboard.org", "sysadmin"); MobileApp mobileApp = new MobileApp(); - String prefix = RandomStringUtils.randomAlphabetic(5).toLowerCase(); + String prefix = RandomStringUtils.insecure().randomAlphabetic(5).toLowerCase(); mobileApp.setPkgName(prefix + "test.app.apple"); mobileApp.setPlatformType(PlatformType.ANDROID); - mobileApp.setAppSecret(RandomStringUtils.randomAlphabetic(20)); + mobileApp.setAppSecret(RandomStringUtils.insecure().randomAlphabetic(20)); mobileApp.setStatus(MobileAppStatus.DRAFT); MobileApp savedMobileApp = restClient.saveMobileApp(mobileApp); @@ -343,7 +369,7 @@ public class JavaRestClientTest extends AbstractContainerTest { assertThat(retrieved.getData()).hasSize(1); MobileAppBundle mobileAppBundle = new MobileAppBundle(); - String bundlePrefix = RandomStringUtils.randomAlphabetic(5).toLowerCase(); + String bundlePrefix = RandomStringUtils.insecure().randomAlphabetic(5).toLowerCase(); mobileAppBundle.setTitle(bundlePrefix + "Test Bundle"); mobileAppBundle.setAndroidAppId(savedMobileApp.getId()); @@ -357,7 +383,7 @@ public class JavaRestClientTest extends AbstractContainerTest { filter.setUsersIds(Arrays.stream(usersIds).map(UUIDBased::getId).toList()); NotificationTarget notificationTarget = new NotificationTarget(); - notificationTarget.setName(filter + RandomStringUtils.randomNumeric(5)); + notificationTarget.setName(filter + RandomStringUtils.insecure().randomNumeric(5)); PlatformUsersNotificationTargetConfig targetConfig = new PlatformUsersNotificationTargetConfig(); targetConfig.setUsersFilter(filter); notificationTarget.setConfiguration(targetConfig); @@ -367,7 +393,7 @@ public class JavaRestClientTest extends AbstractContainerTest { private NotificationTemplate createNotificationTemplate(NotificationType notificationType, String subject, String text, NotificationDeliveryMethod... deliveryMethods) { NotificationTemplate notificationTemplate = new NotificationTemplate(); - notificationTemplate.setName("Notification template: " + RandomStringUtils.randomAlphabetic(5)); + notificationTemplate.setName("Notification template: " + RandomStringUtils.insecure().randomAlphabetic(5)); notificationTemplate.setNotificationType(notificationType); NotificationTemplateConfig config = new NotificationTemplateConfig(); config.setDeliveryMethodsTemplates(new HashMap<>()); @@ -418,9 +444,9 @@ public class JavaRestClientTest extends AbstractContainerTest { public void testApiKeyOperations() { // Create an API key ApiKeyInfo apiKeyInfo = new ApiKeyInfo(); - apiKeyInfo.setDescription("Test API Key " + RandomStringUtils.randomAlphabetic(5)); + apiKeyInfo.setDescription("Test API Key " + RandomStringUtils.insecure().randomAlphabetic(5)); apiKeyInfo.setEnabled(true); - apiKeyInfo.setUserId(user.getId()); + apiKeyInfo.setUserId(tenantAdmin1.getId()); apiKeyInfo.setExpirationTime(0); ApiKey savedApiKey = restClient.saveApiKey(apiKeyInfo); @@ -428,18 +454,18 @@ public class JavaRestClientTest extends AbstractContainerTest { assertThat(savedApiKey.getId()).isNotNull(); assertThat(savedApiKey.getDescription()).isEqualTo(apiKeyInfo.getDescription()); assertThat(savedApiKey.isEnabled()).isTrue(); - assertThat(savedApiKey.getUserId()).isEqualTo(user.getId()); - assertThat(savedApiKey.getTenantId()).isEqualTo(tenant.getId()); + assertThat(savedApiKey.getUserId()).isEqualTo(tenantAdmin1.getId()); + assertThat(savedApiKey.getTenantId()).isEqualTo(tenant1.getId()); assertThat(savedApiKey.getValue()).isNotNull(); // Get user API keys - PageData apiKeys = restClient.getUserApiKeys(user.getId(), new PageLink(10)); + PageData apiKeys = restClient.getUserApiKeys(tenantAdmin1.getId(), new PageLink(10)); assertThat(apiKeys).isNotNull(); assertThat(apiKeys.getData()).hasSize(1); assertThat(apiKeys.getData().get(0).getId()).isEqualTo(savedApiKey.getId()); // Update API key description - String updatedDescription = "Updated description " + RandomStringUtils.randomAlphabetic(5); + String updatedDescription = "Updated description " + RandomStringUtils.insecure().randomAlphabetic(5); ApiKeyInfo updatedApiKeyInfo = restClient.updateApiKeyDescription(savedApiKey.getId(), updatedDescription); assertThat(updatedApiKeyInfo).isNotNull(); assertThat(updatedApiKeyInfo.getDescription()).isEqualTo(updatedDescription); @@ -458,8 +484,96 @@ public class JavaRestClientTest extends AbstractContainerTest { restClient.deleteApiKey(savedApiKey.getId()); // Verify the API key is deleted - PageData apiKeysAfterDelete = restClient.getUserApiKeys(user.getId(), new PageLink(10)); + PageData apiKeysAfterDelete = restClient.getUserApiKeys(tenantAdmin1.getId(), new PageLink(10)); assertThat(apiKeysAfterDelete.getData()).isEmpty(); } + @Test + public void testGetDeviceProfileInfosByIds() { + var profileData = new DeviceProfileData(); + profileData.setConfiguration(new DefaultDeviceProfileConfiguration()); + profileData.setTransportConfiguration(new DefaultDeviceProfileTransportConfiguration()); + + // Create a device profile in tenant1 (current tenant) + var deviceProfile1 = new DeviceProfile(); + deviceProfile1.setTenantId(tenant1.getId()); + deviceProfile1.setName("Device Profile 1"); + deviceProfile1.setType(DeviceProfileType.DEFAULT); + deviceProfile1.setTransportType(DeviceTransportType.DEFAULT); + deviceProfile1.setProfileData(profileData); + deviceProfile1 = restClient.saveDeviceProfile(deviceProfile1); + + var deviceProfile2 = new DeviceProfile(); + deviceProfile2.setTenantId(tenant1.getId()); + deviceProfile2.setName("Device Profile 2"); + deviceProfile2.setType(DeviceProfileType.DEFAULT); + deviceProfile2.setTransportType(DeviceTransportType.DEFAULT); + deviceProfile2.setProfileData(profileData); + deviceProfile2 = restClient.saveDeviceProfile(deviceProfile2); + + // Create two more device profiles in tenant2 (different tenant) + restClient.login(tenantAdmin2.getEmail(), "password123"); + + var deviceProfile3 = new DeviceProfile(); + deviceProfile3.setTenantId(tenant2.getId()); + deviceProfile3.setName("Device Profile 3"); + deviceProfile3.setType(DeviceProfileType.DEFAULT); + deviceProfile3.setTransportType(DeviceTransportType.DEFAULT); + deviceProfile3.setProfileData(profileData); + deviceProfile3 = restClient.saveDeviceProfile(deviceProfile3); + + var deviceProfile4 = new DeviceProfile(); + deviceProfile4.setTenantId(tenant2.getId()); + deviceProfile4.setName("Device Profile 4"); + deviceProfile4.setType(DeviceProfileType.DEFAULT); + deviceProfile4.setTransportType(DeviceTransportType.DEFAULT); + deviceProfile4.setProfileData(profileData); + deviceProfile4 = restClient.saveDeviceProfile(deviceProfile4); + + // Attempt to fetch profiles 1 and 3 while acting as Tenant 2. + // - Profile 1: Filtered out because it belongs to a different tenant. + // - Profile 2: Filtered out because it belongs to a different tenant and was not requested. + // - Profile 3: Should be returned. + // - Profile 4: Filtered out; it belongs to the correct tenant, but was not requested by ID. + List profiles = restClient.getDeviceProfileInfosByIds(Set.of(deviceProfile1.getUuidId(), deviceProfile3.getUuidId())); + assertThat(profiles).hasSize(1); + assertThat(profiles.get(0).getId()).isEqualTo(deviceProfile3.getId()); + } + + @Test + public void testGetAssetProfilesByIds() { + // Create two asset profiles in tenant1 (current tenant) + var assetProfile1 = new AssetProfile(); + assetProfile1.setTenantId(tenant1.getId()); + assetProfile1.setName("Asset Profile 1"); + assetProfile1 = restClient.saveAssetProfile(assetProfile1); + + var assetProfile2 = new AssetProfile(); + assetProfile2.setTenantId(tenant1.getId()); + assetProfile2.setName("Asset Profile 2"); + assetProfile2 = restClient.saveAssetProfile(assetProfile2); + + // Create two more asset profiles in tenant2 (different tenant) + restClient.login(tenantAdmin2.getEmail(), "password123"); + + var assetProfile3 = new AssetProfile(); + assetProfile3.setTenantId(tenant2.getId()); + assetProfile3.setName("Asset Profile 3"); + assetProfile3 = restClient.saveAssetProfile(assetProfile3); + + var assetProfile4 = new AssetProfile(); + assetProfile4.setTenantId(tenant2.getId()); + assetProfile4.setName("Asset Profile 4"); + assetProfile4 = restClient.saveAssetProfile(assetProfile4); + + // Attempt to fetch profiles 1 and 3 while acting as Tenant 2. + // - Profile 1: Filtered out because it belongs to a different tenant. + // - Profile 2: Filtered out because it belongs to a different tenant and was not requested. + // - Profile 3: Should be returned. + // - Profile 4: Filtered out; it belongs to the correct tenant, but was not requested by ID. + List profiles = restClient.getAssetProfilesByIds(Set.of(assetProfile1.getUuidId(), assetProfile3.getUuidId())); + assertThat(profiles).hasSize(1); + assertThat(profiles.get(0).getId()).isEqualTo(assetProfile3.getId()); + } + } diff --git a/rest-client/pom.xml b/rest-client/pom.xml index fd5783227b..33fa4b0c34 100644 --- a/rest-client/pom.xml +++ b/rest-client/pom.xml @@ -51,6 +51,10 @@ com.auth0 java-jwt + + org.apache.httpcomponents.core5 + httpcore5 + 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 83029c4f78..5ecfb07b64 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 @@ -23,6 +23,7 @@ import lombok.Getter; import lombok.SneakyThrows; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.concurrent.LazyInitializer; +import org.apache.hc.core5.net.URIBuilder; import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.Resource; @@ -157,11 +158,11 @@ import org.thingsboard.server.common.data.oauth2.PlatformType; import org.thingsboard.server.common.data.ota.ChecksumAlgorithm; import org.thingsboard.server.common.data.ota.OtaPackageType; import org.thingsboard.server.common.data.page.PageData; -import org.thingsboard.server.common.data.pat.ApiKey; -import org.thingsboard.server.common.data.pat.ApiKeyInfo; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.SortOrder; import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.common.data.pat.ApiKey; +import org.thingsboard.server.common.data.pat.ApiKeyInfo; import org.thingsboard.server.common.data.plugin.ComponentDescriptor; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.query.AlarmCountQuery; @@ -210,17 +211,21 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle; import java.io.Closeable; import java.io.IOException; import java.net.URI; +import java.net.URISyntaxException; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import static java.util.stream.Collectors.joining; import static org.thingsboard.server.common.data.StringUtils.isEmpty; public class RestClient implements Closeable { @@ -1588,6 +1593,33 @@ public class RestClient implements Closeable { }, activeOnly).getBody(); } + public List getDeviceProfileInfosByIds(Set ids) { + URIBuilder builder; + try { + builder = new URIBuilder(baseURL); + } catch (URISyntaxException e) { + throw new IllegalArgumentException("Invalid base URL: " + baseURL, e); + } + + builder.appendPath("/api/deviceProfileInfos"); + + String commaSeparatedIds = ids.stream() + .filter(Objects::nonNull) + .map(UUID::toString) + .collect(joining(",")); + + builder.addParameter("deviceProfileIds", commaSeparatedIds); + + URI uri; + try { + uri = builder.build(); + } catch (URISyntaxException e) { + throw new IllegalStateException("Failed to construct API URI from base URL and provided params", e); + } + + return restTemplate.exchange(uri, HttpMethod.GET, null, new ParameterizedTypeReference>() {}).getBody(); + } + public JsonNode claimDevice(String deviceName, ClaimRequest claimRequest) { return restTemplate.exchange( baseURL + "/api/customer/device/{deviceName}/claim", @@ -1824,6 +1856,33 @@ public class RestClient implements Closeable { }, params).getBody(); } + public List getAssetProfilesByIds(Set ids) { + URIBuilder builder; + try { + builder = new URIBuilder(baseURL); + } catch (URISyntaxException e) { + throw new IllegalArgumentException("Invalid base URL: " + baseURL, e); + } + + builder.appendPath("/api/assetProfileInfos"); + + String commaSeparatedIds = ids.stream() + .filter(Objects::nonNull) + .map(UUID::toString) + .collect(joining(",")); + + builder.addParameter("assetProfileIds", commaSeparatedIds); + + URI uri; + try { + uri = builder.build(); + } catch (URISyntaxException e) { + throw new IllegalStateException("Failed to construct API URI from base URL and provided params", e); + } + + return restTemplate.exchange(uri, HttpMethod.GET, null, new ParameterizedTypeReference>() {}).getBody(); + } + public Long countEntitiesByQuery(EntityCountQuery query) { return restTemplate.postForObject(baseURL + "/api/entitiesQuery/count", query, Long.class); } From e0fbbf6b4e32ded0cf8f57cd1b389d32e75da748 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Tue, 6 Jan 2026 15:10:16 +0200 Subject: [PATCH 012/742] REST API call node: support duplicate query param names --- .../common/data/util/CollectionsUtil.java | 10 -- .../rule/engine/rest/QueryParam.java | 23 +++ .../rule/engine/rest/TbHttpClient.java | 27 ++-- .../rest/TbRestApiCallNodeConfiguration.java | 6 +- .../rule/engine/rest/TbHttpClientTest.java | 146 +++++++++--------- .../engine/rest/TbRestApiCallNodeTest.java | 27 +++- 6 files changed, 136 insertions(+), 103 deletions(-) create mode 100644 rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/QueryParam.java diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/util/CollectionsUtil.java b/common/data/src/main/java/org/thingsboard/server/common/data/util/CollectionsUtil.java index bdc4430387..082be9b71f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/util/CollectionsUtil.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/util/CollectionsUtil.java @@ -18,7 +18,6 @@ package org.thingsboard.server.common.data.util; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -73,15 +72,6 @@ public class CollectionsUtil { return map; } - @SafeVarargs - public static LinkedHashMap orderedMapOf(Map.Entry... entries) { - LinkedHashMap map = new LinkedHashMap<>(); - for (Map.Entry entry : entries) { - map.put(entry.getKey(), entry.getValue()); - } - return map; - } - public static boolean emptyOrContains(Collection collection, V element) { return isEmpty(collection) || collection.contains(element); } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/QueryParam.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/QueryParam.java new file mode 100644 index 0000000000..2a72b3a88a --- /dev/null +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/QueryParam.java @@ -0,0 +1,23 @@ +/** + * Copyright © 2016-2025 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.rule.engine.rest; + +import jakarta.validation.constraints.NotNull; + +record QueryParam( + @NotNull(message = "query parameter names must be non-null") String name, + @NotNull(message = "query parameter values must be non-null") String value +) {} diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index a16b3f5fb5..0d5a78810b 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -15,7 +15,6 @@ */ package org.thingsboard.rule.engine.rest; -import com.google.common.collect.Maps; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.handler.ssl.SslContext; @@ -217,14 +216,15 @@ public class TbHttpClient { String endpointUrl = TbNodeUtils.processPattern(config.getRestEndpointUrlPattern(), msg); - Map processedQueryParams; + List processedQueryParams; if (config.isUseNewEncoding()) { - processedQueryParams = Maps.newHashMapWithExpectedSize(config.getQueryParams().size()); - config.getQueryParams().forEach((name, value) -> { - var processedParamName = TbNodeUtils.processPattern(name, msg); - var processedParamValue = TbNodeUtils.processPattern(value, msg); - processedQueryParams.put(processedParamName, processedParamValue); - }); + processedQueryParams = config.getQueryParams().stream() + .map(param -> { + var processedParamName = TbNodeUtils.processPattern(param.name(), msg); + var processedParamValue = TbNodeUtils.processPattern(param.value(), msg); + return new QueryParam(processedParamName, processedParamValue); + }) + .toList(); } else { processedQueryParams = null; } @@ -278,7 +278,7 @@ public class TbHttpClient { return origin; } - public URI buildEncodedUri(String endpointUrl, Map queryParams) { + public URI buildEncodedUri(String endpointUrl, List queryParams) { if (endpointUrl == null) { throw new RuntimeException("Url string cannot be null!"); } @@ -306,16 +306,15 @@ public class TbHttpClient { return uri; } - private URI buildEncodedUriNew(String endpointUrl, Map queryParams) { + private URI buildEncodedUriNew(String endpointUrl, List queryParams) { try { URIBuilder builder = new URIBuilder(endpointUrl); - queryParams.forEach(builder::addParameter); + queryParams.forEach(param -> builder.addParameter(param.name(), param.value())); return builder.build(); } catch (URISyntaxException e) { throw new IllegalArgumentException(""" - Invalid REST endpoint URL: '%s'. The URL must be valid and properly encoded. - If the path contains special characters (e.g., spaces, braces), they must be percent-encoded (e.g., '/my file/' should be '/my%%20file/', '/path/{id}/' should be '/path/%%7Bid%%7D/'). - Query parameters should be configured separately and will be encoded automatically.""".formatted(endpointUrl), e); + Invalid request URL: '%s'. The URL must be valid and properly encoded. + If URL contains special characters (e.g., spaces), they must be percent-encoded (e.g., '/my file/' should be '/my%%20file/').""".formatted(endpointUrl), e); } } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java index c896dea324..cd12eb5211 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java @@ -17,6 +17,7 @@ package org.thingsboard.rule.engine.rest; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.validation.Valid; import jakarta.validation.constraints.AssertTrue; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -27,6 +28,7 @@ import org.thingsboard.rule.engine.credentials.AnonymousCredentials; import org.thingsboard.rule.engine.credentials.ClientCredentials; import java.util.Collections; +import java.util.List; import java.util.Map; @JsonIgnoreProperties(ignoreUnknown = true) @@ -36,7 +38,7 @@ public class TbRestApiCallNodeConfiguration implements NodeConfiguration queryParams; + private List<@NotNull @Valid QueryParam> queryParams; private Map headers; private boolean useSimpleClientHttpFactory; private int readTimeoutMs; @@ -78,7 +80,7 @@ public class TbRestApiCallNodeConfiguration implements NodeConfiguration queryParams, String expectedEncodedUrl) { + public void testQueryParamsEncoding(String endpointUrl, List queryParams, String expectedEncodedUrl) { // GIVEN Mockito.when(client.buildEncodedUri(any(), any())).thenCallRealMethod(); @@ -253,42 +251,42 @@ public class TbHttpClientTest { return Stream.of( Arguments.of( Named.named("ISO 8601 date-time in value", "http://somecompany/api/data/fetch"), - Map.of("ts", "2016-08-01T09:06:06.0+02:00"), + List.of(new QueryParam("ts", "2016-08-01T09:06:06.0+02:00")), "http://somecompany/api/data/fetch?ts=2016-08-01T09%3A06%3A06.0%2B02%3A00" ), Arguments.of( Named.named("email with plus sign in value", "http://localhost:8080/api/user/sendActivationMail"), - Map.of("email", "someperson+test1289@thingsboard.io"), + List.of(new QueryParam("email", "someperson+test1289@thingsboard.io")), "http://localhost:8080/api/user/sendActivationMail?email=someperson%2Btest1289%40thingsboard.io" ), Arguments.of( Named.named("plus mixed with spaces in value", "http://url/api"), - Map.of("q", "a + b"), + List.of(new QueryParam("q", "a + b")), "http://url/api?q=a%20%2B%20b" ), Arguments.of( Named.named("colon in value", "http://url/api"), - Map.of("time", "12:00"), + List.of(new QueryParam("time", "12:00")), "http://url/api?time=12%3A00" ), Arguments.of( Named.named("slash in value", "http://url"), - Map.of("ref", "/home/user"), + List.of(new QueryParam("ref", "/home/user")), "http://url?ref=%2Fhome%2Fuser" ), Arguments.of( Named.named("comma and semicolon in value", "http://url"), - Map.of("l", "a,b;c"), + List.of(new QueryParam("l", "a,b;c")), "http://url?l=a%2Cb%3Bc" ), Arguments.of( Named.named("ampersand and equals in value", "http://url"), - Map.of("q", "key1=value1&key2=value2"), + List.of(new QueryParam("q", "key1=value1&key2=value2")), "http://url?q=key1%3Dvalue1%26key2%3Dvalue2" ), Arguments.of( Named.named("JSON in value", "http://url"), - Map.of("json", """ + List.of(new QueryParam("json", """ { "string": "hello", "integer": 42, @@ -305,245 +303,253 @@ public class TbHttpClientTest { "object": { "nested": "value" } - }"""), + }""")), "http://url?json=%7B%0A%20%20%20%20%22string%22%3A%20%22hello%22%2C%0A%20%20%20%20%22integer%22%3A%2042%2C%0A%20%20%20%20%22float%22%3A%203.14%2C%0A%20%20%20%20%22boolTrue%22%3A%20true%2C%0A%20%20%20%20%22boolFalse%22%3A%20false%2C%0A%20%20%20%20%22null%22%3A%20null%2C%0A%20%20%20%20%22array%22%3A%20%5B%0A%20%20%20%20%20%20%20%201%2C%0A%20%20%20%20%20%20%20%20%22two%22%2C%0A%20%20%20%20%20%20%20%20true%2C%0A%20%20%20%20%20%20%20%20null%0A%20%20%20%20%5D%2C%0A%20%20%20%20%22object%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22nested%22%3A%20%22value%22%0A%20%20%20%20%7D%0A%7D" ), Arguments.of( Named.named("UTF-8 in query", "http://url/cafes"), - orderedMapOf( - entry("nom", "Le Goût Moderne"), - entry("назва", "У Миколи \uD83D\uDE0B") + List.of( + new QueryParam("nom", "Le Goût Moderne"), + new QueryParam("назва", "У Миколи \uD83D\uDE0B") ), "http://url/cafes?nom=Le%20Go%C3%BBt%20Moderne&%D0%BD%D0%B0%D0%B7%D0%B2%D0%B0=%D0%A3%20%D0%9C%D0%B8%D0%BA%D0%BE%D0%BB%D0%B8%20%F0%9F%98%8B" ), Arguments.of( Named.named("empty value", "http://url/empty"), - Map.of("name", ""), + List.of(new QueryParam("name", "")), "http://url/empty?name=" ), Arguments.of( Named.named("blank value (spaces)", "http://url/empty"), - Map.of("name", " "), + List.of(new QueryParam("name", " ")), "http://url/empty?name=%20%20" ), Arguments.of( Named.named("empty key", "http://url/empty"), - Map.of("", "value"), + List.of(new QueryParam("", "value")), "http://url/empty?=value" ), Arguments.of( Named.named("blank key (spaces)", "http://url/empty"), - Map.of(" ", "value"), + List.of(new QueryParam(" ", "value")), "http://url/empty?%20%20=value" ), Arguments.of( Named.named("blank key with value that needs to be encoded", "http://url/empty"), - Map.of(" ", "value1+value2"), + List.of(new QueryParam(" ", "value1+value2")), "http://url/empty?%20%20=value1%2Bvalue2" ), Arguments.of( Named.named("blank key and value", "http://url/empty"), - Map.of(" ", " "), + List.of(new QueryParam(" ", " ")), "http://url/empty?%20%20=%20%20" ), Arguments.of( Named.named("fragment with query params", "http://url#frag"), - Map.of("docs", "مستندات عقدة القاعدة\n"), + List.of(new QueryParam("docs", "مستندات عقدة القاعدة\n")), "http://url?docs=%D9%85%D8%B3%D8%AA%D9%86%D8%AF%D8%A7%D8%AA%20%D8%B9%D9%82%D8%AF%D8%A9%20%D8%A7%D9%84%D9%82%D8%A7%D8%B9%D8%AF%D8%A9%0A#frag" ), Arguments.of( Named.named("fragment only", "http://url#frag"), - Collections.emptyMap(), + Collections.emptyList(), "http://url#frag" ), Arguments.of( Named.named("multiple query params (ordered)", "http://url/api"), - orderedMapOf( - entry("param1", "value1"), - entry("param2", "value2"), - entry("param3", "value3") + List.of( + new QueryParam("param1", "value1"), + new QueryParam("param2", "value2"), + new QueryParam("param3", "value3") ), "http://url/api?param1=value1¶m2=value2¶m3=value3" ), Arguments.of( Named.named("hash (#) in value", "http://url/api"), - Map.of("color", "#ff0000"), + List.of(new QueryParam("color", "#ff0000")), "http://url/api?color=%23ff0000" ), Arguments.of( Named.named("question mark (?) in value", "http://url/api"), - Map.of("query", "what?"), + List.of(new QueryParam("query", "what?")), "http://url/api?query=what%3F" ), Arguments.of( Named.named("percent sign (%) in value", "http://url/api"), - Map.of("discount", "50%"), + List.of(new QueryParam("discount", "50%")), "http://url/api?discount=50%25" ), Arguments.of( Named.named("already encoded string - double encoding", "http://url/api"), - Map.of("encoded", "%20"), + List.of(new QueryParam("encoded", "%20")), "http://url/api?encoded=%2520" ), Arguments.of( Named.named("URL with port number", "http://localhost:8080/api/v1/data"), - Map.of("key", "value"), + List.of(new QueryParam("key", "value")), "http://localhost:8080/api/v1/data?key=value" ), Arguments.of( Named.named("URL with userinfo (auth)", "http://user:password@hostname/path"), - Map.of("secure", "true"), + List.of(new QueryParam("secure", "true")), "http://user:password@hostname/path?secure=true" ), Arguments.of( Named.named("IPv4 address in URL", "http://192.168.1.100:9090/endpoint"), - Map.of("ip", "test"), + List.of(new QueryParam("ip", "test")), "http://192.168.1.100:9090/endpoint?ip=test" ), Arguments.of( Named.named("IPv6 address in URL", "http://[::1]:8080/api"), - Map.of("ipv6", "true"), + List.of(new QueryParam("ipv6", "true")), "http://[::1]:8080/api?ipv6=true" ), Arguments.of( Named.named("HTTPS protocol", "https://secure.example.com/api"), - Map.of("token", "abc123"), + List.of(new QueryParam("token", "abc123")), "https://secure.example.com/api?token=abc123" ), Arguments.of( Named.named("pipe (|) in value", "http://url/api"), - Map.of("filter", "a|b|c"), + List.of(new QueryParam("filter", "a|b|c")), "http://url/api?filter=a%7Cb%7Cc" ), Arguments.of( Named.named("caret (^) and backtick (`) in value", "http://url/api"), - Map.of("special", "a^b`c"), + List.of(new QueryParam("special", "a^b`c")), "http://url/api?special=a%5Eb%60c" ), Arguments.of( Named.named("tab character in value", "http://url/api"), - Map.of("data", "col1\tcol2\tcol3"), + List.of(new QueryParam("data", "col1\tcol2\tcol3")), "http://url/api?data=col1%09col2%09col3" ), Arguments.of( Named.named("CRLF in value", "http://url/api"), - Map.of("text", "line1\r\nline2"), + List.of(new QueryParam("text", "line1\r\nline2")), "http://url/api?text=line1%0D%0Aline2" ), Arguments.of( Named.named("square brackets in value", "http://url/api"), - Map.of("array", "[1,2,3]"), + List.of(new QueryParam("array", "[1,2,3]")), "http://url/api?array=%5B1%2C2%2C3%5D" ), Arguments.of( Named.named("single and double quotes in value", "http://url/api"), - Map.of("quoted", "He said \"Hello\" and 'Hi'"), + List.of(new QueryParam("quoted", "He said \"Hello\" and 'Hi'")), "http://url/api?quoted=He%20said%20%22Hello%22%20and%20%27Hi%27" ), Arguments.of( Named.named("angle brackets in value (XSS test)", "http://url/api"), - Map.of("html", ""), + List.of(new QueryParam("html", "")), "http://url/api?html=%3Cscript%3Ealert%28%27xss%27%29%3C%2Fscript%3E" ), Arguments.of( Named.named("backslash in value", "http://url/api"), - Map.of("path", "C:\\Users\\test"), + List.of(new QueryParam("path", "C:\\Users\\test")), "http://url/api?path=C%3A%5CUsers%5Ctest" ), Arguments.of( Named.named("at sign (@) in value", "http://url/api"), - Map.of("contact", "user@domain.com"), + List.of(new QueryParam("contact", "user@domain.com")), "http://url/api?contact=user%40domain.com" ), Arguments.of( Named.named("URL as value", "http://url/api"), - Map.of("redirect", "https://example.com/path?foo=bar"), + List.of(new QueryParam("redirect", "https://example.com/path?foo=bar")), "http://url/api?redirect=https%3A%2F%2Fexample.com%2Fpath%3Ffoo%3Dbar" ), Arguments.of( - Named.named("empty map (not null)", "http://url/api"), - Collections.emptyMap(), + Named.named("empty list (not null)", "http://url/api"), + Collections.emptyList(), "http://url/api" ), Arguments.of( Named.named("underscore and hyphen in key/value", "http://url/api"), - Map.of("my-key_name", "my-value_data"), + List.of(new QueryParam("my-key_name", "my-value_data")), "http://url/api?my-key_name=my-value_data" ), Arguments.of( Named.named("dots in key and value", "http://url/api"), - Map.of("version.major", "1.2.3"), + List.of(new QueryParam("version.major", "1.2.3")), "http://url/api?version.major=1.2.3" ), Arguments.of( Named.named("multiple reserved chars combined", "http://url/api"), - Map.of("complex", "a=1&b=2#section?query"), + List.of(new QueryParam("complex", "a=1&b=2#section?query")), "http://url/api?complex=a%3D1%26b%3D2%23section%3Fquery" ), Arguments.of( Named.named("trailing slash in URL", "http://url/api/"), - Map.of("param", "value"), + List.of(new QueryParam("param", "value")), "http://url/api/?param=value" ), Arguments.of( Named.named("long value (1000 chars)", "http://url/api"), - Map.of("long", "a".repeat(1000)), + List.of(new QueryParam("long", "a".repeat(1000))), "http://url/api?long=" + "a".repeat(1000) ), Arguments.of( Named.named("Chinese characters in value", "http://url/api"), - Map.of("greeting", "你好世界"), + List.of(new QueryParam("greeting", "你好世界")), "http://url/api?greeting=%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C" ), Arguments.of( Named.named("Japanese characters in value", "http://url/api"), - Map.of("text", "こんにちは"), + List.of(new QueryParam("text", "こんにちは")), "http://url/api?text=%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF" ), Arguments.of( Named.named("existing query params in URL", "http://url/api?existing=param"), - Map.of("new", "value"), + List.of(new QueryParam("new", "value")), "http://url/api?existing=param&new=value" ), Arguments.of( Named.named("existing query and fragment in URL", "http://url/api?existing=param#section"), - Map.of("additional", "data"), + List.of(new QueryParam("additional", "data")), "http://url/api?existing=param&additional=data#section" ), Arguments.of( Named.named("null byte in value", "http://url/api"), - Map.of("data", "before\u0000after"), + List.of(new QueryParam("data", "before\u0000after")), "http://url/api?data=before%00after" ), Arguments.of( Named.named("form feed and vertical tab in value", "http://url/api"), - Map.of("whitespace", "a\fb\u000Bc"), + List.of(new QueryParam("whitespace", "a\fb\u000Bc")), "http://url/api?whitespace=a%0Cb%0Bc" ), Arguments.of( Named.named("tilde (unreserved, not encoded)", "http://url/api"), - Map.of("pattern", "~user"), + List.of(new QueryParam("pattern", "~user")), "http://url/api?pattern=~user" ), Arguments.of( Named.named("asterisk in value", "http://url/api"), - Map.of("wildcard", "*.txt"), + List.of(new QueryParam("wildcard", "*.txt")), "http://url/api?wildcard=%2A.txt" ), Arguments.of( Named.named("curly braces in key", "http://url/api"), - Map.of("{key}", "value"), + List.of(new QueryParam("{key}", "value")), "http://url/api?%7Bkey%7D=value" ), Arguments.of( Named.named("curly braces in value", "http://url/api"), - Map.of("data", "{value}"), + List.of(new QueryParam("data", "{value}")), "http://url/api?data=%7Bvalue%7D" ), Arguments.of( Named.named("curly braces in both key and value", "http://url/api"), - Map.of("{param}", "{data}"), + List.of(new QueryParam("{param}", "{data}")), "http://url/api?%7Bparam%7D=%7Bdata%7D" + ), + Arguments.of( + Named.named("duplicate param names with different values", "http://url/api"), + List.of( + new QueryParam("test", "a+b"), + new QueryParam("test", "b c") + ), + "http://url/api?test=a%2Bb&test=b%20c" ) ); } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java index 8c3654bdc5..39d9e0d585 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java @@ -52,8 +52,7 @@ import org.thingsboard.server.dao.exception.DataValidationException; import java.io.IOException; import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; @@ -120,14 +119,28 @@ public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest { } } + @Test + public void shouldNotAllowNullQueryParamNames() { + // GIVEN + var config = new TbRestApiCallNodeConfiguration().defaultConfiguration(); + config.setUseNewEncoding(true); + config.setQueryParams(List.of(new QueryParam(null, "value"))); + + // WHEN-THEN + assertThatThrownBy(() -> new TbRestApiCallNode().init(ctx, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) + .isInstanceOf(TbNodeException.class) + .matches(e -> ((TbNodeException) e).isUnrecoverable()) + .rootCause() + .isInstanceOf(DataValidationException.class) + .hasMessageContaining("query parameter names must be non-null"); + } + @Test public void shouldNotAllowNullQueryParamValues() { // GIVEN var config = new TbRestApiCallNodeConfiguration().defaultConfiguration(); config.setUseNewEncoding(true); - var params = new HashMap(); - params.put("key", null); - config.setQueryParams(params); + config.setQueryParams(List.of(new QueryParam("key", null))); // WHEN-THEN assertThatThrownBy(() -> new TbRestApiCallNode().init(ctx, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) @@ -143,7 +156,7 @@ public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest { // GIVEN var config = new TbRestApiCallNodeConfiguration().defaultConfiguration(); config.setUseNewEncoding(false); - config.setQueryParams(Map.of("key", "value")); + config.setQueryParams(List.of(new QueryParam("key", "value"))); // WHEN-THEN assertThatThrownBy(() -> new TbRestApiCallNode().init(ctx, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) @@ -175,7 +188,7 @@ public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest { // THEN assertTrue(defaultConfig.isUseNewEncoding()); - assertEquals(Collections.emptyMap(), defaultConfig.getQueryParams()); + assertEquals(Collections.emptyList(), defaultConfig.getQueryParams()); } @Test From df795e252b7d0bac6948a062240c7205139a9bb1 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Wed, 7 Jan 2026 11:59:46 +0200 Subject: [PATCH 013/742] REST API call node: refactor to avoid boolean flag --- .../rule/engine/rest/TbHttpClient.java | 12 +++---- .../rest/TbRestApiCallNodeConfiguration.java | 22 ------------ .../rule/engine/rest/TbHttpClientTest.java | 2 -- .../engine/rest/TbRestApiCallNodeTest.java | 35 ++++++------------- 4 files changed, 16 insertions(+), 55 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index 0d5a78810b..e9476157aa 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -217,7 +217,7 @@ public class TbHttpClient { String endpointUrl = TbNodeUtils.processPattern(config.getRestEndpointUrlPattern(), msg); List processedQueryParams; - if (config.isUseNewEncoding()) { + if (config.getQueryParams() != null) { processedQueryParams = config.getQueryParams().stream() .map(param -> { var processedParamName = TbNodeUtils.processPattern(param.name(), msg); @@ -312,9 +312,9 @@ public class TbHttpClient { queryParams.forEach(param -> builder.addParameter(param.name(), param.value())); return builder.build(); } catch (URISyntaxException e) { - throw new IllegalArgumentException(""" - Invalid request URL: '%s'. The URL must be valid and properly encoded. - If URL contains special characters (e.g., spaces), they must be percent-encoded (e.g., '/my file/' should be '/my%%20file/').""".formatted(endpointUrl), e); + throw new IllegalArgumentException( + "Invalid request URL: '" + endpointUrl + "'. The URL must be valid and properly encoded. " + + "If URL contains special characters (e.g., spaces), they must be percent-encoded (e.g., '/my device/' should be '/my%20device/').", e); } } @@ -327,10 +327,10 @@ public class TbHttpClient { * Pre-encoding the URL (e.g., {@code email=user%2Btag@test.com}) doesn't help * because {@code .encode()} will double-encode it to {@code email=user%252Btag@test.com}. *

- * Use {@link #buildEncodedUriNew} with a separate query params map, + * Use {@link #buildEncodedUriNew} with a separate query params list, * where values are encoded exactly once: {@code +} → {@code %2B}, {@code @} → {@code %40}. */ - @Deprecated(since = "4.2.1.2", forRemoval = true) // fixme: remove in major 5.0 + @Deprecated(since = "4.2.1.2", forRemoval = true) private URI buildEncodedUriLegacy(String endpointUrl) { return UriComponentsBuilder.fromUriString(endpointUrl).build().encode().toUri(); } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java index cd12eb5211..d319d15157 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java @@ -15,10 +15,8 @@ */ package org.thingsboard.rule.engine.rest; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import jakarta.validation.Valid; -import jakarta.validation.constraints.AssertTrue; import jakarta.validation.constraints.NotNull; import lombok.Data; import org.springframework.http.HttpHeaders; @@ -37,7 +35,6 @@ public class TbRestApiCallNodeConfiguration implements NodeConfiguration queryParams; private Map headers; private boolean useSimpleClientHttpFactory; @@ -55,31 +52,12 @@ public class TbRestApiCallNodeConfiguration implements NodeConfiguration new TbRestApiCallNode().init(ctx, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) - .isInstanceOf(TbNodeException.class) - .hasRootCauseInstanceOf(DataValidationException.class) - .hasRootCauseMessage("'" + ruleNode.getName() + "' node configuration is invalid: query parameters must be null if old encoding is used") - .matches(e -> ((TbNodeException) e).isUnrecoverable()); - } - - @Test - public void shouldNotAllowNullQueryParamsIfNewEncodingIsUsed() { - // GIVEN - var config = new TbRestApiCallNodeConfiguration().defaultConfiguration(); - config.setUseNewEncoding(true); - config.setQueryParams(null); + var queryParams = new ArrayList(); + queryParams.add(new QueryParam("key", "value")); + queryParams.add(null); + config.setQueryParams(queryParams); // WHEN-THEN assertThatThrownBy(() -> new TbRestApiCallNode().init(ctx, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) .isInstanceOf(TbNodeException.class) - .hasRootCauseInstanceOf(DataValidationException.class) - .hasRootCauseMessage("'" + ruleNode.getName() + "' node configuration is invalid: query parameters must be non-null if new encoding is used") - .matches(e -> ((TbNodeException) e).isUnrecoverable()); + .matches(e -> ((TbNodeException) e).isUnrecoverable()) + .rootCause() + .isInstanceOf(DataValidationException.class) + .hasMessageContaining("must not be null"); } @Test @@ -187,7 +174,6 @@ public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest { var defaultConfig = new TbRestApiCallNodeConfiguration().defaultConfiguration(); // THEN - assertTrue(defaultConfig.isUseNewEncoding()); assertEquals(Collections.emptyList(), defaultConfig.getQueryParams()); } @@ -224,7 +210,6 @@ public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest { var config = JacksonUtil.fromString(configJson, TbRestApiCallNodeConfiguration.class); // THEN - assertFalse(config.isUseNewEncoding()); assertNull(config.getQueryParams()); } From aabf0c3813d5f5962f47dd1382589787241ccdfe Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Wed, 7 Jan 2026 13:03:22 +0200 Subject: [PATCH 014/742] Improve validation for user credentials on login --- .../security/system/DefaultSystemSecurityService.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java b/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java index 69536f0953..a977def292 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java @@ -80,11 +80,15 @@ public class DefaultSystemSecurityService implements SystemSecurityService { @Override public void validateUserCredentials(TenantId tenantId, UserCredentials userCredentials, String username, String password) throws AuthenticationException { + if (!userCredentials.isEnabled()) { + throw new DisabledException("User is not active"); + } + if (!encoder.matches(password, userCredentials.getPassword())) { int failedLoginAttempts = userService.increaseFailedLoginAttempts(tenantId, userCredentials.getUserId()); SecuritySettings securitySettings = securitySettingsService.getSecuritySettings(); if (securitySettings.getMaxFailedLoginAttempts() != null && securitySettings.getMaxFailedLoginAttempts() > 0) { - if (failedLoginAttempts > securitySettings.getMaxFailedLoginAttempts() && userCredentials.isEnabled()) { + if (failedLoginAttempts > securitySettings.getMaxFailedLoginAttempts()) { lockAccount(userCredentials.getUserId(), username, securitySettings.getUserLockoutNotificationEmail(), securitySettings.getMaxFailedLoginAttempts()); throw new LockedException("Authentication Failed. Username was locked due to security policy."); } @@ -92,10 +96,6 @@ public class DefaultSystemSecurityService implements SystemSecurityService { throw new BadCredentialsException("Authentication Failed. Username or Password not valid."); } - if (!userCredentials.isEnabled()) { - throw new DisabledException("User is not active"); - } - userService.resetFailedLoginAttempts(tenantId, userCredentials.getUserId()); SecuritySettings securitySettings = securitySettingsService.getSecuritySettings(); From eafa9e6846f6d5548e8f6d22d323dc22e798d543 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Wed, 7 Jan 2026 15:58:41 +0200 Subject: [PATCH 015/742] fix bug validateKeyValueProtos String empty - ok --- .../org/thingsboard/server/common/adaptor/ProtoConverter.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/common/proto/src/main/java/org/thingsboard/server/common/adaptor/ProtoConverter.java b/common/proto/src/main/java/org/thingsboard/server/common/adaptor/ProtoConverter.java index 6dc9387a37..a47caae954 100644 --- a/common/proto/src/main/java/org/thingsboard/server/common/adaptor/ProtoConverter.java +++ b/common/proto/src/main/java/org/thingsboard/server/common/adaptor/ProtoConverter.java @@ -156,11 +156,7 @@ public class ProtoConverter { case BOOLEAN_V: case LONG_V: case DOUBLE_V: - break; case STRING_V: - if (StringUtils.isEmpty(keyValueProto.getStringV())) { - throw new IllegalArgumentException("Value is empty for key: " + key + "!"); - } break; case JSON_V: try { From 493aabebc1bf82ce91d33cb27ab013078ce90285 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Wed, 7 Jan 2026 16:28:10 +0200 Subject: [PATCH 016/742] fix bug validateKeyValueProtos String empty - add test --- .../AbstractMqttV5ClientSparkplugTest.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/mqtt/sparkplug/AbstractMqttV5ClientSparkplugTest.java b/application/src/test/java/org/thingsboard/server/transport/mqtt/sparkplug/AbstractMqttV5ClientSparkplugTest.java index 6fb08f9eea..4e4d0debf9 100644 --- a/application/src/test/java/org/thingsboard/server/transport/mqtt/sparkplug/AbstractMqttV5ClientSparkplugTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/mqtt/sparkplug/AbstractMqttV5ClientSparkplugTest.java @@ -159,14 +159,17 @@ public abstract class AbstractMqttV5ClientSparkplugTest extends AbstractMqttInte protected List connectClientWithCorrectAccessTokenWithNDEATHCreatedDevices(int cntDevices, long ts) throws Exception { List devices = new ArrayList<>(); clientWithCorrectNodeAccessTokenWithNDEATH(); - MetricDataType metricDataType = Int32; - String key = "Node Metric int32"; + String keyInt = "Node Metric int32"; int valueDeviceInt32 = 1024; - SparkplugBProto.Payload.Metric metric = createMetric(valueDeviceInt32, ts, key, metricDataType, -1L); + SparkplugBProto.Payload.Metric metricInt = createMetric(valueDeviceInt32, ts, keyInt, Int32, -1L); + String keyStringEmpty = "Node Metric String Empty"; + String valueDeviceStringEmpty = ""; + SparkplugBProto.Payload.Metric metricStringEmpty = createMetric(valueDeviceStringEmpty, ts, keyStringEmpty, MetricDataType.String, -1L); SparkplugBProto.Payload.Builder payloadBirthNode = SparkplugBProto.Payload.newBuilder() .setTimestamp(ts) .setSeq(getBdSeqNum()); - payloadBirthNode.addMetrics(metric); + payloadBirthNode.addMetrics(metricInt); + payloadBirthNode.addMetrics(metricStringEmpty); payloadBirthNode.setTimestamp(ts); if (client.isConnected()) { client.publish(TOPIC_ROOT_SPB_V_1_0 + "/" + groupId + "/" + SparkplugMessageType.NBIRTH.name() + "/" + edgeNode, @@ -174,14 +177,14 @@ public abstract class AbstractMqttV5ClientSparkplugTest extends AbstractMqttInte } valueDeviceInt32 = 4024; - metric = createMetric(valueDeviceInt32, ts, metricBirthName_Int32, metricBirthDataType_Int32, -1L); + metricInt = createMetric(valueDeviceInt32, ts, metricBirthName_Int32, metricBirthDataType_Int32, -1L); for (int i = 0; i < cntDevices; i++) { SparkplugBProto.Payload.Builder payloadBirthDevice = SparkplugBProto.Payload.newBuilder() .setTimestamp(ts) .setSeq(getSeqNum()); String deviceName = deviceId + "_" + i; - payloadBirthDevice.addMetrics(metric); + payloadBirthDevice.addMetrics(metricInt); if (client.isConnected()) { client.publish(TOPIC_ROOT_SPB_V_1_0 + "/" + groupId + "/" + SparkplugMessageType.DBIRTH.name() + "/" + edgeNode + "/" + deviceName, payloadBirthDevice.build().toByteArray(), 0, false); From 4363e53ff4782b7e7343b05ca13c1a6c97bcc620 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Thu, 8 Jan 2026 12:35:27 +0200 Subject: [PATCH 017/742] Add DefaultSystemSecurityServiceTest --- .../DefaultSystemSecurityServiceTest.java | 204 ++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 application/src/test/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityServiceTest.java diff --git a/application/src/test/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityServiceTest.java b/application/src/test/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityServiceTest.java new file mode 100644 index 0000000000..05e51177af --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityServiceTest.java @@ -0,0 +1,204 @@ +/** + * Copyright © 2016-2025 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.service.security.system; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.DisabledException; +import org.springframework.security.authentication.LockedException; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.thingsboard.rule.engine.api.MailService; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.common.data.security.UserCredentials; +import org.thingsboard.server.common.data.security.model.SecuritySettings; +import org.thingsboard.server.common.data.security.model.UserPasswordPolicy; +import org.thingsboard.server.dao.audit.AuditLogService; +import org.thingsboard.server.dao.settings.AdminSettingsService; +import org.thingsboard.server.dao.settings.SecuritySettingsService; +import org.thingsboard.server.dao.user.UserService; + +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class DefaultSystemSecurityServiceTest { + + @Mock + private AdminSettingsService adminSettingsService; + @Mock + private BCryptPasswordEncoder encoder; + @Mock + private UserService userService; + @Mock + private MailService mailService; + @Mock + private AuditLogService auditLogService; + @Mock + private SecuritySettingsService securitySettingsService; + + private DefaultSystemSecurityService systemSecurityService; + + private TenantId tenantId; + private UserId userId; + private UserCredentials userCredentials; + private SecuritySettings securitySettings; + private String username; + private String password; + private String encodedPassword; + + @Before + public void setUp() { + systemSecurityService = new DefaultSystemSecurityService(adminSettingsService, encoder, userService, mailService, auditLogService, securitySettingsService); + + tenantId = TenantId.fromUUID(UUID.randomUUID()); + userId = new UserId(UUID.randomUUID()); + username = "tenant@example.com"; + password = "correctPassword"; + encodedPassword = "$2a$10$encodedPasswordHash"; + + userCredentials = new UserCredentials(); + userCredentials.setUserId(userId); + userCredentials.setEnabled(true); + userCredentials.setPassword(encodedPassword); + userCredentials.setCreatedTime(System.currentTimeMillis()); + + securitySettings = new SecuritySettings(); + securitySettings.setMaxFailedLoginAttempts(5); + securitySettings.setPasswordPolicy(new UserPasswordPolicy()); + } + + @Test + public void testValidateUserCredentials_successfulLogin() { + when(encoder.matches(password, encodedPassword)).thenReturn(true); + when(securitySettingsService.getSecuritySettings()).thenReturn(securitySettings); + + systemSecurityService.validateUserCredentials(tenantId, userCredentials, username, password); + + verify(encoder).matches(password, encodedPassword); + verify(userService).resetFailedLoginAttempts(tenantId, userId); + verify(userService, never()).increaseFailedLoginAttempts(any(), any()); + } + + @Test + public void testValidateUserCredentials_wrongPassword_incrementsFailedAttempts() { + when(encoder.matches(password, encodedPassword)).thenReturn(false); + when(userService.increaseFailedLoginAttempts(tenantId, userId)).thenReturn(3); + when(securitySettingsService.getSecuritySettings()).thenReturn(securitySettings); + + assertThatThrownBy(() -> systemSecurityService.validateUserCredentials(tenantId, userCredentials, username, password)) + .isInstanceOf(BadCredentialsException.class) + .hasMessageContaining("Authentication Failed"); + + verify(userService).increaseFailedLoginAttempts(tenantId, userId); + verify(userService, never()).setUserCredentialsEnabled(any(), any(), eq(false)); + } + + @Test + public void testValidateUserCredentials_wrongPassword_accountLocked() { + when(encoder.matches(password, encodedPassword)).thenReturn(false); + when(userService.increaseFailedLoginAttempts(tenantId, userId)).thenReturn(6); + when(securitySettingsService.getSecuritySettings()).thenReturn(securitySettings); + + assertThatThrownBy(() -> systemSecurityService.validateUserCredentials(tenantId, userCredentials, username, password)) + .isInstanceOf(LockedException.class) + .hasMessageContaining("locked due to security policy"); + + verify(userService).increaseFailedLoginAttempts(tenantId, userId); + verify(userService).setUserCredentialsEnabled(TenantId.SYS_TENANT_ID, userId, false); + } + + @Test + public void testValidateUserCredentials_wrongPassword_exactlyAtThreshold_noLock() { + when(encoder.matches(password, encodedPassword)).thenReturn(false); + when(userService.increaseFailedLoginAttempts(tenantId, userId)).thenReturn(5); + when(securitySettingsService.getSecuritySettings()).thenReturn(securitySettings); + + assertThatThrownBy(() -> systemSecurityService.validateUserCredentials(tenantId, userCredentials, username, password)) + .isInstanceOf(BadCredentialsException.class) + .hasMessageContaining("Authentication Failed"); + + verify(userService).increaseFailedLoginAttempts(tenantId, userId); + verify(userService, never()).setUserCredentialsEnabled(any(), any(), eq(false)); + } + + @Test + public void testValidateUserCredentials_correctPassword_disabledUser_throwsDisabledException() { + userCredentials.setEnabled(false); + + assertThatThrownBy(() -> systemSecurityService.validateUserCredentials(tenantId, userCredentials, username, password)) + .isInstanceOf(DisabledException.class) + .hasMessage("User is not active"); + + verify(encoder, never()).matches(any(), any()); + verify(userService, never()).increaseFailedLoginAttempts(any(), any()); + } + + @Test + public void testValidateUserCredentials_wrongPassword_maxAttemptsDisabled() { + securitySettings.setMaxFailedLoginAttempts(null); + when(encoder.matches(password, encodedPassword)).thenReturn(false); + when(userService.increaseFailedLoginAttempts(tenantId, userId)).thenReturn(100); + when(securitySettingsService.getSecuritySettings()).thenReturn(securitySettings); + + assertThatThrownBy(() -> systemSecurityService.validateUserCredentials(tenantId, userCredentials, username, password)) + .isInstanceOf(BadCredentialsException.class); + + verify(userService).increaseFailedLoginAttempts(tenantId, userId); + verify(userService, never()).setUserCredentialsEnabled(any(), any(), eq(false)); + } + + @Test + public void testValidateUserCredentials_wrongPassword_maxAttemptsSetToZero() { + securitySettings.setMaxFailedLoginAttempts(0); + when(encoder.matches(password, encodedPassword)).thenReturn(false); + when(userService.increaseFailedLoginAttempts(tenantId, userId)).thenReturn(100); + when(securitySettingsService.getSecuritySettings()).thenReturn(securitySettings); + + assertThatThrownBy(() -> systemSecurityService.validateUserCredentials(tenantId, userCredentials, username, password)) + .isInstanceOf(BadCredentialsException.class); + + verify(userService).increaseFailedLoginAttempts(tenantId, userId); + verify(userService, never()).setUserCredentialsEnabled(any(), any(), eq(false)); + } + + @Test + public void testValidateUserCredentials_wrongPassword_withNotificationEmail() throws ThingsboardException { + String notificationEmail = "admin@example.com"; + securitySettings.setUserLockoutNotificationEmail(notificationEmail); + when(encoder.matches(password, encodedPassword)).thenReturn(false); + when(userService.increaseFailedLoginAttempts(tenantId, userId)).thenReturn(6); + when(securitySettingsService.getSecuritySettings()).thenReturn(securitySettings); + + assertThatThrownBy(() -> systemSecurityService.validateUserCredentials(tenantId, userCredentials, username, password)) + .isInstanceOf(LockedException.class); + + verify(userService).setUserCredentialsEnabled(TenantId.SYS_TENANT_ID, userId, false); + verify(mailService).sendAccountLockoutEmail(eq(username), eq(notificationEmail), eq(5)); + } + +} From bc322a966d30997b38b9fd9d836d9b52e501151e Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Fri, 9 Jan 2026 12:23:48 +0200 Subject: [PATCH 018/742] REST API call node: cleanup properties in node config --- .../rule/engine/rest/TbHttpClient.java | 4 -- .../rule/engine/rest/TbRestApiCallNode.java | 20 ++++++- .../rest/TbRestApiCallNodeConfiguration.java | 7 +-- .../rule/engine/rest/TbHttpClientTest.java | 1 - .../engine/rest/TbRestApiCallNodeTest.java | 55 ++++++++++++++++++- 5 files changed, 73 insertions(+), 14 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index e9476157aa..05f5d547a8 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -130,10 +130,6 @@ public class TbHttpClient { SslContext sslContext = config.getCredentials().initSslContext(); httpClient = httpClient.secure(t -> t.sslContext(sslContext)); } - } else if (config.isUseSimpleClientHttpFactory()) { - if (CredentialsType.CERT_PEM == config.getCredentials().getType()) { - throw new TbNodeException("Simple HTTP Factory does not support CERT PEM credentials!"); - } } else { SslContext sslContext = config.getCredentials().initSslContext(); httpClient = httpClient.secure(t -> t.sslContext(sslContext)); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java index 3e9b034693..bccbc9a08f 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java @@ -28,7 +28,9 @@ import org.thingsboard.server.common.data.util.TbPair; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.dao.exception.DataValidationException; +import java.util.Iterator; import java.util.List; +import java.util.Set; import static org.thingsboard.server.dao.service.ConstraintValidator.validateFields; @@ -36,7 +38,7 @@ import static org.thingsboard.server.dao.service.ConstraintValidator.validateFie type = ComponentType.EXTERNAL, name = "rest api call", configClazz = TbRestApiCallNodeConfiguration.class, - version = 3, + version = 4, nodeDescription = "Invoke REST API calls to external REST server", nodeDetails = "Will invoke REST API call GET | POST | PUT | DELETE to external REST server. " + "Message payload added into Request body. Configured attributes can be added into Headers from Message Metadata." + @@ -108,6 +110,22 @@ public class TbRestApiCallNode extends TbAbstractExternalNode { ((ObjectNode) oldConfiguration).put(MAX_IN_MEMORY_BUFFER_SIZE_IN_KB, 256); } break; + case 3: + Set knownProperties = Set.of( + "restEndpointUrlPattern", "requestMethod", "headers", + "readTimeoutMs", "maxParallelRequestsCount", "parseToPlainText", + "enableProxy", "useSystemProxyProperties", "proxyHost", "proxyPort", + "proxyUser", "proxyPassword", "credentials", "ignoreRequestBody", + "maxInMemoryBufferSizeInKb" + ); + Iterator fieldNames = oldConfiguration.fieldNames(); + while (fieldNames.hasNext()) { + if (!knownProperties.contains(fieldNames.next())) { + hasChanges = true; + fieldNames.remove(); + } + } + break; default: break; } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java index d319d15157..fbff14f640 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java @@ -15,7 +15,6 @@ */ package org.thingsboard.rule.engine.rest; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -29,15 +28,15 @@ import java.util.Collections; import java.util.List; import java.util.Map; -@JsonIgnoreProperties(ignoreUnknown = true) @Data public class TbRestApiCallNodeConfiguration implements NodeConfiguration { private String restEndpointUrlPattern; private String requestMethod; + // null for legacy configs - triggers different URL encoding logic in TbHttpClient to preserver backward compatibility + // all new/modified configs since introduction of this property are forced to have non-null value by UI (and use new encoding logic) private List<@NotNull @Valid QueryParam> queryParams; private Map headers; - private boolean useSimpleClientHttpFactory; private int readTimeoutMs; private int maxParallelRequestsCount; private boolean parseToPlainText; @@ -47,7 +46,6 @@ public class TbRestApiCallNodeConfiguration implements NodeConfiguration Date: Fri, 9 Jan 2026 14:34:25 +0200 Subject: [PATCH 019/742] Move REST API call rule node to new UI --- .../common/credentials-config.component.html | 114 ++++----- .../common/kv-map-config-old.component.html | 78 +++--- .../common/kv-map-config-old.component.ts | 4 + .../rest-api-call-config.component.html | 227 ++++++++++-------- .../rest-api-call-config.component.scss | 30 +++ .../rest-api-call-config.component.ts | 28 ++- .../assets/locale/locale.constant-en_US.json | 9 + 7 files changed, 290 insertions(+), 200 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.scss diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.html index 59bfa7ce9f..9a42bfda14 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.html @@ -15,8 +15,8 @@ limitations under the License. --> -

- +
+ rule-node-config.credentials @@ -24,7 +24,7 @@ - + rule-node-config.credentials-type -
- - - - - rule-node-config.username - - - {{ 'rule-node-config.username-required' | translate }} - - - - rule-node-config.password - - - - {{ 'rule-node-config.password-required' | translate }} - - - - -
{{ 'rule-node-config.credentials-pem-hint' | translate }}
- - - - - - - - rule-node-config.private-key-password - - - -
-
+ @if (credentialsConfigFormGroup.get('type').value !== 'anonymous') { +
+ + + rule-node-config.username + + + {{ 'rule-node-config.username-required' | translate }} + + + + rule-node-config.password + + + + {{ 'rule-node-config.password-required' | translate }} + + + + +
{{ 'rule-node-config.credentials-pem-hint' | translate }}
+ + + + + + + + rule-node-config.private-key-password + + + +
+
+ }
diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.html index df0d61fead..c3a1981ebc 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.html @@ -16,40 +16,52 @@ -->
-
- {{ keyText | translate }} - {{ valText | translate }} - -
-
-
- - - - {{ keyRequiredText | translate }} - - - - - - {{ valRequiredText | translate }} - - - + @if (description) { +
+ } + @if (keyValsFormArray().controls.length || !emptyText) { +
+ {{ keyText | translate }} + {{ valText | translate }} +
-
+ } +
+ @for (keyValControl of keyValsFormArray().controls; track $index) { +
+ + + + {{ keyRequiredText | translate }} + + + + + + {{ valRequiredText | translate }} + + + +
+ } @empty { + @if (emptyText) { +
{{emptyText | translate}}
+ } + } + @if (hintText) { +
+ }
- - rule-node-config.endpoint-url-pattern - - - {{ 'rule-node-config.endpoint-url-pattern-required' | translate }} - - rule-node-config.general-pattern-hint - +
+
+
Request URL
+ + rule-node-config.endpoint-url-pattern + + + {{ 'rule-node-config.endpoint-url-pattern-required' | translate }} + + rule-node-config.url-hint + + + + {{ 'rule-node-config.query-params' | translate }} +
+
+ + > + + +
+
rule-node-config.request-method @@ -32,99 +51,113 @@ - - {{ 'rule-node-config.enable-proxy' | translate }} - - - {{ 'rule-node-config.use-simple-client-http-factory' | translate }} - - - {{ 'rule-node-config.parse-to-plain-text' | translate }} - -
rule-node-config.parse-to-plain-text-hint
- - {{ 'rule-node-config.ignore-request-body' | translate }} - -
- - {{ 'rule-node-config.use-system-proxy-properties' | translate }} - -
-
- - rule-node-config.proxy-scheme - - - {{ proxyScheme }} - - - - - rule-node-config.proxy-host - - - {{ 'rule-node-config.proxy-host-required' | translate }} +
+ + + {{ 'rule-node-config.headers' | translate }} + + + + + + +
+ +
+ + + {{ 'rule-node-config.advanced-settings' | translate }} + + +
+ + {{ 'rule-node-config.enable-proxy' | translate }} + +
+ + {{ 'rule-node-config.use-system-proxy-properties' | translate }} + +
+
+ + rule-node-config.proxy-host + + + {{ 'rule-node-config.proxy-host-required' | translate }} + + + + rule-node-config.proxy-port + + + {{ 'rule-node-config.proxy-port-required' | translate }} + + + {{ 'rule-node-config.proxy-port-range' | translate }} + + +
+ + rule-node-config.proxy-user + + + + rule-node-config.proxy-password + + + +
+
+
+
+ +
+ {{ 'rule-node-config.parse-to-plain-text' | translate }} +
+
+
+
+ + {{ 'rule-node-config.ignore-request-body' | translate }} + +
+ + rule-node-config.read-timeout + + rule-node-config.read-timeout-hint + + {{ 'rule-node-config.int-range' | translate }} - - rule-node-config.proxy-port - - - {{ 'rule-node-config.proxy-port-required' | translate }} + + rule-node-config.max-parallel-requests-count + + rule-node-config.max-parallel-requests-count-hint + + {{ 'rule-node-config.int-range' | translate }} + + + rule-node-config.max-response-size + + rule-node-config.max-response-size-hint - {{ 'rule-node-config.proxy-port-range' | translate }} + *ngIf="restApiCallConfigForm.get('maxInMemoryBufferSizeInKb').hasError('min') || restApiCallConfigForm.get('maxInMemoryBufferSizeInKb').hasError('max')"> + {{ 'rule-node-config.memory-buffer-size-range' | translate: { max: MemoryBufferSizeInKbLimit } }} -
- - rule-node-config.proxy-user - - - - rule-node-config.proxy-password - - -
+ +
- - rule-node-config.read-timeout - - rule-node-config.read-timeout-hint - - {{ 'rule-node-config.int-range' | translate }} - - - - rule-node-config.max-parallel-requests-count - - rule-node-config.max-parallel-requests-count-hint - - {{ 'rule-node-config.int-range' | translate }} - - - - rule-node-config.max-response-size - - rule-node-config.max-response-size-hint - - {{ 'rule-node-config.memory-buffer-size-range' | translate: { max: MemoryBufferSizeInKbLimit } }} - - - -
- - -
diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.scss new file mode 100644 index 0000000000..79b42e8eaa --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.scss @@ -0,0 +1,30 @@ +/** + * Copyright © 2016-2025 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. + */ + +:host ::ng-deep { + .mat-expansion-panel-content { + .mat-expansion-panel-body { + .tb-kv-map-config { + margin-bottom: 0; + .body { + .mdc-icon-button { + margin-bottom: 22px; + } + } + } + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.ts index 483b6318d6..d08b97f7de 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.ts @@ -18,21 +18,24 @@ import { Component } from '@angular/core'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; import { HttpRequestType, IntLimit } from '../rule-node-config.models'; +import { isDefinedAndNotNull } from '@core/utils'; @Component({ selector: 'tb-external-node-rest-api-call-config', templateUrl: './rest-api-call-config.component.html', - styleUrls: [] + styleUrls: ['./rest-api-call-config.component.scss'] }) export class RestApiCallConfigComponent extends RuleNodeConfigurationComponent { restApiCallConfigForm: UntypedFormGroup; - readonly proxySchemes: string[] = ['http', 'https']; readonly httpRequestTypes = Object.keys(HttpRequestType); readonly MemoryBufferSizeInKbLimit = 25000; readonly IntLimit = IntLimit; + isHeadersExpanded = false; + isQueryParamsExpanded = false; + constructor(private fb: UntypedFormBuilder) { super(); } @@ -45,12 +48,10 @@ export class RestApiCallConfigComponent extends RuleNodeConfigurationComponent { this.restApiCallConfigForm = this.fb.group({ restEndpointUrlPattern: [configuration ? configuration.restEndpointUrlPattern : null, [Validators.required]], requestMethod: [configuration ? configuration.requestMethod : null, [Validators.required]], - useSimpleClientHttpFactory: [configuration ? configuration.useSimpleClientHttpFactory : false, []], parseToPlainText: [configuration ? configuration.parseToPlainText : false, []], ignoreRequestBody: [configuration ? configuration.ignoreRequestBody : false, []], enableProxy: [configuration ? configuration.enableProxy : false, []], useSystemProxyProperties: [configuration ? configuration.enableProxy : false, []], - proxyScheme: [configuration ? configuration.proxyHost : null, []], proxyHost: [configuration ? configuration.proxyHost : null, []], proxyPort: [configuration ? configuration.proxyPort : null, []], proxyUser: [configuration ? configuration.proxyUser :null, []], @@ -59,16 +60,22 @@ export class RestApiCallConfigComponent extends RuleNodeConfigurationComponent { maxParallelRequestsCount: [configuration ? configuration.maxParallelRequestsCount : null, [Validators.min(0), Validators.max(IntLimit)]], headers: [configuration ? configuration.headers : null, []], credentials: [configuration ? configuration.credentials : null, []], - maxInMemoryBufferSizeInKb: [configuration ? configuration.maxInMemoryBufferSizeInKb : null, [Validators.min(1), Validators.max(this.MemoryBufferSizeInKbLimit)]] + maxInMemoryBufferSizeInKb: [configuration ? configuration.maxInMemoryBufferSizeInKb : null, [Validators.min(1), Validators.max(this.MemoryBufferSizeInKbLimit)]], + queryParams: [configuration ? configuration.queryParams : [], []], }); } protected validatorTriggers(): string[] { - return ['useSimpleClientHttpFactory', 'enableProxy', 'useSystemProxyProperties']; + return ['enableProxy', 'useSystemProxyProperties']; + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + this.isQueryParamsExpanded = configuration && isDefinedAndNotNull(configuration.queryParams) && !!Object.keys(configuration.queryParams).length; + this.isHeadersExpanded = configuration && isDefinedAndNotNull(configuration.headers) && !!Object.keys(configuration.headers).length; + return super.prepareInputConfig(configuration); } protected updateValidators(emitEvent: boolean) { - const useSimpleClientHttpFactory: boolean = this.restApiCallConfigForm.get('useSimpleClientHttpFactory').value; const enableProxy: boolean = this.restApiCallConfigForm.get('enableProxy').value; const useSystemProxyProperties: boolean = this.restApiCallConfigForm.get('useSystemProxyProperties').value; @@ -79,12 +86,7 @@ export class RestApiCallConfigComponent extends RuleNodeConfigurationComponent { } else { this.restApiCallConfigForm.get('proxyHost').setValidators([]); this.restApiCallConfigForm.get('proxyPort').setValidators([]); - - if (useSimpleClientHttpFactory) { - this.restApiCallConfigForm.get('readTimeoutMs').setValidators([]); - } else { - this.restApiCallConfigForm.get('readTimeoutMs').setValidators([Validators.min(0), Validators.max(IntLimit)]); - } + this.restApiCallConfigForm.get('readTimeoutMs').setValidators([Validators.min(0), Validators.max(IntLimit)]); } this.restApiCallConfigForm.get('readTimeoutMs').updateValueAndValidity({emitEvent}); 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 54ea5737f7..5e30e42e97 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -5404,6 +5404,15 @@ "tell-failure-aws-lambda-hint": "Rule node forces failure of message processing if AWS Lambda function execution raises exception.", "basic-mode": "Basic", "advanced-mode": "Advanced", + "url-hint" : "Enter the request URL. Ensure special characters are percent-encoded.", + "query-params": "Query parameters", + "query-params-hint": "Additional query parameters to include in the request URL. Both names and values support templatization and are strictly (RFC 3986) encoded after template resolution.", + "query-params-empty": "No query parameters configured", + "query-params-name": "Name", + "query-params-value": "Value", + "query-params-name-required": "Name is required", + "query-params-value-required": "Value is required", + "headers-empty": "No headers configured", "save-time-series": { "processing-settings": "Processing settings", "processing-settings-hint": "Define how incoming messages are processed. Basic processing settings allow you to select preconfigured strategies, while Advanced settings allow you to select individual processing strategies for each action.", From 44a283a5a2455330624e6ca0579a6ec1b0175ff9 Mon Sep 17 00:00:00 2001 From: Maksym Tsymbarov Date: Fri, 9 Jan 2026 18:00:58 +0200 Subject: [PATCH 020/742] Translation cleanup --- ui-ngx/src/assets/locale/locale.constant-en_US.json | 2 -- 1 file changed, 2 deletions(-) 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 5e30e42e97..419eaf50ac 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -4964,7 +4964,6 @@ "endpoint-url-pattern": "Endpoint URL pattern", "endpoint-url-pattern-required": "Endpoint URL pattern is required", "request-method": "Request method", - "use-simple-client-http-factory": "Use simple client HTTP factory", "ignore-request-body": "Without request body", "parse-to-plain-text": "Parse to plain text", "parse-to-plain-text-hint": "If selected, request body message payload will be transformed from JSON string to plain text, e.g. msg = \"Hello,\\t\"world\"\" will be parsed to Hello, \"world\"", @@ -5120,7 +5119,6 @@ "proxy-port-range": "Proxy port should be in a range from 1 to 65535.", "proxy-user": "Proxy user", "proxy-password": "Proxy password", - "proxy-scheme": "Proxy scheme", "numbers-to-template": "Phone Numbers To Template", "numbers-to-template-required": "Phone Numbers To Template is required", "numbers-to-template-hint": "Comma separated Phone Numbers, use ${metadataKey} for value from metadata, $[messageKey] for value from message body", From 0468451f3ba02983e540e26f968305dd7a2ed04a Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Mon, 12 Jan 2026 10:52:29 +0200 Subject: [PATCH 021/742] added ws update on telemetry deletion --- .../DefaultTbLocalSubscriptionService.java | 4 +-- .../server/controller/WebsocketApiTest.java | 35 +++++++++++++++++++ .../server/common/data/kv/TsKvEntry.java | 5 +++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbLocalSubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbLocalSubscriptionService.java index 51663eea9c..df28da2dad 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbLocalSubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbLocalSubscriptionService.java @@ -348,7 +348,7 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer if (sub.isLatestValues()) { for (TsKvEntry kv : data) { Long stateTs = keyStates.get(kv.getKey()); - if (stateTs == null || kv.getTs() >= stateTs) { + if (stateTs == null || kv.getTs() >= stateTs || kv.isDeletedEntryMarker()) { if (updateData == null) { updateData = new ArrayList<>(); } @@ -362,7 +362,7 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer for (TsKvEntry kv : data) { Long stateTs = keyStates.get(kv.getKey()); if (stateTs != null) { - if (!sub.isLatestValues() || kv.getTs() >= stateTs) { + if (!sub.isLatestValues() || kv.getTs() >= stateTs || kv.isDeletedEntryMarker()) { if (updateData == null) { updateData = new ArrayList<>(); } diff --git a/application/src/test/java/org/thingsboard/server/controller/WebsocketApiTest.java b/application/src/test/java/org/thingsboard/server/controller/WebsocketApiTest.java index 87ba0ec3e8..e88808ad2a 100644 --- a/application/src/test/java/org/thingsboard/server/controller/WebsocketApiTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/WebsocketApiTest.java @@ -726,6 +726,41 @@ public class WebsocketApiTest extends AbstractControllerTest { Assert.assertNull(msg); } + @Test + public void testShouldSendWsUpdateMessageWhenTelemetryWasDeleted() throws Exception { + long now = System.currentTimeMillis() - 100; + TsKvEntry dataPoint = new BasicTsKvEntry(now, new LongDataEntry("temperature", 42L)); + List tsData = List.of(dataPoint); + sendTelemetry(device, tsData); + + List keys = List.of(new EntityKey(EntityKeyType.TIME_SERIES, "temperature")); + EntityDataUpdate update = getWsClient().subscribeLatestUpdate(keys, dtf); + + Assert.assertEquals(1, update.getCmdId()); + PageData pageData = update.getData(); + Assert.assertNotNull(pageData); + Assert.assertEquals(1, pageData.getData().size()); + Assert.assertEquals(device.getId(), pageData.getData().get(0).getEntityId()); + Assert.assertNotNull(pageData.getData().get(0).getLatest().get(EntityKeyType.TIME_SERIES).get("temperature")); + Assert.assertEquals(now, pageData.getData().get(0).getLatest().get(EntityKeyType.TIME_SERIES).get("temperature").getTs()); + Assert.assertEquals("42", pageData.getData().get(0).getLatest().get(EntityKeyType.TIME_SERIES).get("temperature").getValue()); + + // delete telemetry + getWsClient().registerWaitForUpdate(); + doDeleteAsync("/api/plugins/telemetry/DEVICE/" + device.getId() + "/timeseries/delete?keys=temperature&deleteAllDataForKeys=true", String.class); + update = getWsClient().parseDataReply(getWsClient().waitForUpdate()); + + Assert.assertEquals(1, update.getCmdId()); + + List listData = update.getUpdate(); + Assert.assertNotNull(listData); + Assert.assertEquals(1, listData.size()); + Assert.assertEquals(device.getId(), listData.get(0).getEntityId()); + Assert.assertNotNull(listData.get(0).getLatest().get(EntityKeyType.TIME_SERIES)); + TsValue tsValue = listData.get(0).getLatest().get(EntityKeyType.TIME_SERIES).get("temperature"); + Assert.assertEquals(new TsValue(0, ""), tsValue); + } + @Test public void testEntityDataLatestAttrWsCmd() throws Exception { long now = System.currentTimeMillis(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/kv/TsKvEntry.java b/common/data/src/main/java/org/thingsboard/server/common/data/kv/TsKvEntry.java index cb4092f433..eca0609704 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/kv/TsKvEntry.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/kv/TsKvEntry.java @@ -37,4 +37,9 @@ public interface TsKvEntry extends KvEntry, HasVersion { return new TsValue(getTs(), getValueAsString()); } + @JsonIgnore + default boolean isDeletedEntryMarker() { + return getTs() == 0 && (getValue() == null || getValueAsString().isEmpty()); + } + } From af3ef1d5cecb7859a0f0fc3349071471b7b9866e Mon Sep 17 00:00:00 2001 From: Maksym Tsymbarov Date: Mon, 12 Jan 2026 13:52:09 +0200 Subject: [PATCH 022/742] Fixed set config logic --- .../rule-node/external/rest-api-call-config.component.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.ts index d08b97f7de..42685f2ca7 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.ts @@ -75,6 +75,11 @@ export class RestApiCallConfigComponent extends RuleNodeConfigurationComponent { return super.prepareInputConfig(configuration); } + protected prepareOutputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + configuration.queryParams = isDefinedAndNotNull(configuration.queryParams) ? configuration.queryParams : []; + return super.prepareOutputConfig(configuration); + } + protected updateValidators(emitEvent: boolean) { const enableProxy: boolean = this.restApiCallConfigForm.get('enableProxy').value; const useSystemProxyProperties: boolean = this.restApiCallConfigForm.get('useSystemProxyProperties').value; From 49c34ebe91f20fa65fed267f9509f15b783c4156 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Thu, 15 Jan 2026 17:33:12 +0200 Subject: [PATCH 023/742] Use min value from tenant profile for scheduled update interval when not provided --- ...SupportedCalculatedFieldConfiguration.java | 8 +- ...gregationCalculatedFieldConfiguration.java | 2 +- ...eofencingCalculatedFieldConfiguration.java | 5 +- ...ncingCalculatedFieldConfigurationTest.java | 14 ++ .../dao/cf/BaseCalculatedFieldService.java | 14 ++ .../service/CalculatedFieldServiceTest.java | 169 +++++++++++++++++- 6 files changed, 201 insertions(+), 11 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/ScheduledUpdateSupportedCalculatedFieldConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/ScheduledUpdateSupportedCalculatedFieldConfiguration.java index f5b45c6d5c..f78ff72af0 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/ScheduledUpdateSupportedCalculatedFieldConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/ScheduledUpdateSupportedCalculatedFieldConfiguration.java @@ -22,14 +22,14 @@ public interface ScheduledUpdateSupportedCalculatedFieldConfiguration extends Ca boolean isScheduledUpdateEnabled(); @PositiveOrZero - int getScheduledUpdateInterval(); + Integer getScheduledUpdateInterval(); - void setScheduledUpdateInterval(int interval); + void setScheduledUpdateInterval(Integer interval); default void validate(long minAllowedScheduledUpdateInterval) { if (getScheduledUpdateInterval() < minAllowedScheduledUpdateInterval) { - throw new IllegalArgumentException("Scheduled update interval is less than configured " + - "minimum allowed interval in tenant profile: " + minAllowedScheduledUpdateInterval); + throw new IllegalArgumentException("Scheduled update interval (" + getScheduledUpdateInterval() + + " seconds) is less than minimum allowed interval in tenant profile: " + minAllowedScheduledUpdateInterval + " seconds"); } } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/aggregation/RelatedEntitiesAggregationCalculatedFieldConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/aggregation/RelatedEntitiesAggregationCalculatedFieldConfiguration.java index 3b0df7ed82..98b4b691e3 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/aggregation/RelatedEntitiesAggregationCalculatedFieldConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/aggregation/RelatedEntitiesAggregationCalculatedFieldConfiguration.java @@ -44,7 +44,7 @@ public class RelatedEntitiesAggregationCalculatedFieldConfiguration implements A private Output output; private boolean useLatestTs; - private int scheduledUpdateInterval; + private Integer scheduledUpdateInterval; @Override public CalculatedFieldType getType() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/geofencing/GeofencingCalculatedFieldConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/geofencing/GeofencingCalculatedFieldConfiguration.java index 2d1abd0024..c85604d2ab 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/geofencing/GeofencingCalculatedFieldConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/geofencing/GeofencingCalculatedFieldConfiguration.java @@ -46,7 +46,7 @@ public class GeofencingCalculatedFieldConfiguration implements ArgumentsBasedCal private Map zoneGroups; private boolean scheduledUpdateEnabled; - private int scheduledUpdateInterval; + private Integer scheduledUpdateInterval; private Output output; @@ -79,6 +79,9 @@ public class GeofencingCalculatedFieldConfiguration implements ArgumentsBasedCal @Override public void validate() { + if (scheduledUpdateEnabled && scheduledUpdateInterval == null) { + throw new IllegalArgumentException("Refresh interval is required when periodic zone group refresh is enabled."); + } zoneGroups.forEach((key, value) -> value.validate(key)); } diff --git a/common/data/src/test/java/org/thingsboard/server/common/data/cf/configuration/geofencing/GeofencingCalculatedFieldConfigurationTest.java b/common/data/src/test/java/org/thingsboard/server/common/data/cf/configuration/geofencing/GeofencingCalculatedFieldConfigurationTest.java index 2f391435b2..2c68bcd8c5 100644 --- a/common/data/src/test/java/org/thingsboard/server/common/data/cf/configuration/geofencing/GeofencingCalculatedFieldConfigurationTest.java +++ b/common/data/src/test/java/org/thingsboard/server/common/data/cf/configuration/geofencing/GeofencingCalculatedFieldConfigurationTest.java @@ -28,6 +28,7 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.thingsboard.server.common.data.cf.configuration.geofencing.EntityCoordinates.ENTITY_ID_LATITUDE_ARGUMENT_KEY; @@ -103,4 +104,17 @@ public class GeofencingCalculatedFieldConfigurationTest { assertThat(allowedZonesArgument.getRefEntityKey()).isEqualTo(new ReferencedEntityKey("perimeter", ArgumentType.ATTRIBUTE, AttributeScope.SERVER_SCOPE)); } + @Test + void validateShouldThrowWhenScheduledUpdateEnabledButIntervalNotSet() { + var cfg = new GeofencingCalculatedFieldConfiguration(); + cfg.setEntityCoordinates(mock(EntityCoordinates.class)); + cfg.setZoneGroups(Map.of("zone", mock(ZoneGroupConfiguration.class))); + cfg.setScheduledUpdateEnabled(true); + cfg.setScheduledUpdateInterval(null); + + assertThatThrownBy(cfg::validate) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Refresh interval is required when periodic zone group refresh is enabled."); + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/cf/BaseCalculatedFieldService.java b/dao/src/main/java/org/thingsboard/server/dao/cf/BaseCalculatedFieldService.java index 00c5ec372e..075e2d8a9d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/cf/BaseCalculatedFieldService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/cf/BaseCalculatedFieldService.java @@ -26,18 +26,21 @@ import org.thingsboard.server.common.data.cf.CalculatedFieldFilter; import org.thingsboard.server.common.data.cf.CalculatedFieldInfo; import org.thingsboard.server.common.data.cf.CalculatedFieldType; import org.thingsboard.server.common.data.cf.configuration.CalculatedFieldConfiguration; +import org.thingsboard.server.common.data.cf.configuration.aggregation.RelatedEntitiesAggregationCalculatedFieldConfiguration; import org.thingsboard.server.common.data.id.CalculatedFieldId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.HasId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.entity.EntityService; import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent; import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.service.validator.CalculatedFieldDataValidator; +import org.thingsboard.server.dao.usagerecord.ApiLimitService; import java.util.EnumSet; import java.util.List; @@ -62,6 +65,7 @@ public class BaseCalculatedFieldService extends AbstractEntityService implements private final EntityService entityService; private final CalculatedFieldDao calculatedFieldDao; private final CalculatedFieldDataValidator calculatedFieldDataValidator; + private final ApiLimitService apiLimitService; @Override public CalculatedField save(CalculatedField calculatedField) { @@ -70,6 +74,7 @@ public class BaseCalculatedFieldService extends AbstractEntityService implements @Override public CalculatedField save(CalculatedField calculatedField, boolean doValidate) { + setConfigurationDefaults(calculatedField); CalculatedField oldCalculatedField = null; if (doValidate) { oldCalculatedField = calculatedFieldDataValidator.validate(calculatedField, CalculatedField::getTenantId); @@ -79,6 +84,15 @@ public class BaseCalculatedFieldService extends AbstractEntityService implements return doSave(calculatedField, oldCalculatedField); } + private void setConfigurationDefaults(CalculatedField calculatedField) { + if (calculatedField.getConfiguration() instanceof RelatedEntitiesAggregationCalculatedFieldConfiguration config + && config.getScheduledUpdateInterval() == null) { + int minScheduledUpdateInterval = (int) apiLimitService.getLimit( + calculatedField.getTenantId(), DefaultTenantProfileConfiguration::getMinAllowedScheduledUpdateIntervalInSecForCF + ); + config.setScheduledUpdateInterval(minScheduledUpdateInterval); + } + } private CalculatedField doSave(CalculatedField calculatedField, CalculatedField oldCalculatedField) { try { diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/CalculatedFieldServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/CalculatedFieldServiceTest.java index 97e06ed879..afb380c5be 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/CalculatedFieldServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/CalculatedFieldServiceTest.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.service; +import org.apache.commons.lang3.RandomUtils; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.server.common.data.Device; @@ -27,6 +28,10 @@ import org.thingsboard.server.common.data.cf.configuration.ReferencedEntityKey; import org.thingsboard.server.common.data.cf.configuration.RelationPathQueryDynamicSourceConfiguration; import org.thingsboard.server.common.data.cf.configuration.SimpleCalculatedFieldConfiguration; import org.thingsboard.server.common.data.cf.configuration.TimeSeriesOutput; +import org.thingsboard.server.common.data.cf.configuration.aggregation.AggFunction; +import org.thingsboard.server.common.data.cf.configuration.aggregation.AggKeyInput; +import org.thingsboard.server.common.data.cf.configuration.aggregation.AggMetric; +import org.thingsboard.server.common.data.cf.configuration.aggregation.RelatedEntitiesAggregationCalculatedFieldConfiguration; import org.thingsboard.server.common.data.cf.configuration.geofencing.EntityCoordinates; import org.thingsboard.server.common.data.cf.configuration.geofencing.GeofencingCalculatedFieldConfiguration; import org.thingsboard.server.common.data.cf.configuration.geofencing.ZoneGroupConfiguration; @@ -36,8 +41,8 @@ import org.thingsboard.server.common.data.relation.EntitySearchDirection; import org.thingsboard.server.common.data.relation.RelationPathLevel; import org.thingsboard.server.dao.cf.CalculatedFieldService; import org.thingsboard.server.dao.device.DeviceService; -import org.thingsboard.server.exception.DataValidationException; import org.thingsboard.server.dao.tenant.TbTenantProfileCache; +import org.thingsboard.server.exception.DataValidationException; import java.util.ArrayList; import java.util.List; @@ -107,11 +112,11 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest { int min = tbTenantProfileCache.get(tenantId) .getDefaultProfileConfiguration() .getMinAllowedScheduledUpdateIntervalInSecForCF(); - int valueFromConfig = min - 10; // Enable scheduling with an interval below tenant min cfg.setScheduledUpdateEnabled(true); - cfg.setScheduledUpdateInterval(valueFromConfig); + int invalidInterval = RandomUtils.insecure().randomInt(1, min); + cfg.setScheduledUpdateInterval(invalidInterval); // Create & save Calculated Field CalculatedField cf = new CalculatedField(); @@ -125,8 +130,8 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest { assertThatThrownBy(() -> calculatedFieldService.save(cf)) .isInstanceOf(DataValidationException.class) .hasCauseInstanceOf(IllegalArgumentException.class) - .hasMessageStartingWith("Scheduled update interval is less than configured " + - "minimum allowed interval in tenant profile: "); + .hasMessage("Scheduled update interval (" + invalidInterval + + " seconds) is less than minimum allowed interval in tenant profile: " + min + " seconds"); } @Test @@ -253,6 +258,160 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest { assertThat(calculatedFieldService.findById(tenantId, savedCalculatedField.getId())).isNull(); } + @Test + public void testSaveRelatedEntitiesAggregationCF_shouldUseMinScheduledUpdateIntervalFromTenantProfileWhenNotSet() { + // GIVEN + var device = createTestDevice(); + + var cfg = new RelatedEntitiesAggregationCalculatedFieldConfiguration(); + cfg.setRelation(new RelationPathLevel(EntitySearchDirection.FROM, EntityRelation.CONTAINS_TYPE)); + + var argument = new Argument(); + argument.setRefEntityKey(new ReferencedEntityKey("temperature", ArgumentType.TS_LATEST, null)); + cfg.setArguments(Map.of("temp", argument)); + + var metric = new AggMetric(); + metric.setFunction(AggFunction.AVG); + metric.setInput(new AggKeyInput("temp")); + cfg.setMetrics(Map.of("avgTemp", metric)); + + var output = new TimeSeriesOutput(); + output.setName("avgTemperature"); + cfg.setOutput(output); + + int minDeduplicationInterval = (int) tbTenantProfileCache.get(tenantId) + .getDefaultProfileConfiguration() + .getMinAllowedDeduplicationIntervalInSecForCF(); + cfg.setDeduplicationIntervalInSec(minDeduplicationInterval); + + // Do NOT set scheduledUpdateInterval - it should default to tenant profile min value + + var cf = new CalculatedField(); + cf.setTenantId(tenantId); + cf.setEntityId(device.getId()); + cf.setType(CalculatedFieldType.RELATED_ENTITIES_AGGREGATION); + cf.setName("Related Entities Aggregation CF - default scheduled interval test"); + cf.setConfigurationVersion(0); + cf.setConfiguration(cfg); + + // WHEN + CalculatedField saved = calculatedFieldService.save(cf); + + // THEN + assertThat(saved).isNotNull(); + assertThat(saved.getConfiguration()).isInstanceOf(RelatedEntitiesAggregationCalculatedFieldConfiguration.class); + + var savedConfig = (RelatedEntitiesAggregationCalculatedFieldConfiguration) saved.getConfiguration(); + int expectedMinScheduledUpdateInterval = tbTenantProfileCache.get(tenantId) + .getDefaultProfileConfiguration() + .getMinAllowedScheduledUpdateIntervalInSecForCF(); + + assertThat(savedConfig.getScheduledUpdateInterval()).isEqualTo(expectedMinScheduledUpdateInterval); + + calculatedFieldService.deleteCalculatedField(tenantId, saved.getId()); + } + + @Test + public void testSaveRelatedEntitiesAggregationCF_shouldThrowWhenScheduledUpdateIntervalLessThanMinAllowed() { + // GIVEN + var device = createTestDevice(); + + var cfg = new RelatedEntitiesAggregationCalculatedFieldConfiguration(); + cfg.setRelation(new RelationPathLevel(EntitySearchDirection.FROM, EntityRelation.CONTAINS_TYPE)); + + var argument = new Argument(); + argument.setRefEntityKey(new ReferencedEntityKey("temperature", ArgumentType.TS_LATEST, null)); + cfg.setArguments(Map.of("temp", argument)); + + var metric = new AggMetric(); + metric.setFunction(AggFunction.AVG); + metric.setInput(new AggKeyInput("temp")); + cfg.setMetrics(Map.of("avgTemp", metric)); + + var output = new TimeSeriesOutput(); + output.setName("avgTemperature"); + cfg.setOutput(output); + + int minDeduplicationInterval = (int) tbTenantProfileCache.get(tenantId) + .getDefaultProfileConfiguration() + .getMinAllowedDeduplicationIntervalInSecForCF(); + cfg.setDeduplicationIntervalInSec(minDeduplicationInterval); + + int minScheduledUpdateInterval = tbTenantProfileCache.get(tenantId) + .getDefaultProfileConfiguration() + .getMinAllowedScheduledUpdateIntervalInSecForCF(); + int invalidInterval = RandomUtils.insecure().randomInt(1, minScheduledUpdateInterval); + cfg.setScheduledUpdateInterval(invalidInterval); + + var cf = new CalculatedField(); + cf.setTenantId(tenantId); + cf.setEntityId(device.getId()); + cf.setType(CalculatedFieldType.RELATED_ENTITIES_AGGREGATION); + cf.setName("Related Entities Aggregation CF - invalid scheduled interval test"); + cf.setConfigurationVersion(0); + cf.setConfiguration(cfg); + + // WHEN-THEN + assertThatThrownBy(() -> calculatedFieldService.save(cf)) + .isInstanceOf(DataValidationException.class) + .hasCauseInstanceOf(IllegalArgumentException.class) + .hasMessage("Scheduled update interval (" + invalidInterval + + " seconds) is less than minimum allowed interval in tenant profile: " + minScheduledUpdateInterval + " seconds"); + } + + @Test + public void testSaveRelatedEntitiesAggregationCF_shouldAcceptValidScheduledUpdateInterval() { + // GIVEN + var device = createTestDevice(); + + var cfg = new RelatedEntitiesAggregationCalculatedFieldConfiguration(); + cfg.setRelation(new RelationPathLevel(EntitySearchDirection.FROM, EntityRelation.CONTAINS_TYPE)); + + var argument = new Argument(); + argument.setRefEntityKey(new ReferencedEntityKey("temperature", ArgumentType.TS_LATEST, null)); + cfg.setArguments(Map.of("temp", argument)); + + var metric = new AggMetric(); + metric.setFunction(AggFunction.AVG); + metric.setInput(new AggKeyInput("temp")); + cfg.setMetrics(Map.of("avgTemp", metric)); + + var output = new TimeSeriesOutput(); + output.setName("avgTemperature"); + cfg.setOutput(output); + + int minDeduplicationInterval = (int) tbTenantProfileCache.get(tenantId) + .getDefaultProfileConfiguration() + .getMinAllowedDeduplicationIntervalInSecForCF(); + cfg.setDeduplicationIntervalInSec(minDeduplicationInterval); + + int minScheduledUpdateInterval = tbTenantProfileCache.get(tenantId) + .getDefaultProfileConfiguration() + .getMinAllowedScheduledUpdateIntervalInSecForCF(); + int customScheduledUpdateInterval = minScheduledUpdateInterval + 100; + cfg.setScheduledUpdateInterval(customScheduledUpdateInterval); + + var cf = new CalculatedField(); + cf.setTenantId(tenantId); + cf.setEntityId(device.getId()); + cf.setType(CalculatedFieldType.RELATED_ENTITIES_AGGREGATION); + cf.setName("Related Entities Aggregation CF - valid scheduled interval test"); + cf.setConfigurationVersion(0); + cf.setConfiguration(cfg); + + // WHEN + CalculatedField saved = calculatedFieldService.save(cf); + + // THEN + assertThat(saved).isNotNull(); + assertThat(saved.getConfiguration()).isInstanceOf(RelatedEntitiesAggregationCalculatedFieldConfiguration.class); + + var savedConfig = (RelatedEntitiesAggregationCalculatedFieldConfiguration) saved.getConfiguration(); + assertThat(savedConfig.getScheduledUpdateInterval()).isEqualTo(customScheduledUpdateInterval); + + calculatedFieldService.deleteCalculatedField(tenantId, saved.getId()); + } + private CalculatedField saveValidCalculatedField() { Device device = createTestDevice(); CalculatedField calculatedField = getCalculatedField(device.getId(), device.getId()); From 231b2fe8bc178f075ff66b5b3d05b8e74f2f88d6 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Thu, 15 Jan 2026 18:07:35 +0200 Subject: [PATCH 024/742] Add validation for min scheduled update interval in tenant profile --- .../DefaultTenantProfileConfiguration.java | 2 + .../TenantProfileDataValidatorTest.java | 56 +++++++++++++++++-- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java index a04816365b..297f92cffb 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java @@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.tenant.profile; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -173,6 +174,7 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura @Schema(example = "10") private long maxArgumentsPerCF = 10; @Schema(example = "10") + @PositiveOrZero private int minAllowedScheduledUpdateIntervalInSecForCF = 10; @Builder.Default @Schema(example = "2") diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/TenantProfileDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/TenantProfileDataValidatorTest.java index 170b452fee..373344cb6d 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/TenantProfileDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/TenantProfileDataValidatorTest.java @@ -16,29 +16,35 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import org.thingsboard.server.common.data.tenant.profile.TenantProfileData; import org.thingsboard.server.dao.tenant.TenantProfileDao; import org.thingsboard.server.dao.tenant.TenantProfileService; +import org.thingsboard.server.exception.DataValidationException; import java.util.UUID; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.verify; @SpringBootTest(classes = TenantProfileDataValidator.class) class TenantProfileDataValidatorTest { - @MockBean + @MockitoBean TenantProfileDao tenantProfileDao; - @MockBean + @MockitoBean TenantProfileService tenantProfileService; - @SpyBean + @MockitoSpyBean TenantProfileDataValidator validator; + TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da")); @Test @@ -53,4 +59,44 @@ class TenantProfileDataValidatorTest { verify(validator).validateString("Tenant profile name", tenantProfile.getName()); } + @ParameterizedTest + @ValueSource(ints = {-1, -100, Integer.MIN_VALUE}) + void minAllowedScheduledUpdateIntervalInSecForCF_shouldRejectNegativeValues(int value) { + // GIVEN + var config = new DefaultTenantProfileConfiguration(); + config.setMinAllowedScheduledUpdateIntervalInSecForCF(value); + + var tenantProfileData = new TenantProfileData(); + tenantProfileData.setConfiguration(config); + + var tenantProfile = new TenantProfile(); + tenantProfile.setName("Test"); + tenantProfile.setProfileData(tenantProfileData); + + // WHEN/THEN + assertThatThrownBy(() -> validator.validate(tenantProfile, __ -> TenantId.SYS_TENANT_ID)) + .isInstanceOf(DataValidationException.class) + .hasMessageContaining("minAllowedScheduledUpdateIntervalInSecForCF") + .hasMessageContaining("must be greater than or equal to 0"); + } + + @ParameterizedTest + @ValueSource(ints = {0, 1, 60, Integer.MAX_VALUE}) + void minAllowedScheduledUpdateIntervalInSecForCF_shouldAcceptValidValues(int value) { + // GIVEN + var config = new DefaultTenantProfileConfiguration(); + config.setMinAllowedScheduledUpdateIntervalInSecForCF(value); + + var tenantProfileData = new TenantProfileData(); + tenantProfileData.setConfiguration(config); + + var tenantProfile = new TenantProfile(); + tenantProfile.setName("Test"); + tenantProfile.setProfileData(tenantProfileData); + + // WHEN/THEN + assertThatCode(() -> validator.validate(tenantProfile, __ -> TenantId.SYS_TENANT_ID)) + .doesNotThrowAnyException(); + } + } From b688ca1dcdac48a4f04daad9249a148dfc24242b Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Fri, 16 Jan 2026 09:32:52 +0200 Subject: [PATCH 025/742] Add tests for zero min scheduled update interval --- ...ortedCalculatedFieldConfigurationTest.java | 4 +- .../dao/service/AbstractServiceTest.java | 4 +- .../service/CalculatedFieldServiceTest.java | 69 ++++++++++++++++--- 3 files changed, 65 insertions(+), 12 deletions(-) diff --git a/common/data/src/test/java/org/thingsboard/server/common/data/cf/configuration/ScheduledUpdateSupportedCalculatedFieldConfigurationTest.java b/common/data/src/test/java/org/thingsboard/server/common/data/cf/configuration/ScheduledUpdateSupportedCalculatedFieldConfigurationTest.java index 23e0f1add3..a2df32b483 100644 --- a/common/data/src/test/java/org/thingsboard/server/common/data/cf/configuration/ScheduledUpdateSupportedCalculatedFieldConfigurationTest.java +++ b/common/data/src/test/java/org/thingsboard/server/common/data/cf/configuration/ScheduledUpdateSupportedCalculatedFieldConfigurationTest.java @@ -47,8 +47,8 @@ public class ScheduledUpdateSupportedCalculatedFieldConfigurationTest { assertThatThrownBy(() -> cfg.validate(minAllowedInterval)) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Scheduled update interval is less than configured " + - "minimum allowed interval in tenant profile: " + minAllowedInterval); + .hasMessage("Scheduled update interval (1 seconds) is less than " + + "minimum allowed interval in tenant profile: " + minAllowedInterval + " seconds"); } } diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java index 9a467071ef..5ee9af6292 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java @@ -93,11 +93,13 @@ public abstract class AbstractServiceTest { @Autowired protected EntityServiceRegistry entityServiceRegistry; + protected Tenant tenant; protected TenantId tenantId; @Before public void beforeAbstractService() { - tenantId = createTenant().getId(); + tenant = createTenant(); + tenantId = tenant.getId(); } @After diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/CalculatedFieldServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/CalculatedFieldServiceTest.java index afb380c5be..b5bc51537c 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/CalculatedFieldServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/CalculatedFieldServiceTest.java @@ -19,6 +19,7 @@ import org.apache.commons.lang3.RandomUtils; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.cf.CalculatedField; import org.thingsboard.server.common.data.cf.CalculatedFieldType; import org.thingsboard.server.common.data.cf.configuration.Argument; @@ -42,6 +43,7 @@ import org.thingsboard.server.common.data.relation.RelationPathLevel; import org.thingsboard.server.dao.cf.CalculatedFieldService; import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.tenant.TbTenantProfileCache; +import org.thingsboard.server.dao.tenant.TenantProfileService; import org.thingsboard.server.exception.DataValidationException; import java.util.ArrayList; @@ -62,6 +64,8 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest { private DeviceService deviceService; @Autowired private TbTenantProfileCache tbTenantProfileCache; + @Autowired + private TenantProfileService tenantProfileService; @Test public void testSaveCalculatedField() { @@ -85,8 +89,6 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest { assertThat(updatedCalculatedField.getName()).isEqualTo(savedCalculatedField.getName()); assertThat(updatedCalculatedField.getVersion()).isEqualTo(savedCalculatedField.getVersion() + 1); - - calculatedFieldService.deleteCalculatedField(tenantId, savedCalculatedField.getId()); } @Test @@ -224,8 +226,63 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest { int savedInterval = geofencingCalculatedFieldConfiguration.getScheduledUpdateInterval(); assertThat(savedInterval).isEqualTo(valueFromConfig); + } - calculatedFieldService.deleteCalculatedField(tenantId, saved.getId()); + @Test + public void testSaveGeofencingCalculatedField_shouldAcceptZeroScheduledUpdateIntervalWhenTenantProfileAllows() { + // GIVEN + var device = createTestDevice(); + + // Store original value and update tenant profile to allow 0 as min scheduled update interval + TenantProfile tenantProfile = tenantProfileService.findTenantProfileById(tenantId, tenant.getTenantProfileId()); + int originalMinScheduledUpdateInterval = tenantProfile.getDefaultProfileConfiguration().getMinAllowedScheduledUpdateIntervalInSecForCF(); + tenantProfile.getDefaultProfileConfiguration().setMinAllowedScheduledUpdateIntervalInSecForCF(0); + tenantProfileService.saveTenantProfile(tenantId, tenantProfile); + tbTenantProfileCache.evict(tenantProfile.getId()); + + try { + // Build a valid Geofencing configuration + var cfg = new GeofencingCalculatedFieldConfiguration(); + + // Coordinates: TS_LATEST, no dynamic source + var entityCoordinates = new EntityCoordinates("latitude", "longitude"); + cfg.setEntityCoordinates(entityCoordinates); + + // Zone-group argument (ATTRIBUTE) — make it DYNAMIC so scheduling is enabled + var zoneGroupConfiguration = new ZoneGroupConfiguration("allowed", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false); + var dynamicSourceConfiguration = new RelationPathQueryDynamicSourceConfiguration(); + dynamicSourceConfiguration.setLevels(List.of(new RelationPathLevel(EntitySearchDirection.FROM, EntityRelation.CONTAINS_TYPE))); + zoneGroupConfiguration.setRefDynamicSourceConfiguration(dynamicSourceConfiguration); + cfg.setZoneGroups(Map.of("allowed", zoneGroupConfiguration)); + + // Enable scheduling with interval = 0 + cfg.setScheduledUpdateEnabled(true); + cfg.setScheduledUpdateInterval(0); + + // Create Calculated Field + var cf = new CalculatedField(); + cf.setTenantId(tenantId); + cf.setEntityId(device.getId()); + cf.setType(CalculatedFieldType.GEOFENCING); + cf.setName("GF zero scheduled update interval test"); + cf.setConfigurationVersion(0); + cf.setConfiguration(cfg); + + // WHEN + CalculatedField saved = calculatedFieldService.save(cf); + + // THEN + assertThat(saved).isNotNull(); + assertThat(saved.getConfiguration()).isInstanceOf(GeofencingCalculatedFieldConfiguration.class); + + var savedConfig = (GeofencingCalculatedFieldConfiguration) saved.getConfiguration(); + assertThat(savedConfig.getScheduledUpdateInterval()).isEqualTo(0); + } finally { + // Restore original tenant profile value + tenantProfile.getProfileConfiguration().orElseThrow().setMinAllowedScheduledUpdateIntervalInSecForCF(originalMinScheduledUpdateInterval); + tenantProfileService.saveTenantProfile(tenantId, tenantProfile); + tbTenantProfileCache.evict(tenantProfile.getId()); + } } @Test @@ -245,8 +302,6 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest { CalculatedField fetchedCalculatedField = calculatedFieldService.findById(tenantId, savedCalculatedField.getId()); assertThat(fetchedCalculatedField).isEqualTo(savedCalculatedField); - - calculatedFieldService.deleteCalculatedField(tenantId, savedCalculatedField.getId()); } @Test @@ -307,8 +362,6 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest { .getMinAllowedScheduledUpdateIntervalInSecForCF(); assertThat(savedConfig.getScheduledUpdateInterval()).isEqualTo(expectedMinScheduledUpdateInterval); - - calculatedFieldService.deleteCalculatedField(tenantId, saved.getId()); } @Test @@ -408,8 +461,6 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest { var savedConfig = (RelatedEntitiesAggregationCalculatedFieldConfiguration) saved.getConfiguration(); assertThat(savedConfig.getScheduledUpdateInterval()).isEqualTo(customScheduledUpdateInterval); - - calculatedFieldService.deleteCalculatedField(tenantId, saved.getId()); } private CalculatedField saveValidCalculatedField() { From 1bd9b8d287a237ab35397aa329b082556424382c Mon Sep 17 00:00:00 2001 From: Maksym Tsymbarov Date: Fri, 16 Jan 2026 15:01:18 +0200 Subject: [PATCH 026/742] Added component for query params --- .../common/common-rule-node-config.module.ts | 7 +- .../common/kv-list-config.component.ts | 89 +++++++++++++++++++ .../common/kv-map-config-old.component.ts | 6 +- .../rest-api-call-config.component.html | 9 +- .../assets/locale/locale.constant-en_US.json | 1 + 5 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/kv-list-config.component.ts diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/common-rule-node-config.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/common-rule-node-config.module.ts index c7d8ce2723..e21f0aa689 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/common-rule-node-config.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/common-rule-node-config.module.ts @@ -34,6 +34,7 @@ import { SelectAttributesComponent } from './select-attributes.component'; import { AlarmStatusSelectComponent } from './alarm-status-select.component'; import { ExampleHintComponent } from './example-hint.component'; import { TimeUnitInputComponent } from './time-unit-input.component'; +import { KvListConfigComponent } from '@home/components/rule-node/common/kv-list-config.component'; @NgModule({ declarations: [ @@ -52,7 +53,8 @@ import { TimeUnitInputComponent } from './time-unit-input.component'; SelectAttributesComponent, AlarmStatusSelectComponent, ExampleHintComponent, - TimeUnitInputComponent + TimeUnitInputComponent, + KvListConfigComponent ], imports: [ CommonModule, @@ -75,7 +77,8 @@ import { TimeUnitInputComponent } from './time-unit-input.component'; SelectAttributesComponent, AlarmStatusSelectComponent, ExampleHintComponent, - TimeUnitInputComponent + TimeUnitInputComponent, + KvListConfigComponent ] }) diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-list-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-list-config.component.ts new file mode 100644 index 0000000000..5284b88bce --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-list-config.component.ts @@ -0,0 +1,89 @@ +/// +/// Copyright © 2016-2025 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. +/// + +import { Component, forwardRef, Input, OnInit } from '@angular/core'; +import { + AbstractControl, + ControlValueAccessor, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + Validator, + Validators +} from '@angular/forms'; +import { KvMapConfigOldComponent } from '@home/components/rule-node/common/kv-map-config-old.component'; + +@Component({ + selector: 'tb-kv-list-config', + templateUrl: './kv-map-config-old.component.html', + styleUrls: ['./kv-map-config-old.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => KvListConfigComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => KvListConfigComponent), + multi: true, + } + ] +}) +export class KvListConfigComponent extends KvMapConfigOldComponent implements ControlValueAccessor, OnInit, Validator{ + + @Input() keyProperty: string = 'key'; + + override writeValue(kvList: any): void { + const keyValsControls: Array = []; + if (Array.isArray(kvList) && kvList.length > 0) { + for (const property of kvList) { + keyValsControls.push(this.fb.group({ + key: [property[this.keyProperty], [Validators.required]], + value: [property.value, [Validators.required]] + })) + } + } + this.kvListFormGroup.setControl('keyVals', this.fb.array(keyValsControls), {emitEvent: false}); + } + + public override validate() { + const kvList: { key: string; value: string }[] = this.kvListFormGroup.get('keyVals').value; + if (!kvList.length && this.required) { + return { + kvMapRequired: true + }; + } + if (!this.kvListFormGroup.valid) { + return { + kvFieldsRequired: true + }; + } + return null; + } + + protected override updateModel() { + const kvList: { key: string; value: string }[] = this.kvListFormGroup.get('keyVals').value; + if (this.required && !kvList.length || !this.kvListFormGroup.valid) { + this.propagateChange(null); + } else { + const result = kvList.map(entry => ({ + [this.keyProperty]: entry.key, + value: entry.value + })); + this.propagateChange(result); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.ts index bd56212d4f..69fe1820eb 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.ts @@ -86,11 +86,11 @@ export class KvMapConfigOldComponent extends PageComponent implements ControlVal ngControl: NgControl; - private propagateChange = null; + public propagateChange = null; constructor(public translate: TranslateService, private injector: Injector, - private fb: FormBuilder, + protected fb: FormBuilder, private destroyRef: DestroyRef) { super(); } @@ -182,7 +182,7 @@ export class KvMapConfigOldComponent extends PageComponent implements ControlVal return null; } - private updateModel() { + protected updateModel() { const kvList: { key: string; value: string }[] = this.kvListFormGroup.get('keyVals').value; if (this.required && !kvList.length || !this.kvListFormGroup.valid) { this.propagateChange(null); diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.html index b265b997ac..7a30723f9e 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.html @@ -19,7 +19,7 @@
Request URL
- rule-node-config.endpoint-url-pattern + rule-node-config.url {{ 'rule-node-config.endpoint-url-pattern-required' | translate }} @@ -32,14 +32,15 @@
- > - + emptyText="rule-node-config.query-params-empty" + keyProperty="name"> +
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 419eaf50ac..2ae1b4ff48 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -5411,6 +5411,7 @@ "query-params-name-required": "Name is required", "query-params-value-required": "Value is required", "headers-empty": "No headers configured", + "url": "URL", "save-time-series": { "processing-settings": "Processing settings", "processing-settings-hint": "Define how incoming messages are processed. Basic processing settings allow you to select preconfigured strategies, while Advanced settings allow you to select individual processing strategies for each action.", From 07fd49c080944acdea5888b75d1cccb94eb72d41 Mon Sep 17 00:00:00 2001 From: Maksym Tsymbarov Date: Fri, 16 Jan 2026 17:35:32 +0200 Subject: [PATCH 027/742] Moved to key name prop in Query params --- .../rule-node/common/kv-list-config.component.ts | 12 +++--------- .../external/rest-api-call-config.component.html | 3 +-- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-list-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-list-config.component.ts index 5284b88bce..fe913815cd 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-list-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-list-config.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnInit } from '@angular/core'; +import { Component, forwardRef, OnInit } from '@angular/core'; import { AbstractControl, ControlValueAccessor, @@ -44,14 +44,12 @@ import { KvMapConfigOldComponent } from '@home/components/rule-node/common/kv-ma }) export class KvListConfigComponent extends KvMapConfigOldComponent implements ControlValueAccessor, OnInit, Validator{ - @Input() keyProperty: string = 'key'; - override writeValue(kvList: any): void { const keyValsControls: Array = []; if (Array.isArray(kvList) && kvList.length > 0) { for (const property of kvList) { keyValsControls.push(this.fb.group({ - key: [property[this.keyProperty], [Validators.required]], + key: [property.key, [Validators.required]], value: [property.value, [Validators.required]] })) } @@ -79,11 +77,7 @@ export class KvListConfigComponent extends KvMapConfigOldComponent implements Co if (this.required && !kvList.length || !this.kvListFormGroup.valid) { this.propagateChange(null); } else { - const result = kvList.map(entry => ({ - [this.keyProperty]: entry.key, - value: entry.value - })); - this.propagateChange(result); + this.propagateChange(kvList); } } } diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.html index 7a30723f9e..2f6840639c 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.html @@ -38,8 +38,7 @@ keyRequiredText="rule-node-config.query-params-name-required" valText="rule-node-config.query-params-value" valRequiredText="rule-node-config.query-params-value-required" - emptyText="rule-node-config.query-params-empty" - keyProperty="name"> + emptyText="rule-node-config.query-params-empty"> From 38d35f1ca8366aa728d0eefd98c280c0e15df986 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Mon, 19 Jan 2026 10:37:00 +0200 Subject: [PATCH 028/742] Fix upgrade script --- .../rule/engine/rest/TbRestApiCallNode.java | 1 - .../rule/engine/rest/TbRestApiCallNodeTest.java | 16 ++++++---------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java index bccbc9a08f..86dd5e576e 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java @@ -109,7 +109,6 @@ public class TbRestApiCallNode extends TbAbstractExternalNode { hasChanges = true; ((ObjectNode) oldConfiguration).put(MAX_IN_MEMORY_BUFFER_SIZE_IN_KB, 256); } - break; case 3: Set knownProperties = Set.of( "restEndpointUrlPattern", "requestMethod", "headers", diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java index 011b035e87..c51c044e18 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java @@ -345,7 +345,6 @@ public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest { private static Stream givenFromVersionAndConfig_whenUpgrade_thenVerifyHasChangesAndConfig() { return Stream.of( - // config for version 2 with upgrade from version 0 Arguments.of(0, "{\"restEndpointUrlPattern\":\"http://localhost/api\",\"requestMethod\":\"POST\"," + "\"useSimpleClientHttpFactory\":false,\"ignoreRequestBody\":false,\"enableProxy\":false," + @@ -355,13 +354,12 @@ public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest { "\"trimQueue\":null,\"maxQueueSize\":null,\"credentials\":{\"type\":\"anonymous\"},\"trimDoubleQuotes\":false}", true, "{\"restEndpointUrlPattern\":\"http://localhost/api\",\"requestMethod\": \"POST\"," + - "\"useSimpleClientHttpFactory\": false,\"parseToPlainText\": false,\"ignoreRequestBody\": false," + - "\"enableProxy\": false,\"useSystemProxyProperties\": false,\"proxyScheme\": null,\"proxyHost\": null," + + "\"parseToPlainText\": false,\"ignoreRequestBody\": false," + + "\"enableProxy\": false,\"useSystemProxyProperties\": false,\"proxyHost\": null," + "\"proxyPort\": 0,\"proxyUser\": null,\"proxyPassword\": null,\"readTimeoutMs\": 0," + "\"maxParallelRequestsCount\": 0,\"headers\": {\"Content-Type\": \"application/json\"}," + "\"credentials\": {\"type\": \"anonymous\"}," + "\"maxInMemoryBufferSizeInKb\": 256}"), - // config for version 2 with upgrade from version 1 Arguments.of(1, "{\"restEndpointUrlPattern\":\"http://localhost/api\",\"requestMethod\": \"POST\"," + "\"useSimpleClientHttpFactory\": false,\"parseToPlainText\": false,\"ignoreRequestBody\": false," + @@ -372,13 +370,12 @@ public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest { "\"credentials\": {\"type\": \"anonymous\"}}", true, "{\"restEndpointUrlPattern\":\"http://localhost/api\",\"requestMethod\": \"POST\"," + - "\"useSimpleClientHttpFactory\": false,\"parseToPlainText\": false,\"ignoreRequestBody\": false," + - "\"enableProxy\": false,\"useSystemProxyProperties\": false,\"proxyScheme\": null,\"proxyHost\": null," + + "\"parseToPlainText\": false,\"ignoreRequestBody\": false," + + "\"enableProxy\": false,\"useSystemProxyProperties\": false,\"proxyHost\": null," + "\"proxyPort\": 0,\"proxyUser\": null,\"proxyPassword\": null,\"readTimeoutMs\": 0," + "\"maxParallelRequestsCount\": 0,\"headers\": {\"Content-Type\": \"application/json\"}," + "\"credentials\": {\"type\": \"anonymous\"}," + "\"maxInMemoryBufferSizeInKb\": 256}"), - // config for version 3 with upgrade from version 2 Arguments.of(2, "{\"restEndpointUrlPattern\":\"http://localhost/api\",\"requestMethod\": \"POST\"," + "\"useSimpleClientHttpFactory\": false,\"parseToPlainText\": false,\"ignoreRequestBody\": false," + @@ -388,13 +385,12 @@ public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest { "\"credentials\": {\"type\": \"anonymous\"}}", true, "{\"restEndpointUrlPattern\":\"http://localhost/api\",\"requestMethod\": \"POST\"," + - "\"useSimpleClientHttpFactory\": false,\"parseToPlainText\": false,\"ignoreRequestBody\": false," + - "\"enableProxy\": false,\"useSystemProxyProperties\": false,\"proxyScheme\": null,\"proxyHost\": null," + + "\"parseToPlainText\": false,\"ignoreRequestBody\": false," + + "\"enableProxy\": false,\"useSystemProxyProperties\": false,\"proxyHost\": null," + "\"proxyPort\": 0,\"proxyUser\": null,\"proxyPassword\": null,\"readTimeoutMs\": 0," + "\"maxParallelRequestsCount\": 0,\"headers\": {\"Content-Type\": \"application/json\"}," + "\"credentials\": {\"type\": \"anonymous\"}," + "\"maxInMemoryBufferSizeInKb\": 256}"), - // config for version 4 with upgrade from version 3 Arguments.of(3, """ { "restEndpointUrlPattern": "http://localhost/api", From 208cbb9566e25d63dc1f9eb46a9aba4fe96381b8 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Mon, 19 Jan 2026 10:37:38 +0200 Subject: [PATCH 029/742] Remove version from deprecation annotation --- .../java/org/thingsboard/rule/engine/rest/TbHttpClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index 05f5d547a8..9fb6e451e8 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -326,7 +326,7 @@ public class TbHttpClient { * Use {@link #buildEncodedUriNew} with a separate query params list, * where values are encoded exactly once: {@code +} → {@code %2B}, {@code @} → {@code %40}. */ - @Deprecated(since = "4.2.1.2", forRemoval = true) + @Deprecated(forRemoval = true) private URI buildEncodedUriLegacy(String endpointUrl) { return UriComponentsBuilder.fromUriString(endpointUrl).build().encode().toUri(); } From e3f1f7f7625f3bdeb0289650fd9ede53a91eace1 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Mon, 19 Jan 2026 10:40:25 +0200 Subject: [PATCH 030/742] Fix type --- .../rule/engine/rest/TbRestApiCallNodeConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java index fbff14f640..ac4d493819 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java @@ -33,7 +33,7 @@ public class TbRestApiCallNodeConfiguration implements NodeConfiguration queryParams; private Map headers; From 0f288a137996d59408a840bb3446d0738ef85c83 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Mon, 19 Jan 2026 11:15:33 +0200 Subject: [PATCH 031/742] Refactor `QueryParam` into general-purpose `KeyValueEntry` --- .../common/data/util/KeyValueEntry.java | 18 ++++++++++++ .../rule/engine/rest/TbHttpClient.java | 2 +- .../rest/TbRestApiCallNodeConfiguration.java | 29 ++++++++++++++----- .../rule/engine/rest/TbHttpClientTest.java | 11 +++---- .../engine/rest/TbRestApiCallNodeTest.java | 13 +++++---- 5 files changed, 53 insertions(+), 20 deletions(-) create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/util/KeyValueEntry.java diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/util/KeyValueEntry.java b/common/data/src/main/java/org/thingsboard/server/common/data/util/KeyValueEntry.java new file mode 100644 index 0000000000..3e758f69aa --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/util/KeyValueEntry.java @@ -0,0 +1,18 @@ +/** + * Copyright © 2016-2025 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.common.data.util; + +public record KeyValueEntry(K key, V value) {} diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index 9fb6e451e8..64b4f70b64 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -216,7 +216,7 @@ public class TbHttpClient { if (config.getQueryParams() != null) { processedQueryParams = config.getQueryParams().stream() .map(param -> { - var processedParamName = TbNodeUtils.processPattern(param.name(), msg); + var processedParamName = TbNodeUtils.processPattern(param.key(), msg); var processedParamValue = TbNodeUtils.processPattern(param.value(), msg); return new QueryParam(processedParamName, processedParamValue); }) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java index ac4d493819..bbef69ff31 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java @@ -15,7 +15,8 @@ */ package org.thingsboard.rule.engine.rest; -import jakarta.validation.Valid; +import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.validation.constraints.AssertTrue; import jakarta.validation.constraints.NotNull; import lombok.Data; import org.springframework.http.HttpHeaders; @@ -23,10 +24,12 @@ import org.springframework.http.MediaType; import org.thingsboard.rule.engine.api.NodeConfiguration; import org.thingsboard.rule.engine.credentials.AnonymousCredentials; import org.thingsboard.rule.engine.credentials.ClientCredentials; +import org.thingsboard.server.common.data.util.KeyValueEntry; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; @Data public class TbRestApiCallNodeConfiguration implements NodeConfiguration { @@ -35,7 +38,7 @@ public class TbRestApiCallNodeConfiguration implements NodeConfiguration queryParams; + private List<@NotNull KeyValueEntry> queryParams; private Map headers; private int readTimeoutMs; private int maxParallelRequestsCount; @@ -50,9 +53,23 @@ public class TbRestApiCallNodeConfiguration implements NodeConfiguration queryParam : queryParams) { + if (queryParam == null || queryParam.key() == null || queryParam.value() == null) { + return false; + } + } + return true; + } + @Override public TbRestApiCallNodeConfiguration defaultConfiguration() { - TbRestApiCallNodeConfiguration configuration = new TbRestApiCallNodeConfiguration(); + var configuration = new TbRestApiCallNodeConfiguration(); configuration.setRestEndpointUrlPattern("http://localhost/api"); configuration.setRequestMethod("POST"); configuration.setHeaders(Collections.singletonMap(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)); @@ -68,11 +85,7 @@ public class TbRestApiCallNodeConfiguration implements NodeConfiguration("email", "${userEmail}"), // ${} from metadata + new KeyValueEntry<>("device", "${deviceName}"), // ${} from metadata + new KeyValueEntry<>("${dynamicParam}", "${dynamicValue}"), // ${} in both key and value + new KeyValueEntry<>("temp", "$[temperature]"), // $[] from data + new KeyValueEntry<>("location", "$[sensor.location]") // $[] from nested data )); var metaData = new TbMsgMetaData(); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java index c51c044e18..90d4cdc47d 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java @@ -45,6 +45,7 @@ import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.msg.TbMsgType; import org.thingsboard.server.common.data.rule.RuleNode; +import org.thingsboard.server.common.data.util.KeyValueEntry; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgDataType; import org.thingsboard.server.common.msg.TbMsgMetaData; @@ -123,7 +124,7 @@ public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest { public void shouldNotAllowNullQueryParamNames() { // GIVEN var config = new TbRestApiCallNodeConfiguration().defaultConfiguration(); - config.setQueryParams(List.of(new QueryParam(null, "value"))); + config.setQueryParams(List.of(new KeyValueEntry<>(null, "value"))); // WHEN-THEN assertThatThrownBy(() -> new TbRestApiCallNode().init(ctx, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) @@ -131,14 +132,14 @@ public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest { .matches(e -> ((TbNodeException) e).isUnrecoverable()) .rootCause() .isInstanceOf(DataValidationException.class) - .hasMessageContaining("query parameter names must be non-null"); + .hasMessageContaining("query parameter names and values must be non-null"); } @Test public void shouldNotAllowNullQueryParamValues() { // GIVEN var config = new TbRestApiCallNodeConfiguration().defaultConfiguration(); - config.setQueryParams(List.of(new QueryParam("key", null))); + config.setQueryParams(List.of(new KeyValueEntry<>("key", null))); // WHEN-THEN assertThatThrownBy(() -> new TbRestApiCallNode().init(ctx, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) @@ -146,7 +147,7 @@ public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest { .matches(e -> ((TbNodeException) e).isUnrecoverable()) .rootCause() .isInstanceOf(DataValidationException.class) - .hasMessageContaining("query parameter values must be non-null"); + .hasMessageContaining("query parameter names and values must be non-null"); } @Test @@ -154,8 +155,8 @@ public class TbRestApiCallNodeTest extends AbstractRuleNodeUpgradeTest { // GIVEN var config = new TbRestApiCallNodeConfiguration().defaultConfiguration(); - var queryParams = new ArrayList(); - queryParams.add(new QueryParam("key", "value")); + var queryParams = new ArrayList>(); + queryParams.add(new KeyValueEntry<>("key", "value")); queryParams.add(null); config.setQueryParams(queryParams); From 0ea01d61af763404da95cd0927283488a9a42a79 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Mon, 19 Jan 2026 12:45:54 +0200 Subject: [PATCH 032/742] Cleanup remnants of `QueryParam` --- .../rule/engine/rest/QueryParam.java | 23 ---- .../rule/engine/rest/TbHttpClient.java | 11 +- .../rule/engine/rest/TbHttpClientTest.java | 116 +++++++++--------- 3 files changed, 64 insertions(+), 86 deletions(-) delete mode 100644 rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/QueryParam.java diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/QueryParam.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/QueryParam.java deleted file mode 100644 index 3eeecc0560..0000000000 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/QueryParam.java +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright © 2016-2026 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.rule.engine.rest; - -import jakarta.validation.constraints.NotNull; - -record QueryParam( - @NotNull(message = "query parameter names must be non-null") String name, - @NotNull(message = "query parameter values must be non-null") String value -) {} diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index 177c6811eb..fb0fbd9f35 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -40,6 +40,7 @@ import org.thingsboard.rule.engine.credentials.BasicCredentials; import org.thingsboard.rule.engine.credentials.ClientCredentials; import org.thingsboard.rule.engine.credentials.CredentialsType; import org.thingsboard.server.common.data.StringUtils; +import org.thingsboard.server.common.data.util.KeyValueEntry; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import reactor.netty.http.client.HttpClient; @@ -212,13 +213,13 @@ public class TbHttpClient { String endpointUrl = TbNodeUtils.processPattern(config.getRestEndpointUrlPattern(), msg); - List processedQueryParams; + List> processedQueryParams; if (config.getQueryParams() != null) { processedQueryParams = config.getQueryParams().stream() .map(param -> { var processedParamName = TbNodeUtils.processPattern(param.key(), msg); var processedParamValue = TbNodeUtils.processPattern(param.value(), msg); - return new QueryParam(processedParamName, processedParamValue); + return new KeyValueEntry<>(processedParamName, processedParamValue); }) .toList(); } else { @@ -274,7 +275,7 @@ public class TbHttpClient { return origin; } - public URI buildEncodedUri(String endpointUrl, List queryParams) { + public URI buildEncodedUri(String endpointUrl, List> queryParams) { if (endpointUrl == null) { throw new RuntimeException("Url string cannot be null!"); } @@ -302,10 +303,10 @@ public class TbHttpClient { return uri; } - private URI buildEncodedUriNew(String endpointUrl, List queryParams) { + private URI buildEncodedUriNew(String endpointUrl, List> queryParams) { try { URIBuilder builder = new URIBuilder(endpointUrl); - queryParams.forEach(param -> builder.addParameter(param.name(), param.value())); + queryParams.forEach(param -> builder.addParameter(param.key(), param.value())); return builder.build(); } catch (URISyntaxException e) { throw new IllegalArgumentException( diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java index eb3b9802aa..9abe3d28a9 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java @@ -234,7 +234,7 @@ public class TbHttpClientTest { @ParameterizedTest(name = "{0}") @MethodSource - public void testQueryParamsEncoding(String endpointUrl, List queryParams, String expectedEncodedUrl) { + public void testQueryParamsEncoding(String endpointUrl, List> queryParams, String expectedEncodedUrl) { // GIVEN Mockito.when(client.buildEncodedUri(any(), any())).thenCallRealMethod(); @@ -249,42 +249,42 @@ public class TbHttpClientTest { return Stream.of( Arguments.of( Named.named("ISO 8601 date-time in value", "http://somecompany/api/data/fetch"), - List.of(new QueryParam("ts", "2016-08-01T09:06:06.0+02:00")), + List.of(new KeyValueEntry<>("ts", "2016-08-01T09:06:06.0+02:00")), "http://somecompany/api/data/fetch?ts=2016-08-01T09%3A06%3A06.0%2B02%3A00" ), Arguments.of( Named.named("email with plus sign in value", "http://localhost:8080/api/user/sendActivationMail"), - List.of(new QueryParam("email", "someperson+test1289@thingsboard.io")), + List.of(new KeyValueEntry<>("email", "someperson+test1289@thingsboard.io")), "http://localhost:8080/api/user/sendActivationMail?email=someperson%2Btest1289%40thingsboard.io" ), Arguments.of( Named.named("plus mixed with spaces in value", "http://url/api"), - List.of(new QueryParam("q", "a + b")), + List.of(new KeyValueEntry<>("q", "a + b")), "http://url/api?q=a%20%2B%20b" ), Arguments.of( Named.named("colon in value", "http://url/api"), - List.of(new QueryParam("time", "12:00")), + List.of(new KeyValueEntry<>("time", "12:00")), "http://url/api?time=12%3A00" ), Arguments.of( Named.named("slash in value", "http://url"), - List.of(new QueryParam("ref", "/home/user")), + List.of(new KeyValueEntry<>("ref", "/home/user")), "http://url?ref=%2Fhome%2Fuser" ), Arguments.of( Named.named("comma and semicolon in value", "http://url"), - List.of(new QueryParam("l", "a,b;c")), + List.of(new KeyValueEntry<>("l", "a,b;c")), "http://url?l=a%2Cb%3Bc" ), Arguments.of( Named.named("ampersand and equals in value", "http://url"), - List.of(new QueryParam("q", "key1=value1&key2=value2")), + List.of(new KeyValueEntry<>("q", "key1=value1&key2=value2")), "http://url?q=key1%3Dvalue1%26key2%3Dvalue2" ), Arguments.of( Named.named("JSON in value", "http://url"), - List.of(new QueryParam("json", """ + List.of(new KeyValueEntry<>("json", """ { "string": "hello", "integer": 42, @@ -307,44 +307,44 @@ public class TbHttpClientTest { Arguments.of( Named.named("UTF-8 in query", "http://url/cafes"), List.of( - new QueryParam("nom", "Le Goût Moderne"), - new QueryParam("назва", "У Миколи \uD83D\uDE0B") + new KeyValueEntry<>("nom", "Le Goût Moderne"), + new KeyValueEntry<>("назва", "У Миколи \uD83D\uDE0B") ), "http://url/cafes?nom=Le%20Go%C3%BBt%20Moderne&%D0%BD%D0%B0%D0%B7%D0%B2%D0%B0=%D0%A3%20%D0%9C%D0%B8%D0%BA%D0%BE%D0%BB%D0%B8%20%F0%9F%98%8B" ), Arguments.of( Named.named("empty value", "http://url/empty"), - List.of(new QueryParam("name", "")), + List.of(new KeyValueEntry<>("name", "")), "http://url/empty?name=" ), Arguments.of( Named.named("blank value (spaces)", "http://url/empty"), - List.of(new QueryParam("name", " ")), + List.of(new KeyValueEntry<>("name", " ")), "http://url/empty?name=%20%20" ), Arguments.of( Named.named("empty key", "http://url/empty"), - List.of(new QueryParam("", "value")), + List.of(new KeyValueEntry<>("", "value")), "http://url/empty?=value" ), Arguments.of( Named.named("blank key (spaces)", "http://url/empty"), - List.of(new QueryParam(" ", "value")), + List.of(new KeyValueEntry<>(" ", "value")), "http://url/empty?%20%20=value" ), Arguments.of( Named.named("blank key with value that needs to be encoded", "http://url/empty"), - List.of(new QueryParam(" ", "value1+value2")), + List.of(new KeyValueEntry<>(" ", "value1+value2")), "http://url/empty?%20%20=value1%2Bvalue2" ), Arguments.of( Named.named("blank key and value", "http://url/empty"), - List.of(new QueryParam(" ", " ")), + List.of(new KeyValueEntry<>(" ", " ")), "http://url/empty?%20%20=%20%20" ), Arguments.of( Named.named("fragment with query params", "http://url#frag"), - List.of(new QueryParam("docs", "مستندات عقدة القاعدة\n")), + List.of(new KeyValueEntry<>("docs", "مستندات عقدة القاعدة\n")), "http://url?docs=%D9%85%D8%B3%D8%AA%D9%86%D8%AF%D8%A7%D8%AA%20%D8%B9%D9%82%D8%AF%D8%A9%20%D8%A7%D9%84%D9%82%D8%A7%D8%B9%D8%AF%D8%A9%0A#frag" ), Arguments.of( @@ -355,105 +355,105 @@ public class TbHttpClientTest { Arguments.of( Named.named("multiple query params (ordered)", "http://url/api"), List.of( - new QueryParam("param1", "value1"), - new QueryParam("param2", "value2"), - new QueryParam("param3", "value3") + new KeyValueEntry<>("param1", "value1"), + new KeyValueEntry<>("param2", "value2"), + new KeyValueEntry<>("param3", "value3") ), "http://url/api?param1=value1¶m2=value2¶m3=value3" ), Arguments.of( Named.named("hash (#) in value", "http://url/api"), - List.of(new QueryParam("color", "#ff0000")), + List.of(new KeyValueEntry<>("color", "#ff0000")), "http://url/api?color=%23ff0000" ), Arguments.of( Named.named("question mark (?) in value", "http://url/api"), - List.of(new QueryParam("query", "what?")), + List.of(new KeyValueEntry<>("query", "what?")), "http://url/api?query=what%3F" ), Arguments.of( Named.named("percent sign (%) in value", "http://url/api"), - List.of(new QueryParam("discount", "50%")), + List.of(new KeyValueEntry<>("discount", "50%")), "http://url/api?discount=50%25" ), Arguments.of( Named.named("already encoded string - double encoding", "http://url/api"), - List.of(new QueryParam("encoded", "%20")), + List.of(new KeyValueEntry<>("encoded", "%20")), "http://url/api?encoded=%2520" ), Arguments.of( Named.named("URL with port number", "http://localhost:8080/api/v1/data"), - List.of(new QueryParam("key", "value")), + List.of(new KeyValueEntry<>("key", "value")), "http://localhost:8080/api/v1/data?key=value" ), Arguments.of( Named.named("URL with userinfo (auth)", "http://user:password@hostname/path"), - List.of(new QueryParam("secure", "true")), + List.of(new KeyValueEntry<>("secure", "true")), "http://user:password@hostname/path?secure=true" ), Arguments.of( Named.named("IPv4 address in URL", "http://192.168.1.100:9090/endpoint"), - List.of(new QueryParam("ip", "test")), + List.of(new KeyValueEntry<>("ip", "test")), "http://192.168.1.100:9090/endpoint?ip=test" ), Arguments.of( Named.named("IPv6 address in URL", "http://[::1]:8080/api"), - List.of(new QueryParam("ipv6", "true")), + List.of(new KeyValueEntry<>("ipv6", "true")), "http://[::1]:8080/api?ipv6=true" ), Arguments.of( Named.named("HTTPS protocol", "https://secure.example.com/api"), - List.of(new QueryParam("token", "abc123")), + List.of(new KeyValueEntry<>("token", "abc123")), "https://secure.example.com/api?token=abc123" ), Arguments.of( Named.named("pipe (|) in value", "http://url/api"), - List.of(new QueryParam("filter", "a|b|c")), + List.of(new KeyValueEntry<>("filter", "a|b|c")), "http://url/api?filter=a%7Cb%7Cc" ), Arguments.of( Named.named("caret (^) and backtick (`) in value", "http://url/api"), - List.of(new QueryParam("special", "a^b`c")), + List.of(new KeyValueEntry<>("special", "a^b`c")), "http://url/api?special=a%5Eb%60c" ), Arguments.of( Named.named("tab character in value", "http://url/api"), - List.of(new QueryParam("data", "col1\tcol2\tcol3")), + List.of(new KeyValueEntry<>("data", "col1\tcol2\tcol3")), "http://url/api?data=col1%09col2%09col3" ), Arguments.of( Named.named("CRLF in value", "http://url/api"), - List.of(new QueryParam("text", "line1\r\nline2")), + List.of(new KeyValueEntry<>("text", "line1\r\nline2")), "http://url/api?text=line1%0D%0Aline2" ), Arguments.of( Named.named("square brackets in value", "http://url/api"), - List.of(new QueryParam("array", "[1,2,3]")), + List.of(new KeyValueEntry<>("array", "[1,2,3]")), "http://url/api?array=%5B1%2C2%2C3%5D" ), Arguments.of( Named.named("single and double quotes in value", "http://url/api"), - List.of(new QueryParam("quoted", "He said \"Hello\" and 'Hi'")), + List.of(new KeyValueEntry<>("quoted", "He said \"Hello\" and 'Hi'")), "http://url/api?quoted=He%20said%20%22Hello%22%20and%20%27Hi%27" ), Arguments.of( Named.named("angle brackets in value (XSS test)", "http://url/api"), - List.of(new QueryParam("html", "")), + List.of(new KeyValueEntry<>("html", "")), "http://url/api?html=%3Cscript%3Ealert%28%27xss%27%29%3C%2Fscript%3E" ), Arguments.of( Named.named("backslash in value", "http://url/api"), - List.of(new QueryParam("path", "C:\\Users\\test")), + List.of(new KeyValueEntry<>("path", "C:\\Users\\test")), "http://url/api?path=C%3A%5CUsers%5Ctest" ), Arguments.of( Named.named("at sign (@) in value", "http://url/api"), - List.of(new QueryParam("contact", "user@domain.com")), + List.of(new KeyValueEntry<>("contact", "user@domain.com")), "http://url/api?contact=user%40domain.com" ), Arguments.of( Named.named("URL as value", "http://url/api"), - List.of(new QueryParam("redirect", "https://example.com/path?foo=bar")), + List.of(new KeyValueEntry<>("redirect", "https://example.com/path?foo=bar")), "http://url/api?redirect=https%3A%2F%2Fexample.com%2Fpath%3Ffoo%3Dbar" ), Arguments.of( @@ -463,89 +463,89 @@ public class TbHttpClientTest { ), Arguments.of( Named.named("underscore and hyphen in key/value", "http://url/api"), - List.of(new QueryParam("my-key_name", "my-value_data")), + List.of(new KeyValueEntry<>("my-key_name", "my-value_data")), "http://url/api?my-key_name=my-value_data" ), Arguments.of( Named.named("dots in key and value", "http://url/api"), - List.of(new QueryParam("version.major", "1.2.3")), + List.of(new KeyValueEntry<>("version.major", "1.2.3")), "http://url/api?version.major=1.2.3" ), Arguments.of( Named.named("multiple reserved chars combined", "http://url/api"), - List.of(new QueryParam("complex", "a=1&b=2#section?query")), + List.of(new KeyValueEntry<>("complex", "a=1&b=2#section?query")), "http://url/api?complex=a%3D1%26b%3D2%23section%3Fquery" ), Arguments.of( Named.named("trailing slash in URL", "http://url/api/"), - List.of(new QueryParam("param", "value")), + List.of(new KeyValueEntry<>("param", "value")), "http://url/api/?param=value" ), Arguments.of( Named.named("long value (1000 chars)", "http://url/api"), - List.of(new QueryParam("long", "a".repeat(1000))), + List.of(new KeyValueEntry<>("long", "a".repeat(1000))), "http://url/api?long=" + "a".repeat(1000) ), Arguments.of( Named.named("Chinese characters in value", "http://url/api"), - List.of(new QueryParam("greeting", "你好世界")), + List.of(new KeyValueEntry<>("greeting", "你好世界")), "http://url/api?greeting=%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C" ), Arguments.of( Named.named("Japanese characters in value", "http://url/api"), - List.of(new QueryParam("text", "こんにちは")), + List.of(new KeyValueEntry<>("text", "こんにちは")), "http://url/api?text=%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF" ), Arguments.of( Named.named("existing query params in URL", "http://url/api?existing=param"), - List.of(new QueryParam("new", "value")), + List.of(new KeyValueEntry<>("new", "value")), "http://url/api?existing=param&new=value" ), Arguments.of( Named.named("existing query and fragment in URL", "http://url/api?existing=param#section"), - List.of(new QueryParam("additional", "data")), + List.of(new KeyValueEntry<>("additional", "data")), "http://url/api?existing=param&additional=data#section" ), Arguments.of( Named.named("null byte in value", "http://url/api"), - List.of(new QueryParam("data", "before\u0000after")), + List.of(new KeyValueEntry<>("data", "before\u0000after")), "http://url/api?data=before%00after" ), Arguments.of( Named.named("form feed and vertical tab in value", "http://url/api"), - List.of(new QueryParam("whitespace", "a\fb\u000Bc")), + List.of(new KeyValueEntry<>("whitespace", "a\fb\u000Bc")), "http://url/api?whitespace=a%0Cb%0Bc" ), Arguments.of( Named.named("tilde (unreserved, not encoded)", "http://url/api"), - List.of(new QueryParam("pattern", "~user")), + List.of(new KeyValueEntry<>("pattern", "~user")), "http://url/api?pattern=~user" ), Arguments.of( Named.named("asterisk in value", "http://url/api"), - List.of(new QueryParam("wildcard", "*.txt")), + List.of(new KeyValueEntry<>("wildcard", "*.txt")), "http://url/api?wildcard=%2A.txt" ), Arguments.of( Named.named("curly braces in key", "http://url/api"), - List.of(new QueryParam("{key}", "value")), + List.of(new KeyValueEntry<>("{key}", "value")), "http://url/api?%7Bkey%7D=value" ), Arguments.of( Named.named("curly braces in value", "http://url/api"), - List.of(new QueryParam("data", "{value}")), + List.of(new KeyValueEntry<>("data", "{value}")), "http://url/api?data=%7Bvalue%7D" ), Arguments.of( Named.named("curly braces in both key and value", "http://url/api"), - List.of(new QueryParam("{param}", "{data}")), + List.of(new KeyValueEntry<>("{param}", "{data}")), "http://url/api?%7Bparam%7D=%7Bdata%7D" ), Arguments.of( Named.named("duplicate param names with different values", "http://url/api"), List.of( - new QueryParam("test", "a+b"), - new QueryParam("test", "b c") + new KeyValueEntry<>("test", "a+b"), + new KeyValueEntry<>("test", "b c") ), "http://url/api?test=a%2Bb&test=b%20c" ) From 41cb827c625c3458350fde3e29042fc992125521 Mon Sep 17 00:00:00 2001 From: dshvaika Date: Wed, 21 Jan 2026 14:46:34 +0200 Subject: [PATCH 033/742] Added missing logic to handle propagation path updates --- .../server/service/cf/ctx/state/CalculatedFieldCtx.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java index ab38287b89..7485171514 100644 --- a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java +++ b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java @@ -726,6 +726,9 @@ public class CalculatedFieldCtx implements Closeable { return true; } } + if (cfType == CalculatedFieldType.PROPAGATION && !propagationArgument.equals(other.propagationArgument)) { + return true; + } if (hasGeofencingZoneGroupConfigurationChanges(other)) { return true; } From 924c9cf5d038084fda404185c8e7a60b3cd508f6 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Wed, 21 Jan 2026 09:19:47 +0100 Subject: [PATCH 034/742] hotfix count query by tenant on cf_manager init --- .../device/DefaultNativeAssetRepository.java | 25 ++++++++++--------- .../device/DefaultNativeDeviceRepository.java | 24 +++++++++--------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DefaultNativeAssetRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DefaultNativeAssetRepository.java index 3a11f70a94..e7ba0c206c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DefaultNativeAssetRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DefaultNativeAssetRepository.java @@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; +import java.util.Map; import java.util.UUID; @Repository @@ -41,22 +42,22 @@ public class DefaultNativeAssetRepository extends AbstractNativeRepository imple @Override public PageData findProfileEntityIdInfos(Pageable pageable) { String PROFILE_ASSET_ID_INFO_QUERY = "SELECT tenant_id as tenantId, asset_profile_id as profileId, id as id FROM asset ORDER BY created_time ASC LIMIT %s OFFSET %s"; - return find(COUNT_QUERY, PROFILE_ASSET_ID_INFO_QUERY, pageable, row -> { - AssetId id = new AssetId((UUID) row.get("id")); - AssetProfileId profileId = new AssetProfileId((UUID) row.get("profileId")); - var tenantIdObj = row.get("tenantId"); - return ProfileEntityIdInfo.create(tenantIdObj != null ? (UUID) tenantIdObj : TenantId.SYS_TENANT_ID.getId(), profileId, id); - }); + return find(COUNT_QUERY, PROFILE_ASSET_ID_INFO_QUERY, pageable, DefaultNativeAssetRepository::toInfo); } @Override public PageData findProfileEntityIdInfosByTenantId(UUID tenantId, Pageable pageable) { String PROFILE_ASSET_ID_INFO_QUERY = String.format("SELECT tenant_id as tenantId, asset_profile_id as profileId, id as id FROM asset WHERE tenant_id = '%s' ORDER BY created_time ASC LIMIT %%s OFFSET %%s", tenantId); - return find(COUNT_QUERY, PROFILE_ASSET_ID_INFO_QUERY, pageable, row -> { - AssetId id = new AssetId((UUID) row.get("id")); - AssetProfileId profileId = new AssetProfileId((UUID) row.get("profileId")); - var tenantIdObj = row.get("tenantId"); - return ProfileEntityIdInfo.create(tenantIdObj != null ? (UUID) tenantIdObj : TenantId.SYS_TENANT_ID.getId(), profileId, id); - }); + String COUNT_QUERY_BY_TENANT = String.format("SELECT count(id) FROM asset WHERE tenant_id = '%s';", tenantId); + return find(COUNT_QUERY_BY_TENANT, PROFILE_ASSET_ID_INFO_QUERY, pageable, DefaultNativeAssetRepository::toInfo); } + + private static ProfileEntityIdInfo toInfo(Map row) { + var tenantIdObj = row.get("tenantId"); + UUID tenantId = tenantIdObj != null ? (UUID) tenantIdObj : TenantId.SYS_TENANT_ID.getId(); + AssetId id = new AssetId((UUID) row.get("id")); + AssetProfileId profileId = new AssetProfileId((UUID) row.get("profileId")); + return ProfileEntityIdInfo.create(tenantId, profileId, id); + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DefaultNativeDeviceRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DefaultNativeDeviceRepository.java index b039f30d32..c4ba36ce2e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DefaultNativeDeviceRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DefaultNativeDeviceRepository.java @@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; +import java.util.Map; import java.util.UUID; @Repository @@ -53,23 +54,22 @@ public class DefaultNativeDeviceRepository extends AbstractNativeRepository impl @Override public PageData findProfileEntityIdInfos(Pageable pageable) { String PROFILE_DEVICE_ID_INFO_QUERY = "SELECT tenant_id as tenantId, device_profile_id as profileId, id as id FROM device ORDER BY created_time ASC LIMIT %s OFFSET %s"; - return find(COUNT_QUERY, PROFILE_DEVICE_ID_INFO_QUERY, pageable, row -> { - DeviceId id = new DeviceId((UUID) row.get("id")); - DeviceProfileId profileId = new DeviceProfileId((UUID) row.get("profileId")); - var tenantIdObj = row.get("tenantId"); - return ProfileEntityIdInfo.create(tenantIdObj != null ? (UUID) tenantIdObj : TenantId.SYS_TENANT_ID.getId(), profileId, id); - }); + return find(COUNT_QUERY, PROFILE_DEVICE_ID_INFO_QUERY, pageable, DefaultNativeDeviceRepository::toInfo); } @Override public PageData findProfileEntityIdInfosByTenantId(UUID tenantId, Pageable pageable) { String PROFILE_DEVICE_ID_INFO_QUERY = String.format("SELECT tenant_id as tenantId, device_profile_id as profileId, id as id FROM device WHERE tenant_id = '%s' ORDER BY created_time ASC LIMIT %%s OFFSET %%s", tenantId); - return find(COUNT_QUERY, PROFILE_DEVICE_ID_INFO_QUERY, pageable, row -> { - DeviceId id = new DeviceId((UUID) row.get("id")); - DeviceProfileId profileId = new DeviceProfileId((UUID) row.get("profileId")); - var tenantIdObj = row.get("tenantId"); - return ProfileEntityIdInfo.create(tenantIdObj != null ? (UUID) tenantIdObj : TenantId.SYS_TENANT_ID.getId(), profileId, id); - }); + String COUNT_QUERY_BY_TENANT = String.format("SELECT count(id) FROM device WHERE tenant_id = '%s';", tenantId); + return find(COUNT_QUERY_BY_TENANT, PROFILE_DEVICE_ID_INFO_QUERY, pageable, DefaultNativeDeviceRepository::toInfo); + } + + private static ProfileEntityIdInfo toInfo(Map row) { + var tenantIdObj = row.get("tenantId"); + UUID tenantId = tenantIdObj != null ? (UUID) tenantIdObj : TenantId.SYS_TENANT_ID.getId(); + DeviceId id = new DeviceId((UUID) row.get("id")); + DeviceProfileId profileId = new DeviceProfileId((UUID) row.get("profileId")); + return ProfileEntityIdInfo.create(tenantId, profileId, id); } } From 73fa6734c4925708d4632f7bcf4f7d9145bf15fa Mon Sep 17 00:00:00 2001 From: IrynaMatveieva Date: Thu, 22 Jan 2026 09:54:11 +0200 Subject: [PATCH 035/742] updated error message on cf init --- .../CalculatedFieldManagerMessageProcessor.java | 6 +++--- .../server/service/cf/ctx/state/CalculatedFieldCtx.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldManagerMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldManagerMessageProcessor.java index fed1cc3ada..65ec0b332b 100644 --- a/application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldManagerMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldManagerMessageProcessor.java @@ -262,7 +262,7 @@ public class CalculatedFieldManagerMessageProcessor extends AbstractContextAware try { cfCtx.init(); } catch (Exception e) { - throw CalculatedFieldException.builder().ctx(cfCtx).eventEntity(cf.getEntityId()).cause(e).errorMessage("Failed to initialize CF context").build(); + throw CalculatedFieldException.builder().ctx(cfCtx).eventEntity(cf.getEntityId()).cause(e).errorMessage(e.getMessage()).build(); } calculatedFields.put(cf.getId(), cfCtx); // We use copy on write lists to safely pass the reference to another actor for the iteration. @@ -289,7 +289,7 @@ public class CalculatedFieldManagerMessageProcessor extends AbstractContextAware try { newCfCtx.init(); } catch (Exception e) { - throw CalculatedFieldException.builder().ctx(newCfCtx).eventEntity(newCfCtx.getEntityId()).cause(e).errorMessage("Failed to initialize CF context").build(); + throw CalculatedFieldException.builder().ctx(newCfCtx).eventEntity(newCfCtx.getEntityId()).cause(e).errorMessage(e.getMessage()).build(); } finally { calculatedFields.put(newCf.getId(), newCfCtx); List oldCfList = entityIdCalculatedFields.get(newCf.getEntityId()); @@ -552,7 +552,7 @@ public class CalculatedFieldManagerMessageProcessor extends AbstractContextAware try { cfCtx.init(); } catch (Exception e) { - throw CalculatedFieldException.builder().ctx(cfCtx).eventEntity(cf.getEntityId()).cause(e).errorMessage("Failed to initialize CF context").build(); + throw CalculatedFieldException.builder().ctx(cfCtx).eventEntity(cf.getEntityId()).cause(e).errorMessage(e.getMessage()).build(); } finally { calculatedFields.put(cf.getId(), cfCtx); // We use copy on write lists to safely pass the reference to another actor for the iteration. diff --git a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java index 3438760778..5d0ff5c2ff 100644 --- a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java +++ b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java @@ -114,7 +114,7 @@ public class CalculatedFieldCtx { initialized = true; } catch (Exception e) { initialized = false; - throw new RuntimeException("Failed to init calculated field ctx. Invalid expression syntax.", e); + throw new RuntimeException("Failed to initialize CF context. The script expression is invalid. Please check for syntax errors or unsupported functions.", e); } } else { if (isValidExpression(expression)) { @@ -128,7 +128,7 @@ public class CalculatedFieldCtx { initialized = true; } else { initialized = false; - throw new RuntimeException("Failed to init calculated field ctx. Invalid expression syntax."); + throw new RuntimeException("Failed to initialize CF context. The expression has invalid syntax or unknown variables. Ensure all mathematical operators are correct."); } } } From a2da95760c91fff67ff2cf55214cb79fd2a719cb Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Thu, 22 Jan 2026 11:18:42 +0200 Subject: [PATCH 036/742] Fix API key controller, when user update description or activity --- .../server/controller/ApiKeyController.java | 10 +++++++--- .../server/controller/ApiKeyControllerTest.java | 9 ++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/ApiKeyController.java b/application/src/main/java/org/thingsboard/server/controller/ApiKeyController.java index 2c6ae69ca5..09972bd6c2 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ApiKeyController.java +++ b/application/src/main/java/org/thingsboard/server/controller/ApiKeyController.java @@ -77,7 +77,11 @@ public class ApiKeyController extends BaseController { User user = checkUserId(apiKeyInfo.getUserId(), Operation.WRITE); apiKeyInfo.setTenantId(user.getTenantId()); checkEntity(apiKeyInfo.getId(), apiKeyInfo, Resource.API_KEY); - return checkNotNull(apiKeyService.saveApiKey(apiKeyInfo.getTenantId(), apiKeyInfo)); + ApiKey savedApiKey = checkNotNull(apiKeyService.saveApiKey(apiKeyInfo.getTenantId(), apiKeyInfo)); + if (apiKeyInfo.getId() != null) { + savedApiKey.setValue(null); + } + return savedApiKey; } @ApiOperation(value = "Get User Api Keys (getUserApiKeys)", @@ -121,7 +125,7 @@ public class ApiKeyController extends BaseController { ApiKey apiKey = checkApiKeyId(apiKeyId, Operation.WRITE); checkUserId(apiKey.getUserId(), Operation.WRITE); apiKey.setDescription(description.orElse(null)); - return apiKeyService.saveApiKey(apiKey.getTenantId(), apiKey); + return new ApiKeyInfo(apiKeyService.saveApiKey(apiKey.getTenantId(), apiKey)); } @ApiOperation(value = "Enable or disable API key (enableApiKey)", @@ -137,7 +141,7 @@ public class ApiKeyController extends BaseController { ApiKey apiKey = checkApiKeyId(apiKeyId, Operation.WRITE); checkUserId(apiKey.getUserId(), Operation.WRITE); apiKey.setEnabled(enabledValue); - return apiKeyService.saveApiKey(apiKey.getTenantId(), apiKey); + return new ApiKeyInfo(apiKeyService.saveApiKey(apiKey.getTenantId(), apiKey)); } @ApiOperation(value = "Delete API key by ID (deleteApiKey)", diff --git a/application/src/test/java/org/thingsboard/server/controller/ApiKeyControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/ApiKeyControllerTest.java index 9c7f7a898d..836d1cbfad 100644 --- a/application/src/test/java/org/thingsboard/server/controller/ApiKeyControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/ApiKeyControllerTest.java @@ -53,7 +53,14 @@ public class ApiKeyControllerTest extends AbstractControllerTest { Assert.assertEquals(tenantId, savedApiKey.getTenantId()); Assert.assertEquals(tenantAdminUser.getId(), savedApiKey.getUserId()); - doDelete("/api/apiKey/" + savedApiKey.getId()).andExpect(status().isOk()); + String newDescription = "Updated API Key Description"; + savedApiKey.setDescription(newDescription); + ApiKey updatedApiKey = doPost("/api/apiKey", savedApiKey, ApiKey.class); + Assert.assertNotNull(updatedApiKey); + Assert.assertEquals(newDescription, updatedApiKey.getDescription()); + Assert.assertNull("Verify we do not expose API key value on update", updatedApiKey.getValue()); + + doDelete("/api/apiKey/" + updatedApiKey.getId()).andExpect(status().isOk()); } @Test From 1b190b84e5ce9a62ad64700269377042d455b366 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Tue, 20 Jan 2026 12:52:33 +0100 Subject: [PATCH 037/742] RocksDB log ingested init path on debug level --- .../main/java/org/thingsboard/server/edqs/util/TbRocksDb.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/edqs/src/main/java/org/thingsboard/server/edqs/util/TbRocksDb.java b/common/edqs/src/main/java/org/thingsboard/server/edqs/util/TbRocksDb.java index 9141321dcb..c731cf4548 100644 --- a/common/edqs/src/main/java/org/thingsboard/server/edqs/util/TbRocksDb.java +++ b/common/edqs/src/main/java/org/thingsboard/server/edqs/util/TbRocksDb.java @@ -16,6 +16,7 @@ package org.thingsboard.server.edqs.util; import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import org.rocksdb.Options; import org.rocksdb.RocksDB; import org.rocksdb.RocksIterator; @@ -26,6 +27,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.function.BiConsumer; +@Slf4j public class TbRocksDb { protected final String path; @@ -45,6 +47,7 @@ public class TbRocksDb { @SneakyThrows public void init() { + log.debug("RocksDB init in {}", path); Files.createDirectories(Path.of(path).getParent()); db = RocksDB.open(dbOptions, path); } From f4e2ebde5463a5a1a420bc96069256fe3270b70e Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Tue, 20 Jan 2026 12:58:35 +0100 Subject: [PATCH 038/742] Tests Edge - replaced port 7070 with dynamic port to allow parallel tests in surefire forks --- .../server/controller/EdgeControllerTest.java | 10 +++++++++- .../thingsboard/server/edge/AbstractEdgeTest.java | 14 +++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java index 8c12f8713d..0d0de0a66c 100644 --- a/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java @@ -36,7 +36,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.TestPropertySource; +import org.springframework.test.util.TestSocketUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.ThingsBoardExecutors; import org.thingsboard.server.common.data.AdminSettings; @@ -121,7 +124,12 @@ import static org.thingsboard.server.edge.AbstractEdgeTest.CONNECT_MESSAGE_COUNT public class EdgeControllerTest extends AbstractControllerTest { public static final String EDGE_HOST = "localhost"; - public static final int EDGE_PORT = 7070; + public static final int EDGE_PORT = TestSocketUtils.findAvailableTcpPort(); + @DynamicPropertySource + static void props(DynamicPropertyRegistry registry) { + log.debug("edges.rpc.port = {}", EDGE_PORT); + registry.add("edges.rpc.port", () -> EDGE_PORT); + } private IdComparator idComparator = new IdComparator<>(); diff --git a/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java index cf2f1d1161..b46811daf5 100644 --- a/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java @@ -26,7 +26,10 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.TestPropertySource; +import org.springframework.test.util.TestSocketUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.Customer; @@ -116,6 +119,15 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. }) @Slf4j abstract public class AbstractEdgeTest extends AbstractControllerTest { + + public static final String EDGE_HOST = "localhost"; + public static final int EDGE_PORT = TestSocketUtils.findAvailableTcpPort(); + @DynamicPropertySource + static void props(DynamicPropertyRegistry registry) { + log.debug("edges.rpc.port = {}", EDGE_PORT); + registry.add("edges.rpc.port", () -> EDGE_PORT); + } + public static final Integer CONNECT_MESSAGE_COUNT = 17; public static final Integer INSTALLATION_MESSAGE_COUNT = 8; public static final Integer SYNC_MESSAGE_COUNT = CONNECT_MESSAGE_COUNT + INSTALLATION_MESSAGE_COUNT; @@ -142,7 +154,7 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { //8 installation messages installation(); - edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); + edgeImitator = new EdgeImitator(EDGE_HOST, EDGE_PORT, edge.getRoutingKey(), edge.getSecret()); // 17 connect messages + 8 installation messages edgeImitator.expectMessageAmount(SYNC_MESSAGE_COUNT); edgeImitator.ignoreType(OAuth2ClientUpdateMsg.class); From 8599020aed9243afab004275b20307131fae298b Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Tue, 20 Jan 2026 13:10:24 +0100 Subject: [PATCH 039/742] Tests: Rock DB location moved to the target for safe surefire parallel fork run and easy clean by maven --- pom.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ccc305b6b3..bfb4bbf1ae 100755 --- a/pom.xml +++ b/pom.xml @@ -662,8 +662,10 @@ ${surefire.version} - -XX:+UseStringDeduplication -XX:MaxGCPauseMillis=20 - --add-opens java.base/java.lang.reflect=ALL-UNNAMED + -XX:+UseStringDeduplication -XX:MaxGCPauseMillis=200 + --add-opens=java.base/java.lang.reflect=ALL-UNNAMED + -Dqueue.edqs.local.rocksdb_path="target/rocks/fork_${surefire.forkNumber}/edqs" + -Dqueue.calculated_fields.rocks_db_path="target/rocks/fork_${surefire.forkNumber}/cf" From 2c533c0f86dc3854e5a818d487cbd614d4bf7e37 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Tue, 20 Jan 2026 13:27:09 +0100 Subject: [PATCH 040/742] tests: reducing logging noise --- .../org/thingsboard/server/controller/AbstractWebTest.java | 2 +- application/src/test/resources/logback-test.xml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java index d540fcf49e..599dcf3138 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java @@ -404,7 +404,7 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { jdbcTemplate.execute("TRUNCATE TABLE notification"); - log.info("Executed web test teardown"); + log.debug("Executed web test teardown"); } private void verifyNoTenantsLeft() throws Exception { diff --git a/application/src/test/resources/logback-test.xml b/application/src/test/resources/logback-test.xml index 13c93da411..eafb4e1fba 100644 --- a/application/src/test/resources/logback-test.xml +++ b/application/src/test/resources/logback-test.xml @@ -42,6 +42,9 @@ + + + From 9a2489f5b69f3a449e977785af435c402f2e78f2 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Wed, 21 Jan 2026 22:23:07 +0100 Subject: [PATCH 041/742] tests: DefaultTbResourceDataCache destroy cache on bean destroy that fixes flaky test --- .../server/dao/resource/DefaultTbResourceDataCache.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dao/src/main/java/org/thingsboard/server/dao/resource/DefaultTbResourceDataCache.java b/dao/src/main/java/org/thingsboard/server/dao/resource/DefaultTbResourceDataCache.java index 343c37299e..925b8c2912 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/resource/DefaultTbResourceDataCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/resource/DefaultTbResourceDataCache.java @@ -19,6 +19,7 @@ import com.github.benmanes.caffeine.cache.AsyncLoadingCache; import com.github.benmanes.caffeine.cache.Caffeine; import com.google.common.util.concurrent.FluentFuture; import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -55,6 +56,12 @@ public class DefaultTbResourceDataCache implements TbResourceDataCache { .buildAsync((key, executor) -> CompletableFuture.supplyAsync(() -> resourceService.getResourceDataInfo(key.tenantId(), key.resourceId()), executor)); } + @PreDestroy + private void destroy() { + cache.synchronous().invalidateAll(); + cache = null; + } + @Override public FluentFuture getResourceDataInfoAsync(TenantId tenantId, TbResourceId resourceId) { log.trace("Retrieving resource data info by id [{}], tenant id [{}] from cache", resourceId, tenantId); From 7b9c53d348c66f4d398d4e71893d3ab6272574ef Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Wed, 21 Jan 2026 22:29:01 +0100 Subject: [PATCH 042/742] tests: EdgeImitator - fix for ConcurrentModification at AbstractEdgeTest.validateMsgsCnt:387 --- .../server/edge/imitator/EdgeImitator.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java index 36579e8e22..d1596b1c59 100644 --- a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java @@ -72,6 +72,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; @@ -102,8 +103,13 @@ public class EdgeImitator { @Getter private EdgeConfiguration configuration; - @Getter - private final List downlinkMsgs; + private final ConcurrentLinkedDeque downlinkMsgs; + + //Returns collection copy as Unmodifiable list + //This addressing the issue: DeviceEdgeTest>AbstractEdgeTest.setupEdgeTest:212->AbstractEdgeTest.verifyEdgeConnectionAndInitialData:306->AbstractEdgeTest.validateMsgsCnt:387 » ConcurrentModification + public List getDownlinkMsgs() { + return downlinkMsgs.stream().toList(); + } @Getter private UplinkResponseMsg latestResponseMsg; @@ -112,7 +118,7 @@ public class EdgeImitator { edgeRpcClient = new EdgeGrpcClient(); messagesLatch = new CountDownLatch(0); responsesLatch = new CountDownLatch(0); - downlinkMsgs = new ArrayList<>(); + downlinkMsgs = new ConcurrentLinkedDeque<>(); ignoredTypes = new ArrayList<>(); this.routingKey = routingKey; this.routingSecret = routingSecret; @@ -452,7 +458,7 @@ public class EdgeImitator { } public AbstractMessage getLatestMessage() { - return downlinkMsgs.get(downlinkMsgs.size() - 1); + return downlinkMsgs.peekLast(); } public void ignoreType(Class type) { From 5305ccf18081662c454b8e1f92e9973a3e4b2607 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Wed, 21 Jan 2026 22:45:56 +0100 Subject: [PATCH 043/742] tests: standardizing timeouts to address flakiness in parallel runs and busy CI env --- .../notification/NotificationRuleApiTest.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java index 41982ab91a..7175f0981d 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java @@ -237,12 +237,12 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { .set("bool", BooleanNode.TRUE); doPost("/api/plugins/telemetry/" + device.getId() + "/" + DataConstants.SHARED_SCOPE, attr); - await().atMost(10, TimeUnit.SECONDS) + await().atMost(TIMEOUT, TimeUnit.SECONDS) .until(() -> alarmSubscriptionService.findLatestByOriginatorAndType(tenantId, device.getId(), alarmType) != null); Alarm alarm = alarmSubscriptionService.findLatestByOriginatorAndType(tenantId, device.getId(), alarmType); long ts = System.currentTimeMillis(); - await().atMost(15, TimeUnit.SECONDS) + await().atMost(TIMEOUT, TimeUnit.SECONDS) .until(() -> clients.values().stream().allMatch(client -> client.getLastDataUpdate() != null)); clients.forEach((expectedDelay, wsClient) -> { Notification notification = wsClient.getLastDataUpdate().getUpdate(); @@ -290,8 +290,8 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { alarm.setOriginator(device.getId()); alarm = doPost("/api/alarm", alarm, Alarm.class); - await().atMost(15, TimeUnit.SECONDS) - .pollDelay(2, TimeUnit.SECONDS) + await().atMost(TIMEOUT, TimeUnit.SECONDS) + .pollDelay(1, TimeUnit.SECONDS) .untilAsserted(() -> { List notifications = getMyNotifications(false, 10); assertThat(notifications).singleElement().matches(notification -> { @@ -344,7 +344,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { .set("bool", BooleanNode.TRUE); doPost("/api/plugins/telemetry/" + device.getId() + "/" + DataConstants.SHARED_SCOPE, attr); - await().atMost(10, TimeUnit.SECONDS) + await().atMost(TIMEOUT, TimeUnit.SECONDS) .until(() -> alarmSubscriptionService.findLatestByOriginatorAndType(tenantId, device.getId(), alarmType) != null); Alarm alarm = alarmSubscriptionService.findLatestByOriginatorAndType(tenantId, device.getId(), alarmType); getWsClient().waitForUpdate(true); @@ -354,14 +354,14 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { assertThat(notification.getInfo()).asInstanceOf(type(AlarmNotificationInfo.class)) .extracting(AlarmNotificationInfo::getAlarmId).isEqualTo(alarm.getUuidId()); - await().atMost(10, TimeUnit.SECONDS).until(() -> findNotificationRequests(EntityType.ALARM).getTotalElements() == escalationTable.size()); + await().atMost(TIMEOUT, TimeUnit.SECONDS).until(() -> findNotificationRequests(EntityType.ALARM).getTotalElements() == escalationTable.size()); NotificationRequestInfo scheduledNotificationRequest = findNotificationRequests(EntityType.ALARM).getData().stream() .filter(NotificationRequest::isScheduled) .findFirst().orElse(null); assertThat(scheduledNotificationRequest).extracting(NotificationRequest::getInfo).isEqualTo(notification.getInfo()); alarmSubscriptionService.clearAlarm(tenantId, alarm.getId(), System.currentTimeMillis(), null); - await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> { + await().atMost(TIMEOUT, TimeUnit.SECONDS).untilAsserted(() -> { assertThat(findNotificationRequests(EntityType.ALARM).getData()).filteredOn(NotificationRequest::isScheduled).isEmpty(); }); } @@ -479,7 +479,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { } loginTenantAdmin(); - List notifications = await().atMost(15, TimeUnit.SECONDS) + List notifications = await().atMost(TIMEOUT, TimeUnit.SECONDS) .until(() -> getMyNotifications(true, 10).stream() .filter(notification -> notification.getType() == NotificationType.RATE_LIMITS) .collect(Collectors.toList()), list -> list.size() == 3); @@ -499,7 +499,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { }); loginSysAdmin(); - notifications = await().atMost(15, TimeUnit.SECONDS) + notifications = await().atMost(TIMEOUT, TimeUnit.SECONDS) .until(() -> getMyNotifications(true, 10).stream() .filter(notification -> notification.getType() == NotificationType.RATE_LIMITS) .collect(Collectors.toList()), list -> list.size() == 1); @@ -720,7 +720,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { .updateInfo(new UpdateMessage(true, "CHANGED", "test", "test", "test", "test")) .build()); - await().atMost(5, TimeUnit.SECONDS) + await().atMost(TIMEOUT, TimeUnit.SECONDS) .untilAsserted(() -> { assertThat(getMyNotifications(false, 100)).size().isEqualTo(2); }); @@ -803,7 +803,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { method.setAccessible(true); method.invoke(systemInfoService); - await().atMost(10, TimeUnit.SECONDS).until(() -> getMyNotifications(false, 100).size() == 1); + await().atMost(TIMEOUT, TimeUnit.SECONDS).until(() -> getMyNotifications(false, 100).size() == 1); Notification notification = getMyNotifications(false, 100).get(0); assertThat(notification.getSubject()).isEqualTo("Warning: RAM shortage"); assertThat(notification.getText()).isEqualTo("RAM shortage"); @@ -830,7 +830,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { .build()); TimeUnit.MILLISECONDS.sleep(300); } - await().atMost(10, TimeUnit.SECONDS).until(() -> getMyNotifications(false, 100).size() == 1); + await().atMost(TIMEOUT, TimeUnit.SECONDS).until(() -> getMyNotifications(false, 100).size() == 1); Notification notification = getMyNotifications(false, 100).get(0); assertThat(notification.getSubject()).isEqualTo("Warning: RAM shortage"); assertThat(notification.getText()).isEqualTo("RAM shortage"); @@ -842,7 +842,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { .serviceType("serviceType") .serviceId("serviceId") .build()); - await("").atMost(5, TimeUnit.SECONDS).untilAsserted(() -> assertThat(getMyNotifications(false, 100)).size().isOne()); + await("").atMost(TIMEOUT, TimeUnit.SECONDS).untilAsserted(() -> assertThat(getMyNotifications(false, 100)).size().isOne()); } @Test @@ -873,7 +873,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { method.invoke(systemInfoService); - await().atMost(10, TimeUnit.SECONDS).until(() -> getMyNotifications(false, 100).size() == 1); + await().atMost(TIMEOUT, TimeUnit.SECONDS).until(() -> getMyNotifications(false, 100).size() == 1); Notification notification = getMyNotifications(false, 100).get(0); assertThat(notification.getSubject()).isEqualTo("Warning: RAM shortage"); assertThat(notification.getText()).isEqualTo("RAM shortage"); From b35f46a8eedd4e3117aa10078ff30dc7172c198a Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Wed, 21 Jan 2026 23:22:44 +0100 Subject: [PATCH 044/742] tests: reducing logging noise for dao, cache for CaffeineCacheMetrics --- common/cache/src/test/resources/logback-test.xml | 3 +++ dao/src/test/resources/logback-test.xml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/common/cache/src/test/resources/logback-test.xml b/common/cache/src/test/resources/logback-test.xml index 29dddea8df..9b4c5b62df 100644 --- a/common/cache/src/test/resources/logback-test.xml +++ b/common/cache/src/test/resources/logback-test.xml @@ -9,6 +9,9 @@ + + + diff --git a/dao/src/test/resources/logback-test.xml b/dao/src/test/resources/logback-test.xml index fe0887c678..92cd10f2ca 100644 --- a/dao/src/test/resources/logback-test.xml +++ b/dao/src/test/resources/logback-test.xml @@ -19,6 +19,9 @@ + + + From 243fbec9301a07a643754de4c3e06fdbf173620b Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 22 Jan 2026 01:58:54 +0100 Subject: [PATCH 045/742] tests: spring.main.banner-mode=off --- application/src/test/resources/application-test.properties | 1 + dao/src/test/resources/application-test.properties | 1 + 2 files changed, 2 insertions(+) diff --git a/application/src/test/resources/application-test.properties b/application/src/test/resources/application-test.properties index b8bdcf67e6..e79289340c 100644 --- a/application/src/test/resources/application-test.properties +++ b/application/src/test/resources/application-test.properties @@ -1,3 +1,4 @@ +spring.main.banner-mode=off js.evaluator=mock transport.lwm2m.server.security.credentials.enabled=true transport.lwm2m.server.security.credentials.type=KEYSTORE diff --git a/dao/src/test/resources/application-test.properties b/dao/src/test/resources/application-test.properties index 1c2c0c5519..60605e1710 100644 --- a/dao/src/test/resources/application-test.properties +++ b/dao/src/test/resources/application-test.properties @@ -1,3 +1,4 @@ +spring.main.banner-mode=off zk.enabled=false zk.url=localhost:2181 zk.zk_dir=/thingsboard From 141ac802650dfe72061bf094371d4e5d792927b0 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 22 Jan 2026 02:14:35 +0100 Subject: [PATCH 046/742] tests: transport.mqtt.bind_port is @DynamicPropertySource. Dynamic MQTT port are set in a single AbstractMqttIntegrationTest to be compatible with parallel test run --- .../controller/EntityViewControllerTest.java | 14 ++++++++++++-- .../thingsboard/server/edge/DeviceEdgeTest.java | 10 ++++++++++ .../AbstractTransportIntegrationTest.java | 1 - .../mqtt/AbstractMqttIntegrationTest.java | 13 +++++++++++++ .../transport/mqtt/MqttGatewayRateLimitsTest.java | 10 ++++++++++ .../transport/mqtt/mqttv3/MqttTestClient.java | 6 +++++- .../transport/mqtt/mqttv5/MqttV5TestClient.java | 6 +++++- .../server/msa/rule/node/MqttNodeTest.java | 3 ++- 8 files changed, 57 insertions(+), 6 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/EntityViewControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/EntityViewControllerTest.java index 7812f769b1..421f3785ca 100644 --- a/application/src/test/java/org/thingsboard/server/controller/EntityViewControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/EntityViewControllerTest.java @@ -38,6 +38,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.TestPropertySource; import org.springframework.test.web.servlet.ResultActions; import org.thingsboard.common.util.ThingsBoardExecutors; @@ -85,6 +87,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; +import static org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest.MQTT_PORT; +import static org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest.MQTT_URL; @TestPropertySource(properties = { "transport.mqtt.enabled=true", @@ -94,6 +98,12 @@ import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; @ContextConfiguration(classes = {EntityViewControllerTest.Config.class}) @DaoSqlTest public class EntityViewControllerTest extends AbstractControllerTest { + @DynamicPropertySource + static void props(DynamicPropertyRegistry registry) { + log.warn("transport.mqtt.bind_port = {}", MQTT_PORT); + registry.add("transport.mqtt.bind_port", () -> MQTT_PORT); + } + static final TypeReference> PAGE_DATA_ENTITY_VIEW_TYPE_REF = new TypeReference<>() { }; static final TypeReference> PAGE_DATA_ENTITY_VIEW_INFO_TYPE_REF = new TypeReference<>() { @@ -650,7 +660,7 @@ public class EntityViewControllerTest extends AbstractControllerTest { String viewDeviceId = testDevice.getId().getId().toString(); String clientId = MqttAsyncClient.generateClientId(); - MqttAsyncClient client = new MqttAsyncClient("tcp://localhost:1883", clientId, new MemoryPersistence()); + MqttAsyncClient client = new MqttAsyncClient(MQTT_URL, clientId, new MemoryPersistence()); MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(accessToken); @@ -701,7 +711,7 @@ public class EntityViewControllerTest extends AbstractControllerTest { assertNotNull(accessToken); String clientId = MqttAsyncClient.generateClientId(); - MqttAsyncClient client = new MqttAsyncClient("tcp://localhost:1883", clientId, new MemoryPersistence()); + MqttAsyncClient client = new MqttAsyncClient(MQTT_URL, clientId, new MemoryPersistence()); MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(accessToken); diff --git a/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java index f9b89f4d2c..a8f82f8b7d 100644 --- a/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java @@ -22,10 +22,13 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.gson.JsonObject; import com.google.protobuf.AbstractMessage; import io.netty.handler.codec.mqtt.MqttQoS; +import lombok.extern.slf4j.Slf4j; import org.awaitility.Awaitility; import org.junit.Assert; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.TestPropertySource; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.adaptor.JsonConverter; @@ -85,12 +88,19 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.thingsboard.server.gen.edge.v1.UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE; +import static org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest.MQTT_PORT; @TestPropertySource(properties = { "transport.mqtt.enabled=true" }) +@Slf4j @DaoSqlTest public class DeviceEdgeTest extends AbstractEdgeTest { + @DynamicPropertySource + static void props(DynamicPropertyRegistry registry) { + log.warn("transport.mqtt.bind_port = {}", MQTT_PORT); + registry.add("transport.mqtt.bind_port", () -> MQTT_PORT); + } private static final String DEFAULT_DEVICE_TYPE = "default"; diff --git a/application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java index 0badcd2656..bc06d81588 100644 --- a/application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java @@ -30,7 +30,6 @@ public abstract class AbstractTransportIntegrationTest extends AbstractControlle protected static final int DEFAULT_WAIT_TIMEOUT_SECONDS = 30; - protected static final String MQTT_URL = "tcp://localhost:1883"; protected static final String COAP_BASE_URL = "coap://localhost:5683/api/v1/"; protected static final AtomicInteger atomicInteger = new AtomicInteger(2); diff --git a/application/src/test/java/org/thingsboard/server/transport/mqtt/AbstractMqttIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/mqtt/AbstractMqttIntegrationTest.java index 364b8fbe6a..962d85ec7c 100644 --- a/application/src/test/java/org/thingsboard/server/transport/mqtt/AbstractMqttIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/mqtt/AbstractMqttIntegrationTest.java @@ -19,7 +19,10 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import io.netty.handler.codec.mqtt.MqttQoS; import lombok.extern.slf4j.Slf4j; import org.eclipse.paho.client.mqttv3.MqttException; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.TestPropertySource; +import org.springframework.test.util.TestSocketUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; @@ -58,6 +61,16 @@ import static org.junit.Assert.assertNotNull; @Slf4j public abstract class AbstractMqttIntegrationTest extends AbstractTransportIntegrationTest { + public static final String MQTT_HOST = "localhost"; + public static final int MQTT_PORT = TestSocketUtils.findAvailableTcpPort(); + public static final String MQTT_URL = "tcp://" + MQTT_HOST + ":" + MQTT_PORT; + + @DynamicPropertySource + static void props(DynamicPropertyRegistry registry) { + log.warn("transport.mqtt.bind_port = {}", MQTT_PORT); + registry.add("transport.mqtt.bind_port", () -> MQTT_PORT); + } + protected Device savedGateway; protected String gatewayAccessToken; diff --git a/application/src/test/java/org/thingsboard/server/transport/mqtt/MqttGatewayRateLimitsTest.java b/application/src/test/java/org/thingsboard/server/transport/mqtt/MqttGatewayRateLimitsTest.java index c455ae45d4..541ca40072 100644 --- a/application/src/test/java/org/thingsboard/server/transport/mqtt/MqttGatewayRateLimitsTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/mqtt/MqttGatewayRateLimitsTest.java @@ -16,12 +16,15 @@ package org.thingsboard.server.transport.mqtt; import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.extern.slf4j.Slf4j; import org.awaitility.Awaitility; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.TestPropertySource; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Device; @@ -43,13 +46,20 @@ import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.eq; import static org.thingsboard.server.common.data.limit.LimitedApi.TRANSPORT_MESSAGES_PER_GATEWAY; import static org.thingsboard.server.common.data.limit.LimitedApi.TRANSPORT_MESSAGES_PER_GATEWAY_DEVICE; +import static org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest.MQTT_PORT; @DaoSqlTest @TestPropertySource(properties = { "service.integrations.supported=ALL", "transport.mqtt.enabled=true", }) +@Slf4j public class MqttGatewayRateLimitsTest extends AbstractControllerTest { + @DynamicPropertySource + static void props(DynamicPropertyRegistry registry) { + log.warn("transport.mqtt.bind_port = {}", MQTT_PORT); + registry.add("transport.mqtt.bind_port", () -> MQTT_PORT); + } private static final String GATEWAY_TOPIC = "v1/gateway/telemetry"; private static final String DEVICE_TOPIC = "v1/devices/me/telemetry"; diff --git a/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/MqttTestClient.java b/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/MqttTestClient.java index 7e5cc031a5..4c34d9bc81 100644 --- a/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/MqttTestClient.java +++ b/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/MqttTestClient.java @@ -27,12 +27,16 @@ import org.thingsboard.server.common.data.StringUtils; import java.util.concurrent.TimeUnit; +import static org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest.MQTT_HOST; +import static org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest.MQTT_PORT; + public class MqttTestClient { - private static final String MQTT_URL = "tcp://localhost:1883"; private static final int TIMEOUT = 30; // seconds public static final long TIMEOUT_MS = TimeUnit.SECONDS.toMillis(TIMEOUT); + private String MQTT_URL = "tcp://" + MQTT_HOST + ":" + MQTT_PORT; + private final MqttAsyncClient client; public void setCallback(MqttTestCallback callback) { diff --git a/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv5/MqttV5TestClient.java b/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv5/MqttV5TestClient.java index 545fc148e2..558fa1a46a 100644 --- a/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv5/MqttV5TestClient.java +++ b/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv5/MqttV5TestClient.java @@ -27,12 +27,16 @@ import org.thingsboard.server.common.data.StringUtils; import java.util.concurrent.TimeUnit; +import static org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest.MQTT_HOST; +import static org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest.MQTT_PORT; + public class MqttV5TestClient { // We should copy part of MqttV3TestClient, due to different package names in import - private static final String MQTT_URL = "tcp://localhost:1883"; private static final int TIMEOUT = 30; // seconds private static final long TIMEOUT_MS = TimeUnit.SECONDS.toMillis(TIMEOUT); + private String MQTT_URL = "tcp://" + MQTT_HOST + ":" + MQTT_PORT; + private final MqttAsyncClient client; public void setCallback(MqttCallback callback) { diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/rule/node/MqttNodeTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/rule/node/MqttNodeTest.java index 67f6258767..6fff0b4b6a 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/rule/node/MqttNodeTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/rule/node/MqttNodeTest.java @@ -65,6 +65,7 @@ import static org.thingsboard.server.msa.prototypes.DevicePrototypes.defaultDevi public class MqttNodeTest extends AbstractContainerTest { private static final String TOPIC = "tb/mqtt/device"; + private static final String CONTAINER_MQTT_URL = "tcp://localhost:1883"; private Device device; @@ -94,7 +95,7 @@ public class MqttNodeTest extends AbstractContainerTest { responseClient.connect(); responseClient.subscribe(TOPIC, messageListener); - MqttClient mqttClient = new MqttClient("tcp://localhost:1883", StringUtils.randomAlphanumeric(10), new MemoryPersistence()); + MqttClient mqttClient = new MqttClient(CONTAINER_MQTT_URL, StringUtils.randomAlphanumeric(10), new MemoryPersistence()); MqttConnectOptions mqttConnectOptions = new MqttConnectOptions(); mqttConnectOptions.setUserName(deviceCredentials.getCredentialsId()); mqttClient.connect(mqttConnectOptions); From 9577cb0aeed2127d6911109b5084e8bd1c27135a Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 22 Jan 2026 03:17:00 +0100 Subject: [PATCH 047/742] tests: PortFinder.findAvailableUdpPort added --- .../thingsboard/server/utils/PortFinder.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 application/src/test/java/org/thingsboard/server/utils/PortFinder.java diff --git a/application/src/test/java/org/thingsboard/server/utils/PortFinder.java b/application/src/test/java/org/thingsboard/server/utils/PortFinder.java new file mode 100644 index 0000000000..23990363ce --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/utils/PortFinder.java @@ -0,0 +1,29 @@ +/** + * Copyright © 2016-2026 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.utils; + +import java.net.DatagramSocket; +import java.net.SocketException; + +public class PortFinder { + public static int findAvailableUdpPort() { + try (DatagramSocket socket = new DatagramSocket(0)) { + return socket.getLocalPort(); + } catch (SocketException e) { + throw new IllegalStateException("No available UDP ports found", e); + } + } +} From bcfe4c26417d09a55d33d11e8b0879dd50de5a5b Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 22 Jan 2026 03:18:48 +0100 Subject: [PATCH 048/742] tests: coap transport tests refactored to use dynamic UPD ports to be able to test in parallel --- .../AbstractTransportIntegrationTest.java | 2 -- .../coap/AbstractCoapIntegrationTest.java | 14 ++++++++ .../server/transport/coap/CoapTestClient.java | 3 +- .../AbstractCoapSecurityIntegrationTest.java | 36 ++++++++++++------- .../server/msa/AbstractCoapClientTest.java | 4 +-- 5 files changed, 42 insertions(+), 17 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java index bc06d81588..b0a1d21992 100644 --- a/application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java @@ -30,8 +30,6 @@ public abstract class AbstractTransportIntegrationTest extends AbstractControlle protected static final int DEFAULT_WAIT_TIMEOUT_SECONDS = 30; - protected static final String COAP_BASE_URL = "coap://localhost:5683/api/v1/"; - protected static final AtomicInteger atomicInteger = new AtomicInteger(2); public static final String DEVICE_TELEMETRY_PROTO_SCHEMA = "syntax =\"proto3\";\n" + diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java index 7240ab0afa..cf23a5be97 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java @@ -16,7 +16,10 @@ package org.thingsboard.server.transport.coap; import lombok.extern.slf4j.Slf4j; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.TestPropertySource; +import org.springframework.test.util.TestSocketUtils; import org.thingsboard.server.common.data.CoapDeviceType; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; @@ -40,6 +43,7 @@ import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadCo import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.transport.AbstractTransportIntegrationTest; +import org.thingsboard.server.utils.PortFinder; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -52,6 +56,16 @@ import static org.junit.Assert.assertNotNull; @Slf4j public abstract class AbstractCoapIntegrationTest extends AbstractTransportIntegrationTest { + public static final String COAP_HOST = "localhost"; + public static final int COAP_PORT = PortFinder.findAvailableUdpPort(); + public static final String COAP_BASE_URL = "coap://" + COAP_HOST + ":" + COAP_PORT + "/api/v1/"; + + @DynamicPropertySource + static void props(DynamicPropertyRegistry registry) { + log.info("coap.bind_port = {}", COAP_PORT); + registry.add("coap.bind_port", () -> COAP_PORT); + } + protected final byte[] EMPTY_PAYLOAD = new byte[0]; protected CoapTestClient client; protected static final String PAYLOAD_VALUES_STR = "{\"key1\":\"value1\", \"key2\":true, \"key3\": 3.0, \"key4\": 4," + diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/CoapTestClient.java b/application/src/test/java/org/thingsboard/server/transport/coap/CoapTestClient.java index ce72d68fc6..df7e9babc9 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/CoapTestClient.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/CoapTestClient.java @@ -28,9 +28,10 @@ import org.thingsboard.server.common.msg.session.FeatureType; import java.io.IOException; +import static org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest.COAP_BASE_URL; + public class CoapTestClient { - private static final String COAP_BASE_URL = "coap://localhost:5683/api/v1/"; private static final long CLIENT_REQUEST_TIMEOUT = 60000L; private final CoapClient client; diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java index cfb449aa33..9c42d87369 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java @@ -21,7 +21,10 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.californium.core.CoapResponse; import org.eclipse.californium.core.coap.CoAP; import org.junit.Assert; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.TestPropertySource; +import org.springframework.test.util.TestSocketUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.CoapDeviceType; import org.thingsboard.server.common.data.Device; @@ -37,9 +40,11 @@ import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; import org.thingsboard.server.transport.coap.x509.CertPrivateKey; import org.thingsboard.server.transport.coap.x509.CoapClientX509Test; import org.thingsboard.server.transport.coap.CoapTestConfigProperties; +import org.thingsboard.server.utils.PortFinder; import java.io.IOException; import java.io.InputStream; +import java.net.DatagramSocket; import java.net.ServerSocket; import java.security.GeneralSecurityException; import java.security.KeyStore; @@ -70,7 +75,17 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. "transport.coap.enabled=true", }) public abstract class AbstractCoapSecurityIntegrationTest extends AbstractCoapIntegrationTest { - private static final String COAPS_BASE_URL = "coaps://localhost:5684/api/v1/"; + + public static final String COAPS_HOST = "localhost"; + public static final int COAPS_PORT = PortFinder.findAvailableUdpPort(); + public static final String COAPS_BASE_URL = "coaps://" + COAPS_HOST + ":" + COAPS_PORT + "/api/v1/"; + + @DynamicPropertySource + static void props(DynamicPropertyRegistry registry) { + log.info("coap.dtls.bind_port = {}", COAPS_PORT); + registry.add("coap.dtls.bind_port", () -> COAPS_PORT); + } + protected final String CREDENTIALS_PATH = "coap/credentials/"; protected final String CREDENTIALS_PATH_CLIENT = CREDENTIALS_PATH + "client/"; protected final String CREDENTIALS_PATH_CLIENT_CERT_PEM = CREDENTIALS_PATH_CLIENT + "cert.pem"; @@ -160,17 +175,20 @@ public abstract class AbstractCoapSecurityIntegrationTest extends AbstractCoapIn CertPrivateKey certPrivateKey = new CertPrivateKey(CREDENTIALS_PATH_CLIENT_CERT_PEM, CREDENTIALS_PATH_CLIENT_KEY_PEM); CertPrivateKey certPrivateKey_01 = new CertPrivateKey(CREDENTIALS_PATH_CLIENT + "cert_01.pem", CREDENTIALS_PATH_CLIENT + "key_01.pem"); - Integer fixedPort = getFreePort(); + int fixedPort = PortFinder.findAvailableUdpPort(); CoapClientX509Test clientX509 = clientX509UpdateTest(FeatureType.ATTRIBUTES, certPrivateKey, "CoapX509TrustNo_" + FeatureType.TELEMETRY.name(), deviceProfile.getId(), fixedPort); clientX509.disconnect(); await("Need to make port " + fixedPort + " free") .atMost(40, TimeUnit.SECONDS) - .until(() -> isPortAvailable(fixedPort)); + .until(() -> isUDPPortAvailable(fixedPort)); CoapClientX509Test clientX509_01 = clientX509UpdateTest(FeatureType.ATTRIBUTES, certPrivateKey_01, "CoapX509TrustNo_" + FeatureType.TELEMETRY.name() + "_01", deviceProfile.getId(), fixedPort, PAYLOAD_VALUES_STR_01); clientX509_01.disconnect(); + await("Await to make port " + fixedPort + " free") + .atMost(40, TimeUnit.SECONDS) + .until(() -> isUDPPortAvailable(fixedPort)); } private CoapClientX509Test clientX509UpdateTest(FeatureType featureType, CertPrivateKey certPrivateKey, @@ -274,15 +292,9 @@ public abstract class AbstractCoapSecurityIntegrationTest extends AbstractCoapIn } } - private static int getFreePort() throws IOException { - try (ServerSocket socket = new ServerSocket(0)) { - return socket.getLocalPort(); - } - } - - private static boolean isPortAvailable(int port) { - try (ServerSocket serverSocket = new ServerSocket(port)) { - serverSocket.setReuseAddress(true); + private static boolean isUDPPortAvailable(int port) { + try (DatagramSocket socket = new DatagramSocket(port)) { + socket.setReuseAddress(true); return true; } catch (IOException e) { return false; diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractCoapClientTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractCoapClientTest.java index d4d9d08474..e409a82600 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractCoapClientTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractCoapClientTest.java @@ -28,7 +28,7 @@ import org.thingsboard.server.common.msg.session.FeatureType; public abstract class AbstractCoapClientTest extends AbstractContainerTest{ - private static final String COAP_BASE_URL = "coap://localhost:5683/api/v1/"; + private static final String CONTAINER_COAP_BASE_URL = "coap://localhost:5683/api/v1/"; private static final long CLIENT_REQUEST_TIMEOUT = 60000L; @@ -54,7 +54,7 @@ public abstract class AbstractCoapClientTest extends AbstractContainerTest{ protected byte[] createCoapClientAndPublish(String deviceName) throws Exception { String provisionRequestMsg = createTestProvisionMessage(deviceName); Configuration.addDefaultModule(MODULE_DEFINITIONS_PROVIDER); - String featureTokenUrl = COAP_BASE_URL + FeatureType.PROVISION.name().toLowerCase(); + String featureTokenUrl = CONTAINER_COAP_BASE_URL + FeatureType.PROVISION.name().toLowerCase(); client = new CoapClient(featureTokenUrl); return client.setTimeout(CLIENT_REQUEST_TIMEOUT) .post(provisionRequestMsg.getBytes(), MediaTypeRegistry.APPLICATION_JSON) From f4334436ff45c0653fafd53d80f818ff3b6b9c7e Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 22 Jan 2026 03:46:12 +0100 Subject: [PATCH 049/742] tests: log warn dynamic property coap.bind_port coap.dtls.bind_port --- .../server/transport/coap/AbstractCoapIntegrationTest.java | 2 +- .../coap/security/AbstractCoapSecurityIntegrationTest.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java index cf23a5be97..69d40f5409 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java @@ -62,7 +62,7 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg @DynamicPropertySource static void props(DynamicPropertyRegistry registry) { - log.info("coap.bind_port = {}", COAP_PORT); + log.warn("coap.bind_port = {}", COAP_PORT); registry.add("coap.bind_port", () -> COAP_PORT); } diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java index 9c42d87369..b0531457a4 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java @@ -82,7 +82,7 @@ public abstract class AbstractCoapSecurityIntegrationTest extends AbstractCoapIn @DynamicPropertySource static void props(DynamicPropertyRegistry registry) { - log.info("coap.dtls.bind_port = {}", COAPS_PORT); + log.warn("coap.dtls.bind_port = {}", COAPS_PORT); registry.add("coap.dtls.bind_port", () -> COAPS_PORT); } @@ -297,6 +297,7 @@ public abstract class AbstractCoapSecurityIntegrationTest extends AbstractCoapIn socket.setReuseAddress(true); return true; } catch (IOException e) { + log.warn("Failed to open UDP port on port " + port, e); return false; } } From 189c2ac6ae30245e989b509751a9b529071cde7a Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 22 Jan 2026 03:48:43 +0100 Subject: [PATCH 050/742] tests: fixed Coap X509 Test client by calling dtlsConnector.destroy() on client.disconnect(); --- .../server/transport/coap/x509/CoapClientX509Test.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/x509/CoapClientX509Test.java b/application/src/test/java/org/thingsboard/server/transport/coap/x509/CoapClientX509Test.java index 0f65298d86..aff3902609 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/x509/CoapClientX509Test.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/x509/CoapClientX509Test.java @@ -97,6 +97,9 @@ public class CoapClientX509Test { if (clientX509 != null) { clientX509.shutdown(); } + if (dtlsConnector != null) { + dtlsConnector.destroy(); + } } public CoapResponse postMethod(String requestBody) throws ConnectorException, IOException { From 94f30191884478eea88ca05fafdcde5c8f44591e Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 22 Jan 2026 14:51:20 +0100 Subject: [PATCH 051/742] tests: AbstractCoapSecurityIntegrationTest import cleanup --- .../coap/security/AbstractCoapSecurityIntegrationTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java index b0531457a4..ec68a346f0 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java @@ -45,7 +45,6 @@ import org.thingsboard.server.utils.PortFinder; import java.io.IOException; import java.io.InputStream; import java.net.DatagramSocket; -import java.net.ServerSocket; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.PrivateKey; From 59ff87d2bcd905b025b20a84f7c56b3b41d9674c Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 22 Jan 2026 14:53:21 +0100 Subject: [PATCH 052/742] DeviceProfileDataValidator - refactored validation to allow use-defined ports for LWM@M (also useful for tests in parallel). Addressing the issue: DeviceProfile object is invalid: [LwM2M Server "Port" value = 53197. This value for security PSK must be 5686!] --- .../validator/DeviceProfileDataValidator.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceProfileDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceProfileDataValidator.java index 130251eb35..6402ec0d1f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceProfileDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceProfileDataValidator.java @@ -96,6 +96,18 @@ public class DeviceProfileDataValidator extends AbstractHasOtaPackageValidator Date: Thu, 22 Jan 2026 16:06:26 +0100 Subject: [PATCH 053/742] tests: CoapClientX509Test disconnect() is awaiting until UDP fixedPort released. reuse socket removed for UPD isUDPPortAvailable as not useful --- .../AbstractTransportIntegrationTest.java | 2 +- .../AbstractCoapSecurityIntegrationTest.java | 19 ------------------- .../coap/x509/CoapClientX509Test.java | 11 +++++++++++ .../thingsboard/server/utils/PortFinder.java | 13 +++++++++++++ 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java index b0a1d21992..c91fea282d 100644 --- a/application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java @@ -28,7 +28,7 @@ import java.util.concurrent.atomic.AtomicInteger; @Slf4j public abstract class AbstractTransportIntegrationTest extends AbstractControllerTest { - protected static final int DEFAULT_WAIT_TIMEOUT_SECONDS = 30; + public static final int DEFAULT_WAIT_TIMEOUT_SECONDS = 30; protected static final AtomicInteger atomicInteger = new AtomicInteger(2); diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java index ec68a346f0..04434ff53d 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/security/AbstractCoapSecurityIntegrationTest.java @@ -24,7 +24,6 @@ import org.junit.Assert; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.util.TestSocketUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.CoapDeviceType; import org.thingsboard.server.common.data.Device; @@ -44,7 +43,6 @@ import org.thingsboard.server.utils.PortFinder; import java.io.IOException; import java.io.InputStream; -import java.net.DatagramSocket; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.PrivateKey; @@ -55,9 +53,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.TimeUnit; -import static org.awaitility.Awaitility.await; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -178,16 +174,10 @@ public abstract class AbstractCoapSecurityIntegrationTest extends AbstractCoapIn CoapClientX509Test clientX509 = clientX509UpdateTest(FeatureType.ATTRIBUTES, certPrivateKey, "CoapX509TrustNo_" + FeatureType.TELEMETRY.name(), deviceProfile.getId(), fixedPort); clientX509.disconnect(); - await("Need to make port " + fixedPort + " free") - .atMost(40, TimeUnit.SECONDS) - .until(() -> isUDPPortAvailable(fixedPort)); CoapClientX509Test clientX509_01 = clientX509UpdateTest(FeatureType.ATTRIBUTES, certPrivateKey_01, "CoapX509TrustNo_" + FeatureType.TELEMETRY.name() + "_01", deviceProfile.getId(), fixedPort, PAYLOAD_VALUES_STR_01); clientX509_01.disconnect(); - await("Await to make port " + fixedPort + " free") - .atMost(40, TimeUnit.SECONDS) - .until(() -> isUDPPortAvailable(fixedPort)); } private CoapClientX509Test clientX509UpdateTest(FeatureType featureType, CertPrivateKey certPrivateKey, @@ -291,14 +281,5 @@ public abstract class AbstractCoapSecurityIntegrationTest extends AbstractCoapIn } } - private static boolean isUDPPortAvailable(int port) { - try (DatagramSocket socket = new DatagramSocket(port)) { - socket.setReuseAddress(true); - return true; - } catch (IOException e) { - log.warn("Failed to open UDP port on port " + port, e); - return false; - } - } } diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/x509/CoapClientX509Test.java b/application/src/test/java/org/thingsboard/server/transport/coap/x509/CoapClientX509Test.java index aff3902609..ebbed25243 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/x509/CoapClientX509Test.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/x509/CoapClientX509Test.java @@ -51,6 +51,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static org.awaitility.Awaitility.await; import static org.eclipse.californium.core.config.CoapConfig.DEFAULT_BLOCKWISE_STATUS_LIFETIME_IN_SECONDS; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_AUTO_HANDSHAKE_TIMEOUT; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CIPHER_SUITES; @@ -71,6 +72,8 @@ import static org.eclipse.californium.scandium.config.DtlsConfig.MODULE; import static org.eclipse.californium.scandium.dtls.SignatureAndHashAlgorithm.SHA256_WITH_ECDSA; import static org.eclipse.californium.scandium.dtls.SignatureAndHashAlgorithm.SHA256_WITH_RSA; import static org.eclipse.californium.scandium.dtls.SignatureAndHashAlgorithm.SHA384_WITH_ECDSA; +import static org.thingsboard.server.transport.AbstractTransportIntegrationTest.DEFAULT_WAIT_TIMEOUT_SECONDS; +import static org.thingsboard.server.utils.PortFinder.isUDPPortAvailable; @Slf4j public class CoapClientX509Test { @@ -82,6 +85,7 @@ public class CoapClientX509Test { private final Configuration config; private final CertPrivateKey certPrivateKey; private final String coapsBaseUrl; + private final Integer fixedPort; @Getter private CoAP.Type type = CoAP.Type.CON; @@ -90,6 +94,7 @@ public class CoapClientX509Test { this.certPrivateKey = certPrivateKey; this.coapsBaseUrl = coapsBaseUrl; this.config = createConfiguration(); + this.fixedPort = fixedPort; this.dtlsConnector = createDTLSConnector(fixedPort); this.clientX509 = createClient(getFeatureTokenUrl(featureType)); } @@ -99,6 +104,12 @@ public class CoapClientX509Test { } if (dtlsConnector != null) { dtlsConnector.destroy(); + if (fixedPort != null) { + log.debug("Awaiting releasing UDP fixedPort {}", fixedPort); + await("Await client UDP port " + fixedPort + " to disconnect") + .atMost(DEFAULT_WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS) + .until(() -> isUDPPortAvailable(fixedPort)); + } } } diff --git a/application/src/test/java/org/thingsboard/server/utils/PortFinder.java b/application/src/test/java/org/thingsboard/server/utils/PortFinder.java index 23990363ce..21a1f1eb0d 100644 --- a/application/src/test/java/org/thingsboard/server/utils/PortFinder.java +++ b/application/src/test/java/org/thingsboard/server/utils/PortFinder.java @@ -15,9 +15,13 @@ */ package org.thingsboard.server.utils; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; import java.net.DatagramSocket; import java.net.SocketException; +@Slf4j public class PortFinder { public static int findAvailableUdpPort() { try (DatagramSocket socket = new DatagramSocket(0)) { @@ -26,4 +30,13 @@ public class PortFinder { throw new IllegalStateException("No available UDP ports found", e); } } + + public static boolean isUDPPortAvailable(int port) { + try (DatagramSocket socket = new DatagramSocket(port)) { + return true; + } catch (IOException e) { + log.debug("Failed to open UDP port {}", port, e); + return false; + } + } } From a706859711f995bfa53c358e20101f77377d6fac Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 22 Jan 2026 19:13:46 +0100 Subject: [PATCH 054/742] tests: log MockMvc error responses >= 400 for easier investigation --- .../thingsboard/server/controller/AbstractWebTest.java | 10 +++++++++- application/src/test/resources/logback-test.xml | 3 +++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java index 599dcf3138..44c383a5f0 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java @@ -60,6 +60,7 @@ import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.ResultMatcher; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.context.WebApplicationContext; @@ -330,7 +331,14 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { if (this.mockMvc == null) { this.mockMvc = webAppContextSetup(webApplicationContext) - .apply(springSecurity()).build(); + .apply(springSecurity()) + // conditional printing of non 2xx responses + .alwaysDo(result -> { + if (result.getResponse().getStatus() >= 400) { + MockMvcResultHandlers.log().handle(result); + } + }) + .build(); } loginSysAdmin(); diff --git a/application/src/test/resources/logback-test.xml b/application/src/test/resources/logback-test.xml index eafb4e1fba..6faaf97536 100644 --- a/application/src/test/resources/logback-test.xml +++ b/application/src/test/resources/logback-test.xml @@ -45,6 +45,9 @@ + + + From 45da022944b4bb0e66a6491154b32763bd43ab0b Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 22 Jan 2026 19:15:35 +0100 Subject: [PATCH 055/742] tests: bump versions 3.5.4 1.21.4 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index bfb4bbf1ae..58e0c32e43 100755 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ 1.2.5 1.2.5 1.7.1 - 3.2.5 + 3.5.4 3.4.0 2.8.8TB 2.2.30 @@ -127,7 +127,7 @@ 5.0.0 7.10.1 - 1.20.6 + 1.21.4 1.0.2 1.12 6.1.0 From a4f755b624457d77024f56fa6250e6645590c159 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 22 Jan 2026 19:21:31 +0100 Subject: [PATCH 056/742] tests: refactored blackbox test for LWM2M test client (UDP DatagramSocket instead TCP ServerSocket), ensure UDP socket is available before and after LWM2M client start stop --- .../thingsboard/server/msa/PortFinder.java | 42 +++++++++++++++++++ .../lwm2m/AbstractLwm2mClientTest.java | 8 ++-- .../lwm2m/client/LwM2MTestClient.java | 21 +++++++++- 3 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/PortFinder.java diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/PortFinder.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/PortFinder.java new file mode 100644 index 0000000000..8bd036bf15 --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/PortFinder.java @@ -0,0 +1,42 @@ +/** + * Copyright © 2016-2026 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.msa; + +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.net.DatagramSocket; +import java.net.SocketException; + +@Slf4j +public class PortFinder { + public static int findAvailableUdpPort() { + try (DatagramSocket socket = new DatagramSocket(0)) { + return socket.getLocalPort(); + } catch (SocketException e) { + throw new IllegalStateException("No available UDP ports found", e); + } + } + + public static boolean isUDPPortAvailable(int port) { + try (DatagramSocket socket = new DatagramSocket(port)) { + return true; + } catch (IOException e) { + log.debug("Failed to open UDP port {}", port, e); + return false; + } + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/lwm2m/AbstractLwm2mClientTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/lwm2m/AbstractLwm2mClientTest.java index f991e1b29c..c5673ae667 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/lwm2m/AbstractLwm2mClientTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/lwm2m/AbstractLwm2mClientTest.java @@ -57,12 +57,12 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.msa.AbstractContainerTest; +import org.thingsboard.server.msa.PortFinder; import org.thingsboard.server.msa.WsClient; import org.thingsboard.server.msa.connectivity.lwm2m.client.LwM2MTestClient; import org.thingsboard.server.msa.connectivity.lwm2m.client.Lwm2mTestHelper.LwM2MClientState; import org.thingsboard.server.msa.mapper.WsTelemetryResponse; -import java.net.ServerSocket; import java.nio.charset.StandardCharsets; import java.time.Instant; import java.util.ArrayList; @@ -229,10 +229,8 @@ public class AbstractLwm2mClientTest extends AbstractContainerTest { String endpoint, ScheduledExecutorService executor) throws Exception { this.executor = executor; LwM2MTestClient lwM2MTestClient = new LwM2MTestClient(executor, endpoint); - try (ServerSocket socket = new ServerSocket(0)) { - int clientPort = socket.getLocalPort(); - lwM2MTestClient.init(security, clientPort); - } + int clientPort = PortFinder.findAvailableUdpPort(); + lwM2MTestClient.init(security, clientPort); return lwM2MTestClient; } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/lwm2m/client/LwM2MTestClient.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/lwm2m/client/LwM2MTestClient.java index 64f4d6f08a..61a763562c 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/lwm2m/client/LwM2MTestClient.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/lwm2m/client/LwM2MTestClient.java @@ -65,6 +65,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_LENGTH; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY; import static org.eclipse.leshan.core.LwM2mId.ACCESS_CONTROL; @@ -72,6 +73,7 @@ import static org.eclipse.leshan.core.LwM2mId.DEVICE; import static org.eclipse.leshan.core.LwM2mId.FIRMWARE; import static org.eclipse.leshan.core.LwM2mId.SECURITY; import static org.eclipse.leshan.core.LwM2mId.SERVER; +import static org.thingsboard.server.msa.PortFinder.isUDPPortAvailable; import static org.thingsboard.server.msa.connectivity.lwm2m.client.Lwm2mTestHelper.BINARY_APP_DATA_CONTAINER; import static org.thingsboard.server.msa.connectivity.lwm2m.client.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_FAILURE; import static org.thingsboard.server.msa.connectivity.lwm2m.client.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_STARTED; @@ -95,7 +97,6 @@ import static org.thingsboard.server.msa.connectivity.lwm2m.client.Lwm2mTestHelp import static org.thingsboard.server.msa.connectivity.lwm2m.client.Lwm2mTestHelper.serverId; import static org.thingsboard.server.msa.connectivity.lwm2m.client.Lwm2mTestHelper.shortServerId; - @Slf4j @Data public class LwM2MTestClient { @@ -115,8 +116,11 @@ public class LwM2MTestClient { private int countUpdateRegistrationSuccess; private int countReadObserveAfterUpdateRegistrationSuccess; + private int clientPort; + public void init(Security security, int clientPort) throws InvalidDDFFileException, IOException { assertThat(leshanClient).as("client already initialized").isNull(); + this.clientPort = clientPort; List models = new ArrayList<>(); for (String resourceName : resources) { @@ -342,12 +346,27 @@ public class LwM2MTestClient { } }); + } + + public void start() { leshanClient.start(); + if (clientPort > 0) { + log.error("Await UDP clientPort {} to be available before leshanClient.start()", clientPort); + await("Await UDP clientPort " + clientPort + " to be available before leshanClient.start()") + .atMost(30, TimeUnit.SECONDS) + .until(() -> isUDPPortAvailable(clientPort)); + } } public void destroy() { if (leshanClient != null) { leshanClient.destroy(true); + if (clientPort > 0) { + log.error("Await UDP clientPort {} to disconnect after leshanClient.stop(deregister)", clientPort); + await("Await client UDP port " + clientPort + " to disconnect after leshanClient.stop(deregister)") + .atMost(30, TimeUnit.SECONDS) + .until(() -> isUDPPortAvailable(clientPort)); + } } if (lwM2MDevice != null) { lwM2MDevice.destroy(); From 4bd812b6fdcabe022ba52ad0449067fc601d561f Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 22 Jan 2026 19:33:56 +0100 Subject: [PATCH 057/742] tests: LWM2M transport refactored and fixed to run in parallel. Improved UPD port operation experience for stability. additional logs added --- .../lwm2m/AbstractLwM2MIntegrationTest.java | 61 ++++++++++++------- .../transport/lwm2m/client/FwLwM2MDevice.java | 2 +- .../lwm2m/client/LwM2MTestClient.java | 24 +++++++- .../lwm2m/client/LwM2mTemperatureSensor.java | 1 + .../AbstractSecurityLwM2MIntegrationTest.java | 4 +- .../security/sql/PskLwm2mIntegrationTest.java | 4 +- pom.xml | 15 ++++- 7 files changed, 81 insertions(+), 30 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java index c323df200a..8d0f0f2af0 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java @@ -38,6 +38,8 @@ import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.http.HttpStatus; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.TestPropertySource; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.ThingsBoardExecutors; @@ -84,8 +86,8 @@ import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; import org.thingsboard.server.transport.lwm2m.server.client.ResourceUpdateResult; import org.thingsboard.server.transport.lwm2m.server.uplink.DefaultLwM2mUplinkMsgHandler; import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler; +import org.thingsboard.server.utils.PortFinder; -import java.net.ServerSocket; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -140,13 +142,27 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte private LwM2mClientContext clientContextTest; // Lwm2m Server - public static final int port = 5685; - public static final int securityPort = 5686; - public static final int portBs = 5687; - public static final int securityPortBs = 5688; + public static final String LWM2M_HOST = "localhost"; + public static final int LWM2M_PORT = PortFinder.findAvailableUdpPort(); // 5685 + public static final int LWM2MS_PORT = PortFinder.findAvailableUdpPort(); //5686 + + public static final String LWM2M_BOOTSTRAP_HOST = "localhost"; + public static final int LWM2M_BOOTSTRAP_PORT = PortFinder.findAvailableUdpPort(); // 5687 + public static final int LWM2MS_BOOTSTRAP_PORT = PortFinder.findAvailableUdpPort(); // 5688 + + @DynamicPropertySource + static void props(DynamicPropertyRegistry registry) { + log.warn("transport.lwm2m.server.bind_port = {}", LWM2M_PORT); + registry.add("transport.lwm2m.server.bind_port", () -> LWM2M_PORT); + log.warn("transport.lwm2m.server.security.bind_port = {}", LWM2MS_PORT); + registry.add("transport.lwm2m.server.security.bind_port", () -> LWM2MS_PORT); + + log.warn("transport.lwm2m.bootstrap.bind_port = {}", LWM2M_BOOTSTRAP_PORT); + registry.add("transport.lwm2m.bootstrap.bind_port", () -> LWM2M_BOOTSTRAP_PORT); + log.warn("transport.lwm2m.bootstrap.security.bind_port = {}", LWM2MS_BOOTSTRAP_PORT); + registry.add("transport.lwm2m.bootstrap.security.bind_port", () -> LWM2MS_BOOTSTRAP_PORT); + } - public static final String host = "localhost"; - public static final String hostBs = "localhost"; public static final Integer shortServerId = 123; public static final Integer shortServerIdBs0 = 0; public static final int serverId = 1; @@ -154,10 +170,10 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte public static final String COAP = "coap://"; public static final String COAPS = "coaps://"; - public static final String URI = COAP + host + ":" + port; - public static final String SECURE_URI = COAPS + host + ":" + securityPort; - public static final String URI_BS = COAP + hostBs + ":" + portBs; - public static final String SECURE_URI_BS = COAPS + hostBs + ":" + securityPortBs; + public static final String URI = COAP + LWM2M_HOST + ":" + LWM2M_PORT; + public static final String SECURE_URI = COAPS + LWM2M_HOST + ":" + LWM2MS_PORT; + public static final String URI_BS = COAP + LWM2M_BOOTSTRAP_HOST + ":" + LWM2M_BOOTSTRAP_PORT; + public static final String SECURE_URI_BS = COAPS + LWM2M_BOOTSTRAP_HOST + ":" + LWM2MS_BOOTSTRAP_PORT; public static final Security SECURITY_NO_SEC = noSec(URI, shortServerId); protected final String OBSERVE_ATTRIBUTES_WITHOUT_PARAMS = @@ -572,12 +588,11 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte this.clientDestroy(false); lwM2MTestClient = new LwM2MTestClient(this.executor, endpoint, resources); - try (ServerSocket socket = new ServerSocket(0)) { - int clientPort = socket.getLocalPort(); - lwM2MTestClient.init(security, securityBs, clientPort, isRpc, - this.defaultLwM2mUplinkMsgHandlerTest, this.clientContextTest, - clientDtlsCidLength, queueMode, supportFormatOnly_SenMLJSON_SenMLCBOR, value3_0_9); - } + int clientPort = PortFinder.findAvailableUdpPort(); + //automatic client port assignment + lwM2MTestClient.init(security, securityBs, 0 /* clientPort */, isRpc, + this.defaultLwM2mUplinkMsgHandlerTest, this.clientContextTest, + clientDtlsCidLength, queueMode, supportFormatOnly_SenMLJSON_SenMLCBOR, value3_0_9); lwM2MTestClient.setDeviceIdStr(deviceIdStr); } @@ -715,8 +730,8 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte bootstrapServerCredential.setServerPublicKey(""); bootstrapServerCredential.setShortServerId(isBootstrap ? shortServerIdBs0 : shortServerId); bootstrapServerCredential.setBootstrapServerIs(isBootstrap); - bootstrapServerCredential.setHost(isBootstrap ? hostBs : host); - bootstrapServerCredential.setPort(isBootstrap ? portBs : port); + bootstrapServerCredential.setHost(isBootstrap ? LWM2M_BOOTSTRAP_HOST : LWM2M_HOST); + bootstrapServerCredential.setPort(isBootstrap ? LWM2M_BOOTSTRAP_PORT : LWM2M_PORT); return bootstrapServerCredential; } @@ -731,11 +746,15 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte return credentials; } - protected void awaitObserveReadAll(int cntObserve, String deviceIdStr) throws Exception { + awaitObserveReadAll(cntObserve, deviceIdStr, ""); + } + + protected void awaitObserveReadAll(int cntObserve, String deviceIdStr, String assertionAlias) throws Exception { try { await("ObserveReadAll: countObserve " + cntObserve) - .atMost(40, TimeUnit.SECONDS) + .alias(assertionAlias) + .atMost(TIMEOUT, TimeUnit.SECONDS) .until(() -> cntObserve == getCntObserveAll(deviceIdStr)); } catch (ConditionTimeoutException e) { int current = getCntObserveAll(deviceIdStr); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/FwLwM2MDevice.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/FwLwM2MDevice.java index e2d57077a3..979a2b8c96 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/FwLwM2MDevice.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/FwLwM2MDevice.java @@ -33,7 +33,6 @@ import java.util.List; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicInteger; import static org.thingsboard.server.dao.service.OtaPackageServiceTest.TARGET_FW_VERSION; import static org.thingsboard.server.dao.service.OtaPackageServiceTest.TITLE; @@ -137,6 +136,7 @@ public class FwLwM2MDevice extends BaseInstanceEnabler implements Destroyable { @Override public void destroy() { scheduler.shutdownNow(); + this.leshanClient = null; } private void startDownloading() { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java index 37b30dca97..908c2d52d3 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java @@ -78,6 +78,7 @@ import java.util.Set; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import static org.awaitility.Awaitility.await; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_LENGTH; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY; import static org.eclipse.leshan.core.LwM2mId.ACCESS_CONTROL; @@ -88,6 +89,7 @@ import static org.eclipse.leshan.core.LwM2mId.SECURITY; import static org.eclipse.leshan.core.LwM2mId.SERVER; import static org.eclipse.leshan.core.LwM2mId.SOFTWARE_MANAGEMENT; import static org.eclipse.leshan.core.node.codec.DefaultLwM2mEncoder.getDefaultPathEncoder; +import static org.thingsboard.server.transport.AbstractTransportIntegrationTest.DEFAULT_WAIT_TIMEOUT_SECONDS; import static org.thingsboard.server.transport.lwm2m.AbstractLwM2MIntegrationTest.serverId; import static org.thingsboard.server.transport.lwm2m.AbstractLwM2MIntegrationTest.serverIdBs; import static org.thingsboard.server.transport.lwm2m.AbstractLwM2MIntegrationTest.shortServerId; @@ -118,6 +120,7 @@ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INST import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.TEMPERATURE_SENSOR; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.lwm2mClientResources; import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.setDtlsConnectorConfigCidLength; +import static org.thingsboard.server.utils.PortFinder.isUDPPortAvailable; @Slf4j @@ -140,12 +143,14 @@ public class LwM2MTestClient { private LwM2mClientContext clientContext; private LwM2mTemperatureSensor lwM2mTemperatureSensor12; private String deviceIdStr; + private int clientPort; - public void init(Security security, Security securityBs, int port, boolean isRpc, + public void init(Security security, Security securityBs, int clientPort, boolean isRpc, LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandler, LwM2mClientContext clientContext, Integer cIdLength, boolean queueMode, boolean supportFormatOnly_SenMLJSON_SenMLCBOR, Integer value3_0_9) throws InvalidDDFFileException, IOException { Assert.assertNull("client already initialized", leshanClient); + this.clientPort = clientPort; this.defaultLwM2mUplinkMsgHandlerTest = defaultLwM2mUplinkMsgHandler; this.clientContext = clientContext; @@ -266,7 +271,7 @@ public class LwM2MTestClient { // Set Californium Configuration endpointsBuilder.setConfiguration(clientCoapConfig); - endpointsBuilder.setClientAddress(new InetSocketAddress(port).getAddress()); + endpointsBuilder.setClientAddress(new InetSocketAddress(clientPort).getAddress()); // creates EndpointsProvider @@ -461,10 +466,19 @@ public class LwM2MTestClient { if (lwM2MTemperatureSensor != null) { lwM2MTemperatureSensor.destroy(); } + if (lwM2mTemperatureSensor12 != null) { + lwM2mTemperatureSensor12.destroy(); + } } public void start(boolean isStartLw) { if (leshanClient != null) { + if (clientPort > 0) { + log.error("Await UDP clientPort {} to be available before leshanClient.start()", clientPort); + await("Await UDP clientPort " + clientPort + " to be available before leshanClient.start()") + .atMost(DEFAULT_WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS) + .until(() -> isUDPPortAvailable(clientPort)); + } leshanClient.start(); if (isStartLw) { this.awaitClientAfterStartConnectLw(); @@ -477,6 +491,12 @@ public class LwM2MTestClient { public void stop(boolean deregister) { if (leshanClient != null) { leshanClient.stop(deregister); + if (clientPort > 0) { + log.error("Await UDP clientPort {} to disconnect after leshanClient.stop(deregister)", clientPort); + await("Await client UDP port " + clientPort + " to disconnect after leshanClient.stop(deregister)") + .atMost(DEFAULT_WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS) + .until(() -> isUDPPortAvailable(clientPort)); + } } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mTemperatureSensor.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mTemperatureSensor.java index 64978af44d..bca551e989 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mTemperatureSensor.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mTemperatureSensor.java @@ -169,6 +169,7 @@ public class LwM2mTemperatureSensor extends BaseInstanceEnabler implements Destr @Override public void destroy() { + this.leshanClient = null; } private void sendCollected() { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index d6e9e2d9b0..4adc398fa8 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -359,8 +359,8 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M } bootstrapServerCredential.setShortServerId(isBootstrap ? shortServerIdBs0 : shortServerId); bootstrapServerCredential.setBootstrapServerIs(isBootstrap); - bootstrapServerCredential.setHost(isBootstrap ? hostBs : host); - bootstrapServerCredential.setPort(isBootstrap ? securityPortBs : securityPort); + bootstrapServerCredential.setHost(isBootstrap ? LWM2M_BOOTSTRAP_HOST : LWM2M_HOST); + bootstrapServerCredential.setPort(isBootstrap ? LWM2MS_BOOTSTRAP_PORT : LWM2MS_PORT); return bootstrapServerCredential; } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java index 420ebd16b2..29beace952 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java @@ -136,7 +136,7 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes ON_REGISTRATION_SUCCESS, true); - awaitObserveReadAll(1, lwm2mDevice.getId().getId().toString()); + awaitObserveReadAll(1, lwm2mDevice.getId().getId().toString(), "before client stops for the first time"); lwM2MTestClient.stop(true); DeviceProfile foundDeviceProfile = doGet("/api/deviceProfile/" + lwm2mDevice.getDeviceProfileId().getId().toString(), DeviceProfile.class); @@ -146,7 +146,7 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes Assert.assertNotNull(lwm2mDeviceProfileManyParams); lwM2MTestClient.start(true); - awaitObserveReadAll(1, lwm2mDevice.getId().getId().toString()); + awaitObserveReadAll(1, lwm2mDevice.getId().getId().toString(), "second after client restart"); awaitUpdateReg(3); } diff --git a/pom.xml b/pom.xml index 58e0c32e43..8f5708bcec 100755 --- a/pom.xml +++ b/pom.xml @@ -172,6 +172,16 @@ true + + default-surefire-java-opts + + + !env.SUREFIRE_JAVA_OPTS + + + + + @@ -664,8 +674,9 @@ -XX:+UseStringDeduplication -XX:MaxGCPauseMillis=200 --add-opens=java.base/java.lang.reflect=ALL-UNNAMED - -Dqueue.edqs.local.rocksdb_path="target/rocks/fork_${surefire.forkNumber}/edqs" - -Dqueue.calculated_fields.rocks_db_path="target/rocks/fork_${surefire.forkNumber}/cf" + -Dqueue.edqs.local.rocksdb_path="target/rocksdb/fork_${surefire.forkNumber}/edqs" + -Dqueue.calculated_fields.rocks_db_path="target/rocksdb/fork_${surefire.forkNumber}/cf" + ${env.SUREFIRE_JAVA_OPTS} From 342060c54a75a49b2d4e5609ba373db9079d4dc3 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 22 Jan 2026 23:36:58 +0100 Subject: [PATCH 058/742] tests: fixed EdgeImitator usage in controller test by providing Modifiable Deque getDownlinkMsgsDeque --- .../server/controller/EdgeControllerTest.java | 87 ++++++++++--------- .../server/edge/imitator/EdgeImitator.java | 5 ++ 2 files changed, 49 insertions(+), 43 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java index 0d0de0a66c..fc65d67949 100644 --- a/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java @@ -102,6 +102,7 @@ import org.thingsboard.server.service.edge.instructions.EdgeUpgradeInstructionsS import java.util.ArrayList; import java.util.Collections; +import java.util.Deque; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -924,11 +925,11 @@ public class EdgeControllerTest extends AbstractControllerTest { verifyFetchersMsgs(edgeImitator, savedDevice); // verify queue msgs - Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); - Assert.assertTrue(popDeviceMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Device 1")); - Assert.assertTrue(popDeviceCredentialsMsg(edgeImitator.getDownlinkMsgs(), savedDevice.getId())); - Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); - Assert.assertTrue(popAssetMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Asset 1")); + Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); + Assert.assertTrue(popDeviceMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Device 1")); + Assert.assertTrue(popDeviceCredentialsMsg(edgeImitator.getDownlinkMsgsDeque(), savedDevice.getId())); + Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); + Assert.assertTrue(popAssetMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Asset 1")); printQueueMsgsIfNotEmpty(edgeImitator); // 17 connect messages @@ -1008,32 +1009,32 @@ public class EdgeControllerTest extends AbstractControllerTest { } private void verifyFetchersMsgs(EdgeImitator edgeImitator, Device savedDevice) { - Assert.assertTrue(popQueueMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Main")); - Assert.assertTrue(popRuleChainMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Edge Root Rule Chain")); - Assert.assertTrue(popRuleChainMetadataMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, getEdgeRootRuleChainId(edgeImitator))); - Assert.assertTrue(popAdminSettingsMsg(edgeImitator.getDownlinkMsgs(), "general")); - Assert.assertTrue(popAdminSettingsMsg(edgeImitator.getDownlinkMsgs(), "mail")); - Assert.assertTrue(popAdminSettingsMsg(edgeImitator.getDownlinkMsgs(), "connectivity")); - Assert.assertTrue(popAdminSettingsMsg(edgeImitator.getDownlinkMsgs(), "jwt")); - Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); - Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); - Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); - Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); - Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); - Assert.assertTrue(popUserCredentialsMsg(edgeImitator.getDownlinkMsgs(), currentUserId)); - Assert.assertTrue(popUserMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, TENANT_ADMIN_EMAIL, Authority.TENANT_ADMIN)); - Assert.assertTrue(popCustomerMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Public")); - Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); - Assert.assertTrue(popDeviceMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Device 1")); - Assert.assertTrue(popDeviceCredentialsMsg(edgeImitator.getDownlinkMsgs(), savedDevice.getId())); - Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); - Assert.assertTrue(popAssetMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Asset 1")); - Assert.assertTrue(popTenantMsg(edgeImitator.getDownlinkMsgs(), tenantId)); - Assert.assertTrue(popTenantProfileMsg(edgeImitator.getDownlinkMsgs(), tenantProfileId)); - Assert.assertTrue(popSyncCompletedMsg(edgeImitator.getDownlinkMsgs())); + Assert.assertTrue(popQueueMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Main")); + Assert.assertTrue(popRuleChainMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Edge Root Rule Chain")); + Assert.assertTrue(popRuleChainMetadataMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, getEdgeRootRuleChainId(edgeImitator))); + Assert.assertTrue(popAdminSettingsMsg(edgeImitator.getDownlinkMsgsDeque(), "general")); + Assert.assertTrue(popAdminSettingsMsg(edgeImitator.getDownlinkMsgsDeque(), "mail")); + Assert.assertTrue(popAdminSettingsMsg(edgeImitator.getDownlinkMsgsDeque(), "connectivity")); + Assert.assertTrue(popAdminSettingsMsg(edgeImitator.getDownlinkMsgsDeque(), "jwt")); + Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); + Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); + Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); + Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); + Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); + Assert.assertTrue(popUserCredentialsMsg(edgeImitator.getDownlinkMsgsDeque(), currentUserId)); + Assert.assertTrue(popUserMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, TENANT_ADMIN_EMAIL, Authority.TENANT_ADMIN)); + Assert.assertTrue(popCustomerMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Public")); + Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); + Assert.assertTrue(popDeviceMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Device 1")); + Assert.assertTrue(popDeviceCredentialsMsg(edgeImitator.getDownlinkMsgsDeque(), savedDevice.getId())); + Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); + Assert.assertTrue(popAssetMsg(edgeImitator.getDownlinkMsgsDeque(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Asset 1")); + Assert.assertTrue(popTenantMsg(edgeImitator.getDownlinkMsgsDeque(), tenantId)); + Assert.assertTrue(popTenantProfileMsg(edgeImitator.getDownlinkMsgsDeque(), tenantProfileId)); + Assert.assertTrue(popSyncCompletedMsg(edgeImitator.getDownlinkMsgsDeque())); } - private boolean popQueueMsg(List messages, UpdateMsgType msgType, String name) { + private boolean popQueueMsg(Deque messages, UpdateMsgType msgType, String name) { for (AbstractMessage message : messages) { if (message instanceof QueueUpdateMsg queueUpdateMsg) { Queue queue = JacksonUtil.fromString(queueUpdateMsg.getEntity(), Queue.class, true); @@ -1047,7 +1048,7 @@ public class EdgeControllerTest extends AbstractControllerTest { return false; } - private boolean popRuleChainMsg(List messages, UpdateMsgType msgType, String name) { + private boolean popRuleChainMsg(Deque messages, UpdateMsgType msgType, String name) { for (AbstractMessage message : messages) { if (message instanceof RuleChainUpdateMsg ruleChainUpdateMsg) { RuleChain ruleChain = JacksonUtil.fromString(ruleChainUpdateMsg.getEntity(), RuleChain.class, true); @@ -1063,7 +1064,7 @@ public class EdgeControllerTest extends AbstractControllerTest { return false; } - private boolean popRuleChainMetadataMsg(List messages, UpdateMsgType msgType, RuleChainId ruleChainId) { + private boolean popRuleChainMetadataMsg(Deque messages, UpdateMsgType msgType, RuleChainId ruleChainId) { for (AbstractMessage message : messages) { if (message instanceof RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg) { RuleChainMetaData ruleChainMetaData = JacksonUtil.fromString(ruleChainMetadataUpdateMsg.getEntity(), RuleChainMetaData.class, true); @@ -1078,7 +1079,7 @@ public class EdgeControllerTest extends AbstractControllerTest { return false; } - private boolean popAdminSettingsMsg(List messages, String key) { + private boolean popAdminSettingsMsg(Deque messages, String key) { for (AbstractMessage message : messages) { if (message instanceof AdminSettingsUpdateMsg adminSettingsUpdateMsg) { AdminSettings adminSettings = JacksonUtil.fromString(adminSettingsUpdateMsg.getEntity(), AdminSettings.class, true); @@ -1092,7 +1093,7 @@ public class EdgeControllerTest extends AbstractControllerTest { return false; } - private boolean popDeviceProfileMsg(List messages, UpdateMsgType msgType, String name) { + private boolean popDeviceProfileMsg(Deque messages, UpdateMsgType msgType, String name) { for (AbstractMessage message : messages) { if (message instanceof DeviceProfileUpdateMsg deviceProfileUpdateMsg) { DeviceProfile deviceProfile = JacksonUtil.fromString(deviceProfileUpdateMsg.getEntity(), DeviceProfile.class, true); @@ -1107,7 +1108,7 @@ public class EdgeControllerTest extends AbstractControllerTest { return false; } - private boolean popDeviceMsg(List messages, UpdateMsgType msgType, String name) { + private boolean popDeviceMsg(Deque messages, UpdateMsgType msgType, String name) { for (AbstractMessage message : messages) { if (message instanceof DeviceUpdateMsg deviceUpdateMsg) { Device device = JacksonUtil.fromString(deviceUpdateMsg.getEntity(), Device.class, true); @@ -1122,7 +1123,7 @@ public class EdgeControllerTest extends AbstractControllerTest { return false; } - private boolean popDeviceCredentialsMsg(List messages, DeviceId deviceId) { + private boolean popDeviceCredentialsMsg(Deque messages, DeviceId deviceId) { for (AbstractMessage message : messages) { if (message instanceof DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg) { DeviceCredentials deviceCredentials = JacksonUtil.fromString(deviceCredentialsUpdateMsg.getEntity(), DeviceCredentials.class, true); @@ -1136,7 +1137,7 @@ public class EdgeControllerTest extends AbstractControllerTest { return false; } - private boolean popAssetProfileMsg(List messages, UpdateMsgType msgType, String name) { + private boolean popAssetProfileMsg(Deque messages, UpdateMsgType msgType, String name) { for (AbstractMessage message : messages) { if (message instanceof AssetProfileUpdateMsg assetProfileUpdateMsg) { AssetProfile assetProfile = JacksonUtil.fromString(assetProfileUpdateMsg.getEntity(), AssetProfile.class, true); @@ -1151,7 +1152,7 @@ public class EdgeControllerTest extends AbstractControllerTest { return false; } - private boolean popAssetMsg(List messages, UpdateMsgType msgType, String name) { + private boolean popAssetMsg(Deque messages, UpdateMsgType msgType, String name) { for (AbstractMessage message : messages) { if (message instanceof AssetUpdateMsg assetUpdateMsg) { Asset asset = JacksonUtil.fromString(assetUpdateMsg.getEntity(), Asset.class, true); @@ -1166,7 +1167,7 @@ public class EdgeControllerTest extends AbstractControllerTest { return false; } - private boolean popUserCredentialsMsg(List messages, UserId userId) { + private boolean popUserCredentialsMsg(Deque messages, UserId userId) { for (AbstractMessage message : messages) { if (message instanceof UserCredentialsUpdateMsg userCredentialsUpdateMsg) { UserCredentials userCredentials = JacksonUtil.fromString(userCredentialsUpdateMsg.getEntity(), UserCredentials.class, true); @@ -1180,7 +1181,7 @@ public class EdgeControllerTest extends AbstractControllerTest { return false; } - private boolean popUserMsg(List messages, UpdateMsgType msgType, String email, Authority authority) { + private boolean popUserMsg(Deque messages, UpdateMsgType msgType, String email, Authority authority) { for (AbstractMessage message : messages) { if (message instanceof UserUpdateMsg userUpdateMsg) { User user = JacksonUtil.fromString(userUpdateMsg.getEntity(), User.class, true); @@ -1196,7 +1197,7 @@ public class EdgeControllerTest extends AbstractControllerTest { return false; } - private boolean popCustomerMsg(List messages, UpdateMsgType msgType, String title) { + private boolean popCustomerMsg(Deque messages, UpdateMsgType msgType, String title) { for (AbstractMessage message : messages) { if (message instanceof CustomerUpdateMsg customerUpdateMsg) { Customer customer = JacksonUtil.fromString(customerUpdateMsg.getEntity(), Customer.class, true); @@ -1211,7 +1212,7 @@ public class EdgeControllerTest extends AbstractControllerTest { return false; } - private boolean popTenantMsg(List messages, TenantId tenantId1) { + private boolean popTenantMsg(Deque messages, TenantId tenantId1) { for (AbstractMessage message : messages) { if (message instanceof TenantUpdateMsg tenantUpdateMsg) { Tenant tenant = JacksonUtil.fromString(tenantUpdateMsg.getEntity(), Tenant.class, true); @@ -1226,7 +1227,7 @@ public class EdgeControllerTest extends AbstractControllerTest { return false; } - private boolean popTenantProfileMsg(List messages, TenantProfileId tenantProfileId) { + private boolean popTenantProfileMsg(Deque messages, TenantProfileId tenantProfileId) { for (AbstractMessage message : messages) { if (message instanceof TenantProfileUpdateMsg tenantProfileUpdateMsg) { TenantProfile tenantProfile = JacksonUtil.fromString(tenantProfileUpdateMsg.getEntity(), TenantProfile.class, true); @@ -1241,7 +1242,7 @@ public class EdgeControllerTest extends AbstractControllerTest { return false; } - private boolean popSyncCompletedMsg(List messages) { + private boolean popSyncCompletedMsg(Deque messages) { for (AbstractMessage message : messages) { if (message instanceof SyncCompletedMsg) { messages.remove(message); diff --git a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java index d1596b1c59..266a4dbb62 100644 --- a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java @@ -68,6 +68,7 @@ import org.thingsboard.server.gen.edge.v1.WidgetsBundleUpdateMsg; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Deque; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -111,6 +112,10 @@ public class EdgeImitator { return downlinkMsgs.stream().toList(); } + public Deque getDownlinkMsgsDeque() { + return downlinkMsgs; + } + @Getter private UplinkResponseMsg latestResponseMsg; From 29812b0c8dae1e5d533d387aa5a861174f17aa08 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Fri, 23 Jan 2026 00:16:33 +0100 Subject: [PATCH 059/742] tests: noted how to run tests in parallel fast --- TEST_FAST.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 TEST_FAST.md diff --git a/TEST_FAST.md b/TEST_FAST.md new file mode 100644 index 0000000000..4219d7470b --- /dev/null +++ b/TEST_FAST.md @@ -0,0 +1,27 @@ + +## Running tests in parallel with a reasonable memory usage + +```bash +mvn clean install -T6 -DskipTests +mvn test -pl='!application,!dao,!ui-ngx,!msa/js-executor,!msa/web-ui' -T4 +mvn test -pl dao -Dparallel=packages -DforkCount=4 + +mvn test -pl application -Dsurefire.excludes='**/nosql/*Test.java' -Dtest='org.thingsboard.server.controller.**' -DforkCount=6 -Dparallel=classes -Dsurefire.rerunFailingTestsCount=2 -Dsurefire.failOnFlakeCount=5 +mvn test -pl application -Dsurefire.excludes='**/nosql/*Test.java' -Dtest='org.thingsboard.server.edge.**' -DforkCount=4 -Dparallel=packages -Dsurefire.rerunFailingTestsCount=2 -Dsurefire.failOnFlakeCount=5 +mvn test -pl application -Dsurefire.excludes='**/nosql/*Test.java' -Dtest='org.thingsboard.server.service.**' -DforkCount=6 -Dparallel=packages -Dsurefire.rerunFailingTestsCount=2 -Dsurefire.failOnFlakeCount=5 +mvn test -pl application -Dsurefire.excludes='**/nosql/*Test.java' -Dtest='org.thingsboard.server.transport.mqtt.**' -DforkCount=6 -Dparallel=classes -Dsurefire.rerunFailingTestsCount=2 -Dsurefire.failOnFlakeCount=5 +mvn test -pl application -Dsurefire.excludes='**/nosql/*Test.java' -Dtest='org.thingsboard.server.transport.coap.**' -DforkCount=6 -Dparallel=classes -Dsurefire.rerunFailingTestsCount=2 -Dsurefire.failOnFlakeCount=5 +mvn test -pl application -Dsurefire.excludes='**/nosql/*Test.java' -Dtest='org.thingsboard.server.transport.lwm2m.**' -DforkCount=6 -Dparallel=packages -Dsurefire.rerunFailingTestsCount=2 -Dsurefire.failOnFlakeCount=5 +mvn test -pl application -Dsurefire.excludes='**/nosql/*Test.java' -Dtest='**/*TestSuite.java' -DforkCount=4 -Dparallel=classes -Dsurefire.rerunFailingTestsCount=2 -Dsurefire.failOnFlakeCount=5 + +#the rest of application tests +mvn test -pl application -Dtest=' +!**/nosql/*Test.java, +!org.thingsboard.server.controller.**, +!org.thingsboard.server.edge.**, +!org.thingsboard.server.service.**, +!org.thingsboard.server.transport.mqtt.**, +!org.thingsboard.server.transport.coap.**, +!org.thingsboard.server.transport.lwm2m.** +' -DforkCount=6 -Dparallel=packages -Dsurefire.rerunFailingTestsCount=2 -Dsurefire.failOnFlakeCount=5 +``` From da608805af3f946e233716ee0e9c4a23c0bcea28 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Fri, 23 Jan 2026 07:59:17 +0100 Subject: [PATCH 060/742] test example for memory management --- TEST_FAST.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/TEST_FAST.md b/TEST_FAST.md index 4219d7470b..c0f1174584 100644 --- a/TEST_FAST.md +++ b/TEST_FAST.md @@ -2,6 +2,10 @@ ## Running tests in parallel with a reasonable memory usage ```bash +export MAVEN_OPTS="-Xmx1024m" +export NODE_OPTIONS="--max_old_space_size=4096" +export SUREFIRE_JAVA_OPTS="-Xmx1200m -Xss256k -XX:+ExitOnOutOfMemoryError" + mvn clean install -T6 -DskipTests mvn test -pl='!application,!dao,!ui-ngx,!msa/js-executor,!msa/web-ui' -T4 mvn test -pl dao -Dparallel=packages -DforkCount=4 From 63301c91ba407eeab1993db867c2431039bbacc8 Mon Sep 17 00:00:00 2001 From: Maksym Tsymbarov Date: Fri, 23 Jan 2026 13:03:34 +0200 Subject: [PATCH 061/742] Fixed image upload component to allow refetch on error --- ui-ngx/src/app/core/http/image.service.ts | 9 ++++----- .../components/image/gallery-image-input.component.ts | 7 ++++--- ui-ngx/src/app/shared/pipe/image.pipe.ts | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ui-ngx/src/app/core/http/image.service.ts b/ui-ngx/src/app/core/http/image.service.ts index c714f728c0..896145b351 100644 --- a/ui-ngx/src/app/core/http/image.service.ts +++ b/ui-ngx/src/app/core/http/image.service.ts @@ -31,7 +31,7 @@ import { removeTbImagePrefix, ResourceSubType } from '@shared/models/resource.models'; -import { catchError, map, switchMap } from 'rxjs/operators'; +import { catchError, finalize, map, switchMap } from 'rxjs/operators'; import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; import { blobToBase64, blobToText } from '@core/utils'; import { ResourcesService } from '@core/services/resources.service'; @@ -116,16 +116,15 @@ export class ImageService { request = new ReplaySubject(1); this.imagesLoading[imageLink] = request; const options = defaultHttpOptionsFromConfig({ignoreLoading: true, ignoreErrors: true}); - this.http.get(imageLink, {...options, ...{ responseType: 'blob' } }).subscribe({ + this.http.get(imageLink, {...options, ...{ responseType: 'blob' } }).pipe( + finalize(()=> delete this.imagesLoading[imageLink]) + ).subscribe({ next: (value) => { request.next(value); request.complete(); }, error: err => { request.error(err); - }, - complete: () => { - delete this.imagesLoading[imageLink]; } }); } diff --git a/ui-ngx/src/app/shared/components/image/gallery-image-input.component.ts b/ui-ngx/src/app/shared/components/image/gallery-image-input.component.ts index 421d0ec559..9c5df854a5 100644 --- a/ui-ngx/src/app/shared/components/image/gallery-image-input.component.ts +++ b/ui-ngx/src/app/shared/components/image/gallery-image-input.component.ts @@ -171,9 +171,9 @@ export class GalleryImageInputComponent extends PageComponent implements OnInit, } } - private updateModel(value: string) { + private updateModel(value: string, forcedToUpdate = false): void { this.cd.markForCheck(); - if (this.imageUrl !== value) { + if (this.imageUrl !== value || forcedToUpdate) { this.imageUrl = value; this.propagateChange(prependTbImagePrefix(this.imageUrl)); } @@ -211,9 +211,10 @@ export class GalleryImageInputComponent extends PageComponent implements OnInit, } }).afterClosed().subscribe((image) => { if (image) { + const forcedToUpdate = this.imageUrl === image.link && this.imageResource?.descriptor?.etag !== image.descriptor.etag; this.linkType = ImageLinkType.resource; this.imageResource = image; - this.updateModel(image.link); + this.updateModel(image.link, forcedToUpdate); } }); } diff --git a/ui-ngx/src/app/shared/pipe/image.pipe.ts b/ui-ngx/src/app/shared/pipe/image.pipe.ts index d17ed0ab76..b570da5f24 100644 --- a/ui-ngx/src/app/shared/pipe/image.pipe.ts +++ b/ui-ngx/src/app/shared/pipe/image.pipe.ts @@ -38,7 +38,7 @@ export class ImagePipe implements PipeTransform { private sanitizer: DomSanitizer, private zone: NgZone) { } - transform(urlData: string | UrlHolder, args?: any): Observable { + transform(urlData: string | UrlHolder, args?: any, triggerUpdate?: number): Observable { const ignoreLoadingImage = !!args?.ignoreLoadingImage; const asString = !!args?.asString; const emptyUrl = args?.emptyUrl || NO_IMAGE_DATA_URI; From efead4abd387fcfdccfc163ebe18d5a45bf0712e Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Fri, 23 Jan 2026 13:24:49 +0100 Subject: [PATCH 062/742] tests: fixed LWM2M clientDestroy with PortFinder.isUDPPortAvailable --- .../transport/lwm2m/AbstractLwM2MIntegrationTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java index a0f3f07883..f3a3212e67 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.gson.JsonArray; import com.google.gson.JsonElement; +import jnr.ffi.annotations.In; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.awaitility.core.ConditionTimeoutException; @@ -672,10 +673,9 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte try { if (lwM2MTestClient != null && lwM2MTestClient.getLeshanClient() != null) { boolean serverAlive = false; - for (int port = AbstractLwM2MIntegrationTest.port; port <= securityPortBs; port++) { - try (ServerSocket socket = new ServerSocket(port)) { - log.info("Port {} is free.", port); - } catch (IOException e) { + List ports = List.of(LWM2M_PORT, LWM2MS_PORT, LWM2MS_BOOTSTRAP_PORT, LWM2MS_BOOTSTRAP_PORT); + for (Integer port : ports) { + if (!PortFinder.isUDPPortAvailable(port)) { log.debug("Port {} is busy — CoAP server still active.", port); serverAlive = true; break; From 4b0f776c139708193d3b72db3ad20299462dce2f Mon Sep 17 00:00:00 2001 From: Dmytro Zolotarenko Date: Fri, 23 Jan 2026 15:19:19 +0200 Subject: [PATCH 063/742] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6267cc3a7a..77a758ab73 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ ThingsBoard is a scalable, user-friendly, and device-agnostic IoT platform that [**Fleet tracking**](https://thingsboard.io/use-cases/fleet-tracking/) -[![Fleet tracking](https://github.com/user-attachments/assets/9e8938ba-ee0c-4599-9494-d74b7de8a63d "Fleet tracking")](https://thingsboard.io/use-cases/fleet-tracking/) +[![Fleet tracking](https://github.com/user-attachments/assets/d6ce0766-b138-4a42-86aa-7112a543026c "Fleet tracking")](https://thingsboard.io/use-cases/fleet-tracking/) [**Smart farming**](https://thingsboard.io/use-cases/smart-farming/) From 59056658498f8dfa5f50ae831a3994daa5df6af1 Mon Sep 17 00:00:00 2001 From: Dmytro Zolotarenko Date: Fri, 23 Jan 2026 15:24:44 +0200 Subject: [PATCH 064/742] Update README.md, updated use case name --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 77a758ab73..7776b1a964 100644 --- a/README.md +++ b/README.md @@ -123,9 +123,9 @@ ThingsBoard is a scalable, user-friendly, and device-agnostic IoT platform that [![SCADA Swimming pool](https://github.com/user-attachments/assets/68fd9e29-99f1-4c16-8c4c-476f4ccb20c0 "SCADA Swimming pool")](https://thingsboard.io/use-cases/scada/) -[**Fleet tracking**](https://thingsboard.io/use-cases/fleet-tracking/) +[**Site fleet tracking**](https://thingsboard.io/use-cases/site-fleet-tracking/) -[![Fleet tracking](https://github.com/user-attachments/assets/d6ce0766-b138-4a42-86aa-7112a543026c "Fleet tracking")](https://thingsboard.io/use-cases/fleet-tracking/) +[![Site fleet tracking](https://github.com/user-attachments/assets/d6ce0766-b138-4a42-86aa-7112a543026c "Site fleet tracking")](https://thingsboard.io/use-cases/site-fleet-tracking/) [**Smart farming**](https://thingsboard.io/use-cases/smart-farming/) From 7f427b27fb2f9854cc48d1f14dca3f516295ade0 Mon Sep 17 00:00:00 2001 From: Viacheslav Klimov Date: Fri, 23 Jan 2026 15:37:23 +0200 Subject: [PATCH 065/742] Version set to 4.3.0.1-SNAPSHOT --- application/pom.xml | 2 +- .../main/data/upgrade/basic/schema_update.sql | 66 ------------------- .../install/ThingsboardInstallService.java | 1 - .../DefaultDatabaseSchemaSettingsService.java | 2 +- common/actor/pom.xml | 2 +- common/cache/pom.xml | 2 +- common/cluster-api/pom.xml | 2 +- common/coap-server/pom.xml | 2 +- common/dao-api/pom.xml | 2 +- common/data/pom.xml | 2 +- common/discovery-api/pom.xml | 2 +- common/edge-api/pom.xml | 2 +- common/edqs/pom.xml | 2 +- common/message/pom.xml | 2 +- common/pom.xml | 2 +- common/proto/pom.xml | 2 +- common/queue/pom.xml | 2 +- common/script/pom.xml | 2 +- common/script/remote-js-client/pom.xml | 2 +- common/script/script-api/pom.xml | 2 +- common/stats/pom.xml | 2 +- common/transport/coap/pom.xml | 2 +- common/transport/http/pom.xml | 2 +- common/transport/lwm2m/pom.xml | 2 +- common/transport/mqtt/pom.xml | 2 +- common/transport/pom.xml | 2 +- common/transport/snmp/pom.xml | 2 +- common/transport/transport-api/pom.xml | 2 +- common/util/pom.xml | 2 +- common/version-control/pom.xml | 2 +- dao/pom.xml | 2 +- edqs/pom.xml | 2 +- monitoring/pom.xml | 2 +- msa/black-box-tests/pom.xml | 2 +- msa/edqs/pom.xml | 2 +- msa/js-executor/package.json | 2 +- msa/js-executor/pom.xml | 2 +- msa/monitoring/pom.xml | 2 +- msa/pom.xml | 2 +- msa/tb-node/pom.xml | 2 +- msa/tb/pom.xml | 2 +- msa/transport/coap/pom.xml | 2 +- msa/transport/http/pom.xml | 2 +- msa/transport/lwm2m/pom.xml | 2 +- msa/transport/mqtt/pom.xml | 2 +- msa/transport/pom.xml | 2 +- msa/transport/snmp/pom.xml | 2 +- msa/vc-executor-docker/pom.xml | 2 +- msa/vc-executor/pom.xml | 2 +- msa/web-ui/package.json | 2 +- msa/web-ui/pom.xml | 2 +- netty-mqtt/pom.xml | 4 +- pom.xml | 2 +- rest-client/pom.xml | 2 +- rule-engine/pom.xml | 2 +- rule-engine/rule-engine-api/pom.xml | 2 +- rule-engine/rule-engine-components/pom.xml | 2 +- tools/pom.xml | 2 +- transport/coap/pom.xml | 2 +- transport/http/pom.xml | 2 +- transport/lwm2m/pom.xml | 2 +- transport/mqtt/pom.xml | 2 +- transport/pom.xml | 2 +- transport/snmp/pom.xml | 2 +- ui-ngx/package.json | 2 +- ui-ngx/pom.xml | 2 +- 66 files changed, 65 insertions(+), 132 deletions(-) diff --git a/application/pom.xml b/application/pom.xml index ab26655052..d2cc11f069 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT thingsboard application diff --git a/application/src/main/data/upgrade/basic/schema_update.sql b/application/src/main/data/upgrade/basic/schema_update.sql index 66243461e2..a2dfeac358 100644 --- a/application/src/main/data/upgrade/basic/schema_update.sql +++ b/application/src/main/data/upgrade/basic/schema_update.sql @@ -14,69 +14,3 @@ -- limitations under the License. -- --- UPDATE TENANT PROFILE CONFIGURATION START - -UPDATE tenant_profile -SET profile_data = jsonb_set( - profile_data, - '{configuration}', - jsonb_build_object( - 'minAllowedScheduledUpdateIntervalInSecForCF', 10, - 'maxRelationLevelPerCfArgument', 2, - 'maxRelatedEntitiesToReturnPerCfArgument', 100, - 'minAllowedDeduplicationIntervalInSecForCF', 10, - 'minAllowedAggregationIntervalInSecForCF', 60, - 'intermediateAggregationIntervalInSecForCF', 300, - 'cfReevaluationCheckInterval', 60, - 'alarmsReevaluationInterval', 60 - ) - || - jsonb_strip_nulls(profile_data -> 'configuration') -) -WHERE NOT ( - jsonb_strip_nulls(profile_data -> 'configuration') ?& ARRAY[ - 'minAllowedScheduledUpdateIntervalInSecForCF', - 'maxRelationLevelPerCfArgument', - 'maxRelatedEntitiesToReturnPerCfArgument', - 'minAllowedDeduplicationIntervalInSecForCF', - 'minAllowedAggregationIntervalInSecForCF', - 'intermediateAggregationIntervalInSecForCF', - 'cfReevaluationCheckInterval', - 'alarmsReevaluationInterval' - ] -); - --- UPDATE TENANT PROFILE CONFIGURATION END - --- CALCULATED FIELD UNIQUE CONSTRAINT UPDATE START - -ALTER TABLE calculated_field DROP CONSTRAINT IF EXISTS calculated_field_unq_key; -ALTER TABLE calculated_field ADD CONSTRAINT calculated_field_unq_key UNIQUE (entity_id, type, name); - --- CALCULATED FIELD UNIQUE CONSTRAINT UPDATE END - --- CALCULATED FIELD OUTPUT STRATEGY UPDATE START - -UPDATE calculated_field -SET configuration = jsonb_set( - configuration::jsonb, - '{output}', - (configuration::jsonb -> 'output') - || jsonb_build_object( - 'strategy', - jsonb_build_object( - 'type', 'RULE_CHAIN' - ) - ), - false - ) -WHERE (configuration::jsonb -> 'output' -> 'strategy') IS NULL; - --- CALCULATED FIELD OUTPUT STRATEGY UPDATE END - --- REMOVAL OF CALCULATED FIELD LINKS PERSISTENCE START - -DROP TABLE IF EXISTS calculated_field_link; -ANALYZE calculated_field; - --- REMOVAL OF CALCULATED FIELD LINKS PERSISTENCE END diff --git a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java index 8ea989fc01..66695c396f 100644 --- a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java +++ b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java @@ -116,7 +116,6 @@ public class ThingsboardInstallService { entityDatabaseSchemaService.createDatabaseIndexes(); // TODO: cleanup update code after each release - systemDataLoaderService.updateDefaultNotificationConfigs(false); // Runs upgrade scripts that are not possible in plain SQL. dataUpdateService.updateData(); diff --git a/application/src/main/java/org/thingsboard/server/service/install/DefaultDatabaseSchemaSettingsService.java b/application/src/main/java/org/thingsboard/server/service/install/DefaultDatabaseSchemaSettingsService.java index d8bcf666f7..468aa80e6c 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/DefaultDatabaseSchemaSettingsService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/DefaultDatabaseSchemaSettingsService.java @@ -31,7 +31,7 @@ public class DefaultDatabaseSchemaSettingsService implements DatabaseSchemaSetti // This list should include all versions that are compatible for the upgrade in 4 digits format (like 4.2.0.0, etc.). // The compatibility cycle usually breaks when we have some scripts written in Java that may not work after a new release. // TODO: don't check the "patch" number, since upgrade is not required for patch releases - private static final List SUPPORTED_VERSIONS_FOR_UPGRADE = List.of("4.2.1.0", "4.2.1.1", "4.2.1.2"); + private static final List SUPPORTED_VERSIONS_FOR_UPGRADE = List.of("4.3.0.0"); private final ProjectInfo projectInfo; private final JdbcTemplate jdbcTemplate; diff --git a/common/actor/pom.xml b/common/actor/pom.xml index bd441e3a58..64727ab3f7 100644 --- a/common/actor/pom.xml +++ b/common/actor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/cache/pom.xml b/common/cache/pom.xml index 7d22f5d3dc..163c47356d 100644 --- a/common/cache/pom.xml +++ b/common/cache/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/cluster-api/pom.xml b/common/cluster-api/pom.xml index a7240c8b42..9be12f3b18 100644 --- a/common/cluster-api/pom.xml +++ b/common/cluster-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/coap-server/pom.xml b/common/coap-server/pom.xml index 3fba2211d5..2e8aca2ba4 100644 --- a/common/coap-server/pom.xml +++ b/common/coap-server/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml index bcab0249ef..3468f51be0 100644 --- a/common/dao-api/pom.xml +++ b/common/dao-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/data/pom.xml b/common/data/pom.xml index 43f3a5a38e..ccb0eda1f3 100644 --- a/common/data/pom.xml +++ b/common/data/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/discovery-api/pom.xml b/common/discovery-api/pom.xml index 5aa66562ed..9bcf02dd94 100644 --- a/common/discovery-api/pom.xml +++ b/common/discovery-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/edge-api/pom.xml b/common/edge-api/pom.xml index 507bfc73f8..d52074ace6 100644 --- a/common/edge-api/pom.xml +++ b/common/edge-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/edqs/pom.xml b/common/edqs/pom.xml index 5512d47b79..b953da6d11 100644 --- a/common/edqs/pom.xml +++ b/common/edqs/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/message/pom.xml b/common/message/pom.xml index 1f6bfb20e1..615989da81 100644 --- a/common/message/pom.xml +++ b/common/message/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/pom.xml b/common/pom.xml index c0140e733d..211578b1d2 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT thingsboard common diff --git a/common/proto/pom.xml b/common/proto/pom.xml index 27ca58ac0e..f024f41992 100644 --- a/common/proto/pom.xml +++ b/common/proto/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/queue/pom.xml b/common/queue/pom.xml index b4fd04ef55..4cb3f449a3 100644 --- a/common/queue/pom.xml +++ b/common/queue/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/script/pom.xml b/common/script/pom.xml index 2a5856782e..5f352fb70b 100644 --- a/common/script/pom.xml +++ b/common/script/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/script/remote-js-client/pom.xml b/common/script/remote-js-client/pom.xml index 6a50189371..d1c71bbd9d 100644 --- a/common/script/remote-js-client/pom.xml +++ b/common/script/remote-js-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.3.0-RC + 4.3.0.1-SNAPSHOT script org.thingsboard.common.script diff --git a/common/script/script-api/pom.xml b/common/script/script-api/pom.xml index 38e32661d1..0ba928ebe1 100644 --- a/common/script/script-api/pom.xml +++ b/common/script/script-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.3.0-RC + 4.3.0.1-SNAPSHOT script org.thingsboard.common.script diff --git a/common/stats/pom.xml b/common/stats/pom.xml index fe35fedaec..d2942cd813 100644 --- a/common/stats/pom.xml +++ b/common/stats/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/coap/pom.xml b/common/transport/coap/pom.xml index bb8213666f..273e7e2a7d 100644 --- a/common/transport/coap/pom.xml +++ b/common/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.3.0-RC + 4.3.0.1-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/http/pom.xml b/common/transport/http/pom.xml index d341540104..cd64cc36d2 100644 --- a/common/transport/http/pom.xml +++ b/common/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.3.0-RC + 4.3.0.1-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/lwm2m/pom.xml b/common/transport/lwm2m/pom.xml index cd579c9011..6f61468ed7 100644 --- a/common/transport/lwm2m/pom.xml +++ b/common/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.3.0-RC + 4.3.0.1-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/mqtt/pom.xml b/common/transport/mqtt/pom.xml index a1e13b9d37..5521d83c13 100644 --- a/common/transport/mqtt/pom.xml +++ b/common/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.3.0-RC + 4.3.0.1-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/pom.xml b/common/transport/pom.xml index 697874ea7e..b1c85d22e3 100644 --- a/common/transport/pom.xml +++ b/common/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/snmp/pom.xml b/common/transport/snmp/pom.xml index 011c01a453..eb6ddc4c16 100644 --- a/common/transport/snmp/pom.xml +++ b/common/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard.common - 4.3.0-RC + 4.3.0.1-SNAPSHOT transport diff --git a/common/transport/transport-api/pom.xml b/common/transport/transport-api/pom.xml index 50a0a07b03..26c15a8c9f 100644 --- a/common/transport/transport-api/pom.xml +++ b/common/transport/transport-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.3.0-RC + 4.3.0.1-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/util/pom.xml b/common/util/pom.xml index c540f756a7..96e393dc57 100644 --- a/common/util/pom.xml +++ b/common/util/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/version-control/pom.xml b/common/version-control/pom.xml index ce7102d3f2..f41fe2b4c0 100644 --- a/common/version-control/pom.xml +++ b/common/version-control/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/dao/pom.xml b/dao/pom.xml index 4ec8d13fd0..0b1874919b 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT thingsboard dao diff --git a/edqs/pom.xml b/edqs/pom.xml index 25c6125d82..57b843bfb9 100644 --- a/edqs/pom.xml +++ b/edqs/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT thingsboard edqs diff --git a/monitoring/pom.xml b/monitoring/pom.xml index a1addced5d..23c857204c 100644 --- a/monitoring/pom.xml +++ b/monitoring/pom.xml @@ -21,7 +21,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT thingsboard diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index 425948ae43..6f59dd3a3d 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/edqs/pom.xml b/msa/edqs/pom.xml index 8de67e23b3..2082f134b0 100644 --- a/msa/edqs/pom.xml +++ b/msa/edqs/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/js-executor/package.json b/msa/js-executor/package.json index df1d327c1b..7d4d858f22 100644 --- a/msa/js-executor/package.json +++ b/msa/js-executor/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-js-executor", "private": true, - "version": "4.3.0", + "version": "4.3.0.1", "description": "ThingsBoard JavaScript Executor Microservice", "main": "server.ts", "bin": "server.js", diff --git a/msa/js-executor/pom.xml b/msa/js-executor/pom.xml index 6bd15adc43..31ea60943d 100644 --- a/msa/js-executor/pom.xml +++ b/msa/js-executor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/monitoring/pom.xml b/msa/monitoring/pom.xml index fb10c11ec0..188f1f8bb2 100644 --- a/msa/monitoring/pom.xml +++ b/msa/monitoring/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT msa diff --git a/msa/pom.xml b/msa/pom.xml index b5c40015f7..c03701ca93 100644 --- a/msa/pom.xml +++ b/msa/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT thingsboard msa diff --git a/msa/tb-node/pom.xml b/msa/tb-node/pom.xml index 078f2e1756..d6f08dd6f7 100644 --- a/msa/tb-node/pom.xml +++ b/msa/tb-node/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/tb/pom.xml b/msa/tb/pom.xml index 8825ea7e33..f9449f97ce 100644 --- a/msa/tb/pom.xml +++ b/msa/tb/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/coap/pom.xml b/msa/transport/coap/pom.xml index 9222a95ec2..9809bc2b1e 100644 --- a/msa/transport/coap/pom.xml +++ b/msa/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 4.3.0-RC + 4.3.0.1-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/http/pom.xml b/msa/transport/http/pom.xml index 4ecf529b2c..9ec5f75cd0 100644 --- a/msa/transport/http/pom.xml +++ b/msa/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 4.3.0-RC + 4.3.0.1-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/lwm2m/pom.xml b/msa/transport/lwm2m/pom.xml index 9aec571309..a43ef587b9 100644 --- a/msa/transport/lwm2m/pom.xml +++ b/msa/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 4.3.0-RC + 4.3.0.1-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/mqtt/pom.xml b/msa/transport/mqtt/pom.xml index 2ad9d62c9d..75e8da0d74 100644 --- a/msa/transport/mqtt/pom.xml +++ b/msa/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 4.3.0-RC + 4.3.0.1-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/pom.xml b/msa/transport/pom.xml index f26c27cb4b..60aa6e123f 100644 --- a/msa/transport/pom.xml +++ b/msa/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/snmp/pom.xml b/msa/transport/snmp/pom.xml index a6bb9ebc8f..fb28fbba16 100644 --- a/msa/transport/snmp/pom.xml +++ b/msa/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard.msa transport - 4.3.0-RC + 4.3.0.1-SNAPSHOT org.thingsboard.msa.transport diff --git a/msa/vc-executor-docker/pom.xml b/msa/vc-executor-docker/pom.xml index a740f99743..285761d35a 100644 --- a/msa/vc-executor-docker/pom.xml +++ b/msa/vc-executor-docker/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/vc-executor/pom.xml b/msa/vc-executor/pom.xml index cb71d86ef4..1fbe33abaf 100644 --- a/msa/vc-executor/pom.xml +++ b/msa/vc-executor/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/web-ui/package.json b/msa/web-ui/package.json index 0c22a38465..13d040b836 100644 --- a/msa/web-ui/package.json +++ b/msa/web-ui/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-web-ui", "private": true, - "version": "4.3.0", + "version": "4.3.0.1", "description": "ThingsBoard Web UI Microservice", "main": "server.ts", "bin": "server.js", diff --git a/msa/web-ui/pom.xml b/msa/web-ui/pom.xml index 40059304ba..0a84e52620 100644 --- a/msa/web-ui/pom.xml +++ b/msa/web-ui/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT msa org.thingsboard.msa diff --git a/netty-mqtt/pom.xml b/netty-mqtt/pom.xml index 4ea598d363..c7c077ef38 100644 --- a/netty-mqtt/pom.xml +++ b/netty-mqtt/pom.xml @@ -19,11 +19,11 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT thingsboard netty-mqtt - 4.3.0-RC + 4.3.0.1-SNAPSHOT jar Netty MQTT Client diff --git a/pom.xml b/pom.xml index 92a002cde0..353c295038 100755 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT pom Thingsboard diff --git a/rest-client/pom.xml b/rest-client/pom.xml index 1b33aca512..86e2613dcd 100644 --- a/rest-client/pom.xml +++ b/rest-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT thingsboard rest-client diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml index feb8cbf8f1..a03695f64f 100644 --- a/rule-engine/pom.xml +++ b/rule-engine/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT thingsboard rule-engine diff --git a/rule-engine/rule-engine-api/pom.xml b/rule-engine/rule-engine-api/pom.xml index 7523afc0b6..07719631be 100644 --- a/rule-engine/rule-engine-api/pom.xml +++ b/rule-engine/rule-engine-api/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml index f9218b69de..97f2ad65b1 100644 --- a/rule-engine/rule-engine-components/pom.xml +++ b/rule-engine/rule-engine-components/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/tools/pom.xml b/tools/pom.xml index 20c8fc95fc..4d94ff81df 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT thingsboard tools diff --git a/transport/coap/pom.xml b/transport/coap/pom.xml index ded25e8260..d9b28c7a5e 100644 --- a/transport/coap/pom.xml +++ b/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/http/pom.xml b/transport/http/pom.xml index 2c83bebd0a..a5d093e726 100644 --- a/transport/http/pom.xml +++ b/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/lwm2m/pom.xml b/transport/lwm2m/pom.xml index e28fd452cf..5e744d7fca 100644 --- a/transport/lwm2m/pom.xml +++ b/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml index 2bee6f94e4..c53b606704 100644 --- a/transport/mqtt/pom.xml +++ b/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/pom.xml b/transport/pom.xml index 89c0355407..83c0fccd83 100644 --- a/transport/pom.xml +++ b/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT thingsboard transport diff --git a/transport/snmp/pom.xml b/transport/snmp/pom.xml index 38682ade69..39f72755e5 100644 --- a/transport/snmp/pom.xml +++ b/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT transport diff --git a/ui-ngx/package.json b/ui-ngx/package.json index 3403e7a3aa..329f249912 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -1,6 +1,6 @@ { "name": "thingsboard", - "version": "4.3.0", + "version": "4.3.0.1", "scripts": { "ng": "ng", "start": "node --max_old_space_size=8048 ./node_modules/@angular/cli/bin/ng serve --configuration development --host 0.0.0.0 --open", diff --git a/ui-ngx/pom.xml b/ui-ngx/pom.xml index bc0f5a4ed8..eaca4ec83c 100644 --- a/ui-ngx/pom.xml +++ b/ui-ngx/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0-RC + 4.3.0.1-SNAPSHOT thingsboard org.thingsboard From 7900c51b9db07339a29893e89fa49823a056a1ec Mon Sep 17 00:00:00 2001 From: Viacheslav Klimov Date: Fri, 23 Jan 2026 15:57:21 +0200 Subject: [PATCH 066/742] Version set to 4.4.0-SNAPSHOT --- application/pom.xml | 2 +- .../service/install/DefaultDatabaseSchemaSettingsService.java | 2 +- application/src/main/resources/thingsboard.yml | 2 +- common/actor/pom.xml | 2 +- common/cache/pom.xml | 2 +- common/cluster-api/pom.xml | 2 +- common/coap-server/pom.xml | 2 +- common/dao-api/pom.xml | 2 +- common/data/pom.xml | 2 +- common/discovery-api/pom.xml | 2 +- common/edge-api/pom.xml | 2 +- common/edqs/pom.xml | 2 +- common/message/pom.xml | 2 +- common/pom.xml | 2 +- common/proto/pom.xml | 2 +- common/queue/pom.xml | 2 +- common/script/pom.xml | 2 +- common/script/remote-js-client/pom.xml | 2 +- common/script/script-api/pom.xml | 2 +- common/stats/pom.xml | 2 +- common/transport/coap/pom.xml | 2 +- common/transport/http/pom.xml | 2 +- common/transport/lwm2m/pom.xml | 2 +- common/transport/mqtt/pom.xml | 2 +- common/transport/pom.xml | 2 +- common/transport/snmp/pom.xml | 2 +- common/transport/transport-api/pom.xml | 2 +- common/util/pom.xml | 2 +- common/version-control/pom.xml | 2 +- dao/pom.xml | 2 +- edqs/pom.xml | 2 +- monitoring/pom.xml | 2 +- msa/black-box-tests/pom.xml | 2 +- msa/edqs/pom.xml | 2 +- msa/js-executor/package.json | 2 +- msa/js-executor/pom.xml | 2 +- msa/monitoring/pom.xml | 2 +- msa/pom.xml | 4 ++-- msa/tb-node/pom.xml | 2 +- msa/tb/pom.xml | 2 +- msa/transport/coap/pom.xml | 2 +- msa/transport/http/pom.xml | 2 +- msa/transport/lwm2m/pom.xml | 2 +- msa/transport/mqtt/pom.xml | 2 +- msa/transport/pom.xml | 2 +- msa/transport/snmp/pom.xml | 2 +- msa/vc-executor-docker/pom.xml | 2 +- msa/vc-executor/pom.xml | 2 +- msa/web-ui/package.json | 2 +- msa/web-ui/pom.xml | 2 +- netty-mqtt/pom.xml | 4 ++-- pom.xml | 2 +- rest-client/pom.xml | 2 +- rule-engine/pom.xml | 2 +- rule-engine/rule-engine-api/pom.xml | 2 +- rule-engine/rule-engine-components/pom.xml | 2 +- tools/pom.xml | 2 +- transport/coap/pom.xml | 2 +- transport/http/pom.xml | 2 +- transport/lwm2m/pom.xml | 2 +- transport/mqtt/pom.xml | 2 +- transport/pom.xml | 2 +- transport/snmp/pom.xml | 2 +- ui-ngx/package.json | 2 +- ui-ngx/pom.xml | 2 +- 65 files changed, 67 insertions(+), 67 deletions(-) diff --git a/application/pom.xml b/application/pom.xml index d2cc11f069..0f3c9623f9 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT thingsboard application diff --git a/application/src/main/java/org/thingsboard/server/service/install/DefaultDatabaseSchemaSettingsService.java b/application/src/main/java/org/thingsboard/server/service/install/DefaultDatabaseSchemaSettingsService.java index 468aa80e6c..b692194382 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/DefaultDatabaseSchemaSettingsService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/DefaultDatabaseSchemaSettingsService.java @@ -31,7 +31,7 @@ public class DefaultDatabaseSchemaSettingsService implements DatabaseSchemaSetti // This list should include all versions that are compatible for the upgrade in 4 digits format (like 4.2.0.0, etc.). // The compatibility cycle usually breaks when we have some scripts written in Java that may not work after a new release. // TODO: don't check the "patch" number, since upgrade is not required for patch releases - private static final List SUPPORTED_VERSIONS_FOR_UPGRADE = List.of("4.3.0.0"); + private static final List SUPPORTED_VERSIONS_FOR_UPGRADE = List.of("4.3.0.0", "4.3.0.1"); private final ProjectInfo projectInfo; private final JdbcTemplate jdbcTemplate; diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 072e18af69..ef0d83d564 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -217,7 +217,7 @@ ui: # Help parameters help: # Base URL for UI help assets - base-url: "${UI_HELP_BASE_URL:https://raw.githubusercontent.com/thingsboard/thingsboard-ui-help/release-4.3}" + base-url: "${UI_HELP_BASE_URL:https://raw.githubusercontent.com/thingsboard/thingsboard-ui-help/release-4.4}" # Database telemetry parameters database: diff --git a/common/actor/pom.xml b/common/actor/pom.xml index 64727ab3f7..6326c45685 100644 --- a/common/actor/pom.xml +++ b/common/actor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/common/cache/pom.xml b/common/cache/pom.xml index 163c47356d..774015fc33 100644 --- a/common/cache/pom.xml +++ b/common/cache/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/common/cluster-api/pom.xml b/common/cluster-api/pom.xml index 9be12f3b18..5983b96b95 100644 --- a/common/cluster-api/pom.xml +++ b/common/cluster-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/common/coap-server/pom.xml b/common/coap-server/pom.xml index 2e8aca2ba4..32824826c3 100644 --- a/common/coap-server/pom.xml +++ b/common/coap-server/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml index 3468f51be0..12533cd813 100644 --- a/common/dao-api/pom.xml +++ b/common/dao-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/common/data/pom.xml b/common/data/pom.xml index ccb0eda1f3..0647e706eb 100644 --- a/common/data/pom.xml +++ b/common/data/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/common/discovery-api/pom.xml b/common/discovery-api/pom.xml index 9bcf02dd94..c7658bd738 100644 --- a/common/discovery-api/pom.xml +++ b/common/discovery-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/common/edge-api/pom.xml b/common/edge-api/pom.xml index d52074ace6..b5d7b777da 100644 --- a/common/edge-api/pom.xml +++ b/common/edge-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/common/edqs/pom.xml b/common/edqs/pom.xml index b953da6d11..549ee1515f 100644 --- a/common/edqs/pom.xml +++ b/common/edqs/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/common/message/pom.xml b/common/message/pom.xml index 615989da81..478368afdc 100644 --- a/common/message/pom.xml +++ b/common/message/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/common/pom.xml b/common/pom.xml index 211578b1d2..d241646816 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT thingsboard common diff --git a/common/proto/pom.xml b/common/proto/pom.xml index f024f41992..e24705c25a 100644 --- a/common/proto/pom.xml +++ b/common/proto/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/common/queue/pom.xml b/common/queue/pom.xml index 4cb3f449a3..1cb159b3af 100644 --- a/common/queue/pom.xml +++ b/common/queue/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/common/script/pom.xml b/common/script/pom.xml index 5f352fb70b..a11d320416 100644 --- a/common/script/pom.xml +++ b/common/script/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/common/script/remote-js-client/pom.xml b/common/script/remote-js-client/pom.xml index d1c71bbd9d..202cc20bd3 100644 --- a/common/script/remote-js-client/pom.xml +++ b/common/script/remote-js-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT script org.thingsboard.common.script diff --git a/common/script/script-api/pom.xml b/common/script/script-api/pom.xml index 0ba928ebe1..b074db321a 100644 --- a/common/script/script-api/pom.xml +++ b/common/script/script-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT script org.thingsboard.common.script diff --git a/common/stats/pom.xml b/common/stats/pom.xml index d2942cd813..da650623f9 100644 --- a/common/stats/pom.xml +++ b/common/stats/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/coap/pom.xml b/common/transport/coap/pom.xml index 273e7e2a7d..76ac33b450 100644 --- a/common/transport/coap/pom.xml +++ b/common/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/http/pom.xml b/common/transport/http/pom.xml index cd64cc36d2..275a497b6e 100644 --- a/common/transport/http/pom.xml +++ b/common/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/lwm2m/pom.xml b/common/transport/lwm2m/pom.xml index 6f61468ed7..f47255ac7e 100644 --- a/common/transport/lwm2m/pom.xml +++ b/common/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/mqtt/pom.xml b/common/transport/mqtt/pom.xml index 5521d83c13..985c2a82f6 100644 --- a/common/transport/mqtt/pom.xml +++ b/common/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/pom.xml b/common/transport/pom.xml index b1c85d22e3..810b22670a 100644 --- a/common/transport/pom.xml +++ b/common/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/snmp/pom.xml b/common/transport/snmp/pom.xml index eb6ddc4c16..f98b2426dc 100644 --- a/common/transport/snmp/pom.xml +++ b/common/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard.common - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT transport diff --git a/common/transport/transport-api/pom.xml b/common/transport/transport-api/pom.xml index 26c15a8c9f..73e0bdeec0 100644 --- a/common/transport/transport-api/pom.xml +++ b/common/transport/transport-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/util/pom.xml b/common/util/pom.xml index 96e393dc57..f3077d49c3 100644 --- a/common/util/pom.xml +++ b/common/util/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/common/version-control/pom.xml b/common/version-control/pom.xml index f41fe2b4c0..d9e134128d 100644 --- a/common/version-control/pom.xml +++ b/common/version-control/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT common org.thingsboard.common diff --git a/dao/pom.xml b/dao/pom.xml index 0b1874919b..928a107079 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT thingsboard dao diff --git a/edqs/pom.xml b/edqs/pom.xml index 57b843bfb9..1081b89276 100644 --- a/edqs/pom.xml +++ b/edqs/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT thingsboard edqs diff --git a/monitoring/pom.xml b/monitoring/pom.xml index 23c857204c..391347e56b 100644 --- a/monitoring/pom.xml +++ b/monitoring/pom.xml @@ -21,7 +21,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT thingsboard diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index 6f59dd3a3d..b08d05ed35 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/edqs/pom.xml b/msa/edqs/pom.xml index 2082f134b0..e6adae1f87 100644 --- a/msa/edqs/pom.xml +++ b/msa/edqs/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/js-executor/package.json b/msa/js-executor/package.json index 7d4d858f22..cf7310a084 100644 --- a/msa/js-executor/package.json +++ b/msa/js-executor/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-js-executor", "private": true, - "version": "4.3.0.1", + "version": "4.4.0", "description": "ThingsBoard JavaScript Executor Microservice", "main": "server.ts", "bin": "server.js", diff --git a/msa/js-executor/pom.xml b/msa/js-executor/pom.xml index 31ea60943d..0e75d24919 100644 --- a/msa/js-executor/pom.xml +++ b/msa/js-executor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/monitoring/pom.xml b/msa/monitoring/pom.xml index 188f1f8bb2..27b05f525d 100644 --- a/msa/monitoring/pom.xml +++ b/msa/monitoring/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT msa diff --git a/msa/pom.xml b/msa/pom.xml index c03701ca93..04b1814063 100644 --- a/msa/pom.xml +++ b/msa/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT thingsboard msa @@ -133,7 +133,7 @@ - 4.3.0-latest + 4.4.0-latest false diff --git a/msa/tb-node/pom.xml b/msa/tb-node/pom.xml index d6f08dd6f7..2244241347 100644 --- a/msa/tb-node/pom.xml +++ b/msa/tb-node/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/tb/pom.xml b/msa/tb/pom.xml index f9449f97ce..1bf32786e7 100644 --- a/msa/tb/pom.xml +++ b/msa/tb/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/coap/pom.xml b/msa/transport/coap/pom.xml index 9809bc2b1e..e89a10e5a1 100644 --- a/msa/transport/coap/pom.xml +++ b/msa/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/http/pom.xml b/msa/transport/http/pom.xml index 9ec5f75cd0..76b7ff9602 100644 --- a/msa/transport/http/pom.xml +++ b/msa/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/lwm2m/pom.xml b/msa/transport/lwm2m/pom.xml index a43ef587b9..9c10edfbb7 100644 --- a/msa/transport/lwm2m/pom.xml +++ b/msa/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/mqtt/pom.xml b/msa/transport/mqtt/pom.xml index 75e8da0d74..ff759a52ff 100644 --- a/msa/transport/mqtt/pom.xml +++ b/msa/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/pom.xml b/msa/transport/pom.xml index 60aa6e123f..92978fcaa7 100644 --- a/msa/transport/pom.xml +++ b/msa/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/snmp/pom.xml b/msa/transport/snmp/pom.xml index fb28fbba16..049cbad4ec 100644 --- a/msa/transport/snmp/pom.xml +++ b/msa/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard.msa transport - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT org.thingsboard.msa.transport diff --git a/msa/vc-executor-docker/pom.xml b/msa/vc-executor-docker/pom.xml index 285761d35a..183a82a170 100644 --- a/msa/vc-executor-docker/pom.xml +++ b/msa/vc-executor-docker/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/vc-executor/pom.xml b/msa/vc-executor/pom.xml index 1fbe33abaf..6b0277c2c6 100644 --- a/msa/vc-executor/pom.xml +++ b/msa/vc-executor/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/web-ui/package.json b/msa/web-ui/package.json index 13d040b836..4544aece37 100644 --- a/msa/web-ui/package.json +++ b/msa/web-ui/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-web-ui", "private": true, - "version": "4.3.0.1", + "version": "4.4.0", "description": "ThingsBoard Web UI Microservice", "main": "server.ts", "bin": "server.js", diff --git a/msa/web-ui/pom.xml b/msa/web-ui/pom.xml index 0a84e52620..7dfc4c0aee 100644 --- a/msa/web-ui/pom.xml +++ b/msa/web-ui/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT msa org.thingsboard.msa diff --git a/netty-mqtt/pom.xml b/netty-mqtt/pom.xml index c7c077ef38..6856da9233 100644 --- a/netty-mqtt/pom.xml +++ b/netty-mqtt/pom.xml @@ -19,11 +19,11 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT thingsboard netty-mqtt - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT jar Netty MQTT Client diff --git a/pom.xml b/pom.xml index 353c295038..aee23b8090 100755 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT pom Thingsboard diff --git a/rest-client/pom.xml b/rest-client/pom.xml index a63cca91fd..9996b19d00 100644 --- a/rest-client/pom.xml +++ b/rest-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT thingsboard rest-client diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml index a03695f64f..bba58e92a8 100644 --- a/rule-engine/pom.xml +++ b/rule-engine/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT thingsboard rule-engine diff --git a/rule-engine/rule-engine-api/pom.xml b/rule-engine/rule-engine-api/pom.xml index 07719631be..a9f58a08b3 100644 --- a/rule-engine/rule-engine-api/pom.xml +++ b/rule-engine/rule-engine-api/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml index 97f2ad65b1..4e092211b8 100644 --- a/rule-engine/rule-engine-components/pom.xml +++ b/rule-engine/rule-engine-components/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/tools/pom.xml b/tools/pom.xml index 4d94ff81df..ed02dbf836 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT thingsboard tools diff --git a/transport/coap/pom.xml b/transport/coap/pom.xml index d9b28c7a5e..c012e863f9 100644 --- a/transport/coap/pom.xml +++ b/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/http/pom.xml b/transport/http/pom.xml index a5d093e726..87f3ccec21 100644 --- a/transport/http/pom.xml +++ b/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/lwm2m/pom.xml b/transport/lwm2m/pom.xml index 5e744d7fca..d92d41388e 100644 --- a/transport/lwm2m/pom.xml +++ b/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml index c53b606704..f99409c470 100644 --- a/transport/mqtt/pom.xml +++ b/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/pom.xml b/transport/pom.xml index 83c0fccd83..3b6195f9d8 100644 --- a/transport/pom.xml +++ b/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT thingsboard transport diff --git a/transport/snmp/pom.xml b/transport/snmp/pom.xml index 39f72755e5..54a949f320 100644 --- a/transport/snmp/pom.xml +++ b/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT transport diff --git a/ui-ngx/package.json b/ui-ngx/package.json index 329f249912..c1385e46d2 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -1,6 +1,6 @@ { "name": "thingsboard", - "version": "4.3.0.1", + "version": "4.4.0", "scripts": { "ng": "ng", "start": "node --max_old_space_size=8048 ./node_modules/@angular/cli/bin/ng serve --configuration development --host 0.0.0.0 --open", diff --git a/ui-ngx/pom.xml b/ui-ngx/pom.xml index eaca4ec83c..11ce2dcf5f 100644 --- a/ui-ngx/pom.xml +++ b/ui-ngx/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.3.0.1-SNAPSHOT + 4.4.0-SNAPSHOT thingsboard org.thingsboard From 1fcc419dbca09b5af21a587a52618cf169036470 Mon Sep 17 00:00:00 2001 From: Viacheslav Klimov Date: Fri, 23 Jan 2026 16:19:02 +0200 Subject: [PATCH 067/742] Fix LwM2MTestClient --- .../lwm2m/client/LwM2MTestClient.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java index fd531e8022..c9c39bc701 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java @@ -33,7 +33,6 @@ import org.eclipse.leshan.client.object.Security; import org.eclipse.leshan.client.object.Server; import org.eclipse.leshan.client.observer.LwM2mClientObserver; import org.eclipse.leshan.client.resource.DummyInstanceEnabler; -import org.eclipse.leshan.client.resource.LwM2mInstanceEnabler; import org.eclipse.leshan.client.resource.LwM2mObjectEnabler; import org.eclipse.leshan.client.resource.ObjectsInitializer; import org.eclipse.leshan.client.resource.listener.ObjectsListenerAdapter; @@ -142,7 +141,7 @@ public class LwM2MTestClient { private Map clientDtlsCid; private LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandlerTest; private LwM2mClientContext clientContext; - private LwM2mTemperatureSensor lwM2mTemperatureSensor12; + private LwM2mTemperatureSensor lwM2MTemperatureSensor12; private String deviceIdStr; private int clientPort; @@ -161,7 +160,7 @@ public class LwM2MTestClient { if (securityLwm2m != null && securityLwm2m.getId() != null) { forceNullSecurityId(securityLwm2m); } - if (securityBs!= null && securityBs.getId() != null) { + if (securityBs != null && securityBs.getId() != null) { forceNullSecurityId(securityBs); } if (securityBs != null && securityLwm2m != null) { @@ -170,7 +169,7 @@ public class LwM2MTestClient { } else if (securityBs != null) { log.warn("Security BS only: securityBs: [{}] ", securityBs.getId()); initializer.setInstancesForObject(SECURITY, securityBs); - } else if (securityLwm2m != null){ + } else if (securityLwm2m != null) { // SECURITY log.warn("Security Lwm2m only: security Lwm2m [{}]", securityLwm2m.getId()); initializer.setInstancesForObject(SECURITY, securityLwm2m); @@ -191,8 +190,8 @@ public class LwM2MTestClient { locationParams.getPos(); initializer.setInstancesForObject(LOCATION, new LwM2mLocation(locationParams.getLatitude(), locationParams.getLongitude(), locationParams.getScaleFactor(), executor, OBJECT_INSTANCE_ID_0)); LwM2mTemperatureSensor lwM2mTemperatureSensor0 = new LwM2mTemperatureSensor(executor, OBJECT_INSTANCE_ID_0); - lwM2mTemperatureSensor12 = new LwM2mTemperatureSensor(executor, OBJECT_INSTANCE_ID_12); - initializer.setInstancesForObject(TEMPERATURE_SENSOR, lwM2mTemperatureSensor0, lwM2mTemperatureSensor12); + lwM2MTemperatureSensor12 = new LwM2mTemperatureSensor(executor, OBJECT_INSTANCE_ID_12); + initializer.setInstancesForObject(TEMPERATURE_SENSOR, lwM2mTemperatureSensor0, lwM2MTemperatureSensor12); List enablers = initializer.createAll(); @@ -213,7 +212,9 @@ public class LwM2MTestClient { builder.setSessionListener(new DtlsSessionLogger(clientStates, clientDtlsCid)); return builder; - }; + } + + ; }; } }; @@ -479,7 +480,7 @@ public class LwM2MTestClient { if (isStartLw) { this.awaitClientAfterStartConnectLw(); } - lwM2mTemperatureSensor12.setLeshanClient(leshanClient); + lwM2MTemperatureSensor12.setLeshanClient(leshanClient); fwLwM2MDevice.setLeshanClient(leshanClient); } } @@ -554,5 +555,6 @@ public class LwM2MTestClient { log.error("[forceNullSecurityId] Failed to set id=null for {}", security.getClass(), e); } } + } From d568ee8536d51ceb8fa47ed199b82244b8c5bba3 Mon Sep 17 00:00:00 2001 From: IrynaMatveieva Date: Fri, 23 Jan 2026 16:55:46 +0200 Subject: [PATCH 068/742] fix: process cfs that uses the same key and some of cfs throws error --- ...CalculatedFieldEntityMessageProcessor.java | 27 +++++- .../cf/ctx/state/CalculatedFieldCtx.java | 2 +- .../cf/CalculatedFieldIntegrationTest.java | 93 +++++++++++++++++++ .../server/controller/AbstractWebTest.java | 13 +++ 4 files changed, 131 insertions(+), 4 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldEntityMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldEntityMessageProcessor.java index 752e8a1c11..b95beb81a1 100644 --- a/application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldEntityMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldEntityMessageProcessor.java @@ -131,11 +131,12 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM if (state.isSizeOk()) { processStateIfReady(ctx, Collections.singletonList(ctx.getCfId()), state, null, null, msg.getCallback()); } else { - throw new RuntimeException(ctx.getSizeExceedsLimitMessage()); + throw CalculatedFieldException.builder().ctx(ctx).eventEntity(entityId).errorMessage(ctx.getSizeExceedsLimitMessage()).build(); } } catch (Exception e) { if (e instanceof CalculatedFieldException cfe) { - throw cfe; + persistDebugErrorIfEnabled(cfe, msg.getCallback()); + return; } throw CalculatedFieldException.builder().ctx(ctx).eventEntity(entityId).cause(e).build(); } @@ -200,6 +201,10 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM } } } catch (Exception e) { + if (e instanceof CalculatedFieldException cfe) { + persistDebugErrorIfEnabled(cfe, callback); + return; + } throw CalculatedFieldException.builder().ctx(ctx).eventEntity(entityId).cause(e).build(); } } @@ -223,7 +228,8 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM } } catch (Exception e) { if (e instanceof CalculatedFieldException cfe) { - throw cfe; + persistDebugErrorIfEnabled(cfe, callback); + return; } throw CalculatedFieldException.builder().ctx(ctx).eventEntity(entityId).cause(e).build(); } @@ -485,4 +491,19 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM return null; } + private void persistDebugErrorIfEnabled(CalculatedFieldException cfe, TbCallback callback) { + if (DebugModeUtil.isDebugFailuresAvailable(cfe.getCtx().getCalculatedField())) { + String message; + if (cfe.getErrorMessage() != null) { + message = cfe.getErrorMessage(); + } else if (cfe.getCause() != null) { + message = cfe.getCause().getMessage(); + } else { + message = "N/A"; + } + systemContext.persistCalculatedFieldDebugEvent(tenantId, cfe.getCtx().getCfId(), cfe.getEventEntity(), cfe.getArguments(), cfe.getMsgId(), cfe.getMsgType(), null, message); + } + callback.onSuccess(); + } + } diff --git a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java index 5d0ff5c2ff..373e2f588f 100644 --- a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java +++ b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java @@ -310,7 +310,7 @@ public class CalculatedFieldCtx { } public String getSizeExceedsLimitMessage() { - return "Failed to init CF state. State size exceeds limit of " + (maxStateSize / 1024) + "Kb!"; + return "State size exceeds limit of " + (maxStateSize / 1024) + "Kb!"; } } diff --git a/application/src/test/java/org/thingsboard/server/cf/CalculatedFieldIntegrationTest.java b/application/src/test/java/org/thingsboard/server/cf/CalculatedFieldIntegrationTest.java index a21b081086..7f905ec0ae 100644 --- a/application/src/test/java/org/thingsboard/server/cf/CalculatedFieldIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/cf/CalculatedFieldIntegrationTest.java @@ -23,6 +23,7 @@ import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.AttributeScope; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.EventInfo; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.cf.CalculatedField; @@ -36,7 +37,9 @@ import org.thingsboard.server.common.data.cf.configuration.ScriptCalculatedField import org.thingsboard.server.common.data.cf.configuration.SimpleCalculatedFieldConfiguration; import org.thingsboard.server.common.data.debug.DebugSettings; import org.thingsboard.server.common.data.id.AssetProfileId; +import org.thingsboard.server.common.data.id.CalculatedFieldId; import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.controller.CalculatedFieldControllerTest; import org.thingsboard.server.dao.service.DaoSqlTest; @@ -875,6 +878,96 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes }); } + @Test + public void testCalculatedFieldsWhenOneIsInvalid() throws Exception { + Device testDevice = createDevice("Test device", "1234567890"); + long now = System.currentTimeMillis(); + doPost("/api/plugins/telemetry/DEVICE/" + testDevice.getUuidId() + "/timeseries/" + DataConstants.SERVER_SCOPE, JacksonUtil.toJsonNode(String.format("{\"ts\": %s, \"values\": {\"a\":5}}", now - TimeUnit.MINUTES.toMillis(3)))); + + // Script CF - invalid + CalculatedField invalidCF = new CalculatedField(); + invalidCF.setEntityId(testDevice.getId()); + invalidCF.setType(CalculatedFieldType.SCRIPT); + invalidCF.setName("Script CF"); + invalidCF.setDebugSettings(DebugSettings.all()); + + ScriptCalculatedFieldConfiguration scriptConfig = new ScriptCalculatedFieldConfiguration(); + + ReferencedEntityKey refEntityKeyA = new ReferencedEntityKey("a", ArgumentType.TS_LATEST, null); + Argument argumentA = new Argument(); + argumentA.setRefEntityKey(refEntityKeyA); + scriptConfig.setArguments(Map.of("a", argumentA)); + scriptConfig.setExpression(""" + return { + "temperature": temp + }; + """); + + Output scriptOutput = new Output(); + scriptOutput.setType(OutputType.TIME_SERIES); + scriptConfig.setOutput(scriptOutput); + + invalidCF.setConfiguration(scriptConfig); + + invalidCF = doPost("/api/calculatedField", invalidCF, CalculatedField.class); + CalculatedFieldId invalidCfId = invalidCF.getId(); + + await().alias("create invalid CF -> check error").atMost(TIMEOUT, TimeUnit.SECONDS) + .pollInterval(POLL_INTERVAL, TimeUnit.SECONDS) + .untilAsserted(() -> { + PageData debugEvents = getDebugEvents(tenantId, invalidCfId, 1); + if (!debugEvents.getData().isEmpty()) { + EventInfo eventInfo = debugEvents.getData().get(0); + assertThat(eventInfo.getBody().has("error")).isTrue(); + } + }); + + // Simple CF - valid + CalculatedField validCF = new CalculatedField(); + validCF.setEntityId(testDevice.getId()); + validCF.setType(CalculatedFieldType.SIMPLE); + validCF.setName("Simple CF"); + validCF.setDebugSettings(DebugSettings.all()); + + SimpleCalculatedFieldConfiguration simpleConfig = new SimpleCalculatedFieldConfiguration(); + simpleConfig.setArguments(Map.of("a", argumentA)); + simpleConfig.setExpression("a+1"); + + Output simpleOutput = new Output(); + simpleOutput.setName("a+1"); + simpleOutput.setType(OutputType.TIME_SERIES); + simpleOutput.setDecimalsByDefault(0); + simpleConfig.setOutput(simpleOutput); + + validCF.setConfiguration(simpleConfig); + + validCF = doPost("/api/calculatedField", validCF, CalculatedField.class); + CalculatedFieldId validCfId = validCF.getId(); + + await().alias("create CF -> check initial calculation").atMost(TIMEOUT, TimeUnit.SECONDS) + .pollInterval(POLL_INTERVAL, TimeUnit.SECONDS) + .untilAsserted(() -> { + PageData debugEvents = getDebugEvents(tenantId, validCfId, 1); + if (!debugEvents.getData().isEmpty()) { + EventInfo eventInfo = debugEvents.getData().get(0); + assertThat(eventInfo.getBody().has("error")).isFalse(); + } + ObjectNode result = getLatestTelemetry(testDevice.getId(), "a+1"); + assertThat(result).isNotNull(); + assertThat(result.get("a+1").get(0).get("value").asText()).isEqualTo("6"); + }); + + doPost("/api/plugins/telemetry/DEVICE/" + testDevice.getUuidId() + "/timeseries/" + DataConstants.SERVER_SCOPE, JacksonUtil.toJsonNode("{\"a\":6}")); + + await().alias("update telemetry -> recalculate state").atMost(TIMEOUT, TimeUnit.SECONDS) + .pollInterval(POLL_INTERVAL, TimeUnit.SECONDS) + .untilAsserted(() -> { + ObjectNode result = getLatestTelemetry(testDevice.getId(), "a+1"); + assertThat(result).isNotNull(); + assertThat(result.get("a+1").get(0).get("value").asText()).isEqualTo("7"); + }); + } + private ObjectNode getLatestTelemetry(EntityId entityId, String... keys) throws Exception { return doGetAsync("/api/plugins/telemetry/" + entityId.getEntityType() + "/" + entityId.getId() + "/values/timeseries?keys=" + String.join(",", keys), ObjectNode.class); } diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java index 44c383a5f0..3b7286cf01 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java @@ -80,6 +80,7 @@ import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileType; import org.thingsboard.server.common.data.DeviceTransportType; +import org.thingsboard.server.common.data.EventInfo; import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.TbResourceInfo; @@ -99,6 +100,7 @@ import org.thingsboard.server.common.data.device.profile.MqttTopics; import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.event.EventType; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; @@ -1298,4 +1300,15 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { doPost("/api/job/" + jobId + "/reprocess").andExpect(status().isOk()); } + protected PageData getDebugEvents(TenantId tenantId, EntityId entityId, int limit) throws Exception { + return getEvents(tenantId, entityId, EventType.DEBUG_RULE_NODE, limit); + } + + protected PageData getEvents(TenantId tenantId, EntityId entityId, EventType eventType, int limit) throws Exception { + TimePageLink pageLink = new TimePageLink(limit); + return doGetTypedWithTimePageLink("/api/events/{entityType}/{entityId}/{eventType}?tenantId={tenantId}&", + new TypeReference>() { + }, pageLink, entityId.getEntityType(), entityId.getId(), eventType, tenantId.getId()); + } + } From 50a94b90f34b21ac013f35d8e3e42ddc799b13a4 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Fri, 23 Jan 2026 17:33:15 +0200 Subject: [PATCH 069/742] Angular 20 migration --- ui-ngx/package.json | 36 +- ui-ngx/src/app/app.component.ts | 7 +- .../ai-model/ai-model-dialog.component.ts | 7 +- .../check-connectivity-dialog.component.ts | 7 +- .../alarm/alarm-assignee-panel.component.ts | 7 +- .../alarm-assignee-select-panel.component.ts | 7 +- .../alarm/alarm-assignee-select.component.ts | 21 +- .../alarm/alarm-assignee.component.ts | 7 +- .../alarm/alarm-comment-dialog.component.ts | 7 +- .../alarm/alarm-comment.component.ts | 7 +- .../alarm/alarm-details-dialog.component.ts | 7 +- .../alarm/alarm-filter-config.component.ts | 21 +- .../alarm/alarm-table-header.component.ts | 7 +- .../components/alarm/alarm-table.component.ts | 7 +- .../aliases-entity-autocomplete.component.ts | 17 +- .../aliases-entity-select-panel.component.ts | 7 +- .../alias/aliases-entity-select.component.ts | 7 +- .../alias/entity-alias-dialog.component.ts | 9 +- .../alias/entity-aliases-dialog.component.ts | 9 +- .../add-attribute-dialog.component.ts | 9 +- ...dd-widget-to-dashboard-dialog.component.ts | 9 +- .../attribute/attribute-table.component.ts | 9 +- .../delete-timeseries-panel.component.ts | 7 +- .../edit-attribute-value-panel.component.ts | 9 +- .../audit-log-details-dialog.component.ts | 7 +- .../audit-log/audit-log-table.component.ts | 7 +- .../calculated-fields-table.component.ts | 11 +- ...culated-field-arguments-table.component.ts | 31 +- ...calculated-field-debug-dialog.component.ts | 7 +- .../calculated-field-dialog.component.ts | 9 +- ...lculated-field-argument-panel.component.ts | 7 +- ...lculated-field-test-arguments.component.ts | 31 +- ...ated-field-script-test-dialog.component.ts | 9 +- .../add-widget-dialog.component.ts | 11 +- .../dashboard-image-dialog.component.ts | 7 +- .../dashboard-page.component.ts | 11 +- .../dashboard-settings-dialog.component.ts | 9 +- .../dashboard-state.component.ts | 7 +- .../dashboard-toolbar.component.ts | 9 +- .../dashboard-widget-select.component.ts | 9 +- .../dashboard-page/edit-widget.component.ts | 7 +- .../add-new-breakpoint-dialog.component.ts | 5 +- .../layout/dashboard-layout.component.ts | 7 +- ...nage-dashboard-layouts-dialog.component.ts | 9 +- .../layout/move-widgets-dialog.component.ts | 9 +- .../select-dashboard-breakpoint.component.ts | 7 +- .../dashboard-state-dialog.component.ts | 9 +- .../default-state-controller.component.ts | 7 +- .../entity-state-controller.component.ts | 7 +- ...anage-dashboard-states-dialog.component.ts | 7 +- .../states/states-component.directive.ts | 5 +- .../widget-types-panel.component.ts | 7 +- .../dashboard-view.component.ts | 7 +- .../dashboard/dashboard.component.ts | 9 +- .../select-target-layout-dialog.component.ts | 7 +- .../select-target-state-dialog.component.ts | 9 +- .../components/details-panel.component.ts | 7 +- .../copy-device-credentials.component.ts | 7 +- ...vice-credentials-lwm2m-server.component.ts | 31 +- .../device-credentials-lwm2m.component.ts | 31 +- ...device-credentials-mqtt-basic.component.ts | 30 +- .../device/device-credentials.component.ts | 30 +- .../device/device-info-filter.component.ts | 21 +- .../edge-downlink-table-header.component.ts | 7 +- .../edge/edge-downlink-table.component.ts | 7 +- .../entity/add-entity-dialog.component.ts | 9 +- .../entity-debug-settings-button.component.ts | 33 +- .../entity-debug-settings-panel.component.ts | 17 +- .../entity/entities-table.component.ts | 9 +- .../entity/entity-chips.component.ts | 7 +- .../entity/entity-details-page.component.ts | 9 +- .../entity/entity-details-panel.component.ts | 9 +- .../entity/entity-filter-view.component.ts | 21 +- .../entity/entity-filter.component.ts | 21 +- .../event/event-content-dialog.component.ts | 7 +- .../event/event-filter-panel.component.ts | 7 +- .../event/event-table-header.component.ts | 7 +- .../components/event/event-table.component.ts | 7 +- .../boolean-filter-predicate.component.ts | 31 +- ...mplex-filter-predicate-dialog.component.ts | 9 +- .../complex-filter-predicate.component.ts | 21 +- .../filter/filter-dialog.component.ts | 9 +- .../filter/filter-predicate-list.component.ts | 31 +- .../filter-predicate-value.component.ts | 31 +- .../filter/filter-predicate.component.ts | 31 +- .../filter/filter-text.component.ts | 21 +- .../filter-user-info-dialog.component.ts | 9 +- .../filter/filter-user-info.component.ts | 21 +- .../filter/filters-dialog.component.ts | 9 +- .../filter/filters-edit-panel.component.ts | 7 +- .../filter/filters-edit.component.ts | 7 +- .../filter/key-filter-dialog.component.ts | 9 +- .../filter/key-filter-list.component.ts | 31 +- .../numeric-filter-predicate.component.ts | 31 +- .../string-filter-predicate.component.ts | 31 +- .../filter/user-filter-dialog.component.ts | 9 +- .../github-badge/github-badge.component.ts | 7 +- .../notification-bell.component.ts | 7 +- .../send-notification-button.component.ts | 5 +- .../show-notification-popover.component.ts | 7 +- .../add-device-profile-dialog.component.ts | 9 +- ...larm-duration-predicate-value.component.ts | 21 +- .../alarm/alarm-dynamic-value.component.ts | 15 +- .../alarm-rule-condition-dialog.component.ts | 9 +- .../alarm/alarm-rule-condition.component.ts | 31 +- .../profile/alarm/alarm-rule.component.ts | 31 +- .../alarm/alarm-schedule-dialog.component.ts | 9 +- .../alarm/alarm-schedule-info.component.ts | 17 +- .../profile/alarm/alarm-schedule.component.ts | 25 +- .../alarm/create-alarm-rules.component.ts | 31 +- .../alarm/device-profile-alarm.component.ts | 31 +- .../alarm/device-profile-alarms.component.ts | 31 +- .../edit-alarm-details-dialog.component.ts | 9 +- .../asset-profile-autocomplete.component.ts | 17 +- .../profile/asset-profile-dialog.component.ts | 9 +- .../profile/asset-profile.component.ts | 7 +- .../device-profile-autocomplete.component.ts | 17 +- .../device-profile-dialog.component.ts | 9 +- ...ofile-provision-configuration.component.ts | 31 +- .../profile/device-profile.component.ts | 7 +- ...ofile-transport-configuration.component.ts | 31 +- .../common/power-mode-setting.component.ts | 7 +- .../common/time-unit-select.component.ts | 31 +- ...-device-profile-configuration.component.ts | 17 +- ...ofile-transport-configuration.component.ts | 31 +- .../device-profile-configuration.component.ts | 17 +- ...ofile-transport-configuration.component.ts | 31 +- .../lwm2m-attributes-dialog.component.ts | 9 +- .../lwm2m-attributes-key-list.component.ts | 31 +- .../lwm2m/lwm2m-attributes.component.ts | 17 +- ...trap-add-config-server-dialog.component.ts | 5 +- ...wm2m-bootstrap-config-servers.component.ts | 29 +- .../lwm2m-device-config-server.component.ts | 29 +- ...ofile-transport-configuration.component.ts | 30 +- ...m-object-add-instances-dialog.component.ts | 5 +- ...m2m-object-add-instances-list.component.ts | 28 +- .../lwm2m/lwm2m-object-list.component.ts | 29 +- ...erve-attr-telemetry-instances.component.ts | 31 +- ...erve-attr-telemetry-resources.component.ts | 31 +- .../lwm2m-observe-attr-telemetry.component.ts | 31 +- ...ofile-transport-configuration.component.ts | 31 +- ...-profile-communication-config.component.ts | 30 +- .../snmp-device-profile-mapping.component.ts | 30 +- ...ofile-transport-configuration.component.ts | 30 +- .../queue/tenant-profile-queues.component.ts | 31 +- .../tenant-profile-autocomplete.component.ts | 17 +- .../profile/tenant-profile-data.component.ts | 17 +- .../tenant-profile-dialog.component.ts | 9 +- .../profile/tenant-profile.component.ts | 7 +- ...-tenant-profile-configuration.component.ts | 17 +- .../rate-limits-details-dialog.component.ts | 3 +- .../rate-limits/rate-limits-list.component.ts | 31 +- .../rate-limits/rate-limits-text.component.ts | 7 +- .../rate-limits/rate-limits.component.ts | 31 +- .../tenant-profile-configuration.component.ts | 17 +- .../components/queue/queue-form.component.ts | 31 +- .../relation/relation-dialog.component.ts | 9 +- .../relation/relation-filters.component.ts | 21 +- .../relation/relation-table.component.ts | 9 +- .../resources/resources-dialog.component.ts | 9 +- .../resources/resources-library.component.ts | 5 +- .../home/components/router-tabs.component.ts | 7 +- .../rule-chain-autocomplete.component.ts | 17 +- ...vanced-processing-setting-row.component.ts | 23 +- .../advanced-processing-setting.component.ts | 23 +- .../assign-customer-config.component.ts | 7 +- .../action/attributes-config.component.ts | 7 +- .../action/clear-alarm-config.component.ts | 7 +- .../action/create-alarm-config.component.ts | 7 +- .../create-relation-config.component.ts | 7 +- .../delete-attributes-config.component.ts | 7 +- .../delete-relation-config.component.ts | 7 +- .../action/device-profile-config.component.ts | 7 +- .../action/device-state-config.component.ts | 3 +- .../action/generator-config.component.ts | 7 +- .../action/gps-geo-action-config.component.ts | 7 +- .../rule-node/action/log-config.component.ts | 7 +- .../action/math-function-config.component.ts | 7 +- .../action/msg-count-config.component.ts | 7 +- .../action/msg-delay-config.component.ts | 7 +- .../action/push-to-cloud-config.component.ts | 7 +- .../action/push-to-edge-config.component.ts | 7 +- .../action/rpc-reply-config.component.ts | 7 +- .../action/rpc-request-config.component.ts | 7 +- .../save-to-custom-table-config.component.ts | 7 +- ...nd-rest-api-call-reply-config.component.ts | 7 +- .../action/timeseries-config.component.ts | 7 +- .../unassign-customer-config.component.ts | 7 +- .../common/alarm-status-select.component.ts | 17 +- .../common/arguments-map-config.component.ts | 31 +- .../common/credentials-config.component.ts | 31 +- ...device-relations-query-config.component.ts | 21 +- .../common/example-hint.component.ts | 7 +- .../common/kv-map-config-old.component.ts | 31 +- .../common/kv-map-config.component.ts | 31 +- .../math-function-autocomplete.component.ts | 21 +- .../common/message-types-config.component.ts | 21 +- .../common/msg-metadata-chip.component.ts | 15 +- ...put-message-type-autocomplete.component.ts | 31 +- .../relations-query-config-old.component.ts | 21 +- .../relations-query-config.component.ts | 19 +- .../common/select-attributes.component.ts | 25 +- .../common/sv-map-config.component.ts | 31 +- .../common/time-unit-input.component.ts | 23 +- .../rule-node/empty-config.component.ts | 7 +- .../calculate-delta-config.component.ts | 5 +- .../customer-attributes-config.component.ts | 7 +- .../device-attributes-config.component.ts | 7 +- .../entity-details-config.component.ts | 7 +- ...tch-device-credentials-config.component.ts | 5 +- ...elemetry-from-database-config.component.ts | 7 +- .../originator-attributes-config.component.ts | 7 +- .../originator-fields-config.component.ts | 5 +- .../related-attributes-config.component.ts | 7 +- .../tenant-attributes-config.component.ts | 7 +- .../rule-node/external/ai-config.component.ts | 7 +- .../azure-iot-hub-config.component.ts | 7 +- .../external/kafka-config.component.ts | 7 +- .../external/lambda-config.component.ts | 7 +- .../external/mqtt-config.component.ts | 7 +- .../external/notification-config.component.ts | 7 +- .../external/pubsub-config.component.ts | 7 +- .../external/rabbit-mq-config.component.ts | 7 +- .../rest-api-call-config.component.ts | 7 +- .../external/send-email-config.component.ts | 7 +- .../external/send-sms-config.component.ts | 7 +- .../external/slack-config.component.ts | 7 +- .../external/sns-config.component.ts | 7 +- .../external/sqs-config.component.ts | 7 +- .../filter/check-alarm-status.component.ts | 7 +- .../filter/check-message-config.component.ts | 7 +- .../filter/check-relation-config.component.ts | 7 +- .../filter/gps-geo-filter-config.component.ts | 7 +- .../filter/message-type-config.component.ts | 7 +- .../originator-type-config.component.ts | 7 +- .../filter/script-config.component.ts | 7 +- .../filter/switch-config.component.ts | 7 +- .../flow/rule-chain-input.component.ts | 7 +- .../flow/rule-chain-output.component.ts | 7 +- .../change-originator-config.component.ts | 5 +- .../copy-keys-config.component.ts | 7 +- .../deduplication-config.component.ts | 7 +- .../delete-keys-config.component.ts | 7 +- .../node-json-path-config.component.ts | 7 +- .../rename-keys-config.component.ts | 7 +- .../transformation/script-config.component.ts | 7 +- .../to-email-config.component.ts | 7 +- ...ws-sns-provider-configuration.component.ts | 17 +- ...pp-sms-provider-configuration.component.ts | 17 +- .../sms-provider-configuration.component.ts | 17 +- ...io-sms-provider-configuration.component.ts | 17 +- .../vc/auto-commit-settings.component.ts | 7 +- .../vc/complex-version-create.component.ts | 7 +- .../vc/complex-version-load.component.ts | 7 +- .../entity-types-version-create.component.ts | 31 +- .../vc/entity-types-version-load.component.ts | 31 +- .../vc/entity-version-create.component.ts | 7 +- .../vc/entity-version-diff.component.ts | 9 +- .../vc/entity-version-restore.component.ts | 7 +- .../vc/entity-versions-table.component.ts | 7 +- ...remove-other-entities-confirm.component.ts | 7 +- .../vc/repository-settings.component.ts | 7 +- .../vc/version-control.component.ts | 7 +- .../manage-widget-actions-dialog.component.ts | 9 +- .../action/manage-widget-actions.component.ts | 21 +- .../action/widget-action-dialog.component.ts | 9 +- .../alarm-count-basic-config.component.ts | 7 +- .../alarms-table-basic-config.component.ts | 7 +- .../action-button-basic-config.component.ts | 7 +- .../command-button-basic-config.component.ts | 7 +- .../power-button-basic-config.component.ts | 7 +- ...segmented-button-basic-config.component.ts | 7 +- .../toggle-button-basic-config.component.ts | 7 +- .../aggregated-data-key-row.component.ts | 23 +- .../aggregated-data-keys-panel.component.ts | 23 +- ...gated-value-card-basic-config.component.ts | 7 +- .../label-card-basic-config.component.ts | 7 +- ...label-value-card-basic-config.component.ts | 7 +- ...bile-app-qr-code-basic-config.component.ts | 7 +- .../progress-bar-basic-config.component.ts | 7 +- .../simple-card-basic-config.component.ts | 7 +- ...timeseries-table-basic-config.component.ts | 7 +- ...ead-notification-basic-config.component.ts | 7 +- .../value-card-basic-config.component.ts | 7 +- ...value-chart-card-basic-config.component.ts | 7 +- .../chart/bar-chart-basic-config.component.ts | 7 +- ...hart-with-labels-basic-config.component.ts | 7 +- .../chart/comparison-key-row.component.ts | 23 +- .../chart/comparison-keys-table.component.ts | 23 +- .../chart/doughnut-basic-config.component.ts | 7 +- .../chart/flot-basic-config.component.ts | 7 +- .../chart/pie-chart-basic-config.component.ts | 7 +- ...polar-area-chart-basic-config.component.ts | 7 +- .../radar-chart-basic-config.component.ts | 7 +- .../range-chart-basic-config.component.ts | 7 +- ...ime-series-chart-basic-config.component.ts | 7 +- .../basic/common/data-key-row.component.ts | 23 +- .../basic/common/data-keys-panel.component.ts | 33 +- .../common/widget-actions-panel.component.ts | 21 +- .../entities-table-basic-config.component.ts | 7 +- .../entity-count-basic-config.component.ts | 7 +- .../compass-gauge-basic-config.component.ts | 7 +- ...tal-simple-gauge-basic-config.component.ts | 7 +- .../radial-gauge-basic-config.component.ts | 7 +- ...eter-scale-gauge-basic-config.component.ts | 7 +- .../battery-level-basic-config.component.ts | 7 +- ...iquid-level-card-basic-config.component.ts | 7 +- .../signal-strength-basic-config.component.ts | 7 +- .../status-widget-basic-config.component.ts | 7 +- .../basic/map/map-basic-config.component.ts | 7 +- .../single-switch-basic-config.component.ts | 7 +- .../rpc/slider-basic-config.component.ts | 7 +- .../value-stepper-basic-config.component.ts | 7 +- .../scada-symbol-basic-config.component.ts | 7 +- ...-speed-direction-basic-config.component.ts | 7 +- .../widget/config/datasource.component.ts | 31 +- .../widget/config/datasources.component.ts | 31 +- .../widget/config/target-device.component.ts | 31 +- .../timewindow-config-panel.component.ts | 21 +- .../timewindow-style-panel.component.ts | 11 +- .../config/timewindow-style.component.ts | 21 +- .../custom-dialog-container.component.ts | 5 +- .../embed-dashboard-dialog.component.ts | 7 +- .../alarm/alarms-table-widget.component.ts | 7 +- .../button/action-button-widget.component.ts | 9 +- .../button/command-button-widget.component.ts | 9 +- .../button/toggle-button-widget.component.ts | 9 +- .../two-segment-button-widget.component.ts | 9 +- .../aggregated-value-card-widget.component.ts | 7 +- .../lib/cards/label-card-widget.component.ts | 9 +- .../label-value-card-widget.component.ts | 9 +- ...otification-type-filter-panel.component.ts | 7 +- .../cards/progress-bar-widget.component.ts | 9 +- .../unread-notification-widget.component.ts | 9 +- .../lib/cards/value-card-widget.component.ts | 7 +- .../value-chart-card-widget.component.ts | 9 +- .../lib/chart/bar-chart-widget.component.ts | 9 +- .../bar-chart-with-labels-widget.component.ts | 9 +- .../lib/chart/doughnut-widget.component.ts | 9 +- .../lib/chart/latest-chart.component.ts | 9 +- .../lib/chart/pie-chart-widget.component.ts | 9 +- .../lib/chart/polar-area-widget.component.ts | 9 +- .../lib/chart/radar-chart-widget.component.ts | 9 +- .../lib/chart/range-chart-widget.component.ts | 9 +- .../time-series-chart-widget.component.ts | 9 +- .../lib/count/count-widget.component.ts | 7 +- .../date-range-navigator.component.ts | 16 +- .../lib/display-columns-panel.component.ts | 7 +- .../lib/edges-overview-widget.component.ts | 7 +- .../entities-hierarchy-widget.component.ts | 7 +- .../entity/entities-table-widget.component.ts | 7 +- .../widget/lib/flot-widget.component.ts | 7 +- .../add-doc-link-dialog.component.ts | 7 +- .../add-quick-link-dialog.component.ts | 7 +- .../home-page/cluster-info-table.component.ts | 7 +- .../configured-features.component.ts | 7 +- .../lib/home-page/doc-link.component.ts | 23 +- .../home-page/doc-links-widget.component.ts | 7 +- .../home-page/edit-links-dialog.component.ts | 7 +- ...ting-started-completed-dialog.component.ts | 9 +- .../getting-started-widget.component.ts | 7 +- .../lib/home-page/quick-link.component.ts | 23 +- .../home-page/quick-links-widget.component.ts | 7 +- .../recent-dashboards-widget.component.ts | 7 +- .../home-page/usage-info-widget.component.ts | 7 +- .../lib/home-page/version-info.component.ts | 7 +- .../battery-level-widget.component.ts | 9 +- .../liquid-level-widget.component.ts | 9 +- .../signal-strength-widget.component.ts | 9 +- .../lib/indicator/status-widget.component.ts | 9 +- .../widget/lib/json-input-widget.component.ts | 7 +- .../components/widget/lib/legend.component.ts | 7 +- .../dialogs/select-entity-dialog.component.ts | 7 +- .../widget/lib/maps/map-widget.component.ts | 9 +- .../panels/map-timeline-panel.component.ts | 9 +- .../select-map-entity-panel.component.ts | 11 +- .../widget/lib/markdown-widget.component.ts | 5 +- .../lib/mobile-app-qrcode-widget.component.ts | 7 +- .../lib/multiple-input-widget.component.ts | 7 +- .../lib/navigation-card-widget.component.ts | 7 +- .../lib/navigation-cards-widget.component.ts | 7 +- .../lib/photo-camera-input.component.ts | 9 +- .../widget/lib/qrcode-widget.component.ts | 7 +- .../widget/lib/rpc/knob.component.ts | 7 +- .../widget/lib/rpc/led-indicator.component.ts | 7 +- .../rpc/persistent-add-dialog.component.ts | 7 +- .../persistent-details-dialog.component.ts | 7 +- .../rpc/persistent-filter-panel.component.ts | 7 +- .../lib/rpc/persistent-table.component.ts | 7 +- .../lib/rpc/power-button-widget.component.ts | 9 +- .../widget/lib/rpc/round-switch.component.ts | 7 +- .../lib/rpc/single-switch-widget.component.ts | 9 +- .../widget/lib/rpc/slider-widget.component.ts | 9 +- .../widget/lib/rpc/switch.component.ts | 7 +- .../lib/rpc/value-stepper-widget.component.ts | 9 +- .../scada/scada-symbol-widget.component.ts | 9 +- .../alarm-count-widget-settings.component.ts | 7 +- .../alarms-table-key-settings.component.ts | 7 +- .../alarms-table-widget-settings.component.ts | 7 +- ...action-button-widget-settings.component.ts | 7 +- ...ommand-button-widget-settings.component.ts | 7 +- .../power-button-widget-settings.component.ts | 7 +- ...mented-button-widget-settings.component.ts | 7 +- ...toggle-button-widget-settings.component.ts | 7 +- ...gated-value-card-key-settings.component.ts | 7 +- ...ed-value-card-widget-settings.component.ts | 7 +- ...shboard-state-widget-settings.component.ts | 7 +- ...uick-overview-widget-settings.component.ts | 7 +- .../html-card-widget-settings.component.ts | 7 +- .../label-card-widget-settings.component.ts | 7 +- ...el-value-card-widget-settings.component.ts | 7 +- .../cards/label-widget-label.component.ts | 21 +- .../cards/label-widget-settings.component.ts | 7 +- .../markdown-widget-settings.component.ts | 7 +- ...e-app-qr-code-widget-settings.component.ts | 7 +- .../progress-bar-widget-settings.component.ts | 7 +- .../cards/qrcode-widget-settings.component.ts | 7 +- .../simple-card-widget-settings.component.ts | 7 +- ...timeseries-table-key-settings.component.ts | 7 +- ...ies-table-latest-key-settings.component.ts | 7 +- ...eseries-table-widget-settings.component.ts | 7 +- ...-notification-widget-settings.component.ts | 7 +- .../value-card-widget-settings.component.ts | 7 +- ...ue-chart-card-widget-settings.component.ts | 7 +- .../bar-chart-widget-settings.component.ts | 7 +- ...t-with-labels-widget-settings.component.ts | 7 +- .../chart/chart-widget-settings.component.ts | 7 +- ...oughnut-chart-widget-settings.component.ts | 7 +- .../doughnut-widget-settings.component.ts | 7 +- .../chart/flot-bar-key-settings.component.ts | 7 +- .../flot-bar-widget-settings.component.ts | 7 +- .../chart/flot-key-settings.component.ts | 31 +- .../flot-latest-key-settings.component.ts | 7 +- .../chart/flot-line-key-settings.component.ts | 7 +- .../flot-line-widget-settings.component.ts | 7 +- .../chart/flot-pie-key-settings.component.ts | 7 +- .../flot-pie-widget-settings.component.ts | 7 +- .../chart/flot-threshold.component.ts | 23 +- .../chart/flot-widget-settings.component.ts | 31 +- .../chart/label-data-key.component.ts | 21 +- .../pie-chart-widget-settings.component.ts | 7 +- ...ar-area-chart-widget-settings.component.ts | 7 +- .../radar-chart-widget-settings.component.ts | 7 +- .../range-chart-widget-settings.component.ts | 7 +- ...ime-series-chart-key-settings.component.ts | 7 +- ...me-series-chart-line-settings.component.ts | 21 +- ...-series-chart-widget-settings.component.ts | 7 +- .../custom-action-pretty-editor.component.ts | 23 +- ...-action-pretty-resources-tabs.component.ts | 9 +- ...t-value-action-settings-panel.component.ts | 11 +- .../get-value-action-settings.component.ts | 23 +- .../action/map-item-tooltips.component.ts | 19 +- .../action/mobile-action-editor.component.ts | 17 +- ...t-value-action-settings-panel.component.ts | 11 +- .../set-value-action-settings.component.ts | 23 +- .../widget-action-settings-panel.component.ts | 11 +- .../widget-action-settings.component.ts | 23 +- .../common/action/widget-action.component.ts | 31 +- .../common/advanced-range.component.ts | 21 +- .../alias/entity-alias-select.component.ts | 17 +- ...to-date-format-settings-panel.component.ts | 11 +- .../auto-date-format-settings.component.ts | 21 +- .../background-settings-panel.component.ts | 11 +- .../common/background-settings.component.ts | 23 +- .../widget-button-appearance.component.ts | 23 +- ...get-button-custom-style-panel.component.ts | 11 +- .../widget-button-custom-style.component.ts | 23 +- ...ton-toggle-custom-style-panel.component.ts | 11 +- ...et-button-toggle-custom-style.component.ts | 23 +- .../chart-animation-settings.component.ts | 21 +- .../chart/chart-bar-settings.component.ts | 21 +- .../chart/chart-fill-settings.component.ts | 21 +- ...es-chart-axis-settings-button.component.ts | 21 +- ...ies-chart-axis-settings-panel.component.ts | 11 +- ...me-series-chart-axis-settings.component.ts | 21 +- ...me-series-chart-grid-settings.component.ts | 21 +- .../time-series-chart-state-row.component.ts | 23 +- ...ime-series-chart-states-panel.component.ts | 33 +- ...me-series-chart-threshold-row.component.ts | 23 +- ...hart-threshold-settings-panel.component.ts | 11 +- ...ries-chart-threshold-settings.component.ts | 21 +- ...series-chart-thresholds-panel.component.ts | 33 +- ...ime-series-chart-y-axes-panel.component.ts | 33 +- .../time-series-chart-y-axis-row.component.ts | 23 +- ...ggregation-bar-width-settings.component.ts | 21 +- .../common/color-range-list.component.ts | 23 +- .../common/color-range-panel.component.ts | 11 +- .../common/color-range-settings.component.ts | 21 +- .../common/color-settings-panel.component.ts | 11 +- .../common/color-settings.component.ts | 21 +- .../common/count-widget-settings.component.ts | 21 +- .../common/css-size-input.component.ts | 31 +- .../common/css-unit-select.component.ts | 21 +- .../common/date-format-select.component.ts | 21 +- .../date-format-settings-panel.component.ts | 11 +- .../dynamic-form-array.component.ts | 33 +- .../dynamic-form-properties.component.ts | 33 +- .../dynamic-form-property-panel.component.ts | 9 +- .../dynamic-form-property-row.component.ts | 33 +- .../dynamic-form-select-item-row.component.ts | 33 +- .../dynamic-form-select-items.component.ts | 33 +- .../dynamic-form/dynamic-form.component.ts | 31 +- .../common/entity-alias-input.component.ts | 23 +- .../common/filter/filter-select.component.ts | 25 +- .../common/font-settings-panel.component.ts | 11 +- .../common/font-settings.component.ts | 21 +- .../lib/settings/common/gradient.component.ts | 21 +- .../common/image-cards-select.component.ts | 26 +- .../status-widget-state-settings.component.ts | 21 +- .../key/data-key-config-dialog.component.ts | 9 +- .../common/key/data-key-config.component.ts | 31 +- .../common/key/data-key-input.component.ts | 23 +- .../common/key/data-keys.component.ts | 41 +- .../common/legend-config.component.ts | 21 +- ...dditional-map-data-source-row.component.ts | 23 +- .../additional-map-data-sources.component.ts | 33 +- ...ta-layer-color-settings-panel.component.ts | 11 +- .../data-layer-color-settings.component.ts | 21 +- .../data-layer-pattern-settings.component.ts | 31 +- .../image-map-source-settings.component.ts | 31 +- .../map/map-action-button-row.component.ts | 25 +- .../map-action-buttons-settings.component.ts | 25 +- .../map/map-data-layer-dialog.component.ts | 9 +- .../map/map-data-layer-row.component.ts | 23 +- .../common/map/map-data-layers.component.ts | 33 +- .../map/map-data-source-row.component.ts | 23 +- .../common/map/map-data-sources.component.ts | 33 +- .../common/map/map-layer-row.component.ts | 23 +- .../map/map-layer-settings-panel.component.ts | 11 +- .../common/map/map-layers.component.ts | 33 +- .../common/map/map-settings.component.ts | 31 +- .../map/map-tooltip-tag-actions.component.ts | 23 +- .../marker-clustering-settings.component.ts | 31 +- .../map/marker-icon-shapes.component.ts | 11 +- .../marker-image-settings-panel.component.ts | 11 +- .../map/marker-image-settings.component.ts | 21 +- .../map/marker-shape-settings.component.ts | 21 +- .../common/map/marker-shapes.component.ts | 11 +- ...ape-fill-image-settings-panel.component.ts | 11 +- .../shape-fill-image-settings.component.ts | 21 +- ...pe-fill-stripe-settings-panel.component.ts | 11 +- .../shape-fill-stripe-settings.component.ts | 21 +- .../map/trip-timeline-settings.component.ts | 31 +- .../scada-symbol-object-settings.component.ts | 31 +- .../common/value-source-data-key.component.ts | 21 +- .../settings/common/value-source.component.ts | 21 +- .../settings/common/widget-font.component.ts | 21 +- .../widget/widget-settings.component.ts | 27 +- .../device-key-autocomplete.component.ts | 21 +- .../knob-control-widget-settings.component.ts | 7 +- ...led-indicator-widget-settings.component.ts | 7 +- ...sistent-table-widget-settings.component.ts | 7 +- .../round-switch-widget-settings.component.ts | 7 +- .../control/rpc-button-style.component.ts | 21 +- .../rpc-shell-widget-settings.component.ts | 7 +- .../rpc-terminal-widget-settings.component.ts | 7 +- .../send-rpc-widget-settings.component.ts | 7 +- ...single-switch-widget-settings.component.ts | 7 +- .../slide-toggle-widget-settings.component.ts | 7 +- .../slider-widget-settings.component.ts | 7 +- ...witch-control-widget-settings.component.ts | 7 +- .../control/switch-rpc-settings.component.ts | 31 +- ...ice-attribute-widget-settings.component.ts | 7 +- ...value-stepper-widget-settings.component.ts | 7 +- ...nge-navigator-widget-settings.component.ts | 7 +- ...ies-hierarchy-widget-settings.component.ts | 7 +- .../entities-table-key-settings.component.ts | 7 +- ...ntities-table-widget-settings.component.ts | 7 +- .../entity-count-widget-settings.component.ts | 7 +- ...single-device-widget-settings.component.ts | 7 +- ...ateway-config-widget-settings.component.ts | 7 +- ...ateway-events-widget-settings.component.ts | 7 +- .../gateway-logs-settings.component.ts | 7 +- .../gateway-service-rpc-settings.component.ts | 7 +- ...logue-compass-widget-settings.component.ts | 7 +- ...-linear-gauge-widget-settings.component.ts | 7 +- ...-radial-gauge-widget-settings.component.ts | 7 +- ...digital-gauge-widget-settings.component.ts | 7 +- .../settings/gauge/tick-value.component.ts | 21 +- .../gpio-control-widget-settings.component.ts | 7 +- .../lib/settings/gpio/gpio-item.component.ts | 21 +- .../gpio-panel-widget-settings.component.ts | 7 +- .../doc-links-widget-settings.component.ts | 7 +- .../quick-links-widget-settings.component.ts | 7 +- ...battery-level-widget-settings.component.ts | 7 +- ...id-level-card-widget-settings.component.ts | 7 +- ...gnal-strength-widget-settings.component.ts | 7 +- .../status-widget-settings.component.ts | 7 +- .../input/datakey-select-option.component.ts | 21 +- ...vice-claiming-widget-settings.component.ts | 7 +- ...-camera-input-widget-settings.component.ts | 7 +- ...te-attribute-general-settings.component.ts | 31 +- ...ean-attribute-widget-settings.component.ts | 7 +- ...ate-attribute-widget-settings.component.ts | 7 +- ...ble-attribute-widget-settings.component.ts | 7 +- ...age-attribute-widget-settings.component.ts | 7 +- ...ger-attribute-widget-settings.component.ts | 7 +- ...son-attribute-widget-settings.component.ts | 7 +- ...ion-attribute-widget-settings.component.ts | 7 +- ...tiple-attributes-key-settings.component.ts | 7 +- ...le-attributes-widget-settings.component.ts | 7 +- ...ing-attribute-widget-settings.component.ts | 7 +- .../map/legacy/circle-settings.component.ts | 31 +- .../legacy/common-map-settings.component.ts | 31 +- .../datasources-key-autocomplete.component.ts | 21 +- .../google-map-provider-settings.component.ts | 31 +- .../here-map-provider-settings.component.ts | 31 +- .../image-map-provider-settings.component.ts | 31 +- .../legacy/map-editor-settings.component.ts | 31 +- .../legacy/map-provider-settings.component.ts | 31 +- .../legacy/map-settings-legacy.component.ts | 31 +- .../map-widget-settings-legacy.component.ts | 7 +- .../marker-clustering-settings.component.ts | 31 +- .../map/legacy/markers-settings.component.ts | 31 +- ...nstreet-map-provider-settings.component.ts | 31 +- .../map/legacy/polygon-settings.component.ts | 31 +- .../legacy/route-map-settings.component.ts | 31 +- .../route-map-widget-settings.component.ts | 7 +- ...tencent-map-provider-settings.component.ts | 31 +- ...rip-animation-common-settings.component.ts | 31 +- ...rip-animation-marker-settings.component.ts | 31 +- .../trip-animation-path-settings.component.ts | 31 +- ...trip-animation-point-settings.component.ts | 31 +- ...rip-animation-widget-settings.component.ts | 7 +- .../map/map-widget-settings.component.ts | 7 +- ...vigation-card-widget-settings.component.ts | 7 +- ...igation-cards-widget-settings.component.ts | 7 +- .../scada-symbol-widget-settings.component.ts | 7 +- ...eed-direction-widget-settings.component.ts | 7 +- .../lib/timeseries-table-widget.component.ts | 7 +- .../trip-animation.component.ts | 9 +- .../wind-speed-direction-widget.component.ts | 9 +- .../widget/widget-config.component.ts | 31 +- .../widget/widget-container.component.ts | 18 +- .../widget/widget-preview.component.ts | 7 +- .../components/widget/widget.component.ts | 11 +- .../wizard/device-wizard-dialog.component.ts | 7 +- ...d-entities-to-customer-dialog.component.ts | 9 +- .../add-entities-to-edge-dialog.component.ts | 9 +- .../assign-to-customer-dialog.component.ts | 9 +- ui-ngx/src/app/modules/home/home.component.ts | 7 +- .../modules/home/menu/menu-link.component.ts | 9 +- .../home/menu/menu-toggle.component.ts | 9 +- .../modules/home/menu/side-menu.component.ts | 9 +- .../auto-commit-admin-settings.component.ts | 7 +- .../pages/admin/general-settings.component.ts | 7 +- .../pages/admin/home-settings.component.ts | 7 +- .../home/pages/admin/mail-server.component.ts | 7 +- .../oauth2/clients/client-dialog.component.ts | 9 +- .../clients/client-table-header.component.ts | 7 +- .../admin/oauth2/clients/client.component.ts | 7 +- .../domains/domain-table-header.component.ts | 7 +- .../admin/oauth2/domains/domain.component.ts | 7 +- .../home/pages/admin/queue/queue.component.ts | 7 +- .../repository-admin-settings.component.ts | 7 +- .../js-library-table-header.component.ts | 7 +- .../admin/resource/js-resource.component.ts | 5 +- .../resource-library-tabs.component.ts | 7 +- .../admin/resource/resource-tabs.component.ts | 7 +- .../resources-table-header.component.ts | 7 +- .../admin/security-settings.component.ts | 7 +- .../admin/send-test-sms-dialog.component.ts | 7 +- .../pages/admin/sms-provider.component.ts | 7 +- .../pages/admin/trendz-settings.component.ts | 7 +- .../two-factor-auth-settings.component.ts | 7 +- .../ai-model-table-header.component.ts | 9 +- .../asset-profile-tabs.component.ts | 7 +- .../asset/asset-table-header.component.ts | 7 +- .../home/pages/asset/asset-tabs.component.ts | 7 +- .../home/pages/asset/asset.component.ts | 7 +- .../pages/customer/customer-tabs.component.ts | 7 +- .../home/pages/customer/customer.component.ts | 7 +- .../dashboard/dashboard-form.component.ts | 7 +- .../dashboard/dashboard-tabs.component.ts | 7 +- .../make-dashboard-public-dialog.component.ts | 7 +- ...ge-dashboard-customers-dialog.component.ts | 9 +- .../device-profile-tabs.component.ts | 7 +- ...evice-transport-configuration.component.ts | 17 +- .../default-device-configuration.component.ts | 17 +- ...evice-transport-configuration.component.ts | 17 +- .../data/device-configuration.component.ts | 17 +- .../device/data/device-data.component.ts | 31 +- ...evice-transport-configuration.component.ts | 30 +- ...evice-transport-configuration.component.ts | 17 +- ...evice-transport-configuration.component.ts | 17 +- ...evice-transport-configuration.component.ts | 28 +- ...ice-check-connectivity-dialog.component.ts | 7 +- .../device-credentials-dialog.component.ts | 9 +- .../device/device-table-header.component.ts | 7 +- .../pages/device/device-tabs.component.ts | 7 +- .../home/pages/device/device.component.ts | 7 +- .../edge-instructions-dialog.component.ts | 7 +- .../pages/edge/edge-table-header.component.ts | 7 +- .../home/pages/edge/edge-tabs.component.ts | 7 +- .../modules/home/pages/edge/edge.component.ts | 7 +- .../entity-view-table-header.component.ts | 7 +- .../entity-view/entity-view-tabs.component.ts | 7 +- .../entity-view/entity-view.component.ts | 7 +- .../pages/home-links/home-links.component.ts | 9 +- .../mobile-app-dialog.component.ts | 9 +- .../mobile-app-table-header.component.ts | 7 +- .../applications/mobile-app.component.ts | 7 +- .../remove-app-dialog.component.ts | 7 +- .../add-mobile-page-dialog.component.ts | 7 +- .../custom-mobile-page-panel.component.ts | 9 +- .../layout/custom-mobile-page.component.ts | 31 +- .../default-mobile-page-panel.component.ts | 9 +- .../bundes/layout/mobile-layout.component.ts | 31 +- .../layout/mobile-page-item-row.component.ts | 33 +- ...bile-app-configuration-dialog.component.ts | 7 +- .../bundes/mobile-bundle-dialog.component.ts | 7 +- .../mobile-bundle-table-header.component.ts | 7 +- .../mobile/common/editor-panel.component.ts | 9 +- ...obile-qr-code-widget-settings.component.ts | 7 +- .../inbox-notification-dialog.component.ts | 7 +- .../inbox/inbox-table-header.component.ts | 7 +- ...recipient-notification-dialog.component.ts | 7 +- .../rule/escalation-form.component.ts | 31 +- .../rule/escalations.component.ts | 31 +- .../rule-notification-dialog.component.ts | 7 +- .../sent/sent-error-dialog.component.ts | 7 +- .../sent/sent-notification-dialog.componet.ts | 7 +- .../notification-setting-form.component.ts | 21 +- .../notification-settings.component.ts | 7 +- ...n-action-button-configuration.component.ts | 29 +- ...cation-template-configuration.component.ts | 31 +- .../template-notification-dialog.component.ts | 7 +- .../ota-update/ota-update-tabs.component.ts | 7 +- .../pages/ota-update/ota-update.component.ts | 5 +- .../home/pages/profile/profile.component.ts | 7 +- .../pages/rulechain/link-labels.component.ts | 17 +- .../rulechain/rule-node-config.component.ts | 19 +- .../rulechain/rule-node-details.component.ts | 7 +- .../rulechain/rule-node-link.component.ts | 17 +- .../rulechain/rulechain-page.component.ts | 36 +- .../rulechain/rulechain-tabs.component.ts | 7 +- .../pages/rulechain/rulechain.component.ts | 7 +- .../pages/rulechain/rulenode.component.ts | 9 +- .../scada-symbol-behavior-panel.component.ts | 9 +- .../scada-symbol-behavior-row.component.ts | 33 +- .../scada-symbol-behaviors.component.ts | 33 +- ...l-metadata-tag-function-panel.component.ts | 9 +- .../scada-symbol-metadata-tag.component.ts | 33 +- .../scada-symbol-metadata-tags.component.ts | 33 +- .../scada-symbol-metadata.component.ts | 33 +- .../scada-symbol-editor.component.ts | 9 +- .../scada-symbol-tooltip.components.ts | 35 +- .../scada-symbol/scada-symbol.component.ts | 9 +- .../backup-code-auth-dialog.component.ts | 7 +- .../email-auth-dialog.component.ts | 7 +- .../sms-auth-dialog.component.ts | 7 +- .../totp-auth-dialog.component.ts | 7 +- .../home/pages/security/security.component.ts | 7 +- .../tenant-profile-tabs.component.ts | 7 +- .../pages/tenant/tenant-tabs.component.ts | 7 +- .../home/pages/tenant/tenant.component.ts | 7 +- .../user/activation-link-dialog.component.ts | 5 +- .../pages/user/add-user-dialog.component.ts | 7 +- .../home/pages/user/user-tabs.component.ts | 7 +- .../modules/home/pages/user/user.component.ts | 7 +- .../save-widget-type-as-dialog.component.ts | 7 +- .../select-widget-type-dialog.component.ts | 7 +- .../pages/widget/widget-editor.component.ts | 9 +- .../widget-type-autocomplete.component.ts | 19 +- .../widget/widget-type-tabs.component.ts | 7 +- .../pages/widget/widget-type.component.ts | 7 +- .../widget/widgets-bundle-dialog.component.ts | 9 +- .../widget/widgets-bundle-tabs.component.ts | 7 +- .../widgets-bundle-widgets.component.ts | 7 +- .../pages/widget/widgets-bundle.component.ts | 7 +- .../pages/login/create-password.component.ts | 7 +- .../pages/login/link-expired.component.ts | 7 +- .../login/pages/login/login.component.ts | 7 +- .../login/reset-password-request.component.ts | 7 +- .../pages/login/reset-password.component.ts | 7 +- .../login/two-factor-auth-login.component.ts | 7 +- .../shared/components/breadcrumb.component.ts | 9 +- .../button/copy-button.component.ts | 7 +- .../button/toggle-password.component.ts | 7 +- .../button/widget-button-toggle.component.ts | 7 +- .../button/widget-button.component.ts | 9 +- .../shared/components/cheatsheet.component.ts | 7 +- .../components/circular-progress.directive.ts | 5 +- .../components/color-input.component.ts | 21 +- .../color-picker-panel.component.ts | 11 +- .../color-picker/color-picker.component.ts | 21 +- .../color-picker/hex-input.component.ts | 9 +- .../shared/components/contact.component.ts | 5 +- .../country-autocomplete.component.ts | 33 +- .../app/shared/components/css.component.ts | 33 +- .../dashboard-autocomplete.component.ts | 17 +- .../dashboard-select-panel.component.ts | 7 +- .../components/dashboard-select.component.ts | 17 +- .../dashboard-state-autocomplete.component.ts | 17 +- .../dialog/alert-dialog.component.ts | 7 +- .../dialog/color-picker-dialog.component.ts | 7 +- .../dialog/confirm-dialog.component.ts | 7 +- .../entity-conflict-dialog.component.ts | 15 +- .../dialog/error-alert-dialog.component.ts | 7 +- .../json-object-edit-dialog.component.ts | 7 +- .../dialog/material-icons-dialog.component.ts | 9 +- .../node-script-test-dialog.component.ts | 11 +- .../dialog/todo-dialog.component.ts | 7 +- .../directives/component-outlet.directive.ts | 7 +- .../sring-template-outlet.directive.ts | 7 +- .../directives/tb-json-to-string.directive.ts | 39 +- .../entity/entity-autocomplete.component.ts | 17 +- .../entity/entity-gateway-select.component.ts | 17 +- .../entity-key-autocomplete.component.ts | 29 +- .../entity/entity-keys-list.component.ts | 21 +- .../entity/entity-list-select.component.ts | 17 +- .../entity/entity-list.component.ts | 31 +- .../entity/entity-select.component.ts | 17 +- .../entity-subtype-autocomplete.component.ts | 17 +- .../entity/entity-subtype-list.component.ts | 21 +- .../entity/entity-subtype-select.component.ts | 17 +- .../entity/entity-type-list.component.ts | 21 +- .../entity/entity-type-select.component.ts | 17 +- .../components/fab-toolbar.component.ts | 21 +- .../shared/components/file-input.component.ts | 21 +- .../footer-fab-buttons.component.ts | 9 +- .../app/shared/components/footer.component.ts | 7 +- .../shared/components/fullscreen.directive.ts | 5 +- .../components/grid/scroll-grid.component.ts | 9 +- .../components/help-markdown.component.ts | 7 +- .../shared/components/help-popup.component.ts | 9 +- .../app/shared/components/help.component.ts | 5 +- .../components/hint-tooltip-icon.component.ts | 7 +- .../shared/components/hotkeys.directive.ts | 5 +- .../app/shared/components/html.component.ts | 33 +- .../app/shared/components/icon.component.ts | 35 +- .../components/image-input.component.ts | 21 +- .../image/embed-image-dialog.component.ts | 7 +- .../image/gallery-image-input.component.ts | 21 +- .../image/image-dialog.component.ts | 7 +- .../image/image-gallery-dialog.component.ts | 7 +- .../image/image-gallery.component.ts | 9 +- .../image/image-references.component.ts | 7 +- .../multiple-gallery-image-input.component.ts | 21 +- .../image/scada-symbol-input.component.ts | 21 +- .../image/upload-image-dialog.component.ts | 9 +- .../js-func-module-row.component.ts | 33 +- .../components/js-func-modules.component.ts | 9 +- .../shared/components/js-func.component.ts | 33 +- .../components/json-content.component.ts | 33 +- .../components/json-object-edit.component.ts | 33 +- .../components/json-object-view.component.ts | 21 +- .../app/shared/components/kv-map.component.ts | 31 +- .../shared/components/led-light.component.ts | 7 +- .../app/shared/components/logo.component.ts | 7 +- .../components/markdown-editor.component.ts | 23 +- .../shared/components/markdown.component.ts | 7 +- .../material-icon-select.component.ts | 21 +- .../components/material-icons.component.ts | 11 +- .../message-type-autocomplete.component.ts | 17 +- .../mqtt-version-select.component.ts | 17 +- .../multiple-image-input.component.ts | 21 +- .../shared/components/nav-tree.component.ts | 9 +- .../notification/notification.component.ts | 7 +- .../template-autocomplete.component.ts | 19 +- .../ota-package-autocomplete.component.ts | 17 +- .../components/phone-input.component.ts | 33 +- .../shared/components/popover.component.ts | 32 +- .../components/protobuf-content.component.ts | 21 +- .../queue/queue-autocomplete.component.ts | 17 +- .../relation-type-autocomplete.component.ts | 17 +- .../resource-autocomplete.component.ts | 17 +- .../resources-in-use-dialog.component.ts | 7 +- .../rule-chain-select-panel.component.ts | 7 +- .../rule-chain/rule-chain-select.component.ts | 17 +- .../components/script-lang.component.ts | 23 +- ...ack-conversation-autocomplete.component.ts | 17 +- .../components/socialshare-panel.component.ts | 7 +- .../string-autocomplete.component.ts | 21 +- .../components/string-items-list.component.ts | 23 +- .../shared/components/svg-xml.component.ts | 33 +- .../shared/components/tb-anchor.component.ts | 5 +- .../components/tb-checkbox.component.ts | 19 +- .../shared/components/tb-error.component.ts | 33 +- ...regation-options-config-panel.component.ts | 7 +- .../aggregation-type-select.component.ts | 17 +- .../grouping-interval-options.component.ts | 21 +- .../time/datapoints-limit.component.ts | 31 +- .../time/datetime-period.component.ts | 21 +- .../components/time/datetime.component.ts | 21 +- .../history-selector.component.ts | 7 +- ...interval-options-config-panel.component.ts | 7 +- .../time/quick-time-interval.component.ts | 21 +- .../components/time/timeinterval.component.ts | 21 +- .../timewindow-config-dialog.component.ts | 7 +- .../time/timewindow-panel.component.ts | 7 +- .../components/time/timewindow.component.ts | 21 +- .../time/timezone-panel.component.ts | 7 +- .../time/timezone-select.component.ts | 17 +- .../components/time/timezone.component.ts | 21 +- .../app/shared/components/toast.directive.ts | 12 +- .../components/toggle-header.component.ts | 10 +- .../components/toggle-select.component.ts | 21 +- .../shared/components/unit-input.component.ts | 23 +- .../unit-settings-panel.component.ts | 11 +- .../shared/components/user-menu.component.ts | 9 +- .../components/value-input.component.ts | 21 +- .../vc/branch-autocomplete.component.ts | 19 +- .../widgets-bundle-search.component.ts | 19 +- .../widgets-bundle-select.component.ts | 19 +- .../directives/context-menu.directive.ts | 3 +- .../truncate-with-tooltip.directive.ts | 11 +- .../export-resource-dialog.component.ts | 7 +- .../import-dialog-csv.component.ts | 9 +- .../import-export/import-dialog.component.ts | 9 +- .../table-columns-assignment.component.ts | 31 +- .../app/shared/pipe/custom-translate.pipe.ts | 3 +- ui-ngx/src/app/shared/pipe/date-ago.pipe.ts | 3 +- .../src/app/shared/pipe/enum-to-array.pipe.ts | 3 +- ui-ngx/src/app/shared/pipe/file-size.pipe.ts | 5 +- ui-ngx/src/app/shared/pipe/highlight.pipe.ts | 5 +- ui-ngx/src/app/shared/pipe/image.pipe.ts | 3 +- .../app/shared/pipe/keyboard-shortcut.pipe.ts | 3 +- .../pipe/milliseconds-to-time-string.pipe.ts | 3 +- ui-ngx/src/app/shared/pipe/nospace.pipe.ts | 3 +- ui-ngx/src/app/shared/pipe/safe.pipe.ts | 3 +- .../shared/pipe/selectable-columns.pipe.ts | 5 +- .../src/app/shared/pipe/short-number.pipe.ts | 3 +- ui-ngx/src/app/shared/pipe/tbJson.pipe.ts | 5 +- ui-ngx/src/app/shared/pipe/truncate.pipe.ts | 5 +- ui-ngx/yarn.lock | 3149 ++++++++++++++--- 926 files changed, 9352 insertions(+), 6269 deletions(-) diff --git a/ui-ngx/package.json b/ui-ngx/package.json index b17c3e1d35..d11f3c4909 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -13,16 +13,16 @@ }, "private": true, "dependencies": { - "@angular/animations": "18.2.13", + "@angular/animations": "19.2.18", "@angular/cdk": "18.2.14", - "@angular/common": "18.2.13", - "@angular/compiler": "18.2.13", - "@angular/core": "18.2.13", - "@angular/forms": "18.2.13", + "@angular/common": "19.2.18", + "@angular/compiler": "19.2.18", + "@angular/core": "19.2.18", + "@angular/forms": "19.2.18", "@angular/material": "18.2.14", - "@angular/platform-browser": "18.2.13", - "@angular/platform-browser-dynamic": "18.2.13", - "@angular/router": "18.2.13", + "@angular/platform-browser": "19.2.18", + "@angular/platform-browser-dynamic": "19.2.18", + "@angular/router": "19.2.18", "@auth0/angular-jwt": "^5.2.0", "@flowjs/flow.js": "^2.14.1", "@flowjs/ngx-flow": "18.0.1", @@ -65,7 +65,7 @@ "leaflet.markercluster": "1.5.3", "libphonenumber-js": "^1.11.15", "maplibre-gl": "^5.2.0", - "marked": "~12.0.2", + "marked": "~15.0.12", "moment": "^2.30.1", "moment-timezone": "^0.5.45", "ngx-clipboard": "^16.0.0", @@ -73,7 +73,7 @@ "ngx-drag-drop": "^18.0.2", "ngx-flowchart": "https://github.com/thingsboard/ngx-flowchart.git#release/3.0.0", "ngx-hm-carousel": "^18.0.0", - "ngx-markdown": "^18.1.0", + "ngx-markdown": "^19.1.1", "ngx-sharebuttons": "^15.0.6", "ngx-translate-messageformat-compiler": "^7.0.0", "objectpath": "^2.0.0", @@ -90,17 +90,17 @@ "tooltipster": "^4.2.8", "tslib": "^2.7.0", "typeface-roboto": "^1.1.13", - "zone.js": "~0.14.10" + "zone.js": "~0.15.1" }, "devDependencies": { "@angular-builders/custom-esbuild": "18.0.0", - "@angular-devkit/build-angular": "18.2.12", - "@angular-devkit/core": "18.2.12", - "@angular-devkit/schematics": "18.2.12", - "@angular/build": "18.2.12", - "@angular/cli": "18.2.12", - "@angular/compiler-cli": "18.2.13", - "@angular/language-service": "18.2.13", + "@angular-devkit/build-angular": "19.2.19", + "@angular-devkit/core": "19.2.19", + "@angular-devkit/schematics": "19.2.19", + "@angular/build": "19.2.19", + "@angular/cli": "19.2.19", + "@angular/compiler-cli": "19.2.18", + "@angular/language-service": "19.2.18", "@types/ace-diff": "^2.1.4", "@types/canvas-gauges": "^2.1.8", "@types/flot": "^0.0.36", diff --git a/ui-ngx/src/app/app.component.ts b/ui-ngx/src/app/app.component.ts index 5bc70240a5..90e01c4c17 100644 --- a/ui-ngx/src/app/app.component.ts +++ b/ui-ngx/src/app/app.component.ts @@ -35,9 +35,10 @@ import { SETTINGS_KEY } from '@core/settings/settings.effects'; import { initCustomJQueryEvents } from '@shared/models/jquery-event.models'; @Component({ - selector: 'tb-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.scss'] + selector: 'tb-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'], + standalone: false }) export class AppComponent { diff --git a/ui-ngx/src/app/modules/home/components/ai-model/ai-model-dialog.component.ts b/ui-ngx/src/app/modules/home/components/ai-model/ai-model-dialog.component.ts index 570e1e7cb4..d5d5f20ed8 100644 --- a/ui-ngx/src/app/modules/home/components/ai-model/ai-model-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/ai-model/ai-model-dialog.component.ts @@ -46,9 +46,10 @@ export interface AIModelDialogData { } @Component({ - selector: 'tb-ai-model-dialog', - templateUrl: './ai-model-dialog.component.html', - styleUrls: ['./ai-model-dialog.component.scss'] + selector: 'tb-ai-model-dialog', + templateUrl: './ai-model-dialog.component.html', + styleUrls: ['./ai-model-dialog.component.scss'], + standalone: false }) export class AIModelDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/components/ai-model/check-connectivity-dialog.component.ts b/ui-ngx/src/app/modules/home/components/ai-model/check-connectivity-dialog.component.ts index f16e85983f..3c48890c2f 100644 --- a/ui-ngx/src/app/modules/home/components/ai-model/check-connectivity-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/ai-model/check-connectivity-dialog.component.ts @@ -28,9 +28,10 @@ export interface AIModelDialogData { } @Component({ - selector: 'tb-check-connectivity-dialog', - templateUrl: './check-connectivity-dialog.component.html', - styleUrls: ['./check-connectivity-dialog.component.scss'] + selector: 'tb-check-connectivity-dialog', + templateUrl: './check-connectivity-dialog.component.html', + styleUrls: ['./check-connectivity-dialog.component.scss'], + standalone: false }) export class CheckConnectivityDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-panel.component.ts b/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-panel.component.ts index 4dedace9cc..ddc46edcb8 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-panel.component.ts @@ -54,9 +54,10 @@ export interface AlarmAssigneePanelData { } @Component({ - selector: 'tb-alarm-assignee-panel', - templateUrl: './alarm-assignee-panel.component.html', - styleUrls: ['./alarm-assignee-panel.component.scss'] + selector: 'tb-alarm-assignee-panel', + templateUrl: './alarm-assignee-panel.component.html', + styleUrls: ['./alarm-assignee-panel.component.scss'], + standalone: false }) export class AlarmAssigneePanelComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-select-panel.component.ts b/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-select-panel.component.ts index 7cba10aa2f..845d3a8089 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-select-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-select-panel.component.ts @@ -47,9 +47,10 @@ export interface AlarmAssigneeSelectPanelData { } @Component({ - selector: 'tb-alarm-assignee-select-panel', - templateUrl: './alarm-assignee-panel.component.html', - styleUrls: ['./alarm-assignee-panel.component.scss'] + selector: 'tb-alarm-assignee-select-panel', + templateUrl: './alarm-assignee-panel.component.html', + styleUrls: ['./alarm-assignee-panel.component.scss'], + standalone: false }) export class AlarmAssigneeSelectPanelComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-select.component.ts b/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-select.component.ts index dd0ebce70b..a97a4a04ac 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-select.component.ts +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-select.component.ts @@ -34,16 +34,17 @@ import { coerceBoolean } from '@shared/decorators/coercion'; import { AlarmAssigneeOption } from '@shared/models/alarm.models'; @Component({ - selector: 'tb-alarm-assignee-select', - templateUrl: './alarm-assignee-select.component.html', - styleUrls: ['./alarm-assignee.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AlarmAssigneeSelectComponent), - multi: true - } - ] + selector: 'tb-alarm-assignee-select', + templateUrl: './alarm-assignee-select.component.html', + styleUrls: ['./alarm-assignee.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AlarmAssigneeSelectComponent), + multi: true + } + ], + standalone: false }) export class AlarmAssigneeSelectComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.ts b/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.ts index 604685d76e..55127e68c5 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.ts +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.ts @@ -28,9 +28,10 @@ import { TranslateService } from '@ngx-translate/core'; import { isNotEmptyStr } from '@core/utils'; @Component({ - selector: 'tb-alarm-assignee', - templateUrl: './alarm-assignee.component.html', - styleUrls: ['./alarm-assignee.component.scss'] + selector: 'tb-alarm-assignee', + templateUrl: './alarm-assignee.component.html', + styleUrls: ['./alarm-assignee.component.scss'], + standalone: false }) export class AlarmAssigneeComponent { @Input() diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-comment-dialog.component.ts b/ui-ngx/src/app/modules/home/components/alarm/alarm-comment-dialog.component.ts index 0584c4d4e4..8c9b751348 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-comment-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-comment-dialog.component.ts @@ -28,9 +28,10 @@ export interface AlarmCommentDialogData { } @Component({ - selector: 'tb-alarm-comment-dialog', - templateUrl: './alarm-comment-dialog.component.html', - styleUrls: [] + selector: 'tb-alarm-comment-dialog', + templateUrl: './alarm-comment-dialog.component.html', + styleUrls: [], + standalone: false }) export class AlarmCommentDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-comment.component.ts b/ui-ngx/src/app/modules/home/components/alarm/alarm-comment.component.ts index 3020d73831..1121b53d3d 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-comment.component.ts +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-comment.component.ts @@ -51,9 +51,10 @@ interface AlarmCommentsDisplayData { } @Component({ - selector: 'tb-alarm-comment', - templateUrl: './alarm-comment.component.html', - styleUrls: ['./alarm-comment.component.scss'] + selector: 'tb-alarm-comment', + templateUrl: './alarm-comment.component.html', + styleUrls: ['./alarm-comment.component.scss'], + standalone: false }) export class AlarmCommentComponent implements OnInit { @Input() diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-details-dialog.component.ts b/ui-ngx/src/app/modules/home/components/alarm/alarm-details-dialog.component.ts index b68d1d983a..67d2b71245 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-details-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-details-dialog.component.ts @@ -47,9 +47,10 @@ export interface AlarmDetailsDialogData { } @Component({ - selector: 'tb-alarm-details-dialog', - templateUrl: './alarm-details-dialog.component.html', - styleUrls: ['./alarm-details-dialog.component.scss'] + selector: 'tb-alarm-details-dialog', + templateUrl: './alarm-details-dialog.component.html', + styleUrls: ['./alarm-details-dialog.component.scss'], + standalone: false }) export class AlarmDetailsDialogComponent extends DialogComponent { 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 0c4344e257..c296f70455 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 @@ -60,16 +60,17 @@ export interface AlarmFilterConfigData { // @dynamic @Component({ - selector: 'tb-alarm-filter-config', - templateUrl: './alarm-filter-config.component.html', - styleUrls: ['./alarm-filter-config.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AlarmFilterConfigComponent), - multi: true - } - ] + selector: 'tb-alarm-filter-config', + templateUrl: './alarm-filter-config.component.html', + styleUrls: ['./alarm-filter-config.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AlarmFilterConfigComponent), + multi: true + } + ], + standalone: false }) export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-table-header.component.ts b/ui-ngx/src/app/modules/home/components/alarm/alarm-table-header.component.ts index c069169e4a..7805498f1c 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-table-header.component.ts +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-table-header.component.ts @@ -23,9 +23,10 @@ import { AlarmTableConfig } from './alarm-table-config'; import { AlarmFilterConfig } from '@shared/models/query/query.models'; @Component({ - selector: 'tb-alarm-table-header', - templateUrl: './alarm-table-header.component.html', - styleUrls: ['./alarm-table-header.component.scss'] + selector: 'tb-alarm-table-header', + templateUrl: './alarm-table-header.component.html', + styleUrls: ['./alarm-table-header.component.scss'], + standalone: false }) export class AlarmTableHeaderComponent extends EntityTableHeaderComponent { diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-table.component.ts b/ui-ngx/src/app/modules/home/components/alarm/alarm-table.component.ts index daa28d0fd9..c0754b3a94 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-table.component.ts @@ -42,9 +42,10 @@ interface AlarmPageQueryParams extends PageQueryParam { } @Component({ - selector: 'tb-alarm-table', - templateUrl: './alarm-table.component.html', - styleUrls: ['./alarm-table.component.scss'] + selector: 'tb-alarm-table', + templateUrl: './alarm-table.component.html', + styleUrls: ['./alarm-table.component.scss'], + standalone: false }) export class AlarmTableComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/alias/aliases-entity-autocomplete.component.ts b/ui-ngx/src/app/modules/home/components/alias/aliases-entity-autocomplete.component.ts index c1f3938853..89bdc9c8cc 100644 --- a/ui-ngx/src/app/modules/home/components/alias/aliases-entity-autocomplete.component.ts +++ b/ui-ngx/src/app/modules/home/components/alias/aliases-entity-autocomplete.component.ts @@ -29,14 +29,15 @@ import { EntityService } from '@core/http/entity.service'; import { isDefinedAndNotNull } from '@core/utils'; @Component({ - selector: 'tb-aliases-entity-autocomplete', - templateUrl: './aliases-entity-autocomplete.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AliasesEntityAutocompleteComponent), - multi: true - }] + selector: 'tb-aliases-entity-autocomplete', + templateUrl: './aliases-entity-autocomplete.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AliasesEntityAutocompleteComponent), + multi: true + }], + standalone: false }) export class AliasesEntityAutocompleteComponent implements ControlValueAccessor, OnInit, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/alias/aliases-entity-select-panel.component.ts b/ui-ngx/src/app/modules/home/components/alias/aliases-entity-select-panel.component.ts index 9d6c84b3ff..89df2ee017 100644 --- a/ui-ngx/src/app/modules/home/components/alias/aliases-entity-select-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/alias/aliases-entity-select-panel.component.ts @@ -26,9 +26,10 @@ export interface AliasesEntitySelectPanelData { } @Component({ - selector: 'tb-aliases-entity-select-panel', - templateUrl: './aliases-entity-select-panel.component.html', - styleUrls: ['./aliases-entity-select-panel.component.scss'] + selector: 'tb-aliases-entity-select-panel', + templateUrl: './aliases-entity-select-panel.component.html', + styleUrls: ['./aliases-entity-select-panel.component.scss'], + standalone: false }) export class AliasesEntitySelectPanelComponent { diff --git a/ui-ngx/src/app/modules/home/components/alias/aliases-entity-select.component.ts b/ui-ngx/src/app/modules/home/components/alias/aliases-entity-select.component.ts index 74f4a8c866..a8e1ddf762 100644 --- a/ui-ngx/src/app/modules/home/components/alias/aliases-entity-select.component.ts +++ b/ui-ngx/src/app/modules/home/components/alias/aliases-entity-select.component.ts @@ -41,9 +41,10 @@ import { deepClone } from '@core/utils'; import { AliasFilterType } from '@shared/models/alias.models'; @Component({ - selector: 'tb-aliases-entity-select', - templateUrl: './aliases-entity-select.component.html', - styleUrls: ['./aliases-entity-select.component.scss'] + selector: 'tb-aliases-entity-select', + templateUrl: './aliases-entity-select.component.html', + styleUrls: ['./aliases-entity-select.component.scss'], + standalone: false }) export class AliasesEntitySelectComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/alias/entity-alias-dialog.component.ts b/ui-ngx/src/app/modules/home/components/alias/entity-alias-dialog.component.ts index 5fc1e4baa1..208aabab3c 100644 --- a/ui-ngx/src/app/modules/home/components/alias/entity-alias-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/alias/entity-alias-dialog.component.ts @@ -46,10 +46,11 @@ export interface EntityAliasDialogData { } @Component({ - selector: 'tb-entity-alias-dialog', - templateUrl: './entity-alias-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: EntityAliasDialogComponent}], - styleUrls: ['./entity-alias-dialog.component.scss'] + selector: 'tb-entity-alias-dialog', + templateUrl: './entity-alias-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: EntityAliasDialogComponent }], + styleUrls: ['./entity-alias-dialog.component.scss'], + standalone: false }) export class EntityAliasDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/alias/entity-aliases-dialog.component.ts b/ui-ngx/src/app/modules/home/components/alias/entity-aliases-dialog.component.ts index a1a430670e..62f325d8ae 100644 --- a/ui-ngx/src/app/modules/home/components/alias/entity-aliases-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/alias/entity-aliases-dialog.component.ts @@ -54,10 +54,11 @@ export interface EntityAliasesDialogData { } @Component({ - selector: 'tb-entity-aliases-dialog', - templateUrl: './entity-aliases-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: EntityAliasesDialogComponent}], - styleUrls: ['./entity-aliases-dialog.component.scss'] + selector: 'tb-entity-aliases-dialog', + templateUrl: './entity-aliases-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: EntityAliasesDialogComponent }], + styleUrls: ['./entity-aliases-dialog.component.scss'], + standalone: false }) export class EntityAliasesDialogComponent extends DialogComponent implements ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/attribute/add-attribute-dialog.component.ts b/ui-ngx/src/app/modules/home/components/attribute/add-attribute-dialog.component.ts index c80f1cacd7..8300e0696c 100644 --- a/ui-ngx/src/app/modules/home/components/attribute/add-attribute-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/attribute/add-attribute-dialog.component.ts @@ -33,10 +33,11 @@ export interface AddAttributeDialogData { } @Component({ - selector: 'tb-add-attribute-dialog', - templateUrl: './add-attribute-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: AddAttributeDialogComponent}], - styleUrls: [] + selector: 'tb-add-attribute-dialog', + templateUrl: './add-attribute-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: AddAttributeDialogComponent }], + styleUrls: [], + standalone: false }) export class AddAttributeDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/attribute/add-widget-to-dashboard-dialog.component.ts b/ui-ngx/src/app/modules/home/components/attribute/add-widget-to-dashboard-dialog.component.ts index 95e51ac915..c03b7a71f2 100644 --- a/ui-ngx/src/app/modules/home/components/attribute/add-widget-to-dashboard-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/attribute/add-widget-to-dashboard-dialog.component.ts @@ -49,10 +49,11 @@ export interface AddWidgetToDashboardDialogData { } @Component({ - selector: 'tb-add-widget-to-dashboard-dialog', - templateUrl: './add-widget-to-dashboard-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: AddWidgetToDashboardDialogComponent}], - styleUrls: ['./add-widget-to-dashboard-dialog.component.scss'] + selector: 'tb-add-widget-to-dashboard-dialog', + templateUrl: './add-widget-to-dashboard-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: AddWidgetToDashboardDialogComponent }], + styleUrls: ['./add-widget-to-dashboard-dialog.component.scss'], + standalone: false }) export class AddWidgetToDashboardDialogComponent extends DialogComponent diff --git a/ui-ngx/src/app/modules/home/components/attribute/attribute-table.component.ts b/ui-ngx/src/app/modules/home/components/attribute/attribute-table.component.ts index a1b954b8ab..55acece392 100644 --- a/ui-ngx/src/app/modules/home/components/attribute/attribute-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/attribute/attribute-table.component.ts @@ -92,10 +92,11 @@ import { FormBuilder } from '@angular/forms'; @Component({ - selector: 'tb-attribute-table', - templateUrl: './attribute-table.component.html', - styleUrls: ['./attribute-table.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-attribute-table', + templateUrl: './attribute-table.component.html', + styleUrls: ['./attribute-table.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: false }) export class AttributeTableComponent extends PageComponent implements AfterViewInit, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/attribute/delete-timeseries-panel.component.ts b/ui-ngx/src/app/modules/home/components/attribute/delete-timeseries-panel.component.ts index 5b24eea5a9..c7d68f04e0 100644 --- a/ui-ngx/src/app/modules/home/components/attribute/delete-timeseries-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/attribute/delete-timeseries-panel.component.ts @@ -36,9 +36,10 @@ export interface DeleteTimeseriesPanelResult { } @Component({ - selector: 'tb-delete-timeseries-panel', - templateUrl: './delete-timeseries-panel.component.html', - styleUrls: ['./delete-timeseries-panel.component.scss'] + selector: 'tb-delete-timeseries-panel', + templateUrl: './delete-timeseries-panel.component.html', + styleUrls: ['./delete-timeseries-panel.component.scss'], + standalone: false }) export class DeleteTimeseriesPanelComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/attribute/edit-attribute-value-panel.component.ts b/ui-ngx/src/app/modules/home/components/attribute/edit-attribute-value-panel.component.ts index 0eca716bb9..dbe63cb2b3 100644 --- a/ui-ngx/src/app/modules/home/components/attribute/edit-attribute-value-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/attribute/edit-attribute-value-panel.component.ts @@ -29,10 +29,11 @@ export interface EditAttributeValuePanelData { } @Component({ - selector: 'tb-edit-attribute-value-panel', - templateUrl: './edit-attribute-value-panel.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: EditAttributeValuePanelComponent}], - styleUrls: ['./edit-attribute-value-panel.component.scss'] + selector: 'tb-edit-attribute-value-panel', + templateUrl: './edit-attribute-value-panel.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: EditAttributeValuePanelComponent }], + styleUrls: ['./edit-attribute-value-panel.component.scss'], + standalone: false }) export class EditAttributeValuePanelComponent extends PageComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.ts b/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.ts index 12305365e0..d430e97e1b 100644 --- a/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.ts @@ -29,9 +29,10 @@ export interface AuditLogDetailsDialogData { } @Component({ - selector: 'tb-audit-log-details-dialog', - templateUrl: './audit-log-details-dialog.component.html', - styleUrls: ['./audit-log-details-dialog.component.scss'] + selector: 'tb-audit-log-details-dialog', + templateUrl: './audit-log-details-dialog.component.html', + styleUrls: ['./audit-log-details-dialog.component.scss'], + standalone: false }) export class AuditLogDetailsDialogComponent extends DialogComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/audit-log/audit-log-table.component.ts b/ui-ngx/src/app/modules/home/components/audit-log/audit-log-table.component.ts index 71e845502a..8a912348be 100644 --- a/ui-ngx/src/app/modules/home/components/audit-log/audit-log-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/audit-log/audit-log-table.component.ts @@ -32,9 +32,10 @@ import { getCurrentAuthUser } from '@core/auth/auth.selectors'; import { ActivatedRoute } from '@angular/router'; @Component({ - selector: 'tb-audit-log-table', - templateUrl: './audit-log-table.component.html', - styleUrls: ['./audit-log-table.component.scss'] + selector: 'tb-audit-log-table', + templateUrl: './audit-log-table.component.html', + styleUrls: ['./audit-log-table.component.scss'], + standalone: false }) export class AuditLogTableComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table.component.ts index 666a347564..741e9851e1 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table.component.ts @@ -37,11 +37,12 @@ import { EntityDebugSettingsService } from '@home/components/entity/debug/entity import { DatePipe } from '@angular/common'; @Component({ - selector: 'tb-calculated-fields-table', - templateUrl: './calculated-fields-table.component.html', - styleUrls: ['./calculated-fields-table.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - providers: [EntityDebugSettingsService] + selector: 'tb-calculated-fields-table', + templateUrl: './calculated-fields-table.component.html', + styleUrls: ['./calculated-fields-table.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + providers: [EntityDebugSettingsService], + standalone: false }) export class CalculatedFieldsTableComponent { diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts index 5446aaf14e..4b89028fb4 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts @@ -62,21 +62,22 @@ import { NULL_UUID } from '@shared/models/id/has-uuid'; import { BaseData } from '@shared/models/base-data'; @Component({ - selector: 'tb-calculated-field-arguments-table', - templateUrl: './calculated-field-arguments-table.component.html', - styleUrls: [`calculated-field-arguments-table.component.scss`], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => CalculatedFieldArgumentsTableComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => CalculatedFieldArgumentsTableComponent), - multi: true - } - ], + selector: 'tb-calculated-field-arguments-table', + templateUrl: './calculated-field-arguments-table.component.html', + styleUrls: [`calculated-field-arguments-table.component.scss`], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CalculatedFieldArgumentsTableComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => CalculatedFieldArgumentsTableComponent), + multi: true + } + ], + standalone: false }) export class CalculatedFieldArgumentsTableComponent implements ControlValueAccessor, Validator, OnChanges, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.ts index e0f67a87cd..579433b5ca 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.ts @@ -35,9 +35,10 @@ export interface CalculatedFieldDebugDialogData { } @Component({ - selector: 'tb-calculated-field-debug-dialog', - styleUrls: ['calculated-field-debug-dialog.component.scss'], - templateUrl: './calculated-field-debug-dialog.component.html', + selector: 'tb-calculated-field-debug-dialog', + styleUrls: ['calculated-field-debug-dialog.component.scss'], + templateUrl: './calculated-field-debug-dialog.component.html', + standalone: false }) export class CalculatedFieldDebugDialogComponent extends DialogComponent implements AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts index 1dbdf59f13..5a4cc6cedb 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts @@ -56,10 +56,11 @@ export interface CalculatedFieldDialogData { } @Component({ - selector: 'tb-calculated-field-dialog', - templateUrl: './calculated-field-dialog.component.html', - styleUrls: ['./calculated-field-dialog.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-calculated-field-dialog', + templateUrl: './calculated-field-dialog.component.html', + styleUrls: ['./calculated-field-dialog.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class CalculatedFieldDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.ts index cd32d96076..494d083b66 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.ts @@ -45,9 +45,10 @@ import { EntityAutocompleteComponent } from '@shared/components/entity/entity-au import { NULL_UUID } from '@shared/models/id/has-uuid'; @Component({ - selector: 'tb-calculated-field-argument-panel', - templateUrl: './calculated-field-argument-panel.component.html', - styleUrls: ['./calculated-field-argument-panel.component.scss'] + selector: 'tb-calculated-field-argument-panel', + templateUrl: './calculated-field-argument-panel.component.html', + styleUrls: ['./calculated-field-argument-panel.component.scss'], + standalone: false }) export class CalculatedFieldArgumentPanelComponent implements OnInit, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts index 09b8b5e2cf..9f67906ce7 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts @@ -44,21 +44,22 @@ import { filter } from 'rxjs/operators'; import { MatDialog } from '@angular/material/dialog'; @Component({ - selector: 'tb-calculated-field-test-arguments', - templateUrl: './calculated-field-test-arguments.component.html', - styleUrls: ['./calculated-field-test-arguments.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => CalculatedFieldTestArgumentsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => CalculatedFieldTestArgumentsComponent), - multi: true, - } - ] + selector: 'tb-calculated-field-test-arguments', + templateUrl: './calculated-field-test-arguments.component.html', + styleUrls: ['./calculated-field-test-arguments.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CalculatedFieldTestArgumentsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => CalculatedFieldTestArgumentsComponent), + multi: true, + } + ], + standalone: false }) export class CalculatedFieldTestArgumentsComponent extends PageComponent implements ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.ts index 8cf7515e3c..2593ab503b 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.ts @@ -55,10 +55,11 @@ export interface CalculatedFieldTestScriptDialogData extends CalculatedFieldTest } @Component({ - selector: 'tb-calculated-field-script-test-dialog', - templateUrl: './calculated-field-script-test-dialog.component.html', - styleUrls: ['./calculated-field-script-test-dialog.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-calculated-field-script-test-dialog', + templateUrl: './calculated-field-script-test-dialog.component.html', + styleUrls: ['./calculated-field-script-test-dialog.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class CalculatedFieldScriptTestDialogComponent extends DialogComponent implements AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.ts index 0a4f527064..cc1ef8aed1 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.ts @@ -42,11 +42,12 @@ export interface AddWidgetDialogData { } @Component({ - selector: 'tb-add-widget-dialog', - templateUrl: './add-widget-dialog.component.html', - providers: [/*{provide: ErrorStateMatcher, useExisting: AddWidgetDialogComponent}*/], - styleUrls: ['./add-widget-dialog.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-add-widget-dialog', + templateUrl: './add-widget-dialog.component.html', + providers: [ /*{provide: ErrorStateMatcher, useExisting: AddWidgetDialogComponent}*/], + styleUrls: ['./add-widget-dialog.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class AddWidgetDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.ts index ed17125e0e..571629789b 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.ts @@ -41,9 +41,10 @@ export interface DashboardImageDialogResult { } @Component({ - selector: 'tb-dashboard-image-dialog', - templateUrl: './dashboard-image-dialog.component.html', - styleUrls: ['./dashboard-image-dialog.component.scss'] + selector: 'tb-dashboard-image-dialog', + templateUrl: './dashboard-image-dialog.component.html', + styleUrls: ['./dashboard-image-dialog.component.scss'], + standalone: false }) export class DashboardImageDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts index dfeae2b227..6f8488a249 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts @@ -160,11 +160,12 @@ import { HttpStatusCode } from '@angular/common/http'; // @dynamic @Component({ - selector: 'tb-dashboard-page', - templateUrl: './dashboard-page.component.html', - styleUrls: ['./dashboard-page.component.scss'], - encapsulation: ViewEncapsulation.None, - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-dashboard-page', + templateUrl: './dashboard-page.component.html', + styleUrls: ['./dashboard-page.component.scss'], + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: false }) export class DashboardPageComponent extends PageComponent implements IDashboardController, HasDirtyFlag, OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.ts index 1dc3b4e462..52df3ca144 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.ts @@ -47,10 +47,11 @@ export interface DashboardSettingsDialogData { } @Component({ - selector: 'tb-dashboard-settings-dialog', - templateUrl: './dashboard-settings-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: DashboardSettingsDialogComponent}], - styleUrls: ['./dashboard-settings-dialog.component.scss'] + selector: 'tb-dashboard-settings-dialog', + templateUrl: './dashboard-settings-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: DashboardSettingsDialogComponent }], + styleUrls: ['./dashboard-settings-dialog.component.scss'], + standalone: false }) export class DashboardSettingsDialogComponent extends DialogComponent implements OnDestroy, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-state.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-state.component.ts index e83ef81e26..7e10544ffa 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-state.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-state.component.ts @@ -27,9 +27,10 @@ import { EntityId } from '@shared/models/id/entity-id'; import { Subscription } from 'rxjs'; @Component({ - selector: 'tb-dashboard-state', - templateUrl: './dashboard-state.component.html', - styleUrls: ['./dashboard-state.component.scss'] + selector: 'tb-dashboard-state', + templateUrl: './dashboard-state.component.html', + styleUrls: ['./dashboard-state.component.scss'], + standalone: false }) export class DashboardStateComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-toolbar.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-toolbar.component.ts index 13961e4c54..fa02811fdb 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-toolbar.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-toolbar.component.ts @@ -17,10 +17,11 @@ import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core'; @Component({ - selector: 'tb-dashboard-toolbar', - templateUrl: './dashboard-toolbar.component.html', - styleUrls: ['./dashboard-toolbar.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-dashboard-toolbar', + templateUrl: './dashboard-toolbar.component.html', + styleUrls: ['./dashboard-toolbar.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DashboardToolbarComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts index 5ae629a003..bf4a7b78eb 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts @@ -48,10 +48,11 @@ interface BundleWidgetsFilter extends WidgetsFilter { } @Component({ - selector: 'tb-dashboard-widget-select', - templateUrl: './dashboard-widget-select.component.html', - styleUrls: ['./dashboard-widget-select.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-dashboard-widget-select', + templateUrl: './dashboard-widget-select.component.html', + styleUrls: ['./dashboard-widget-select.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DashboardWidgetSelectComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.ts index 1bb15be0e3..e7d0491efd 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.ts @@ -31,9 +31,10 @@ import { DataKeySettingsFunction } from '@home/components/widget/lib/settings/co import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ - selector: 'tb-edit-widget', - templateUrl: './edit-widget.component.html', - styleUrls: ['./edit-widget.component.scss'] + selector: 'tb-edit-widget', + templateUrl: './edit-widget.component.html', + styleUrls: ['./edit-widget.component.scss'], + standalone: false }) export class EditWidgetComponent extends PageComponent implements OnInit, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/add-new-breakpoint-dialog.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/add-new-breakpoint-dialog.component.ts index 08f577a045..94c068da8e 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/add-new-breakpoint-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/add-new-breakpoint-dialog.component.ts @@ -35,8 +35,9 @@ export interface AddNewBreakpointDialogResult { } @Component({ - selector: 'add-new-breakpoint-dialog', - templateUrl: './add-new-breakpoint-dialog.component.html', + selector: 'add-new-breakpoint-dialog', + templateUrl: './add-new-breakpoint-dialog.component.html', + standalone: false }) export class AddNewBreakpointDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.ts index 36ec78e3a7..1699fe6c54 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.ts @@ -42,9 +42,10 @@ import { isNotEmptyStr } from '@core/utils'; import { TbContextMenuEvent } from '@shared/models/jquery-event.models'; @Component({ - selector: 'tb-dashboard-layout', - templateUrl: './dashboard-layout.component.html', - styleUrls: ['./dashboard-layout.component.scss'] + selector: 'tb-dashboard-layout', + templateUrl: './dashboard-layout.component.html', + styleUrls: ['./dashboard-layout.component.scss'], + standalone: false }) export class DashboardLayoutComponent extends PageComponent implements ILayoutController, DashboardCallbacks, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.ts index fe7d68eba6..20bded3dd0 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.ts @@ -75,10 +75,11 @@ export interface DashboardLayoutSettings { } @Component({ - selector: 'tb-manage-dashboard-layouts-dialog', - templateUrl: './manage-dashboard-layouts-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: ManageDashboardLayoutsDialogComponent}], - styleUrls: ['./manage-dashboard-layouts-dialog.component.scss', '../../../components/dashboard/layout-button.scss'] + selector: 'tb-manage-dashboard-layouts-dialog', + templateUrl: './manage-dashboard-layouts-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: ManageDashboardLayoutsDialogComponent }], + styleUrls: ['./manage-dashboard-layouts-dialog.component.scss', '../../../components/dashboard/layout-button.scss'], + standalone: false }) export class ManageDashboardLayoutsDialogComponent extends DialogComponent implements ErrorStateMatcher, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/move-widgets-dialog.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/move-widgets-dialog.component.ts index 2b9a430e3b..d377983169 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/move-widgets-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/move-widgets-dialog.component.ts @@ -28,10 +28,11 @@ export interface MoveWidgetsDialogResult { } @Component({ - selector: 'tb-move-widgets-dialog', - templateUrl: './move-widgets-dialog.component.html', - providers: [], - styleUrls: [] + selector: 'tb-move-widgets-dialog', + templateUrl: './move-widgets-dialog.component.html', + providers: [], + styleUrls: [], + standalone: false }) export class MoveWidgetsDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/select-dashboard-breakpoint.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/select-dashboard-breakpoint.component.ts index c9ad66d233..25e2a23a5d 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/select-dashboard-breakpoint.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/select-dashboard-breakpoint.component.ts @@ -21,9 +21,10 @@ import { BreakpointId } from '@shared/models/dashboard.models'; import { DashboardUtilsService } from '@core/services/dashboard-utils.service'; @Component({ - selector: 'tb-select-dashboard-breakpoint', - templateUrl: './select-dashboard-breakpoint.component.html', - styleUrls: ['./select-dashboard-breakpoint.component.scss'] + selector: 'tb-select-dashboard-breakpoint', + templateUrl: './select-dashboard-breakpoint.component.html', + styleUrls: ['./select-dashboard-breakpoint.component.scss'], + standalone: false }) export class SelectDashboardBreakpointComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/states/dashboard-state-dialog.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/states/dashboard-state-dialog.component.ts index 64f9153546..b90164e6c0 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/states/dashboard-state-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/states/dashboard-state-dialog.component.ts @@ -43,10 +43,11 @@ export interface DashboardStateDialogData { } @Component({ - selector: 'tb-dashboard-state-dialog', - templateUrl: './dashboard-state-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: DashboardStateDialogComponent}], - styleUrls: [] + selector: 'tb-dashboard-state-dialog', + templateUrl: './dashboard-state-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: DashboardStateDialogComponent }], + styleUrls: [], + standalone: false }) export class DashboardStateDialogComponent extends DialogComponent diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/states/default-state-controller.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/states/default-state-controller.component.ts index 92be4229b6..c0b3668e2e 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/states/default-state-controller.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/states/default-state-controller.component.ts @@ -29,9 +29,10 @@ import { EntityService } from '@core/http/entity.service'; import { MobileService } from '@core/services/mobile.service'; @Component({ - selector: 'tb-default-state-controller', - templateUrl: './default-state-controller.component.html', - styleUrls: ['./default-state-controller.component.scss'] + selector: 'tb-default-state-controller', + templateUrl: './default-state-controller.component.html', + styleUrls: ['./default-state-controller.component.scss'], + standalone: false }) export class DefaultStateControllerComponent extends StateControllerComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/states/entity-state-controller.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/states/entity-state-controller.component.ts index 15e18573f2..f8dfff6c97 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/states/entity-state-controller.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/states/entity-state-controller.component.ts @@ -31,9 +31,10 @@ import { map, tap } from 'rxjs/operators'; import { MobileService } from '@core/services/mobile.service'; @Component({ - selector: 'tb-entity-state-controller', - templateUrl: './entity-state-controller.component.html', - styleUrls: ['./entity-state-controller.component.scss'] + selector: 'tb-entity-state-controller', + templateUrl: './entity-state-controller.component.html', + styleUrls: ['./entity-state-controller.component.scss'], + standalone: false }) export class EntityStateControllerComponent extends StateControllerComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/states/manage-dashboard-states-dialog.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/states/manage-dashboard-states-dialog.component.ts index c570783684..7e0971aa4b 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/states/manage-dashboard-states-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/states/manage-dashboard-states-dialog.component.ts @@ -53,9 +53,10 @@ export interface ManageDashboardStatesDialogResult { } @Component({ - selector: 'tb-manage-dashboard-states-dialog', - templateUrl: './manage-dashboard-states-dialog.component.html', - styleUrls: ['./manage-dashboard-states-dialog.component.scss'] + selector: 'tb-manage-dashboard-states-dialog', + templateUrl: './manage-dashboard-states-dialog.component.html', + styleUrls: ['./manage-dashboard-states-dialog.component.scss'], + standalone: false }) export class ManageDashboardStatesDialogComponent extends DialogComponent diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/states/states-component.directive.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/states/states-component.directive.ts index 3588b22158..2229e6c24b 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/states/states-component.directive.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/states/states-component.directive.ts @@ -31,8 +31,9 @@ import { IStateControllerComponent } from '@home/components/dashboard-page/state import { BehaviorSubject, Subject } from 'rxjs'; @Directive({ - // eslint-disable-next-line @angular-eslint/directive-selector - selector: 'tb-states-component' + // eslint-disable-next-line @angular-eslint/directive-selector + selector: 'tb-states-component', + standalone: false }) export class StatesComponentDirective implements OnInit, OnDestroy, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/widget-types-panel.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/widget-types-panel.component.ts index 4aec56771c..cb43dce650 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/widget-types-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/widget-types-panel.component.ts @@ -30,9 +30,10 @@ export interface DisplayWidgetTypesPanelData { } @Component({ - selector: 'tb-widget-types-panel', - templateUrl: './widget-types-panel.component.html', - styleUrls: ['./widget-types-panel.component.scss'] + selector: 'tb-widget-types-panel', + templateUrl: './widget-types-panel.component.html', + styleUrls: ['./widget-types-panel.component.scss'], + standalone: false }) export class DisplayWidgetTypesPanelComponent { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-view/dashboard-view.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-view/dashboard-view.component.ts index 3e22d0719e..14bbd20688 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-view/dashboard-view.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-view/dashboard-view.component.ts @@ -22,9 +22,10 @@ import { Dashboard } from '@shared/models/dashboard.models'; import { ActivatedRoute } from '@angular/router'; @Component({ - selector: 'tb-dashboard-view', - templateUrl: './dashboard-view.component.html', - styleUrls: ['./dashboard-view.component.scss'] + selector: 'tb-dashboard-view', + templateUrl: './dashboard-view.component.html', + styleUrls: ['./dashboard-view.component.scss'], + standalone: false }) export class DashboardViewComponent extends PageComponent { diff --git a/ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts b/ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts index dedbecd8fd..a7df545332 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts @@ -63,10 +63,11 @@ import { coerceBoolean } from '@shared/decorators/coercion'; import { TbContextMenuEvent } from '@shared/models/jquery-event.models'; @Component({ - selector: 'tb-dashboard', - templateUrl: './dashboard.component.html', - styleUrls: ['./dashboard.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-dashboard', + templateUrl: './dashboard.component.html', + styleUrls: ['./dashboard.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: false }) export class DashboardComponent extends PageComponent implements IDashboardComponent, DoCheck, OnInit, OnDestroy, AfterViewInit, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/dashboard/select-target-layout-dialog.component.ts b/ui-ngx/src/app/modules/home/components/dashboard/select-target-layout-dialog.component.ts index 0ef839365f..a8e4e1c88e 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard/select-target-layout-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard/select-target-layout-dialog.component.ts @@ -23,9 +23,10 @@ import { DialogComponent } from '@app/shared/components/dialog.component'; import { DashboardLayoutId } from '@app/shared/models/dashboard.models'; @Component({ - selector: 'tb-select-target-layout-dialog', - templateUrl: './select-target-layout-dialog.component.html', - styleUrls: ['./layout-button.scss'] + selector: 'tb-select-target-layout-dialog', + templateUrl: './select-target-layout-dialog.component.html', + styleUrls: ['./layout-button.scss'], + standalone: false }) export class SelectTargetLayoutDialogComponent extends DialogComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/dashboard/select-target-state-dialog.component.ts b/ui-ngx/src/app/modules/home/components/dashboard/select-target-state-dialog.component.ts index 7c10619b08..20f81fe724 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard/select-target-state-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard/select-target-state-dialog.component.ts @@ -30,10 +30,11 @@ export interface SelectTargetStateDialogData { } @Component({ - selector: 'tb-select-target-state-dialog', - templateUrl: './select-target-state-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: SelectTargetStateDialogComponent}], - styleUrls: [] + selector: 'tb-select-target-state-dialog', + templateUrl: './select-target-state-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: SelectTargetStateDialogComponent }], + styleUrls: [], + standalone: false }) export class SelectTargetStateDialogComponent extends DialogComponent diff --git a/ui-ngx/src/app/modules/home/components/details-panel.component.ts b/ui-ngx/src/app/modules/home/components/details-panel.component.ts index dd82bf9879..1ab62c3081 100644 --- a/ui-ngx/src/app/modules/home/components/details-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/details-panel.component.ts @@ -31,9 +31,10 @@ import { Subscription } from 'rxjs'; import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ - selector: 'tb-details-panel', - templateUrl: './details-panel.component.html', - styleUrls: ['./details-panel.component.scss'] + selector: 'tb-details-panel', + templateUrl: './details-panel.component.html', + styleUrls: ['./details-panel.component.scss'], + standalone: false }) export class DetailsPanelComponent extends PageComponent implements OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/device/copy-device-credentials.component.ts b/ui-ngx/src/app/modules/home/components/device/copy-device-credentials.component.ts index 038c83b643..4d668d3255 100644 --- a/ui-ngx/src/app/modules/home/components/device/copy-device-credentials.component.ts +++ b/ui-ngx/src/app/modules/home/components/device/copy-device-credentials.component.ts @@ -28,9 +28,10 @@ import { AppState } from '@core/core.state'; import { TranslateService } from '@ngx-translate/core'; @Component({ - selector: 'tb-copy-device-credentials', - templateUrl: './copy-device-credentials.component.html', - styleUrls: [] + selector: 'tb-copy-device-credentials', + templateUrl: './copy-device-credentials.component.html', + styleUrls: [], + standalone: false }) export class CopyDeviceCredentialsComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials-lwm2m-server.component.ts b/ui-ngx/src/app/modules/home/components/device/device-credentials-lwm2m-server.component.ts index 7d7a3c2c6b..810993d6f5 100644 --- a/ui-ngx/src/app/modules/home/components/device/device-credentials-lwm2m-server.component.ts +++ b/ui-ngx/src/app/modules/home/components/device/device-credentials-lwm2m-server.component.ts @@ -36,21 +36,22 @@ import { takeUntil } from 'rxjs/operators'; import { Subject } from 'rxjs'; @Component({ - selector: 'tb-device-credentials-lwm2m-server', - templateUrl: './device-credentials-lwm2m-server.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DeviceCredentialsLwm2mServerComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DeviceCredentialsLwm2mServerComponent), - multi: true - } - ] + selector: 'tb-device-credentials-lwm2m-server', + templateUrl: './device-credentials-lwm2m-server.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceCredentialsLwm2mServerComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DeviceCredentialsLwm2mServerComponent), + multi: true + } + ], + standalone: false }) export class DeviceCredentialsLwm2mServerComponent implements OnDestroy, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials-lwm2m.component.ts b/ui-ngx/src/app/modules/home/components/device/device-credentials-lwm2m.component.ts index a73ac37795..3daa094f8f 100644 --- a/ui-ngx/src/app/modules/home/components/device/device-credentials-lwm2m.component.ts +++ b/ui-ngx/src/app/modules/home/components/device/device-credentials-lwm2m.component.ts @@ -37,21 +37,22 @@ import { takeUntil } from 'rxjs/operators'; import { isDefinedAndNotNull } from '@core/utils'; @Component({ - selector: 'tb-device-credentials-lwm2m', - templateUrl: './device-credentials-lwm2m.component.html', - styleUrls: ['./device-credentials-lwm2m.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DeviceCredentialsLwm2mComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DeviceCredentialsLwm2mComponent), - multi: true - } - ] + selector: 'tb-device-credentials-lwm2m', + templateUrl: './device-credentials-lwm2m.component.html', + styleUrls: ['./device-credentials-lwm2m.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceCredentialsLwm2mComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DeviceCredentialsLwm2mComponent), + multi: true + } + ], + standalone: false }) export class DeviceCredentialsLwm2mComponent implements ControlValueAccessor, Validator, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials-mqtt-basic.component.ts b/ui-ngx/src/app/modules/home/components/device/device-credentials-mqtt-basic.component.ts index 8c55b3bd6b..5ad1a1ac21 100644 --- a/ui-ngx/src/app/modules/home/components/device/device-credentials-mqtt-basic.component.ts +++ b/ui-ngx/src/app/modules/home/components/device/device-credentials-mqtt-basic.component.ts @@ -32,20 +32,22 @@ import { takeUntil } from 'rxjs/operators'; import { generateSecret, isDefinedAndNotNull, isEmptyStr } from '@core/utils'; @Component({ - selector: 'tb-device-credentials-mqtt-basic', - templateUrl: './device-credentials-mqtt-basic.component.html', - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DeviceCredentialsMqttBasicComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DeviceCredentialsMqttBasicComponent), - multi: true, - }], - styleUrls: [] + selector: 'tb-device-credentials-mqtt-basic', + templateUrl: './device-credentials-mqtt-basic.component.html', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceCredentialsMqttBasicComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DeviceCredentialsMqttBasicComponent), + multi: true, + } + ], + styleUrls: [], + standalone: false }) export class DeviceCredentialsMqttBasicComponent implements ControlValueAccessor, Validator, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts b/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts index 9e394b613d..6a663b5d93 100644 --- a/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts +++ b/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts @@ -38,20 +38,22 @@ import { generateSecret, isDefinedAndNotNull } from '@core/utils'; import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ - selector: 'tb-device-credentials', - templateUrl: './device-credentials.component.html', - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DeviceCredentialsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DeviceCredentialsComponent), - multi: true, - }], - styleUrls: ['./device-credentials.component.scss'] + selector: 'tb-device-credentials', + templateUrl: './device-credentials.component.html', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceCredentialsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DeviceCredentialsComponent), + multi: true, + } + ], + styleUrls: ['./device-credentials.component.scss'], + standalone: false }) export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit, Validator, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/device/device-info-filter.component.ts b/ui-ngx/src/app/modules/home/components/device/device-info-filter.component.ts index ad583ad1df..f25712d105 100644 --- a/ui-ngx/src/app/modules/home/components/device/device-info-filter.component.ts +++ b/ui-ngx/src/app/modules/home/components/device/device-info-filter.component.ts @@ -50,16 +50,17 @@ export interface DeviceFilterConfigData { // @dynamic @Component({ - selector: 'tb-device-info-filter', - templateUrl: './device-info-filter.component.html', - styleUrls: ['./device-info-filter.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DeviceInfoFilterComponent), - multi: true - } - ] + selector: 'tb-device-info-filter', + templateUrl: './device-info-filter.component.html', + styleUrls: ['./device-info-filter.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceInfoFilterComponent), + multi: true + } + ], + standalone: false }) export class DeviceInfoFilterComponent implements OnInit, OnDestroy, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/edge/edge-downlink-table-header.component.ts b/ui-ngx/src/app/modules/home/components/edge/edge-downlink-table-header.component.ts index d6e9c29c37..e1366d474c 100644 --- a/ui-ngx/src/app/modules/home/components/edge/edge-downlink-table-header.component.ts +++ b/ui-ngx/src/app/modules/home/components/edge/edge-downlink-table-header.component.ts @@ -22,9 +22,10 @@ import { EdgeEvent } from '@shared/models/edge.models'; import { EdgeDownlinkTableConfig } from '@home/components/edge/edge-downlink-table-config'; @Component({ - selector: 'tb-edge-downlink-table-header', - templateUrl: './edge-downlink-table-header.component.html', - styleUrls: ['./edge-downlink-table-header.component.scss'] + selector: 'tb-edge-downlink-table-header', + templateUrl: './edge-downlink-table-header.component.html', + styleUrls: ['./edge-downlink-table-header.component.scss'], + standalone: false }) export class EdgeDownlinkTableHeaderComponent extends EntityTableHeaderComponent { diff --git a/ui-ngx/src/app/modules/home/components/edge/edge-downlink-table.component.ts b/ui-ngx/src/app/modules/home/components/edge/edge-downlink-table.component.ts index 279381b110..8bb83eda19 100644 --- a/ui-ngx/src/app/modules/home/components/edge/edge-downlink-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/edge/edge-downlink-table.component.ts @@ -29,9 +29,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-edge-downlink-table', - templateUrl: './edge-downlink-table.component.html', - styleUrls: ['./edge-downlink-table.component.scss'] + selector: 'tb-edge-downlink-table', + templateUrl: './edge-downlink-table.component.html', + styleUrls: ['./edge-downlink-table.component.scss'], + standalone: false }) export class EdgeDownlinkTableComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/entity/add-entity-dialog.component.ts b/ui-ngx/src/app/modules/home/components/entity/add-entity-dialog.component.ts index f117fd2a44..5894921d1a 100644 --- a/ui-ngx/src/app/modules/home/components/entity/add-entity-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/entity/add-entity-dialog.component.ts @@ -31,10 +31,11 @@ import { DialogComponent } from '@shared/components/dialog.component'; import { Router } from '@angular/router'; @Component({ - selector: 'tb-add-entity-dialog', - templateUrl: './add-entity-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: AddEntityDialogComponent}], - styleUrls: ['./add-entity-dialog.component.scss'] + selector: 'tb-add-entity-dialog', + templateUrl: './add-entity-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: AddEntityDialogComponent }], + styleUrls: ['./add-entity-dialog.component.scss'], + standalone: false }) export class AddEntityDialogComponent extends DialogComponent> implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings-button.component.ts b/ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings-button.component.ts index f0e3cdb2d0..e0dd1360e5 100644 --- a/ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings-button.component.ts +++ b/ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings-button.component.ts @@ -39,23 +39,22 @@ import { AdditionalDebugActionConfig } from '@home/components/entity/debug/entit import { EntityType } from '@shared/models/entity-type.models'; @Component({ - selector: 'tb-entity-debug-settings-button', - templateUrl: './entity-debug-settings-button.component.html', - standalone: true, - imports: [ - CommonModule, - SharedModule, - DurationLeftPipe, - ], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => EntityDebugSettingsButtonComponent), - multi: true - }, - EntityDebugSettingsService - ], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-entity-debug-settings-button', + templateUrl: './entity-debug-settings-button.component.html', + imports: [ + CommonModule, + SharedModule, + DurationLeftPipe, + ], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => EntityDebugSettingsButtonComponent), + multi: true + }, + EntityDebugSettingsService + ], + changeDetection: ChangeDetectionStrategy.OnPush }) export class EntityDebugSettingsButtonComponent implements ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings-panel.component.ts index 458c5e9765..6baefe0627 100644 --- a/ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings-panel.component.ts @@ -39,15 +39,14 @@ import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.m import { getCurrentAuthState } from '@core/auth/auth.selectors'; @Component({ - selector: 'tb-entity-debug-settings-panel', - templateUrl: './entity-debug-settings-panel.component.html', - standalone: true, - imports: [ - SharedModule, - CommonModule, - DurationLeftPipe - ], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-entity-debug-settings-panel', + templateUrl: './entity-debug-settings-panel.component.html', + imports: [ + SharedModule, + CommonModule, + DurationLeftPipe + ], + changeDetection: ChangeDetectionStrategy.OnPush }) export class EntityDebugSettingsPanelComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts b/ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts index ec04a7eed8..6999c76180 100644 --- a/ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts @@ -71,10 +71,11 @@ import { EntityDetailsPanelComponent } from '@home/components/entity/entity-deta import { FormBuilder } from '@angular/forms'; @Component({ - selector: 'tb-entities-table', - templateUrl: './entities-table.component.html', - styleUrls: ['./entities-table.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-entities-table', + templateUrl: './entities-table.component.html', + styleUrls: ['./entities-table.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: false }) export class EntitiesTableComponent extends PageComponent implements IEntitiesTableComponent, AfterViewInit, OnInit, OnChanges, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/entity/entity-chips.component.ts b/ui-ngx/src/app/modules/home/components/entity/entity-chips.component.ts index eed41e2820..7dbe3d2949 100644 --- a/ui-ngx/src/app/modules/home/components/entity/entity-chips.component.ts +++ b/ui-ngx/src/app/modules/home/components/entity/entity-chips.component.ts @@ -21,9 +21,10 @@ import { baseDetailsPageByEntityType, EntityType } from '@app/shared/public-api' import { isEqual, isNotEmptyStr, isObject } from '@core/utils'; @Component({ - selector: 'tb-entity-chips', - templateUrl: './entity-chips.component.html', - styleUrls: ['./entity-chips.component.scss'] + selector: 'tb-entity-chips', + templateUrl: './entity-chips.component.html', + styleUrls: ['./entity-chips.component.scss'], + standalone: false }) export class EntityChipsComponent implements OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/entity/entity-details-page.component.ts b/ui-ngx/src/app/modules/home/components/entity/entity-details-page.component.ts index a66e04f23f..8988a02380 100644 --- a/ui-ngx/src/app/modules/home/components/entity/entity-details-page.component.ts +++ b/ui-ngx/src/app/modules/home/components/entity/entity-details-page.component.ts @@ -37,10 +37,11 @@ import { DialogService } from '@core/services/dialog.service'; import { IEntityDetailsPageComponent } from '@home/models/entity/entity-details-page-component.models'; @Component({ - selector: 'tb-entity-details-page', - templateUrl: './entity-details-page.component.html', - styleUrls: ['./entity-details-page.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-entity-details-page', + templateUrl: './entity-details-page.component.html', + styleUrls: ['./entity-details-page.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: false }) export class EntityDetailsPageComponent extends EntityDetailsPanelComponent implements IEntityDetailsPageComponent, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/entity/entity-details-panel.component.ts b/ui-ngx/src/app/modules/home/components/entity/entity-details-panel.component.ts index 88b981d9db..8c6fc004d8 100644 --- a/ui-ngx/src/app/modules/home/components/entity/entity-details-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/entity/entity-details-panel.component.ts @@ -47,10 +47,11 @@ import { catchError } from 'rxjs/operators'; import { HttpStatusCode } from '@angular/common/http'; @Component({ - selector: 'tb-entity-details-panel', - templateUrl: './entity-details-panel.component.html', - styleUrls: ['./entity-details-panel.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-entity-details-panel', + templateUrl: './entity-details-panel.component.html', + styleUrls: ['./entity-details-panel.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: false }) export class EntityDetailsPanelComponent extends PageComponent implements AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/entity/entity-filter-view.component.ts b/ui-ngx/src/app/modules/home/components/entity/entity-filter-view.component.ts index 7fb4768be4..ce5d78804d 100644 --- a/ui-ngx/src/app/modules/home/components/entity/entity-filter-view.component.ts +++ b/ui-ngx/src/app/modules/home/components/entity/entity-filter-view.component.ts @@ -21,16 +21,17 @@ import { AliasEntityType, EntityType, entityTypeTranslations } from '@shared/mod import { TranslateService } from '@ngx-translate/core'; @Component({ - selector: 'tb-entity-filter-view', - templateUrl: './entity-filter-view.component.html', - styleUrls: ['./entity-filter-view.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => EntityFilterViewComponent), - multi: true - } - ] + selector: 'tb-entity-filter-view', + templateUrl: './entity-filter-view.component.html', + styleUrls: ['./entity-filter-view.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => EntityFilterViewComponent), + multi: true + } + ], + standalone: false }) export class EntityFilterViewComponent implements ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/entity/entity-filter.component.ts b/ui-ngx/src/app/modules/home/components/entity/entity-filter.component.ts index 88c0035902..dcd127c4a3 100644 --- a/ui-ngx/src/app/modules/home/components/entity/entity-filter.component.ts +++ b/ui-ngx/src/app/modules/home/components/entity/entity-filter.component.ts @@ -24,16 +24,17 @@ import { Subject, Subscription } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ - selector: 'tb-entity-filter', - templateUrl: './entity-filter.component.html', - styleUrls: ['./entity-filter.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => EntityFilterComponent), - multi: true - } - ] + selector: 'tb-entity-filter', + templateUrl: './entity-filter.component.html', + styleUrls: ['./entity-filter.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => EntityFilterComponent), + multi: true + } + ], + standalone: false }) export class EntityFilterComponent implements ControlValueAccessor, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts b/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts index 770ebb9c9b..5eb15642bb 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts @@ -36,9 +36,10 @@ export interface EventContentDialogData { } @Component({ - selector: 'tb-event-content-dialog', - templateUrl: './event-content-dialog.component.html', - styleUrls: ['./event-content-dialog.component.scss'] + selector: 'tb-event-content-dialog', + templateUrl: './event-content-dialog.component.html', + styleUrls: ['./event-content-dialog.component.scss'], + standalone: false }) export class EventContentDialogComponent extends DialogComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/event/event-filter-panel.component.ts b/ui-ngx/src/app/modules/home/components/event/event-filter-panel.component.ts index efc24adb8d..6b50c95d76 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-filter-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/event/event-filter-panel.component.ts @@ -35,9 +35,10 @@ export interface FilterEntityColumn { @Component({ - selector: 'tb-event-filter-panel', - templateUrl: './event-filter-panel.component.html', - styleUrls: ['./event-filter-panel.component.scss'] + selector: 'tb-event-filter-panel', + templateUrl: './event-filter-panel.component.html', + styleUrls: ['./event-filter-panel.component.scss'], + standalone: false }) export class EventFilterPanelComponent { diff --git a/ui-ngx/src/app/modules/home/components/event/event-table-header.component.ts b/ui-ngx/src/app/modules/home/components/event/event-table-header.component.ts index d4cd493e73..867df4d6d2 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-table-header.component.ts +++ b/ui-ngx/src/app/modules/home/components/event/event-table-header.component.ts @@ -22,9 +22,10 @@ import { DebugEventType, Event, EventType, eventTypeTranslations } from '@app/sh import { EventTableConfig } from '@home/components/event/event-table-config'; @Component({ - selector: 'tb-event-table-header', - templateUrl: './event-table-header.component.html', - styleUrls: ['./event-table-header.component.scss'] + selector: 'tb-event-table-header', + templateUrl: './event-table-header.component.html', + styleUrls: ['./event-table-header.component.scss'], + standalone: false }) export class EventTableHeaderComponent extends EntityTableHeaderComponent { diff --git a/ui-ngx/src/app/modules/home/components/event/event-table.component.ts b/ui-ngx/src/app/modules/home/components/event/event-table.component.ts index 77fbb7d0bc..76f6747099 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/event/event-table.component.ts @@ -40,9 +40,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-event-table', - templateUrl: './event-table.component.html', - styleUrls: ['./event-table.component.scss'] + selector: 'tb-event-table', + templateUrl: './event-table.component.html', + styleUrls: ['./event-table.component.scss'], + standalone: false }) export class EventTableComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.ts b/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.ts index 3f152e79fa..c3a445d4a3 100644 --- a/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.ts @@ -35,21 +35,22 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-boolean-filter-predicate', - templateUrl: './boolean-filter-predicate.component.html', - styleUrls: ['./filter-predicate.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => BooleanFilterPredicateComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => BooleanFilterPredicateComponent), - multi: true - } - ] + selector: 'tb-boolean-filter-predicate', + templateUrl: './boolean-filter-predicate.component.html', + styleUrls: ['./filter-predicate.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => BooleanFilterPredicateComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => BooleanFilterPredicateComponent), + multi: true + } + ], + standalone: false }) export class BooleanFilterPredicateComponent implements ControlValueAccessor, Validator, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate-dialog.component.ts b/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate-dialog.component.ts index f2770affb5..ceb5b63ce7 100644 --- a/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate-dialog.component.ts @@ -31,10 +31,11 @@ import { import { ComplexFilterPredicateDialogData } from '@home/components/filter/filter-component.models'; @Component({ - selector: 'tb-complex-filter-predicate-dialog', - templateUrl: './complex-filter-predicate-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: ComplexFilterPredicateDialogComponent}], - styleUrls: [] + selector: 'tb-complex-filter-predicate-dialog', + templateUrl: './complex-filter-predicate-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: ComplexFilterPredicateDialogComponent }], + styleUrls: [], + standalone: false }) export class ComplexFilterPredicateDialogComponent extends DialogComponent diff --git a/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate.component.ts b/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate.component.ts index 0df6a9d69b..88a2971b87 100644 --- a/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate.component.ts @@ -24,16 +24,17 @@ import { COMPLEX_FILTER_PREDICATE_DIALOG_COMPONENT_TOKEN } from '@home/component import { ComponentType } from '@angular/cdk/portal'; @Component({ - selector: 'tb-complex-filter-predicate', - templateUrl: './complex-filter-predicate.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ComplexFilterPredicateComponent), - multi: true - } - ] + selector: 'tb-complex-filter-predicate', + templateUrl: './complex-filter-predicate.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ComplexFilterPredicateComponent), + multi: true + } + ], + standalone: false }) export class ComplexFilterPredicateComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-dialog.component.ts b/ui-ngx/src/app/modules/home/components/filter/filter-dialog.component.ts index 75b56e15a5..ec3c9b79f0 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/filter-dialog.component.ts @@ -41,10 +41,11 @@ export interface FilterDialogData { } @Component({ - selector: 'tb-filter-dialog', - templateUrl: './filter-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: FilterDialogComponent}], - styleUrls: ['./filter-dialog.component.scss'] + selector: 'tb-filter-dialog', + templateUrl: './filter-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: FilterDialogComponent }], + styleUrls: ['./filter-dialog.component.scss'], + standalone: false }) export class FilterDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.ts b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.ts index 1fb3a00360..8ab2bd6e35 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.ts @@ -43,21 +43,22 @@ import { COMPLEX_FILTER_PREDICATE_DIALOG_COMPONENT_TOKEN } from '@home/component import { ComplexFilterPredicateDialogData } from '@home/components/filter/filter-component.models'; @Component({ - selector: 'tb-filter-predicate-list', - templateUrl: './filter-predicate-list.component.html', - styleUrls: ['./filter-predicate-list.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => FilterPredicateListComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => FilterPredicateListComponent), - multi: true - } - ] + selector: 'tb-filter-predicate-list', + templateUrl: './filter-predicate-list.component.html', + styleUrls: ['./filter-predicate-list.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => FilterPredicateListComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => FilterPredicateListComponent), + multi: true + } + ], + standalone: false }) export class FilterPredicateListComponent implements ControlValueAccessor, Validator, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts index 01154c8930..14c334b72c 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts @@ -38,21 +38,22 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-filter-predicate-value', - templateUrl: './filter-predicate-value.component.html', - styleUrls: ['./filter-predicate.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => FilterPredicateValueComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => FilterPredicateValueComponent), - multi: true - } - ] + selector: 'tb-filter-predicate-value', + templateUrl: './filter-predicate-value.component.html', + styleUrls: ['./filter-predicate.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => FilterPredicateValueComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => FilterPredicateValueComponent), + multi: true + } + ], + standalone: false }) export class FilterPredicateValueComponent implements ControlValueAccessor, Validator, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate.component.ts b/ui-ngx/src/app/modules/home/components/filter/filter-predicate.component.ts index 170945e4ce..e4e327bf0a 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate.component.ts @@ -29,21 +29,22 @@ import { EntityKeyValueType, FilterPredicateType, KeyFilterPredicateInfo } from import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-filter-predicate', - templateUrl: './filter-predicate.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => FilterPredicateComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => FilterPredicateComponent), - multi: true - } - ] + selector: 'tb-filter-predicate', + templateUrl: './filter-predicate.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => FilterPredicateComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => FilterPredicateComponent), + multi: true + } + ], + standalone: false }) export class FilterPredicateComponent implements ControlValueAccessor, Validator, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-text.component.ts b/ui-ngx/src/app/modules/home/components/filter/filter-text.component.ts index 2dce9164db..d2d53c0918 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-text.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/filter-text.component.ts @@ -23,16 +23,17 @@ import { DatePipe } from '@angular/common'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; @Component({ - selector: 'tb-filter-text', - templateUrl: './filter-text.component.html', - styleUrls: ['./filter-text.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => FilterTextComponent), - multi: true - } - ] + selector: 'tb-filter-text', + templateUrl: './filter-text.component.html', + styleUrls: ['./filter-text.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => FilterTextComponent), + multi: true + } + ], + standalone: false }) export class FilterTextComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-user-info-dialog.component.ts b/ui-ngx/src/app/modules/home/components/filter/filter-user-info-dialog.component.ts index 0c4509f133..6eb7da12b2 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-user-info-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/filter-user-info-dialog.component.ts @@ -43,10 +43,11 @@ export interface FilterUserInfoDialogData { } @Component({ - selector: 'tb-filter-user-info-dialog', - templateUrl: './filter-user-info-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: FilterUserInfoDialogComponent}], - styleUrls: [] + selector: 'tb-filter-user-info-dialog', + templateUrl: './filter-user-info-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: FilterUserInfoDialogComponent }], + styleUrls: [], + standalone: false }) export class FilterUserInfoDialogComponent extends DialogComponent diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-user-info.component.ts b/ui-ngx/src/app/modules/home/components/filter/filter-user-info.component.ts index 006bbf81f6..952e0ac9d6 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-user-info.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/filter-user-info.component.ts @@ -30,16 +30,17 @@ import { import { deepClone } from '@core/utils'; @Component({ - selector: 'tb-filter-user-info', - templateUrl: './filter-user-info.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => FilterUserInfoComponent), - multi: true - } - ] + selector: 'tb-filter-user-info', + templateUrl: './filter-user-info.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => FilterUserInfoComponent), + multi: true + } + ], + standalone: false }) export class FilterUserInfoComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/filter/filters-dialog.component.ts b/ui-ngx/src/app/modules/home/components/filter/filters-dialog.component.ts index 545c97bffd..8282c2cd21 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filters-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/filters-dialog.component.ts @@ -52,10 +52,11 @@ export interface FiltersDialogData { } @Component({ - selector: 'tb-filters-dialog', - templateUrl: './filters-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: FiltersDialogComponent}], - styleUrls: ['./filters-dialog.component.scss'] + selector: 'tb-filters-dialog', + templateUrl: './filters-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: FiltersDialogComponent }], + styleUrls: ['./filters-dialog.component.scss'], + standalone: false }) export class FiltersDialogComponent extends DialogComponent implements ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/filter/filters-edit-panel.component.ts b/ui-ngx/src/app/modules/home/components/filter/filters-edit-panel.component.ts index ccb05c7f0c..06a218394c 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filters-edit-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/filters-edit-panel.component.ts @@ -29,9 +29,10 @@ export interface FiltersEditPanelData { } @Component({ - selector: 'tb-filters-edit-panel', - templateUrl: './filters-edit-panel.component.html', - styleUrls: ['./filters-edit-panel.component.scss'] + selector: 'tb-filters-edit-panel', + templateUrl: './filters-edit-panel.component.html', + styleUrls: ['./filters-edit-panel.component.scss'], + standalone: false }) export class FiltersEditPanelComponent { diff --git a/ui-ngx/src/app/modules/home/components/filter/filters-edit.component.ts b/ui-ngx/src/app/modules/home/components/filter/filters-edit.component.ts index 48a33a8765..5bbd4ac034 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filters-edit.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/filters-edit.component.ts @@ -42,9 +42,10 @@ import { UserFilterDialogComponent, UserFilterDialogData } from '@home/component import { MatDialog } from '@angular/material/dialog'; @Component({ - selector: 'tb-filters-edit', - templateUrl: './filters-edit.component.html', - styleUrls: ['./filters-edit.component.scss'] + selector: 'tb-filters-edit', + templateUrl: './filters-edit.component.html', + styleUrls: ['./filters-edit.component.scss'], + standalone: false }) export class FiltersEditComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/filter/key-filter-dialog.component.ts b/ui-ngx/src/app/modules/home/components/filter/key-filter-dialog.component.ts index e6e58c33cb..ffaa10570d 100644 --- a/ui-ngx/src/app/modules/home/components/filter/key-filter-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/key-filter-dialog.component.ts @@ -50,10 +50,11 @@ export interface KeyFilterDialogData { } @Component({ - selector: 'tb-key-filter-dialog', - templateUrl: './key-filter-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: KeyFilterDialogComponent}], - styleUrls: ['./key-filter-dialog.component.scss'] + selector: 'tb-key-filter-dialog', + templateUrl: './key-filter-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: KeyFilterDialogComponent }], + styleUrls: ['./key-filter-dialog.component.scss'], + standalone: false }) export class KeyFilterDialogComponent extends DialogComponent diff --git a/ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.ts b/ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.ts index ec3075f9f8..aad686707d 100644 --- a/ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.ts @@ -42,21 +42,22 @@ import { EntityId } from '@shared/models/id/entity-id'; import { takeUntil } from 'rxjs/operators'; @Component({ - selector: 'tb-key-filter-list', - templateUrl: './key-filter-list.component.html', - styleUrls: ['./key-filter-list.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => KeyFilterListComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => KeyFilterListComponent), - multi: true - } - ] + selector: 'tb-key-filter-list', + templateUrl: './key-filter-list.component.html', + styleUrls: ['./key-filter-list.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => KeyFilterListComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => KeyFilterListComponent), + multi: true + } + ], + standalone: false }) export class KeyFilterListComponent implements ControlValueAccessor, Validator, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.ts b/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.ts index 6d5952c1ee..3fb257f55f 100644 --- a/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.ts @@ -35,21 +35,22 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-numeric-filter-predicate', - templateUrl: './numeric-filter-predicate.component.html', - styleUrls: ['./filter-predicate.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => NumericFilterPredicateComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => NumericFilterPredicateComponent), - multi: true - } - ] + selector: 'tb-numeric-filter-predicate', + templateUrl: './numeric-filter-predicate.component.html', + styleUrls: ['./filter-predicate.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => NumericFilterPredicateComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => NumericFilterPredicateComponent), + multi: true + } + ], + standalone: false }) export class NumericFilterPredicateComponent implements ControlValueAccessor, Validator, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.ts b/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.ts index c2fac83db0..d4e3be6b5f 100644 --- a/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.ts @@ -35,21 +35,22 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-string-filter-predicate', - templateUrl: './string-filter-predicate.component.html', - styleUrls: ['./filter-predicate.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => StringFilterPredicateComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => StringFilterPredicateComponent), - multi: true - } - ] + selector: 'tb-string-filter-predicate', + templateUrl: './string-filter-predicate.component.html', + styleUrls: ['./filter-predicate.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => StringFilterPredicateComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => StringFilterPredicateComponent), + multi: true + } + ], + standalone: false }) export class StringFilterPredicateComponent implements ControlValueAccessor, Validator, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/filter/user-filter-dialog.component.ts b/ui-ngx/src/app/modules/home/components/filter/user-filter-dialog.component.ts index 279b257178..6e068fdcf3 100644 --- a/ui-ngx/src/app/modules/home/components/filter/user-filter-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/user-filter-dialog.component.ts @@ -40,10 +40,11 @@ export interface UserFilterDialogData { } @Component({ - selector: 'tb-user-filter-dialog', - templateUrl: './user-filter-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: UserFilterDialogComponent}], - styleUrls: ['./user-filter-dialog.component.scss'], + selector: 'tb-user-filter-dialog', + templateUrl: './user-filter-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: UserFilterDialogComponent }], + styleUrls: ['./user-filter-dialog.component.scss'], + standalone: false }) export class UserFilterDialogComponent extends DialogComponent implements ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/github-badge/github-badge.component.ts b/ui-ngx/src/app/modules/home/components/github-badge/github-badge.component.ts index a1ec8318d3..7b12265e66 100644 --- a/ui-ngx/src/app/modules/home/components/github-badge/github-badge.component.ts +++ b/ui-ngx/src/app/modules/home/components/github-badge/github-badge.component.ts @@ -27,9 +27,10 @@ import { Subject } from 'rxjs'; const SETTINGS_KEY = 'HIDE_GITHUB_STAR_BUTTON'; @Component({ - selector: 'tb-github-badge', - templateUrl: './github-badge.component.html', - styleUrl: './github-badge.component.scss' + selector: 'tb-github-badge', + templateUrl: './github-badge.component.html', + styleUrl: './github-badge.component.scss', + standalone: false }) export class GithubBadgeComponent implements OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/notification/notification-bell.component.ts b/ui-ngx/src/app/modules/home/components/notification/notification-bell.component.ts index 4060e4c54f..40df0ed280 100644 --- a/ui-ngx/src/app/modules/home/components/notification/notification-bell.component.ts +++ b/ui-ngx/src/app/modules/home/components/notification/notification-bell.component.ts @@ -35,9 +35,10 @@ import { selectIsAuthenticated } from '@core/auth/auth.selectors'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-notification-bell', - templateUrl: './notification-bell.component.html', - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-notification-bell', + templateUrl: './notification-bell.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: false }) export class NotificationBellComponent implements OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/notification/send-notification-button.component.ts b/ui-ngx/src/app/modules/home/components/notification/send-notification-button.component.ts index 8bb603d023..d159baecd4 100644 --- a/ui-ngx/src/app/modules/home/components/notification/send-notification-button.component.ts +++ b/ui-ngx/src/app/modules/home/components/notification/send-notification-button.component.ts @@ -30,8 +30,9 @@ import { getCurrentAuthUser } from '@core/auth/auth.selectors'; import { Authority } from '@shared/models/authority.enum'; @Component({ - selector: 'tb-send-notification-button', - templateUrl: './send-notification-button.component.html', + selector: 'tb-send-notification-button', + templateUrl: './send-notification-button.component.html', + standalone: false }) export class SendNotificationButtonComponent { diff --git a/ui-ngx/src/app/modules/home/components/notification/show-notification-popover.component.ts b/ui-ngx/src/app/modules/home/components/notification/show-notification-popover.component.ts index 65891d77c3..f9e4969788 100644 --- a/ui-ngx/src/app/modules/home/components/notification/show-notification-popover.component.ts +++ b/ui-ngx/src/app/modules/home/components/notification/show-notification-popover.component.ts @@ -28,9 +28,10 @@ import { NotificationSubscriber } from '@shared/models/telemetry/telemetry.model import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-show-notification-popover', - templateUrl: './show-notification-popover.component.html', - styleUrls: ['show-notification-popover.component.scss'] + selector: 'tb-show-notification-popover', + templateUrl: './show-notification-popover.component.html', + styleUrls: ['show-notification-popover.component.scss'], + standalone: false }) export class ShowNotificationPopoverComponent extends PageComponent implements OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.ts index 480e4b74eb..a8ee087ad7 100644 --- a/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.ts @@ -54,10 +54,11 @@ export interface AddDeviceProfileDialogData { } @Component({ - selector: 'tb-add-device-profile-dialog', - templateUrl: './add-device-profile-dialog.component.html', - providers: [], - styleUrls: ['./add-device-profile-dialog.component.scss'] + selector: 'tb-add-device-profile-dialog', + templateUrl: './add-device-profile-dialog.component.html', + providers: [], + styleUrls: ['./add-device-profile-dialog.component.scss'], + standalone: false }) export class AddDeviceProfileDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-duration-predicate-value.component.ts b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-duration-predicate-value.component.ts index d0a08dce25..fe8945fd83 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-duration-predicate-value.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-duration-predicate-value.component.ts @@ -27,16 +27,17 @@ import { AlarmConditionType } from '@shared/models/device.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-alarm-duration-predicate-value', - templateUrl: './alarm-duration-predicate-value.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AlarmDurationPredicateValueComponent), - multi: true - } - ] + selector: 'tb-alarm-duration-predicate-value', + templateUrl: './alarm-duration-predicate-value.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AlarmDurationPredicateValueComponent), + multi: true + } + ], + standalone: false }) export class AlarmDurationPredicateValueComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-dynamic-value.component.ts b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-dynamic-value.component.ts index af7e4b07be..da5022571a 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-dynamic-value.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-dynamic-value.component.ts @@ -29,13 +29,14 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-alarm-dynamic-value', - templateUrl: './alarm-dynamic-value.component.html', - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AlarmDynamicValue), - multi: true - }] + selector: 'tb-alarm-dynamic-value', + templateUrl: './alarm-dynamic-value.component.html', + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AlarmDynamicValue), + multi: true + }], + standalone: false }) export class AlarmDynamicValue implements ControlValueAccessor, OnInit{ diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-condition-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-condition-dialog.component.ts index 0f3f183341..ba16a910db 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-condition-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-condition-dialog.component.ts @@ -36,10 +36,11 @@ export interface AlarmRuleConditionDialogData { } @Component({ - selector: 'tb-alarm-rule-condition-dialog', - templateUrl: './alarm-rule-condition-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: AlarmRuleConditionDialogComponent}], - styleUrls: ['./alarm-rule-condition-dialog.component.scss'] + selector: 'tb-alarm-rule-condition-dialog', + templateUrl: './alarm-rule-condition-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: AlarmRuleConditionDialogComponent }], + styleUrls: ['./alarm-rule-condition-dialog.component.scss'], + standalone: false }) export class AlarmRuleConditionDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-condition.component.ts b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-condition.component.ts index df98b4906a..944e73b508 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-condition.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-condition.component.ts @@ -38,21 +38,22 @@ import { EntityId } from '@shared/models/id/entity-id'; import { dynamicValueSourceTypeTranslationMap } from '@shared/models/query/query.models'; @Component({ - selector: 'tb-alarm-rule-condition', - templateUrl: './alarm-rule-condition.component.html', - styleUrls: ['./alarm-rule-condition.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AlarmRuleConditionComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => AlarmRuleConditionComponent), - multi: true, - } - ] + selector: 'tb-alarm-rule-condition', + templateUrl: './alarm-rule-condition.component.html', + styleUrls: ['./alarm-rule-condition.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AlarmRuleConditionComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => AlarmRuleConditionComponent), + multi: true, + } + ], + standalone: false }) export class AlarmRuleConditionComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule.component.ts b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule.component.ts index a3238e4385..a6506aa33d 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule.component.ts @@ -39,21 +39,22 @@ import { UtilsService } from '@core/services/utils.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-alarm-rule', - templateUrl: './alarm-rule.component.html', - styleUrls: ['./alarm-rule.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AlarmRuleComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => AlarmRuleComponent), - multi: true, - } - ] + selector: 'tb-alarm-rule', + templateUrl: './alarm-rule.component.html', + styleUrls: ['./alarm-rule.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AlarmRuleComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => AlarmRuleComponent), + multi: true, + } + ], + standalone: false }) export class AlarmRuleComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-schedule-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-schedule-dialog.component.ts index 24424f5048..f9224cdccc 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-schedule-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-schedule-dialog.component.ts @@ -32,10 +32,11 @@ export interface AlarmScheduleDialogData { } @Component({ - selector: 'tb-alarm-schedule-dialog', - templateUrl: './alarm-schedule-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: AlarmScheduleDialogComponent}], - styleUrls: [] + selector: 'tb-alarm-schedule-dialog', + templateUrl: './alarm-schedule-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: AlarmScheduleDialogComponent }], + styleUrls: [], + standalone: false }) export class AlarmScheduleDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-schedule-info.component.ts b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-schedule-info.component.ts index a0257da8ad..30209a2f7c 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-schedule-info.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-schedule-info.component.ts @@ -31,14 +31,15 @@ import { deepClone, isDefinedAndNotNull } from '@core/utils'; import { TranslateService } from '@ngx-translate/core'; @Component({ - selector: 'tb-alarm-schedule-info', - templateUrl: './alarm-schedule-info.component.html', - styleUrls: ['./alarm-schedule-info.component.scss'], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AlarmScheduleInfoComponent), - multi: true - }] + selector: 'tb-alarm-schedule-info', + templateUrl: './alarm-schedule-info.component.html', + styleUrls: ['./alarm-schedule-info.component.scss'], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AlarmScheduleInfoComponent), + multi: true + }], + standalone: false }) export class AlarmScheduleInfoComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-schedule.component.ts b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-schedule.component.ts index 384a266a08..90caf04b70 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-schedule.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-schedule.component.ts @@ -43,18 +43,19 @@ import { getDefaultTimezone } from '@shared/models/time/time.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-alarm-schedule', - templateUrl: './alarm-schedule.component.html', - styleUrls: ['./alarm-schedule.component.scss'], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AlarmScheduleComponent), - multi: true - }, { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => AlarmScheduleComponent), - multi: true - }] + selector: 'tb-alarm-schedule', + templateUrl: './alarm-schedule.component.html', + styleUrls: ['./alarm-schedule.component.scss'], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AlarmScheduleComponent), + multi: true + }, { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => AlarmScheduleComponent), + multi: true + }], + standalone: false }) export class AlarmScheduleComponent implements ControlValueAccessor, Validator, OnInit { @Input() diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.ts b/ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.ts index b81c65dbcf..4445f45ca8 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.ts @@ -35,21 +35,22 @@ import { EntityId } from '@shared/models/id/entity-id'; import { takeUntil } from 'rxjs/operators'; @Component({ - selector: 'tb-create-alarm-rules', - templateUrl: './create-alarm-rules.component.html', - styleUrls: ['./create-alarm-rules.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => CreateAlarmRulesComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => CreateAlarmRulesComponent), - multi: true, - } - ] + selector: 'tb-create-alarm-rules', + templateUrl: './create-alarm-rules.component.html', + styleUrls: ['./create-alarm-rules.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CreateAlarmRulesComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => CreateAlarmRulesComponent), + multi: true, + } + ], + standalone: false }) export class CreateAlarmRulesComponent implements ControlValueAccessor, OnInit, Validator, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.ts b/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.ts index cf42c444d2..a282f1ee0b 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.ts @@ -34,21 +34,22 @@ import { UtilsService } from '@core/services/utils.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-device-profile-alarm', - templateUrl: './device-profile-alarm.component.html', - styleUrls: ['./device-profile-alarm.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DeviceProfileAlarmComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DeviceProfileAlarmComponent), - multi: true, - } - ] + selector: 'tb-device-profile-alarm', + templateUrl: './device-profile-alarm.component.html', + styleUrls: ['./device-profile-alarm.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceProfileAlarmComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DeviceProfileAlarmComponent), + multi: true, + } + ], + standalone: false }) export class DeviceProfileAlarmComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.ts b/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.ts index ff0f824cf1..14e8d0d32d 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.ts @@ -37,21 +37,22 @@ import { EntityId } from '@shared/models/id/entity-id'; import { takeUntil } from 'rxjs/operators'; @Component({ - selector: 'tb-device-profile-alarms', - templateUrl: './device-profile-alarms.component.html', - styleUrls: ['./device-profile-alarms.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DeviceProfileAlarmsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DeviceProfileAlarmsComponent), - multi: true, - } - ] + selector: 'tb-device-profile-alarms', + templateUrl: './device-profile-alarms.component.html', + styleUrls: ['./device-profile-alarms.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceProfileAlarmsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DeviceProfileAlarmsComponent), + multi: true, + } + ], + standalone: false }) export class DeviceProfileAlarmsComponent implements ControlValueAccessor, OnInit, Validator, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/edit-alarm-details-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/alarm/edit-alarm-details-dialog.component.ts index 4078930902..45f13a4487 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/edit-alarm-details-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/edit-alarm-details-dialog.component.ts @@ -31,10 +31,11 @@ export interface EditAlarmDetailsDialogData { } @Component({ - selector: 'tb-edit-alarm-details-dialog', - templateUrl: './edit-alarm-details-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: EditAlarmDetailsDialogComponent}], - styleUrls: [] + selector: 'tb-edit-alarm-details-dialog', + templateUrl: './edit-alarm-details-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: EditAlarmDetailsDialogComponent }], + styleUrls: [], + standalone: false }) export class EditAlarmDetailsDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/profile/asset-profile-autocomplete.component.ts b/ui-ngx/src/app/modules/home/components/profile/asset-profile-autocomplete.component.ts index 0c2a7bbd9f..79b4c6ed4d 100644 --- a/ui-ngx/src/app/modules/home/components/profile/asset-profile-autocomplete.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/asset-profile-autocomplete.component.ts @@ -51,14 +51,15 @@ import { getCurrentAuthUser } from '@core/auth/auth.selectors'; import { Authority } from '@shared/models/authority.enum'; @Component({ - selector: 'tb-asset-profile-autocomplete', - templateUrl: './asset-profile-autocomplete.component.html', - styleUrls: ['./asset-profile-autocomplete.component.scss'], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AssetProfileAutocompleteComponent), - multi: true - }] + selector: 'tb-asset-profile-autocomplete', + templateUrl: './asset-profile-autocomplete.component.html', + styleUrls: ['./asset-profile-autocomplete.component.scss'], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AssetProfileAutocompleteComponent), + multi: true + }], + standalone: false }) export class AssetProfileAutocompleteComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/profile/asset-profile-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/asset-profile-dialog.component.ts index 1b196536f1..11ba3aabf4 100644 --- a/ui-ngx/src/app/modules/home/components/profile/asset-profile-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/asset-profile-dialog.component.ts @@ -32,10 +32,11 @@ export interface AssetProfileDialogData { } @Component({ - selector: 'tb-asset-profile-dialog', - templateUrl: './asset-profile-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: AssetProfileDialogComponent}], - styleUrls: [] + selector: 'tb-asset-profile-dialog', + templateUrl: './asset-profile-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: AssetProfileDialogComponent }], + styleUrls: [], + standalone: false }) export class AssetProfileDialogComponent extends DialogComponent implements ErrorStateMatcher, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/profile/asset-profile.component.ts b/ui-ngx/src/app/modules/home/components/profile/asset-profile.component.ts index 7c78ea881f..18374dc7df 100644 --- a/ui-ngx/src/app/modules/home/components/profile/asset-profile.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/asset-profile.component.ts @@ -31,9 +31,10 @@ import { AssetProfile } from '@shared/models/asset.models'; import { RuleChainType } from '@shared/models/rule-chain.models'; @Component({ - selector: 'tb-asset-profile', - templateUrl: './asset-profile.component.html', - styleUrls: [] + selector: 'tb-asset-profile', + templateUrl: './asset-profile.component.html', + styleUrls: [], + standalone: false }) export class AssetProfileComponent extends EntityComponent { diff --git a/ui-ngx/src/app/modules/home/components/profile/device-profile-autocomplete.component.ts b/ui-ngx/src/app/modules/home/components/profile/device-profile-autocomplete.component.ts index a24219bb41..9989eee7ca 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device-profile-autocomplete.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device-profile-autocomplete.component.ts @@ -54,14 +54,15 @@ import { getCurrentAuthUser } from '@core/auth/auth.selectors'; import { Authority } from '@shared/models/authority.enum'; @Component({ - selector: 'tb-device-profile-autocomplete', - templateUrl: './device-profile-autocomplete.component.html', - styleUrls: ['./device-profile-autocomplete.component.scss'], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DeviceProfileAutocompleteComponent), - multi: true - }] + selector: 'tb-device-profile-autocomplete', + templateUrl: './device-profile-autocomplete.component.html', + styleUrls: ['./device-profile-autocomplete.component.scss'], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceProfileAutocompleteComponent), + multi: true + }], + standalone: false }) export class DeviceProfileAutocompleteComponent implements ControlValueAccessor, OnInit, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/profile/device-profile-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/device-profile-dialog.component.ts index 2f791f6cda..eacc40e4d8 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device-profile-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device-profile-dialog.component.ts @@ -32,10 +32,11 @@ export interface DeviceProfileDialogData { } @Component({ - selector: 'tb-device-profile-dialog', - templateUrl: './device-profile-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: DeviceProfileDialogComponent}], - styleUrls: [] + selector: 'tb-device-profile-dialog', + templateUrl: './device-profile-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: DeviceProfileDialogComponent }], + styleUrls: [], + standalone: false }) export class DeviceProfileDialogComponent extends DialogComponent implements ErrorStateMatcher, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/profile/device-profile-provision-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device-profile-provision-configuration.component.ts index 6ba2a62f0e..1da59bbc5c 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device-profile-provision-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device-profile-provision-configuration.component.ts @@ -40,21 +40,22 @@ import { TranslateService } from '@ngx-translate/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-device-profile-provision-configuration', - templateUrl: './device-profile-provision-configuration.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DeviceProfileProvisionConfigurationComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DeviceProfileProvisionConfigurationComponent), - multi: true, - } - ] + selector: 'tb-device-profile-provision-configuration', + templateUrl: './device-profile-provision-configuration.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceProfileProvisionConfigurationComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DeviceProfileProvisionConfigurationComponent), + multi: true, + } + ], + standalone: false }) export class DeviceProfileProvisionConfigurationComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/device-profile.component.ts b/ui-ngx/src/app/modules/home/components/profile/device-profile.component.ts index c7533cd09f..1c7c52ec32 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device-profile.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device-profile.component.ts @@ -46,9 +46,10 @@ import { RuleChainType } from '@shared/models/rule-chain.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-device-profile', - templateUrl: './device-profile.component.html', - styleUrls: [] + selector: 'tb-device-profile', + templateUrl: './device-profile.component.html', + styleUrls: [], + standalone: false }) export class DeviceProfileComponent extends EntityComponent { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/coap-device-profile-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/coap-device-profile-transport-configuration.component.ts index d264626399..72c1552978 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/coap-device-profile-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/coap-device-profile-transport-configuration.component.ts @@ -46,21 +46,22 @@ import { takeUntil } from 'rxjs/operators'; import { PowerMode } from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models'; @Component({ - selector: 'tb-coap-device-profile-transport-configuration', - templateUrl: './coap-device-profile-transport-configuration.component.html', - styleUrls: ['./coap-device-profile-transport-configuration.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => CoapDeviceProfileTransportConfigurationComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => CoapDeviceProfileTransportConfigurationComponent), - multi: true - } - ] + selector: 'tb-coap-device-profile-transport-configuration', + templateUrl: './coap-device-profile-transport-configuration.component.html', + styleUrls: ['./coap-device-profile-transport-configuration.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CoapDeviceProfileTransportConfigurationComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => CoapDeviceProfileTransportConfigurationComponent), + multi: true + } + ], + standalone: false }) export class CoapDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, OnInit, OnDestroy, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/common/power-mode-setting.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/common/power-mode-setting.component.ts index 7b653f43e0..ec4576a162 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/common/power-mode-setting.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/common/power-mode-setting.component.ts @@ -26,9 +26,10 @@ import { takeUntil } from 'rxjs/operators'; import { Subject } from 'rxjs'; @Component({ - selector: 'tb-power-mode-settings', - templateUrl: './power-mode-setting.component.html', - styleUrls: [] + selector: 'tb-power-mode-settings', + templateUrl: './power-mode-setting.component.html', + styleUrls: [], + standalone: false }) export class PowerModeSettingComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/common/time-unit-select.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/common/time-unit-select.component.ts index 49f84c14fa..709d4ececa 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/common/time-unit-select.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/common/time-unit-select.component.ts @@ -44,21 +44,22 @@ interface FormGroupModel { } @Component({ - selector: 'tb-time-unit-select', - templateUrl: './time-unit-select.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimeUnitSelectComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => TimeUnitSelectComponent), - multi: true - } - ] + selector: 'tb-time-unit-select', + templateUrl: './time-unit-select.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeUnitSelectComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => TimeUnitSelectComponent), + multi: true + } + ], + standalone: false }) export class TimeUnitSelectComponent implements OnInit, OnDestroy, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/default-device-profile-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/default-device-profile-configuration.component.ts index 0f082fd97a..e9c5ef36dc 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/default-device-profile-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/default-device-profile-configuration.component.ts @@ -26,14 +26,15 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-default-device-profile-configuration', - templateUrl: './default-device-profile-configuration.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DefaultDeviceProfileConfigurationComponent), - multi: true - }] + selector: 'tb-default-device-profile-configuration', + templateUrl: './default-device-profile-configuration.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DefaultDeviceProfileConfigurationComponent), + multi: true + }], + standalone: false }) export class DefaultDeviceProfileConfigurationComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/default-device-profile-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/default-device-profile-transport-configuration.component.ts index 1b7db15d7c..dcb8abc4a3 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/default-device-profile-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/default-device-profile-transport-configuration.component.ts @@ -32,21 +32,22 @@ import { DefaultDeviceProfileTransportConfiguration, DeviceTransportType } from import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-default-device-profile-transport-configuration', - templateUrl: './default-device-profile-transport-configuration.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DefaultDeviceProfileTransportConfigurationComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DefaultDeviceProfileTransportConfigurationComponent), - multi: true - } - ] + selector: 'tb-default-device-profile-transport-configuration', + templateUrl: './default-device-profile-transport-configuration.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DefaultDeviceProfileTransportConfigurationComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DefaultDeviceProfileTransportConfigurationComponent), + multi: true + } + ], + standalone: false }) export class DefaultDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/device-profile-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/device-profile-configuration.component.ts index 80d2a8e0d7..5e6cc15409 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/device-profile-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/device-profile-configuration.component.ts @@ -24,14 +24,15 @@ import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ - selector: 'tb-device-profile-configuration', - templateUrl: './device-profile-configuration.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DeviceProfileConfigurationComponent), - multi: true - }] + selector: 'tb-device-profile-configuration', + templateUrl: './device-profile-configuration.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceProfileConfigurationComponent), + multi: true + }], + standalone: false }) export class DeviceProfileConfigurationComponent implements ControlValueAccessor, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.ts index 8ef5804433..574e14ac7e 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.ts @@ -32,21 +32,22 @@ import { deepClone } from '@core/utils'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-device-profile-transport-configuration', - templateUrl: './device-profile-transport-configuration.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DeviceProfileTransportConfigurationComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DeviceProfileTransportConfigurationComponent), - multi: true, - } - ] + selector: 'tb-device-profile-transport-configuration', + templateUrl: './device-profile-transport-configuration.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceProfileTransportConfigurationComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DeviceProfileTransportConfigurationComponent), + multi: true, + } + ], + standalone: false }) export class DeviceProfileTransportConfigurationComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-attributes-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-attributes-dialog.component.ts index 595b62ffde..c61622963f 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-attributes-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-attributes-dialog.component.ts @@ -32,10 +32,11 @@ export interface Lwm2mAttributesDialogData { } @Component({ - selector: 'tb-lwm2m-attributes-dialog', - templateUrl: './lwm2m-attributes-dialog.component.html', - styleUrls: [], - providers: [{provide: ErrorStateMatcher, useExisting: Lwm2mAttributesDialogComponent}], + selector: 'tb-lwm2m-attributes-dialog', + templateUrl: './lwm2m-attributes-dialog.component.html', + styleUrls: [], + providers: [{ provide: ErrorStateMatcher, useExisting: Lwm2mAttributesDialogComponent }], + standalone: false }) export class Lwm2mAttributesDialogComponent extends DialogComponent implements ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-attributes-key-list.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-attributes-key-list.component.ts index d17b37b5fa..0d6cf4df1d 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-attributes-key-list.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-attributes-key-list.component.ts @@ -41,21 +41,22 @@ import { PageComponent } from '@shared/components/page.component'; import { takeUntil } from 'rxjs/operators'; @Component({ - selector: 'tb-lwm2m-attributes-key-list', - templateUrl: './lwm2m-attributes-key-list.component.html', - styleUrls: ['./lwm2m-attributes-key-list.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Lwm2mAttributesKeyListComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => Lwm2mAttributesKeyListComponent), - multi: true, - } - ] + selector: 'tb-lwm2m-attributes-key-list', + templateUrl: './lwm2m-attributes-key-list.component.html', + styleUrls: ['./lwm2m-attributes-key-list.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Lwm2mAttributesKeyListComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => Lwm2mAttributesKeyListComponent), + multi: true, + } + ], + standalone: false }) export class Lwm2mAttributesKeyListComponent extends PageComponent implements ControlValueAccessor, OnDestroy, OnDestroy, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-attributes.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-attributes.component.ts index af12a85389..a3a29e6961 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-attributes.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-attributes.component.ts @@ -25,14 +25,15 @@ import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ - selector: 'tb-profile-lwm2m-attributes', - templateUrl: './lwm2m-attributes.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Lwm2mAttributesComponent), - multi: true - }] + selector: 'tb-profile-lwm2m-attributes', + templateUrl: './lwm2m-attributes.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Lwm2mAttributesComponent), + multi: true + }], + standalone: false }) export class Lwm2mAttributesComponent implements ControlValueAccessor, OnDestroy { attributesFormGroup: UntypedFormGroup; diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component.ts index d9ca2426a6..e50fe79cda 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component.ts @@ -27,8 +27,9 @@ import { } from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models'; @Component({ - selector: 'tb-profile-lwm2m-bootstrap-add-config-server-dialog', - templateUrl: './lwm2m-bootstrap-add-config-server-dialog.component.html' + selector: 'tb-profile-lwm2m-bootstrap-add-config-server-dialog', + templateUrl: './lwm2m-bootstrap-add-config-server-dialog.component.html', + standalone: false }) export class Lwm2mBootstrapAddConfigServerDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.ts index a64e262213..2f0fd69102 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.ts @@ -35,20 +35,21 @@ import { DeviceProfileService } from '@core/http/device-profile.service'; import { Lwm2mSecurityType } from '@shared/models/lwm2m-security-config.models'; @Component({ - selector: 'tb-profile-lwm2m-bootstrap-config-servers', - templateUrl: './lwm2m-bootstrap-config-servers.component.html', - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Lwm2mBootstrapConfigServersComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => Lwm2mBootstrapConfigServersComponent), - multi: true, - } - ] + selector: 'tb-profile-lwm2m-bootstrap-config-servers', + templateUrl: './lwm2m-bootstrap-config-servers.component.html', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Lwm2mBootstrapConfigServersComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => Lwm2mBootstrapConfigServersComponent), + multi: true, + } + ], + standalone: false }) export class Lwm2mBootstrapConfigServersComponent implements OnInit, ControlValueAccessor, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.ts index dc523e1b87..4464880588 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.ts @@ -41,20 +41,21 @@ import { import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ - selector: 'tb-profile-lwm2m-device-config-server', - templateUrl: './lwm2m-device-config-server.component.html', - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Lwm2mDeviceConfigServerComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => Lwm2mDeviceConfigServerComponent), - multi: true - }, - ] + selector: 'tb-profile-lwm2m-device-config-server', + templateUrl: './lwm2m-device-config-server.component.html', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Lwm2mDeviceConfigServerComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => Lwm2mDeviceConfigServerComponent), + multi: true + }, + ], + standalone: false }) export class Lwm2mDeviceConfigServerComponent implements OnInit, ControlValueAccessor, Validator, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts index 18eb3581bd..010b3d528b 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts @@ -58,20 +58,22 @@ import { DialogService } from '@core/services/dialog.service'; import { TranslateService } from '@ngx-translate/core'; @Component({ - selector: 'tb-profile-lwm2m-device-transport-configuration', - templateUrl: './lwm2m-device-profile-transport-configuration.component.html', - styleUrls: ['./lwm2m-device-profile-transport-configuration.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Lwm2mDeviceProfileTransportConfigurationComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => Lwm2mDeviceProfileTransportConfigurationComponent), - multi: true - }] + selector: 'tb-profile-lwm2m-device-transport-configuration', + templateUrl: './lwm2m-device-profile-transport-configuration.component.html', + styleUrls: ['./lwm2m-device-profile-transport-configuration.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Lwm2mDeviceProfileTransportConfigurationComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => Lwm2mDeviceProfileTransportConfigurationComponent), + multi: true + } + ], + standalone: false }) export class Lwm2mDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, Validator, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-dialog.component.ts index 2a2db7551b..0b8c23bbe4 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-dialog.component.ts @@ -29,8 +29,9 @@ export interface Lwm2mObjectAddInstancesData { } @Component({ - selector: 'tb-lwm2m-object-add-instances', - templateUrl: './lwm2m-object-add-instances-dialog.component.html' + selector: 'tb-lwm2m-object-add-instances', + templateUrl: './lwm2m-object-add-instances-dialog.component.html', + standalone: false }) export class Lwm2mObjectAddInstancesDialogComponent extends DialogComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-list.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-list.component.ts index f139d40d2f..9c9d25e2f0 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-list.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-list.component.ts @@ -29,19 +29,21 @@ import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; import { MatChipInputEvent } from '@angular/material/chips'; @Component({ - selector: 'tb-profile-lwm2m-object-add-instances-list', - templateUrl: './lwm2m-object-add-instances-list.component.html', - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Lwm2mObjectAddInstancesListComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => Lwm2mObjectAddInstancesListComponent), - multi: true - }] + selector: 'tb-profile-lwm2m-object-add-instances-list', + templateUrl: './lwm2m-object-add-instances-list.component.html', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Lwm2mObjectAddInstancesListComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => Lwm2mObjectAddInstancesListComponent), + multi: true + } + ], + standalone: false }) export class Lwm2mObjectAddInstancesListComponent implements ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.ts index 2db720da8c..3aafd2d56f 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.ts @@ -37,20 +37,21 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatAutocompleteTrigger } from '@angular/material/autocomplete'; @Component({ - selector: 'tb-profile-lwm2m-object-list', - templateUrl: './lwm2m-object-list.component.html', - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Lwm2mObjectListComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => Lwm2mObjectListComponent), - multi: true - } - ] + selector: 'tb-profile-lwm2m-object-list', + templateUrl: './lwm2m-object-list.component.html', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Lwm2mObjectListComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => Lwm2mObjectListComponent), + multi: true + } + ], + standalone: false }) export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-instances.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-instances.component.ts index ecfeb9cf55..1bdd5cba82 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-instances.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-instances.component.ts @@ -34,21 +34,22 @@ import { TranslateService } from '@ngx-translate/core'; import { Subscription } from 'rxjs'; @Component({ - selector: 'tb-profile-lwm2m-observe-attr-telemetry-instances', - templateUrl: './lwm2m-observe-attr-telemetry-instances.component.html', - styleUrls: [ './lwm2m-observe-attr-telemetry-instances.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Lwm2mObserveAttrTelemetryInstancesComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => Lwm2mObserveAttrTelemetryInstancesComponent), - multi: true - } - ] + selector: 'tb-profile-lwm2m-observe-attr-telemetry-instances', + templateUrl: './lwm2m-observe-attr-telemetry-instances.component.html', + styleUrls: ['./lwm2m-observe-attr-telemetry-instances.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Lwm2mObserveAttrTelemetryInstancesComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => Lwm2mObserveAttrTelemetryInstancesComponent), + multi: true + } + ], + standalone: false }) export class Lwm2mObserveAttrTelemetryInstancesComponent implements ControlValueAccessor, Validator, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-resources.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-resources.component.ts index d3686b002f..0e107d43bf 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-resources.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-resources.component.ts @@ -33,21 +33,22 @@ import { combineLatest, Subject } from 'rxjs'; import { startWith, takeUntil } from 'rxjs/operators'; @Component({ - selector: 'tb-profile-lwm2m-observe-attr-telemetry-resource', - templateUrl: './lwm2m-observe-attr-telemetry-resources.component.html', - styleUrls: ['./lwm2m-observe-attr-telemetry-resources.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Lwm2mObserveAttrTelemetryResourcesComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => Lwm2mObserveAttrTelemetryResourcesComponent), - multi: true - } - ] + selector: 'tb-profile-lwm2m-observe-attr-telemetry-resource', + templateUrl: './lwm2m-observe-attr-telemetry-resources.component.html', + styleUrls: ['./lwm2m-observe-attr-telemetry-resources.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Lwm2mObserveAttrTelemetryResourcesComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => Lwm2mObserveAttrTelemetryResourcesComponent), + multi: true + } + ], + standalone: false }) export class Lwm2mObserveAttrTelemetryResourcesComponent implements ControlValueAccessor, OnDestroy, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.ts index 2de0b0f0a7..c2d5a21537 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.ts @@ -39,21 +39,22 @@ import _ from 'lodash'; import { Subscription } from 'rxjs'; @Component({ - selector: 'tb-profile-lwm2m-observe-attr-telemetry', - templateUrl: './lwm2m-observe-attr-telemetry.component.html', - styleUrls: [ './lwm2m-observe-attr-telemetry.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Lwm2mObserveAttrTelemetryComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => Lwm2mObserveAttrTelemetryComponent), - multi: true - } - ] + selector: 'tb-profile-lwm2m-observe-attr-telemetry', + templateUrl: './lwm2m-observe-attr-telemetry.component.html', + styleUrls: ['./lwm2m-observe-attr-telemetry.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Lwm2mObserveAttrTelemetryComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => Lwm2mObserveAttrTelemetryComponent), + multi: true + } + ], + standalone: false }) export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor, OnDestroy, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.ts index 9ade4171bf..bc997d6960 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.ts @@ -44,21 +44,22 @@ import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ - selector: 'tb-mqtt-device-profile-transport-configuration', - templateUrl: './mqtt-device-profile-transport-configuration.component.html', - styleUrls: ['./mqtt-device-profile-transport-configuration.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MqttDeviceProfileTransportConfigurationComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MqttDeviceProfileTransportConfigurationComponent), - multi: true - } - ] + selector: 'tb-mqtt-device-profile-transport-configuration', + templateUrl: './mqtt-device-profile-transport-configuration.component.html', + styleUrls: ['./mqtt-device-profile-transport-configuration.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MqttDeviceProfileTransportConfigurationComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MqttDeviceProfileTransportConfigurationComponent), + multi: true + } + ], + standalone: false }) export class MqttDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, OnInit, OnDestroy, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-communication-config.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-communication-config.component.ts index 6811f636dd..544fcfdac6 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-communication-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-communication-config.component.ts @@ -32,20 +32,22 @@ import { isUndefinedOrNull } from '@core/utils'; import { takeUntil } from 'rxjs/operators'; @Component({ - selector: 'tb-snmp-device-profile-communication-config', - templateUrl: './snmp-device-profile-communication-config.component.html', - styleUrls: ['./snmp-device-profile-communication-config.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => SnmpDeviceProfileCommunicationConfigComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => SnmpDeviceProfileCommunicationConfigComponent), - multi: true - }] + selector: 'tb-snmp-device-profile-communication-config', + templateUrl: './snmp-device-profile-communication-config.component.html', + styleUrls: ['./snmp-device-profile-communication-config.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => SnmpDeviceProfileCommunicationConfigComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => SnmpDeviceProfileCommunicationConfigComponent), + multi: true + } + ], + standalone: false }) export class SnmpDeviceProfileCommunicationConfigComponent implements OnInit, OnDestroy, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-mapping.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-mapping.component.ts index b18a1c37f0..66f8c0737e 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-mapping.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-mapping.component.ts @@ -34,20 +34,22 @@ import { isUndefinedOrNull } from '@core/utils'; import { takeUntil } from 'rxjs/operators'; @Component({ - selector: 'tb-snmp-device-profile-mapping', - templateUrl: './snmp-device-profile-mapping.component.html', - styleUrls: ['./snmp-device-profile-mapping.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => SnmpDeviceProfileMappingComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => SnmpDeviceProfileMappingComponent), - multi: true - }] + selector: 'tb-snmp-device-profile-mapping', + templateUrl: './snmp-device-profile-mapping.component.html', + styleUrls: ['./snmp-device-profile-mapping.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => SnmpDeviceProfileMappingComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => SnmpDeviceProfileMappingComponent), + multi: true + } + ], + standalone: false }) export class SnmpDeviceProfileMappingComponent implements OnInit, OnDestroy, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-transport-configuration.component.ts index e2681319c2..15338a385d 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-transport-configuration.component.ts @@ -42,20 +42,22 @@ export interface OidMappingConfiguration { } @Component({ - selector: 'tb-snmp-device-profile-transport-configuration', - templateUrl: './snmp-device-profile-transport-configuration.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => SnmpDeviceProfileTransportConfigurationComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => SnmpDeviceProfileTransportConfigurationComponent), - multi: true - }] + selector: 'tb-snmp-device-profile-transport-configuration', + templateUrl: './snmp-device-profile-transport-configuration.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => SnmpDeviceProfileTransportConfigurationComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => SnmpDeviceProfileTransportConfigurationComponent), + multi: true + } + ], + standalone: false }) export class SnmpDeviceProfileTransportConfigurationComponent implements OnInit, OnDestroy, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.ts b/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.ts index c2166ae859..aa7bebaba8 100644 --- a/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.ts @@ -37,21 +37,22 @@ import { guid } from '@core/utils'; import { takeUntil } from 'rxjs/operators'; @Component({ - selector: 'tb-tenant-profile-queues', - templateUrl: './tenant-profile-queues.component.html', - styleUrls: ['./tenant-profile-queues.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TenantProfileQueuesComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => TenantProfileQueuesComponent), - multi: true, - } - ] + selector: 'tb-tenant-profile-queues', + templateUrl: './tenant-profile-queues.component.html', + styleUrls: ['./tenant-profile-queues.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TenantProfileQueuesComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => TenantProfileQueuesComponent), + multi: true, + } + ], + standalone: false }) export class TenantProfileQueuesComponent implements ControlValueAccessor, Validator, OnDestroy, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant-profile-autocomplete.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant-profile-autocomplete.component.ts index 207eb19253..1bd785cf7a 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant-profile-autocomplete.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant-profile-autocomplete.component.ts @@ -37,14 +37,15 @@ import { emptyPageData } from '@shared/models/page/page-data'; import { getEntityDetailsPageURL } from '@core/utils'; @Component({ - selector: 'tb-tenant-profile-autocomplete', - templateUrl: './tenant-profile-autocomplete.component.html', - styleUrls: ['./tenant-profile-autocomplete.component.scss'], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TenantProfileAutocompleteComponent), - multi: true - }] + selector: 'tb-tenant-profile-autocomplete', + templateUrl: './tenant-profile-autocomplete.component.html', + styleUrls: ['./tenant-profile-autocomplete.component.scss'], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TenantProfileAutocompleteComponent), + multi: true + }], + standalone: false }) export class TenantProfileAutocompleteComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant-profile-data.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant-profile-data.component.ts index 543fdf9e1a..695fa2ceca 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant-profile-data.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant-profile-data.component.ts @@ -23,14 +23,15 @@ import { TenantProfileData } from '@shared/models/tenant.model'; import { Subscription } from 'rxjs'; @Component({ - selector: 'tb-tenant-profile-data', - templateUrl: './tenant-profile-data.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TenantProfileDataComponent), - multi: true - }] + selector: 'tb-tenant-profile-data', + templateUrl: './tenant-profile-data.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TenantProfileDataComponent), + multi: true + }], + standalone: false }) export class TenantProfileDataComponent implements ControlValueAccessor, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant-profile-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant-profile-dialog.component.ts index 4f10376eaa..67ca86a215 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant-profile-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant-profile-dialog.component.ts @@ -32,10 +32,11 @@ export interface TenantProfileDialogData { } @Component({ - selector: 'tb-tenant-profile-dialog', - templateUrl: './tenant-profile-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: TenantProfileDialogComponent}], - styleUrls: ['tenant-profile-dialog.component.scss'] + selector: 'tb-tenant-profile-dialog', + templateUrl: './tenant-profile-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: TenantProfileDialogComponent }], + styleUrls: ['tenant-profile-dialog.component.scss'], + standalone: false }) export class TenantProfileDialogComponent extends DialogComponent implements ErrorStateMatcher, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant-profile.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant-profile.component.ts index 5025ce556a..4ae02c8ac8 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant-profile.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant-profile.component.ts @@ -27,9 +27,10 @@ import { guid } from '@core/utils'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-tenant-profile', - templateUrl: './tenant-profile.component.html', - styleUrls: ['./tenant-profile.component.scss'] + selector: 'tb-tenant-profile', + templateUrl: './tenant-profile.component.html', + styleUrls: ['./tenant-profile.component.scss'], + standalone: false }) export class TenantProfileComponent extends EntityComponent { diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts index 4f1efa32d2..90f38ba13d 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts @@ -26,14 +26,15 @@ import { takeUntil } from 'rxjs/operators'; import { Subject } from 'rxjs'; @Component({ - selector: 'tb-default-tenant-profile-configuration', - templateUrl: './default-tenant-profile-configuration.component.html', - styleUrls: ['./default-tenant-profile-configuration.component.scss'], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DefaultTenantProfileConfigurationComponent), - multi: true - }] + selector: 'tb-default-tenant-profile-configuration', + templateUrl: './default-tenant-profile-configuration.component.html', + styleUrls: ['./default-tenant-profile-configuration.component.scss'], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DefaultTenantProfileConfigurationComponent), + multi: true + }], + standalone: false }) export class DefaultTenantProfileConfigurationComponent implements ControlValueAccessor, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts index abca908623..a7ada0090b 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts @@ -29,7 +29,8 @@ export interface RateLimitsDetailsDialogData { } @Component({ - templateUrl: './rate-limits-details-dialog.component.html' + templateUrl: './rate-limits-details-dialog.component.html', + standalone: false }) export class RateLimitsDetailsDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts index 4434259bb4..7b58242e4d 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts @@ -33,21 +33,22 @@ import { isDefinedAndNotNull } from '@core/utils'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-rate-limits-list', - templateUrl: './rate-limits-list.component.html', - styleUrls: ['./rate-limits-list.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => RateLimitsListComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => RateLimitsListComponent), - multi: true - } - ] + selector: 'tb-rate-limits-list', + templateUrl: './rate-limits-list.component.html', + styleUrls: ['./rate-limits-list.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RateLimitsListComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => RateLimitsListComponent), + multi: true + } + ], + standalone: false }) export class RateLimitsListComponent implements ControlValueAccessor, Validator, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts index 16b00f0d6e..d5195cbad9 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts @@ -19,9 +19,10 @@ import { TranslateService } from '@ngx-translate/core'; import { RateLimits, rateLimitsArrayToHtml } from './rate-limits.models'; @Component({ - selector: 'tb-rate-limits-text', - templateUrl: './rate-limits-text.component.html', - styleUrls: ['./rate-limits-text.component.scss'] + selector: 'tb-rate-limits-text', + templateUrl: './rate-limits-text.component.html', + styleUrls: ['./rate-limits-text.component.scss'], + standalone: false }) export class RateLimitsTextComponent implements OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts index 6e03646bba..397253b753 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts @@ -39,21 +39,22 @@ import { import { isDefined } from '@core/utils'; @Component({ - selector: 'tb-rate-limits', - templateUrl: './rate-limits.component.html', - styleUrls: ['./rate-limits.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => RateLimitsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => RateLimitsComponent), - multi: true, - } - ] + selector: 'tb-rate-limits', + templateUrl: './rate-limits.component.html', + styleUrls: ['./rate-limits.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RateLimitsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => RateLimitsComponent), + multi: true, + } + ], + standalone: false }) export class RateLimitsComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/tenant-profile-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/tenant-profile-configuration.component.ts index 0117706d12..a140a7053d 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/tenant-profile-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/tenant-profile-configuration.component.ts @@ -24,14 +24,15 @@ import { TenantProfileConfiguration, TenantProfileType } from '@shared/models/te import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-tenant-profile-configuration', - templateUrl: './tenant-profile-configuration.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TenantProfileConfigurationComponent), - multi: true - }] + selector: 'tb-tenant-profile-configuration', + templateUrl: './tenant-profile-configuration.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TenantProfileConfigurationComponent), + multi: true + }], + standalone: false }) export class TenantProfileConfigurationComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/queue/queue-form.component.ts b/ui-ngx/src/app/modules/home/components/queue/queue-form.component.ts index 2760226998..e3b22095c4 100644 --- a/ui-ngx/src/app/modules/home/components/queue/queue-form.component.ts +++ b/ui-ngx/src/app/modules/home/components/queue/queue-form.component.ts @@ -38,21 +38,22 @@ import { Subscription } from 'rxjs'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-queue-form', - templateUrl: './queue-form.component.html', - styleUrls: ['./queue-form.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => QueueFormComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => QueueFormComponent), - multi: true, - } - ] + selector: 'tb-queue-form', + templateUrl: './queue-form.component.html', + styleUrls: ['./queue-form.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => QueueFormComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => QueueFormComponent), + multi: true, + } + ], + standalone: false }) export class QueueFormComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/relation/relation-dialog.component.ts b/ui-ngx/src/app/modules/home/components/relation/relation-dialog.component.ts index c9a4fedb69..362bb73dab 100644 --- a/ui-ngx/src/app/modules/home/components/relation/relation-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/relation/relation-dialog.component.ts @@ -44,10 +44,11 @@ export interface RelationDialogData { } @Component({ - selector: 'tb-relation-dialog', - templateUrl: './relation-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: RelationDialogComponent}], - styleUrls: ['./relation-dialog.component.scss'] + selector: 'tb-relation-dialog', + templateUrl: './relation-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: RelationDialogComponent }], + styleUrls: ['./relation-dialog.component.scss'], + standalone: false }) export class RelationDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/relation/relation-filters.component.ts b/ui-ngx/src/app/modules/home/components/relation/relation-filters.component.ts index 76ca033183..f8e1e796a5 100644 --- a/ui-ngx/src/app/modules/home/components/relation/relation-filters.component.ts +++ b/ui-ngx/src/app/modules/home/components/relation/relation-filters.component.ts @@ -33,16 +33,17 @@ import { takeUntil } from 'rxjs/operators'; import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ - selector: 'tb-relation-filters', - templateUrl: './relation-filters.component.html', - styleUrls: ['./relation-filters.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => RelationFiltersComponent), - multi: true - } - ] + selector: 'tb-relation-filters', + templateUrl: './relation-filters.component.html', + styleUrls: ['./relation-filters.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RelationFiltersComponent), + multi: true + } + ], + standalone: false }) export class RelationFiltersComponent extends PageComponent implements ControlValueAccessor, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/relation/relation-table.component.ts b/ui-ngx/src/app/modules/home/components/relation/relation-table.component.ts index f5dcd97032..00b10e401a 100644 --- a/ui-ngx/src/app/modules/home/components/relation/relation-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/relation/relation-table.component.ts @@ -52,10 +52,11 @@ import { hidePageSizePixelValue } from '@shared/models/constants'; import { FormBuilder } from '@angular/forms'; @Component({ - selector: 'tb-relation-table', - templateUrl: './relation-table.component.html', - styleUrls: ['./relation-table.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-relation-table', + templateUrl: './relation-table.component.html', + styleUrls: ['./relation-table.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: false }) export class RelationTableComponent extends PageComponent implements AfterViewInit, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/resources/resources-dialog.component.ts b/ui-ngx/src/app/modules/home/components/resources/resources-dialog.component.ts index fb20a0fe26..3cd2a7f790 100644 --- a/ui-ngx/src/app/modules/home/components/resources/resources-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/resources/resources-dialog.component.ts @@ -34,10 +34,11 @@ export interface ResourcesDialogData { } @Component({ - selector: 'tb-resources-dialog', - templateUrl: './resources-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: ResourcesDialogComponent}], - styleUrls: ['./resources-dialog.component.scss'] + selector: 'tb-resources-dialog', + templateUrl: './resources-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: ResourcesDialogComponent }], + styleUrls: ['./resources-dialog.component.scss'], + standalone: false }) export class ResourcesDialogComponent extends DialogComponent implements ErrorStateMatcher, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/resources/resources-library.component.ts b/ui-ngx/src/app/modules/home/components/resources/resources-library.component.ts index cd2998af82..8bb8f05359 100644 --- a/ui-ngx/src/app/modules/home/components/resources/resources-library.component.ts +++ b/ui-ngx/src/app/modules/home/components/resources/resources-library.component.ts @@ -35,8 +35,9 @@ import { isDefinedAndNotNull } from '@core/utils'; import { getCurrentAuthState } from '@core/auth/auth.selectors'; @Component({ - selector: 'tb-resources-library', - templateUrl: './resources-library.component.html' + selector: 'tb-resources-library', + templateUrl: './resources-library.component.html', + standalone: false }) export class ResourcesLibraryComponent extends EntityComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/router-tabs.component.ts b/ui-ngx/src/app/modules/home/components/router-tabs.component.ts index a4e6a883b6..b75b90e373 100644 --- a/ui-ngx/src/app/modules/home/components/router-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/components/router-tabs.component.ts @@ -28,9 +28,10 @@ import { TbAnchorComponent } from '@shared/components/tb-anchor.component'; import { getCurrentAuthUser } from '@core/auth/auth.selectors'; @Component({ - selector: 'tb-router-tabs', - templateUrl: './router-tabs.component.html', - styleUrls: ['./router-tabs.component.scss'] + selector: 'tb-router-tabs', + templateUrl: './router-tabs.component.html', + styleUrls: ['./router-tabs.component.scss'], + standalone: false }) export class RouterTabsComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/rule-chain/rule-chain-autocomplete.component.ts b/ui-ngx/src/app/modules/home/components/rule-chain/rule-chain-autocomplete.component.ts index e6176603c3..b0d83cac46 100644 --- a/ui-ngx/src/app/modules/home/components/rule-chain/rule-chain-autocomplete.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-chain/rule-chain-autocomplete.component.ts @@ -33,14 +33,15 @@ import { RuleChainType } from '@app/shared/models/rule-chain.models'; import { getEntityDetailsPageURL } from '@core/utils'; @Component({ - selector: 'tb-rule-chain-autocomplete', - templateUrl: './rule-chain-autocomplete.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => RuleChainAutocompleteComponent), - multi: true - }] + selector: 'tb-rule-chain-autocomplete', + templateUrl: './rule-chain-autocomplete.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RuleChainAutocompleteComponent), + multi: true + }], + standalone: false }) export class RuleChainAutocompleteComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/advanced-processing-setting-row.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/advanced-processing-setting-row.component.ts index 7e73655529..22cdec0c82 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/advanced-processing-setting-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/advanced-processing-setting-row.component.ts @@ -34,17 +34,18 @@ import { isDefinedAndNotNull } from '@core/utils'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-advanced-processing-setting-row', - templateUrl: './advanced-processing-setting-row.component.html', - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AdvancedProcessingSettingRowComponent), - multi: true - },{ - provide: NG_VALIDATORS, - useExisting: forwardRef(() => AdvancedProcessingSettingRowComponent), - multi: true - }] + selector: 'tb-advanced-processing-setting-row', + templateUrl: './advanced-processing-setting-row.component.html', + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AdvancedProcessingSettingRowComponent), + multi: true + }, { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => AdvancedProcessingSettingRowComponent), + multi: true + }], + standalone: false }) export class AdvancedProcessingSettingRowComponent implements ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/advanced-processing-setting.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/advanced-processing-setting.component.ts index 3cd880cedd..6a8ef33a56 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/advanced-processing-setting.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/advanced-processing-setting.component.ts @@ -30,17 +30,18 @@ import { coerceBoolean } from '@shared/decorators/coercion'; import { AttributeAdvancedProcessingStrategy } from '@home/components/rule-node/action/attributes-config.model'; @Component({ - selector: 'tb-advanced-processing-settings', - templateUrl: './advanced-processing-setting.component.html', - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AdvancedProcessingSettingComponent), - multi: true - },{ - provide: NG_VALIDATORS, - useExisting: forwardRef(() => AdvancedProcessingSettingComponent), - multi: true - }] + selector: 'tb-advanced-processing-settings', + templateUrl: './advanced-processing-setting.component.html', + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AdvancedProcessingSettingComponent), + multi: true + }, { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => AdvancedProcessingSettingComponent), + multi: true + }], + standalone: false }) export class AdvancedProcessingSettingComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/assign-customer-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/assign-customer-config.component.ts index 0a67f7ba56..c844cd114b 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/assign-customer-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/assign-customer-config.component.ts @@ -19,9 +19,10 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-action-node-assign-to-customer-config', - templateUrl: './assign-customer-config.component.html', - styleUrls: [] + selector: 'tb-action-node-assign-to-customer-config', + templateUrl: './assign-customer-config.component.html', + styleUrls: [], + standalone: false }) export class AssignCustomerConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.ts index 13deb3afda..ab43627104 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.ts @@ -33,9 +33,10 @@ import { } from '@home/components/rule-node/action/attributes-config.model'; @Component({ - selector: 'tb-action-node-attributes-config', - templateUrl: './attributes-config.component.html', - styleUrls: [] + selector: 'tb-action-node-attributes-config', + templateUrl: './attributes-config.component.html', + styleUrls: [], + standalone: false }) export class AttributesConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/clear-alarm-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/clear-alarm-config.component.ts index fdc7883fec..812f50955a 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/clear-alarm-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/clear-alarm-config.component.ts @@ -28,9 +28,10 @@ import type { JsFuncComponent } from '@app/shared/components/js-func.component'; import { DebugRuleNodeEventBody } from '@shared/models/event.models'; @Component({ - selector: 'tb-action-node-clear-alarm-config', - templateUrl: './clear-alarm-config.component.html', - styleUrls: [] + selector: 'tb-action-node-clear-alarm-config', + templateUrl: './clear-alarm-config.component.html', + styleUrls: [], + standalone: false }) export class ClearAlarmConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.ts index f4ec7424aa..cd2122a8dd 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.ts @@ -32,9 +32,10 @@ import { DebugRuleNodeEventBody } from '@shared/models/event.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-action-node-create-alarm-config', - templateUrl: './create-alarm-config.component.html', - styleUrls: [] + selector: 'tb-action-node-create-alarm-config', + templateUrl: './create-alarm-config.component.html', + styleUrls: [], + standalone: false }) export class CreateAlarmConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.ts index 40fce452a9..5d3e85e565 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.ts @@ -21,9 +21,10 @@ import { EntitySearchDirection } from '@app/shared/models/relation.models'; import { EntityType } from '@app/shared/models/entity-type.models'; @Component({ - selector: 'tb-action-node-create-relation-config', - templateUrl: './create-relation-config.component.html', - styleUrls: [] + selector: 'tb-action-node-create-relation-config', + templateUrl: './create-relation-config.component.html', + styleUrls: [], + standalone: false }) export class CreateRelationConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.ts index 79e27e594f..565b5e9dea 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.ts @@ -23,9 +23,10 @@ import { AttributeScope, telemetryTypeTranslations } from '@shared/models/teleme import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-action-node-delete-attributes-config', - templateUrl: './delete-attributes-config.component.html', - styleUrls: [] + selector: 'tb-action-node-delete-attributes-config', + templateUrl: './delete-attributes-config.component.html', + styleUrls: [], + standalone: false }) export class DeleteAttributesConfigComponent extends RuleNodeConfigurationComponent { @ViewChild('attributeChipList') attributeChipList: MatChipGrid; diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.ts index d7839e1f23..606035bd08 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.ts @@ -21,9 +21,10 @@ import { EntitySearchDirection } from '@app/shared/models/relation.models'; import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; @Component({ - selector: 'tb-action-node-delete-relation-config', - templateUrl: './delete-relation-config.component.html', - styleUrls: [] + selector: 'tb-action-node-delete-relation-config', + templateUrl: './delete-relation-config.component.html', + styleUrls: [], + standalone: false }) export class DeleteRelationConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/device-profile-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/device-profile-config.component.ts index 3bd49c65f2..e7397f431c 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/device-profile-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/device-profile-config.component.ts @@ -19,9 +19,10 @@ import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-action-node-device-profile-config', - templateUrl: './device-profile-config.component.html', - styleUrls: [] + selector: 'tb-action-node-device-profile-config', + templateUrl: './device-profile-config.component.html', + styleUrls: [], + standalone: false }) export class DeviceProfileConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/device-state-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/device-state-config.component.ts index f3176849f1..08a81b8bbb 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/device-state-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/device-state-config.component.ts @@ -27,7 +27,8 @@ import { @Component({ selector: 'tb-action-node-device-state-config', templateUrl: './device-state-config.component.html', - styleUrls: [] + styleUrls: [], + standalone: false }) export class DeviceStateConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.ts index 2632a080a6..a421400791 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.ts @@ -28,9 +28,10 @@ import { EntityType } from '@app/shared/models/entity-type.models'; import { DebugRuleNodeEventBody } from '@shared/models/event.models'; @Component({ - selector: 'tb-action-node-generator-config', - templateUrl: './generator-config.component.html', - styleUrls: ['generator-config.component.scss'] + selector: 'tb-action-node-generator-config', + templateUrl: './generator-config.component.html', + styleUrls: ['generator-config.component.scss'], + standalone: false }) export class GeneratorConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.ts index c16a13c5d8..b74efbe677 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.ts @@ -28,9 +28,10 @@ import { } from '../rule-node-config.models'; @Component({ - selector: 'tb-action-node-gps-geofencing-config', - templateUrl: './gps-geo-action-config.component.html', - styleUrls: ['./gps-geo-action-config.component.scss'] + selector: 'tb-action-node-gps-geofencing-config', + templateUrl: './gps-geo-action-config.component.html', + styleUrls: ['./gps-geo-action-config.component.scss'], + standalone: false }) export class GpsGeoActionConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/log-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/log-config.component.ts index 4be9783e6a..7d62fdb7d4 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/log-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/log-config.component.ts @@ -27,9 +27,10 @@ import type { JsFuncComponent } from '@app/shared/components/js-func.component'; import { DebugRuleNodeEventBody } from '@shared/models/event.models'; @Component({ - selector: 'tb-action-node-log-config', - templateUrl: './log-config.component.html', - styleUrls: [] + selector: 'tb-action-node-log-config', + templateUrl: './log-config.component.html', + styleUrls: [], + standalone: false }) export class LogConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/math-function-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/math-function-config.component.ts index b7579e52a6..66c962a4e7 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/math-function-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/math-function-config.component.ts @@ -27,9 +27,10 @@ import { @Component({ - selector: 'tb-action-node-math-function-config', - templateUrl: './math-function-config.component.html', - styleUrls: ['./math-function-config.component.scss'] + selector: 'tb-action-node-math-function-config', + templateUrl: './math-function-config.component.html', + styleUrls: ['./math-function-config.component.scss'], + standalone: false }) export class MathFunctionConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/msg-count-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/msg-count-config.component.ts index 1cdff79ff6..ab9f1186f6 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/msg-count-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/msg-count-config.component.ts @@ -19,9 +19,10 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-action-node-msg-count-config', - templateUrl: './msg-count-config.component.html', - styleUrls: [] + selector: 'tb-action-node-msg-count-config', + templateUrl: './msg-count-config.component.html', + styleUrls: [], + standalone: false }) export class MsgCountConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/msg-delay-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/msg-delay-config.component.ts index 09ce257e94..c36ad95a58 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/msg-delay-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/msg-delay-config.component.ts @@ -19,9 +19,10 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-action-node-msg-delay-config', - templateUrl: './msg-delay-config.component.html', - styleUrls: [] + selector: 'tb-action-node-msg-delay-config', + templateUrl: './msg-delay-config.component.html', + styleUrls: [], + standalone: false }) export class MsgDelayConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-cloud-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-cloud-config.component.ts index 451caa2301..a7a5542b98 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-cloud-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-cloud-config.component.ts @@ -20,9 +20,10 @@ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/m import { AttributeScope, telemetryTypeTranslations } from '@shared/models/telemetry/telemetry.models'; @Component({ - selector: 'tb-action-node-push-to-cloud-config', - templateUrl: './push-to-cloud-config.component.html', - styleUrls: [] + selector: 'tb-action-node-push-to-cloud-config', + templateUrl: './push-to-cloud-config.component.html', + styleUrls: [], + standalone: false }) export class PushToCloudConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-edge-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-edge-config.component.ts index 59a9f539cb..5192161cc8 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-edge-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-edge-config.component.ts @@ -20,9 +20,10 @@ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/m import { AttributeScope, telemetryTypeTranslations } from '@shared/models/telemetry/telemetry.models'; @Component({ - selector: 'tb-action-node-push-to-edge-config', - templateUrl: './push-to-edge-config.component.html', - styleUrls: [] + selector: 'tb-action-node-push-to-edge-config', + templateUrl: './push-to-edge-config.component.html', + styleUrls: [], + standalone: false }) export class PushToEdgeConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-reply-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-reply-config.component.ts index 016373c78b..53b1268189 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-reply-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-reply-config.component.ts @@ -19,9 +19,10 @@ import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-action-node-rpc-reply-config', - templateUrl: './rpc-reply-config.component.html', - styleUrls: [] + selector: 'tb-action-node-rpc-reply-config', + templateUrl: './rpc-reply-config.component.html', + styleUrls: [], + standalone: false }) export class RpcReplyConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-request-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-request-config.component.ts index f1dbc1db86..546f344863 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-request-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-request-config.component.ts @@ -19,9 +19,10 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-action-node-rpc-request-config', - templateUrl: './rpc-request-config.component.html', - styleUrls: [] + selector: 'tb-action-node-rpc-request-config', + templateUrl: './rpc-request-config.component.html', + styleUrls: [], + standalone: false }) export class RpcRequestConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/save-to-custom-table-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/save-to-custom-table-config.component.ts index 03f9dd7382..ac7cda0abc 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/save-to-custom-table-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/save-to-custom-table-config.component.ts @@ -19,9 +19,10 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-action-node-custom-table-config', - templateUrl: './save-to-custom-table-config.component.html', - styleUrls: [] + selector: 'tb-action-node-custom-table-config', + templateUrl: './save-to-custom-table-config.component.html', + styleUrls: [], + standalone: false }) export class SaveToCustomTableConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/send-rest-api-call-reply-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/send-rest-api-call-reply-config.component.ts index 1c825aba3c..b3d2887be5 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/send-rest-api-call-reply-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/send-rest-api-call-reply-config.component.ts @@ -19,9 +19,10 @@ import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-action-node-send-rest-api-call-reply-config', - templateUrl: './send-rest-api-call-reply-config.component.html', - styleUrls: [] + selector: 'tb-action-node-send-rest-api-call-reply-config', + templateUrl: './send-rest-api-call-reply-config.component.html', + styleUrls: [], + standalone: false }) export class SendRestApiCallReplyConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/timeseries-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/timeseries-config.component.ts index 1349eeb963..93427afeda 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/timeseries-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/timeseries-config.component.ts @@ -29,9 +29,10 @@ import { } from '@home/components/rule-node/action/timeseries-config.models'; @Component({ - selector: 'tb-action-node-timeseries-config', - templateUrl: './timeseries-config.component.html', - styleUrls: [] + selector: 'tb-action-node-timeseries-config', + templateUrl: './timeseries-config.component.html', + styleUrls: [], + standalone: false }) export class TimeseriesConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/unassign-customer-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/unassign-customer-config.component.ts index 5fe0c5c1df..ee5c1a5031 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/unassign-customer-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/unassign-customer-config.component.ts @@ -20,9 +20,10 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; @Component({ - selector: 'tb-action-node-un-assign-to-customer-config', - templateUrl: './unassign-customer-config.component.html', - styleUrls: [] + selector: 'tb-action-node-un-assign-to-customer-config', + templateUrl: './unassign-customer-config.component.html', + styleUrls: [], + standalone: false }) export class UnassignCustomerConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.ts index bc9de1be09..2ccceb8877 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.ts @@ -20,14 +20,15 @@ import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-alarm-status-select', - templateUrl: './alarm-status-select.component.html', - styleUrls: ['./alarm-status-select.component.scss'], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AlarmStatusSelectComponent), - multi: true - }] + selector: 'tb-alarm-status-select', + templateUrl: './alarm-status-select.component.html', + styleUrls: ['./alarm-status-select.component.scss'], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AlarmStatusSelectComponent), + multi: true + }], + standalone: false }) export class AlarmStatusSelectComponent extends PageComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.ts index 60bf03607d..dd46d40b5e 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.ts @@ -39,21 +39,22 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-arguments-map-config', - templateUrl: './arguments-map-config.component.html', - styleUrls: ['./arguments-map-config.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ArgumentsMapConfigComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => ArgumentsMapConfigComponent), - multi: true, - } - ] + selector: 'tb-arguments-map-config', + templateUrl: './arguments-map-config.component.html', + styleUrls: ['./arguments-map-config.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ArgumentsMapConfigComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ArgumentsMapConfigComponent), + multi: true, + } + ], + standalone: false }) export class ArgumentsMapConfigComponent extends PageComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.ts index 1a8556930c..941ccb2706 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.ts @@ -45,21 +45,22 @@ interface CredentialsConfig { } @Component({ - selector: 'tb-credentials-config', - templateUrl: './credentials-config.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => CredentialsConfigComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => CredentialsConfigComponent), - multi: true, - } - ] + selector: 'tb-credentials-config', + templateUrl: './credentials-config.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CredentialsConfigComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => CredentialsConfigComponent), + multi: true, + } + ], + standalone: false }) export class CredentialsConfigComponent extends PageComponent implements ControlValueAccessor, OnInit, Validator, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.ts index c99f9d7848..2b55bf2342 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.ts @@ -31,16 +31,17 @@ interface DeviceRelationsQuery { } @Component({ - selector: 'tb-device-relations-query-config', - templateUrl: './device-relations-query-config.component.html', - styleUrls: ['./device-relations-query-config.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DeviceRelationsQueryConfigComponent), - multi: true - } - ] + selector: 'tb-device-relations-query-config', + templateUrl: './device-relations-query-config.component.html', + styleUrls: ['./device-relations-query-config.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceRelationsQueryConfigComponent), + multi: true + } + ], + standalone: false }) export class DeviceRelationsQueryConfigComponent extends PageComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.ts index c40ab0ff92..1159d1ca9b 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.ts @@ -17,9 +17,10 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'tb-example-hint', - templateUrl: './example-hint.component.html', - styleUrls: [] + selector: 'tb-example-hint', + templateUrl: './example-hint.component.html', + styleUrls: [], + standalone: false }) export class ExampleHintComponent { @Input() hintText: string; diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.ts index 30d96016bc..33e4a203a7 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.ts @@ -33,21 +33,22 @@ import { TranslateService } from '@ngx-translate/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-kv-map-config-old', - templateUrl: './kv-map-config-old.component.html', - styleUrls: ['./kv-map-config-old.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => KvMapConfigOldComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => KvMapConfigOldComponent), - multi: true, - } - ] + selector: 'tb-kv-map-config-old', + templateUrl: './kv-map-config-old.component.html', + styleUrls: ['./kv-map-config-old.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => KvMapConfigOldComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => KvMapConfigOldComponent), + multi: true, + } + ], + standalone: false }) export class KvMapConfigOldComponent extends PageComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.ts index 9cfb50961f..e98f145724 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.ts @@ -34,21 +34,22 @@ import { isEqual } from '@core/public-api'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-kv-map-config', - templateUrl: './kv-map-config.component.html', - styleUrls: ['./kv-map-config.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => KvMapConfigComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => KvMapConfigComponent), - multi: true, - } - ] + selector: 'tb-kv-map-config', + templateUrl: './kv-map-config.component.html', + styleUrls: ['./kv-map-config.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => KvMapConfigComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => KvMapConfigComponent), + multi: true, + } + ], + standalone: false }) export class KvMapConfigComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.ts index 917c4c7a68..6f540b6181 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.ts @@ -23,16 +23,17 @@ import { map, tap } from 'rxjs/operators'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; @Component({ - selector: 'tb-math-function-autocomplete', - templateUrl: './math-function-autocomplete.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MathFunctionAutocompleteComponent), - multi: true - } - ] + selector: 'tb-math-function-autocomplete', + templateUrl: './math-function-autocomplete.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MathFunctionAutocompleteComponent), + multi: true + } + ], + standalone: false }) export class MathFunctionAutocompleteComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.ts index 6ff08c5f7e..b41af5c78b 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.ts @@ -26,16 +26,17 @@ import { TranslateService } from '@ngx-translate/core'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; @Component({ - selector: 'tb-message-types-config', - templateUrl: './message-types-config.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MessageTypesConfigComponent), - multi: true - } - ] + selector: 'tb-message-types-config', + templateUrl: './message-types-config.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MessageTypesConfigComponent), + multi: true + } + ], + standalone: false }) export class MessageTypesConfigComponent extends PageComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/msg-metadata-chip.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/msg-metadata-chip.component.ts index 2d31d016ac..1aca581efc 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/msg-metadata-chip.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/msg-metadata-chip.component.ts @@ -21,13 +21,14 @@ import { TranslateService } from '@ngx-translate/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-msg-metadata-chip', - templateUrl: './msg-metadata-chip.component.html', - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MsgMetadataChipComponent), - multi: true - }] + selector: 'tb-msg-metadata-chip', + templateUrl: './msg-metadata-chip.component.html', + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MsgMetadataChipComponent), + multi: true + }], + standalone: false }) export class MsgMetadataChipComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.ts index cf9f54a35a..5cb9922fcb 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.ts @@ -34,21 +34,22 @@ interface MessageType { } @Component({ - selector: 'tb-output-message-type-autocomplete', - templateUrl: './output-message-type-autocomplete.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => OutputMessageTypeAutocompleteComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => OutputMessageTypeAutocompleteComponent), - multi: true - } - ] + selector: 'tb-output-message-type-autocomplete', + templateUrl: './output-message-type-autocomplete.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => OutputMessageTypeAutocompleteComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => OutputMessageTypeAutocompleteComponent), + multi: true + } + ], + standalone: false }) export class OutputMessageTypeAutocompleteComponent implements ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.ts index c209df227a..83ed4a435f 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.ts @@ -22,16 +22,17 @@ import { RelationsQuery } from '../rule-node-config.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-relations-query-config-old', - templateUrl: './relations-query-config-old.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => RelationsQueryConfigOldComponent), - multi: true - } - ] + selector: 'tb-relations-query-config-old', + templateUrl: './relations-query-config-old.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RelationsQueryConfigOldComponent), + multi: true + } + ], + standalone: false }) export class RelationsQueryConfigOldComponent extends PageComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.ts index a06aeec2c3..cc283afe27 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.ts @@ -22,15 +22,16 @@ import { RelationsQuery } from '../rule-node-config.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-relations-query-config', - templateUrl: './relations-query-config.component.html', - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => RelationsQueryConfigComponent), - multi: true - } - ] + selector: 'tb-relations-query-config', + templateUrl: './relations-query-config.component.html', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RelationsQueryConfigComponent), + multi: true + } + ], + standalone: false }) export class RelationsQueryConfigComponent extends PageComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.ts index 10a8658490..bc7bc01a55 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.ts @@ -31,18 +31,19 @@ import { isDefinedAndNotNull } from '@core/public-api'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-select-attributes', - templateUrl: './select-attributes.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => SelectAttributesComponent), - multi: true - }, { - provide: NG_VALIDATORS, - useExisting: SelectAttributesComponent, - multi: true - }] + selector: 'tb-select-attributes', + templateUrl: './select-attributes.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => SelectAttributesComponent), + multi: true + }, { + provide: NG_VALIDATORS, + useExisting: SelectAttributesComponent, + multi: true + }], + standalone: false }) export class SelectAttributesComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.ts index 61807afa1e..558aabe9ba 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.ts @@ -36,21 +36,22 @@ import { OriginatorFieldsMappingValues, SvMapOption } from '../rule-node-config. import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-sv-map-config', - templateUrl: './sv-map-config.component.html', - styleUrls: ['./sv-map-config.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => SvMapConfigComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => SvMapConfigComponent), - multi: true, - } - ] + selector: 'tb-sv-map-config', + templateUrl: './sv-map-config.component.html', + styleUrls: ['./sv-map-config.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => SvMapConfigComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => SvMapConfigComponent), + multi: true, + } + ], + standalone: false }) export class SvMapConfigComponent extends PageComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/time-unit-input.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/time-unit-input.component.ts index 484c2da12f..e863d957b6 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/time-unit-input.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/time-unit-input.component.ts @@ -38,17 +38,18 @@ interface TimeUnitInputModel { } @Component({ - selector: 'tb-time-unit-input', - templateUrl: './time-unit-input.component.html', - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimeUnitInputComponent), - multi: true - },{ - provide: NG_VALIDATORS, - useExisting: forwardRef(() => TimeUnitInputComponent), - multi: true - }] + selector: 'tb-time-unit-input', + templateUrl: './time-unit-input.component.html', + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeUnitInputComponent), + multi: true + }, { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => TimeUnitInputComponent), + multi: true + }], + standalone: false }) export class TimeUnitInputComponent implements ControlValueAccessor, Validator, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/empty-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/empty-config.component.ts index 06747e23cf..554fbf0c7b 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/empty-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/empty-config.component.ts @@ -19,9 +19,10 @@ import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-node-empty-config', - template: '
', - styleUrls: [] + selector: 'tb-node-empty-config', + template: '
', + styleUrls: [], + standalone: false }) export class EmptyConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/calculate-delta-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/calculate-delta-config.component.ts index a5fdc62b1a..c7df00c008 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/calculate-delta-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/calculate-delta-config.component.ts @@ -22,8 +22,9 @@ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/m import { deepTrim, isDefinedAndNotNull } from '@app/core/utils'; @Component({ - selector: 'tb-enrichment-node-calculate-delta-config', - templateUrl: './calculate-delta-config.component.html' + selector: 'tb-enrichment-node-calculate-delta-config', + templateUrl: './calculate-delta-config.component.html', + standalone: false }) export class CalculateDeltaConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.ts index ae8fb3b1b9..757b9d5add 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.ts @@ -22,9 +22,10 @@ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shar import { DataToFetch, dataToFetchTranslations, FetchTo } from '@home/components/rule-node/rule-node-config.models'; @Component({ - selector: 'tb-enrichment-node-customer-attributes-config', - templateUrl: './customer-attributes-config.component.html', - styleUrls: ['./customer-attributes-config.component.scss'] + selector: 'tb-enrichment-node-customer-attributes-config', + templateUrl: './customer-attributes-config.component.html', + styleUrls: ['./customer-attributes-config.component.scss'], + standalone: false }) export class CustomerAttributesConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/device-attributes-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/device-attributes-config.component.ts index c05119c0f5..0520ed1d48 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/device-attributes-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/device-attributes-config.component.ts @@ -22,9 +22,10 @@ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shar import { FetchTo } from '@home/components/rule-node/rule-node-config.models'; @Component({ - selector: 'tb-enrichment-node-device-attributes-config', - templateUrl: './device-attributes-config.component.html', - styleUrls: [] + selector: 'tb-enrichment-node-device-attributes-config', + templateUrl: './device-attributes-config.component.html', + styleUrls: [], + standalone: false }) export class DeviceAttributesConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/entity-details-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/entity-details-config.component.ts index 02cd9192b8..2f558dbc45 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/entity-details-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/entity-details-config.component.ts @@ -26,9 +26,10 @@ import { } from '@home/components/rule-node/rule-node-config.models'; @Component({ - selector: 'tb-enrichment-node-entity-details-config', - templateUrl: './entity-details-config.component.html', - styleUrls: [] + selector: 'tb-enrichment-node-entity-details-config', + templateUrl: './entity-details-config.component.html', + styleUrls: [], + standalone: false }) export class EntityDetailsConfigComponent extends RuleNodeConfigurationComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/fetch-device-credentials-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/fetch-device-credentials-config.component.ts index 25e6a209ed..2ca92eb72c 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/fetch-device-credentials-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/fetch-device-credentials-config.component.ts @@ -21,8 +21,9 @@ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/m import { FetchTo } from '@home/components/rule-node/rule-node-config.models'; @Component({ - selector: 'tb-enrichment-node-fetch-device-credentials-config', - templateUrl: './fetch-device-credentials-config.component.html' + selector: 'tb-enrichment-node-fetch-device-credentials-config', + templateUrl: './fetch-device-credentials-config.component.html', + standalone: false }) export class FetchDeviceCredentialsConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.ts index 148cc1b758..cea4771021 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.ts @@ -31,9 +31,10 @@ import { } from '../rule-node-config.models'; @Component({ - selector: 'tb-enrichment-node-get-telemetry-from-database', - templateUrl: './get-telemetry-from-database-config.component.html', - styleUrls: ['./get-telemetry-from-database-config.component.scss'] + selector: 'tb-enrichment-node-get-telemetry-from-database', + templateUrl: './get-telemetry-from-database-config.component.html', + styleUrls: ['./get-telemetry-from-database-config.component.scss'], + standalone: false }) export class GetTelemetryFromDatabaseConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-attributes-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-attributes-config.component.ts index 2d6f5bd663..57fa20dc21 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-attributes-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-attributes-config.component.ts @@ -22,9 +22,10 @@ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shar import { FetchTo } from '@home/components/rule-node/rule-node-config.models'; @Component({ - selector: 'tb-enrichment-node-originator-attributes-config', - templateUrl: './originator-attributes-config.component.html', - styleUrls: [] + selector: 'tb-enrichment-node-originator-attributes-config', + templateUrl: './originator-attributes-config.component.html', + styleUrls: [], + standalone: false }) export class OriginatorAttributesConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-fields-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-fields-config.component.ts index 9173ada5ee..102d61fddf 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-fields-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-fields-config.component.ts @@ -22,8 +22,9 @@ import { allowedOriginatorFields, FetchTo, SvMapOption } from '@home/components/ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; @Component({ - selector: 'tb-enrichment-node-originator-fields-config', - templateUrl: './originator-fields-config.component.html' + selector: 'tb-enrichment-node-originator-fields-config', + templateUrl: './originator-fields-config.component.html', + standalone: false }) export class OriginatorFieldsConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/related-attributes-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/related-attributes-config.component.ts index 0927645a47..f5c6acd5a4 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/related-attributes-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/related-attributes-config.component.ts @@ -30,9 +30,10 @@ import { import { entityFields } from '@shared/models/entity.models'; @Component({ - selector: 'tb-enrichment-node-related-attributes-config', - templateUrl: './related-attributes-config.component.html', - styleUrls: [] + selector: 'tb-enrichment-node-related-attributes-config', + templateUrl: './related-attributes-config.component.html', + styleUrls: [], + standalone: false }) export class RelatedAttributesConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/tenant-attributes-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/tenant-attributes-config.component.ts index 2d29081184..9635d2d45f 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/tenant-attributes-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/tenant-attributes-config.component.ts @@ -22,9 +22,10 @@ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shar import { DataToFetch, dataToFetchTranslations, FetchTo } from '../rule-node-config.models'; @Component({ - selector: 'tb-enrichment-node-tenant-attributes-config', - templateUrl: './tenant-attributes-config.component.html', - styleUrls: ['./tenant-attributes-config.component.scss'] + selector: 'tb-enrichment-node-tenant-attributes-config', + templateUrl: './tenant-attributes-config.component.html', + styleUrls: ['./tenant-attributes-config.component.scss'], + standalone: false }) export class TenantAttributesConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/ai-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/ai-config.component.ts index de1a1085f8..c83f69ae27 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/ai-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/ai-config.component.ts @@ -28,9 +28,10 @@ import { Resource, ResourceType } from "@shared/models/resource.models"; import { ResourcesDialogComponent, ResourcesDialogData } from "@home/components/resources/resources-dialog.component"; @Component({ - selector: 'tb-external-node-ai-config', - templateUrl: './ai-config.component.html', - styleUrls: [] + selector: 'tb-external-node-ai-config', + templateUrl: './ai-config.component.html', + styleUrls: [], + standalone: false }) export class AiConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.ts index 772f411c44..ac7ecd58cb 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.ts @@ -25,9 +25,10 @@ import { import { MqttVersion } from '@shared/models/mqtt.models'; @Component({ - selector: 'tb-external-node-azure-iot-hub-config', - templateUrl: './azure-iot-hub-config.component.html', - styleUrls: ['./mqtt-config.component.scss'] + selector: 'tb-external-node-azure-iot-hub-config', + templateUrl: './azure-iot-hub-config.component.html', + styleUrls: ['./mqtt-config.component.scss'], + standalone: false }) export class AzureIotHubConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/kafka-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/kafka-config.component.ts index 41fd064314..3b8b07b108 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/kafka-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/kafka-config.component.ts @@ -23,9 +23,10 @@ import { } from '@home/components/rule-node/rule-node-config.models'; @Component({ - selector: 'tb-external-node-kafka-config', - templateUrl: './kafka-config.component.html', - styleUrls: [] + selector: 'tb-external-node-kafka-config', + templateUrl: './kafka-config.component.html', + styleUrls: [], + standalone: false }) export class KafkaConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/lambda-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/lambda-config.component.ts index eccbad5295..914ed3522c 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/lambda-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/lambda-config.component.ts @@ -19,9 +19,10 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-external-node-lambda-config', - templateUrl: './lambda-config.component.html', - styleUrls: [] + selector: 'tb-external-node-lambda-config', + templateUrl: './lambda-config.component.html', + styleUrls: [], + standalone: false }) export class LambdaConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.ts index bf0f5d174a..1fe03704dd 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.ts @@ -20,9 +20,10 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-external-node-mqtt-config', - templateUrl: './mqtt-config.component.html', - styleUrls: ['./mqtt-config.component.scss'] + selector: 'tb-external-node-mqtt-config', + templateUrl: './mqtt-config.component.html', + styleUrls: ['./mqtt-config.component.scss'], + standalone: false }) export class MqttConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/notification-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/notification-config.component.ts index 6ee6c0525f..386d85ac1a 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/notification-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/notification-config.component.ts @@ -21,9 +21,10 @@ import { NotificationType } from '@shared/models/notification.models'; import { EntityType } from '@shared/models/entity-type.models'; @Component({ - selector: 'tb-external-node-notification-config', - templateUrl: './notification-config.component.html', - styleUrls: [] + selector: 'tb-external-node-notification-config', + templateUrl: './notification-config.component.html', + styleUrls: [], + standalone: false }) export class NotificationConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/pubsub-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/pubsub-config.component.ts index 652b8dca5b..4a7d9f972f 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/pubsub-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/pubsub-config.component.ts @@ -19,9 +19,10 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-external-node-pub-sub-config', - templateUrl: './pubsub-config.component.html', - styleUrls: [] + selector: 'tb-external-node-pub-sub-config', + templateUrl: './pubsub-config.component.html', + styleUrls: [], + standalone: false }) export class PubSubConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/rabbit-mq-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/rabbit-mq-config.component.ts index d4fdc4601a..2f44901d52 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/rabbit-mq-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/rabbit-mq-config.component.ts @@ -19,9 +19,10 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-external-node-rabbit-mq-config', - templateUrl: './rabbit-mq-config.component.html', - styleUrls: [] + selector: 'tb-external-node-rabbit-mq-config', + templateUrl: './rabbit-mq-config.component.html', + styleUrls: [], + standalone: false }) export class RabbitMqConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.ts index 3be6a6499b..4723a0c510 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.ts @@ -20,9 +20,10 @@ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shar import { HttpRequestType, IntLimit } from '../rule-node-config.models'; @Component({ - selector: 'tb-external-node-rest-api-call-config', - templateUrl: './rest-api-call-config.component.html', - styleUrls: [] + selector: 'tb-external-node-rest-api-call-config', + templateUrl: './rest-api-call-config.component.html', + styleUrls: [], + standalone: false }) export class RestApiCallConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/send-email-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/send-email-config.component.ts index fd2b587446..98bbdc0ff5 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/send-email-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/send-email-config.component.ts @@ -19,9 +19,10 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-external-node-send-email-config', - templateUrl: './send-email-config.component.html', - styleUrls: [] + selector: 'tb-external-node-send-email-config', + templateUrl: './send-email-config.component.html', + styleUrls: [], + standalone: false }) export class SendEmailConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/send-sms-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/send-sms-config.component.ts index dbf8afb6c6..38c1cee016 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/send-sms-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/send-sms-config.component.ts @@ -19,9 +19,10 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-external-node-send-sms-config', - templateUrl: './send-sms-config.component.html', - styleUrls: [] + selector: 'tb-external-node-send-sms-config', + templateUrl: './send-sms-config.component.html', + styleUrls: [], + standalone: false }) export class SendSmsConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/slack-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/slack-config.component.ts index 3d719577a7..a0e584e672 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/slack-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/slack-config.component.ts @@ -20,9 +20,10 @@ import { RuleNodeConfiguration, SlackChanelType, SlackChanelTypesTranslateMap } import { RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-external-node-slack-config', - templateUrl: './slack-config.component.html', - styleUrls: ['./slack-config.component.scss'] + selector: 'tb-external-node-slack-config', + templateUrl: './slack-config.component.html', + styleUrls: ['./slack-config.component.scss'], + standalone: false }) export class SlackConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/sns-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/sns-config.component.ts index 352fda3d70..cc9f18c181 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/sns-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/sns-config.component.ts @@ -19,9 +19,10 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-external-node-sns-config', - templateUrl: './sns-config.component.html', - styleUrls: [] + selector: 'tb-external-node-sns-config', + templateUrl: './sns-config.component.html', + styleUrls: [], + standalone: false }) export class SnsConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/sqs-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/sqs-config.component.ts index 7170db813e..ee6cfac5da 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/sqs-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/sqs-config.component.ts @@ -20,9 +20,10 @@ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shar import { SqsQueueType, sqsQueueTypeTranslations } from '@home/components/rule-node/rule-node-config.models'; @Component({ - selector: 'tb-external-node-sqs-config', - templateUrl: './sqs-config.component.html', - styleUrls: [] + selector: 'tb-external-node-sqs-config', + templateUrl: './sqs-config.component.html', + styleUrls: [], + standalone: false }) export class SqsConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-alarm-status.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-alarm-status.component.ts index 082b6c0585..b64f9374fc 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-alarm-status.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-alarm-status.component.ts @@ -20,9 +20,10 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; @Component({ - selector: 'tb-filter-node-check-alarm-status-config', - templateUrl: './check-alarm-status.component.html', - styleUrls: [] + selector: 'tb-filter-node-check-alarm-status-config', + templateUrl: './check-alarm-status.component.html', + styleUrls: [], + standalone: false }) export class CheckAlarmStatusComponent extends RuleNodeConfigurationComponent { alarmStatusConfigForm: FormGroup; diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-message-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-message-config.component.ts index 8bad5ac4ca..9f44bf83c1 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-message-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-message-config.component.ts @@ -20,9 +20,10 @@ import { FormBuilder, FormGroup, ValidationErrors, ValidatorFn, Validators } fro import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; @Component({ - selector: 'tb-filter-node-check-message-config', - templateUrl: './check-message-config.component.html', - styleUrls: [] + selector: 'tb-filter-node-check-message-config', + templateUrl: './check-message-config.component.html', + styleUrls: [], + standalone: false }) export class CheckMessageConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.ts index 09196196bf..a4678eef0e 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.ts @@ -21,9 +21,10 @@ import { EntitySearchDirection, entitySearchDirectionTranslations } from '@app/s import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; @Component({ - selector: 'tb-filter-node-check-relation-config', - templateUrl: './check-relation-config.component.html', - styleUrls: ['./check-relation-config.component.scss'] + selector: 'tb-filter-node-check-relation-config', + templateUrl: './check-relation-config.component.html', + styleUrls: ['./check-relation-config.component.scss'], + standalone: false }) export class CheckRelationConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.ts index e92af96ee6..17aaf675f3 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.ts @@ -21,9 +21,10 @@ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shar import { PerimeterType, perimeterTypeTranslations, RangeUnit, rangeUnitTranslations } from '../rule-node-config.models'; @Component({ - selector: 'tb-filter-node-gps-geofencing-config', - templateUrl: './gps-geo-filter-config.component.html', - styleUrls: ['./gps-geo-filter-config.component.scss'] + selector: 'tb-filter-node-gps-geofencing-config', + templateUrl: './gps-geo-filter-config.component.html', + styleUrls: ['./gps-geo-filter-config.component.scss'], + standalone: false }) export class GpsGeoFilterConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.ts index 9145719950..34596c141c 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.ts @@ -20,9 +20,10 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-filter-node-message-type-config', - templateUrl: './message-type-config.component.html', - styleUrls: [] + selector: 'tb-filter-node-message-type-config', + templateUrl: './message-type-config.component.html', + styleUrls: [], + standalone: false }) export class MessageTypeConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/originator-type-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/originator-type-config.component.ts index d72cc3231f..66d381075b 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/originator-type-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/originator-type-config.component.ts @@ -21,9 +21,10 @@ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shar import { EntityType } from '@app/shared/models/entity-type.models'; @Component({ - selector: 'tb-filter-node-originator-type-config', - templateUrl: './originator-type-config.component.html', - styleUrls: [] + selector: 'tb-filter-node-originator-type-config', + templateUrl: './originator-type-config.component.html', + styleUrls: [], + standalone: false }) export class OriginatorTypeConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/script-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/script-config.component.ts index 9bbc9601e7..9d1a7d511f 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/script-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/script-config.component.ts @@ -24,9 +24,10 @@ import type { JsFuncComponent } from '@app/shared/components/js-func.component'; import { DebugRuleNodeEventBody } from '@app/shared/models/event.models'; @Component({ - selector: 'tb-filter-node-script-config', - templateUrl: './script-config.component.html', - styleUrls: [] + selector: 'tb-filter-node-script-config', + templateUrl: './script-config.component.html', + styleUrls: [], + standalone: false }) export class ScriptConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/switch-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/switch-config.component.ts index 26e6d0a21e..8a00fe94e8 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/switch-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/switch-config.component.ts @@ -27,9 +27,10 @@ import type { JsFuncComponent } from '@app/shared/components/js-func.component'; import { DebugRuleNodeEventBody } from '@shared/models/event.models'; @Component({ - selector: 'tb-filter-node-switch-config', - templateUrl: './switch-config.component.html', - styleUrls: [] + selector: 'tb-filter-node-switch-config', + templateUrl: './switch-config.component.html', + styleUrls: [], + standalone: false }) export class SwitchConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-input.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-input.component.ts index 87cf38bd7c..0403a37563 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-input.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-input.component.ts @@ -20,9 +20,10 @@ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/m import { EntityType } from '@shared/models/entity-type.models'; @Component({ - selector: 'tb-flow-node-rule-chain-input-config', - templateUrl: './rule-chain-input.component.html', - styleUrls: [] + selector: 'tb-flow-node-rule-chain-input-config', + templateUrl: './rule-chain-input.component.html', + styleUrls: [], + standalone: false }) export class RuleChainInputComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-output.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-output.component.ts index f4b2760f04..0505a2be7f 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-output.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-output.component.ts @@ -19,9 +19,10 @@ import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-flow-node-rule-chain-output-config', - templateUrl: './rule-chain-output.component.html', - styleUrls: [] + selector: 'tb-flow-node-rule-chain-output-config', + templateUrl: './rule-chain-output.component.html', + styleUrls: [], + standalone: false }) export class RuleChainOutputComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/change-originator-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/change-originator-config.component.ts index b5c63de344..3aeb18a453 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/change-originator-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/change-originator-config.component.ts @@ -25,8 +25,9 @@ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shar import { EntityType } from '@app/shared/models/entity-type.models'; @Component({ - selector: 'tb-transformation-node-change-originator-config', - templateUrl: './change-originator-config.component.html' + selector: 'tb-transformation-node-change-originator-config', + templateUrl: './change-originator-config.component.html', + standalone: false }) export class ChangeOriginatorConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/copy-keys-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/copy-keys-config.component.ts index 2f4bd029dc..e059a7de97 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/copy-keys-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/copy-keys-config.component.ts @@ -22,9 +22,10 @@ import { FetchFromToTranslation, FetchTo } from '../rule-node-config.models'; import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; @Component({ - selector: 'tb-transformation-node-copy-keys-config', - templateUrl: './copy-keys-config.component.html', - styleUrls: [] + selector: 'tb-transformation-node-copy-keys-config', + templateUrl: './copy-keys-config.component.html', + styleUrls: [], + standalone: false }) export class CopyKeysConfigComponent extends RuleNodeConfigurationComponent{ diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.ts index 4661084ef3..77c95515d3 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.ts @@ -21,9 +21,10 @@ import { deduplicationStrategiesTranslations, FetchMode } from '@home/components import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-transformation-node-deduplication-config', - templateUrl: './deduplication-config.component.html', - styleUrls: [] + selector: 'tb-transformation-node-deduplication-config', + templateUrl: './deduplication-config.component.html', + styleUrls: [], + standalone: false }) export class DeduplicationConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/delete-keys-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/delete-keys-config.component.ts index bac37fb4f5..6d04408b75 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/delete-keys-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/delete-keys-config.component.ts @@ -22,9 +22,10 @@ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shar import { FetchTo, FetchToTranslation } from '@home/components/rule-node/rule-node-config.models'; @Component({ - selector: 'tb-transformation-node-delete-keys-config', - templateUrl: './delete-keys-config.component.html', - styleUrls: [] + selector: 'tb-transformation-node-delete-keys-config', + templateUrl: './delete-keys-config.component.html', + styleUrls: [], + standalone: false }) export class DeleteKeysConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/node-json-path-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/node-json-path-config.component.ts index e6e5d65d85..27719ccbb9 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/node-json-path-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/node-json-path-config.component.ts @@ -19,9 +19,10 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-transformation-node-json-path-config', - templateUrl: './node-json-path-config.component.html', - styleUrls: [] + selector: 'tb-transformation-node-json-path-config', + templateUrl: './node-json-path-config.component.html', + styleUrls: [], + standalone: false }) export class NodeJsonPathConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/rename-keys-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/rename-keys-config.component.ts index c99e6029a5..fc6a677878 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/rename-keys-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/rename-keys-config.component.ts @@ -23,9 +23,10 @@ import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/m @Component({ - selector: 'tb-transformation-node-rename-keys-config', - templateUrl: './rename-keys-config.component.html', - styleUrls: ['./rename-keys-config.component.scss'] + selector: 'tb-transformation-node-rename-keys-config', + templateUrl: './rename-keys-config.component.html', + styleUrls: ['./rename-keys-config.component.scss'], + standalone: false }) export class RenameKeysConfigComponent extends RuleNodeConfigurationComponent { renameKeysConfigForm: FormGroup; diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/script-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/script-config.component.ts index 021bb21cb1..2007e06180 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/script-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/script-config.component.ts @@ -27,9 +27,10 @@ import { import { DebugRuleNodeEventBody } from '@shared/models/event.models'; @Component({ - selector: 'tb-transformation-node-script-config', - templateUrl: './script-config.component.html', - styleUrls: [] + selector: 'tb-transformation-node-script-config', + templateUrl: './script-config.component.html', + styleUrls: [], + standalone: false }) export class TransformScriptConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.ts index e2c7117ae0..21a1748085 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.ts @@ -20,9 +20,10 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; @Component({ - selector: 'tb-transformation-node-to-email-config', - templateUrl: './to-email-config.component.html', - styleUrls: ['./to-email-config.component.scss'] + selector: 'tb-transformation-node-to-email-config', + templateUrl: './to-email-config.component.html', + styleUrls: ['./to-email-config.component.scss'], + standalone: false }) export class ToEmailConfigComponent extends RuleNodeConfigurationComponent { diff --git a/ui-ngx/src/app/modules/home/components/sms/aws-sns-provider-configuration.component.ts b/ui-ngx/src/app/modules/home/components/sms/aws-sns-provider-configuration.component.ts index 772ae7366a..d864c3ccfd 100644 --- a/ui-ngx/src/app/modules/home/components/sms/aws-sns-provider-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/sms/aws-sns-provider-configuration.component.ts @@ -28,14 +28,15 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-aws-sns-provider-configuration', - templateUrl: './aws-sns-provider-configuration.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AwsSnsProviderConfigurationComponent), - multi: true - }] + selector: 'tb-aws-sns-provider-configuration', + templateUrl: './aws-sns-provider-configuration.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AwsSnsProviderConfigurationComponent), + multi: true + }], + standalone: false }) export class AwsSnsProviderConfigurationComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/sms/smpp-sms-provider-configuration.component.ts b/ui-ngx/src/app/modules/home/components/sms/smpp-sms-provider-configuration.component.ts index 04ea006af4..35111be91b 100644 --- a/ui-ngx/src/app/modules/home/components/sms/smpp-sms-provider-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/sms/smpp-sms-provider-configuration.component.ts @@ -36,14 +36,15 @@ import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-smpp-sms-provider-configuration', - templateUrl: './smpp-sms-provider-configuration.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => SmppSmsProviderConfigurationComponent), - multi: true - }] + selector: 'tb-smpp-sms-provider-configuration', + templateUrl: './smpp-sms-provider-configuration.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => SmppSmsProviderConfigurationComponent), + multi: true + }], + standalone: false }) export class SmppSmsProviderConfigurationComponent implements ControlValueAccessor, OnInit{ diff --git a/ui-ngx/src/app/modules/home/components/sms/sms-provider-configuration.component.ts b/ui-ngx/src/app/modules/home/components/sms/sms-provider-configuration.component.ts index 807b39f93f..adb477d8fb 100644 --- a/ui-ngx/src/app/modules/home/components/sms/sms-provider-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/sms/sms-provider-configuration.component.ts @@ -34,14 +34,15 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-sms-provider-configuration', - templateUrl: './sms-provider-configuration.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => SmsProviderConfigurationComponent), - multi: true - }] + selector: 'tb-sms-provider-configuration', + templateUrl: './sms-provider-configuration.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => SmsProviderConfigurationComponent), + multi: true + }], + standalone: false }) export class SmsProviderConfigurationComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.ts b/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.ts index 550a2d8112..1041672c50 100644 --- a/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.ts @@ -29,14 +29,15 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-twilio-sms-provider-configuration', - templateUrl: './twilio-sms-provider-configuration.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TwilioSmsProviderConfigurationComponent), - multi: true - }] + selector: 'tb-twilio-sms-provider-configuration', + templateUrl: './twilio-sms-provider-configuration.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TwilioSmsProviderConfigurationComponent), + multi: true + }], + standalone: false }) export class TwilioSmsProviderConfigurationComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/vc/auto-commit-settings.component.ts b/ui-ngx/src/app/modules/home/components/vc/auto-commit-settings.component.ts index 2f07e2b55c..a2a87edde0 100644 --- a/ui-ngx/src/app/modules/home/components/vc/auto-commit-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/vc/auto-commit-settings.component.ts @@ -34,9 +34,10 @@ import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.m import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; @Component({ - selector: 'tb-auto-commit-settings', - templateUrl: './auto-commit-settings.component.html', - styleUrls: ['./auto-commit-settings.component.scss', './../../pages/admin/settings-card.scss'] + selector: 'tb-auto-commit-settings', + templateUrl: './auto-commit-settings.component.html', + styleUrls: ['./auto-commit-settings.component.scss', './../../pages/admin/settings-card.scss'], + standalone: false }) export class AutoCommitSettingsComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/vc/complex-version-create.component.ts b/ui-ngx/src/app/modules/home/components/vc/complex-version-create.component.ts index 21ac0825c9..af80a5be3a 100644 --- a/ui-ngx/src/app/modules/home/components/vc/complex-version-create.component.ts +++ b/ui-ngx/src/app/modules/home/components/vc/complex-version-create.component.ts @@ -37,9 +37,10 @@ import { share } from 'rxjs/operators'; import { parseHttpErrorMessage } from '@core/utils'; @Component({ - selector: 'tb-complex-version-create', - templateUrl: './complex-version-create.component.html', - styleUrls: ['./version-control.scss'] + selector: 'tb-complex-version-create', + templateUrl: './complex-version-create.component.html', + styleUrls: ['./version-control.scss'], + standalone: false }) export class ComplexVersionCreateComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/vc/complex-version-load.component.ts b/ui-ngx/src/app/modules/home/components/vc/complex-version-load.component.ts index 4bf029404b..8eab024032 100644 --- a/ui-ngx/src/app/modules/home/components/vc/complex-version-load.component.ts +++ b/ui-ngx/src/app/modules/home/components/vc/complex-version-load.component.ts @@ -35,9 +35,10 @@ import { share } from 'rxjs/operators'; import { parseHttpErrorMessage } from '@core/utils'; @Component({ - selector: 'tb-complex-version-load', - templateUrl: './complex-version-load.component.html', - styleUrls: ['./version-control.scss'] + selector: 'tb-complex-version-load', + templateUrl: './complex-version-load.component.html', + styleUrls: ['./version-control.scss'], + standalone: false }) export class ComplexVersionLoadComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/vc/entity-types-version-create.component.ts b/ui-ngx/src/app/modules/home/components/vc/entity-types-version-create.component.ts index bc5b2c8883..45712eab00 100644 --- a/ui-ngx/src/app/modules/home/components/vc/entity-types-version-create.component.ts +++ b/ui-ngx/src/app/modules/home/components/vc/entity-types-version-create.component.ts @@ -44,21 +44,22 @@ import { isDefinedAndNotNull } from '@core/utils'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-entity-types-version-create', - templateUrl: './entity-types-version-create.component.html', - styleUrls: ['./entity-types-version.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => EntityTypesVersionCreateComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => EntityTypesVersionCreateComponent), - multi: true - } - ] + selector: 'tb-entity-types-version-create', + templateUrl: './entity-types-version-create.component.html', + styleUrls: ['./entity-types-version.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => EntityTypesVersionCreateComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => EntityTypesVersionCreateComponent), + multi: true + } + ], + standalone: false }) export class EntityTypesVersionCreateComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/vc/entity-types-version-load.component.ts b/ui-ngx/src/app/modules/home/components/vc/entity-types-version-load.component.ts index 254a178091..bdcad871de 100644 --- a/ui-ngx/src/app/modules/home/components/vc/entity-types-version-load.component.ts +++ b/ui-ngx/src/app/modules/home/components/vc/entity-types-version-load.component.ts @@ -44,21 +44,22 @@ import { RemoveOtherEntitiesConfirmComponent } from '@home/components/vc/remove- import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-entity-types-version-load', - templateUrl: './entity-types-version-load.component.html', - styleUrls: ['./entity-types-version.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => EntityTypesVersionLoadComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => EntityTypesVersionLoadComponent), - multi: true - } - ] + selector: 'tb-entity-types-version-load', + templateUrl: './entity-types-version-load.component.html', + styleUrls: ['./entity-types-version.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => EntityTypesVersionLoadComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => EntityTypesVersionLoadComponent), + multi: true + } + ], + standalone: false }) export class EntityTypesVersionLoadComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/vc/entity-version-create.component.ts b/ui-ngx/src/app/modules/home/components/vc/entity-version-create.component.ts index b01134f85c..7dfafba9a2 100644 --- a/ui-ngx/src/app/modules/home/components/vc/entity-version-create.component.ts +++ b/ui-ngx/src/app/modules/home/components/vc/entity-version-create.component.ts @@ -36,9 +36,10 @@ import { share } from 'rxjs/operators'; import { parseHttpErrorMessage } from '@core/utils'; @Component({ - selector: 'tb-entity-version-create', - templateUrl: './entity-version-create.component.html', - styleUrls: ['./version-control.scss'] + selector: 'tb-entity-version-create', + templateUrl: './entity-version-create.component.html', + styleUrls: ['./version-control.scss'], + standalone: false }) export class EntityVersionCreateComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/vc/entity-version-diff.component.ts b/ui-ngx/src/app/modules/home/components/vc/entity-version-diff.component.ts index 84480efb35..d7a6cd8003 100644 --- a/ui-ngx/src/app/modules/home/components/vc/entity-version-diff.component.ts +++ b/ui-ngx/src/app/modules/home/components/vc/entity-version-diff.component.ts @@ -49,10 +49,11 @@ interface DiffInfo { } @Component({ - selector: 'tb-entity-version-diff', - templateUrl: './entity-version-diff.component.html', - styleUrls: ['./entity-version-diff.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-entity-version-diff', + templateUrl: './entity-version-diff.component.html', + styleUrls: ['./entity-version-diff.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class EntityVersionDiffComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/vc/entity-version-restore.component.ts b/ui-ngx/src/app/modules/home/components/vc/entity-version-restore.component.ts index 89915593a8..7b1eaf1621 100644 --- a/ui-ngx/src/app/modules/home/components/vc/entity-version-restore.component.ts +++ b/ui-ngx/src/app/modules/home/components/vc/entity-version-restore.component.ts @@ -35,9 +35,10 @@ import { Observable, Subscription } from 'rxjs'; import { parseHttpErrorMessage } from '@core/utils'; @Component({ - selector: 'tb-entity-version-restore', - templateUrl: './entity-version-restore.component.html', - styleUrls: ['./version-control.scss'] + selector: 'tb-entity-version-restore', + templateUrl: './entity-version-restore.component.html', + styleUrls: ['./version-control.scss'], + standalone: false }) export class EntityVersionRestoreComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/vc/entity-versions-table.component.ts b/ui-ngx/src/app/modules/home/components/vc/entity-versions-table.component.ts index 96f28e2b4a..c50b7d6c36 100644 --- a/ui-ngx/src/app/modules/home/components/vc/entity-versions-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/vc/entity-versions-table.component.ts @@ -57,9 +57,10 @@ import { AdminService } from '@core/http/admin.service'; import { FormBuilder } from '@angular/forms'; @Component({ - selector: 'tb-entity-versions-table', - templateUrl: './entity-versions-table.component.html', - styleUrls: ['./entity-versions-table.component.scss'] + selector: 'tb-entity-versions-table', + templateUrl: './entity-versions-table.component.html', + styleUrls: ['./entity-versions-table.component.scss'], + standalone: false }) export class EntityVersionsTableComponent extends PageComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/vc/remove-other-entities-confirm.component.ts b/ui-ngx/src/app/modules/home/components/vc/remove-other-entities-confirm.component.ts index b5590cd841..dd9baf20e4 100644 --- a/ui-ngx/src/app/modules/home/components/vc/remove-other-entities-confirm.component.ts +++ b/ui-ngx/src/app/modules/home/components/vc/remove-other-entities-confirm.component.ts @@ -23,9 +23,10 @@ import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; @Component({ - selector: 'tb-remove-other-entities-confirm', - templateUrl: './remove-other-entities-confirm.component.html', - styleUrls: [] + selector: 'tb-remove-other-entities-confirm', + templateUrl: './remove-other-entities-confirm.component.html', + styleUrls: [], + standalone: false }) export class RemoveOtherEntitiesConfirmComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/vc/repository-settings.component.ts b/ui-ngx/src/app/modules/home/components/vc/repository-settings.component.ts index f4959fa761..88ffbd9171 100644 --- a/ui-ngx/src/app/modules/home/components/vc/repository-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/vc/repository-settings.component.ts @@ -38,9 +38,10 @@ import { coerceBoolean } from '@shared/decorators/coercion'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-repository-settings', - templateUrl: './repository-settings.component.html', - styleUrls: ['./repository-settings.component.scss', './../../pages/admin/settings-card.scss'] + selector: 'tb-repository-settings', + templateUrl: './repository-settings.component.html', + styleUrls: ['./repository-settings.component.scss', './../../pages/admin/settings-card.scss'], + standalone: false }) export class RepositorySettingsComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/vc/version-control.component.ts b/ui-ngx/src/app/modules/home/components/vc/version-control.component.ts index 4a2c944e2c..f3f4863653 100644 --- a/ui-ngx/src/app/modules/home/components/vc/version-control.component.ts +++ b/ui-ngx/src/app/modules/home/components/vc/version-control.component.ts @@ -26,9 +26,10 @@ import { Observable } from 'rxjs'; import { TbPopoverComponent } from '@shared/components/popover.component'; @Component({ - selector: 'tb-version-control', - templateUrl: './version-control.component.html', - styleUrls: ['./version-control.component.scss'] + selector: 'tb-version-control', + templateUrl: './version-control.component.html', + styleUrls: ['./version-control.component.scss'], + standalone: false }) export class VersionControlComponent implements OnInit, HasConfirmForm { diff --git a/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions-dialog.component.ts index 367f9c8a6e..8c2def215e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions-dialog.component.ts @@ -37,10 +37,11 @@ export interface ManageWidgetActionsDialogData { } @Component({ - selector: 'tb-manage-widget-actions-dialog', - templateUrl: './manage-widget-actions-dialog.component.html', - providers: [], - styleUrls: [] + selector: 'tb-manage-widget-actions-dialog', + templateUrl: './manage-widget-actions-dialog.component.html', + providers: [], + styleUrls: [], + standalone: false }) export class ManageWidgetActionsDialogComponent extends DialogComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions.component.ts b/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions.component.ts index 8779085003..2da5066816 100644 --- a/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions.component.ts @@ -57,16 +57,17 @@ import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; import { DomSanitizer } from '@angular/platform-browser'; @Component({ - selector: 'tb-manage-widget-actions', - templateUrl: './manage-widget-actions.component.html', - styleUrls: ['./manage-widget-actions.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ManageWidgetActionsComponent), - multi: true - } - ] + selector: 'tb-manage-widget-actions', + templateUrl: './manage-widget-actions.component.html', + styleUrls: ['./manage-widget-actions.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ManageWidgetActionsComponent), + multi: true + } + ], + standalone: false }) export class ManageWidgetActionsComponent extends PageComponent implements OnInit, AfterViewInit, OnDestroy, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.ts index 5549531100..b652f76e06 100644 --- a/ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.ts @@ -66,10 +66,11 @@ export interface WidgetActionDialogData { } @Component({ - selector: 'tb-widget-action-dialog', - templateUrl: './widget-action-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: WidgetActionDialogComponent}], - styleUrls: [] + selector: 'tb-widget-action-dialog', + templateUrl: './widget-action-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: WidgetActionDialogComponent }], + styleUrls: [], + standalone: false }) export class WidgetActionDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarm-count-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarm-count-basic-config.component.ts index 73edce98ee..6d049826d7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarm-count-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarm-count-basic-config.component.ts @@ -33,9 +33,10 @@ import { } from '@home/components/widget/lib/count/count-widget.models'; @Component({ - selector: 'tb-alarm-count-basic-config', - templateUrl: './alarm-count-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-alarm-count-basic-config', + templateUrl: './alarm-count-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class AlarmCountBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarms-table-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarms-table-basic-config.component.ts index a2f25da117..802c1bb0bc 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarms-table-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarms-table-basic-config.component.ts @@ -29,9 +29,10 @@ import { } from '@home/components/widget/config/timewindow-config-panel.component'; @Component({ - selector: 'tb-alarms-table-basic-config', - templateUrl: './alarms-table-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-alarms-table-basic-config', + templateUrl: './alarms-table-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class AlarmsTableBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/button/action-button-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/button/action-button-basic-config.component.ts index b7edac8efb..93b9d03d73 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/button/action-button-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/button/action-button-basic-config.component.ts @@ -38,9 +38,10 @@ import { } from '@home/components/widget/lib/button/action-button-widget.models'; @Component({ - selector: 'tb-action-button-basic-config', - templateUrl: './action-button-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-action-button-basic-config', + templateUrl: './action-button-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class ActionButtonBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/button/command-button-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/button/command-button-basic-config.component.ts index ab5ef0df91..b909cd0e57 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/button/command-button-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/button/command-button-basic-config.component.ts @@ -29,9 +29,10 @@ import { } from '@home/components/widget/lib/button/command-button-widget.models'; @Component({ - selector: 'tb-command-button-basic-config', - templateUrl: './command-button-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-command-button-basic-config', + templateUrl: './command-button-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class CommandButtonBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/button/power-button-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/button/power-button-basic-config.component.ts index a1c0549931..ce40d50626 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/button/power-button-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/button/power-button-basic-config.component.ts @@ -34,9 +34,10 @@ import { import { cssSizeToStrSize, resolveCssSize } from '@shared/models/widget-settings.models'; @Component({ - selector: 'tb-power-button-basic-config', - templateUrl: './power-button-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-power-button-basic-config', + templateUrl: './power-button-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class PowerButtonBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/button/segmented-button-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/button/segmented-button-basic-config.component.ts index 12542ac5be..296959a4b4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/button/segmented-button-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/button/segmented-button-basic-config.component.ts @@ -38,9 +38,10 @@ import { } from '@home/components/widget/lib/button/segmented-button-widget.models'; @Component({ - selector: 'tb-segmented-button-basic-config', - templateUrl: './segmented-button-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-segmented-button-basic-config', + templateUrl: './segmented-button-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class SegmentedButtonBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/button/toggle-button-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/button/toggle-button-basic-config.component.ts index 7a487664c7..7641946666 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/button/toggle-button-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/button/toggle-button-basic-config.component.ts @@ -33,9 +33,10 @@ import { type ButtonAppearanceType = 'checked' | 'unchecked'; @Component({ - selector: 'tb-toggle-button-basic-config', - templateUrl: './toggle-button-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-toggle-button-basic-config', + templateUrl: './toggle-button-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class ToggleButtonBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/aggregated-data-key-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/aggregated-data-key-row.component.ts index aba164f60e..8751ced932 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/aggregated-data-key-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/aggregated-data-key-row.component.ts @@ -56,17 +56,18 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { getSourceTbUnitSymbol, TbUnit } from '@shared/models/unit.models'; @Component({ - selector: 'tb-aggregated-data-key-row', - templateUrl: './aggregated-data-key-row.component.html', - styleUrls: ['./aggregated-data-key-row.component.scss', '../../../lib/settings/common/key/data-keys.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AggregatedDataKeyRowComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-aggregated-data-key-row', + templateUrl: './aggregated-data-key-row.component.html', + styleUrls: ['./aggregated-data-key-row.component.scss', '../../../lib/settings/common/key/data-keys.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AggregatedDataKeyRowComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class AggregatedDataKeyRowComponent implements ControlValueAccessor, OnInit, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/aggregated-data-keys-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/aggregated-data-keys-panel.component.ts index 2931c6eeee..d2cba50bb8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/aggregated-data-keys-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/aggregated-data-keys-panel.component.ts @@ -40,17 +40,18 @@ import { aggregatedValueCardDefaultKeySettings } from '@home/components/widget/l import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-aggregated-data-keys-panel', - templateUrl: './aggregated-data-keys-panel.component.html', - styleUrls: ['./aggregated-data-keys-panel.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AggregatedDataKeysPanelComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-aggregated-data-keys-panel', + templateUrl: './aggregated-data-keys-panel.component.html', + styleUrls: ['./aggregated-data-keys-panel.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AggregatedDataKeysPanelComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class AggregatedDataKeysPanelComponent implements ControlValueAccessor, OnInit, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/aggregated-value-card-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/aggregated-value-card-basic-config.component.ts index e31ea66342..4be3bc7eae 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/aggregated-value-card-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/aggregated-value-card-basic-config.component.ts @@ -52,9 +52,10 @@ import { } from '@shared/models/time/time.models'; @Component({ - selector: 'tb-aggregated-value-card-basic-config', - templateUrl: './aggregated-value-card-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-aggregated-value-card-basic-config', + templateUrl: './aggregated-value-card-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class AggregatedValueCardBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/label-card-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/label-card-basic-config.component.ts index 7c782da2be..59a8f07307 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/label-card-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/label-card-basic-config.component.ts @@ -29,9 +29,10 @@ import { } from '@home/components/widget/lib/cards/label-card-widget.models'; @Component({ - selector: 'tb-label-card-basic-config', - templateUrl: './label-card-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-label-card-basic-config', + templateUrl: './label-card-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class LabelCardBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/label-value-card-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/label-value-card-basic-config.component.ts index 5fdc60083d..d57add2d5b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/label-value-card-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/label-value-card-basic-config.component.ts @@ -40,9 +40,10 @@ import { import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-label-value-card-basic-config', - templateUrl: './label-value-card-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-label-value-card-basic-config', + templateUrl: './label-value-card-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class LabelValueCardBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/mobile-app-qr-code-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/mobile-app-qr-code-basic-config.component.ts index cb7331721d..6aa3f4196a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/mobile-app-qr-code-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/mobile-app-qr-code-basic-config.component.ts @@ -31,9 +31,10 @@ import { import { badgePositionTranslationsMap } from '@app/shared/models/mobile-app.models'; @Component({ - selector: 'tb-mobile-app-qr-code-basic-config', - templateUrl: './mobile-app-qr-code-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-mobile-app-qr-code-basic-config', + templateUrl: './mobile-app-qr-code-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class MobileAppQrCodeBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/progress-bar-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/progress-bar-basic-config.component.ts index f822801058..426c3ee8f7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/progress-bar-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/progress-bar-basic-config.component.ts @@ -45,9 +45,10 @@ import { import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-progress-bar-basic-config', - templateUrl: './progress-bar-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-progress-bar-basic-config', + templateUrl: './progress-bar-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class ProgressBarBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/simple-card-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/simple-card-basic-config.component.ts index de7d66d9d9..104787dd0f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/simple-card-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/simple-card-basic-config.component.ts @@ -36,9 +36,10 @@ import { isUndefined } from '@core/utils'; import { getLabel, setLabel } from '@shared/models/widget-settings.models'; @Component({ - selector: 'tb-simple-card-basic-config', - templateUrl: './simple-card-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-simple-card-basic-config', + templateUrl: './simple-card-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class SimpleCardBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/timeseries-table-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/timeseries-table-basic-config.component.ts index 8acd390b42..01eb67c638 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/timeseries-table-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/timeseries-table-basic-config.component.ts @@ -30,9 +30,10 @@ import { } from '@home/components/widget/config/timewindow-config-panel.component'; @Component({ - selector: 'tb-timeseries-table-basic-config', - templateUrl: './timeseries-table-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-timeseries-table-basic-config', + templateUrl: './timeseries-table-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class TimeseriesTableBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/unread-notification-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/unread-notification-basic-config.component.ts index 7b6347c9a5..a75a84fcca 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/unread-notification-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/unread-notification-basic-config.component.ts @@ -30,9 +30,10 @@ import { } from '@home/components/widget/lib/cards/unread-notification-widget.models'; @Component({ - selector: 'tb-unread-notification-basic-config', - templateUrl: './unread-notification-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-unread-notification-basic-config', + templateUrl: './unread-notification-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class UnreadNotificationBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.ts index 975f8a9655..04905fd657 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.ts @@ -45,9 +45,10 @@ import { import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-value-card-basic-config', - templateUrl: './value-card-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-value-card-basic-config', + templateUrl: './value-card-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class ValueCardBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-chart-card-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-chart-card-basic-config.component.ts index ecf0e8b24e..8d572888c9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-chart-card-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-chart-card-basic-config.component.ts @@ -39,9 +39,10 @@ import { import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-value-chart-card-basic-config', - templateUrl: './value-chart-card-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-value-chart-card-basic-config', + templateUrl: './value-chart-card-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class ValueChartCardBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/bar-chart-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/bar-chart-basic-config.component.ts index db6afe3404..6a940a7a75 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/bar-chart-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/bar-chart-basic-config.component.ts @@ -31,9 +31,10 @@ import { } from '@home/components/widget/config/basic/chart/latest-chart-basic-config.component'; @Component({ - selector: 'tb-bar-chart-basic-config', - templateUrl: './latest-chart-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-bar-chart-basic-config', + templateUrl: './latest-chart-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class BarChartBasicConfigComponent extends LatestChartBasicConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/bar-chart-with-labels-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/bar-chart-with-labels-basic-config.component.ts index d7603fe76f..07cd236fb5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/bar-chart-with-labels-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/bar-chart-with-labels-basic-config.component.ts @@ -48,9 +48,10 @@ import { TimeSeriesChartType } from '@home/components/widget/lib/chart/time-seri import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-bar-chart-with-labels-basic-config', - templateUrl: './bar-chart-with-labels-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-bar-chart-with-labels-basic-config', + templateUrl: './bar-chart-with-labels-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class BarChartWithLabelsBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/comparison-key-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/comparison-key-row.component.ts index e7ff98eed8..add7085af1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/comparison-key-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/comparison-key-row.component.ts @@ -32,17 +32,18 @@ import { deepClone } from '@core/utils'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-comparison-key-row', - templateUrl: './comparison-key-row.component.html', - styleUrls: ['./comparison-key-row.component.scss', '../../../lib/settings/common/key/data-keys.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ComparisonKeyRowComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-comparison-key-row', + templateUrl: './comparison-key-row.component.html', + styleUrls: ['./comparison-key-row.component.scss', '../../../lib/settings/common/key/data-keys.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ComparisonKeyRowComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ComparisonKeyRowComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/comparison-keys-table.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/comparison-keys-table.component.ts index 162f55ae9e..2409c9af57 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/comparison-keys-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/comparison-keys-table.component.ts @@ -27,17 +27,18 @@ import { DataKey, DatasourceType } from '@shared/models/widget.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-comparison-keys-table', - templateUrl: './comparison-keys-table.component.html', - styleUrls: ['./comparison-keys-table.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ComparisonKeysTableComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-comparison-keys-table', + templateUrl: './comparison-keys-table.component.html', + styleUrls: ['./comparison-keys-table.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ComparisonKeysTableComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ComparisonKeysTableComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/doughnut-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/doughnut-basic-config.component.ts index f1e5501343..af411c4bb7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/doughnut-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/doughnut-basic-config.component.ts @@ -32,9 +32,10 @@ import { } from '@home/components/widget/config/basic/chart/latest-chart-basic-config.component'; @Component({ - selector: 'tb-doughnut-basic-config', - templateUrl: './latest-chart-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-doughnut-basic-config', + templateUrl: './latest-chart-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class DoughnutBasicConfigComponent extends LatestChartBasicConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/flot-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/flot-basic-config.component.ts index d03d2f4c5f..9e2673a9ca 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/flot-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/flot-basic-config.component.ts @@ -30,9 +30,10 @@ import { } from '@home/components/widget/config/timewindow-config-panel.component'; @Component({ - selector: 'tb-flot-basic-config', - templateUrl: './flot-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-flot-basic-config', + templateUrl: './flot-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class FlotBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/pie-chart-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/pie-chart-basic-config.component.ts index d71338e45b..6dea17141b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/pie-chart-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/pie-chart-basic-config.component.ts @@ -31,9 +31,10 @@ import { } from '@home/components/widget/config/basic/chart/latest-chart-basic-config.component'; @Component({ - selector: 'tb-pie-chart-basic-config', - templateUrl: './latest-chart-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-pie-chart-basic-config', + templateUrl: './latest-chart-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class PieChartBasicConfigComponent extends LatestChartBasicConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/polar-area-chart-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/polar-area-chart-basic-config.component.ts index 0e5abe194d..578a4957e2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/polar-area-chart-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/polar-area-chart-basic-config.component.ts @@ -31,9 +31,10 @@ import { } from '@home/components/widget/config/basic/chart/latest-chart-basic-config.component'; @Component({ - selector: 'tb-polar-area-chart-basic-config', - templateUrl: './latest-chart-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-polar-area-chart-basic-config', + templateUrl: './latest-chart-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class PolarAreaChartBasicConfigComponent extends LatestChartBasicConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/radar-chart-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/radar-chart-basic-config.component.ts index 56cdf66fb6..52f3094da6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/radar-chart-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/radar-chart-basic-config.component.ts @@ -31,9 +31,10 @@ import { } from '@home/components/widget/config/basic/chart/latest-chart-basic-config.component'; @Component({ - selector: 'tb-radar-chart-basic-config', - templateUrl: './latest-chart-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-radar-chart-basic-config', + templateUrl: './latest-chart-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class RadarChartBasicConfigComponent extends LatestChartBasicConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/range-chart-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/range-chart-basic-config.component.ts index 6681ad09a6..3b24d1b98e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/range-chart-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/range-chart-basic-config.component.ts @@ -59,9 +59,10 @@ import { import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-range-chart-basic-config', - templateUrl: './range-chart-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-range-chart-basic-config', + templateUrl: './range-chart-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class RangeChartBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts index a945aa34ef..008e1fda57 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts @@ -55,9 +55,10 @@ import { TimeSeriesChartTooltipTrigger } from '@home/components/widget/lib/chart import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-time-series-chart-basic-config', - templateUrl: './time-series-chart-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-time-series-chart-basic-config', + templateUrl: './time-series-chart-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts index bca32ef235..e84587c758 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts @@ -76,17 +76,18 @@ export const dataKeyRowValidator = (control: AbstractControl): ValidationErrors }; @Component({ - selector: 'tb-data-key-row', - templateUrl: './data-key-row.component.html', - styleUrls: ['./data-key-row.component.scss', '../../../lib/settings/common/key/data-keys.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DataKeyRowComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-data-key-row', + templateUrl: './data-key-row.component.html', + styleUrls: ['./data-key-row.component.scss', '../../../lib/settings/common/key/data-keys.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DataKeyRowComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.ts index d0b6ca68d9..a42b046bb8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.ts @@ -50,22 +50,23 @@ import { FormProperty } from '@shared/models/dynamic-form.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-data-keys-panel', - templateUrl: './data-keys-panel.component.html', - styleUrls: ['./data-keys-panel.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DataKeysPanelComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DataKeysPanelComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-data-keys-panel', + templateUrl: './data-keys-panel.component.html', + styleUrls: ['./data-keys-panel.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DataKeysPanelComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DataKeysPanelComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DataKeysPanelComponent implements ControlValueAccessor, OnInit, OnChanges, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/widget-actions-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/widget-actions-panel.component.ts index f63825a285..0320dc7fd1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/widget-actions-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/widget-actions-panel.component.ts @@ -28,16 +28,17 @@ import { MatDialog } from '@angular/material/dialog'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-widget-actions-panel', - templateUrl: './widget-actions-panel.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => WidgetActionsPanelComponent), - multi: true - } - ] + selector: 'tb-widget-actions-panel', + templateUrl: './widget-actions-panel.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => WidgetActionsPanelComponent), + multi: true + } + ], + standalone: false }) export class WidgetActionsPanelComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/entity/entities-table-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/entity/entities-table-basic-config.component.ts index b9d0efe45d..ea49d88c8d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/entity/entities-table-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/entity/entities-table-basic-config.component.ts @@ -35,9 +35,10 @@ import { } from '@home/components/widget/config/timewindow-config-panel.component'; @Component({ - selector: 'tb-entities-table-basic-config', - templateUrl: './entities-table-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-entities-table-basic-config', + templateUrl: './entities-table-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class EntitiesTableBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/entity/entity-count-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/entity/entity-count-basic-config.component.ts index 53712619a1..7928be4ba2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/entity/entity-count-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/entity/entity-count-basic-config.component.ts @@ -28,9 +28,10 @@ import { UtilsService } from '@core/services/utils.service'; import { countDefaultSettings, CountWidgetSettings } from '@home/components/widget/lib/count/count-widget.models'; @Component({ - selector: 'tb-entity-count-basic-config', - templateUrl: './entity-count-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-entity-count-basic-config', + templateUrl: './entity-count-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class EntityCountBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/compass-gauge-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/compass-gauge-basic-config.component.ts index f0b8188075..04c3141aef 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/compass-gauge-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/compass-gauge-basic-config.component.ts @@ -33,9 +33,10 @@ import { import { isUndefined } from '@core/utils'; @Component({ - selector: 'tb-compass-gauge-basic-config', - templateUrl: './compass-gauge-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-compass-gauge-basic-config', + templateUrl: './compass-gauge-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class CompassGaugeBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/digital-simple-gauge-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/digital-simple-gauge-basic-config.component.ts index c90c19aca8..e0ca65cdea 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/digital-simple-gauge-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/digital-simple-gauge-basic-config.component.ts @@ -45,9 +45,10 @@ import { ColorSettings, ColorType } from '@shared/models/widget-settings.models' import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-digital-simple-gauge-basic-config', - templateUrl: './digital-simple-gauge-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-digital-simple-gauge-basic-config', + templateUrl: './digital-simple-gauge-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class DigitalSimpleGaugeBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/radial-gauge-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/radial-gauge-basic-config.component.ts index 4b832956e6..e156c0bbfc 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/radial-gauge-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/radial-gauge-basic-config.component.ts @@ -25,9 +25,10 @@ import { WidgetConfigComponent } from '@home/components/widget/widget-config.com import { WidgetConfigComponentData } from '@home/models/widget-component.models'; @Component({ - selector: 'tb-radial-gauge-basic-config', - templateUrl: './analog-gauge-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-radial-gauge-basic-config', + templateUrl: './analog-gauge-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class RadialGaugeBasicConfigComponent extends GaugeBasicConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/thermometer-scale-gauge-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/thermometer-scale-gauge-basic-config.component.ts index c8d560370e..d173b9bce9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/thermometer-scale-gauge-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/thermometer-scale-gauge-basic-config.component.ts @@ -25,9 +25,10 @@ import { WidgetConfigComponent } from '@home/components/widget/widget-config.com import { WidgetConfigComponentData } from '@home/models/widget-component.models'; @Component({ - selector: 'tb-thermometer-scale-gauge-basic-config', - templateUrl: './analog-gauge-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-thermometer-scale-gauge-basic-config', + templateUrl: './analog-gauge-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class ThermometerScaleGaugeBasicConfigComponent extends GaugeBasicConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/battery-level-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/battery-level-basic-config.component.ts index ac8bf4891d..af236c54cd 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/battery-level-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/battery-level-basic-config.component.ts @@ -46,9 +46,10 @@ import { import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-battery-level-basic-config', - templateUrl: './battery-level-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-battery-level-basic-config', + templateUrl: './battery-level-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class BatteryLevelBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/liquid-level-card-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/liquid-level-card-basic-config.component.ts index af11303c46..72820c9564 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/liquid-level-card-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/liquid-level-card-basic-config.component.ts @@ -66,9 +66,10 @@ import { UtilsService } from '@core/services/utils.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-liquid-level-card-basic-config', - templateUrl: './liquid-level-card-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-liquid-level-card-basic-config', + templateUrl: './liquid-level-card-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class LiquidLevelCardBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/signal-strength-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/signal-strength-basic-config.component.ts index 0e2fce08be..db6ebaeaa0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/signal-strength-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/signal-strength-basic-config.component.ts @@ -49,9 +49,10 @@ import { import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-signal-strength-basic-config', - templateUrl: './signal-strength-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-signal-strength-basic-config', + templateUrl: './signal-strength-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class SignalStrengthBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.ts index 8abefc479f..3048f509ff 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.ts @@ -33,9 +33,10 @@ import { } from '@home/components/widget/lib/indicator/status-widget.models'; @Component({ - selector: 'tb-status-widget-basic-config', - templateUrl: './status-widget-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-status-widget-basic-config', + templateUrl: './status-widget-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class StatusWidgetBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/map/map-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/map/map-basic-config.component.ts index 1a1543218e..67e88597b2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/map/map-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/map/map-basic-config.component.ts @@ -31,9 +31,10 @@ import { } from '@home/components/widget/config/timewindow-config-panel.component'; @Component({ - selector: 'tb-map-basic-config', - templateUrl: './map-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-map-basic-config', + templateUrl: './map-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class MapBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.ts index 1d8a741c91..cdf8a72fe7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.ts @@ -33,9 +33,10 @@ import { import { ValueType } from '@shared/models/constants'; @Component({ - selector: 'tb-single-switch-basic-config', - templateUrl: './single-switch-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-single-switch-basic-config', + templateUrl: './single-switch-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class SingleSwitchBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/slider-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/slider-basic-config.component.ts index bb24654704..1946db01f8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/slider-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/slider-basic-config.component.ts @@ -36,9 +36,10 @@ import { cssSizeToStrSize, resolveCssSize } from '@shared/models/widget-settings import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-slider-basic-config', - templateUrl: './slider-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-slider-basic-config', + templateUrl: './slider-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class SliderBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/value-stepper-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/value-stepper-basic-config.component.ts index a149118743..d9806967d3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/value-stepper-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/value-stepper-basic-config.component.ts @@ -36,9 +36,10 @@ import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; type ButtonAppearanceType = 'left' | 'right'; @Component({ - selector: 'tb-value-stepper-basic-config', - templateUrl: './value-stepper-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-value-stepper-basic-config', + templateUrl: './value-stepper-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class ValueStepperBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/scada/scada-symbol-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/scada/scada-symbol-basic-config.component.ts index 46a87c89e3..e118e2a4b8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/scada/scada-symbol-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/scada/scada-symbol-basic-config.component.ts @@ -30,9 +30,10 @@ import { isUndefined } from '@core/utils'; import { cssSizeToStrSize, resolveCssSize } from '@shared/models/widget-settings.models'; @Component({ - selector: 'tb-scada-symbol-basic-config', - templateUrl: './scada-symbol-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-scada-symbol-basic-config', + templateUrl: './scada-symbol-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class ScadaSymbolBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.ts index ba45cfe3b3..b48d44de6d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.ts @@ -46,9 +46,10 @@ import { import { getSourceTbUnitSymbol, TbUnit } from '@shared/models/unit.models'; @Component({ - selector: 'tb-wind-speed-direction-basic-config', - templateUrl: './wind-speed-direction-basic-config.component.html', - styleUrls: ['../basic-config.scss'] + selector: 'tb-wind-speed-direction-basic-config', + templateUrl: './wind-speed-direction-basic-config.component.html', + styleUrls: ['../basic-config.scss'], + standalone: false }) export class WindSpeedDirectionBasicConfigComponent extends BasicWidgetConfigComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/datasource.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/datasource.component.ts index dcec6497da..6dcfee5146 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/datasource.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/datasource.component.ts @@ -47,21 +47,22 @@ import { FormProperty } from '@shared/models/dynamic-form.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-datasource', - templateUrl: './datasource.component.html', - styleUrls: ['./datasource.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DatasourceComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DatasourceComponent), - multi: true, - } - ] + selector: 'tb-datasource', + templateUrl: './datasource.component.html', + styleUrls: ['./datasource.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DatasourceComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DatasourceComponent), + multi: true, + } + ], + standalone: false }) export class DatasourceComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/datasources.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/datasources.component.ts index dd518177d0..36dcbbd9f8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/datasources.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/datasources.component.ts @@ -46,21 +46,22 @@ import { FormProperty } from '@shared/models/dynamic-form.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-datasources', - templateUrl: './datasources.component.html', - styleUrls: ['./datasources.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DatasourcesComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DatasourcesComponent), - multi: true, - } - ] + selector: 'tb-datasources', + templateUrl: './datasources.component.html', + styleUrls: ['./datasources.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DatasourcesComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DatasourcesComponent), + multi: true, + } + ], + standalone: false }) export class DatasourcesComponent implements ControlValueAccessor, OnInit, Validator, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/target-device.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/target-device.component.ts index 3b68b52668..bcabcf9099 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/target-device.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/target-device.component.ts @@ -35,21 +35,22 @@ import { EntityAliasSelectCallbacks } from '@home/components/widget/lib/settings import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-target-device', - templateUrl: './target-device.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TargetDeviceComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => TargetDeviceComponent), - multi: true, - } - ] + selector: 'tb-target-device', + templateUrl: './target-device.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TargetDeviceComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => TargetDeviceComponent), + multi: true, + } + ], + standalone: false }) export class TargetDeviceComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/timewindow-config-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/timewindow-config-panel.component.ts index 1c1ecf9e2f..03a7804658 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/timewindow-config-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/timewindow-config-panel.component.ts @@ -49,16 +49,17 @@ export const setTimewindowConfig = (config: WidgetConfig, data: TimewindowConfig }; @Component({ - selector: 'tb-timewindow-config-panel', - templateUrl: './timewindow-config-panel.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimewindowConfigPanelComponent), - multi: true - } - ] + selector: 'tb-timewindow-config-panel', + templateUrl: './timewindow-config-panel.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimewindowConfigPanelComponent), + multi: true + } + ], + standalone: false }) export class TimewindowConfigPanelComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/timewindow-style-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/timewindow-style-panel.component.ts index 0a3dc78902..4370dfc358 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/timewindow-style-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/timewindow-style-panel.component.ts @@ -26,11 +26,12 @@ import { deepClone } from '@core/utils'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-timewindow-style-panel', - templateUrl: './timewindow-style-panel.component.html', - providers: [], - styleUrls: ['./timewindow-style-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-timewindow-style-panel', + templateUrl: './timewindow-style-panel.component.html', + providers: [], + styleUrls: ['./timewindow-style-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class TimewindowStylePanelComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/timewindow-style.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/timewindow-style.component.ts index 03abbf7c2a..d0e0eef7e2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/timewindow-style.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/timewindow-style.component.ts @@ -23,16 +23,17 @@ import { Timewindow } from '@shared/models/time/time.models'; import { TimewindowStylePanelComponent } from '@home/components/widget/config/timewindow-style-panel.component'; @Component({ - selector: 'tb-timewindow-style', - templateUrl: './timewindow-style.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimewindowStyleComponent), - multi: true - } - ] + selector: 'tb-timewindow-style', + templateUrl: './timewindow-style.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimewindowStyleComponent), + multi: true + } + ], + standalone: false }) export class TimewindowStyleComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog-container.component.ts b/ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog-container.component.ts index 3c05469d04..31c63187ae 100644 --- a/ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog-container.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog-container.component.ts @@ -44,8 +44,9 @@ export interface CustomDialogContainerData { } @Component({ - selector: 'tb-custom-dialog-container-component', - template: '' + selector: 'tb-custom-dialog-container-component', + template: '', + standalone: false }) export class CustomDialogContainerComponent extends DialogComponent implements OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/dialog/embed-dashboard-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/dialog/embed-dashboard-dialog.component.ts index 667316f76b..5b791ada3f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/dialog/embed-dashboard-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/dialog/embed-dashboard-dialog.component.ts @@ -34,9 +34,10 @@ export interface EmbedDashboardDialogData { } @Component({ - selector: 'tb-embed-dashboard-dialog', - templateUrl: './embed-dashboard-dialog.component.html', - styleUrls: ['./embed-dashboard-dialog.component.scss'] + selector: 'tb-embed-dashboard-dialog', + templateUrl: './embed-dashboard-dialog.component.html', + styleUrls: ['./embed-dashboard-dialog.component.scss'], + standalone: false }) export class EmbedDashboardDialogComponent extends DialogComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/alarm/alarms-table-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/alarm/alarms-table-widget.component.ts index 1a5f6a018f..31927e0cb3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/alarm/alarms-table-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/alarm/alarms-table-widget.component.ts @@ -166,9 +166,10 @@ interface AlarmWidgetActionDescriptor extends TableCellButtonActionDescriptor { } @Component({ - selector: 'tb-alarms-table-widget', - templateUrl: './alarms-table-widget.component.html', - styleUrls: ['./alarms-table-widget.component.scss', './../table-widget.scss'] + selector: 'tb-alarms-table-widget', + templateUrl: './alarms-table-widget.component.html', + styleUrls: ['./alarms-table-widget.component.scss', './../table-widget.scss'], + standalone: false }) export class AlarmsTableWidgetComponent extends PageComponent implements OnInit, OnDestroy, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/button/action-button-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/button/action-button-widget.component.ts index 9a397eaf9b..eaa723acd3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/button/action-button-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/button/action-button-widget.component.ts @@ -26,10 +26,11 @@ import { import { WidgetButtonAppearance } from '@shared/components/button/widget-button.models'; @Component({ - selector: 'tb-action-button-widget', - templateUrl: './action-button-widget.component.html', - styleUrls: ['../action/action-widget.scss', './action-button-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-action-button-widget', + templateUrl: './action-button-widget.component.html', + styleUrls: ['../action/action-widget.scss', './action-button-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ActionButtonWidgetComponent extends BasicActionWidgetComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/button/command-button-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/button/command-button-widget.component.ts index ca863f9108..70298808da 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/button/command-button-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/button/command-button-widget.component.ts @@ -26,10 +26,11 @@ import { } from '@home/components/widget/lib/button/command-button-widget.models'; @Component({ - selector: 'tb-command-button-widget', - templateUrl: './command-button-widget.component.html', - styleUrls: ['../action/action-widget.scss', './command-button-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-command-button-widget', + templateUrl: './command-button-widget.component.html', + styleUrls: ['../action/action-widget.scss', './command-button-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class CommandButtonWidgetComponent extends BasicActionWidgetComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.component.ts index 9c20a279ed..a1601a6fb8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.component.ts @@ -28,10 +28,11 @@ import { Observable } from 'rxjs'; import { backgroundStyle, ComponentStyle, overlayStyle } from '@shared/models/widget-settings.models'; @Component({ - selector: 'tb-toggle-button-widget', - templateUrl: './toggle-button-widget.component.html', - styleUrls: ['../action/action-widget.scss', './toggle-button-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-toggle-button-widget', + templateUrl: './toggle-button-widget.component.html', + styleUrls: ['../action/action-widget.scss', './toggle-button-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ToggleButtonWidgetComponent extends BasicActionWidgetComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/button/two-segment-button-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/button/two-segment-button-widget.component.ts index efff97c29c..46382dab77 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/button/two-segment-button-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/button/two-segment-button-widget.component.ts @@ -28,10 +28,11 @@ import { ComponentStyle } from '@shared/models/widget-settings.models'; import { MatButtonToggleChange } from '@angular/material/button-toggle'; @Component({ - selector: 'tb-two-segment-button-widget', - templateUrl: './two-segment-button-widget.component.html', - styleUrls: ['../action/action-widget.scss', './two-segment-button-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-two-segment-button-widget', + templateUrl: './two-segment-button-widget.component.html', + styleUrls: ['../action/action-widget.scss', './two-segment-button-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class TwoSegmentButtonWidgetComponent extends BasicActionWidgetComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/aggregated-value-card-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/aggregated-value-card-widget.component.ts index 3a4a836c5e..c4b07619e7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/aggregated-value-card-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/aggregated-value-card-widget.component.ts @@ -63,9 +63,10 @@ const valuesLayoutHeight = 66; const valuesLayoutVerticalPadding = 16; @Component({ - selector: 'tb-aggregated-value-card-widget', - templateUrl: './aggregated-value-card-widget.component.html', - styleUrls: ['./aggregated-value-card-widget.component.scss'] + selector: 'tb-aggregated-value-card-widget', + templateUrl: './aggregated-value-card-widget.component.html', + styleUrls: ['./aggregated-value-card-widget.component.scss'], + standalone: false }) export class AggregatedValueCardWidgetComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/label-card-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/label-card-widget.component.ts index 195e683c57..52905a0469 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/label-card-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/label-card-widget.component.ts @@ -45,10 +45,11 @@ import { ImagePipe } from '@shared/pipe/image.pipe'; import { DomSanitizer } from '@angular/platform-browser'; @Component({ - selector: 'tb-label-card-widget', - templateUrl: './label-card-widget.component.html', - styleUrls: ['./label-card-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-label-card-widget', + templateUrl: './label-card-widget.component.html', + styleUrls: ['./label-card-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class LabelCardWidgetComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/label-value-card-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/label-value-card-widget.component.ts index 978d52d854..04e2c03679 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/label-value-card-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/label-value-card-widget.component.ts @@ -50,10 +50,11 @@ import { import { isDefinedAndNotNull } from '@core/utils'; @Component({ - selector: 'tb-label-value-card-widget', - templateUrl: './label-value-card-widget.component.html', - styleUrls: ['./label-value-card-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-label-value-card-widget', + templateUrl: './label-value-card-widget.component.html', + styleUrls: ['./label-value-card-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class LabelValueCardWidgetComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/notification-type-filter-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/notification-type-filter-panel.component.ts index 30976c8442..a39044c759 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/notification-type-filter-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/notification-type-filter-panel.component.ts @@ -32,9 +32,10 @@ export interface NotificationTypeFilterPanelData { } @Component({ - selector: 'tb-notification-type-filter-panel', - templateUrl: './notification-type-filter-panel.component.html', - styleUrls: ['notification-type-filter-panel.component.scss'] + selector: 'tb-notification-type-filter-panel', + templateUrl: './notification-type-filter-panel.component.html', + styleUrls: ['notification-type-filter-panel.component.scss'], + standalone: false }) export class NotificationTypeFilterPanelComponent implements OnInit{ diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/progress-bar-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/progress-bar-widget.component.ts index 66f5d90254..bc4180b0e7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/progress-bar-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/progress-bar-widget.component.ts @@ -52,10 +52,11 @@ const defaultAspect = defaultLayoutHeight / 150; const simplifiedAspect = simplifiedLayoutHeight / 150; @Component({ - selector: 'tb-progress-bar-widget', - templateUrl: './progress-bar-widget.component.html', - styleUrls: ['./progress-bar-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-progress-bar-widget', + templateUrl: './progress-bar-widget.component.html', + styleUrls: ['./progress-bar-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ProgressBarWidgetComponent implements OnInit, OnDestroy, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/unread-notification-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/unread-notification-widget.component.ts index 450d59e22e..e68cddacf0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/unread-notification-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/unread-notification-widget.component.ts @@ -54,10 +54,11 @@ import { select, Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-unread-notification-widget', - templateUrl: './unread-notification-widget.component.html', - styleUrls: ['unread-notification-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-unread-notification-widget', + templateUrl: './unread-notification-widget.component.html', + styleUrls: ['unread-notification-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class UnreadNotificationWidgetComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts index 4db8f11ba2..b994ff8b23 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts @@ -52,9 +52,10 @@ const squareLayoutSize = 160; const horizontalLayoutHeight = 80; @Component({ - selector: 'tb-value-card-widget', - templateUrl: './value-card-widget.component.html', - styleUrls: ['./value-card-widget.component.scss'] + selector: 'tb-value-card-widget', + templateUrl: './value-card-widget.component.html', + styleUrls: ['./value-card-widget.component.scss'], + standalone: false }) export class ValueCardWidgetComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-chart-card-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-chart-card-widget.component.ts index 0198fdf6e3..5da48a00d3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-chart-card-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-chart-card-widget.component.ts @@ -62,10 +62,11 @@ const layoutHeight = 56; const valueRelativeWidth = 0.35; @Component({ - selector: 'tb-value-chart-card-widget', - templateUrl: './value-chart-card-widget.component.html', - styleUrls: ['./value-chart-card-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-value-chart-card-widget', + templateUrl: './value-chart-card-widget.component.html', + styleUrls: ['./value-chart-card-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ValueChartCardWidgetComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-widget.component.ts index b6c88a7d3a..3fb90f4f21 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-widget.component.ts @@ -30,10 +30,11 @@ import { import { TbBarsChart } from '@home/components/widget/lib/chart/bars-chart'; @Component({ - selector: 'tb-bar-chart-widget', - templateUrl: './latest-chart-widget.component.html', - styleUrls: [], - encapsulation: ViewEncapsulation.None + selector: 'tb-bar-chart-widget', + templateUrl: './latest-chart-widget.component.html', + styleUrls: [], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class BarChartWidgetComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts index f9bd213fdb..1f63cd8638 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts @@ -43,10 +43,11 @@ import { DataKey } from '@shared/models/widget.models'; import { WidgetComponent } from '@home/components/widget/widget.component'; @Component({ - selector: 'tb-bar-chart-with-labels-widget', - templateUrl: './bar-chart-with-labels-widget.component.html', - styleUrls: ['./bar-chart-with-labels-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-bar-chart-with-labels-widget', + templateUrl: './bar-chart-with-labels-widget.component.html', + styleUrls: ['./bar-chart-with-labels-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class BarChartWithLabelsWidgetComponent implements OnInit, OnDestroy, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/doughnut-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/doughnut-widget.component.ts index 00cc814246..64b4f2caf2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/doughnut-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/doughnut-widget.component.ts @@ -31,10 +31,11 @@ import { } from '@home/components/widget/lib/chart/latest-chart.component'; @Component({ - selector: 'tb-doughnut-widget', - templateUrl: './latest-chart-widget.component.html', - styleUrls: [], - encapsulation: ViewEncapsulation.None + selector: 'tb-doughnut-widget', + templateUrl: './latest-chart-widget.component.html', + styleUrls: [], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DoughnutWidgetComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart.component.ts index facd9f0cad..7dd9c060c7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart.component.ts @@ -49,10 +49,11 @@ export interface LatestChartComponentCallbacks { } @Component({ - selector: 'tb-latest-chart', - templateUrl: './latest-chart.component.html', - styleUrls: ['./latest-chart.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-latest-chart', + templateUrl: './latest-chart.component.html', + styleUrls: ['./latest-chart.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class LatestChartComponent implements OnInit, OnDestroy, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/pie-chart-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/pie-chart-widget.component.ts index 2ea605739c..3da64540e3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/pie-chart-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/pie-chart-widget.component.ts @@ -30,10 +30,11 @@ import { } from '@home/components/widget/lib/chart/pie-chart-widget.models'; @Component({ - selector: 'tb-pie-chart-widget', - templateUrl: './latest-chart-widget.component.html', - styleUrls: [], - encapsulation: ViewEncapsulation.None + selector: 'tb-pie-chart-widget', + templateUrl: './latest-chart-widget.component.html', + styleUrls: [], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class PieChartWidgetComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/polar-area-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/polar-area-widget.component.ts index adc74628c5..d54ced555b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/polar-area-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/polar-area-widget.component.ts @@ -30,10 +30,11 @@ import { } from '@home/components/widget/lib/chart/polar-area-widget.models'; @Component({ - selector: 'tb-polar-area-chart-widget', - templateUrl: './latest-chart-widget.component.html', - styleUrls: [], - encapsulation: ViewEncapsulation.None + selector: 'tb-polar-area-chart-widget', + templateUrl: './latest-chart-widget.component.html', + styleUrls: [], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class PolarAreaWidgetComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/radar-chart-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/radar-chart-widget.component.ts index 305ae940ca..7bf770e3ff 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/radar-chart-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/radar-chart-widget.component.ts @@ -30,10 +30,11 @@ import { import { TbRadarChart } from '@home/components/widget/lib/chart/radar-chart'; @Component({ - selector: 'tb-radar-chart-widget', - templateUrl: './latest-chart-widget.component.html', - styleUrls: [], - encapsulation: ViewEncapsulation.None + selector: 'tb-radar-chart-widget', + templateUrl: './latest-chart-widget.component.html', + styleUrls: [], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class RadarChartWidgetComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts index 27fe86a393..2412d51a83 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts @@ -54,10 +54,11 @@ import { TbUnit } from '@shared/models/unit.models'; import { UnitService } from '@core/services/unit.service'; @Component({ - selector: 'tb-range-chart-widget', - templateUrl: './range-chart-widget.component.html', - styleUrls: ['./range-chart-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-range-chart-widget', + templateUrl: './range-chart-widget.component.html', + styleUrls: ['./range-chart-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class RangeChartWidgetComponent implements OnInit, OnDestroy, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.ts index b96ff3996f..aa94ee717c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.ts @@ -46,10 +46,11 @@ import { mergeDeep } from '@core/utils'; import { WidgetComponent } from '@home/components/widget/widget.component'; @Component({ - selector: 'tb-time-series-chart-widget', - templateUrl: './time-series-chart-widget.component.html', - styleUrls: ['./time-series-chart-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-time-series-chart-widget', + templateUrl: './time-series-chart-widget.component.html', + styleUrls: ['./time-series-chart-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class TimeSeriesChartWidgetComponent implements OnInit, OnDestroy, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/count/count-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/count/count-widget.component.ts index 611223c5df..01a652b03f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/count/count-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/count/count-widget.component.ts @@ -48,9 +48,10 @@ const layoutHeightWithTitle = 60; const layoutPadding = 24; @Component({ - selector: 'tb-count-widget', - templateUrl: './count-widget.component.html', - styleUrls: ['./count-widget.component.scss'] + selector: 'tb-count-widget', + templateUrl: './count-widget.component.html', + styleUrls: ['./count-widget.component.scss'], + standalone: false }) export class CountWidgetComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/date-range-navigator/date-range-navigator.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/date-range-navigator/date-range-navigator.component.ts index 2870287548..2dc78059e9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/date-range-navigator/date-range-navigator.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/date-range-navigator/date-range-navigator.component.ts @@ -50,9 +50,10 @@ import { HistoryWindowType, TimewindowType } from '@shared/models/time/time.mode import { isDefined } from '@core/utils'; @Component({ - selector: 'tb-date-range-navigator-widget', - templateUrl: './date-range-navigator.component.html', - styleUrls: ['./date-range-navigator.component.scss'] + selector: 'tb-date-range-navigator-widget', + templateUrl: './date-range-navigator.component.html', + styleUrls: ['./date-range-navigator.component.scss'], + standalone: false }) export class DateRangeNavigatorWidgetComponent extends PageComponent implements OnInit, OnDestroy { @@ -276,10 +277,11 @@ export interface DateRangeNavigatorPanelData { } @Component({ - selector: 'tb-date-range-navigator-panel', - templateUrl: './date-range-navigator-panel.component.html', - styleUrls: ['./date-range-navigator-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-date-range-navigator-panel', + templateUrl: './date-range-navigator-panel.component.html', + styleUrls: ['./date-range-navigator-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DateRangeNavigatorPanelComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/display-columns-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/display-columns-panel.component.ts index e868919b92..54af0a4916 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/display-columns-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/display-columns-panel.component.ts @@ -25,9 +25,10 @@ export interface DisplayColumnsPanelData { } @Component({ - selector: 'tb-display-columns-panel', - templateUrl: './display-columns-panel.component.html', - styleUrls: ['./display-columns-panel.component.scss'] + selector: 'tb-display-columns-panel', + templateUrl: './display-columns-panel.component.html', + styleUrls: ['./display-columns-panel.component.scss'], + standalone: false }) export class DisplayColumnsPanelComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/edges-overview-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/edges-overview-widget.component.ts index 797ea4a03d..5f11d57cc4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/edges-overview-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/edges-overview-widget.component.ts @@ -48,9 +48,10 @@ interface EdgesOverviewWidgetSettings { } @Component({ - selector: 'tb-edges-overview-widget', - templateUrl: './edges-overview-widget.component.html', - styleUrls: ['./edges-overview-widget.component.scss'] + selector: 'tb-edges-overview-widget', + templateUrl: './edges-overview-widget.component.html', + styleUrls: ['./edges-overview-widget.component.scss'], + standalone: false }) export class EdgesOverviewWidgetComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/entity/entities-hierarchy-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/entity/entities-hierarchy-widget.component.ts index 5820625076..12cd55f5b1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/entity/entities-hierarchy-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/entity/entities-hierarchy-widget.component.ts @@ -72,9 +72,10 @@ import { FormBuilder } from '@angular/forms'; import { Subject } from 'rxjs'; @Component({ - selector: 'tb-entities-hierarchy-widget', - templateUrl: './entities-hierarchy-widget.component.html', - styleUrls: ['./entities-hierarchy-widget.component.scss'] + selector: 'tb-entities-hierarchy-widget', + templateUrl: './entities-hierarchy-widget.component.html', + styleUrls: ['./entities-hierarchy-widget.component.scss'], + standalone: false }) export class EntitiesHierarchyWidgetComponent extends PageComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/entity/entities-table-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/entity/entities-table-widget.component.ts index 8d89e6cd6d..b99ba01212 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/entity/entities-table-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/entity/entities-table-widget.component.ts @@ -123,9 +123,10 @@ interface EntitiesTableWidgetSettings extends TableWidgetSettings { } @Component({ - selector: 'tb-entities-table-widget', - templateUrl: './entities-table-widget.component.html', - styleUrls: ['./entities-table-widget.component.scss', './../table-widget.scss'] + selector: 'tb-entities-table-widget', + templateUrl: './entities-table-widget.component.html', + styleUrls: ['./entities-table-widget.component.scss', './../table-widget.scss'], + standalone: false }) export class EntitiesTableWidgetComponent extends PageComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.component.ts index 0b670879ac..93c93f9004 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.component.ts @@ -28,9 +28,10 @@ import { import { isDefinedAndNotNull } from '@core/utils'; @Component({ - selector: 'tb-flot-widget', - templateUrl: './flot-widget.component.html', - styleUrls: [] + selector: 'tb-flot-widget', + templateUrl: './flot-widget.component.html', + styleUrls: [], + standalone: false }) export class FlotWidgetComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/add-doc-link-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/add-doc-link-dialog.component.ts index 447508e808..cef15ed649 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/add-doc-link-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/add-doc-link-dialog.component.ts @@ -25,9 +25,10 @@ import { Router } from '@angular/router'; import { DocumentationLink } from '@shared/models/user-settings.models'; @Component({ - selector: 'tb-add-doc-link-dialog', - templateUrl: './add-doc-link-dialog.component.html', - styleUrls: ['./add-doc-link-dialog.component.scss'] + selector: 'tb-add-doc-link-dialog', + templateUrl: './add-doc-link-dialog.component.html', + styleUrls: ['./add-doc-link-dialog.component.scss'], + standalone: false }) export class AddDocLinkDialogComponent extends DialogComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/add-quick-link-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/add-quick-link-dialog.component.ts index f7cac6cdf9..69087d21ee 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/add-quick-link-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/add-quick-link-dialog.component.ts @@ -24,9 +24,10 @@ import { DialogComponent } from '@shared/components/dialog.component'; import { Router } from '@angular/router'; @Component({ - selector: 'tb-add-quick-link-dialog', - templateUrl: './add-quick-link-dialog.component.html', - styleUrls: ['./add-quick-link-dialog.component.scss'] + selector: 'tb-add-quick-link-dialog', + templateUrl: './add-quick-link-dialog.component.html', + styleUrls: ['./add-quick-link-dialog.component.scss'], + standalone: false }) export class AddQuickLinkDialogComponent extends DialogComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/cluster-info-table.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/cluster-info-table.component.ts index 927c80da30..625ddca093 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/cluster-info-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/cluster-info-table.component.ts @@ -43,9 +43,10 @@ export interface SystemInfoData { } @Component({ - selector: 'tb-cluster-info-table', - templateUrl: './cluster-info-table.component.html', - styleUrls: ['./cluster-info-table.component.scss'] + selector: 'tb-cluster-info-table', + templateUrl: './cluster-info-table.component.html', + styleUrls: ['./cluster-info-table.component.scss'], + standalone: false }) export class ClusterInfoTableComponent extends PageComponent implements OnInit, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/configured-features.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/configured-features.component.ts index 835df2f99d..06808d75ba 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/configured-features.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/configured-features.component.ts @@ -28,9 +28,10 @@ import { TranslateService } from '@ngx-translate/core'; import { MediaBreakpoints } from '@shared/models/constants'; @Component({ - selector: 'tb-configured-features', - templateUrl: './configured-features.component.html', - styleUrls: ['./home-page-widget.scss', './configured-features.component.scss'] + selector: 'tb-configured-features', + templateUrl: './configured-features.component.html', + styleUrls: ['./home-page-widget.scss', './configured-features.component.scss'], + standalone: false }) export class ConfiguredFeaturesComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/doc-link.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/doc-link.component.ts index 73c91d64b4..17f96f3b74 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/doc-link.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/doc-link.component.ts @@ -29,17 +29,18 @@ import { DocumentationLink } from '@shared/models/user-settings.models'; import { ErrorStateMatcher } from '@angular/material/core'; @Component({ - selector: 'tb-doc-link', - templateUrl: './doc-link.component.html', - styleUrls: ['./link.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DocLinkComponent), - multi: true - }, - {provide: ErrorStateMatcher, useExisting: DocLinkComponent} - ] + selector: 'tb-doc-link', + templateUrl: './doc-link.component.html', + styleUrls: ['./link.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DocLinkComponent), + multi: true + }, + { provide: ErrorStateMatcher, useExisting: DocLinkComponent } + ], + standalone: false }) export class DocLinkComponent extends PageComponent implements OnInit, ControlValueAccessor, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/doc-links-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/doc-links-widget.component.ts index 56b2418a81..74159f184c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/doc-links-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/doc-links-widget.component.ts @@ -100,9 +100,10 @@ interface DocLinksWidgetSettings { } @Component({ - selector: 'tb-doc-links-widget', - templateUrl: './doc-links-widget.component.html', - styleUrls: ['./home-page-widget.scss', './links-widget.component.scss'] + selector: 'tb-doc-links-widget', + templateUrl: './doc-links-widget.component.html', + styleUrls: ['./home-page-widget.scss', './links-widget.component.scss'], + standalone: false }) export class DocLinksWidgetComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/edit-links-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/edit-links-dialog.component.ts index 224d963a23..6e33e8e645 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/edit-links-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/edit-links-dialog.component.ts @@ -32,9 +32,10 @@ export interface EditLinksDialogData { } @Component({ - selector: 'tb-edit-links-dialog', - templateUrl: './edit-links-dialog.component.html', - styleUrls: ['./edit-links-dialog.component.scss'] + selector: 'tb-edit-links-dialog', + templateUrl: './edit-links-dialog.component.html', + styleUrls: ['./edit-links-dialog.component.scss'], + standalone: false }) export class EditLinksDialogComponent extends DialogComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/getting-started-completed-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/getting-started-completed-dialog.component.ts index 13356e6a1c..9d21b73dd3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/getting-started-completed-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/getting-started-completed-dialog.component.ts @@ -23,10 +23,11 @@ import { DialogComponent } from '@shared/components/dialog.component'; import { Router } from '@angular/router'; @Component({ - selector: 'tb-getting-started-completed-dialog', - templateUrl: './getting-started-completed-dialog.component.html', - styleUrls: ['./getting-started-completed-dialog.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-getting-started-completed-dialog', + templateUrl: './getting-started-completed-dialog.component.html', + styleUrls: ['./getting-started-completed-dialog.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class GettingStartedCompletedDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/getting-started-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/getting-started-widget.component.ts index a6d901c2af..6c13054b67 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/getting-started-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/getting-started-widget.component.ts @@ -33,9 +33,10 @@ import { first } from 'rxjs/operators'; import { Authority } from '@shared/models/authority.enum'; @Component({ - selector: 'tb-getting-started-widget', - templateUrl: './getting-started-widget.component.html', - styleUrls: ['./getting-started-widget.component.scss'] + selector: 'tb-getting-started-widget', + templateUrl: './getting-started-widget.component.html', + styleUrls: ['./getting-started-widget.component.scss'], + standalone: false }) export class GettingStartedWidgetComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/quick-link.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/quick-link.component.ts index c7d9a640d2..f9221dfb5f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/quick-link.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/quick-link.component.ts @@ -52,17 +52,18 @@ import { deepClone } from '@core/utils'; import { CustomTranslatePipe } from '@shared/pipe/custom-translate.pipe'; @Component({ - selector: 'tb-quick-link', - templateUrl: './quick-link.component.html', - styleUrls: ['./link.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => QuickLinkComponent), - multi: true - }, - {provide: ErrorStateMatcher, useExisting: QuickLinkComponent} - ] + selector: 'tb-quick-link', + templateUrl: './quick-link.component.html', + styleUrls: ['./link.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => QuickLinkComponent), + multi: true + }, + { provide: ErrorStateMatcher, useExisting: QuickLinkComponent } + ], + standalone: false }) export class QuickLinkComponent extends PageComponent implements OnInit, ControlValueAccessor, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/quick-links-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/quick-links-widget.component.ts index 3c1452decd..7d4783a3fe 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/quick-links-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/quick-links-widget.component.ts @@ -54,9 +54,10 @@ interface QuickLinksWidgetSettings { } @Component({ - selector: 'tb-quick-links-widget', - templateUrl: './quick-links-widget.component.html', - styleUrls: ['./home-page-widget.scss', './links-widget.component.scss'] + selector: 'tb-quick-links-widget', + templateUrl: './quick-links-widget.component.html', + styleUrls: ['./home-page-widget.scss', './links-widget.component.scss'], + standalone: false }) export class QuickLinksWidgetComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/recent-dashboards-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/recent-dashboards-widget.component.ts index f66c226379..899ffa5aea 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/recent-dashboards-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/recent-dashboards-widget.component.ts @@ -50,9 +50,10 @@ import { DashboardInfo } from '@shared/models/dashboard.models'; import { DashboardAutocompleteComponent } from '@shared/components/dashboard-autocomplete.component'; @Component({ - selector: 'tb-recent-dashboards-widget', - templateUrl: './recent-dashboards-widget.component.html', - styleUrls: ['./home-page-widget.scss', './recent-dashboards-widget.component.scss'] + selector: 'tb-recent-dashboards-widget', + templateUrl: './recent-dashboards-widget.component.html', + styleUrls: ['./home-page-widget.scss', './recent-dashboards-widget.component.scss'], + standalone: false }) export class RecentDashboardsWidgetComponent extends PageComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/usage-info-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/usage-info-widget.component.ts index aa7319f495..230d7842c2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/usage-info-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/usage-info-widget.component.ts @@ -27,9 +27,10 @@ import { UsageInfoService } from '@core/http/usage-info.service'; import { ShortNumberPipe } from '@shared/pipe/short-number.pipe'; @Component({ - selector: 'tb-usage-info-widget', - templateUrl: './usage-info-widget.component.html', - styleUrls: ['./home-page-widget.scss', './usage-info-widget.component.scss'] + selector: 'tb-usage-info-widget', + templateUrl: './usage-info-widget.component.html', + styleUrls: ['./home-page-widget.scss', './usage-info-widget.component.scss'], + standalone: false }) export class UsageInfoWidgetComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/version-info.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/version-info.component.ts index 5d9fc59c6e..f3cf60d3e1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/version-info.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/version-info.component.ts @@ -25,9 +25,10 @@ import { Authority } from '@shared/models/authority.enum'; import { of } from 'rxjs'; @Component({ - selector: 'tb-version-info', - templateUrl: './version-info.component.html', - styleUrls: ['./home-page-widget.scss', './version-info.component.scss'] + selector: 'tb-version-info', + templateUrl: './version-info.component.html', + styleUrls: ['./home-page-widget.scss', './version-info.component.scss'], + standalone: false }) export class VersionInfoComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.ts index ff95a4882f..47550763d4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.ts @@ -74,10 +74,11 @@ const horizontalBatteryDimensions = { }; @Component({ - selector: 'tb-battery-level-widget', - templateUrl: './battery-level-widget.component.html', - styleUrls: ['./battery-level-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-battery-level-widget', + templateUrl: './battery-level-widget.component.html', + styleUrls: ['./battery-level-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class BatteryLevelWidgetComponent implements OnInit, OnDestroy, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.ts index aeecc94050..f3d02a096a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.ts @@ -71,10 +71,11 @@ import { UnitService } from '@core/services/unit.service'; import ITooltipsterInstance = JQueryTooltipster.ITooltipsterInstance; @Component({ - selector: 'tb-liquid-level-widget', - templateUrl: './liquid-level-widget.component.html', - styleUrls: ['./liquid-level-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-liquid-level-widget', + templateUrl: './liquid-level-widget.component.html', + styleUrls: ['./liquid-level-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class LiquidLevelWidgetComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.component.ts index 9baa7e5e10..be4d992330 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.component.ts @@ -76,10 +76,11 @@ const shapeHeight = 113; const shapeAspect = shapeWidth / shapeHeight; @Component({ - selector: 'tb-signal-strength-widget', - templateUrl: './signal-strength-widget.component.html', - styleUrls: ['./signal-strength-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-signal-strength-widget', + templateUrl: './signal-strength-widget.component.html', + styleUrls: ['./signal-strength-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class SignalStrengthWidgetComponent implements OnInit, OnDestroy, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts index dd0a776939..e59570d44a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts @@ -48,10 +48,11 @@ import { ValueType } from '@shared/models/constants'; const initialStatusWidgetSize = 147; @Component({ - selector: 'tb-status-widget', - templateUrl: './status-widget.component.html', - styleUrls: ['../action/action-widget.scss', './status-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-status-widget', + templateUrl: './status-widget.component.html', + styleUrls: ['../action/action-widget.scss', './status-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class StatusWidgetComponent extends BasicActionWidgetComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/json-input-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/json-input-widget.component.ts index 3aa5f0cd71..f6a6bb0ad3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/json-input-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/json-input-widget.component.ts @@ -49,9 +49,10 @@ interface JsonInputWidgetSettings { } @Component({ - selector: 'tb-json-input-widget ', - templateUrl: './json-input-widget.component.html', - styleUrls: ['./json-input-widget.component.scss'] + selector: 'tb-json-input-widget ', + templateUrl: './json-input-widget.component.html', + styleUrls: ['./json-input-widget.component.scss'], + standalone: false }) export class JsonInputWidgetComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/legend.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/legend.component.ts index 41551b98f3..b570910fb7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/legend.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/legend.component.ts @@ -18,9 +18,10 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { LegendConfig, LegendData, LegendDirection, LegendKey, LegendPosition } from '@shared/models/widget.models'; @Component({ - selector: 'tb-legend', - templateUrl: './legend.component.html', - styleUrls: ['./legend.component.scss'] + selector: 'tb-legend', + templateUrl: './legend.component.html', + styleUrls: ['./legend.component.scss'], + standalone: false }) export class LegendComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps-legacy/dialogs/select-entity-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps-legacy/dialogs/select-entity-dialog.component.ts index d79a6d4dbd..71cfb95ebe 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps-legacy/dialogs/select-entity-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps-legacy/dialogs/select-entity-dialog.component.ts @@ -28,9 +28,10 @@ export interface SelectEntityDialogData { } @Component({ - selector: 'tb-select-entity-dialog', - templateUrl: './select-entity-dialog.component.html', - styleUrls: ['./select-entity-dialog.component.scss'] + selector: 'tb-select-entity-dialog', + templateUrl: './select-entity-dialog.component.html', + styleUrls: ['./select-entity-dialog.component.scss'], + standalone: false }) export class SelectEntityDialogComponent extends DialogComponent { selectEntityFormGroup: FormGroup; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.ts index ac55e9e5ab..e9b0e761f9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.ts @@ -40,10 +40,11 @@ import { ImagePipe } from '@shared/pipe/image.pipe'; import { DomSanitizer } from '@angular/platform-browser'; @Component({ - selector: 'tb-map-widget', - templateUrl: './map-widget.component.html', - styleUrls: ['./map-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-map-widget', + templateUrl: './map-widget.component.html', + styleUrls: ['./map-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class MapWidgetComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/panels/map-timeline-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/panels/map-timeline-panel.component.ts index fceec947af..30ba8f0f40 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/panels/map-timeline-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/panels/map-timeline-panel.component.ts @@ -34,10 +34,11 @@ import { filter } from 'rxjs/operators'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-map-timeline-panel', - templateUrl: './map-timeline-panel.component.html', - styleUrls: ['./map-timeline-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-map-timeline-panel', + templateUrl: './map-timeline-panel.component.html', + styleUrls: ['./map-timeline-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class MapTimelinePanelComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/panels/select-map-entity-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/panels/select-map-entity-panel.component.ts index 6165a2da91..ffeca2728b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/panels/select-map-entity-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/panels/select-map-entity-panel.component.ts @@ -20,11 +20,12 @@ import { TbPopoverComponent } from '@shared/components/popover.component'; import { UnplacedMapDataItem } from '@home/components/widget/lib/maps/data-layer/latest-map-data-layer'; @Component({ - selector: 'tb-select-map-entity-panel', - templateUrl: './select-map-entity-panel.component.html', - providers: [], - styleUrls: ['./select-map-entity-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-select-map-entity-panel', + templateUrl: './select-map-entity-panel.component.html', + providers: [], + styleUrls: ['./select-map-entity-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class SelectMapEntityPanelComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/markdown-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/markdown-widget.component.ts index faeeb0bbf2..5f653c38d9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/markdown-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/markdown-widget.component.ts @@ -50,8 +50,9 @@ interface MarkdownWidgetSettings { type MarkdownTextFunction = (data: FormattedData[], ctx: WidgetContext) => string; @Component({ - selector: 'tb-markdown-widget', - templateUrl: './markdown-widget.component.html' + selector: 'tb-markdown-widget', + templateUrl: './markdown-widget.component.html', + standalone: false }) export class MarkdownWidgetComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.ts index f0a843688c..7324d16672 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.ts @@ -30,9 +30,10 @@ import { ImagePipe } from '@shared/pipe/image.pipe'; import { DomSanitizer } from '@angular/platform-browser'; @Component({ - selector: 'tb-mobile-app-qrcode-widget', - templateUrl: './mobile-app-qrcode-widget.component.html', - styleUrls: ['./mobile-app-qrcode-widget.component.scss'] + selector: 'tb-mobile-app-qrcode-widget', + templateUrl: './mobile-app-qrcode-widget.component.html', + styleUrls: ['./mobile-app-qrcode-widget.component.scss'], + standalone: false }) export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts index b09d5f9972..5abdbc495e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts @@ -134,9 +134,10 @@ interface MultipleInputWidgetSource { } @Component({ - selector: 'tb-multiple-input-widget ', - templateUrl: './multiple-input-widget.component.html', - styleUrls: ['./multiple-input-widget.component.scss'] + selector: 'tb-multiple-input-widget ', + templateUrl: './multiple-input-widget.component.html', + styleUrls: ['./multiple-input-widget.component.scss'], + standalone: false }) export class MultipleInputWidgetComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/navigation-card-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/navigation-card-widget.component.ts index 6dc1dfe292..089c5e11d7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/navigation-card-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/navigation-card-widget.component.ts @@ -29,9 +29,10 @@ interface NavigationCardWidgetSettings { } @Component({ - selector: 'tb-navigation-card-widget', - templateUrl: './navigation-card-widget.component.html', - styleUrls: ['./navigation-card-widget.component.scss'] + selector: 'tb-navigation-card-widget', + templateUrl: './navigation-card-widget.component.html', + styleUrls: ['./navigation-card-widget.component.scss'], + standalone: false }) export class NavigationCardWidgetComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/navigation-cards-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/navigation-cards-widget.component.ts index f2953630e5..fc1b60f096 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/navigation-cards-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/navigation-cards-widget.component.ts @@ -30,9 +30,10 @@ interface NavigationCardsWidgetSettings { } @Component({ - selector: 'tb-navigation-cards-widget', - templateUrl: './navigation-cards-widget.component.html', - styleUrls: ['./navigation-cards-widget.component.scss'] + selector: 'tb-navigation-cards-widget', + templateUrl: './navigation-cards-widget.component.html', + styleUrls: ['./navigation-cards-widget.component.scss'], + standalone: false }) export class NavigationCardsWidgetComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/photo-camera-input.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/photo-camera-input.component.ts index 98f75da94d..ae3dff1d97 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/photo-camera-input.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/photo-camera-input.component.ts @@ -50,10 +50,11 @@ interface PhotoCameraInputWidgetSettings { // @dynamic @Component({ - selector: 'tb-photo-camera-widget', - templateUrl: './photo-camera-input.component.html', - styleUrls: ['./photo-camera-input.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-photo-camera-widget', + templateUrl: './photo-camera-input.component.html', + styleUrls: ['./photo-camera-input.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class PhotoCameraInputWidgetComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/qrcode-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/qrcode-widget.component.ts index e253485b1b..5426266e35 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/qrcode-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/qrcode-widget.component.ts @@ -44,9 +44,10 @@ interface QrCodeWidgetSettings { type QrCodeTextFunction = (data: FormattedData[]) => string; @Component({ - selector: 'tb-qrcode-widget', - templateUrl: './qrcode-widget.component.html', - styleUrls: [] + selector: 'tb-qrcode-widget', + templateUrl: './qrcode-widget.component.html', + styleUrls: [], + standalone: false }) export class QrCodeWidgetComponent extends PageComponent implements OnInit, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/knob.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/knob.component.ts index 127306db01..cdaff8fd15 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/knob.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/knob.component.ts @@ -30,9 +30,10 @@ import { BasicActionWidgetComponent, ValueSetter } from '@home/components/widget import GenericOptions = CanvasGauges.GenericOptions; @Component({ - selector: 'tb-knob', - templateUrl: './knob.component.html', - styleUrls: ['./knob.component.scss'] + selector: 'tb-knob', + templateUrl: './knob.component.html', + styleUrls: ['./knob.component.scss'], + standalone: false }) export class KnobComponent extends BasicActionWidgetComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/led-indicator.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/led-indicator.component.ts index 8c480e70ef..6230020aa0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/led-indicator.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/led-indicator.component.ts @@ -46,9 +46,10 @@ interface LedIndicatorSettings { } @Component({ - selector: 'tb-led-indicator', - templateUrl: './led-indicator.component.html', - styleUrls: ['./led-indicator.component.scss'] + selector: 'tb-led-indicator', + templateUrl: './led-indicator.component.html', + styleUrls: ['./led-indicator.component.scss'], + standalone: false }) export class LedIndicatorComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-add-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-add-dialog.component.ts index 2f759f7c25..ef00b39a65 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-add-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-add-dialog.component.ts @@ -26,9 +26,10 @@ import { TranslateService } from '@ngx-translate/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-persistent-add-dialog', - templateUrl: './persistent-add-dialog.component.html', - styleUrls: ['./persistent-add-dialog.component.scss'] + selector: 'tb-persistent-add-dialog', + templateUrl: './persistent-add-dialog.component.html', + styleUrls: ['./persistent-add-dialog.component.scss'], + standalone: false }) export class PersistentAddDialogComponent extends DialogComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-details-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-details-dialog.component.ts index 9eec2c9a37..0cb7e874c4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-details-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-details-dialog.component.ts @@ -34,9 +34,10 @@ export interface PersistentDetailsDialogData { } @Component({ - selector: 'tb-persistent-details-dialog', - templateUrl: './persistent-details-dialog.component.html', - styleUrls: ['./persistent-details-dialog.component.scss'] + selector: 'tb-persistent-details-dialog', + templateUrl: './persistent-details-dialog.component.html', + styleUrls: ['./persistent-details-dialog.component.scss'], + standalone: false }) export class PersistentDetailsDialogComponent extends DialogComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-filter-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-filter-panel.component.ts index 1215a60f8c..50eb4dddc9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-filter-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-filter-panel.component.ts @@ -27,9 +27,10 @@ export interface PersistentFilterPanelData { } @Component({ - selector: 'tb-persistent-filter-panel', - templateUrl: './persistent-filter-panel.component.html', - styleUrls: ['./persistent-filter-panel.component.scss'] + selector: 'tb-persistent-filter-panel', + templateUrl: './persistent-filter-panel.component.html', + styleUrls: ['./persistent-filter-panel.component.scss'], + standalone: false }) export class PersistentFilterPanelComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-table.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-table.component.ts index 0452a07422..225cfe6a4e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-table.component.ts @@ -98,9 +98,10 @@ interface PersistentTableWidgetActionDescriptor extends TableCellButtonActionDes } @Component({ - selector: 'tb-persistent-table-widget', - templateUrl: './persistent-table.component.html', - styleUrls: ['./persistent-table.component.scss' , '../table-widget.scss'] + selector: 'tb-persistent-table-widget', + templateUrl: './persistent-table.component.html', + styleUrls: ['./persistent-table.component.scss', '../table-widget.scss'], + standalone: false }) export class PersistentTableComponent extends PageComponent implements OnInit, OnDestroy, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.component.ts index 4b7bb9922b..acfb9b209e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.component.ts @@ -42,10 +42,11 @@ import { SVG, Svg } from '@svgdotjs/svg.js'; import { MatIconRegistry } from '@angular/material/icon'; @Component({ - selector: 'tb-power-button-widget', - templateUrl: './power-button-widget.component.html', - styleUrls: ['../action/action-widget.scss', './power-button-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-power-button-widget', + templateUrl: './power-button-widget.component.html', + styleUrls: ['../action/action-widget.scss', './power-button-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class PowerButtonWidgetComponent extends BasicActionWidgetComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/round-switch.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/round-switch.component.ts index 2d9b7b3d19..d397b47e1c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/round-switch.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/round-switch.component.ts @@ -42,9 +42,10 @@ interface RoundSwitchSettings { } @Component({ - selector: 'tb-round-switch', - templateUrl: './round-switch.component.html', - styleUrls: ['./round-switch.component.scss'] + selector: 'tb-round-switch', + templateUrl: './round-switch.component.html', + styleUrls: ['./round-switch.component.scss'], + standalone: false }) export class RoundSwitchComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts index 1026d1f73e..ef9c1ff826 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts @@ -50,10 +50,11 @@ const horizontalLayoutPadding = 48; const verticalLayoutPadding = 36; @Component({ - selector: 'tb-single-switch-widget', - templateUrl: './single-switch-widget.component.html', - styleUrls: ['../action/action-widget.scss', './single-switch-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-single-switch-widget', + templateUrl: './single-switch-widget.component.html', + styleUrls: ['../action/action-widget.scss', './single-switch-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class SingleSwitchWidgetComponent extends BasicActionWidgetComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/slider-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/slider-widget.component.ts index 14278c98e4..a1c25cbd39 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/slider-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/slider-widget.component.ts @@ -50,10 +50,11 @@ import tinycolor from 'tinycolor2'; import { UnitService } from '@core/services/unit.service'; @Component({ - selector: 'tb-slider-widget', - templateUrl: './slider-widget.component.html', - styleUrls: ['../action/action-widget.scss', './slider-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-slider-widget', + templateUrl: './slider-widget.component.html', + styleUrls: ['../action/action-widget.scss', './slider-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class SliderWidgetComponent extends BasicActionWidgetComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/switch.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/switch.component.ts index 52c1149808..d7056558a3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/switch.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/switch.component.ts @@ -51,9 +51,10 @@ interface SwitchSettings { } @Component({ - selector: 'tb-switch', - templateUrl: './switch.component.html', - styleUrls: ['./switch.component.scss'] + selector: 'tb-switch', + templateUrl: './switch.component.html', + styleUrls: ['./switch.component.scss'], + standalone: false }) export class SwitchComponent extends PageComponent implements AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/value-stepper-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/value-stepper-widget.component.ts index 4c462a5e56..8ccda39a54 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/value-stepper-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/value-stepper-widget.component.ts @@ -57,10 +57,11 @@ import { UtilsService } from '@core/services/utils.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-value-stepper-widget', - templateUrl: './value-stepper-widget.component.html', - styleUrls: ['../action/action-widget.scss', './value-stepper-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-value-stepper-widget', + templateUrl: './value-stepper-widget.component.html', + styleUrls: ['../action/action-widget.scss', './value-stepper-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ValueStepperWidgetComponent extends BasicActionWidgetComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol-widget.component.ts index 2edf94b94f..5e13120800 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol-widget.component.ts @@ -44,10 +44,11 @@ import { MatIconRegistry } from '@angular/material/icon'; import { RafService } from '@core/services/raf.service'; @Component({ - selector: 'tb-scada-symbol-widget', - templateUrl: './scada-symbol-widget.component.html', - styleUrls: ['../action/action-widget.scss', './scada-symbol-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-scada-symbol-widget', + templateUrl: './scada-symbol-widget.component.html', + styleUrls: ['../action/action-widget.scss', './scada-symbol-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ScadaSymbolWidgetComponent implements OnInit, AfterViewInit, OnDestroy, ScadaSymbolObjectCallbacks { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarm-count-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarm-count-widget-settings.component.ts index 449319df59..4c7d90bf77 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarm-count-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarm-count-widget-settings.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { countDefaultSettings } from '@home/components/widget/lib/count/count-widget.models'; @Component({ - selector: 'tb-alarm-count-widget-settings', - templateUrl: './alarm-count-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-alarm-count-widget-settings', + templateUrl: './alarm-count-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class AlarmCountWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-key-settings.component.ts index 3e183bcba6..08cc62b33f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-key-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-key-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-alarms-table-key-settings', - templateUrl: './alarms-table-key-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-alarms-table-key-settings', + templateUrl: './alarms-table-key-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class AlarmsTableKeySettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-widget-settings.component.ts index 7dabd06ea1..79fc3d1f59 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-widget-settings.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { buildPageStepSizeValues } from '@home/components/widget/lib/table-widget.models'; @Component({ - selector: 'tb-alarms-table-widget-settings', - templateUrl: './alarms-table-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-alarms-table-widget-settings', + templateUrl: './alarms-table-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class AlarmsTableWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/action-button-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/action-button-widget-settings.component.ts index cc7a73294a..6c85eb8e22 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/action-button-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/action-button-widget-settings.component.ts @@ -24,9 +24,10 @@ import { getTargetDeviceFromDatasources } from '@shared/models/widget-settings.m import { actionButtonDefaultSettings } from '@home/components/widget/lib/button/action-button-widget.models'; @Component({ - selector: 'tb-action-button-widget-settings', - templateUrl: './action-button-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-action-button-widget-settings', + templateUrl: './action-button-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class ActionButtonWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/command-button-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/command-button-widget-settings.component.ts index 304d4b91a0..9f82a93285 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/command-button-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/command-button-widget-settings.component.ts @@ -23,9 +23,10 @@ import { ValueType } from '@shared/models/constants'; import { commandButtonDefaultSettings } from '@home/components/widget/lib/button/command-button-widget.models'; @Component({ - selector: 'tb-command-button-widget-settings', - templateUrl: './command-button-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-command-button-widget-settings', + templateUrl: './command-button-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class CommandButtonWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/power-button-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/power-button-widget-settings.component.ts index df83f077d9..4c95654fdb 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/power-button-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/power-button-widget-settings.component.ts @@ -28,9 +28,10 @@ import { } from '@home/components/widget/lib/rpc/power-button-widget.models'; @Component({ - selector: 'tb-power-button-widget-settings', - templateUrl: './power-button-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-power-button-widget-settings', + templateUrl: './power-button-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class PowerButtonWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/segmented-button-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/segmented-button-widget-settings.component.ts index 758be4b07f..a87b9d1917 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/segmented-button-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/segmented-button-widget-settings.component.ts @@ -34,9 +34,10 @@ import { } from '@home/components/widget/lib/button/segmented-button-widget.models'; @Component({ - selector: 'tb-segmented-button-widget-settings', - templateUrl: './segmented-button-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-segmented-button-widget-settings', + templateUrl: './segmented-button-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class SegmentedButtonWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/toggle-button-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/toggle-button-widget-settings.component.ts index c14616ee7f..e8bb057b70 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/toggle-button-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/toggle-button-widget-settings.component.ts @@ -25,9 +25,10 @@ import { toggleButtonDefaultSettings } from '@home/components/widget/lib/button/ type ButtonAppearanceType = 'checked' | 'unchecked'; @Component({ - selector: 'tb-toggle-button-widget-settings', - templateUrl: './toggle-button-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-toggle-button-widget-settings', + templateUrl: './toggle-button-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class ToggleButtonWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/aggregated-value-card-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/aggregated-value-card-key-settings.component.ts index c1088cecab..0744461c2d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/aggregated-value-card-key-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/aggregated-value-card-key-settings.component.ts @@ -26,9 +26,10 @@ import { } from '@home/components/widget/lib/cards/aggregated-value-card.models'; @Component({ - selector: 'tb-aggregated-value-card-key-settings', - templateUrl: './aggregated-value-card-key-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-aggregated-value-card-key-settings', + templateUrl: './aggregated-value-card-key-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class AggregatedValueCardKeySettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/aggregated-value-card-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/aggregated-value-card-widget-settings.component.ts index 66fdcd0918..e64f47b3b0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/aggregated-value-card-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/aggregated-value-card-widget-settings.component.ts @@ -23,9 +23,10 @@ import { DateFormatProcessor, DateFormatSettings } from '@shared/models/widget-s import { aggregatedValueCardDefaultSettings } from '@home/components/widget/lib/cards/aggregated-value-card.models'; @Component({ - selector: 'tb-aggregated-value-card-widget-settings', - templateUrl: './aggregated-value-card-widget-settings.component.html', - styleUrls: [] + selector: 'tb-aggregated-value-card-widget-settings', + templateUrl: './aggregated-value-card-widget-settings.component.html', + styleUrls: [], + standalone: false }) export class AggregatedValueCardWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/dashboard-state-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/dashboard-state-widget-settings.component.ts index 5fa4a4b5fa..181ef7ddaf 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/dashboard-state-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/dashboard-state-widget-settings.component.ts @@ -23,9 +23,10 @@ import { Observable, of } from 'rxjs'; import { map, mergeMap, startWith } from 'rxjs/operators'; @Component({ - selector: 'tb-dashboard-state-widget-settings', - templateUrl: './dashboard-state-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-dashboard-state-widget-settings', + templateUrl: './dashboard-state-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class DashboardStateWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/edge-quick-overview-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/edge-quick-overview-widget-settings.component.ts index 448476f707..6c6691d65c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/edge-quick-overview-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/edge-quick-overview-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-edge-quick-overview-widget-settings', - templateUrl: './edge-quick-overview-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-edge-quick-overview-widget-settings', + templateUrl: './edge-quick-overview-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class EdgeQuickOverviewWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/html-card-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/html-card-widget-settings.component.ts index 0fa63f4cd1..4cdb47b1dd 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/html-card-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/html-card-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-html-card-widget-settings', - templateUrl: './html-card-widget-settings.component.html', - styleUrls: [] + selector: 'tb-html-card-widget-settings', + templateUrl: './html-card-widget-settings.component.html', + styleUrls: [], + standalone: false }) export class HtmlCardWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-card-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-card-widget-settings.component.ts index 51342a4944..1472a58ab1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-card-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-card-widget-settings.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { labelCardWidgetDefaultSettings } from '@home/components/widget/lib/cards/label-card-widget.models'; @Component({ - selector: 'tb-label-card-widget-settings', - templateUrl: './label-card-widget-settings.component.html', - styleUrls: [] + selector: 'tb-label-card-widget-settings', + templateUrl: './label-card-widget-settings.component.html', + styleUrls: [], + standalone: false }) export class LabelCardWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-value-card-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-value-card-widget-settings.component.ts index b0aa8139dc..c9177cb78b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-value-card-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-value-card-widget-settings.component.ts @@ -24,9 +24,10 @@ import { formatValue } from '@core/utils'; import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-label-value-card-widget-settings', - templateUrl: './label-value-card-widget-settings.component.html', - styleUrls: [] + selector: 'tb-label-value-card-widget-settings', + templateUrl: './label-value-card-widget-settings.component.html', + styleUrls: [], + standalone: false }) export class LabelValueCardWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-label.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-label.component.ts index 26b995c7a2..f0a6bd1ce4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-label.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-label.component.ts @@ -32,16 +32,17 @@ export interface LabelWidgetLabel { } @Component({ - selector: 'tb-label-widget-label', - templateUrl: './label-widget-label.component.html', - styleUrls: ['./label-widget-label.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => LabelWidgetLabelComponent), - multi: true - } - ] + selector: 'tb-label-widget-label', + templateUrl: './label-widget-label.component.html', + styleUrls: ['./label-widget-label.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => LabelWidgetLabelComponent), + multi: true + } + ], + standalone: false }) export class LabelWidgetLabelComponent extends PageComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-settings.component.ts index 01a8862307..88e3e23cf2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-settings.component.ts @@ -23,9 +23,10 @@ import { LabelWidgetLabel } from '@home/components/widget/lib/settings/cards/lab import { CdkDragDrop } from '@angular/cdk/drag-drop'; @Component({ - selector: 'tb-label-widget-settings', - templateUrl: './label-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-label-widget-settings', + templateUrl: './label-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class LabelWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.ts index 997db94c2c..0fed9263e8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-markdown-widget-settings', - templateUrl: './markdown-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-markdown-widget-settings', + templateUrl: './markdown-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class MarkdownWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/mobile-app-qr-code-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/mobile-app-qr-code-widget-settings.component.ts index a4ad7933f3..82aea1e4a1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/mobile-app-qr-code-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/mobile-app-qr-code-widget-settings.component.ts @@ -23,9 +23,10 @@ import { badgePositionTranslationsMap } from '@shared/models/mobile-app.models'; import { mobileAppQrCodeWidgetDefaultSettings } from '@home/components/widget/lib/cards/mobile-app-qr-code-widget.models'; @Component({ - selector: 'tb-mobile-app-qr-code-widget-settings', - templateUrl: './mobile-app-qr-code-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-mobile-app-qr-code-widget-settings', + templateUrl: './mobile-app-qr-code-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class MobileAppQrCodeWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/progress-bar-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/progress-bar-widget-settings.component.ts index e425d17893..80d8c79141 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/progress-bar-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/progress-bar-widget-settings.component.ts @@ -30,9 +30,10 @@ import { import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-progress-bar-widget-settings', - templateUrl: './progress-bar-widget-settings.component.html', - styleUrls: [] + selector: 'tb-progress-bar-widget-settings', + templateUrl: './progress-bar-widget-settings.component.html', + styleUrls: [], + standalone: false }) export class ProgressBarWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/qrcode-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/qrcode-widget-settings.component.ts index 62fdc7a487..b93a95b75e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/qrcode-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/qrcode-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-qrcode-widget-settings', - templateUrl: './qrcode-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-qrcode-widget-settings', + templateUrl: './qrcode-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class QrCodeWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/simple-card-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/simple-card-widget-settings.component.ts index e6e796e863..54722150f2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/simple-card-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/simple-card-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-simple-card-widget-settings', - templateUrl: './simple-card-widget-settings.component.html', - styleUrls: [] + selector: 'tb-simple-card-widget-settings', + templateUrl: './simple-card-widget-settings.component.html', + styleUrls: [], + standalone: false }) export class SimpleCardWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-key-settings.component.ts index e8ab4f73fa..e49cb5b4e4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-key-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-key-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-timeseries-table-key-settings', - templateUrl: './timeseries-table-key-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-timeseries-table-key-settings', + templateUrl: './timeseries-table-key-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class TimeseriesTableKeySettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-latest-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-latest-key-settings.component.ts index 842cf779e6..918ff9a7b8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-latest-key-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-latest-key-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-timeseries-table-latest-key-settings', - templateUrl: './timeseries-table-latest-key-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-timeseries-table-latest-key-settings', + templateUrl: './timeseries-table-latest-key-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class TimeseriesTableLatestKeySettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.ts index 0ed98e1758..494963fa53 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { buildPageStepSizeValues } from '@home/components/widget/lib/table-widget.models'; @Component({ - selector: 'tb-timeseries-table-widget-settings', - templateUrl: './timeseries-table-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-timeseries-table-widget-settings', + templateUrl: './timeseries-table-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class TimeseriesTableWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/unread-notification-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/unread-notification-widget-settings.component.ts index 6a4482012e..c0baba8794 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/unread-notification-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/unread-notification-widget-settings.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { unreadNotificationDefaultSettings } from '@home/components/widget/lib/cards/unread-notification-widget.models'; @Component({ - selector: 'tb-unread-notification-widget-settings', - templateUrl: './unread-notification-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-unread-notification-widget-settings', + templateUrl: './unread-notification-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class UnreadNotificationWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.ts index 18ba0bdca9..00614b7f40 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.ts @@ -32,9 +32,10 @@ import { DateFormatProcessor, DateFormatSettings, getLabel } from '@shared/model import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-value-card-widget-settings', - templateUrl: './value-card-widget-settings.component.html', - styleUrls: [] + selector: 'tb-value-card-widget-settings', + templateUrl: './value-card-widget-settings.component.html', + styleUrls: [], + standalone: false }) export class ValueCardWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-chart-card-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-chart-card-widget-settings.component.ts index 46878d0fcd..d218757030 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-chart-card-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-chart-card-widget-settings.component.ts @@ -29,9 +29,10 @@ import { import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-value-chart-card-widget-settings', - templateUrl: './value-chart-card-widget-settings.component.html', - styleUrls: [] + selector: 'tb-value-chart-card-widget-settings', + templateUrl: './value-chart-card-widget-settings.component.html', + styleUrls: [], + standalone: false }) export class ValueChartCardWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-widget-settings.component.ts index ace61904cc..432007de53 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-widget-settings.component.ts @@ -28,9 +28,10 @@ import { } from '@home/components/widget/lib/settings/chart/latest-chart-widget-settings.component'; @Component({ - selector: 'tb-bar-chart-widget-settings', - templateUrl: './latest-chart-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-bar-chart-widget-settings', + templateUrl: './latest-chart-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class BarChartWidgetSettingsComponent extends LatestChartWidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-with-labels-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-with-labels-widget-settings.component.ts index cc0c5c03cd..6290572770 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-with-labels-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-with-labels-widget-settings.component.ts @@ -33,9 +33,10 @@ import { import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-bar-chart-with-labels-widget-settings', - templateUrl: './bar-chart-with-labels-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-bar-chart-with-labels-widget-settings', + templateUrl: './bar-chart-with-labels-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class BarChartWithLabelsWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/chart-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/chart-widget-settings.component.ts index 7152a6a39e..50d407948b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/chart-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/chart-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-chart-widget-settings', - templateUrl: './chart-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-chart-widget-settings', + templateUrl: './chart-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class ChartWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-chart-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-chart-widget-settings.component.ts index 12e39a52d7..88226f4c28 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-chart-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-chart-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-doughnut-chart-widget-settings', - templateUrl: './doughnut-chart-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-doughnut-chart-widget-settings', + templateUrl: './doughnut-chart-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class DoughnutChartWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-widget-settings.component.ts index 6ba0508c95..17a0d60aab 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-widget-settings.component.ts @@ -29,9 +29,10 @@ import { } from '@home/components/widget/lib/settings/chart/latest-chart-widget-settings.component'; @Component({ - selector: 'tb-doughnut-widget-settings', - templateUrl: './latest-chart-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-doughnut-widget-settings', + templateUrl: './latest-chart-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class DoughnutWidgetSettingsComponent extends LatestChartWidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-bar-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-bar-key-settings.component.ts index bc2e7c22db..b2c0a34596 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-bar-key-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-bar-key-settings.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { flotDataKeyDefaultSettings } from '@home/components/widget/lib/settings/chart/flot-key-settings.component'; @Component({ - selector: 'tb-flot-bar-key-settings', - templateUrl: './flot-bar-key-settings.component.html', - styleUrls: [] + selector: 'tb-flot-bar-key-settings', + templateUrl: './flot-bar-key-settings.component.html', + styleUrls: [], + standalone: false }) export class FlotBarKeySettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-bar-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-bar-widget-settings.component.ts index c6720ecd13..c74fad3cda 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-bar-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-bar-widget-settings.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { flotDefaultSettings } from '@home/components/widget/lib/settings/chart/flot-widget-settings.component'; @Component({ - selector: 'tb-flot-bar-widget-settings', - templateUrl: './flot-bar-widget-settings.component.html', - styleUrls: [] + selector: 'tb-flot-bar-widget-settings', + templateUrl: './flot-bar-widget-settings.component.html', + styleUrls: [], + standalone: false }) export class FlotBarWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.ts index e5711e4af3..cd46662ae5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.ts @@ -91,21 +91,22 @@ export function flotDataKeyDefaultSettings(chartType: ChartType): TbFlotKeySetti } @Component({ - selector: 'tb-flot-key-settings', - templateUrl: './flot-key-settings.component.html', - styleUrls: ['./../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => FlotKeySettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => FlotKeySettingsComponent), - multi: true, - } - ] + selector: 'tb-flot-key-settings', + templateUrl: './flot-key-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => FlotKeySettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => FlotKeySettingsComponent), + multi: true, + } + ], + standalone: false }) export class FlotKeySettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-latest-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-latest-key-settings.component.ts index cc7842386e..78897b5db0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-latest-key-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-latest-key-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-flot-latest-key-settings', - templateUrl: './flot-latest-key-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-flot-latest-key-settings', + templateUrl: './flot-latest-key-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class FlotLatestKeySettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-line-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-line-key-settings.component.ts index 74b6ae9839..2b972a0d89 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-line-key-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-line-key-settings.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { flotDataKeyDefaultSettings } from '@home/components/widget/lib/settings/chart/flot-key-settings.component'; @Component({ - selector: 'tb-flot-line-key-settings', - templateUrl: './flot-line-key-settings.component.html', - styleUrls: [] + selector: 'tb-flot-line-key-settings', + templateUrl: './flot-line-key-settings.component.html', + styleUrls: [], + standalone: false }) export class FlotLineKeySettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-line-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-line-widget-settings.component.ts index ca01b3cbc5..3c4882a3c8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-line-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-line-widget-settings.component.ts @@ -23,9 +23,10 @@ import { flotDefaultSettings } from '@home/components/widget/lib/settings/chart/ import { deepClone } from '@core/utils'; @Component({ - selector: 'tb-flot-line-widget-settings', - templateUrl: './flot-line-widget-settings.component.html', - styleUrls: [] + selector: 'tb-flot-line-widget-settings', + templateUrl: './flot-line-widget-settings.component.html', + styleUrls: [], + standalone: false }) export class FlotLineWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-pie-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-pie-key-settings.component.ts index 9d8674dddf..39f6b3333a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-pie-key-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-pie-key-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-flot-pie-key-settings', - templateUrl: './flot-pie-key-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-flot-pie-key-settings', + templateUrl: './flot-pie-key-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class FlotPieKeySettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-pie-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-pie-widget-settings.component.ts index 78147a4d52..98ac711499 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-pie-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-pie-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-flot-pie-widget-settings', - templateUrl: './flot-pie-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-flot-pie-widget-settings', + templateUrl: './flot-pie-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class FlotPieWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-threshold.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-threshold.component.ts index 0ebe86668b..b8accc637b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-threshold.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-threshold.component.ts @@ -40,17 +40,18 @@ import { TbFlotKeyThreshold } from '@home/components/widget/lib/flot-widget.mode import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-flot-threshold', - templateUrl: './flot-threshold.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => FlotThresholdComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-flot-threshold', + templateUrl: './flot-threshold.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => FlotThresholdComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class FlotThresholdComponent extends PageComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.ts index 73b5248f04..65fc17df26 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.ts @@ -106,21 +106,22 @@ export const flotDefaultSettings = (chartType: ChartType): Partial FlotWidgetSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => FlotWidgetSettingsComponent), - multi: true, - } - ] + selector: 'tb-flot-widget-settings', + templateUrl: './flot-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => FlotWidgetSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => FlotWidgetSettingsComponent), + multi: true, + } + ], + standalone: false }) export class FlotWidgetSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/label-data-key.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/label-data-key.component.ts index 6d2b50824b..71e1163d16 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/label-data-key.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/label-data-key.component.ts @@ -46,16 +46,17 @@ export function labelDataKeyValidator(control: AbstractControl): ValidationError } @Component({ - selector: 'tb-label-data-key', - templateUrl: './label-data-key.component.html', - styleUrls: ['./label-data-key.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => LabelDataKeyComponent), - multi: true - } - ] + selector: 'tb-label-data-key', + templateUrl: './label-data-key.component.html', + styleUrls: ['./label-data-key.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => LabelDataKeyComponent), + multi: true + } + ], + standalone: false }) export class LabelDataKeyComponent extends PageComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/pie-chart-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/pie-chart-widget-settings.component.ts index 85db032513..9a7c2318bf 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/pie-chart-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/pie-chart-widget-settings.component.ts @@ -28,9 +28,10 @@ import { } from '@home/components/widget/lib/settings/chart/latest-chart-widget-settings.component'; @Component({ - selector: 'tb-pie-chart-widget-settings', - templateUrl: './latest-chart-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-pie-chart-widget-settings', + templateUrl: './latest-chart-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class PieChartWidgetSettingsComponent extends LatestChartWidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/polar-area-chart-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/polar-area-chart-widget-settings.component.ts index f452fee0bf..e941e27f13 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/polar-area-chart-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/polar-area-chart-widget-settings.component.ts @@ -28,9 +28,10 @@ import { } from '@home/components/widget/lib/settings/chart/latest-chart-widget-settings.component'; @Component({ - selector: 'tb-polar-area-chart-widget-settings', - templateUrl: './latest-chart-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-polar-area-chart-widget-settings', + templateUrl: './latest-chart-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class PolarAreaChartWidgetSettingsComponent extends LatestChartWidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/radar-chart-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/radar-chart-widget-settings.component.ts index 6e15a4c2bc..f9d3128027 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/radar-chart-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/radar-chart-widget-settings.component.ts @@ -28,9 +28,10 @@ import { } from '@home/components/widget/lib/settings/chart/latest-chart-widget-settings.component'; @Component({ - selector: 'tb-radar-chart-widget-settings', - templateUrl: './latest-chart-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-radar-chart-widget-settings', + templateUrl: './latest-chart-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class RadarChartWidgetSettingsComponent extends LatestChartWidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/range-chart-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/range-chart-widget-settings.component.ts index 5b1b20c2fd..703c621d62 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/range-chart-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/range-chart-widget-settings.component.ts @@ -43,9 +43,10 @@ import { import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-range-chart-widget-settings', - templateUrl: './range-chart-widget-settings.component.html', - styleUrls: [] + selector: 'tb-range-chart-widget-settings', + templateUrl: './range-chart-widget-settings.component.html', + styleUrls: [], + standalone: false }) export class RangeChartWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts index 3c99b96c07..34b0edb6ae 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts @@ -35,9 +35,10 @@ import { TimeSeriesChartWidgetSettings } from '@home/components/widget/lib/chart import { WidgetService } from '@core/http/widget.service'; @Component({ - selector: 'tb-time-series-chart-key-settings', - templateUrl: './time-series-chart-key-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-time-series-chart-key-settings', + templateUrl: './time-series-chart-key-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class TimeSeriesChartKeySettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.ts index 05afef0af8..c2e024bb55 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.ts @@ -45,16 +45,17 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { getSourceTbUnitSymbol, isNotEmptyTbUnits } from '@shared/models/unit.models'; @Component({ - selector: 'tb-time-series-chart-line-settings', - templateUrl: './time-series-chart-line-settings.component.html', - styleUrls: ['./../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimeSeriesChartLineSettingsComponent), - multi: true - } - ] + selector: 'tb-time-series-chart-line-settings', + templateUrl: './time-series-chart-line-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartLineSettingsComponent), + multi: true + } + ], + standalone: false }) export class TimeSeriesChartLineSettingsComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts index 4abc0bf437..8a96f31445 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts @@ -42,9 +42,10 @@ import { WidgetService } from '@core/http/widget.service'; import { TimeSeriesChartTooltipTrigger } from '@home/components/widget/lib/chart/time-series-chart-tooltip.models'; @Component({ - selector: 'tb-time-series-chart-widget-settings', - templateUrl: './time-series-chart-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-time-series-chart-widget-settings', + templateUrl: './time-series-chart-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action-pretty-editor.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action-pretty-editor.component.ts index 97d7bfed25..2537cbe310 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action-pretty-editor.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action-pretty-editor.component.ts @@ -32,17 +32,18 @@ import { } from '@home/components/widget/lib/settings/common/action/custom-action.models'; @Component({ - selector: 'tb-custom-action-pretty-editor', - templateUrl: './custom-action-pretty-editor.component.html', - styleUrls: ['./custom-action-pretty-editor.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => CustomActionPrettyEditorComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-custom-action-pretty-editor', + templateUrl: './custom-action-pretty-editor.component.html', + styleUrls: ['./custom-action-pretty-editor.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CustomActionPrettyEditorComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class CustomActionPrettyEditorComponent implements AfterViewInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action-pretty-resources-tabs.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action-pretty-resources-tabs.component.ts index 7cc295e94e..dfd03e406b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action-pretty-resources-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action-pretty-resources-tabs.component.ts @@ -41,10 +41,11 @@ import { getAce } from '@shared/models/ace/ace.models'; import { beautifyCss, beautifyHtml } from '@shared/models/beautify.models'; @Component({ - selector: 'tb-custom-action-pretty-resources-tabs', - templateUrl: './custom-action-pretty-resources-tabs.component.html', - styleUrls: ['./custom-action-pretty-resources-tabs.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-custom-action-pretty-resources-tabs', + templateUrl: './custom-action-pretty-resources-tabs.component.html', + styleUrls: ['./custom-action-pretty-resources-tabs.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class CustomActionPrettyResourcesTabsComponent extends PageComponent implements OnInit, OnChanges, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/get-value-action-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/get-value-action-settings-panel.component.ts index 96915e5712..cb384248c5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/get-value-action-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/get-value-action-settings-panel.component.ts @@ -38,11 +38,12 @@ import { EntityType } from '@shared/models/entity-type.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-get-value-action-settings-panel', - templateUrl: './get-value-action-settings-panel.component.html', - providers: [], - styleUrls: ['./action-settings-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-get-value-action-settings-panel', + templateUrl: './get-value-action-settings-panel.component.html', + providers: [], + styleUrls: ['./action-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class GetValueActionSettingsPanelComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/get-value-action-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/get-value-action-settings.component.ts index d27efc1081..8b1e18a917 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/get-value-action-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/get-value-action-settings.component.ts @@ -38,17 +38,18 @@ import { IAliasController } from '@core/api/widget-api.models'; import { TargetDevice, widgetType } from '@shared/models/widget.models'; @Component({ - selector: 'tb-get-value-action-settings', - templateUrl: './action-settings-button.component.html', - styleUrls: ['./action-settings-button.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => GetValueActionSettingsComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-get-value-action-settings', + templateUrl: './action-settings-button.component.html', + styleUrls: ['./action-settings-button.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => GetValueActionSettingsComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class GetValueActionSettingsComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/map-item-tooltips.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/map-item-tooltips.component.ts index c6f60c1892..9a4ba9b2aa 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/map-item-tooltips.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/map-item-tooltips.component.ts @@ -21,15 +21,16 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { deepTrim, isEqual } from '@core/utils'; @Component({ - selector: 'tb-map-item-tooltips', - templateUrl: './map-item-tooltips.component.html', - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MapItemTooltipsComponent), - multi: true - } - ] + selector: 'tb-map-item-tooltips', + templateUrl: './map-item-tooltips.component.html', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MapItemTooltipsComponent), + multi: true + } + ], + standalone: false }) export class MapItemTooltipsComponent implements ControlValueAccessor, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/mobile-action-editor.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/mobile-action-editor.component.ts index a30e7a8adc..469bbf95c7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/mobile-action-editor.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/mobile-action-editor.component.ts @@ -46,14 +46,15 @@ import { TbFunction } from '@shared/models/js-function.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-mobile-action-editor', - templateUrl: './mobile-action-editor.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MobileActionEditorComponent), - multi: true - }] + selector: 'tb-mobile-action-editor', + templateUrl: './mobile-action-editor.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MobileActionEditorComponent), + multi: true + }], + standalone: false }) export class MobileActionEditorComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/set-value-action-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/set-value-action-settings-panel.component.ts index 17a3ae5b6c..a778b9a509 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/set-value-action-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/set-value-action-settings-panel.component.ts @@ -36,11 +36,12 @@ import { ValueType } from '@shared/models/constants'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-set-value-action-settings-panel', - templateUrl: './set-value-action-settings-panel.component.html', - providers: [], - styleUrls: ['./action-settings-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-set-value-action-settings-panel', + templateUrl: './set-value-action-settings-panel.component.html', + providers: [], + styleUrls: ['./action-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class SetValueActionSettingsPanelComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/set-value-action-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/set-value-action-settings.component.ts index 30202ed551..6e9950033b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/set-value-action-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/set-value-action-settings.component.ts @@ -39,17 +39,18 @@ import { import { ValueType } from '@shared/models/constants'; @Component({ - selector: 'tb-set-value-action-settings', - templateUrl: './action-settings-button.component.html', - styleUrls: ['./action-settings-button.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => SetValueActionSettingsComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-set-value-action-settings', + templateUrl: './action-settings-button.component.html', + styleUrls: ['./action-settings-button.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => SetValueActionSettingsComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class SetValueActionSettingsComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action-settings-panel.component.ts index c43b36e014..f0ba6f05ce 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action-settings-panel.component.ts @@ -23,11 +23,12 @@ import { coerceBoolean } from '@shared/decorators/coercion'; import { TranslateService } from '@ngx-translate/core'; @Component({ - selector: 'tb-widget-action-settings-panel', - templateUrl: './widget-action-settings-panel.component.html', - providers: [], - styleUrls: ['./action-settings-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-widget-action-settings-panel', + templateUrl: './widget-action-settings-panel.component.html', + providers: [], + styleUrls: ['./action-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class WidgetActionSettingsPanelComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action-settings.component.ts index f60a7f1d3c..737fafd75a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action-settings.component.ts @@ -41,17 +41,18 @@ import { } from '@home/components/widget/lib/settings/common/action/widget-action-settings-panel.component'; @Component({ - selector: 'tb-widget-action-settings', - templateUrl: './action-settings-button.component.html', - styleUrls: ['./action-settings-button.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => WidgetActionSettingsComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-widget-action-settings', + templateUrl: './action-settings-button.component.html', + styleUrls: ['./action-settings-button.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => WidgetActionSettingsComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class WidgetActionSettingsComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.ts index 09bddd26dd..9efb80081e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.ts @@ -66,21 +66,22 @@ const stateDisplayTypesTranslations = new Map( ); @Component({ - selector: 'tb-widget-action', - templateUrl: './widget-action.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => WidgetActionComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => WidgetActionComponent), - multi: true, - } - ] + selector: 'tb-widget-action', + templateUrl: './widget-action.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => WidgetActionComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => WidgetActionComponent), + multi: true, + } + ], + standalone: false }) export class WidgetActionComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/advanced-range.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/advanced-range.component.ts index c1e5114eb6..d2f1544014 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/advanced-range.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/advanced-range.component.ts @@ -32,16 +32,17 @@ import { Datasource } from '@shared/models/widget.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-advanced-range', - templateUrl: './advanced-range.component.html', - styleUrls: ['./advanced-range.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AdvancedRangeComponent), - multi: true - } - ] + selector: 'tb-advanced-range', + templateUrl: './advanced-range.component.html', + styleUrls: ['./advanced-range.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AdvancedRangeComponent), + multi: true + } + ], + standalone: false }) export class AdvancedRangeComponent extends PageComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/alias/entity-alias-select.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/alias/entity-alias-select.component.ts index 7c374e9654..0b2cacd6da 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/alias/entity-alias-select.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/alias/entity-alias-select.component.ts @@ -39,14 +39,15 @@ import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form- import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-entity-alias-select', - templateUrl: './entity-alias-select.component.html', - styleUrls: ['./entity-alias-select.component.scss'], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => EntityAliasSelectComponent), - multi: true - }] + selector: 'tb-entity-alias-select', + templateUrl: './entity-alias-select.component.html', + styleUrls: ['./entity-alias-select.component.scss'], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => EntityAliasSelectComponent), + multi: true + }], + standalone: false }) export class EntityAliasSelectComponent implements ControlValueAccessor, OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings-panel.component.ts index 01f16eccc1..ab0ab9fa4b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings-panel.component.ts @@ -30,11 +30,12 @@ import { DatePipe } from '@angular/common'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-auto-date-format-settings-panel', - templateUrl: './auto-date-format-settings-panel.component.html', - providers: [], - styleUrls: ['./auto-date-format-settings-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-auto-date-format-settings-panel', + templateUrl: './auto-date-format-settings-panel.component.html', + providers: [], + styleUrls: ['./auto-date-format-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class AutoDateFormatSettingsPanelComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings.component.ts index 8d3dadb56d..59a145c66f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings.component.ts @@ -25,16 +25,17 @@ import { } from '@home/components/widget/lib/settings/common/auto-date-format-settings-panel.component'; @Component({ - selector: 'tb-auto-date-format-settings', - templateUrl: './auto-date-format-settings.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AutoDateFormatSettingsComponent), - multi: true - } - ] + selector: 'tb-auto-date-format-settings', + templateUrl: './auto-date-format-settings.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AutoDateFormatSettingsComponent), + multi: true + } + ], + standalone: false }) export class AutoDateFormatSettingsComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.ts index b1ee8ff332..323241e0f2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.ts @@ -42,11 +42,12 @@ import { DomSanitizer } from '@angular/platform-browser'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-background-settings-panel', - templateUrl: './background-settings-panel.component.html', - providers: [], - styleUrls: ['./background-settings-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-background-settings-panel', + templateUrl: './background-settings-panel.component.html', + providers: [], + styleUrls: ['./background-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class BackgroundSettingsPanelComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings.component.ts index 94737fa3b1..fd15e6da1a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings.component.ts @@ -43,17 +43,18 @@ import { DomSanitizer } from '@angular/platform-browser'; import { tap } from 'rxjs/operators'; @Component({ - selector: 'tb-background-settings', - templateUrl: './background-settings.component.html', - styleUrls: ['./background-settings.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => BackgroundSettingsComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-background-settings', + templateUrl: './background-settings.component.html', + styleUrls: ['./background-settings.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => BackgroundSettingsComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class BackgroundSettingsComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-appearance.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-appearance.component.ts index 61f84d8029..41cfbcc3d2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-appearance.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-appearance.component.ts @@ -28,17 +28,18 @@ import { coerceBoolean } from '@shared/decorators/coercion'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-widget-button-appearance', - templateUrl: './widget-button-appearance.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => WidgetButtonAppearanceComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-widget-button-appearance', + templateUrl: './widget-button-appearance.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => WidgetButtonAppearanceComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class WidgetButtonAppearanceComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style-panel.component.ts index f4d11a9d2f..1fc3c4f20c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style-panel.component.ts @@ -46,11 +46,12 @@ import { WidgetButtonComponent } from '@shared/components/button/widget-button.c import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-widget-button-custom-style-panel', - templateUrl: './widget-button-custom-style-panel.component.html', - providers: [], - styleUrls: ['./widget-button-custom-style-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-widget-button-custom-style-panel', + templateUrl: './widget-button-custom-style-panel.component.html', + providers: [], + styleUrls: ['./widget-button-custom-style-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class WidgetButtonCustomStylePanelComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style.component.ts index 9f54623698..72d3d5e5fd 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style.component.ts @@ -40,17 +40,18 @@ import { import { deepClone } from '@core/utils'; @Component({ - selector: 'tb-widget-button-custom-style', - templateUrl: './widget-button-custom-style.component.html', - styleUrls: ['./widget-button-custom-style.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => WidgetButtonCustomStyleComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-widget-button-custom-style', + templateUrl: './widget-button-custom-style.component.html', + styleUrls: ['./widget-button-custom-style.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => WidgetButtonCustomStyleComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class WidgetButtonCustomStyleComponent implements OnInit, OnChanges, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-toggle-custom-style-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-toggle-custom-style-panel.component.ts index 6ba1021b5c..6502548bf2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-toggle-custom-style-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-toggle-custom-style-panel.component.ts @@ -48,11 +48,12 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-widget-button-toggle-custom-style-panel', - templateUrl: './widget-button-toggle-custom-style-panel.component.html', - providers: [], - styleUrls: ['./widget-button-toggle-custom-style-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-widget-button-toggle-custom-style-panel', + templateUrl: './widget-button-toggle-custom-style-panel.component.html', + providers: [], + styleUrls: ['./widget-button-toggle-custom-style-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class WidgetButtonToggleCustomStylePanelComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-toggle-custom-style.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-toggle-custom-style.component.ts index 4d7767f04a..af93d58722 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-toggle-custom-style.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-toggle-custom-style.component.ts @@ -40,17 +40,18 @@ import { } from '@home/components/widget/lib/settings/common/button/widget-button-toggle-custom-style-panel.component'; @Component({ - selector: 'tb-widget-button-toggle-custom-style', - templateUrl: './widget-button-toggle-custom-style.component.html', - styleUrls: ['./widget-button-toggle-custom-style.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => WidgetButtonToggleCustomStyleComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-widget-button-toggle-custom-style', + templateUrl: './widget-button-toggle-custom-style.component.html', + styleUrls: ['./widget-button-toggle-custom-style.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => WidgetButtonToggleCustomStyleComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class WidgetButtonToggleCustomStyleComponent implements OnInit, OnChanges, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/chart-animation-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/chart-animation-settings.component.ts index d5cab573ed..61374113bf 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/chart-animation-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/chart-animation-settings.component.ts @@ -26,16 +26,17 @@ import { chartAnimationEasings, ChartAnimationSettings } from '@home/components/ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-chart-animation-settings', - templateUrl: './chart-animation-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ChartAnimationSettingsComponent), - multi: true - } - ] + selector: 'tb-chart-animation-settings', + templateUrl: './chart-animation-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ChartAnimationSettingsComponent), + multi: true + } + ], + standalone: false }) export class ChartAnimationSettingsComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/chart-bar-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/chart-bar-settings.component.ts index ca60fe0db2..4a652e84b5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/chart-bar-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/chart-bar-settings.component.ts @@ -41,16 +41,17 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { getSourceTbUnitSymbol, isNotEmptyTbUnits } from '@shared/models/unit.models'; @Component({ - selector: 'tb-chart-bar-settings', - templateUrl: './chart-bar-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ChartBarSettingsComponent), - multi: true - } - ] + selector: 'tb-chart-bar-settings', + templateUrl: './chart-bar-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ChartBarSettingsComponent), + multi: true + } + ], + standalone: false }) export class ChartBarSettingsComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/chart-fill-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/chart-fill-settings.component.ts index e85c8bb226..f980264f4a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/chart-fill-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/chart-fill-settings.component.ts @@ -33,16 +33,17 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-chart-fill-settings', - templateUrl: './chart-fill-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ChartFillSettingsComponent), - multi: true - } - ] + selector: 'tb-chart-fill-settings', + templateUrl: './chart-fill-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ChartFillSettingsComponent), + multi: true + } + ], + standalone: false }) export class ChartFillSettingsComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings-button.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings-button.component.ts index de1ef16a43..5aad0ab4f1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings-button.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings-button.component.ts @@ -25,16 +25,17 @@ import { } from '@home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings-panel.component'; @Component({ - selector: 'tb-time-series-chart-axis-settings-button', - templateUrl: './time-series-chart-axis-settings-button.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimeSeriesChartAxisSettingsButtonComponent), - multi: true - } - ] + selector: 'tb-time-series-chart-axis-settings-button', + templateUrl: './time-series-chart-axis-settings-button.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartAxisSettingsButtonComponent), + multi: true + } + ], + standalone: false }) export class TimeSeriesChartAxisSettingsButtonComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings-panel.component.ts index 53bed97847..6d55817b1a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings-panel.component.ts @@ -24,11 +24,12 @@ import { import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ - selector: 'tb-time-series-chart-axis-settings-panel', - templateUrl: './time-series-chart-axis-settings-panel.component.html', - providers: [], - styleUrls: ['./time-series-chart-axis-settings-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-time-series-chart-axis-settings-panel', + templateUrl: './time-series-chart-axis-settings-panel.component.html', + providers: [], + styleUrls: ['./time-series-chart-axis-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class TimeSeriesChartAxisSettingsPanelComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts index b713a6335f..1d7a4a2c37 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts @@ -34,16 +34,17 @@ import { WidgetService } from '@core/http/widget.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-time-series-chart-axis-settings', - templateUrl: './time-series-chart-axis-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimeSeriesChartAxisSettingsComponent), - multi: true - } - ] + selector: 'tb-time-series-chart-axis-settings', + templateUrl: './time-series-chart-axis-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartAxisSettingsComponent), + multi: true + } + ], + standalone: false }) export class TimeSeriesChartAxisSettingsComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-grid-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-grid-settings.component.ts index 1ad240f8b0..7dd1354cd0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-grid-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-grid-settings.component.ts @@ -27,16 +27,17 @@ import { WidgetService } from '@core/http/widget.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-time-series-chart-grid-settings', - templateUrl: './time-series-chart-grid-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimeSeriesChartGridSettingsComponent), - multi: true - } - ] + selector: 'tb-time-series-chart-grid-settings', + templateUrl: './time-series-chart-grid-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartGridSettingsComponent), + multi: true + } + ], + standalone: false }) export class TimeSeriesChartGridSettingsComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-state-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-state-row.component.ts index 1e48cb6def..b3997331f8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-state-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-state-row.component.ts @@ -41,17 +41,18 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-time-series-chart-state-row', - templateUrl: './time-series-chart-state-row.component.html', - styleUrls: ['./time-series-chart-state-row.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimeSeriesChartStateRowComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-time-series-chart-state-row', + templateUrl: './time-series-chart-state-row.component.html', + styleUrls: ['./time-series-chart-state-row.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartStateRowComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class TimeSeriesChartStateRowComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-states-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-states-panel.component.ts index 1de5e8019f..aaa9d6d9f0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-states-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-states-panel.component.ts @@ -35,22 +35,23 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-time-series-chart-states-panel', - templateUrl: './time-series-chart-states-panel.component.html', - styleUrls: ['./time-series-chart-states-panel.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimeSeriesChartStatesPanelComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => TimeSeriesChartStatesPanelComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-time-series-chart-states-panel', + templateUrl: './time-series-chart-states-panel.component.html', + styleUrls: ['./time-series-chart-states-panel.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartStatesPanelComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => TimeSeriesChartStatesPanelComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class TimeSeriesChartStatesPanelComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.ts index 37ae10c330..136ad2c728 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.ts @@ -56,17 +56,18 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-time-series-chart-threshold-row', - templateUrl: './time-series-chart-threshold-row.component.html', - styleUrls: ['./time-series-chart-threshold-row.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimeSeriesChartThresholdRowComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-time-series-chart-threshold-row', + templateUrl: './time-series-chart-threshold-row.component.html', + styleUrls: ['./time-series-chart-threshold-row.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartThresholdRowComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class TimeSeriesChartThresholdRowComponent implements ControlValueAccessor, OnInit, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.ts index 916ba3dd53..57001605a6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.ts @@ -38,11 +38,12 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { getSourceTbUnitSymbol, isNotEmptyTbUnits, TbUnit } from '@shared/models/unit.models'; @Component({ - selector: 'tb-time-series-chart-threshold-settings-panel', - templateUrl: './time-series-chart-threshold-settings-panel.component.html', - providers: [], - styleUrls: ['./time-series-chart-threshold-settings-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-time-series-chart-threshold-settings-panel', + templateUrl: './time-series-chart-threshold-settings-panel.component.html', + providers: [], + styleUrls: ['./time-series-chart-threshold-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class TimeSeriesChartThresholdSettingsPanelComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings.component.ts index 1757b14b77..3195c3a944 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings.component.ts @@ -30,16 +30,17 @@ import { } from '@home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component'; @Component({ - selector: 'tb-time-series-chart-threshold-settings', - templateUrl: './time-series-chart-threshold-settings.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimeSeriesChartThresholdSettingsComponent), - multi: true - } - ] + selector: 'tb-time-series-chart-threshold-settings', + templateUrl: './time-series-chart-threshold-settings.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartThresholdSettingsComponent), + multi: true + } + ], + standalone: false }) export class TimeSeriesChartThresholdSettingsComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.ts index f7b9e157e1..944c28b4d8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.ts @@ -43,22 +43,23 @@ import { ValueSourceType } from '@shared/models/widget-settings.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-time-series-chart-thresholds-panel', - templateUrl: './time-series-chart-thresholds-panel.component.html', - styleUrls: ['./time-series-chart-thresholds-panel.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimeSeriesChartThresholdsPanelComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => TimeSeriesChartThresholdsPanelComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-time-series-chart-thresholds-panel', + templateUrl: './time-series-chart-thresholds-panel.component.html', + styleUrls: ['./time-series-chart-thresholds-panel.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartThresholdsPanelComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => TimeSeriesChartThresholdsPanelComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class TimeSeriesChartThresholdsPanelComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axes-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axes-panel.component.ts index 8a229d0a7b..de7b19deba 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axes-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axes-panel.component.ts @@ -49,22 +49,23 @@ import { coerceBoolean } from '@shared/decorators/coercion'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-time-series-chart-y-axes-panel', - templateUrl: './time-series-chart-y-axes-panel.component.html', - styleUrls: ['./time-series-chart-y-axes-panel.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimeSeriesChartYAxesPanelComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => TimeSeriesChartYAxesPanelComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-time-series-chart-y-axes-panel', + templateUrl: './time-series-chart-y-axes-panel.component.html', + styleUrls: ['./time-series-chart-y-axes-panel.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartYAxesPanelComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => TimeSeriesChartYAxesPanelComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class TimeSeriesChartYAxesPanelComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component.ts index 7c7daea095..67ec499ab1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component.ts @@ -44,17 +44,18 @@ import { TranslateService } from '@ngx-translate/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-time-series-chart-y-axis-row', - templateUrl: './time-series-chart-y-axis-row.component.html', - styleUrls: ['./time-series-chart-y-axis-row.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimeSeriesChartYAxisRowComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-time-series-chart-y-axis-row', + templateUrl: './time-series-chart-y-axis-row.component.html', + styleUrls: ['./time-series-chart-y-axis-row.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartYAxisRowComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class TimeSeriesChartYAxisRowComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component.ts index 320b239c22..1e078d995f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component.ts @@ -33,16 +33,17 @@ import { coerceBoolean } from '@shared/decorators/coercion'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-time-series-no-aggregation-bar-width-settings', - templateUrl: './time-series-no-aggregation-bar-width-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimeSeriesNoAggregationBarWidthSettingsComponent), - multi: true - } - ] + selector: 'tb-time-series-no-aggregation-bar-width-settings', + templateUrl: './time-series-no-aggregation-bar-width-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesNoAggregationBarWidthSettingsComponent), + multi: true + } + ], + standalone: false }) export class TimeSeriesNoAggregationBarWidthSettingsComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-range-list.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-range-list.component.ts index 45acb33b31..b781107fde 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-range-list.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-range-list.component.ts @@ -53,17 +53,18 @@ export function advancedRangeValidator(control: AbstractControl): ValidationErro } @Component({ - selector: 'tb-color-range-list', - templateUrl: './color-range-list.component.html', - styleUrls: ['color-settings-panel.component.scss', 'color-range-list.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ColorRangeListComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-color-range-list', + templateUrl: './color-range-list.component.html', + styleUrls: ['color-settings-panel.component.scss', 'color-range-list.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ColorRangeListComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ColorRangeListComponent implements OnInit, ControlValueAccessor, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-range-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-range-panel.component.ts index 68485e8572..b6f1c02bfb 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-range-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-range-panel.component.ts @@ -27,11 +27,12 @@ import { } from '@home/components/widget/lib/settings/common/color-range-settings.component'; @Component({ - selector: 'tb-color-range-panel', - templateUrl: './color-range-panel.component.html', - providers: [], - styleUrls: ['./color-settings-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-color-range-panel', + templateUrl: './color-range-panel.component.html', + providers: [], + styleUrls: ['./color-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ColorRangePanelComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-range-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-range-settings.component.ts index 85e248e811..0c0022b252 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-range-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-range-settings.component.ts @@ -58,16 +58,17 @@ export class ColorRangeSettingsComponentService { } @Component({ - selector: 'tb-color-range-settings', - templateUrl: './color-range-settings.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ColorRangeSettingsComponent), - multi: true - } - ] + selector: 'tb-color-range-settings', + templateUrl: './color-range-settings.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ColorRangeSettingsComponent), + multi: true + } + ], + standalone: false }) export class ColorRangeSettingsComponent implements OnInit, ControlValueAccessor, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings-panel.component.ts index 5fc7ebb698..0c0e504d74 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings-panel.component.ts @@ -37,11 +37,12 @@ import { Datasource } from '@shared/models/widget.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-color-settings-panel', - templateUrl: './color-settings-panel.component.html', - providers: [], - styleUrls: ['./color-settings-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-color-settings-panel', + templateUrl: './color-settings-panel.component.html', + providers: [], + styleUrls: ['./color-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ColorSettingsPanelComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings.component.ts index f67b647c48..9a9ba27ce0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings.component.ts @@ -65,16 +65,17 @@ export class ColorSettingsComponentService { } @Component({ - selector: 'tb-color-settings', - templateUrl: './color-settings.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ColorSettingsComponent), - multi: true - } - ] + selector: 'tb-color-settings', + templateUrl: './color-settings.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ColorSettingsComponent), + multi: true + } + ], + standalone: false }) export class ColorSettingsComponent implements OnInit, ControlValueAccessor, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/count-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/count-widget-settings.component.ts index 7221c54061..79689174c0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/count-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/count-widget-settings.component.ts @@ -41,16 +41,17 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-count-widget-settings', - templateUrl: './count-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => CountWidgetSettingsComponent), - multi: true - } - ] + selector: 'tb-count-widget-settings', + templateUrl: './count-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CountWidgetSettingsComponent), + multi: true + } + ], + standalone: false }) export class CountWidgetSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/css-size-input.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/css-size-input.component.ts index 41361112f5..5dc81ff163 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/css-size-input.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/css-size-input.component.ts @@ -31,21 +31,22 @@ import { isDefinedAndNotNull } from '@core/utils'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-css-size-input', - templateUrl: './css-size-input.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => CssSizeInputComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => CssSizeInputComponent), - multi: true, - } - ] + selector: 'tb-css-size-input', + templateUrl: './css-size-input.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CssSizeInputComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => CssSizeInputComponent), + multi: true, + } + ], + standalone: false }) export class CssSizeInputComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/css-unit-select.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/css-unit-select.component.ts index 1d5ab7f12e..861bf64044 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/css-unit-select.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/css-unit-select.component.ts @@ -21,16 +21,17 @@ import { coerceBoolean } from '@shared/decorators/coercion'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-css-unit-select', - templateUrl: './css-unit-select.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => CssUnitSelectComponent), - multi: true - } - ] + selector: 'tb-css-unit-select', + templateUrl: './css-unit-select.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CssUnitSelectComponent), + multi: true + } + ], + standalone: false }) export class CssUnitSelectComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-select.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-select.component.ts index 9545e6cb37..746cc6c90b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-select.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-select.component.ts @@ -48,16 +48,17 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-date-format-select', - templateUrl: './date-format-select.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DateFormatSelectComponent), - multi: true - } - ] + selector: 'tb-date-format-select', + templateUrl: './date-format-select.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DateFormatSelectComponent), + multi: true + } + ], + standalone: false }) export class DateFormatSelectComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-settings-panel.component.ts index 45ffdcc580..b66d49c711 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-settings-panel.component.ts @@ -25,11 +25,12 @@ import { DatePipe } from '@angular/common'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-date-format-settings-panel', - templateUrl: './date-format-settings-panel.component.html', - providers: [], - styleUrls: ['./date-format-settings-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-date-format-settings-panel', + templateUrl: './date-format-settings-panel.component.html', + providers: [], + styleUrls: ['./date-format-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DateFormatSettingsPanelComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-array.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-array.component.ts index f5b71fb52c..f0b085dbae 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-array.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-array.component.ts @@ -31,22 +31,23 @@ import { defaultFormPropertyValue, FormProperty } from '@shared/models/dynamic-f import { CdkDragDrop } from '@angular/cdk/drag-drop'; @Component({ - selector: 'tb-dynamic-form-array', - templateUrl: './dynamic-form-array.component.html', - styleUrls: ['./dynamic-form-array.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DynamicFormArrayComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DynamicFormArrayComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-dynamic-form-array', + templateUrl: './dynamic-form-array.component.html', + styleUrls: ['./dynamic-form-array.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DynamicFormArrayComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DynamicFormArrayComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DynamicFormArrayComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-properties.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-properties.component.ts index bddbda4401..d994a65901 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-properties.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-properties.component.ts @@ -53,22 +53,23 @@ import { DialogService } from '@core/services/dialog.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-dynamic-form-properties', - templateUrl: './dynamic-form-properties.component.html', - styleUrls: ['./dynamic-form-properties.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DynamicFormPropertiesComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DynamicFormPropertiesComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-dynamic-form-properties', + templateUrl: './dynamic-form-properties.component.html', + styleUrls: ['./dynamic-form-properties.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DynamicFormPropertiesComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DynamicFormPropertiesComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DynamicFormPropertiesComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-panel.component.ts index dfcdf49192..e59a08037f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-panel.component.ts @@ -34,10 +34,11 @@ import { isUndefinedOrNull } from '@core/utils'; import { StringItemsOption } from '@shared/components/string-items-list.component'; @Component({ - selector: 'tb-dynamic-form-property-panel', - templateUrl: './dynamic-form-property-panel.component.html', - styleUrls: ['./dynamic-form-property-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-dynamic-form-property-panel', + templateUrl: './dynamic-form-property-panel.component.html', + styleUrls: ['./dynamic-form-property-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DynamicFormPropertyPanelComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-row.component.ts index 7692be80e0..4f1dd8b23d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-row.component.ts @@ -59,22 +59,23 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-dynamic-form-property-row', - templateUrl: './dynamic-form-property-row.component.html', - styleUrls: ['./dynamic-form-property-row.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DynamicFormPropertyRowComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DynamicFormPropertyRowComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-dynamic-form-property-row', + templateUrl: './dynamic-form-property-row.component.html', + styleUrls: ['./dynamic-form-property-row.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DynamicFormPropertyRowComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DynamicFormPropertyRowComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DynamicFormPropertyRowComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-select-item-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-select-item-row.component.ts index 6d414a18f9..d92cc58489 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-select-item-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-select-item-row.component.ts @@ -46,22 +46,23 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; export const selectItemValid = (item: FormSelectItem): boolean => isDefinedAndNotNull(item.value) && !!item.label; @Component({ - selector: 'tb-dynamic-form-select-item-row', - templateUrl: './dynamic-form-select-item-row.component.html', - styleUrls: ['./dynamic-form-select-item-row.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DynamicFormSelectItemRowComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DynamicFormSelectItemRowComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-dynamic-form-select-item-row', + templateUrl: './dynamic-form-select-item-row.component.html', + styleUrls: ['./dynamic-form-select-item-row.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DynamicFormSelectItemRowComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DynamicFormSelectItemRowComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DynamicFormSelectItemRowComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-select-items.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-select-items.component.ts index 9d664d5796..8970569cf3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-select-items.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-select-items.component.ts @@ -45,22 +45,23 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-dynamic-form-select-items', - templateUrl: './dynamic-form-select-items.component.html', - styleUrls: ['./dynamic-form-select-items.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DynamicFormSelectItemsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DynamicFormSelectItemsComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-dynamic-form-select-items', + templateUrl: './dynamic-form-select-items.component.html', + styleUrls: ['./dynamic-form-select-items.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DynamicFormSelectItemsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DynamicFormSelectItemsComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DynamicFormSelectItemsComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form.component.ts index 7441bf470f..5fa33a422b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form.component.ts @@ -55,21 +55,22 @@ import { ContentType } from '@shared/models/constants'; import { DomSanitizer } from '@angular/platform-browser'; @Component({ - selector: 'tb-dynamic-form', - templateUrl: './dynamic-form.component.html', - styleUrls: ['./dynamic-form.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DynamicFormComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DynamicFormComponent), - multi: true - } - ] + selector: 'tb-dynamic-form', + templateUrl: './dynamic-form.component.html', + styleUrls: ['./dynamic-form.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DynamicFormComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DynamicFormComponent), + multi: true + } + ], + standalone: false }) export class DynamicFormComponent implements OnInit, OnChanges, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.ts index f774a32657..95f137ce39 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.ts @@ -39,17 +39,18 @@ import { Observable, of } from 'rxjs'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-entity-alias-input', - templateUrl: './entity-alias-input.component.html', - styleUrls: ['./entity-alias-input.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => EntityAliasInputComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-entity-alias-input', + templateUrl: './entity-alias-input.component.html', + styleUrls: ['./entity-alias-input.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => EntityAliasInputComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class EntityAliasInputComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/filter/filter-select.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/filter/filter-select.component.ts index 80e1ce105b..c57ce2a231 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/filter/filter-select.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/filter/filter-select.component.ts @@ -37,18 +37,19 @@ import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form- import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-filter-select', - templateUrl: './filter-select.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => FilterSelectComponent), - multi: true - }, - { - provide: ErrorStateMatcher, - useExisting: FilterSelectComponent - }] + selector: 'tb-filter-select', + templateUrl: './filter-select.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => FilterSelectComponent), + multi: true + }, + { + provide: ErrorStateMatcher, + useExisting: FilterSelectComponent + }], + standalone: false }) export class FilterSelectComponent implements ControlValueAccessor, OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/font-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/font-settings-panel.component.ts index 07d9173fd8..7428439921 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/font-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/font-settings-panel.component.ts @@ -46,11 +46,12 @@ import { coerceBoolean } from '@shared/decorators/coercion'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-font-settings-panel', - templateUrl: './font-settings-panel.component.html', - providers: [], - styleUrls: ['./font-settings-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-font-settings-panel', + templateUrl: './font-settings-panel.component.html', + providers: [], + styleUrls: ['./font-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class FontSettingsPanelComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/font-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/font-settings.component.ts index 203b9080bf..52e2169311 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/font-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/font-settings.component.ts @@ -24,16 +24,17 @@ import { isDefinedAndNotNull } from '@core/utils'; import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ - selector: 'tb-font-settings', - templateUrl: './font-settings.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => FontSettingsComponent), - multi: true - } - ] + selector: 'tb-font-settings', + templateUrl: './font-settings.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => FontSettingsComponent), + multi: true + } + ], + standalone: false }) export class FontSettingsComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.ts index ba778cf607..c908c86eea 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.ts @@ -37,16 +37,17 @@ import { DataKeysCallbacks } from '@home/components/widget/lib/settings/common/k import { Datasource } from '@shared/models/widget.models'; @Component({ - selector: 'tb-gradient', - templateUrl: './gradient.component.html', - styleUrls: ['color-settings-panel.component.scss', 'gradient.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => GradientComponent), - multi: true - } - ] + selector: 'tb-gradient', + templateUrl: './gradient.component.html', + styleUrls: ['color-settings-panel.component.scss', 'gradient.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => GradientComponent), + multi: true + } + ], + standalone: false }) export class GradientComponent implements OnInit, ControlValueAccessor, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/image-cards-select.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/image-cards-select.component.ts index dca656ac46..8021f9d2dd 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/image-cards-select.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/image-cards-select.component.ts @@ -52,7 +52,8 @@ export interface ImageCardsColumns { { // eslint-disable-next-line @angular-eslint/directive-selector selector: 'tb-image-cards-select-option', - } + standalone: false +} ) export class ImageCardsSelectOptionDirective { @@ -70,17 +71,18 @@ export class ImageCardsSelectOptionDirective { } @Component({ - selector: 'tb-image-cards-select', - templateUrl: './image-cards-select.component.html', - styleUrls: ['./image-cards-select.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ImageCardsSelectComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-image-cards-select', + templateUrl: './image-cards-select.component.html', + styleUrls: ['./image-cards-select.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ImageCardsSelectComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ImageCardsSelectComponent implements ControlValueAccessor, OnInit, OnChanges, AfterContentInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/indicator/status-widget-state-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/indicator/status-widget-state-settings.component.ts index a810896685..ed80795ca0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/indicator/status-widget-state-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/indicator/status-widget-state-settings.component.ts @@ -24,16 +24,17 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-status-widget-state-settings', - templateUrl: './status-widget-state-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => StatusWidgetStateSettingsComponent), - multi: true - } - ] + selector: 'tb-status-widget-state-settings', + templateUrl: './status-widget-state-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => StatusWidgetStateSettingsComponent), + multi: true + } + ], + standalone: false }) export class StatusWidgetStateSettingsComponent implements OnInit, OnChanges, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/key/data-key-config-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/key/data-key-config-dialog.component.ts index 6ed15ce4f5..131a332f04 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/key/data-key-config-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/key/data-key-config-dialog.component.ts @@ -60,10 +60,11 @@ export interface DataKeyConfigDialogData { } @Component({ - selector: 'tb-data-key-config-dialog', - templateUrl: './data-key-config-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: DataKeyConfigDialogComponent}], - styleUrls: ['./data-key-config-dialog.component.scss'] + selector: 'tb-data-key-config-dialog', + templateUrl: './data-key-config-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: DataKeyConfigDialogComponent }], + styleUrls: ['./data-key-config-dialog.component.scss'], + standalone: false }) export class DataKeyConfigDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/key/data-key-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/key/data-key-config.component.ts index dafcce57b6..4311a06ddd 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/key/data-key-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/key/data-key-config.component.ts @@ -62,21 +62,22 @@ import { FormProperty } from '@shared/models/dynamic-form.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-data-key-config', - templateUrl: './data-key-config.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DataKeyConfigComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DataKeyConfigComponent), - multi: true, - } - ] + selector: 'tb-data-key-config', + templateUrl: './data-key-config.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DataKeyConfigComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DataKeyConfigComponent), + multi: true, + } + ], + standalone: false }) export class DataKeyConfigComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/key/data-key-input.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/key/data-key-input.component.ts index 1c1fa01956..28a6714d23 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/key/data-key-input.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/key/data-key-input.component.ts @@ -55,17 +55,18 @@ import { IAliasController } from '@core/api/widget-api.models'; import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-field'; @Component({ - selector: 'tb-data-key-input', - templateUrl: './data-key-input.component.html', - styleUrls: ['./data-key-input.component.scss', './data-keys.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DataKeyInputComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-data-key-input', + templateUrl: './data-key-input.component.html', + styleUrls: ['./data-key-input.component.scss', './data-keys.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DataKeyInputComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DataKeyInputComponent implements ControlValueAccessor, OnInit, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/key/data-keys.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/key/data-keys.component.ts index 44fb225c96..02aa5b7548 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/key/data-keys.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/key/data-keys.component.ts @@ -75,26 +75,27 @@ import { FormProperty } from '@shared/models/dynamic-form.models'; import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-field'; @Component({ - selector: 'tb-data-keys', - templateUrl: './data-keys.component.html', - styleUrls: ['./data-keys.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DataKeysComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DataKeysComponent), - multi: true, - }, - { - provide: ErrorStateMatcher, - useExisting: DataKeysComponent - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-data-keys', + templateUrl: './data-keys.component.html', + styleUrls: ['./data-keys.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DataKeysComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DataKeysComponent), + multi: true, + }, + { + provide: ErrorStateMatcher, + useExisting: DataKeysComponent + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChanges, ErrorStateMatcher, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.ts index 0f946cd479..99e7f21e19 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.ts @@ -29,16 +29,17 @@ import { coerceBoolean } from '@shared/decorators/coercion'; // @dynamic @Component({ - selector: 'tb-legend-config', - templateUrl: './legend-config.component.html', - styleUrls: ['./../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => LegendConfigComponent), - multi: true - } - ] + selector: 'tb-legend-config', + templateUrl: './legend-config.component.html', + styleUrls: ['./../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => LegendConfigComponent), + multi: true + } + ], + standalone: false }) export class LegendConfigComponent implements OnInit, OnDestroy, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/additional-map-data-source-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/additional-map-data-source-row.component.ts index 57646cb304..7976a3773a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/additional-map-data-source-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/additional-map-data-source-row.component.ts @@ -41,17 +41,18 @@ import { genNextLabelForDataKeys } from '@core/utils'; import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models'; @Component({ - selector: 'tb-additional-map-data-source-row', - templateUrl: './additional-map-data-source-row.component.html', - styleUrls: ['./additional-map-data-source-row.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AdditionalMapDataSourceRowComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-additional-map-data-source-row', + templateUrl: './additional-map-data-source-row.component.html', + styleUrls: ['./additional-map-data-source-row.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AdditionalMapDataSourceRowComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class AdditionalMapDataSourceRowComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/additional-map-data-sources.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/additional-map-data-sources.component.ts index 7e96dcf847..eb8fef90d0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/additional-map-data-sources.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/additional-map-data-sources.component.ts @@ -37,22 +37,23 @@ import { import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models'; @Component({ - selector: 'tb-additional-map-data-sources', - templateUrl: './additional-map-data-sources.component.html', - styleUrls: ['./additional-map-data-sources.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AdditionalMapDataSourcesComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => AdditionalMapDataSourcesComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-additional-map-data-sources', + templateUrl: './additional-map-data-sources.component.html', + styleUrls: ['./additional-map-data-sources.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AdditionalMapDataSourcesComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => AdditionalMapDataSourcesComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class AdditionalMapDataSourcesComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component.ts index 7f8fe16279..102cfe97b8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component.ts @@ -28,11 +28,12 @@ import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models'; @Component({ - selector: 'tb-data-layer-color-settings-panel', - templateUrl: './data-layer-color-settings-panel.component.html', - providers: [], - styleUrls: ['./data-layer-color-settings-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-data-layer-color-settings-panel', + templateUrl: './data-layer-color-settings-panel.component.html', + providers: [], + styleUrls: ['./data-layer-color-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DataLayerColorSettingsPanelComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings.component.ts index 17e3a15177..f3c095ba4e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings.component.ts @@ -27,16 +27,17 @@ import { MapSettingsContext } from '@home/components/widget/lib/settings/common/ import { DatasourceType } from '@shared/models/widget.models'; @Component({ - selector: 'tb-data-layer-color-settings', - templateUrl: './data-layer-color-settings.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DataLayerColorSettingsComponent), - multi: true - } - ] + selector: 'tb-data-layer-color-settings', + templateUrl: './data-layer-color-settings.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DataLayerColorSettingsComponent), + multi: true + } + ], + standalone: false }) export class DataLayerColorSettingsComponent implements ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-pattern-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-pattern-settings.component.ts index 5a7c1afa0b..6bc2fb7489 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-pattern-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-pattern-settings.component.ts @@ -37,21 +37,22 @@ import { coerceBoolean } from '@shared/decorators/coercion'; import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models'; @Component({ - selector: 'tb-data-layer-pattern-settings', - templateUrl: './data-layer-pattern-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DataLayerPatternSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DataLayerPatternSettingsComponent), - multi: true - } - ] + selector: 'tb-data-layer-pattern-settings', + templateUrl: './data-layer-pattern-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DataLayerPatternSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DataLayerPatternSettingsComponent), + multi: true + } + ], + standalone: false }) export class DataLayerPatternSettingsComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/image-map-source-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/image-map-source-settings.component.ts index ddd3b1842d..ed02417950 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/image-map-source-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/image-map-source-settings.component.ts @@ -32,21 +32,22 @@ import { MapSettingsContext } from '@home/components/widget/lib/settings/common/ import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; @Component({ - selector: 'tb-image-map-source-settings', - templateUrl: './image-map-source-settings.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ImageMapSourceSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => ImageMapSourceSettingsComponent), - multi: true - } - ] + selector: 'tb-image-map-source-settings', + templateUrl: './image-map-source-settings.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ImageMapSourceSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ImageMapSourceSettingsComponent), + multi: true + } + ], + standalone: false }) export class ImageMapSourceSettingsComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-action-button-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-action-button-row.component.ts index b58999a406..3d474c79e1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-action-button-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-action-button-row.component.ts @@ -30,18 +30,19 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { isEmptyStr } from '@core/utils'; @Component({ - selector: 'tb-map-action-button-row', - templateUrl: 'map-action-button-row.component.html', - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MapActionButtonRowComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MapActionButtonRowComponent), - multi: true - }] + selector: 'tb-map-action-button-row', + templateUrl: 'map-action-button-row.component.html', + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MapActionButtonRowComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MapActionButtonRowComponent), + multi: true + }], + standalone: false }) export class MapActionButtonRowComponent implements ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-action-buttons-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-action-buttons-settings.component.ts index 76968e3e4d..2494d4b30a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-action-buttons-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-action-buttons-settings.component.ts @@ -31,18 +31,19 @@ import { CdkDragDrop } from '@angular/cdk/drag-drop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-map-action-button-settings', - templateUrl: './map-action-buttons-settings.component.html', - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MapActionButtonsSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MapActionButtonsSettingsComponent), - multi: true - }] + selector: 'tb-map-action-button-settings', + templateUrl: './map-action-buttons-settings.component.html', + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MapActionButtonsSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MapActionButtonsSettingsComponent), + multi: true + }], + standalone: false }) export class MapActionButtonsSettingsComponent implements ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.ts index 8c5e37d148..43f9616809 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.ts @@ -56,10 +56,11 @@ export interface MapDataLayerDialogData { } @Component({ - selector: 'tb-map-data-layer-dialog', - templateUrl: './map-data-layer-dialog.component.html', - styleUrls: ['./map-data-layer-dialog.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-map-data-layer-dialog', + templateUrl: './map-data-layer-dialog.component.html', + styleUrls: ['./map-data-layer-dialog.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class MapDataLayerDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-row.component.ts index 25ede1cea3..707d8f983f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-row.component.ts @@ -57,17 +57,18 @@ import { import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models'; @Component({ - selector: 'tb-map-data-layer-row', - templateUrl: './map-data-layer-row.component.html', - styleUrls: ['./map-data-layer-row.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MapDataLayerRowComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-map-data-layer-row', + templateUrl: './map-data-layer-row.component.html', + styleUrls: ['./map-data-layer-row.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MapDataLayerRowComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class MapDataLayerRowComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layers.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layers.component.ts index 9bf34b08f8..63fe3dc31a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layers.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layers.component.ts @@ -41,22 +41,23 @@ import { MapSettingsContext } from '@home/components/widget/lib/settings/common/ import { CdkDragDrop } from '@angular/cdk/drag-drop'; @Component({ - selector: 'tb-map-data-layers', - templateUrl: './map-data-layers.component.html', - styleUrls: ['./map-data-layers.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MapDataLayersComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MapDataLayersComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-map-data-layers', + templateUrl: './map-data-layers.component.html', + styleUrls: ['./map-data-layers.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MapDataLayersComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MapDataLayersComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class MapDataLayersComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-source-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-source-row.component.ts index 7737c3a4b6..114e22b5a9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-source-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-source-row.component.ts @@ -39,17 +39,18 @@ import { EntityType } from '@shared/models/entity-type.models'; import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models'; @Component({ - selector: 'tb-map-data-source-row', - templateUrl: './map-data-source-row.component.html', - styleUrls: ['./map-data-source-row.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MapDataSourceRowComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-map-data-source-row', + templateUrl: './map-data-source-row.component.html', + styleUrls: ['./map-data-source-row.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MapDataSourceRowComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class MapDataSourceRowComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-sources.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-sources.component.ts index 4b62112cc1..71afc02dec 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-sources.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-sources.component.ts @@ -37,22 +37,23 @@ import { import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models'; @Component({ - selector: 'tb-map-data-sources', - templateUrl: './map-data-sources.component.html', - styleUrls: ['./map-data-sources.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MapDataSourcesComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MapDataSourcesComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-map-data-sources', + templateUrl: './map-data-sources.component.html', + styleUrls: ['./map-data-sources.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MapDataSourcesComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MapDataSourcesComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class MapDataSourcesComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-layer-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-layer-row.component.ts index 14136f018e..1604ff8683 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-layer-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-layer-row.component.ts @@ -60,17 +60,18 @@ import { } from '@home/components/widget/lib/settings/common/map/map-layer-settings-panel.component'; @Component({ - selector: 'tb-map-layer-row', - templateUrl: './map-layer-row.component.html', - styleUrls: ['./map-layer-row.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MapLayerRowComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-map-layer-row', + templateUrl: './map-layer-row.component.html', + styleUrls: ['./map-layer-row.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MapLayerRowComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class MapLayerRowComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-layer-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-layer-settings-panel.component.ts index 536c953bb7..bedb92a6af 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-layer-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-layer-settings-panel.component.ts @@ -37,11 +37,12 @@ import { import { TranslateService } from '@ngx-translate/core'; @Component({ - selector: 'tb-map-layer-settings-panel', - templateUrl: './map-layer-settings-panel.component.html', - providers: [], - styleUrls: ['./map-layer-settings-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-map-layer-settings-panel', + templateUrl: './map-layer-settings-panel.component.html', + providers: [], + styleUrls: ['./map-layer-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class MapLayerSettingsPanelComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-layers.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-layers.component.ts index feaa633b34..35dc5ff04a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-layers.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-layers.component.ts @@ -38,22 +38,23 @@ import { } from '@shared/models/widget/maps/map.models'; @Component({ - selector: 'tb-map-layers', - templateUrl: './map-layers.component.html', - styleUrls: ['./map-layers.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MapLayersComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MapLayersComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-map-layers', + templateUrl: './map-layers.component.html', + styleUrls: ['./map-layers.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MapLayersComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MapLayersComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class MapLayersComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-settings.component.ts index 985e5df1f9..0e33f9d83e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-settings.component.ts @@ -54,21 +54,22 @@ import { deepClone, mergeDeep } from '@core/utils'; import { MatDialog } from '@angular/material/dialog'; @Component({ - selector: 'tb-map-settings', - templateUrl: './map-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MapSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MapSettingsComponent), - multi: true - } - ] + selector: 'tb-map-settings', + templateUrl: './map-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MapSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MapSettingsComponent), + multi: true + } + ], + standalone: false }) export class MapSettingsComponent implements OnInit, ControlValueAccessor, Validator, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-tooltip-tag-actions.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-tooltip-tag-actions.component.ts index 5c751ac950..8c9864c456 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-tooltip-tag-actions.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-tooltip-tag-actions.component.ts @@ -37,17 +37,18 @@ import { TranslateService } from '@ngx-translate/core'; import { deepClone } from '@core/utils'; @Component({ - selector: 'tb-map-tooltip-tag-actions-panel', - templateUrl: './map-tooltip-tag-actions.component.html', - styleUrls: ['./map-tooltip-tag-actions.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MapTooltipTagActionsComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-map-tooltip-tag-actions-panel', + templateUrl: './map-tooltip-tag-actions.component.html', + styleUrls: ['./map-tooltip-tag-actions.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MapTooltipTagActionsComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class MapTooltipTagActionsComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-clustering-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-clustering-settings.component.ts index 8c7ff9371e..eac6b9e410 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-clustering-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-clustering-settings.component.ts @@ -31,21 +31,22 @@ import { MarkerClusteringSettings } from '@shared/models/widget/maps/map.models' import { merge } from 'rxjs'; @Component({ - selector: 'tb-marker-clustering-settings', - templateUrl: './marker-clustering-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MarkerClusteringSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MarkerClusteringSettingsComponent), - multi: true - } - ] + selector: 'tb-marker-clustering-settings', + templateUrl: './marker-clustering-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MarkerClusteringSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MarkerClusteringSettingsComponent), + multi: true + } + ], + standalone: false }) export class MarkerClusteringSettingsComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-icon-shapes.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-icon-shapes.component.ts index f1671807d8..8094bc0a68 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-icon-shapes.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-icon-shapes.component.ts @@ -42,11 +42,12 @@ interface MarkerIconContainerInfo { } @Component({ - selector: 'tb-marker-icon-shapes', - templateUrl: './marker-icon-shapes.component.html', - providers: [], - styleUrls: ['./marker-icon-shapes.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-marker-icon-shapes', + templateUrl: './marker-icon-shapes.component.html', + providers: [], + styleUrls: ['./marker-icon-shapes.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class MarkerIconShapesComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings-panel.component.ts index eea2bc6700..67539b82f2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings-panel.component.ts @@ -25,11 +25,12 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MarkerImageSettings, MarkerImageType } from '@shared/models/widget/maps/map.models'; @Component({ - selector: 'tb-marker-image-settings-panel', - templateUrl: './marker-image-settings-panel.component.html', - providers: [], - styleUrls: ['./marker-image-settings-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-marker-image-settings-panel', + templateUrl: './marker-image-settings-panel.component.html', + providers: [], + styleUrls: ['./marker-image-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class MarkerImageSettingsPanelComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings.component.ts index 0d84469410..6da6c809e0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings.component.ts @@ -24,16 +24,17 @@ import { } from '@home/components/widget/lib/settings/common/map/marker-image-settings-panel.component'; @Component({ - selector: 'tb-marker-image-settings', - templateUrl: './marker-image-settings.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MarkerImageSettingsComponent), - multi: true - } - ] + selector: 'tb-marker-image-settings', + templateUrl: './marker-image-settings.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MarkerImageSettingsComponent), + multi: true + } + ], + standalone: false }) export class MarkerImageSettingsComponent implements ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-shape-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-shape-settings.component.ts index 319b423b2d..e251f6f9a8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-shape-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-shape-settings.component.ts @@ -53,16 +53,17 @@ import { MapSettingsContext } from '@home/components/widget/lib/settings/common/ import { DatasourceType } from '@shared/models/widget.models'; @Component({ - selector: 'tb-marker-shape-settings', - templateUrl: './marker-shape-settings.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MarkerShapeSettingsComponent), - multi: true - } - ] + selector: 'tb-marker-shape-settings', + templateUrl: './marker-shape-settings.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MarkerShapeSettingsComponent), + multi: true + } + ], + standalone: false }) export class MarkerShapeSettingsComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-shapes.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-shapes.component.ts index 5499c6e39c..23fadbf093 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-shapes.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-shapes.component.ts @@ -37,11 +37,12 @@ interface MarkerShapeInfo { } @Component({ - selector: 'tb-marker-shapes', - templateUrl: './marker-shapes.component.html', - providers: [], - styleUrls: ['./marker-shapes.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-marker-shapes', + templateUrl: './marker-shapes.component.html', + providers: [], + styleUrls: ['./marker-shapes.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class MarkerShapesComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-image-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-image-settings-panel.component.ts index 8988365644..dcea878241 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-image-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-image-settings-panel.component.ts @@ -22,11 +22,12 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ShapeFillImageSettings, ShapeFillImageType } from '@shared/models/widget/maps/map.models'; @Component({ - selector: 'tb-shape-fill-image-settings-panel', - templateUrl: './shape-fill-image-settings-panel.component.html', - providers: [], - styleUrls: ['./shape-fill-image-settings-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-shape-fill-image-settings-panel', + templateUrl: './shape-fill-image-settings-panel.component.html', + providers: [], + styleUrls: ['./shape-fill-image-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ShapeFillImageSettingsPanelComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-image-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-image-settings.component.ts index 466525f46f..5c9bbb260f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-image-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-image-settings.component.ts @@ -24,16 +24,17 @@ import { } from '@home/components/widget/lib/settings/common/map/shape-fill-image-settings-panel.component'; @Component({ - selector: 'tb-shape-fill-image-settings', - templateUrl: './shape-fill-image-settings.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ShapeFillImageSettingsComponent), - multi: true - } - ] + selector: 'tb-shape-fill-image-settings', + templateUrl: './shape-fill-image-settings.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ShapeFillImageSettingsComponent), + multi: true + } + ], + standalone: false }) export class ShapeFillImageSettingsComponent implements ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-stripe-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-stripe-settings-panel.component.ts index 60fab91c82..52ab290e6f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-stripe-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-stripe-settings-panel.component.ts @@ -28,11 +28,12 @@ import { MapSettingsContext } from '@home/components/widget/lib/settings/common/ import { DatasourceType } from '@shared/models/widget.models'; @Component({ - selector: 'tb-shape-fill-stripe-settings-panel', - templateUrl: './shape-fill-stripe-settings-panel.component.html', - providers: [], - styleUrls: ['./shape-fill-stripe-settings-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-shape-fill-stripe-settings-panel', + templateUrl: './shape-fill-stripe-settings-panel.component.html', + providers: [], + styleUrls: ['./shape-fill-stripe-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ShapeFillStripeSettingsPanelComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-stripe-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-stripe-settings.component.ts index 0b8d19b4a7..b1f65c541c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-stripe-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-stripe-settings.component.ts @@ -28,16 +28,17 @@ import { } from '@home/components/widget/lib/settings/common/map/shape-fill-stripe-settings-panel.component'; @Component({ - selector: 'tb-shape-fill-stripe-settings', - templateUrl: './shape-fill-stripe-settings.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ShapeFillStripeSettingsComponent), - multi: true - } - ] + selector: 'tb-shape-fill-stripe-settings', + templateUrl: './shape-fill-stripe-settings.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ShapeFillStripeSettingsComponent), + multi: true + } + ], + standalone: false }) export class ShapeFillStripeSettingsComponent implements ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/trip-timeline-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/trip-timeline-settings.component.ts index 1a041cd584..b3064b0dd3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/trip-timeline-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/trip-timeline-settings.component.ts @@ -33,21 +33,22 @@ import { } from '@shared/models/widget/maps/map.models'; @Component({ - selector: 'tb-trip-timeline-settings', - templateUrl: './trip-timeline-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TripTimelineSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => TripTimelineSettingsComponent), - multi: true - } - ] + selector: 'tb-trip-timeline-settings', + templateUrl: './trip-timeline-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TripTimelineSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => TripTimelineSettingsComponent), + multi: true + } + ], + standalone: false }) export class TripTimelineSettingsComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/scada/scada-symbol-object-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/scada/scada-symbol-object-settings.component.ts index 80d31cf678..90616286f5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/scada/scada-symbol-object-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/scada/scada-symbol-object-settings.component.ts @@ -56,21 +56,22 @@ import { map } from 'rxjs/operators'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-scada-symbol-object-settings', - templateUrl: './scada-symbol-object-settings.component.html', - styleUrls: ['./scada-symbol-object-settings.component.scss', './../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ScadaSymbolObjectSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => ScadaSymbolObjectSettingsComponent), - multi: true - } - ] + selector: 'tb-scada-symbol-object-settings', + templateUrl: './scada-symbol-object-settings.component.html', + styleUrls: ['./scada-symbol-object-settings.component.scss', './../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ScadaSymbolObjectSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ScadaSymbolObjectSettingsComponent), + multi: true + } + ], + standalone: false }) export class ScadaSymbolObjectSettingsComponent implements OnInit, OnChanges, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/value-source-data-key.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/value-source-data-key.component.ts index 2bc5f55597..cabeb765c8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/value-source-data-key.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/value-source-data-key.component.ts @@ -39,16 +39,17 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-value-source-data-key', - templateUrl: './value-source-data-key.component.html', - styleUrls: ['value-source-data-key.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ValueSourceDataKeyComponent), - multi: true - } - ] + selector: 'tb-value-source-data-key', + templateUrl: './value-source-data-key.component.html', + styleUrls: ['value-source-data-key.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ValueSourceDataKeyComponent), + multi: true + } + ], + standalone: false }) export class ValueSourceDataKeyComponent extends PageComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/value-source.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/value-source.component.ts index e006e54208..2b91efa474 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/value-source.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/value-source.component.ts @@ -37,16 +37,17 @@ export interface ValueSourceProperty { } @Component({ - selector: 'tb-value-source', - templateUrl: './value-source.component.html', - styleUrls: ['./../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ValueSourceComponent), - multi: true - } - ] + selector: 'tb-value-source', + templateUrl: './value-source.component.html', + styleUrls: ['./../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ValueSourceComponent), + multi: true + } + ], + standalone: false }) export class ValueSourceComponent extends PageComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-font.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-font.component.ts index 980cfe5780..79633ac7f2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-font.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-font.component.ts @@ -32,16 +32,17 @@ export interface WidgetFont { } @Component({ - selector: 'tb-widget-font', - templateUrl: './widget-font.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => WidgetFontComponent), - multi: true - } - ] + selector: 'tb-widget-font', + templateUrl: './widget-font.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => WidgetFontComponent), + multi: true + } + ], + standalone: false }) export class WidgetFontComponent extends PageComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget/widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget/widget-settings.component.ts index 7b07fe47e0..d779a634ac 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget/widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget/widget-settings.component.ts @@ -47,19 +47,20 @@ import { WidgetConfigCallbacks } from '@home/components/widget/config/widget-con import { FormProperty } from '@shared/models/dynamic-form.models'; @Component({ - selector: 'tb-widget-settings', - templateUrl: './widget-settings.component.html', - styleUrls: ['./widget-settings.component.scss'], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => WidgetSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => WidgetSettingsComponent), - multi: true - }] + selector: 'tb-widget-settings', + templateUrl: './widget-settings.component.html', + styleUrls: ['./widget-settings.component.scss'], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => WidgetSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => WidgetSettingsComponent), + multi: true + }], + standalone: false }) export class WidgetSettingsComponent implements ControlValueAccessor, OnDestroy, OnChanges, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/device-key-autocomplete.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/device-key-autocomplete.component.ts index 52110ad50a..f02de5fa8d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/device-key-autocomplete.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/device-key-autocomplete.component.ts @@ -49,16 +49,17 @@ import { coerceBoolean } from '@shared/decorators/coercion'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-device-key-autocomplete', - templateUrl: './device-key-autocomplete.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DeviceKeyAutocompleteComponent), - multi: true - } - ] + selector: 'tb-device-key-autocomplete', + templateUrl: './device-key-autocomplete.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceKeyAutocompleteComponent), + multi: true + } + ], + standalone: false }) export class DeviceKeyAutocompleteComponent extends PageComponent implements OnInit, ControlValueAccessor, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/knob-control-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/knob-control-widget-settings.component.ts index 481097cf94..9c115025d7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/knob-control-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/knob-control-widget-settings.component.ts @@ -24,9 +24,10 @@ import { ValueType } from '@shared/models/constants'; import { deepClone } from '@core/utils'; @Component({ - selector: 'tb-knob-control-widget-settings', - templateUrl: './knob-control-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-knob-control-widget-settings', + templateUrl: './knob-control-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class KnobControlWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/led-indicator-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/led-indicator-widget-settings.component.ts index 45cfbcf7ec..faaa56db65 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/led-indicator-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/led-indicator-widget-settings.component.ts @@ -23,9 +23,10 @@ import { WidgetService } from '@core/http/widget.service'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; @Component({ - selector: 'tb-led-indicator-widget-settings', - templateUrl: './led-indicator-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-led-indicator-widget-settings', + templateUrl: './led-indicator-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class LedIndicatorWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/persistent-table-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/persistent-table-widget-settings.component.ts index d89e46e7b1..170947af25 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/persistent-table-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/persistent-table-widget-settings.component.ts @@ -35,9 +35,10 @@ interface DisplayColumn { } @Component({ - selector: 'tb-persistent-table-widget-settings', - templateUrl: './persistent-table-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-persistent-table-widget-settings', + templateUrl: './persistent-table-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class PersistentTableWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/round-switch-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/round-switch-widget-settings.component.ts index 6f008e5a82..8c443e1462 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/round-switch-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/round-switch-widget-settings.component.ts @@ -23,9 +23,10 @@ import { switchRpcDefaultSettings } from '@home/components/widget/lib/settings/c import { deepClone } from '@core/utils'; @Component({ - selector: 'tb-round-switch-widget-settings', - templateUrl: './round-switch-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-round-switch-widget-settings', + templateUrl: './round-switch-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class RoundSwitchWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/rpc-button-style.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/rpc-button-style.component.ts index 6edd8f191b..730bf1a0b5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/rpc-button-style.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/rpc-button-style.component.ts @@ -29,16 +29,17 @@ export interface RpcButtonStyle { } @Component({ - selector: 'tb-rpc-button-style', - templateUrl: './rpc-button-style.component.html', - styleUrls: ['./../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => RpcButtonStyleComponent), - multi: true - } - ] + selector: 'tb-rpc-button-style', + templateUrl: './rpc-button-style.component.html', + styleUrls: ['./../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RpcButtonStyleComponent), + multi: true + } + ], + standalone: false }) export class RpcButtonStyleComponent extends PageComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/rpc-shell-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/rpc-shell-widget-settings.component.ts index 157689a4ad..141ac5a6de 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/rpc-shell-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/rpc-shell-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-rpc-shell-widget-settings', - templateUrl: './rpc-shell-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-rpc-shell-widget-settings', + templateUrl: './rpc-shell-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class RpcShellWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/rpc-terminal-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/rpc-terminal-widget-settings.component.ts index 77e60522fe..31a5a0d81b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/rpc-terminal-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/rpc-terminal-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-rpc-terminal-widget-settings', - templateUrl: './rpc-terminal-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-rpc-terminal-widget-settings', + templateUrl: './rpc-terminal-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class RpcTerminalWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/send-rpc-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/send-rpc-widget-settings.component.ts index b8af3eaf0d..4319b823c2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/send-rpc-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/send-rpc-widget-settings.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { ContentType } from '@shared/models/constants'; @Component({ - selector: 'tb-send-rpc-widget-settings', - templateUrl: './send-rpc-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-send-rpc-widget-settings', + templateUrl: './send-rpc-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class SendRpcWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.ts index c3e768ae5b..d2c022bdf4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.ts @@ -28,9 +28,10 @@ import { import { ValueType } from '@shared/models/constants'; @Component({ - selector: 'tb-single-switch-widget-settings', - templateUrl: './single-switch-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-single-switch-widget-settings', + templateUrl: './single-switch-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class SingleSwitchWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/slide-toggle-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/slide-toggle-widget-settings.component.ts index 888a016d91..3c9bf7fff8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/slide-toggle-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/slide-toggle-widget-settings.component.ts @@ -23,9 +23,10 @@ import { switchRpcDefaultSettings } from '@home/components/widget/lib/settings/c import { deepClone } from '@core/utils'; @Component({ - selector: 'tb-slide-toggle-widget-settings', - templateUrl: './slide-toggle-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-slide-toggle-widget-settings', + templateUrl: './slide-toggle-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class SlideToggleWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/slider-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/slider-widget-settings.component.ts index 53a9d483a7..f3899d7c66 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/slider-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/slider-widget-settings.component.ts @@ -31,9 +31,10 @@ import { formatValue } from '@core/utils'; import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-slider-widget-settings', - templateUrl: './slider-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-slider-widget-settings', + templateUrl: './slider-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class SliderWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/switch-control-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/switch-control-widget-settings.component.ts index d51c9f8d8e..c9ea433d93 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/switch-control-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/switch-control-widget-settings.component.ts @@ -23,9 +23,10 @@ import { switchRpcDefaultSettings } from '@home/components/widget/lib/settings/c import { deepClone } from '@core/utils'; @Component({ - selector: 'tb-switch-control-widget-settings', - templateUrl: './switch-control-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-switch-control-widget-settings', + templateUrl: './switch-control-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class SwitchControlWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/switch-rpc-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/switch-rpc-settings.component.ts index e58006d1cf..29f436c61d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/switch-rpc-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/switch-rpc-settings.component.ts @@ -65,21 +65,22 @@ export const switchRpcDefaultSettings = (): SwitchRpcSettings => ({ }); @Component({ - selector: 'tb-switch-rpc-settings', - templateUrl: './switch-rpc-settings.component.html', - styleUrls: ['./../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => SwitchRpcSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => SwitchRpcSettingsComponent), - multi: true - } - ] + selector: 'tb-switch-rpc-settings', + templateUrl: './switch-rpc-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => SwitchRpcSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => SwitchRpcSettingsComponent), + multi: true + } + ], + standalone: false }) export class SwitchRpcSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/update-device-attribute-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/update-device-attribute-widget-settings.component.ts index a9fedf335c..4871e3db37 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/update-device-attribute-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/update-device-attribute-widget-settings.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { ContentType } from '@shared/models/constants'; @Component({ - selector: 'tb-update-device-attribute-widget-settings', - templateUrl: './update-device-attribute-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-update-device-attribute-widget-settings', + templateUrl: './update-device-attribute-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class UpdateDeviceAttributeWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/value-stepper-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/value-stepper-widget-settings.component.ts index 72377dddbc..ac3921f3ab 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/value-stepper-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/value-stepper-widget-settings.component.ts @@ -33,9 +33,10 @@ import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; type ButtonAppearanceType = 'left' | 'right'; @Component({ - selector: 'tb-value-stepper-widget-settings', - templateUrl: './value-stepper-widget-settings.component.html', - styleUrls: ['../widget-settings.scss'] + selector: 'tb-value-stepper-widget-settings', + templateUrl: './value-stepper-widget-settings.component.html', + styleUrls: ['../widget-settings.scss'], + standalone: false }) export class ValueStepperWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/date/date-range-navigator-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/date/date-range-navigator-widget-settings.component.ts index ece9e5f9dc..183009aef7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/date/date-range-navigator-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/date/date-range-navigator-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-date-range-navigator-widget-settings', - templateUrl: './date-range-navigator-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-date-range-navigator-widget-settings', + templateUrl: './date-range-navigator-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class DateRangeNavigatorWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/entity/entities-hierarchy-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/entity/entities-hierarchy-widget-settings.component.ts index a990e234bb..3acf41af24 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/entity/entities-hierarchy-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/entity/entities-hierarchy-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-entities-hierarchy-widget-settings', - templateUrl: './entities-hierarchy-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-entities-hierarchy-widget-settings', + templateUrl: './entities-hierarchy-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class EntitiesHierarchyWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/entity/entities-table-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/entity/entities-table-key-settings.component.ts index 22483166f0..c1c4a5eab3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/entity/entities-table-key-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/entity/entities-table-key-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-entities-table-key-settings', - templateUrl: './entities-table-key-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-entities-table-key-settings', + templateUrl: './entities-table-key-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class EntitiesTableKeySettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/entity/entities-table-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/entity/entities-table-widget-settings.component.ts index 5c19810eb4..3b31cf5645 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/entity/entities-table-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/entity/entities-table-widget-settings.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { buildPageStepSizeValues } from '@home/components/widget/lib/table-widget.models'; @Component({ - selector: 'tb-entities-table-widget-settings', - templateUrl: './entities-table-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-entities-table-widget-settings', + templateUrl: './entities-table-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class EntitiesTableWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/entity/entity-count-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/entity/entity-count-widget-settings.component.ts index 956158aafc..6b2ef15a65 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/entity/entity-count-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/entity/entity-count-widget-settings.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { countDefaultSettings } from '@home/components/widget/lib/count/count-widget.models'; @Component({ - selector: 'tb-entity-count-widget-settings', - templateUrl: './entity-count-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-entity-count-widget-settings', + templateUrl: './entity-count-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class EntityCountWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-config-single-device-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-config-single-device-widget-settings.component.ts index dcc8f15d2b..404a731df9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-config-single-device-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-config-single-device-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-gateway-config-single-device-widget-settings', - templateUrl: './gateway-config-single-device-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-gateway-config-single-device-widget-settings', + templateUrl: './gateway-config-single-device-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class GatewayConfigSingleDeviceWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-config-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-config-widget-settings.component.ts index c63e19d4ec..6992b416ab 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-config-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-config-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-gateway-config-widget-settings', - templateUrl: './gateway-config-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-gateway-config-widget-settings', + templateUrl: './gateway-config-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class GatewayConfigWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-events-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-events-widget-settings.component.ts index b0f335726b..82551fa327 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-events-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-events-widget-settings.component.ts @@ -23,9 +23,10 @@ import { MatChipInputEvent } from '@angular/material/chips'; import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; @Component({ - selector: 'tb-gateway-events-widget-settings', - templateUrl: './gateway-events-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-gateway-events-widget-settings', + templateUrl: './gateway-events-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class GatewayEventsWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-logs-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-logs-settings.component.ts index 9af2f702da..95d7b437da 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-logs-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-logs-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-gateway-logs-settings', - templateUrl: './gateway-logs-settings.component.html', - styleUrls: ['../widget-settings.scss'] + selector: 'tb-gateway-logs-settings', + templateUrl: './gateway-logs-settings.component.html', + styleUrls: ['../widget-settings.scss'], + standalone: false }) export class GatewayLogsSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-service-rpc-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-service-rpc-settings.component.ts index 720b2538a2..9e30608b3e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-service-rpc-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gateway/gateway-service-rpc-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-gateway-service-rpc-settings', - templateUrl: './gateway-service-rpc-settings.component.html', - styleUrls: ['../widget-settings.scss'] + selector: 'tb-gateway-service-rpc-settings', + templateUrl: './gateway-service-rpc-settings.component.html', + styleUrls: ['../widget-settings.scss'], + standalone: false }) export class GatewayServiceRPCSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/analogue-compass-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/analogue-compass-widget-settings.component.ts index 625f205507..40331412b6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/analogue-compass-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/analogue-compass-widget-settings.component.ts @@ -22,9 +22,10 @@ import { Component } from '@angular/core'; import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; @Component({ - selector: 'tb-analogue-compass-widget-settings', - templateUrl: './analogue-compass-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-analogue-compass-widget-settings', + templateUrl: './analogue-compass-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class AnalogueCompassWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/analogue-linear-gauge-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/analogue-linear-gauge-widget-settings.component.ts index ef7589de8c..58741c3350 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/analogue-linear-gauge-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/analogue-linear-gauge-widget-settings.component.ts @@ -24,9 +24,10 @@ import { } from '@home/components/widget/lib/settings/gauge/analogue-gauge-widget-settings.component'; @Component({ - selector: 'tb-analogue-linear-gauge-widget-settings', - templateUrl: './analogue-gauge-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-analogue-linear-gauge-widget-settings', + templateUrl: './analogue-gauge-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class AnalogueLinearGaugeWidgetSettingsComponent extends AnalogueGaugeWidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/analogue-radial-gauge-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/analogue-radial-gauge-widget-settings.component.ts index 891e248d67..6b60cf8ac0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/analogue-radial-gauge-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/analogue-radial-gauge-widget-settings.component.ts @@ -24,9 +24,10 @@ import { } from '@home/components/widget/lib/settings/gauge/analogue-gauge-widget-settings.component'; @Component({ - selector: 'tb-analogue-radial-gauge-widget-settings', - templateUrl: './analogue-gauge-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-analogue-radial-gauge-widget-settings', + templateUrl: './analogue-gauge-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class AnalogueRadialGaugeWidgetSettingsComponent extends AnalogueGaugeWidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts index e55bbeef66..ff22abd28a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts @@ -49,9 +49,10 @@ import { import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-digital-gauge-widget-settings', - templateUrl: './digital-gauge-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-digital-gauge-widget-settings', + templateUrl: './digital-gauge-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class DigitalGaugeWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/tick-value.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/tick-value.component.ts index dbc093a11f..82e8aacd1f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/tick-value.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/tick-value.component.ts @@ -27,16 +27,17 @@ import { Datasource } from '@shared/models/widget.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-tick-value', - templateUrl: './tick-value.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TickValueComponent), - multi: true - } - ] + selector: 'tb-tick-value', + templateUrl: './tick-value.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TickValueComponent), + multi: true + } + ], + standalone: false }) export class TickValueComponent extends PageComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gpio/gpio-control-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gpio/gpio-control-widget-settings.component.ts index a65f85e500..059c027310 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gpio/gpio-control-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gpio/gpio-control-widget-settings.component.ts @@ -23,9 +23,10 @@ import { GpioItem, gpioItemValidator } from '@home/components/widget/lib/setting import { ContentType } from '@shared/models/constants'; @Component({ - selector: 'tb-gpio-control-widget-settings', - templateUrl: './gpio-control-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-gpio-control-widget-settings', + templateUrl: './gpio-control-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class GpioControlWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gpio/gpio-item.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gpio/gpio-item.component.ts index cae8737c3b..229fc61c6f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gpio/gpio-item.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gpio/gpio-item.component.ts @@ -55,16 +55,17 @@ export const gpioItemValidator = (hasColor: boolean): ValidatorFn => (control: A }; @Component({ - selector: 'tb-gpio-item', - templateUrl: './gpio-item.component.html', - styleUrls: ['./gpio-item.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => GpioItemComponent), - multi: true - } - ] + selector: 'tb-gpio-item', + templateUrl: './gpio-item.component.html', + styleUrls: ['./gpio-item.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => GpioItemComponent), + multi: true + } + ], + standalone: false }) export class GpioItemComponent extends PageComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gpio/gpio-panel-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gpio/gpio-panel-widget-settings.component.ts index 0a2c20f0bf..dff3f9c3cb 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gpio/gpio-panel-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gpio/gpio-panel-widget-settings.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { GpioItem, gpioItemValidator } from '@home/components/widget/lib/settings/gpio/gpio-item.component'; @Component({ - selector: 'tb-gpio-panel-widget-settings', - templateUrl: './gpio-panel-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-gpio-panel-widget-settings', + templateUrl: './gpio-panel-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class GpioPanelWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/home-page/doc-links-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/home-page/doc-links-widget-settings.component.ts index 7fdb10dc99..b57de685f6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/home-page/doc-links-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/home-page/doc-links-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-doc-links-widget-settings', - templateUrl: './doc-links-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-doc-links-widget-settings', + templateUrl: './doc-links-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class DocLinksWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/home-page/quick-links-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/home-page/quick-links-widget-settings.component.ts index 7e90c21767..48806e14ae 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/home-page/quick-links-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/home-page/quick-links-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-quick-links-widget-settings', - templateUrl: './quick-links-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-quick-links-widget-settings', + templateUrl: './quick-links-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class QuickLinksWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/battery-level-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/battery-level-widget-settings.component.ts index 41b28a3b4c..abd51b35d5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/battery-level-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/battery-level-widget-settings.component.ts @@ -30,9 +30,10 @@ import { import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-battery-level-widget-settings', - templateUrl: './battery-level-widget-settings.component.html', - styleUrls: [] + selector: 'tb-battery-level-widget-settings', + templateUrl: './battery-level-widget-settings.component.html', + styleUrls: [], + standalone: false }) export class BatteryLevelWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/liquid-level-card-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/liquid-level-card-widget-settings.component.ts index a0d0afc14d..f3086291d6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/liquid-level-card-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/liquid-level-card-widget-settings.component.ts @@ -56,9 +56,10 @@ import { EntityService } from '@core/http/entity.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-liquid-level-card-widget-settings', - templateUrl: './liquid-level-card-widget-settings.component.html', - styleUrls: [] + selector: 'tb-liquid-level-card-widget-settings', + templateUrl: './liquid-level-card-widget-settings.component.html', + styleUrls: [], + standalone: false }) export class LiquidLevelCardWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/signal-strength-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/signal-strength-widget-settings.component.ts index a676a8279b..6ce541273a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/signal-strength-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/signal-strength-widget-settings.component.ts @@ -30,9 +30,10 @@ import { DateFormatProcessor, DateFormatSettings } from '@shared/models/widget-s import { getSourceTbUnitSymbol } from '@shared/models/unit.models'; @Component({ - selector: 'tb-signal-strength-widget-settings', - templateUrl: './signal-strength-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'], + selector: 'tb-signal-strength-widget-settings', + templateUrl: './signal-strength-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class SignalStrengthWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.ts index b2327a94fa..942d2cf3c8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.ts @@ -28,9 +28,10 @@ import { import { ValueType } from '@shared/models/constants'; @Component({ - selector: 'tb-status-widget-settings', - templateUrl: './status-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'], + selector: 'tb-status-widget-settings', + templateUrl: './status-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class StatusWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/datakey-select-option.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/datakey-select-option.component.ts index 63689be5c5..1734b25c46 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/datakey-select-option.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/datakey-select-option.component.ts @@ -45,16 +45,17 @@ export const dataKeySelectOptionValidator = (control: AbstractControl) => { }; @Component({ - selector: 'tb-datakey-select-option', - templateUrl: './datakey-select-option.component.html', - styleUrls: ['./datakey-select-option.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DataKeySelectOptionComponent), - multi: true - } - ] + selector: 'tb-datakey-select-option', + templateUrl: './datakey-select-option.component.html', + styleUrls: ['./datakey-select-option.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DataKeySelectOptionComponent), + multi: true + } + ], + standalone: false }) export class DataKeySelectOptionComponent extends PageComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/device-claiming-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/device-claiming-widget-settings.component.ts index a74152df79..00993a3b27 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/device-claiming-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/device-claiming-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-device-claiming-widget-settings', - templateUrl: './device-claiming-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-device-claiming-widget-settings', + templateUrl: './device-claiming-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class DeviceClaimingWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/photo-camera-input-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/photo-camera-input-widget-settings.component.ts index 7cd51b5722..8350ababa2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/photo-camera-input-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/photo-camera-input-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-photo-camera-input-widget-settings', - templateUrl: './photo-camera-input-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-photo-camera-input-widget-settings', + templateUrl: './photo-camera-input-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class PhotoCameraInputWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-attribute-general-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-attribute-general-settings.component.ts index 5d9703e95b..56dbc014c3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-attribute-general-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-attribute-general-settings.component.ts @@ -54,21 +54,22 @@ export function updateAttributeGeneralDefaultSettings(hasLabelValue = true): Upd } @Component({ - selector: 'tb-update-attribute-general-settings', - templateUrl: './update-attribute-general-settings.component.html', - styleUrls: ['./../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => UpdateAttributeGeneralSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => UpdateAttributeGeneralSettingsComponent), - multi: true - } - ] + selector: 'tb-update-attribute-general-settings', + templateUrl: './update-attribute-general-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => UpdateAttributeGeneralSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => UpdateAttributeGeneralSettingsComponent), + multi: true + } + ], + standalone: false }) export class UpdateAttributeGeneralSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-boolean-attribute-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-boolean-attribute-widget-settings.component.ts index fc212f5ae3..8e9e739543 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-boolean-attribute-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-boolean-attribute-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-update-boolean-attribute-widget-settings', - templateUrl: './update-boolean-attribute-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-update-boolean-attribute-widget-settings', + templateUrl: './update-boolean-attribute-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class UpdateBooleanAttributeWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-date-attribute-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-date-attribute-widget-settings.component.ts index 0e18de2ee0..895e0affc0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-date-attribute-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-date-attribute-widget-settings.component.ts @@ -25,9 +25,10 @@ import { } from '@home/components/widget/lib/settings/input/update-attribute-general-settings.component'; @Component({ - selector: 'tb-update-date-attribute-widget-settings', - templateUrl: './update-date-attribute-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-update-date-attribute-widget-settings', + templateUrl: './update-date-attribute-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class UpdateDateAttributeWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-double-attribute-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-double-attribute-widget-settings.component.ts index 305db7e982..1323f552aa 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-double-attribute-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-double-attribute-widget-settings.component.ts @@ -25,9 +25,10 @@ import { } from '@home/components/widget/lib/settings/input/update-attribute-general-settings.component'; @Component({ - selector: 'tb-update-double-attribute-widget-settings', - templateUrl: './update-double-attribute-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-update-double-attribute-widget-settings', + templateUrl: './update-double-attribute-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class UpdateDoubleAttributeWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-image-attribute-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-image-attribute-widget-settings.component.ts index 7839e48cfc..506fe0b69e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-image-attribute-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-image-attribute-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-update-image-attribute-widget-settings', - templateUrl: './update-image-attribute-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-update-image-attribute-widget-settings', + templateUrl: './update-image-attribute-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class UpdateImageAttributeWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-integer-attribute-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-integer-attribute-widget-settings.component.ts index 997b9d1805..3d6ad3fc8f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-integer-attribute-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-integer-attribute-widget-settings.component.ts @@ -25,9 +25,10 @@ import { } from '@home/components/widget/lib/settings/input/update-attribute-general-settings.component'; @Component({ - selector: 'tb-update-integer-attribute-widget-settings', - templateUrl: './update-integer-attribute-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-update-integer-attribute-widget-settings', + templateUrl: './update-integer-attribute-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class UpdateIntegerAttributeWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-json-attribute-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-json-attribute-widget-settings.component.ts index 84be46e289..2154c40f3a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-json-attribute-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-json-attribute-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-update-json-attribute-widget-settings', - templateUrl: './update-json-attribute-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-update-json-attribute-widget-settings', + templateUrl: './update-json-attribute-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class UpdateJsonAttributeWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-location-attribute-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-location-attribute-widget-settings.component.ts index 7756a465c8..18ecb43711 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-location-attribute-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-location-attribute-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-update-location-attribute-widget-settings', - templateUrl: './update-location-attribute-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-update-location-attribute-widget-settings', + templateUrl: './update-location-attribute-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class UpdateLocationAttributeWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-multiple-attributes-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-multiple-attributes-key-settings.component.ts index d29decfc04..c007c51ef8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-multiple-attributes-key-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-multiple-attributes-key-settings.component.ts @@ -30,9 +30,10 @@ import { } from '@home/components/widget/lib/multiple-input-widget.component'; @Component({ - selector: 'tb-update-multiple-attributes-key-settings', - templateUrl: './update-multiple-attributes-key-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-update-multiple-attributes-key-settings', + templateUrl: './update-multiple-attributes-key-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class UpdateMultipleAttributesKeySettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-multiple-attributes-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-multiple-attributes-widget-settings.component.ts index 880bce24c8..5fbfad3486 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-multiple-attributes-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-multiple-attributes-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-update-multiple-attributes-widget-settings', - templateUrl: './update-multiple-attributes-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-update-multiple-attributes-widget-settings', + templateUrl: './update-multiple-attributes-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class UpdateMultipleAttributesWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-string-attribute-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-string-attribute-widget-settings.component.ts index ca134d8c73..0eb561a5f3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-string-attribute-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-string-attribute-widget-settings.component.ts @@ -25,9 +25,10 @@ import { } from '@home/components/widget/lib/settings/input/update-attribute-general-settings.component'; @Component({ - selector: 'tb-update-string-attribute-widget-settings', - templateUrl: './update-string-attribute-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-update-string-attribute-widget-settings', + templateUrl: './update-string-attribute-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class UpdateStringAttributeWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/circle-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/circle-settings.component.ts index 173901aa16..f229998584 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/circle-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/circle-settings.component.ts @@ -39,21 +39,22 @@ import { Widget } from '@shared/models/widget.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-circle-settings', - templateUrl: './circle-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => CircleSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => CircleSettingsComponent), - multi: true - } - ] + selector: 'tb-circle-settings', + templateUrl: './circle-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CircleSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => CircleSettingsComponent), + multi: true + } + ], + standalone: false }) export class CircleSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/common-map-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/common-map-settings.component.ts index 8c49152772..8702cf28f3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/common-map-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/common-map-settings.component.ts @@ -34,21 +34,22 @@ import { Widget } from '@shared/models/widget.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-common-map-settings', - templateUrl: './common-map-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => CommonMapSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => CommonMapSettingsComponent), - multi: true - } - ] + selector: 'tb-common-map-settings', + templateUrl: './common-map-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CommonMapSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => CommonMapSettingsComponent), + multi: true + } + ], + standalone: false }) export class CommonMapSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/datasources-key-autocomplete.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/datasources-key-autocomplete.component.ts index c0c1ef98d4..7f085e920f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/datasources-key-autocomplete.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/datasources-key-autocomplete.component.ts @@ -28,16 +28,17 @@ import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-datasources-key-autocomplete', - templateUrl: './datasources-key-autocomplete.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DatasourcesKeyAutocompleteComponent), - multi: true - } - ] + selector: 'tb-datasources-key-autocomplete', + templateUrl: './datasources-key-autocomplete.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DatasourcesKeyAutocompleteComponent), + multi: true + } + ], + standalone: false }) export class DatasourcesKeyAutocompleteComponent extends PageComponent implements OnInit, ControlValueAccessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/google-map-provider-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/google-map-provider-settings.component.ts index b9d54db5a6..673f7fc573 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/google-map-provider-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/google-map-provider-settings.component.ts @@ -37,21 +37,22 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-google-map-provider-settings', - templateUrl: './google-map-provider-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => GoogleMapProviderSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => GoogleMapProviderSettingsComponent), - multi: true - } - ] + selector: 'tb-google-map-provider-settings', + templateUrl: './google-map-provider-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => GoogleMapProviderSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => GoogleMapProviderSettingsComponent), + multi: true + } + ], + standalone: false }) export class GoogleMapProviderSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/here-map-provider-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/here-map-provider-settings.component.ts index e201586a63..40140fb1ff 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/here-map-provider-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/here-map-provider-settings.component.ts @@ -38,21 +38,22 @@ import { isDefinedAndNotNull } from '@core/utils'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-here-map-provider-settings', - templateUrl: './here-map-provider-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => HereMapProviderSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => HereMapProviderSettingsComponent), - multi: true - } - ] + selector: 'tb-here-map-provider-settings', + templateUrl: './here-map-provider-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => HereMapProviderSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => HereMapProviderSettingsComponent), + multi: true + } + ], + standalone: false }) export class HereMapProviderSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/image-map-provider-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/image-map-provider-settings.component.ts index a5493468a0..338db7c24f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/image-map-provider-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/image-map-provider-settings.component.ts @@ -38,21 +38,22 @@ import { EntityService } from '@core/http/entity.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-image-map-provider-settings', - templateUrl: './image-map-provider-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ImageMapProviderSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => ImageMapProviderSettingsComponent), - multi: true - } - ] + selector: 'tb-image-map-provider-settings', + templateUrl: './image-map-provider-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ImageMapProviderSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ImageMapProviderSettingsComponent), + multi: true + } + ], + standalone: false }) export class ImageMapProviderSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-editor-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-editor-settings.component.ts index 398376f71a..9d127af2d8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-editor-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-editor-settings.component.ts @@ -33,21 +33,22 @@ import { WidgetService } from '@core/http/widget.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-map-editor-settings', - templateUrl: './map-editor-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MapEditorSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MapEditorSettingsComponent), - multi: true - } - ] + selector: 'tb-map-editor-settings', + templateUrl: './map-editor-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MapEditorSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MapEditorSettingsComponent), + multi: true + } + ], + standalone: false }) export class MapEditorSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-provider-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-provider-settings.component.ts index 08b2a99e31..ea3b143db2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-provider-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-provider-settings.component.ts @@ -47,21 +47,22 @@ import { IAliasController } from '@core/api/widget-api.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-map-provider-settings', - templateUrl: './map-provider-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MapProviderSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MapProviderSettingsComponent), - multi: true - } - ] + selector: 'tb-map-provider-settings', + templateUrl: './map-provider-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MapProviderSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MapProviderSettingsComponent), + multi: true + } + ], + standalone: false }) export class MapProviderSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-settings-legacy.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-settings-legacy.component.ts index eb31c33075..5e98827469 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-settings-legacy.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-settings-legacy.component.ts @@ -53,21 +53,22 @@ import { Widget } from '@shared/models/widget.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-map-settings-legacy', - templateUrl: './map-settings-legacy.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MapSettingsLegacyComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MapSettingsLegacyComponent), - multi: true - } - ] + selector: 'tb-map-settings-legacy', + templateUrl: './map-settings-legacy.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MapSettingsLegacyComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MapSettingsLegacyComponent), + multi: true + } + ], + standalone: false }) export class MapSettingsLegacyComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-widget-settings-legacy.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-widget-settings-legacy.component.ts index 3262e6b1cb..4a804c8e78 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-widget-settings-legacy.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-widget-settings-legacy.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { defaultMapSettings } from 'src/app/modules/home/components/widget/lib/maps-legacy/map-models'; @Component({ - selector: 'tb-map-widget-settings-legacy', - templateUrl: './map-widget-settings-legacy.component.html', - styleUrls: ['./../../widget-settings.scss'] + selector: 'tb-map-widget-settings-legacy', + templateUrl: './map-widget-settings-legacy.component.html', + styleUrls: ['./../../widget-settings.scss'], + standalone: false }) export class MapWidgetSettingsLegacyComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/marker-clustering-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/marker-clustering-settings.component.ts index c757d7805a..6615302230 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/marker-clustering-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/marker-clustering-settings.component.ts @@ -34,21 +34,22 @@ import { WidgetService } from '@core/http/widget.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-marker-clustering-settings', - templateUrl: './marker-clustering-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MarkerClusteringSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MarkerClusteringSettingsComponent), - multi: true - } - ] + selector: 'tb-marker-clustering-settings', + templateUrl: './marker-clustering-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MarkerClusteringSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MarkerClusteringSettingsComponent), + multi: true + } + ], + standalone: false }) export class MarkerClusteringSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/markers-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/markers-settings.component.ts index d890494f54..65421d0f53 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/markers-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/markers-settings.component.ts @@ -36,21 +36,22 @@ import { WidgetService } from '@core/http/widget.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-markers-settings', - templateUrl: './markers-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MarkersSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MarkersSettingsComponent), - multi: true - } - ] + selector: 'tb-markers-settings', + templateUrl: './markers-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MarkersSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MarkersSettingsComponent), + multi: true + } + ], + standalone: false }) export class MarkersSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/openstreet-map-provider-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/openstreet-map-provider-settings.component.ts index ef650fc877..6a795edd84 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/openstreet-map-provider-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/openstreet-map-provider-settings.component.ts @@ -37,21 +37,22 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-openstreet-map-provider-settings', - templateUrl: './openstreet-map-provider-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => OpenStreetMapProviderSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => OpenStreetMapProviderSettingsComponent), - multi: true - } - ] + selector: 'tb-openstreet-map-provider-settings', + templateUrl: './openstreet-map-provider-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => OpenStreetMapProviderSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => OpenStreetMapProviderSettingsComponent), + multi: true + } + ], + standalone: false }) export class OpenStreetMapProviderSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/polygon-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/polygon-settings.component.ts index 129d268908..9b0b6e0110 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/polygon-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/polygon-settings.component.ts @@ -39,21 +39,22 @@ import { Widget } from '@shared/models/widget.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-polygon-settings', - templateUrl: './polygon-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => PolygonSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => PolygonSettingsComponent), - multi: true - } - ] + selector: 'tb-polygon-settings', + templateUrl: './polygon-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => PolygonSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => PolygonSettingsComponent), + multi: true + } + ], + standalone: false }) export class PolygonSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/route-map-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/route-map-settings.component.ts index 4a3cd9a3f8..cfba6811f2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/route-map-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/route-map-settings.component.ts @@ -33,21 +33,22 @@ import { WidgetService } from '@core/http/widget.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-route-map-settings', - templateUrl: './route-map-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => RouteMapSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => RouteMapSettingsComponent), - multi: true - } - ] + selector: 'tb-route-map-settings', + templateUrl: './route-map-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RouteMapSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => RouteMapSettingsComponent), + multi: true + } + ], + standalone: false }) export class RouteMapSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/route-map-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/route-map-widget-settings.component.ts index 23bf193892..67e88aa7b5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/route-map-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/route-map-widget-settings.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { defaultMapSettings } from 'src/app/modules/home/components/widget/lib/maps-legacy/map-models'; @Component({ - selector: 'tb-route-map-widget-settings', - templateUrl: './route-map-widget-settings.component.html', - styleUrls: ['./../../widget-settings.scss'] + selector: 'tb-route-map-widget-settings', + templateUrl: './route-map-widget-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + standalone: false }) export class RouteMapWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/tencent-map-provider-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/tencent-map-provider-settings.component.ts index d3f81a7ff3..4e6e8284d1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/tencent-map-provider-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/tencent-map-provider-settings.component.ts @@ -37,21 +37,22 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-tencent-map-provider-settings', - templateUrl: './tencent-map-provider-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TencentMapProviderSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => TencentMapProviderSettingsComponent), - multi: true - } - ] + selector: 'tb-tencent-map-provider-settings', + templateUrl: './tencent-map-provider-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TencentMapProviderSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => TencentMapProviderSettingsComponent), + multi: true + } + ], + standalone: false }) export class TencentMapProviderSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-common-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-common-settings.component.ts index 074cba4a5c..861188a6b9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-common-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-common-settings.component.ts @@ -35,21 +35,22 @@ import { WidgetService } from '@core/http/widget.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-trip-animation-common-settings', - templateUrl: './trip-animation-common-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TripAnimationCommonSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => TripAnimationCommonSettingsComponent), - multi: true - } - ] + selector: 'tb-trip-animation-common-settings', + templateUrl: './trip-animation-common-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TripAnimationCommonSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => TripAnimationCommonSettingsComponent), + multi: true + } + ], + standalone: false }) export class TripAnimationCommonSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-marker-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-marker-settings.component.ts index f7ecd02f03..8f31d24f2f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-marker-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-marker-settings.component.ts @@ -34,21 +34,22 @@ import { WidgetService } from '@core/http/widget.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-trip-animation-marker-settings', - templateUrl: './trip-animation-marker-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TripAnimationMarkerSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => TripAnimationMarkerSettingsComponent), - multi: true - } - ] + selector: 'tb-trip-animation-marker-settings', + templateUrl: './trip-animation-marker-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TripAnimationMarkerSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => TripAnimationMarkerSettingsComponent), + multi: true + } + ], + standalone: false }) export class TripAnimationMarkerSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-path-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-path-settings.component.ts index 16c75cee56..9674ac2820 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-path-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-path-settings.component.ts @@ -37,21 +37,22 @@ import { WidgetService } from '@core/http/widget.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-trip-animation-path-settings', - templateUrl: './trip-animation-path-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TripAnimationPathSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => TripAnimationPathSettingsComponent), - multi: true - } - ] + selector: 'tb-trip-animation-path-settings', + templateUrl: './trip-animation-path-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TripAnimationPathSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => TripAnimationPathSettingsComponent), + multi: true + } + ], + standalone: false }) export class TripAnimationPathSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-point-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-point-settings.component.ts index 5e372051ad..8aae459e18 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-point-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-point-settings.component.ts @@ -38,21 +38,22 @@ import { WidgetService } from '@core/http/widget.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-trip-animation-point-settings', - templateUrl: './trip-animation-point-settings.component.html', - styleUrls: ['./../../widget-settings.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TripAnimationPointSettingsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => TripAnimationPointSettingsComponent), - multi: true - } - ] + selector: 'tb-trip-animation-point-settings', + templateUrl: './trip-animation-point-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TripAnimationPointSettingsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => TripAnimationPointSettingsComponent), + multi: true + } + ], + standalone: false }) export class TripAnimationPointSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-widget-settings.component.ts index 440fd5df2c..5d4e28d7bb 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-widget-settings.component.ts @@ -39,9 +39,10 @@ import { import { extractType } from '@core/utils'; @Component({ - selector: 'tb-trip-animation-widget-settings', - templateUrl: './trip-animation-widget-settings.component.html', - styleUrls: ['./../../widget-settings.scss'] + selector: 'tb-trip-animation-widget-settings', + templateUrl: './trip-animation-widget-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + standalone: false }) export class TripAnimationWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-widget-settings.component.ts index 296086b22f..3963f144fa 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-widget-settings.component.ts @@ -24,9 +24,10 @@ import { mapWidgetDefaultSettings } from '@home/components/widget/lib/maps/map-w import { WidgetConfigComponentData } from '@home/models/widget-component.models'; @Component({ - selector: 'tb-map-widget-settings', - templateUrl: './map-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-map-widget-settings', + templateUrl: './map-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class MapWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/navigation/navigation-card-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/navigation/navigation-card-widget-settings.component.ts index 08ee515099..b3f6c2838f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/navigation/navigation-card-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/navigation/navigation-card-widget-settings.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-navigation-card-widget-settings', - templateUrl: './navigation-card-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-navigation-card-widget-settings', + templateUrl: './navigation-card-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class NavigationCardWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/navigation/navigation-cards-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/navigation/navigation-cards-widget-settings.component.ts index 3ffe4d6c22..fc17f555d4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/navigation/navigation-cards-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/navigation/navigation-cards-widget-settings.component.ts @@ -26,9 +26,10 @@ import { Observable, of, Subject } from 'rxjs'; import { map, mergeMap, share, startWith } from 'rxjs/operators'; @Component({ - selector: 'tb-navigation-cards-widget-settings', - templateUrl: './navigation-cards-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-navigation-cards-widget-settings', + templateUrl: './navigation-cards-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class NavigationCardsWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/scada/scada-symbol-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/scada/scada-symbol-widget-settings.component.ts index 361a305421..cc04e67f2f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/scada/scada-symbol-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/scada/scada-symbol-widget-settings.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { scadaSymbolWidgetDefaultSettings } from '@home/components/widget/lib/scada/scada-symbol-widget.models'; @Component({ - selector: 'tb-scada-symbol-widget-settings', - templateUrl: './scada-symbol-widget-settings.component.html', - styleUrls: ['./../widget-settings.scss'] + selector: 'tb-scada-symbol-widget-settings', + templateUrl: './scada-symbol-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + standalone: false }) export class ScadaSymbolWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.ts index 96ea317109..102dc7ade6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.ts @@ -31,9 +31,10 @@ import { getDataKey } from '@shared/models/widget-settings.models'; import { getSourceTbUnitSymbol, TbUnit } from '@shared/models/unit.models'; @Component({ - selector: 'tb-wind-speed-direction-widget-settings', - templateUrl: './wind-speed-direction-widget-settings.component.html', - styleUrls: [] + selector: 'tb-wind-speed-direction-widget-settings', + templateUrl: './wind-speed-direction-widget-settings.component.html', + styleUrls: [], + standalone: false }) export class WindSpeedDirectionWidgetSettingsComponent extends WidgetSettingsComponent { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/timeseries-table-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/timeseries-table-widget.component.ts index 9235453e93..a7fcfee6d3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/timeseries-table-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/timeseries-table-widget.component.ts @@ -155,9 +155,10 @@ interface TimeseriesTableSource { } @Component({ - selector: 'tb-timeseries-table-widget', - templateUrl: './timeseries-table-widget.component.html', - styleUrls: ['./timeseries-table-widget.component.scss', './table-widget.scss'] + selector: 'tb-timeseries-table-widget', + templateUrl: './timeseries-table-widget.component.html', + styleUrls: ['./timeseries-table-widget.component.scss', './table-widget.scss'], + standalone: false }) export class TimeseriesTableWidgetComponent extends PageComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/trip-animation/trip-animation.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/trip-animation/trip-animation.component.ts index b69456ee30..9a7ea52d17 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/trip-animation/trip-animation.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/trip-animation/trip-animation.component.ts @@ -59,10 +59,11 @@ interface DataMap { } @Component({ - // eslint-disable-next-line @angular-eslint/component-selector - selector: 'trip-animation', - templateUrl: './trip-animation.component.html', - styleUrls: ['./trip-animation.component.scss'] + // eslint-disable-next-line @angular-eslint/component-selector + selector: 'trip-animation', + templateUrl: './trip-animation.component.html', + styleUrls: ['./trip-animation.component.scss'], + standalone: false }) export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts index 1c3570ad0f..dbc7bf889d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts @@ -68,10 +68,11 @@ const ticksTextMap: {[angle: number]: string} = { }; @Component({ - selector: 'tb-wind-speed-direction-widget', - templateUrl: './wind-speed-direction-widget.component.html', - styleUrls: ['./wind-speed-direction-widget.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-wind-speed-direction-widget', + templateUrl: './wind-speed-direction-widget.component.html', + styleUrls: ['./wind-speed-direction-widget.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class WindSpeedDirectionWidgetComponent implements OnInit, OnDestroy, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts index e30ee2e93d..a8fa966bd7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts @@ -87,21 +87,22 @@ import { WidgetService } from '@core/http/widget.service'; import Timeout = NodeJS.Timeout; @Component({ - selector: 'tb-widget-config', - templateUrl: './widget-config.component.html', - styleUrls: ['./widget-config.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => WidgetConfigComponent), - multi: true - }, - { - provide: NG_ASYNC_VALIDATORS, - useExisting: forwardRef(() => WidgetConfigComponent), - multi: true, - } - ] + selector: 'tb-widget-config', + templateUrl: './widget-config.component.html', + styleUrls: ['./widget-config.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => WidgetConfigComponent), + multi: true + }, + { + provide: NG_ASYNC_VALIDATORS, + useExisting: forwardRef(() => WidgetConfigComponent), + multi: true, + } + ], + standalone: false }) export class WidgetConfigComponent extends PageComponent implements OnInit, OnDestroy, ControlValueAccessor, AsyncValidator { diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.ts index 3a60c46f02..1fedcbec13 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.ts @@ -67,11 +67,12 @@ export class WidgetComponentAction { // @dynamic @Component({ - selector: 'tb-widget-container', - templateUrl: './widget-container.component.html', - styleUrls: ['./widget-container.component.scss'], - encapsulation: ViewEncapsulation.None, - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-widget-container', + templateUrl: './widget-container.component.html', + styleUrls: ['./widget-container.component.scss'], + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: false }) export class WidgetContainerComponent extends PageComponent implements OnInit, OnChanges, AfterViewInit, OnDestroy { @@ -394,7 +395,7 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, O } @Component({ - template: ` + template: `
{{ 'widget.reference' | translate }} @@ -431,8 +432,9 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, O
`, - styles: [], - encapsulation: ViewEncapsulation.None + styles: [], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class EditWidgetActionsTooltipComponent implements AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-preview.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget-preview.component.ts index ea2770d0e5..d940696078 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-preview.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-preview.component.ts @@ -24,9 +24,10 @@ import { deepClone } from '@core/utils'; import { Timewindow } from '@shared/models/time/time.models'; @Component({ - selector: 'tb-widget-preview', - templateUrl: './widget-preview.component.html', - styleUrls: ['./widget-preview.component.scss'] + selector: 'tb-widget-preview', + templateUrl: './widget-preview.component.html', + styleUrls: ['./widget-preview.component.scss'], + standalone: false }) export class WidgetPreviewComponent extends PageComponent implements OnInit, OnChanges { diff --git a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts index 26421012d4..d3a7bb5b83 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts @@ -128,11 +128,12 @@ import { CompiledTbFunction, compileTbFunction, isNotEmptyTbFunction } from '@sh import { HttpClient } from '@angular/common/http'; @Component({ - selector: 'tb-widget', - templateUrl: './widget.component.html', - styleUrls: ['./widget.component.scss'], - encapsulation: ViewEncapsulation.None, - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-widget', + templateUrl: './widget.component.html', + styleUrls: ['./widget.component.scss'], + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: false }) export class WidgetComponent extends PageComponent implements OnInit, OnChanges, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.ts b/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.ts index 6c991d492a..c88be6b550 100644 --- a/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.ts @@ -35,9 +35,10 @@ import { CustomerId } from '@shared/models/id/customer-id'; import { HttpErrorResponse } from '@angular/common/http'; @Component({ - selector: 'tb-device-wizard', - templateUrl: './device-wizard-dialog.component.html', - styleUrls: ['./device-wizard-dialog.component.scss'] + selector: 'tb-device-wizard', + templateUrl: './device-wizard-dialog.component.html', + styleUrls: ['./device-wizard-dialog.component.scss'], + standalone: false }) export class DeviceWizardDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/dialogs/add-entities-to-customer-dialog.component.ts b/ui-ngx/src/app/modules/home/dialogs/add-entities-to-customer-dialog.component.ts index 31020d49a4..dd11ea16c8 100644 --- a/ui-ngx/src/app/modules/home/dialogs/add-entities-to-customer-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/dialogs/add-entities-to-customer-dialog.component.ts @@ -36,10 +36,11 @@ export interface AddEntitiesToCustomerDialogData { } @Component({ - selector: 'tb-add-entities-to-customer-dialog', - templateUrl: './add-entities-to-customer-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: AddEntitiesToCustomerDialogComponent}], - styleUrls: [] + selector: 'tb-add-entities-to-customer-dialog', + templateUrl: './add-entities-to-customer-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: AddEntitiesToCustomerDialogComponent }], + styleUrls: [], + standalone: false }) export class AddEntitiesToCustomerDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/dialogs/add-entities-to-edge-dialog.component.ts b/ui-ngx/src/app/modules/home/dialogs/add-entities-to-edge-dialog.component.ts index 18abe0c30e..e2c4568c8e 100644 --- a/ui-ngx/src/app/modules/home/dialogs/add-entities-to-edge-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/dialogs/add-entities-to-edge-dialog.component.ts @@ -38,10 +38,11 @@ export interface AddEntitiesToEdgeDialogData { } @Component({ - selector: 'tb-add-entities-to-edge-dialog', - templateUrl: './add-entities-to-edge-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: AddEntitiesToEdgeDialogComponent}], - styleUrls: [] + selector: 'tb-add-entities-to-edge-dialog', + templateUrl: './add-entities-to-edge-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: AddEntitiesToEdgeDialogComponent }], + styleUrls: [], + standalone: false }) export class AddEntitiesToEdgeDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/dialogs/assign-to-customer-dialog.component.ts b/ui-ngx/src/app/modules/home/dialogs/assign-to-customer-dialog.component.ts index 7bc7ad92a2..541312bf1a 100644 --- a/ui-ngx/src/app/modules/home/dialogs/assign-to-customer-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/dialogs/assign-to-customer-dialog.component.ts @@ -36,10 +36,11 @@ export interface AssignToCustomerDialogData { } @Component({ - selector: 'tb-assign-to-customer-dialog', - templateUrl: './assign-to-customer-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: AssignToCustomerDialogComponent}], - styleUrls: [] + selector: 'tb-assign-to-customer-dialog', + templateUrl: './assign-to-customer-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: AssignToCustomerDialogComponent }], + styleUrls: [], + standalone: false }) export class AssignToCustomerDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/home.component.ts b/ui-ngx/src/app/modules/home/home.component.ts index 25edc77b33..6191280933 100644 --- a/ui-ngx/src/app/modules/home/home.component.ts +++ b/ui-ngx/src/app/modules/home/home.component.ts @@ -36,9 +36,10 @@ import { ActivatedRoute } from '@angular/router'; import { isDefined, isDefinedAndNotNull } from '@core/utils'; @Component({ - selector: 'tb-home', - templateUrl: './home.component.html', - styleUrls: ['./home.component.scss'] + selector: 'tb-home', + templateUrl: './home.component.html', + styleUrls: ['./home.component.scss'], + standalone: false }) export class HomeComponent extends PageComponent implements AfterViewInit, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/menu/menu-link.component.ts b/ui-ngx/src/app/modules/home/menu/menu-link.component.ts index 20b8957b15..95abc6623b 100644 --- a/ui-ngx/src/app/modules/home/menu/menu-link.component.ts +++ b/ui-ngx/src/app/modules/home/menu/menu-link.component.ts @@ -18,10 +18,11 @@ import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core import { MenuSection } from '@core/services/menu.models'; @Component({ - selector: 'tb-menu-link', - templateUrl: './menu-link.component.html', - styleUrls: ['./menu-link.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-menu-link', + templateUrl: './menu-link.component.html', + styleUrls: ['./menu-link.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: false }) export class MenuLinkComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/menu/menu-toggle.component.ts b/ui-ngx/src/app/modules/home/menu/menu-toggle.component.ts index cd00627433..4415e9f580 100644 --- a/ui-ngx/src/app/modules/home/menu/menu-toggle.component.ts +++ b/ui-ngx/src/app/modules/home/menu/menu-toggle.component.ts @@ -22,10 +22,11 @@ import { AppState } from '@core/core.state'; import { ActionPreferencesUpdateOpenedMenuSection } from '@core/auth/auth.actions'; @Component({ - selector: 'tb-menu-toggle', - templateUrl: './menu-toggle.component.html', - styleUrls: ['./menu-toggle.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-menu-toggle', + templateUrl: './menu-toggle.component.html', + styleUrls: ['./menu-toggle.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: false }) export class MenuToggleComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/menu/side-menu.component.ts b/ui-ngx/src/app/modules/home/menu/side-menu.component.ts index 6194146781..f266cee1a8 100644 --- a/ui-ngx/src/app/modules/home/menu/side-menu.component.ts +++ b/ui-ngx/src/app/modules/home/menu/side-menu.component.ts @@ -19,10 +19,11 @@ import { MenuService } from '@core/services/menu.service'; import { MenuSection } from '@core/services/menu.models'; @Component({ - selector: 'tb-side-menu', - templateUrl: './side-menu.component.html', - styleUrls: ['./side-menu.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-side-menu', + templateUrl: './side-menu.component.html', + styleUrls: ['./side-menu.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: false }) export class SideMenuComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/admin/auto-commit-admin-settings.component.ts b/ui-ngx/src/app/modules/home/pages/admin/auto-commit-admin-settings.component.ts index 950f1606c2..94134bb100 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/auto-commit-admin-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/auto-commit-admin-settings.component.ts @@ -25,9 +25,10 @@ import { selectHasRepository } from '@core/auth/auth.selectors'; import { RepositorySettingsComponent } from '@home/components/vc/repository-settings.component'; @Component({ - selector: 'tb-auto-commit-admin-settings', - templateUrl: './auto-commit-admin-settings.component.html', - styleUrls: [] + selector: 'tb-auto-commit-admin-settings', + templateUrl: './auto-commit-admin-settings.component.html', + styleUrls: [], + standalone: false }) export class AutoCommitAdminSettingsComponent extends PageComponent implements OnInit, HasConfirmForm { diff --git a/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.ts b/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.ts index e4634370d3..72543b5e6b 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.ts @@ -31,9 +31,10 @@ import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ - selector: 'tb-general-settings', - templateUrl: './general-settings.component.html', - styleUrls: ['./general-settings.component.scss', './settings-card.scss'] + selector: 'tb-general-settings', + templateUrl: './general-settings.component.html', + styleUrls: ['./general-settings.component.scss', './settings-card.scss'], + standalone: false }) export class GeneralSettingsComponent extends PageComponent implements HasConfirmForm, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/admin/home-settings.component.ts b/ui-ngx/src/app/modules/home/pages/admin/home-settings.component.ts index a02d27f1bb..b518c4138d 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/home-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/home-settings.component.ts @@ -27,9 +27,10 @@ import { isDefinedAndNotNull } from '@core/utils'; import { DashboardId } from '@shared/models/id/dashboard-id'; @Component({ - selector: 'tb-home-settings', - templateUrl: './home-settings.component.html', - styleUrls: ['./home-settings.component.scss', './settings-card.scss'] + selector: 'tb-home-settings', + templateUrl: './home-settings.component.html', + styleUrls: ['./home-settings.component.scss', './settings-card.scss'], + standalone: false }) export class HomeSettingsComponent extends PageComponent implements OnInit, HasConfirmForm { diff --git a/ui-ngx/src/app/modules/home/pages/admin/mail-server.component.ts b/ui-ngx/src/app/modules/home/pages/admin/mail-server.component.ts index c5126d5d10..bc226933b4 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/mail-server.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/mail-server.component.ts @@ -38,9 +38,10 @@ import { DomainSchema, domainSchemaTranslations, } from '@shared/models/oauth2.m import { WINDOW } from '@core/services/window.service'; @Component({ - selector: 'tb-mail-server', - templateUrl: './mail-server.component.html', - styleUrls: ['./mail-server.component.scss', './settings-card.scss'] + selector: 'tb-mail-server', + templateUrl: './mail-server.component.html', + styleUrls: ['./mail-server.component.scss', './settings-card.scss'], + standalone: false }) export class MailServerComponent extends PageComponent implements OnInit, OnDestroy, HasConfirmForm { adminSettings: AdminSettings; diff --git a/ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/client-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/client-dialog.component.ts index 26cbc1002d..ef2c44e8de 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/client-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/client-dialog.component.ts @@ -27,10 +27,11 @@ import { ClientComponent } from '@home/pages/admin/oauth2/clients/client.compone import { ErrorStateMatcher } from '@angular/material/core'; @Component({ - selector: 'tb-client-dialog', - templateUrl: './client-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: ClientDialogComponent}], - styleUrls: [] + selector: 'tb-client-dialog', + templateUrl: './client-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: ClientDialogComponent }], + styleUrls: [], + standalone: false }) export class ClientDialogComponent extends DialogComponent implements OnDestroy, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/client-table-header.component.ts b/ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/client-table-header.component.ts index 3ec2eed2f0..b0d28a8a1e 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/client-table-header.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/client-table-header.component.ts @@ -22,9 +22,10 @@ import { OAuth2Client, OAuth2ClientInfo } from '@shared/models/oauth2.models'; import { PageLink } from '@shared/models/page/page-link'; @Component({ - selector: 'tb-client-table-header', - templateUrl: './client-table-header.component.html', - styleUrls: [] + selector: 'tb-client-table-header', + templateUrl: './client-table-header.component.html', + styleUrls: [], + standalone: false }) export class ClientTableHeaderComponent extends EntityTableHeaderComponent { diff --git a/ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/client.component.ts b/ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/client.component.ts index 7298f339f2..151b56df6c 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/client.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/client.component.ts @@ -44,9 +44,10 @@ import { getCurrentAuthUser } from '@core/auth/auth.selectors'; import { Authority } from '@shared/models/authority.enum'; @Component({ - selector: 'tb-client', - templateUrl: './client.component.html', - styleUrls: ['./client.component.scss'] + selector: 'tb-client', + templateUrl: './client.component.html', + styleUrls: ['./client.component.scss'], + standalone: false }) export class ClientComponent extends EntityComponent implements OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/admin/oauth2/domains/domain-table-header.component.ts b/ui-ngx/src/app/modules/home/pages/admin/oauth2/domains/domain-table-header.component.ts index 91e18ec8b3..ff94740791 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/oauth2/domains/domain-table-header.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/oauth2/domains/domain-table-header.component.ts @@ -21,9 +21,10 @@ import { AppState } from '@core/core.state'; import { DomainInfo } from '@shared/models/oauth2.models'; @Component({ - selector: 'tb-domain-table-header', - templateUrl: './domain-table-header.component.html', - styleUrls: [] + selector: 'tb-domain-table-header', + templateUrl: './domain-table-header.component.html', + styleUrls: [], + standalone: false }) export class DomainTableHeaderComponent extends EntityTableHeaderComponent { diff --git a/ui-ngx/src/app/modules/home/pages/admin/oauth2/domains/domain.component.ts b/ui-ngx/src/app/modules/home/pages/admin/oauth2/domains/domain.component.ts index ffa4934480..f01c14b19f 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/oauth2/domains/domain.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/oauth2/domains/domain.component.ts @@ -31,9 +31,10 @@ import { ClientDialogComponent } from '@home/pages/admin/oauth2/clients/client-d import { EntityType } from '@shared/models/entity-type.models'; @Component({ - selector: 'tb-domain', - templateUrl: './domain.component.html', - styleUrls: [] + selector: 'tb-domain', + templateUrl: './domain.component.html', + styleUrls: [], + standalone: false }) export class DomainComponent extends EntityComponent { diff --git a/ui-ngx/src/app/modules/home/pages/admin/queue/queue.component.ts b/ui-ngx/src/app/modules/home/pages/admin/queue/queue.component.ts index 371fab4a69..082243c6ac 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/queue/queue.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/queue/queue.component.ts @@ -26,9 +26,10 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.mod import { ActionNotificationShow } from '@core/notification/notification.actions'; @Component({ - selector: 'tb-queue', - templateUrl: './queue.component.html', - styleUrls: [] + selector: 'tb-queue', + templateUrl: './queue.component.html', + styleUrls: [], + standalone: false }) export class QueueComponent extends EntityComponent { entityForm: UntypedFormGroup; diff --git a/ui-ngx/src/app/modules/home/pages/admin/repository-admin-settings.component.ts b/ui-ngx/src/app/modules/home/pages/admin/repository-admin-settings.component.ts index 46927f4671..4390484467 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/repository-admin-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/repository-admin-settings.component.ts @@ -23,9 +23,10 @@ import { UntypedFormGroup } from '@angular/forms'; import { RepositorySettingsComponent } from '@home/components/vc/repository-settings.component'; @Component({ - selector: 'tb-repository-admin-settings', - templateUrl: './repository-admin-settings.component.html', - styleUrls: [] + selector: 'tb-repository-admin-settings', + templateUrl: './repository-admin-settings.component.html', + styleUrls: [], + standalone: false }) export class RepositoryAdminSettingsComponent extends PageComponent implements OnInit, HasConfirmForm { diff --git a/ui-ngx/src/app/modules/home/pages/admin/resource/js-library-table-header.component.ts b/ui-ngx/src/app/modules/home/pages/admin/resource/js-library-table-header.component.ts index 814ae7cf34..83d6248c92 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/resource/js-library-table-header.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/resource/js-library-table-header.component.ts @@ -22,9 +22,10 @@ import { Resource, ResourceInfo, ResourceSubType, ResourceSubTypeTranslationMap import { PageLink } from '@shared/models/page/page-link'; @Component({ - selector: 'tb-js-library-table-header', - templateUrl: './js-library-table-header.component.html', - styleUrls: [] + selector: 'tb-js-library-table-header', + templateUrl: './js-library-table-header.component.html', + styleUrls: [], + standalone: false }) export class JsLibraryTableHeaderComponent extends EntityTableHeaderComponent { diff --git a/ui-ngx/src/app/modules/home/pages/admin/resource/js-resource.component.ts b/ui-ngx/src/app/modules/home/pages/admin/resource/js-resource.component.ts index 06e6381595..bc25e87dab 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/resource/js-resource.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/resource/js-resource.component.ts @@ -36,8 +36,9 @@ import { base64toString, isDefinedAndNotNull, stringToBase64 } from '@core/utils import { getCurrentAuthState } from '@core/auth/auth.selectors'; @Component({ - selector: 'tb-js-resource', - templateUrl: './js-resource.component.html' + selector: 'tb-js-resource', + templateUrl: './js-resource.component.html', + standalone: false }) export class JsResourceComponent extends EntityComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/admin/resource/resource-library-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/admin/resource/resource-library-tabs.component.ts index 22599d7d73..4ed898bcc2 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/resource/resource-library-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/resource/resource-library-tabs.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { NULL_UUID } from '@shared/models/id/has-uuid'; @Component({ - selector: 'tb-resource-library-tabs', - templateUrl: './resource-library-tabs.component.html', - styleUrls: [] + selector: 'tb-resource-library-tabs', + templateUrl: './resource-library-tabs.component.html', + styleUrls: [], + standalone: false }) export class ResourceLibraryTabsComponent extends EntityTabsComponent { diff --git a/ui-ngx/src/app/modules/home/pages/admin/resource/resource-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/admin/resource/resource-tabs.component.ts index bd831acdc6..ff12763bfc 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/resource/resource-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/resource/resource-tabs.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { NULL_UUID } from '@shared/models/id/has-uuid'; @Component({ - selector: 'tb-resource-tabs', - templateUrl: './resource-tabs.component.html', - styleUrls: [] + selector: 'tb-resource-tabs', + templateUrl: './resource-tabs.component.html', + styleUrls: [], + standalone: false }) export class ResourceTabsComponent extends EntityTabsComponent { diff --git a/ui-ngx/src/app/modules/home/pages/admin/resource/resources-table-header.component.ts b/ui-ngx/src/app/modules/home/pages/admin/resource/resources-table-header.component.ts index 8b7ff4babc..33ed389a29 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/resource/resources-table-header.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/resource/resources-table-header.component.ts @@ -22,9 +22,10 @@ import { Resource, ResourceInfo, ResourceType, ResourceTypeTranslationMap } from import { PageLink } from '@shared/models/page/page-link'; @Component({ - selector: 'tb-resources-table-header', - templateUrl: './resources-table-header.component.html', - styleUrls: [] + selector: 'tb-resources-table-header', + templateUrl: './resources-table-header.component.html', + styleUrls: [], + standalone: false }) export class ResourcesTableHeaderComponent extends EntityTableHeaderComponent { diff --git a/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.ts b/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.ts index 74c28f05ad..12375a68ac 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.ts @@ -40,9 +40,10 @@ import { Observable, of } from 'rxjs'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-security-settings', - templateUrl: './security-settings.component.html', - styleUrls: ['./security-settings.component.scss', './settings-card.scss'] + selector: 'tb-security-settings', + templateUrl: './security-settings.component.html', + styleUrls: ['./security-settings.component.scss', './settings-card.scss'], + standalone: false }) export class SecuritySettingsComponent extends PageComponent implements HasConfirmForm { diff --git a/ui-ngx/src/app/modules/home/pages/admin/send-test-sms-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/admin/send-test-sms-dialog.component.ts index 73687aabb3..f13dd74daa 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/send-test-sms-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/send-test-sms-dialog.component.ts @@ -31,9 +31,10 @@ export interface SendTestSmsDialogData { } @Component({ - selector: 'tb-send-test-sms-dialog', - templateUrl: './send-test-sms-dialog.component.html', - styleUrls: [] + selector: 'tb-send-test-sms-dialog', + templateUrl: './send-test-sms-dialog.component.html', + styleUrls: [], + standalone: false }) export class SendTestSmsDialogComponent extends DialogComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/admin/sms-provider.component.ts b/ui-ngx/src/app/modules/home/pages/admin/sms-provider.component.ts index fa8bca245e..ed259cecee 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/sms-provider.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/sms-provider.component.ts @@ -33,9 +33,10 @@ import { AuthUser } from '@shared/models/user.model'; import { getCurrentAuthUser } from '@core/auth/auth.selectors'; @Component({ - selector: 'tb-sms-provider', - templateUrl: './sms-provider.component.html', - styleUrls: ['./sms-provider.component.scss', './settings-card.scss'] + selector: 'tb-sms-provider', + templateUrl: './sms-provider.component.html', + styleUrls: ['./sms-provider.component.scss', './settings-card.scss'], + standalone: false }) export class SmsProviderComponent extends PageComponent implements HasConfirmForm { diff --git a/ui-ngx/src/app/modules/home/pages/admin/trendz-settings.component.ts b/ui-ngx/src/app/modules/home/pages/admin/trendz-settings.component.ts index 8b9d73c73f..44b5dd3b6e 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/trendz-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/trendz-settings.component.ts @@ -26,9 +26,10 @@ import { AppState } from "@core/core.state"; import { ActionAuthUpdateTrendzSettings } from "@core/auth/auth.actions"; @Component({ - selector: 'tb-trendz-settings', - templateUrl: './trendz-settings.component.html', - styleUrls: ['./trendz-settings.component.scss', './settings-card.scss'] + selector: 'tb-trendz-settings', + templateUrl: './trendz-settings.component.html', + styleUrls: ['./trendz-settings.component.scss', './settings-card.scss'], + standalone: false }) export class TrendzSettingsComponent extends PageComponent implements OnInit, HasConfirmForm { diff --git a/ui-ngx/src/app/modules/home/pages/admin/two-factor-auth-settings.component.ts b/ui-ngx/src/app/modules/home/pages/admin/two-factor-auth-settings.component.ts index 3d8cc5efde..a70996291d 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/two-factor-auth-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/two-factor-auth-settings.component.ts @@ -34,9 +34,10 @@ import { takeUntil } from 'rxjs/operators'; import { MatExpansionPanel } from '@angular/material/expansion'; @Component({ - selector: 'tb-2fa-settings', - templateUrl: './two-factor-auth-settings.component.html', - styleUrls: [ './settings-card.scss', './two-factor-auth-settings.component.scss'] + selector: 'tb-2fa-settings', + templateUrl: './two-factor-auth-settings.component.html', + styleUrls: ['./settings-card.scss', './two-factor-auth-settings.component.scss'], + standalone: false }) export class TwoFactorAuthSettingsComponent extends PageComponent implements OnInit, HasConfirmForm, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/ai-model/ai-model-table-header.component.ts b/ui-ngx/src/app/modules/home/pages/ai-model/ai-model-table-header.component.ts index f416e75033..fb9d1e814e 100644 --- a/ui-ngx/src/app/modules/home/pages/ai-model/ai-model-table-header.component.ts +++ b/ui-ngx/src/app/modules/home/pages/ai-model/ai-model-table-header.component.ts @@ -21,14 +21,15 @@ import { AppState } from '@core/core.state'; import { AiModel } from '@shared/models/ai-model.models'; @Component({ - selector: 'tb-ai-model-table-header', - templateUrl: './ai-model-table-header.component.html', - styles: [` + selector: 'tb-ai-model-table-header', + templateUrl: './ai-model-table-header.component.html', + styles: [` :host { width: 100%; } `], - styleUrls: [] + styleUrls: [], + standalone: false }) export class AiModelTableHeaderComponent extends EntityTableHeaderComponent { diff --git a/ui-ngx/src/app/modules/home/pages/asset-profile/asset-profile-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/asset-profile/asset-profile-tabs.component.ts index 836e46d2fe..a7ce0082cd 100644 --- a/ui-ngx/src/app/modules/home/pages/asset-profile/asset-profile-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/asset-profile/asset-profile-tabs.component.ts @@ -21,9 +21,10 @@ import { EntityTabsComponent } from '../../components/entity/entity-tabs.compone import { AssetProfile } from '@shared/models/asset.models'; @Component({ - selector: 'tb-asset-profile-tabs', - templateUrl: './asset-profile-tabs.component.html', - styleUrls: [] + selector: 'tb-asset-profile-tabs', + templateUrl: './asset-profile-tabs.component.html', + styleUrls: [], + standalone: false }) export class AssetProfileTabsComponent extends EntityTabsComponent { diff --git a/ui-ngx/src/app/modules/home/pages/asset/asset-table-header.component.ts b/ui-ngx/src/app/modules/home/pages/asset/asset-table-header.component.ts index 8be127163e..d65362733e 100644 --- a/ui-ngx/src/app/modules/home/pages/asset/asset-table-header.component.ts +++ b/ui-ngx/src/app/modules/home/pages/asset/asset-table-header.component.ts @@ -23,9 +23,10 @@ import { AssetInfo } from '@shared/models/asset.models'; import { AssetProfileId } from '@shared/models/id/asset-profile-id'; @Component({ - selector: 'tb-asset-table-header', - templateUrl: './asset-table-header.component.html', - styleUrls: [] + selector: 'tb-asset-table-header', + templateUrl: './asset-table-header.component.html', + styleUrls: [], + standalone: false }) export class AssetTableHeaderComponent extends EntityTableHeaderComponent { diff --git a/ui-ngx/src/app/modules/home/pages/asset/asset-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/asset/asset-tabs.component.ts index 47509bf309..10ef434755 100644 --- a/ui-ngx/src/app/modules/home/pages/asset/asset-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/asset/asset-tabs.component.ts @@ -21,9 +21,10 @@ import { EntityTabsComponent } from '../../components/entity/entity-tabs.compone import { AssetInfo } from '@app/shared/models/asset.models'; @Component({ - selector: 'tb-asset-tabs', - templateUrl: './asset-tabs.component.html', - styleUrls: [] + selector: 'tb-asset-tabs', + templateUrl: './asset-tabs.component.html', + styleUrls: [], + standalone: false }) export class AssetTabsComponent extends EntityTabsComponent { diff --git a/ui-ngx/src/app/modules/home/pages/asset/asset.component.ts b/ui-ngx/src/app/modules/home/pages/asset/asset.component.ts index bd6d94b1e0..4f8e3b7c63 100644 --- a/ui-ngx/src/app/modules/home/pages/asset/asset.component.ts +++ b/ui-ngx/src/app/modules/home/pages/asset/asset.component.ts @@ -27,9 +27,10 @@ import { AssetInfo } from '@app/shared/models/asset.models'; import { EntityTableConfig } from '@home/models/entity/entities-table-config.models'; @Component({ - selector: 'tb-asset', - templateUrl: './asset.component.html', - styleUrls: ['./asset.component.scss'] + selector: 'tb-asset', + templateUrl: './asset.component.html', + styleUrls: ['./asset.component.scss'], + standalone: false }) export class AssetComponent extends EntityComponent { diff --git a/ui-ngx/src/app/modules/home/pages/customer/customer-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/customer/customer-tabs.component.ts index 13afac05ac..0bf2f691a0 100644 --- a/ui-ngx/src/app/modules/home/pages/customer/customer-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/customer/customer-tabs.component.ts @@ -21,9 +21,10 @@ import { EntityTabsComponent } from '../../components/entity/entity-tabs.compone import { Customer } from '@shared/models/customer.model'; @Component({ - selector: 'tb-customer-tabs', - templateUrl: './customer-tabs.component.html', - styleUrls: [] + selector: 'tb-customer-tabs', + templateUrl: './customer-tabs.component.html', + styleUrls: [], + standalone: false }) export class CustomerTabsComponent extends EntityTabsComponent { diff --git a/ui-ngx/src/app/modules/home/pages/customer/customer.component.ts b/ui-ngx/src/app/modules/home/pages/customer/customer.component.ts index 6a90ac0b03..0eb5681cc2 100644 --- a/ui-ngx/src/app/modules/home/pages/customer/customer.component.ts +++ b/ui-ngx/src/app/modules/home/pages/customer/customer.component.ts @@ -29,9 +29,10 @@ import { AuthState } from '@core/auth/auth.models'; import { CountryData } from '@shared/models/country.models'; @Component({ - selector: 'tb-customer', - templateUrl: './customer.component.html', - styleUrls: ['./customer.component.scss'] + selector: 'tb-customer', + templateUrl: './customer.component.html', + styleUrls: ['./customer.component.scss'], + standalone: false }) export class CustomerComponent extends ContactBasedComponent { diff --git a/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-form.component.ts b/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-form.component.ts index fffcce8380..c3eb9f1b00 100644 --- a/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-form.component.ts +++ b/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-form.component.ts @@ -33,9 +33,10 @@ import { isEqual } from '@core/utils'; import { EntityType } from '@shared/models/entity-type.models'; @Component({ - selector: 'tb-dashboard-form', - templateUrl: './dashboard-form.component.html', - styleUrls: ['./dashboard-form.component.scss'] + selector: 'tb-dashboard-form', + templateUrl: './dashboard-form.component.html', + styleUrls: ['./dashboard-form.component.scss'], + standalone: false }) export class DashboardFormComponent extends EntityComponent { diff --git a/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-tabs.component.ts index 88610d212c..52e4c180a8 100644 --- a/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-tabs.component.ts @@ -21,9 +21,10 @@ import { EntityTabsComponent } from '../../components/entity/entity-tabs.compone import { Dashboard } from '@shared/models/dashboard.models'; @Component({ - selector: 'tb-dashboard-tabs', - templateUrl: './dashboard-tabs.component.html', - styleUrls: [] + selector: 'tb-dashboard-tabs', + templateUrl: './dashboard-tabs.component.html', + styleUrls: [], + standalone: false }) export class DashboardTabsComponent extends EntityTabsComponent { diff --git a/ui-ngx/src/app/modules/home/pages/dashboard/make-dashboard-public-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/dashboard/make-dashboard-public-dialog.component.ts index 0af06fd787..ede15ab957 100644 --- a/ui-ngx/src/app/modules/home/pages/dashboard/make-dashboard-public-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/dashboard/make-dashboard-public-dialog.component.ts @@ -31,9 +31,10 @@ export interface MakeDashboardPublicDialogData { } @Component({ - selector: 'tb-make-dashboard-public-dialog', - templateUrl: './make-dashboard-public-dialog.component.html', - styleUrls: [] + selector: 'tb-make-dashboard-public-dialog', + templateUrl: './make-dashboard-public-dialog.component.html', + styleUrls: [], + standalone: false }) export class MakeDashboardPublicDialogComponent extends DialogComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/dashboard/manage-dashboard-customers-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/dashboard/manage-dashboard-customers-dialog.component.ts index eb25e7cba1..ab1da02eef 100644 --- a/ui-ngx/src/app/modules/home/pages/dashboard/manage-dashboard-customers-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/dashboard/manage-dashboard-customers-dialog.component.ts @@ -35,10 +35,11 @@ export interface ManageDashboardCustomersDialogData { } @Component({ - selector: 'tb-manage-dashboard-customers-dialog', - templateUrl: './manage-dashboard-customers-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: ManageDashboardCustomersDialogComponent}], - styleUrls: [] + selector: 'tb-manage-dashboard-customers-dialog', + templateUrl: './manage-dashboard-customers-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: ManageDashboardCustomersDialogComponent }], + styleUrls: [], + standalone: false }) export class ManageDashboardCustomersDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts index e7984ee009..1a762ac881 100644 --- a/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts @@ -27,9 +27,10 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-device-profile-tabs', - templateUrl: './device-profile-tabs.component.html', - styleUrls: [] + selector: 'tb-device-profile-tabs', + templateUrl: './device-profile-tabs.component.html', + styleUrls: [], + standalone: false }) export class DeviceProfileTabsComponent extends EntityTabsComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/device/data/coap-device-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/pages/device/data/coap-device-transport-configuration.component.ts index 0dce317071..15c5a7eaa6 100644 --- a/ui-ngx/src/app/modules/home/pages/device/data/coap-device-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device/data/coap-device-transport-configuration.component.ts @@ -29,14 +29,15 @@ import { takeUntil } from 'rxjs/operators'; import { isDefinedAndNotNull } from '@core/utils'; @Component({ - selector: 'tb-coap-device-transport-configuration', - templateUrl: './coap-device-transport-configuration.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => CoapDeviceTransportConfigurationComponent), - multi: true - }] + selector: 'tb-coap-device-transport-configuration', + templateUrl: './coap-device-transport-configuration.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CoapDeviceTransportConfigurationComponent), + multi: true + }], + standalone: false }) export class CoapDeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/device/data/default-device-configuration.component.ts b/ui-ngx/src/app/modules/home/pages/device/data/default-device-configuration.component.ts index 4e4c4b51a1..ff39e03bb0 100644 --- a/ui-ngx/src/app/modules/home/pages/device/data/default-device-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device/data/default-device-configuration.component.ts @@ -27,14 +27,15 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-default-device-configuration', - templateUrl: './default-device-configuration.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DefaultDeviceConfigurationComponent), - multi: true - }] + selector: 'tb-default-device-configuration', + templateUrl: './default-device-configuration.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DefaultDeviceConfigurationComponent), + multi: true + }], + standalone: false }) export class DefaultDeviceConfigurationComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/device/data/default-device-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/pages/device/data/default-device-transport-configuration.component.ts index 1e196210fc..fe6238ab90 100644 --- a/ui-ngx/src/app/modules/home/pages/device/data/default-device-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device/data/default-device-transport-configuration.component.ts @@ -27,14 +27,15 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-default-device-transport-configuration', - templateUrl: './default-device-transport-configuration.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DefaultDeviceTransportConfigurationComponent), - multi: true - }] + selector: 'tb-default-device-transport-configuration', + templateUrl: './default-device-transport-configuration.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DefaultDeviceTransportConfigurationComponent), + multi: true + }], + standalone: false }) export class DefaultDeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/device/data/device-configuration.component.ts b/ui-ngx/src/app/modules/home/pages/device/data/device-configuration.component.ts index 54432ccf11..aab6c76339 100644 --- a/ui-ngx/src/app/modules/home/pages/device/data/device-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device/data/device-configuration.component.ts @@ -24,14 +24,15 @@ import { deepClone } from '@core/utils'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-device-configuration', - templateUrl: './device-configuration.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DeviceConfigurationComponent), - multi: true - }] + selector: 'tb-device-configuration', + templateUrl: './device-configuration.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceConfigurationComponent), + multi: true + }], + standalone: false }) export class DeviceConfigurationComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/device/data/device-data.component.ts b/ui-ngx/src/app/modules/home/pages/device/data/device-data.component.ts index 9acf174e4b..c6f03a84f1 100644 --- a/ui-ngx/src/app/modules/home/pages/device/data/device-data.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device/data/device-data.component.ts @@ -36,21 +36,22 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-device-data', - templateUrl: './device-data.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DeviceDataComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DeviceDataComponent), - multi: true - }, - ] + selector: 'tb-device-data', + templateUrl: './device-data.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceDataComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DeviceDataComponent), + multi: true + }, + ], + standalone: false }) export class DeviceDataComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/pages/device/data/device-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/pages/device/data/device-transport-configuration.component.ts index ccc7f20c5e..96456ebe14 100644 --- a/ui-ngx/src/app/modules/home/pages/device/data/device-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device/data/device-transport-configuration.component.ts @@ -33,20 +33,22 @@ import { deepClone } from '@core/utils'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-device-transport-configuration', - templateUrl: './device-transport-configuration.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => DeviceTransportConfigurationComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DeviceTransportConfigurationComponent), - multi: true - }] + selector: 'tb-device-transport-configuration', + templateUrl: './device-transport-configuration.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceTransportConfigurationComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DeviceTransportConfigurationComponent), + multi: true + } + ], + standalone: false }) export class DeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/pages/device/data/lwm2m-device-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/pages/device/data/lwm2m-device-transport-configuration.component.ts index 930b62b9f8..aa11e891d8 100644 --- a/ui-ngx/src/app/modules/home/pages/device/data/lwm2m-device-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device/data/lwm2m-device-transport-configuration.component.ts @@ -29,14 +29,15 @@ import { Subject } from 'rxjs'; import { isDefinedAndNotNull } from '@core/utils'; @Component({ - selector: 'tb-lwm2m-device-transport-configuration', - templateUrl: './lwm2m-device-transport-configuration.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Lwm2mDeviceTransportConfigurationComponent), - multi: true - }] + selector: 'tb-lwm2m-device-transport-configuration', + templateUrl: './lwm2m-device-transport-configuration.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Lwm2mDeviceTransportConfigurationComponent), + multi: true + }], + standalone: false }) export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/device/data/mqtt-device-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/pages/device/data/mqtt-device-transport-configuration.component.ts index f409713ed3..414fe213bc 100644 --- a/ui-ngx/src/app/modules/home/pages/device/data/mqtt-device-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device/data/mqtt-device-transport-configuration.component.ts @@ -26,14 +26,15 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-mqtt-device-transport-configuration', - templateUrl: './mqtt-device-transport-configuration.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MqttDeviceTransportConfigurationComponent), - multi: true - }] + selector: 'tb-mqtt-device-transport-configuration', + templateUrl: './mqtt-device-transport-configuration.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MqttDeviceTransportConfigurationComponent), + multi: true + }], + standalone: false }) export class MqttDeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/device/data/snmp-device-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/pages/device/data/snmp-device-transport-configuration.component.ts index 1c87b0d95d..c27b4eed9f 100644 --- a/ui-ngx/src/app/modules/home/pages/device/data/snmp-device-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device/data/snmp-device-transport-configuration.component.ts @@ -42,19 +42,21 @@ import { isDefinedAndNotNull } from '@core/utils'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-snmp-device-transport-configuration', - templateUrl: './snmp-device-transport-configuration.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => SnmpDeviceTransportConfigurationComponent), - multi: true - }, { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => SnmpDeviceTransportConfigurationComponent), - multi: true - }] + selector: 'tb-snmp-device-transport-configuration', + templateUrl: './snmp-device-transport-configuration.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => SnmpDeviceTransportConfigurationComponent), + multi: true + }, { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => SnmpDeviceTransportConfigurationComponent), + multi: true + } + ], + standalone: false }) export class SnmpDeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/pages/device/device-check-connectivity-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/device/device-check-connectivity-dialog.component.ts index 77bd019133..2385d1a933 100644 --- a/ui-ngx/src/app/modules/home/pages/device/device-check-connectivity-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device/device-check-connectivity-dialog.component.ts @@ -50,9 +50,10 @@ export interface DeviceCheckConnectivityDialogData { } @Component({ - selector: 'tb-device-check-connectivity-dialog', - templateUrl: './device-check-connectivity-dialog.component.html', - styleUrls: ['./device-check-connectivity-dialog.component.scss'] + selector: 'tb-device-check-connectivity-dialog', + templateUrl: './device-check-connectivity-dialog.component.html', + styleUrls: ['./device-check-connectivity-dialog.component.scss'], + standalone: false }) export class DeviceCheckConnectivityDialogComponent extends DialogComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.ts index 470604499c..4eda9c96d8 100644 --- a/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.ts @@ -36,10 +36,11 @@ export interface DeviceCredentialsDialogData { } @Component({ - selector: 'tb-device-credentials-dialog', - templateUrl: './device-credentials-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: DeviceCredentialsDialogComponent}], - styleUrls: ['./device-credentials-dialog.component.scss'] + selector: 'tb-device-credentials-dialog', + templateUrl: './device-credentials-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: DeviceCredentialsDialogComponent }], + styleUrls: ['./device-credentials-dialog.component.scss'], + standalone: false }) export class DeviceCredentialsDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/pages/device/device-table-header.component.ts b/ui-ngx/src/app/modules/home/pages/device/device-table-header.component.ts index a51d21f9b2..d65f21d312 100644 --- a/ui-ngx/src/app/modules/home/pages/device/device-table-header.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device/device-table-header.component.ts @@ -23,9 +23,10 @@ import { EntityType } from '@shared/models/entity-type.models'; import { DeviceProfileId } from '../../../../shared/models/id/device-profile-id'; @Component({ - selector: 'tb-device-table-header', - templateUrl: './device-table-header.component.html', - styleUrls: [] + selector: 'tb-device-table-header', + templateUrl: './device-table-header.component.html', + styleUrls: [], + standalone: false }) export class DeviceTableHeaderComponent extends EntityTableHeaderComponent { diff --git a/ui-ngx/src/app/modules/home/pages/device/device-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/device/device-tabs.component.ts index 8416be4d96..d1729e5fb4 100644 --- a/ui-ngx/src/app/modules/home/pages/device/device-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device/device-tabs.component.ts @@ -21,9 +21,10 @@ import { DeviceInfo } from '@shared/models/device.models'; import { EntityTabsComponent } from '../../components/entity/entity-tabs.component'; @Component({ - selector: 'tb-device-tabs', - templateUrl: './device-tabs.component.html', - styleUrls: [] + selector: 'tb-device-tabs', + templateUrl: './device-tabs.component.html', + styleUrls: [], + standalone: false }) export class DeviceTabsComponent extends EntityTabsComponent { diff --git a/ui-ngx/src/app/modules/home/pages/device/device.component.ts b/ui-ngx/src/app/modules/home/pages/device/device.component.ts index c5e798c0ff..de4ec0ae27 100644 --- a/ui-ngx/src/app/modules/home/pages/device/device.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device/device.component.ts @@ -39,9 +39,10 @@ import { distinctUntilChanged } from 'rxjs/operators'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-device', - templateUrl: './device.component.html', - styleUrls: ['./device.component.scss'] + selector: 'tb-device', + templateUrl: './device.component.html', + styleUrls: ['./device.component.scss'], + standalone: false }) export class DeviceComponent extends EntityComponent { diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge-instructions-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/edge/edge-instructions-dialog.component.ts index 41ed81b1f4..f907f11238 100644 --- a/ui-ngx/src/app/modules/home/pages/edge/edge-instructions-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/edge/edge-instructions-dialog.component.ts @@ -39,9 +39,10 @@ export interface EdgeInstructionsDialogData { } @Component({ - selector: 'tb-edge-installation-dialog', - templateUrl: './edge-instructions-dialog.component.html', - styleUrls: ['./edge-instructions-dialog.component.scss'] + selector: 'tb-edge-installation-dialog', + templateUrl: './edge-instructions-dialog.component.html', + styleUrls: ['./edge-instructions-dialog.component.scss'], + standalone: false }) export class EdgeInstructionsDialogComponent extends DialogComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.ts b/ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.ts index 054b6626b4..c1111fa449 100644 --- a/ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.ts +++ b/ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.ts @@ -22,9 +22,10 @@ import { AppState } from '@core/core.state'; import { EdgeInfo } from '@shared/models/edge.models'; @Component({ - selector: 'tb-edge-table-header', - templateUrl: './edge-table-header.component.html', - styleUrls: [] + selector: 'tb-edge-table-header', + templateUrl: './edge-table-header.component.html', + styleUrls: [], + standalone: false }) export class EdgeTableHeaderComponent extends EntityTableHeaderComponent { diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/edge/edge-tabs.component.ts index 48a19840c2..58bc88a8db 100644 --- a/ui-ngx/src/app/modules/home/pages/edge/edge-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/edge/edge-tabs.component.ts @@ -21,9 +21,10 @@ import { EdgeInfo } from '@shared/models/edge.models'; import { EntityTabsComponent } from '@home/components/entity/entity-tabs.component'; @Component({ - selector: 'tb-edge-tabs', - templateUrl: './edge-tabs.component.html', - styleUrls: [] + selector: 'tb-edge-tabs', + templateUrl: './edge-tabs.component.html', + styleUrls: [], + standalone: false }) export class EdgeTabsComponent extends EntityTabsComponent { diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge.component.ts b/ui-ngx/src/app/modules/home/pages/edge/edge.component.ts index 396ba8b9b5..7a0d82798c 100644 --- a/ui-ngx/src/app/modules/home/pages/edge/edge.component.ts +++ b/ui-ngx/src/app/modules/home/pages/edge/edge.component.ts @@ -29,9 +29,10 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.mod import {EdgeService} from "@core/http/edge.service"; @Component({ - selector: 'tb-edge', - templateUrl: './edge.component.html', - styleUrls: ['./edge.component.scss'] + selector: 'tb-edge', + templateUrl: './edge.component.html', + styleUrls: ['./edge.component.scss'], + standalone: false }) export class EdgeComponent extends EntityComponent { diff --git a/ui-ngx/src/app/modules/home/pages/entity-view/entity-view-table-header.component.ts b/ui-ngx/src/app/modules/home/pages/entity-view/entity-view-table-header.component.ts index 782d1d2c83..da2a867c56 100644 --- a/ui-ngx/src/app/modules/home/pages/entity-view/entity-view-table-header.component.ts +++ b/ui-ngx/src/app/modules/home/pages/entity-view/entity-view-table-header.component.ts @@ -22,9 +22,10 @@ import { EntityType } from '@shared/models/entity-type.models'; import { EntityViewInfo } from '@app/shared/models/entity-view.models'; @Component({ - selector: 'tb-entity-view-table-header', - templateUrl: './entity-view-table-header.component.html', - styleUrls: [] + selector: 'tb-entity-view-table-header', + templateUrl: './entity-view-table-header.component.html', + styleUrls: [], + standalone: false }) export class EntityViewTableHeaderComponent extends EntityTableHeaderComponent { diff --git a/ui-ngx/src/app/modules/home/pages/entity-view/entity-view-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/entity-view/entity-view-tabs.component.ts index 26d678c45b..577b4eb147 100644 --- a/ui-ngx/src/app/modules/home/pages/entity-view/entity-view-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/entity-view/entity-view-tabs.component.ts @@ -21,9 +21,10 @@ import { EntityTabsComponent } from '../../components/entity/entity-tabs.compone import { EntityViewInfo } from '@app/shared/models/entity-view.models'; @Component({ - selector: 'tb-entity-view-tabs', - templateUrl: './entity-view-tabs.component.html', - styleUrls: [] + selector: 'tb-entity-view-tabs', + templateUrl: './entity-view-tabs.component.html', + styleUrls: [], + standalone: false }) export class EntityViewTabsComponent extends EntityTabsComponent { diff --git a/ui-ngx/src/app/modules/home/pages/entity-view/entity-view.component.ts b/ui-ngx/src/app/modules/home/pages/entity-view/entity-view.component.ts index 98e1a55695..65485f340c 100644 --- a/ui-ngx/src/app/modules/home/pages/entity-view/entity-view.component.ts +++ b/ui-ngx/src/app/modules/home/pages/entity-view/entity-view.component.ts @@ -30,9 +30,10 @@ import { EntityId } from '@app/shared/models/id/entity-id'; import { EntityTableConfig } from '@home/models/entity/entities-table-config.models'; @Component({ - selector: 'tb-entity-view', - templateUrl: './entity-view.component.html', - styleUrls: ['./entity-view.component.scss'] + selector: 'tb-entity-view', + templateUrl: './entity-view.component.html', + styleUrls: ['./entity-view.component.scss'], + standalone: false }) export class EntityViewComponent extends EntityComponent { diff --git a/ui-ngx/src/app/modules/home/pages/home-links/home-links.component.ts b/ui-ngx/src/app/modules/home/pages/home-links/home-links.component.ts index 67546086cb..f7b38179ab 100644 --- a/ui-ngx/src/app/modules/home/pages/home-links/home-links.component.ts +++ b/ui-ngx/src/app/modules/home/pages/home-links/home-links.component.ts @@ -23,10 +23,11 @@ import { ActivatedRoute } from '@angular/router'; import { HomeDashboard } from '@shared/models/dashboard.models'; @Component({ - selector: 'tb-home-links', - templateUrl: './home-links.component.html', - styleUrls: ['./home-links.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-home-links', + templateUrl: './home-links.component.html', + styleUrls: ['./home-links.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: false }) export class HomeLinksComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/mobile/applications/mobile-app-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/applications/mobile-app-dialog.component.ts index 51f087f13a..2ee6465d33 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/applications/mobile-app-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/applications/mobile-app-dialog.component.ts @@ -32,10 +32,11 @@ export interface MobileAppDialogData { } @Component({ - selector: 'tb-mobile-app-dialog', - templateUrl: './mobile-app-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: MobileAppDialogComponent}], - styleUrls: [] + selector: 'tb-mobile-app-dialog', + templateUrl: './mobile-app-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: MobileAppDialogComponent }], + styleUrls: [], + standalone: false }) export class MobileAppDialogComponent extends DialogComponent implements OnDestroy, AfterViewInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/pages/mobile/applications/mobile-app-table-header.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/applications/mobile-app-table-header.component.ts index 0711aa1116..d0b5f2f416 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/applications/mobile-app-table-header.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/applications/mobile-app-table-header.component.ts @@ -21,9 +21,10 @@ import { AppState } from '@core/core.state'; import { MobileApp } from '@shared/models/mobile-app.models'; @Component({ - selector: 'tb-mobile-app-table-header', - templateUrl: './mobile-app-table-header.component.html', - styleUrls: ['./mobile-app-table-header.component.scss'] + selector: 'tb-mobile-app-table-header', + templateUrl: './mobile-app-table-header.component.html', + styleUrls: ['./mobile-app-table-header.component.scss'], + standalone: false }) export class MobileAppTableHeaderComponent extends EntityTableHeaderComponent { diff --git a/ui-ngx/src/app/modules/home/pages/mobile/applications/mobile-app.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/applications/mobile-app.component.ts index abcb7beb5d..d2c1fe3dc9 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/applications/mobile-app.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/applications/mobile-app.component.ts @@ -31,9 +31,10 @@ import { TbPopoverService } from '@shared/components/popover.service'; import { EditorPanelComponent } from '@home/pages/mobile/common/editor-panel.component'; @Component({ - selector: 'tb-mobile-app', - templateUrl: './mobile-app.component.html', - styleUrls: ['./mobile-app.component.scss'] + selector: 'tb-mobile-app', + templateUrl: './mobile-app.component.html', + styleUrls: ['./mobile-app.component.scss'], + standalone: false }) export class MobileAppComponent extends EntityComponent { diff --git a/ui-ngx/src/app/modules/home/pages/mobile/applications/remove-app-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/applications/remove-app-dialog.component.ts index 39d0c5e266..1843192844 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/applications/remove-app-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/applications/remove-app-dialog.component.ts @@ -32,9 +32,10 @@ export interface MobileAppDeleteDialogData { } @Component({ - selector: 'tb-remove-app-dialog', - templateUrl: './remove-app-dialog.component.html', - styleUrls: ['./remove-app-dialog.component.scss'] + selector: 'tb-remove-app-dialog', + templateUrl: './remove-app-dialog.component.html', + styleUrls: ['./remove-app-dialog.component.scss'], + standalone: false }) export class RemoveAppDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/add-mobile-page-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/add-mobile-page-dialog.component.ts index e3644c117f..bff9631ce4 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/add-mobile-page-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/add-mobile-page-dialog.component.ts @@ -25,9 +25,10 @@ import { FormBuilder } from '@angular/forms'; import { deepTrim } from '@core/utils'; @Component({ - selector: 'tb-add-mobile-page-dialog', - templateUrl: './add-mobile-page-dialog.component.html', - styleUrls: ['./add-mobile-page-dialog.component.scss'] + selector: 'tb-add-mobile-page-dialog', + templateUrl: './add-mobile-page-dialog.component.html', + styleUrls: ['./add-mobile-page-dialog.component.scss'], + standalone: false }) export class AddMobilePageDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/custom-mobile-page-panel.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/custom-mobile-page-panel.component.ts index 045f1e3298..afbdd00885 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/custom-mobile-page-panel.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/custom-mobile-page-panel.component.ts @@ -20,10 +20,11 @@ import { CustomMobilePage } from '@shared/models/mobile-app.models'; import { TbPopoverComponent } from '@shared/components/popover.component'; @Component({ - selector: 'tb-custom-menu-item-panel', - templateUrl: './custom-mobile-page-panel.component.html', - styleUrls: ['./custom-mobile-page-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-custom-menu-item-panel', + templateUrl: './custom-mobile-page-panel.component.html', + styleUrls: ['./custom-mobile-page-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class CustomMobilePagePanelComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/custom-mobile-page.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/custom-mobile-page.component.ts index 4c97990028..84652c3027 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/custom-mobile-page.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/custom-mobile-page.component.ts @@ -37,21 +37,22 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-mobile-page-item', - templateUrl: './custom-mobile-page.component.html', - styleUrls: ['./custom-mobile-page.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => CustomMobilePageComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => CustomMobilePageComponent), - multi: true - } - ] + selector: 'tb-mobile-page-item', + templateUrl: './custom-mobile-page.component.html', + styleUrls: ['./custom-mobile-page.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CustomMobilePageComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => CustomMobilePageComponent), + multi: true + } + ], + standalone: false }) export class CustomMobilePageComponent implements ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/default-mobile-page-panel.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/default-mobile-page-panel.component.ts index de3d7a1a79..e4c1d3b288 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/default-mobile-page-panel.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/default-mobile-page-panel.component.ts @@ -21,10 +21,11 @@ import { FormBuilder, Validators } from '@angular/forms'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-default-mobile-page-panel', - templateUrl: './default-mobile-page-panel.component.html', - styleUrls: ['./default-mobile-page-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-default-mobile-page-panel', + templateUrl: './default-mobile-page-panel.component.html', + styleUrls: ['./default-mobile-page-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class DefaultMobilePagePanelComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/mobile-layout.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/mobile-layout.component.ts index b61263c2d5..9506f68043 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/mobile-layout.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/mobile-layout.component.ts @@ -44,21 +44,22 @@ import { MatDialog } from '@angular/material/dialog'; import { AddMobilePageDialogComponent } from '@home/pages/mobile/bundes/layout/add-mobile-page-dialog.component'; @Component({ - selector: 'tb-mobile-layout', - templateUrl: './mobile-layout.component.html', - styleUrls: ['./mobile-layout.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MobileLayoutComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MobileLayoutComponent), - multi: true - } - ], + selector: 'tb-mobile-layout', + templateUrl: './mobile-layout.component.html', + styleUrls: ['./mobile-layout.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MobileLayoutComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MobileLayoutComponent), + multi: true + } + ], + standalone: false }) export class MobileLayoutComponent implements ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/mobile-page-item-row.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/mobile-page-item-row.component.ts index 516e007761..8772b6ad71 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/mobile-page-item-row.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/mobile-page-item-row.component.ts @@ -58,22 +58,23 @@ import { TranslateService } from '@ngx-translate/core'; import { DisplayPopoverConfig } from '@shared/components/popover.models'; @Component({ - selector: 'tb-mobile-menu-item-row', - templateUrl: './mobile-page-item-row.component.html', - styleUrls: ['./mobile-page-item-row.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MobilePageItemRowComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MobilePageItemRowComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-mobile-menu-item-row', + templateUrl: './mobile-page-item-row.component.html', + styleUrls: ['./mobile-page-item-row.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MobilePageItemRowComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MobilePageItemRowComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class MobilePageItemRowComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-app-configuration-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-app-configuration-dialog.component.ts index 1f120de868..b03faa5b5a 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-app-configuration-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-app-configuration-dialog.component.ts @@ -33,9 +33,10 @@ export interface MobileAppConfigurationDialogData { } @Component({ - selector: 'tb-mobile-app-configuration-dialog', - templateUrl: './mobile-app-configuration-dialog.component.html', - styleUrls: ['./mobile-app-configuration-dialog.component.scss'] + selector: 'tb-mobile-app-configuration-dialog', + templateUrl: './mobile-app-configuration-dialog.component.html', + styleUrls: ['./mobile-app-configuration-dialog.component.scss'], + standalone: false }) export class MobileAppConfigurationDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-bundle-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-bundle-dialog.component.ts index acc1d3785b..18cc3c2688 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-bundle-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-bundle-dialog.component.ts @@ -45,9 +45,10 @@ export interface MobileBundleDialogData { } @Component({ - selector: 'tb-mobile-bundle-dialog', - templateUrl: './mobile-bundle-dialog.component.html', - styleUrls: ['./mobile-bundle-dialog.component.scss'] + selector: 'tb-mobile-bundle-dialog', + templateUrl: './mobile-bundle-dialog.component.html', + styleUrls: ['./mobile-bundle-dialog.component.scss'], + standalone: false }) export class MobileBundleDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-bundle-table-header.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-bundle-table-header.component.ts index 1a0a6aeca9..dc9c6492f8 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-bundle-table-header.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-bundle-table-header.component.ts @@ -21,9 +21,10 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @Component({ - selector: 'tb-mobile-bundle-table-header', - templateUrl: './mobile-bundle-table-header.component.html', - styleUrls: ['./mobile-bundle-table-header.component.scss'] + selector: 'tb-mobile-bundle-table-header', + templateUrl: './mobile-bundle-table-header.component.html', + styleUrls: ['./mobile-bundle-table-header.component.scss'], + standalone: false }) export class MobileBundleTableHeaderComponent extends EntityTableHeaderComponent { diff --git a/ui-ngx/src/app/modules/home/pages/mobile/common/editor-panel.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/common/editor-panel.component.ts index 49cad3a3ab..9f2e850b53 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/common/editor-panel.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/common/editor-panel.component.ts @@ -20,10 +20,11 @@ import { TbPopoverComponent } from '@shared/components/popover.component'; import { EditorOptions } from 'tinymce'; @Component({ - selector: 'tb-release-notes-panel', - templateUrl: './editor-panel.component.html', - styleUrls: ['./editor-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-release-notes-panel', + templateUrl: './editor-panel.component.html', + styleUrls: ['./editor-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class EditorPanelComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/mobile/qr-code-widget/mobile-qr-code-widget-settings.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/qr-code-widget/mobile-qr-code-widget-settings.component.ts index 9c6b58a967..1745a8a0b1 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/qr-code-widget/mobile-qr-code-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/qr-code-widget/mobile-qr-code-widget-settings.component.ts @@ -27,9 +27,10 @@ import { EntityType } from '@shared/models/entity-type.models'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-mobile-qr-code-widget', - templateUrl: './mobile-qr-code-widget-settings.component.html', - styleUrls: ['mobile-qr-code-widget-settings.component.scss', '../../admin/settings-card.scss'] + selector: 'tb-mobile-qr-code-widget', + templateUrl: './mobile-qr-code-widget-settings.component.html', + styleUrls: ['mobile-qr-code-widget-settings.component.scss', '../../admin/settings-card.scss'], + standalone: false }) export class MobileQrCodeWidgetSettingsComponent extends PageComponent implements HasConfirmForm { diff --git a/ui-ngx/src/app/modules/home/pages/notification/inbox/inbox-notification-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/notification/inbox/inbox-notification-dialog.component.ts index f1ce8808ef..2ab4382a2c 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/inbox/inbox-notification-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/inbox/inbox-notification-dialog.component.ts @@ -27,9 +27,10 @@ export interface InboxNotificationDialogData { } @Component({ - selector: 'tb-inbox-notification-dialog', - templateUrl: './inbox-notification-dialog.component.html', - styleUrls: ['inbox-notification-dialog.component.scss'] + selector: 'tb-inbox-notification-dialog', + templateUrl: './inbox-notification-dialog.component.html', + styleUrls: ['inbox-notification-dialog.component.scss'], + standalone: false }) export class InboxNotificationDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/pages/notification/inbox/inbox-table-header.component.ts b/ui-ngx/src/app/modules/home/pages/notification/inbox/inbox-table-header.component.ts index f1b9bea7c7..7aade4fbad 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/inbox/inbox-table-header.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/inbox/inbox-table-header.component.ts @@ -21,9 +21,10 @@ import { AppState } from '@core/core.state'; import { Notification } from '@shared/models/notification.models'; @Component({ - selector: 'tb-inbox-table-header', - templateUrl: './inbox-table-header.component.html', - styleUrls: [] + selector: 'tb-inbox-table-header', + templateUrl: './inbox-table-header.component.html', + styleUrls: [], + standalone: false }) export class InboxTableHeaderComponent extends EntityTableHeaderComponent { diff --git a/ui-ngx/src/app/modules/home/pages/notification/recipient/recipient-notification-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/notification/recipient/recipient-notification-dialog.component.ts index 755d9d181d..deb518e93b 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/recipient/recipient-notification-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/recipient/recipient-notification-dialog.component.ts @@ -46,9 +46,10 @@ export interface RecipientNotificationDialogData { } @Component({ - selector: 'tb-target-notification-dialog', - templateUrl: './recipient-notification-dialog.component.html', - styleUrls: ['recipient-notification-dialog.component.scss'] + selector: 'tb-target-notification-dialog', + templateUrl: './recipient-notification-dialog.component.html', + styleUrls: ['recipient-notification-dialog.component.scss'], + standalone: false }) export class RecipientNotificationDialogComponent extends DialogComponent implements OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/notification/rule/escalation-form.component.ts b/ui-ngx/src/app/modules/home/pages/notification/rule/escalation-form.component.ts index 3794d7ab26..faa6a565e3 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/rule/escalation-form.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/rule/escalation-form.component.ts @@ -42,21 +42,22 @@ import { MatDialog } from '@angular/material/dialog'; import { MatButton } from '@angular/material/button'; @Component({ - selector: 'tb-escalation-form', - templateUrl: './escalation-form.component.html', - styleUrls: ['./escalation-form.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => EscalationFormComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => EscalationFormComponent), - multi: true, - } - ] + selector: 'tb-escalation-form', + templateUrl: './escalation-form.component.html', + styleUrls: ['./escalation-form.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => EscalationFormComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => EscalationFormComponent), + multi: true, + } + ], + standalone: false }) export class EscalationFormComponent implements ControlValueAccessor, OnInit, OnDestroy, Validator { diff --git a/ui-ngx/src/app/modules/home/pages/notification/rule/escalations.component.ts b/ui-ngx/src/app/modules/home/pages/notification/rule/escalations.component.ts index 36d2913621..37aa7393f8 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/rule/escalations.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/rule/escalations.component.ts @@ -35,21 +35,22 @@ import { takeUntil } from 'rxjs/operators'; import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ - selector: 'tb-escalations-component', - templateUrl: './escalations.component.html', - styleUrls: [], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => EscalationsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => EscalationsComponent), - multi: true, - } - ] + selector: 'tb-escalations-component', + templateUrl: './escalations.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => EscalationsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => EscalationsComponent), + multi: true, + } + ], + standalone: false }) export class EscalationsComponent implements ControlValueAccessor, Validator, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.ts index 629407ace3..5bfa64c99d 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.ts @@ -77,9 +77,10 @@ export interface RuleNotificationDialogData { } @Component({ - selector: 'tb-rule-notification-dialog', - templateUrl: './rule-notification-dialog.component.html', - styleUrls: ['rule-notification-dialog.component.scss'] + selector: 'tb-rule-notification-dialog', + templateUrl: './rule-notification-dialog.component.html', + styleUrls: ['rule-notification-dialog.component.scss'], + standalone: false }) export class RuleNotificationDialogComponent extends DialogComponent implements OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-error-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-error-dialog.component.ts index c20b49bc16..ea6e0bed5c 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-error-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-error-dialog.component.ts @@ -31,9 +31,10 @@ export interface NotificationRequestErrorDialogData { } @Component({ - selector: 'tb-notification-send-error-dialog', - templateUrl: './sent-error-dialog.component.html', - styleUrls: ['sent-error-dialog.component.scss'] + selector: 'tb-notification-send-error-dialog', + templateUrl: './sent-error-dialog.component.html', + styleUrls: ['sent-error-dialog.component.scss'], + standalone: false }) export class SentErrorDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts index 70a972066f..eec70df210 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts @@ -54,9 +54,10 @@ export interface RequestNotificationDialogData { } @Component({ - selector: 'tb-sent-notification-dialog', - templateUrl: './sent-notification-dialog.component.html', - styleUrls: ['./sent-notification-dialog.component.scss'] + selector: 'tb-sent-notification-dialog', + templateUrl: './sent-notification-dialog.component.html', + styleUrls: ['./sent-notification-dialog.component.scss'], + standalone: false }) export class SentNotificationDialogComponent extends TemplateConfiguration implements OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/notification/settings/notification-setting-form.component.ts b/ui-ngx/src/app/modules/home/pages/notification/settings/notification-setting-form.component.ts index 187ae39d3d..071ccbeeb5 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/settings/notification-setting-form.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/settings/notification-setting-form.component.ts @@ -25,16 +25,17 @@ import { } from '@shared/models/notification.models'; @Component({ - selector: 'tb-notification-setting-form', - templateUrl: './notification-setting-form.component.html', - styleUrls: ['./notification-setting-form.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => NotificationSettingFormComponent), - multi: true - } - ] + selector: 'tb-notification-setting-form', + templateUrl: './notification-setting-form.component.html', + styleUrls: ['./notification-setting-form.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => NotificationSettingFormComponent), + multi: true + } + ], + standalone: false }) export class NotificationSettingFormComponent implements ControlValueAccessor, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/notification/settings/notification-settings.component.ts b/ui-ngx/src/app/modules/home/pages/notification/settings/notification-settings.component.ts index 3abddf49af..4adc4d4c6c 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/settings/notification-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/settings/notification-settings.component.ts @@ -32,9 +32,10 @@ import { NotificationService } from '@core/http/notification.service'; import { DialogService } from '@core/services/dialog.service'; @Component({ - selector: 'tb-notification-settings', - templateUrl: './notification-settings.component.html', - styleUrls: ['./notification-settings.component.scss'] + selector: 'tb-notification-settings', + templateUrl: './notification-settings.component.html', + styleUrls: ['./notification-settings.component.scss'], + standalone: false }) export class NotificationSettingsComponent extends PageComponent implements OnInit, HasConfirmForm { diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-action-button-configuration.component.ts b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-action-button-configuration.component.ts index cf828ce68f..5b3975a1a0 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-action-button-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-action-button-configuration.component.ts @@ -32,20 +32,21 @@ import { isDefinedAndNotNull } from '@core/utils'; import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ - selector: 'tb-notification-action-button-configuration', - templateUrl: './notification-action-button-configuration.component.html', - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => NotificationActionButtonConfigurationComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => NotificationActionButtonConfigurationComponent), - multi: true, - } - ] + selector: 'tb-notification-action-button-configuration', + templateUrl: './notification-action-button-configuration.component.html', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => NotificationActionButtonConfigurationComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => NotificationActionButtonConfigurationComponent), + multi: true, + } + ], + standalone: false }) export class NotificationActionButtonConfigurationComponent implements ControlValueAccessor, Validator, OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.ts b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.ts index d3a606b8b9..4a4f11d40b 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.ts @@ -40,21 +40,22 @@ import { TranslateService } from '@ngx-translate/core'; import { EditorOptions } from 'tinymce'; @Component({ - selector: 'tb-template-configuration', - templateUrl: './notification-template-configuration.component.html', - styleUrls: ['./notification-template-configuration.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => NotificationTemplateConfigurationComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => NotificationTemplateConfigurationComponent), - multi: true, - } - ] + selector: 'tb-template-configuration', + templateUrl: './notification-template-configuration.component.html', + styleUrls: ['./notification-template-configuration.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => NotificationTemplateConfigurationComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => NotificationTemplateConfigurationComponent), + multi: true, + } + ], + standalone: false }) export class NotificationTemplateConfigurationComponent implements OnDestroy, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts index 14201b3301..11c759c40f 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts @@ -44,9 +44,10 @@ export interface TemplateNotificationDialogData { } @Component({ - selector: 'tb-template-notification-dialog', - templateUrl: './template-notification-dialog.component.html', - styleUrls: ['./template-notification-dialog.component.scss'] + selector: 'tb-template-notification-dialog', + templateUrl: './template-notification-dialog.component.html', + styleUrls: ['./template-notification-dialog.component.scss'], + standalone: false }) export class TemplateNotificationDialogComponent extends TemplateConfiguration implements OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/ota-update/ota-update-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/ota-update/ota-update-tabs.component.ts index faa54215f7..31b2813d78 100644 --- a/ui-ngx/src/app/modules/home/pages/ota-update/ota-update-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/ota-update/ota-update-tabs.component.ts @@ -23,9 +23,10 @@ import { NULL_UUID } from '@shared/models/id/has-uuid'; import { OtaPackage } from '@shared/models/ota-package.models'; @Component({ - selector: 'tb-ota-update-tabs', - templateUrl: './ota-update-tabs.component.html', - styleUrls: [] + selector: 'tb-ota-update-tabs', + templateUrl: './ota-update-tabs.component.html', + styleUrls: [], + standalone: false }) export class OtaUpdateTabsComponent extends EntityTabsComponent { diff --git a/ui-ngx/src/app/modules/home/pages/ota-update/ota-update.component.ts b/ui-ngx/src/app/modules/home/pages/ota-update/ota-update.component.ts index 5ec5ca42e7..8810d46627 100644 --- a/ui-ngx/src/app/modules/home/pages/ota-update/ota-update.component.ts +++ b/ui-ngx/src/app/modules/home/pages/ota-update/ota-update.component.ts @@ -34,8 +34,9 @@ import { filter, startWith, takeUntil } from 'rxjs/operators'; import { isNotEmptyStr } from '@core/utils'; @Component({ - selector: 'tb-ota-update', - templateUrl: './ota-update.component.html' + selector: 'tb-ota-update', + templateUrl: './ota-update.component.html', + standalone: false }) export class OtaUpdateComponent extends EntityComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/profile/profile.component.ts b/ui-ngx/src/app/modules/home/pages/profile/profile.component.ts index fc35321d9a..6de7338d92 100644 --- a/ui-ngx/src/app/modules/home/pages/profile/profile.component.ts +++ b/ui-ngx/src/app/modules/home/pages/profile/profile.component.ts @@ -35,9 +35,10 @@ import { UnitSystem, UnitSystems } from '@shared/models/unit.models'; import { UnitService } from '@core/services/unit.service'; @Component({ - selector: 'tb-profile', - templateUrl: './profile.component.html', - styleUrls: ['./profile.component.scss'] + selector: 'tb-profile', + templateUrl: './profile.component.html', + styleUrls: ['./profile.component.scss'], + standalone: false }) export class ProfileComponent extends PageComponent implements OnInit, HasConfirmForm { diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/link-labels.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/link-labels.component.ts index 0aa2d86e6f..6745796cbb 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/link-labels.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/link-labels.component.ts @@ -29,14 +29,15 @@ import { catchError, map, mergeMap, share, startWith } from 'rxjs/operators'; import { RuleChainService } from '@core/http/rule-chain.service'; @Component({ - selector: 'tb-link-labels', - templateUrl: './link-labels.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => LinkLabelsComponent), - multi: true - }] + selector: 'tb-link-labels', + templateUrl: './link-labels.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => LinkLabelsComponent), + multi: true + }], + standalone: false }) export class LinkLabelsComponent implements ControlValueAccessor, OnInit, OnChanges { diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts index e1d8f11bf5..013e4841f3 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts @@ -47,15 +47,16 @@ import { deepClone } from '@core/utils'; import { RuleChainType } from '@shared/models/rule-chain.models'; @Component({ - selector: 'tb-rule-node-config', - templateUrl: './rule-node-config.component.html', - styleUrls: ['./rule-node-config.component.scss'], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => RuleNodeConfigComponent), - multi: true - }], - encapsulation: ViewEncapsulation.None + selector: 'tb-rule-node-config', + templateUrl: './rule-node-config.component.html', + styleUrls: ['./rule-node-config.component.scss'], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RuleNodeConfigComponent), + multi: true + }], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class RuleNodeConfigComponent implements ControlValueAccessor, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts index 67f97624c5..bf231b7126 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts @@ -39,9 +39,10 @@ import { ServiceType } from '@shared/models/queue.models'; import { takeUntil } from 'rxjs/operators'; @Component({ - selector: 'tb-rule-node', - templateUrl: './rule-node-details.component.html', - styleUrls: ['./rule-node-details.component.scss'] + selector: 'tb-rule-node', + templateUrl: './rule-node-details.component.html', + styleUrls: ['./rule-node-details.component.scss'], + standalone: false }) export class RuleNodeDetailsComponent extends PageComponent implements OnInit, OnChanges, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-link.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-link.component.ts index 14cd0a8190..e8ac36e3fb 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-link.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-link.component.ts @@ -23,14 +23,15 @@ import { TranslateService } from '@ngx-translate/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-rule-node-link', - templateUrl: './rule-node-link.component.html', - styleUrls: [], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => RuleNodeLinkComponent), - multi: true - }] + selector: 'tb-rule-node-link', + templateUrl: './rule-node-link.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RuleNodeLinkComponent), + multi: true + }], + standalone: false }) export class RuleNodeLinkComponent implements ControlValueAccessor, OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts index d4d3655e2f..c6dc3eae9c 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts @@ -101,10 +101,11 @@ import Timeout = NodeJS.Timeout; import { DomSanitizer } from '@angular/platform-browser'; @Component({ - selector: 'tb-rulechain-page', - templateUrl: './rulechain-page.component.html', - styleUrls: ['./rulechain-page.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-rulechain-page', + templateUrl: './rulechain-page.component.html', + styleUrls: ['./rulechain-page.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class RuleChainPageComponent extends PageComponent implements AfterViewInit, OnInit, OnDestroy, HasDirtyFlag, ISearchableComponent, AfterViewChecked { @@ -1753,10 +1754,11 @@ export interface AddRuleNodeLinkDialogData { } @Component({ - selector: 'tb-add-rule-node-link-dialog', - templateUrl: './add-rule-node-link-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: AddRuleNodeLinkDialogComponent}], - styleUrls: ['./add-rule-node-link-dialog.component.scss'] + selector: 'tb-add-rule-node-link-dialog', + templateUrl: './add-rule-node-link-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: AddRuleNodeLinkDialogComponent }], + styleUrls: ['./add-rule-node-link-dialog.component.scss'], + standalone: false }) export class AddRuleNodeLinkDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { @@ -1817,10 +1819,11 @@ export interface AddRuleNodeDialogData { } @Component({ - selector: 'tb-add-rule-node-dialog', - templateUrl: './add-rule-node-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: AddRuleNodeDialogComponent}], - styleUrls: ['./add-rule-node-dialog.component.scss'] + selector: 'tb-add-rule-node-dialog', + templateUrl: './add-rule-node-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: AddRuleNodeDialogComponent }], + styleUrls: ['./add-rule-node-dialog.component.scss'], + standalone: false }) export class AddRuleNodeDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { @@ -1877,10 +1880,11 @@ export interface CreateNestedRuleChainDialogData { } @Component({ - selector: 'tb-create-nested-rulechain-dialog', - templateUrl: './create-nested-rulechain-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: CreateNestedRuleChainDialogComponent}], - styleUrls: [] + selector: 'tb-create-nested-rulechain-dialog', + templateUrl: './create-nested-rulechain-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: CreateNestedRuleChainDialogComponent }], + styleUrls: [], + standalone: false }) export class CreateNestedRuleChainDialogComponent extends DialogComponent implements OnInit, ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-tabs.component.ts index 0ec3c4df52..8e26eed483 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-tabs.component.ts @@ -21,9 +21,10 @@ import { EntityTabsComponent } from '../../components/entity/entity-tabs.compone import { RuleChain } from '@shared/models/rule-chain.models'; @Component({ - selector: 'tb-rulechain-tabs', - templateUrl: './rulechain-tabs.component.html', - styleUrls: [] + selector: 'tb-rulechain-tabs', + templateUrl: './rulechain-tabs.component.html', + styleUrls: [], + standalone: false }) export class RuleChainTabsComponent extends EntityTabsComponent { diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain.component.ts index df55eeff90..5769009066 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain.component.ts @@ -25,9 +25,10 @@ import { RuleChain } from '@shared/models/rule-chain.models'; import { EntityTableConfig } from '@home/models/entity/entities-table-config.models'; @Component({ - selector: 'tb-rulechain', - templateUrl: './rulechain.component.html', - styleUrls: ['./rulechain.component.scss'] + selector: 'tb-rulechain', + templateUrl: './rulechain.component.html', + styleUrls: ['./rulechain.component.scss'], + standalone: false }) export class RuleChainComponent extends EntityComponent { diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.ts index 87e2d0a31b..04c293d241 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulenode.component.ts @@ -23,10 +23,11 @@ import { RuleChainType } from '@app/shared/models/rule-chain.models'; import { TranslateService } from '@ngx-translate/core'; @Component({ - // eslint-disable-next-line @angular-eslint/component-selector - selector: 'rule-node', - templateUrl: './rulenode.component.html', - styleUrls: ['./rulenode.component.scss'] + // eslint-disable-next-line @angular-eslint/component-selector + selector: 'rule-node', + templateUrl: './rulenode.component.html', + styleUrls: ['./rulenode.component.scss'], + standalone: false }) export class RuleNodeComponent extends FcNodeComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-panel.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-panel.component.ts index c488258b6d..793c1307db 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-panel.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-panel.component.ts @@ -35,10 +35,11 @@ import { WidgetActionCallbacks } from '@home/components/widget/action/manage-wid import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-scada-symbol-behavior-panel', - templateUrl: './scada-symbol-behavior-panel.component.html', - styleUrls: ['./scada-symbol-behavior-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-scada-symbol-behavior-panel', + templateUrl: './scada-symbol-behavior-panel.component.html', + styleUrls: ['./scada-symbol-behavior-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ScadaSymbolBehaviorPanelComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-row.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-row.component.ts index 2d53986923..18b3d3bf4c 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-row.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-row.component.ts @@ -91,22 +91,23 @@ export const behaviorValid = (behavior: ScadaSymbolBehavior): boolean => { }; @Component({ - selector: 'tb-scada-symbol-metadata-behavior-row', - templateUrl: './scada-symbol-behavior-row.component.html', - styleUrls: ['./scada-symbol-behavior-row.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ScadaSymbolBehaviorRowComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => ScadaSymbolBehaviorRowComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-scada-symbol-metadata-behavior-row', + templateUrl: './scada-symbol-behavior-row.component.html', + styleUrls: ['./scada-symbol-behavior-row.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ScadaSymbolBehaviorRowComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ScadaSymbolBehaviorRowComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ScadaSymbolBehaviorRowComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behaviors.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behaviors.component.ts index 9775ad9a63..bb24f86a19 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behaviors.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behaviors.component.ts @@ -55,22 +55,23 @@ import { WidgetActionCallbacks } from '@home/components/widget/action/manage-wid import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-scada-symbol-metadata-behaviors', - templateUrl: './scada-symbol-behaviors.component.html', - styleUrls: ['./scada-symbol-behaviors.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ScadaSymbolBehaviorsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => ScadaSymbolBehaviorsComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-scada-symbol-metadata-behaviors', + templateUrl: './scada-symbol-behaviors.component.html', + styleUrls: ['./scada-symbol-behaviors.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ScadaSymbolBehaviorsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ScadaSymbolBehaviorsComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ScadaSymbolBehaviorsComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.ts index 3f9cdddd7c..2e1a7e4d29 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.ts @@ -36,10 +36,11 @@ import { import { JsFuncComponent } from '@shared/components/js-func.component'; @Component({ - selector: 'tb-scada-symbol-metadata-tag-function-panel', - templateUrl: './scada-symbol-metadata-tag-function-panel.component.html', - styleUrls: ['./scada-symbol-metadata-tag-function-panel.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-scada-symbol-metadata-tag-function-panel', + templateUrl: './scada-symbol-metadata-tag-function-panel.component.html', + styleUrls: ['./scada-symbol-metadata-tag-function-panel.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ScadaSymbolMetadataTagFunctionPanelComponent implements OnInit, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component.ts index 352d3823da..a1237d87dc 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag.component.ts @@ -43,22 +43,23 @@ import { } from '@home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component'; @Component({ - selector: 'tb-scada-symbol-metadata-tag', - templateUrl: './scada-symbol-metadata-tag.component.html', - styleUrls: ['./scada-symbol-metadata-tag.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ScadaSymbolMetadataTagComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => ScadaSymbolMetadataTagComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-scada-symbol-metadata-tag', + templateUrl: './scada-symbol-metadata-tag.component.html', + styleUrls: ['./scada-symbol-metadata-tag.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ScadaSymbolMetadataTagComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ScadaSymbolMetadataTagComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ScadaSymbolMetadataTagComponent implements ControlValueAccessor, OnInit, Validator { diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component.ts index d4286b762c..f2556d3cf0 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tags.component.ts @@ -49,22 +49,23 @@ const tagIsEmpty = (tag: ScadaSymbolTag): boolean => !tag.stateRenderFunction && !tag.actions?.click?.actionFunction; @Component({ - selector: 'tb-scada-symbol-metadata-tags', - templateUrl: './scada-symbol-metadata-tags.component.html', - styleUrls: ['./scada-symbol-metadata-tags.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ScadaSymbolMetadataTagsComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => ScadaSymbolMetadataTagsComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-scada-symbol-metadata-tags', + templateUrl: './scada-symbol-metadata-tags.component.html', + styleUrls: ['./scada-symbol-metadata-tags.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ScadaSymbolMetadataTagsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ScadaSymbolMetadataTagsComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ScadaSymbolMetadataTagsComponent implements ControlValueAccessor, OnInit, Validator, OnChanges { diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts index 9dd2afba52..a893100791 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts @@ -58,22 +58,23 @@ import { WidgetActionCallbacks } from '@home/components/widget/action/manage-wid import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-scada-symbol-metadata', - templateUrl: './scada-symbol-metadata.component.html', - styleUrls: ['./scada-symbol-metadata.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ScadaSymbolMetadataComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => ScadaSymbolMetadataComponent), - multi: true - } - ], - encapsulation: ViewEncapsulation.None + selector: 'tb-scada-symbol-metadata', + templateUrl: './scada-symbol-metadata.component.html', + styleUrls: ['./scada-symbol-metadata.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ScadaSymbolMetadataComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ScadaSymbolMetadataComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ScadaSymbolMetadataComponent extends PageComponent implements OnInit, OnChanges, ControlValueAccessor, Validator { diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.component.ts index 6ba0866d89..16380ea570 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.component.ts @@ -50,10 +50,11 @@ export interface ScadaSymbolEditorData { type editorModeType = 'svg' | 'xml'; @Component({ - selector: 'tb-scada-symbol-editor', - templateUrl: './scada-symbol-editor.component.html', - styleUrls: ['./scada-symbol-editor.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-scada-symbol-editor', + templateUrl: './scada-symbol-editor.component.html', + styleUrls: ['./scada-symbol-editor.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ScadaSymbolEditorComponent implements OnInit, OnDestroy, AfterViewInit, OnChanges { diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-tooltip.components.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-tooltip.components.ts index e8558c5206..60baf0e63b 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-tooltip.components.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-tooltip.components.ts @@ -57,15 +57,16 @@ abstract class ScadaSymbolPanelComponent implements AfterViewInit { } @Component({ - template: `
+ template: `
{{ symbolElement?.element?.type }}{{ symbolElement?.invisible ? ' (' + ('scada.hidden' | translate) + ')' : '' }}
`, - styleUrls: ['./scada-symbol-tooltip.component.scss'], - encapsulation: ViewEncapsulation.None + styleUrls: ['./scada-symbol-tooltip.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) class ScadaSymbolAddTagPanelComponent extends ScadaSymbolPanelComponent { @@ -83,7 +84,7 @@ class ScadaSymbolAddTagPanelComponent extends ScadaSymbolPanelComponent { } @Component({ - template: `
+ template: `
{{ (isAdd ? 'scada.tag.enter-tag' : 'scada.tag.update-tag' ) | translate }}: close
`, - styleUrls: ['./scada-symbol-tooltip.component.scss'], - encapsulation: ViewEncapsulation.None + styleUrls: ['./scada-symbol-tooltip.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) class ScadaSymbolTagInputPanelComponent extends ScadaSymbolPanelComponent implements AfterViewInit, OnDestroy { @@ -181,7 +183,7 @@ class ScadaSymbolTagInputPanelComponent extends ScadaSymbolPanelComponent implem } @Component({ - template: `
+ template: `
{{ symbolElement?.element?.type }}{{ symbolElement?.invisible ? ' (' + ('scada.hidden' | translate) + ')' : '' }}: {{ symbolElement?.tag }}
`, - styleUrls: ['./scada-symbol-tooltip.component.scss'], - encapsulation: ViewEncapsulation.None + styleUrls: ['./scada-symbol-tooltip.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) class ScadaSymbolTagPanelComponent extends ScadaSymbolPanelComponent implements OnInit, AfterViewInit { @@ -305,7 +308,7 @@ class ScadaSymbolTagPanelComponent extends ScadaSymbolPanelComponent implements } @Component({ - template: `
+ template: `
`, - styleUrls: ['./scada-symbol-tooltip.component.scss'], - encapsulation: ViewEncapsulation.None + styleUrls: ['./scada-symbol-tooltip.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) class ScadaSymbolRemoveTagConfirmComponent extends ScadaSymbolPanelComponent implements OnInit, AfterViewInit { @@ -355,7 +359,7 @@ class ScadaSymbolRemoveTagConfirmComponent extends ScadaSymbolPanelComponent imp } @Component({ - template: `
+ template: `
scada.state-render-function
`, - styleUrls: ['./scada-symbol-tooltip.component.scss'], - encapsulation: ViewEncapsulation.None + styleUrls: ['./scada-symbol-tooltip.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) class ScadaSymbolTagSettingsComponent extends ScadaSymbolPanelComponent implements OnInit, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.ts index 2c04591850..f2a358fde7 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.ts @@ -82,10 +82,11 @@ import { WidgetService } from '@core/http/widget.service'; import { ActionNotificationShow } from '@core/notification/notification.actions'; @Component({ - selector: 'tb-scada-symbol', - templateUrl: './scada-symbol.component.html', - styleUrls: ['./scada-symbol.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-scada-symbol', + templateUrl: './scada-symbol.component.html', + styleUrls: ['./scada-symbol.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class ScadaSymbolComponent extends PageComponent implements OnInit, OnDestroy, HasDirtyFlag, ScadaSymbolEditObjectCallbacks { diff --git a/ui-ngx/src/app/modules/home/pages/security/authentication-dialog/backup-code-auth-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/security/authentication-dialog/backup-code-auth-dialog.component.ts index 121aac9ee3..e785b6b538 100644 --- a/ui-ngx/src/app/modules/home/pages/security/authentication-dialog/backup-code-auth-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/security/authentication-dialog/backup-code-auth-dialog.component.ts @@ -34,9 +34,10 @@ import { deepClone } from '@core/utils'; import printTemplate from './backup-code-print-template.raw'; @Component({ - selector: 'tb-backup-code-auth-dialog', - templateUrl: './backup-code-auth-dialog.component.html', - styleUrls: ['./authentication-dialog.component.scss'] + selector: 'tb-backup-code-auth-dialog', + templateUrl: './backup-code-auth-dialog.component.html', + styleUrls: ['./authentication-dialog.component.scss'], + standalone: false }) export class BackupCodeAuthDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/pages/security/authentication-dialog/email-auth-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/security/authentication-dialog/email-auth-dialog.component.ts index 055298aa3c..dee27ba294 100644 --- a/ui-ngx/src/app/modules/home/pages/security/authentication-dialog/email-auth-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/security/authentication-dialog/email-auth-dialog.component.ts @@ -35,9 +35,10 @@ export interface EmailAuthDialogData { } @Component({ - selector: 'tb-email-auth-dialog', - templateUrl: './email-auth-dialog.component.html', - styleUrls: ['./authentication-dialog.component.scss'] + selector: 'tb-email-auth-dialog', + templateUrl: './email-auth-dialog.component.html', + styleUrls: ['./authentication-dialog.component.scss'], + standalone: false }) export class EmailAuthDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/pages/security/authentication-dialog/sms-auth-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/security/authentication-dialog/sms-auth-dialog.component.ts index 63b759f79f..952bb21211 100644 --- a/ui-ngx/src/app/modules/home/pages/security/authentication-dialog/sms-auth-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/security/authentication-dialog/sms-auth-dialog.component.ts @@ -31,9 +31,10 @@ import { phoneNumberPattern } from '@shared/models/settings.models'; import { MatStepper } from '@angular/material/stepper'; @Component({ - selector: 'tb-sms-auth-dialog', - templateUrl: './sms-auth-dialog.component.html', - styleUrls: ['./authentication-dialog.component.scss'] + selector: 'tb-sms-auth-dialog', + templateUrl: './sms-auth-dialog.component.html', + styleUrls: ['./authentication-dialog.component.scss'], + standalone: false }) export class SMSAuthDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/pages/security/authentication-dialog/totp-auth-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/security/authentication-dialog/totp-auth-dialog.component.ts index e52b07bc41..e110b1ebaf 100644 --- a/ui-ngx/src/app/modules/home/pages/security/authentication-dialog/totp-auth-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/security/authentication-dialog/totp-auth-dialog.component.ts @@ -31,9 +31,10 @@ import { MatStepper } from '@angular/material/stepper'; import { unwrapModule } from '@core/utils'; @Component({ - selector: 'tb-totp-auth-dialog', - templateUrl: './totp-auth-dialog.component.html', - styleUrls: ['./authentication-dialog.component.scss'] + selector: 'tb-totp-auth-dialog', + templateUrl: './totp-auth-dialog.component.html', + styleUrls: ['./authentication-dialog.component.scss'], + standalone: false }) export class TotpAuthDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/pages/security/security.component.ts b/ui-ngx/src/app/modules/home/pages/security/security.component.ts index d5d671e905..6b66cc7eb6 100644 --- a/ui-ngx/src/app/modules/home/pages/security/security.component.ts +++ b/ui-ngx/src/app/modules/home/pages/security/security.component.ts @@ -54,9 +54,10 @@ import { UserPasswordPolicy } from '@shared/models/settings.models'; import { MatCheckboxChange } from '@angular/material/checkbox'; @Component({ - selector: 'tb-security', - templateUrl: './security.component.html', - styleUrls: ['./security.component.scss'] + selector: 'tb-security', + templateUrl: './security.component.html', + styleUrls: ['./security.component.scss'], + standalone: false }) export class SecurityComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/pages/tenant-profile/tenant-profile-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/tenant-profile/tenant-profile-tabs.component.ts index e034ad9b7f..0eb66ec279 100644 --- a/ui-ngx/src/app/modules/home/pages/tenant-profile/tenant-profile-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/tenant-profile/tenant-profile-tabs.component.ts @@ -21,9 +21,10 @@ import { EntityTabsComponent } from '../../components/entity/entity-tabs.compone import { TenantProfile } from '@shared/models/tenant.model'; @Component({ - selector: 'tb-tenant-profile-tabs', - templateUrl: './tenant-profile-tabs.component.html', - styleUrls: [] + selector: 'tb-tenant-profile-tabs', + templateUrl: './tenant-profile-tabs.component.html', + styleUrls: [], + standalone: false }) export class TenantProfileTabsComponent extends EntityTabsComponent { diff --git a/ui-ngx/src/app/modules/home/pages/tenant/tenant-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/tenant/tenant-tabs.component.ts index 39d31a5367..8e0738b848 100644 --- a/ui-ngx/src/app/modules/home/pages/tenant/tenant-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/tenant/tenant-tabs.component.ts @@ -21,9 +21,10 @@ import { EntityTabsComponent } from '../../components/entity/entity-tabs.compone import { TenantInfo } from '@shared/models/tenant.model'; @Component({ - selector: 'tb-tenant-tabs', - templateUrl: './tenant-tabs.component.html', - styleUrls: [] + selector: 'tb-tenant-tabs', + templateUrl: './tenant-tabs.component.html', + styleUrls: [], + standalone: false }) export class TenantTabsComponent extends EntityTabsComponent { diff --git a/ui-ngx/src/app/modules/home/pages/tenant/tenant.component.ts b/ui-ngx/src/app/modules/home/pages/tenant/tenant.component.ts index 9ce2817e00..bfac5322f4 100644 --- a/ui-ngx/src/app/modules/home/pages/tenant/tenant.component.ts +++ b/ui-ngx/src/app/modules/home/pages/tenant/tenant.component.ts @@ -27,9 +27,10 @@ import { isDefinedAndNotNull } from '@core/utils'; import { CountryData } from '@shared/models/country.models'; @Component({ - selector: 'tb-tenant', - templateUrl: './tenant.component.html', - styleUrls: ['./tenant.component.scss'] + selector: 'tb-tenant', + templateUrl: './tenant.component.html', + styleUrls: ['./tenant.component.scss'], + standalone: false }) export class TenantComponent extends ContactBasedComponent { diff --git a/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.ts index ec869655c7..ead57fc0bf 100644 --- a/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.ts @@ -30,8 +30,9 @@ export interface ActivationLinkDialogData { } @Component({ - selector: 'tb-activation-link-dialog', - templateUrl: './activation-link-dialog.component.html' + selector: 'tb-activation-link-dialog', + templateUrl: './activation-link-dialog.component.html', + standalone: false }) export class ActivationLinkDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/pages/user/add-user-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/user/add-user-dialog.component.ts index dddf388eb1..a58931e2f3 100644 --- a/ui-ngx/src/app/modules/home/pages/user/add-user-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/user/add-user-dialog.component.ts @@ -40,9 +40,10 @@ export interface AddUserDialogData { } @Component({ - selector: 'tb-add-user-dialog', - templateUrl: './add-user-dialog.component.html', - styleUrls: ['./add-user-dialog.component.scss'] + selector: 'tb-add-user-dialog', + templateUrl: './add-user-dialog.component.html', + styleUrls: ['./add-user-dialog.component.scss'], + standalone: false }) export class AddUserDialogComponent extends DialogComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/user/user-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/user/user-tabs.component.ts index 0180d79f79..298af6f0de 100644 --- a/ui-ngx/src/app/modules/home/pages/user/user-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/user/user-tabs.component.ts @@ -21,9 +21,10 @@ import { EntityTabsComponent } from '../../components/entity/entity-tabs.compone import { User } from '@app/shared/models/user.model'; @Component({ - selector: 'tb-user-tabs', - templateUrl: './user-tabs.component.html', - styleUrls: [] + selector: 'tb-user-tabs', + templateUrl: './user-tabs.component.html', + styleUrls: [], + standalone: false }) export class UserTabsComponent extends EntityTabsComponent { diff --git a/ui-ngx/src/app/modules/home/pages/user/user.component.ts b/ui-ngx/src/app/modules/home/pages/user/user.component.ts index 1e1cb9cbea..515e80af71 100644 --- a/ui-ngx/src/app/modules/home/pages/user/user.component.ts +++ b/ui-ngx/src/app/modules/home/pages/user/user.component.ts @@ -29,9 +29,10 @@ import { ActionNotificationShow } from '@app/core/notification/notification.acti import { TranslateService } from '@ngx-translate/core'; @Component({ - selector: 'tb-user', - templateUrl: './user.component.html', - styleUrls: ['./user.component.scss'] + selector: 'tb-user', + templateUrl: './user.component.html', + styleUrls: ['./user.component.scss'], + standalone: false }) export class UserComponent extends EntityComponent{ diff --git a/ui-ngx/src/app/modules/home/pages/widget/save-widget-type-as-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/widget/save-widget-type-as-dialog.component.ts index 8c6e8fe9d4..c0522ba993 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/save-widget-type-as-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/save-widget-type-as-dialog.component.ts @@ -36,9 +36,10 @@ export interface SaveWidgetTypeAsDialogData { } @Component({ - selector: 'tb-save-widget-type-as-dialog', - templateUrl: './save-widget-type-as-dialog.component.html', - styleUrls: [] + selector: 'tb-save-widget-type-as-dialog', + templateUrl: './save-widget-type-as-dialog.component.html', + styleUrls: [], + standalone: false }) export class SaveWidgetTypeAsDialogComponent extends DialogComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/widget/select-widget-type-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/widget/select-widget-type-dialog.component.ts index c2c7195003..aec29b4ecd 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/select-widget-type-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/select-widget-type-dialog.component.ts @@ -23,9 +23,10 @@ import { Router } from '@angular/router'; import { widgetType, widgetTypesData } from '@shared/models/widget.models'; @Component({ - selector: 'tb-select-widget-type-dialog', - templateUrl: './select-widget-type-dialog.component.html', - styleUrls: ['./select-widget-type-dialog.component.scss'] + selector: 'tb-select-widget-type-dialog', + templateUrl: './select-widget-type-dialog.component.html', + styleUrls: ['./select-widget-type-dialog.component.scss'], + standalone: false }) export class SelectWidgetTypeDialogComponent extends DialogComponent { diff --git a/ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.ts b/ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.ts index 098cfce2f6..8504cc01d5 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.ts @@ -78,10 +78,11 @@ import Timeout = NodeJS.Timeout; // @dynamic @Component({ - selector: 'tb-widget-editor', - templateUrl: './widget-editor.component.html', - styleUrls: ['./widget-editor.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-widget-editor', + templateUrl: './widget-editor.component.html', + styleUrls: ['./widget-editor.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class WidgetEditorComponent extends PageComponent implements OnInit, OnDestroy, HasDirtyFlag { diff --git a/ui-ngx/src/app/modules/home/pages/widget/widget-type-autocomplete.component.ts b/ui-ngx/src/app/modules/home/pages/widget/widget-type-autocomplete.component.ts index e309e21d1d..04fd5af1cb 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widget-type-autocomplete.component.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/widget-type-autocomplete.component.ts @@ -37,15 +37,16 @@ import { coerceBoolean } from '@shared/decorators/coercion'; import { WidgetService } from '@core/http/widget.service'; @Component({ - selector: 'tb-widget-type-autocomplete', - templateUrl: './widget-type-autocomplete.component.html', - styleUrls: ['./widget-type-autocomplete.component.scss'], - providers: [{ - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => WidgetTypeAutocompleteComponent), - multi: true - }], - encapsulation: ViewEncapsulation.None + selector: 'tb-widget-type-autocomplete', + templateUrl: './widget-type-autocomplete.component.html', + styleUrls: ['./widget-type-autocomplete.component.scss'], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => WidgetTypeAutocompleteComponent), + multi: true + }], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class WidgetTypeAutocompleteComponent implements ControlValueAccessor, OnInit, AfterViewInit { diff --git a/ui-ngx/src/app/modules/home/pages/widget/widget-type-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/widget/widget-type-tabs.component.ts index acee3159d2..0168bfb639 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widget-type-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/widget-type-tabs.component.ts @@ -22,9 +22,10 @@ import { NULL_UUID } from '@shared/models/id/has-uuid'; import { WidgetTypeDetails } from '@shared/models/widget.models'; @Component({ - selector: 'tb-widget-type-tabs', - templateUrl: './widget-type-tabs.component.html', - styleUrls: [] + selector: 'tb-widget-type-tabs', + templateUrl: './widget-type-tabs.component.html', + styleUrls: [], + standalone: false }) export class WidgetTypeTabsComponent extends EntityTabsComponent { diff --git a/ui-ngx/src/app/modules/home/pages/widget/widget-type.component.ts b/ui-ngx/src/app/modules/home/pages/widget/widget-type.component.ts index b765fadb1d..c6911e287e 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widget-type.component.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/widget-type.component.ts @@ -24,9 +24,10 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.mod import { WidgetTypeDetails } from '@shared/models/widget.models'; @Component({ - selector: 'tb-widget-type', - templateUrl: './widget-type.component.html', - styleUrls: [] + selector: 'tb-widget-type', + templateUrl: './widget-type.component.html', + styleUrls: [], + standalone: false }) export class WidgetTypeComponent extends EntityComponent { diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.ts index 5e2e4e0c4d..c493ba032d 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.ts @@ -31,10 +31,11 @@ export interface WidgetsBundleDialogData { } @Component({ - selector: 'tb-widgets-bundle-dialog', - templateUrl: './widgets-bundle-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: WidgetsBundleDialogComponent}], - styleUrls: ['widgets-bundle-dialog.component.scss'] + selector: 'tb-widgets-bundle-dialog', + templateUrl: './widgets-bundle-dialog.component.html', + providers: [{ provide: ErrorStateMatcher, useExisting: WidgetsBundleDialogComponent }], + styleUrls: ['widgets-bundle-dialog.component.scss'], + standalone: false }) export class WidgetsBundleDialogComponent extends DialogComponent implements ErrorStateMatcher { diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-tabs.component.ts index 5a684bc031..6e569ff701 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-tabs.component.ts @@ -22,9 +22,10 @@ import { WidgetsBundle } from '@shared/models/widgets-bundle.model'; import { NULL_UUID } from '@shared/models/id/has-uuid'; @Component({ - selector: 'tb-widgets-bundle-tabs', - templateUrl: './widgets-bundle-tabs.component.html', - styleUrls: [] + selector: 'tb-widgets-bundle-tabs', + templateUrl: './widgets-bundle-tabs.component.html', + styleUrls: [], + standalone: false }) export class WidgetsBundleTabsComponent extends EntityTabsComponent { diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-widgets.component.ts b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-widgets.component.ts index 7eb3afddc6..50cf6b9ef7 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-widgets.component.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-widgets.component.ts @@ -36,9 +36,10 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; type WidgetTypeBundle = WithOptional; @Component({ - selector: 'tb-widgets-bundle-widget', - templateUrl: './widgets-bundle-widgets.component.html', - styleUrls: ['./widgets-bundle-widgets.component.scss'] + selector: 'tb-widgets-bundle-widget', + templateUrl: './widgets-bundle-widgets.component.html', + styleUrls: ['./widgets-bundle-widgets.component.scss'], + standalone: false }) export class WidgetsBundleWidgetsComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.ts b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.ts index 1ccabc8050..bbfe6cb90e 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.ts @@ -23,9 +23,10 @@ import { WidgetsBundle } from '@shared/models/widgets-bundle.model'; import { EntityTableConfig } from '@home/models/entity/entities-table-config.models'; @Component({ - selector: 'tb-widgets-bundle', - templateUrl: './widgets-bundle.component.html', - styleUrls: ['./widgets-bundle.component.scss'] + selector: 'tb-widgets-bundle', + templateUrl: './widgets-bundle.component.html', + styleUrls: ['./widgets-bundle.component.scss'], + standalone: false }) export class WidgetsBundleComponent extends EntityComponent { diff --git a/ui-ngx/src/app/modules/login/pages/login/create-password.component.ts b/ui-ngx/src/app/modules/login/pages/login/create-password.component.ts index 27c72dd6f4..cfc57d3bb6 100644 --- a/ui-ngx/src/app/modules/login/pages/login/create-password.component.ts +++ b/ui-ngx/src/app/modules/login/pages/login/create-password.component.ts @@ -26,9 +26,10 @@ import { ActivatedRoute } from '@angular/router'; import { Subscription } from 'rxjs'; @Component({ - selector: 'tb-create-password', - templateUrl: './create-password.component.html', - styleUrls: ['./create-password.component.scss'] + selector: 'tb-create-password', + templateUrl: './create-password.component.html', + styleUrls: ['./create-password.component.scss'], + standalone: false }) export class CreatePasswordComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/login/pages/login/link-expired.component.ts b/ui-ngx/src/app/modules/login/pages/login/link-expired.component.ts index 0278dbb232..9b927b7c7a 100644 --- a/ui-ngx/src/app/modules/login/pages/login/link-expired.component.ts +++ b/ui-ngx/src/app/modules/login/pages/login/link-expired.component.ts @@ -21,9 +21,10 @@ import { PageComponent } from '@shared/components/page.component'; import { ActivatedRoute, Router } from '@angular/router'; @Component({ - selector: 'tb-link-expired', - templateUrl: './link-expired.component.html', - styleUrls: ['./link-expired.component.scss'] + selector: 'tb-link-expired', + templateUrl: './link-expired.component.html', + styleUrls: ['./link-expired.component.scss'], + standalone: false }) export class LinkExpiredComponent extends PageComponent { diff --git a/ui-ngx/src/app/modules/login/pages/login/login.component.ts b/ui-ngx/src/app/modules/login/pages/login/login.component.ts index 51d85eb69b..afe029791b 100644 --- a/ui-ngx/src/app/modules/login/pages/login/login.component.ts +++ b/ui-ngx/src/app/modules/login/pages/login/login.component.ts @@ -27,9 +27,10 @@ import { OAuth2ClientLoginInfo } from '@shared/models/oauth2.models'; import { validateEmail } from '@app/core/utils'; @Component({ - selector: 'tb-login', - templateUrl: './login.component.html', - styleUrls: ['./login.component.scss'] + selector: 'tb-login', + templateUrl: './login.component.html', + styleUrls: ['./login.component.scss'], + standalone: false }) export class LoginComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/login/pages/login/reset-password-request.component.ts b/ui-ngx/src/app/modules/login/pages/login/reset-password-request.component.ts index e96e44cedf..f59b4b3632 100644 --- a/ui-ngx/src/app/modules/login/pages/login/reset-password-request.component.ts +++ b/ui-ngx/src/app/modules/login/pages/login/reset-password-request.component.ts @@ -25,9 +25,10 @@ import { TranslateService } from '@ngx-translate/core'; import { validateEmail } from '@app/core/utils'; @Component({ - selector: 'tb-reset-password-request', - templateUrl: './reset-password-request.component.html', - styleUrls: ['./reset-password-request.component.scss'] + selector: 'tb-reset-password-request', + templateUrl: './reset-password-request.component.html', + styleUrls: ['./reset-password-request.component.scss'], + standalone: false }) export class ResetPasswordRequestComponent extends PageComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/login/pages/login/reset-password.component.ts b/ui-ngx/src/app/modules/login/pages/login/reset-password.component.ts index 225421810a..ce90ec829f 100644 --- a/ui-ngx/src/app/modules/login/pages/login/reset-password.component.ts +++ b/ui-ngx/src/app/modules/login/pages/login/reset-password.component.ts @@ -26,9 +26,10 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Subscription } from 'rxjs'; @Component({ - selector: 'tb-reset-password', - templateUrl: './reset-password.component.html', - styleUrls: ['./reset-password.component.scss'] + selector: 'tb-reset-password', + templateUrl: './reset-password.component.html', + styleUrls: ['./reset-password.component.scss'], + standalone: false }) export class ResetPasswordComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/modules/login/pages/login/two-factor-auth-login.component.ts b/ui-ngx/src/app/modules/login/pages/login/two-factor-auth-login.component.ts index b4b2e896ac..856374fe27 100644 --- a/ui-ngx/src/app/modules/login/pages/login/two-factor-auth-login.component.ts +++ b/ui-ngx/src/app/modules/login/pages/login/two-factor-auth-login.component.ts @@ -32,9 +32,10 @@ import { isEqual } from '@core/utils'; import { ActionNotificationShow } from '@core/notification/notification.actions'; @Component({ - selector: 'tb-two-factor-auth-login', - templateUrl: './two-factor-auth-login.component.html', - styleUrls: ['./two-factor-auth-login.component.scss'] + selector: 'tb-two-factor-auth-login', + templateUrl: './two-factor-auth-login.component.html', + styleUrls: ['./two-factor-auth-login.component.scss'], + standalone: false }) export class TwoFactorAuthLoginComponent extends PageComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/shared/components/breadcrumb.component.ts b/ui-ngx/src/app/shared/components/breadcrumb.component.ts index 858bd20370..75603fc9cb 100644 --- a/ui-ngx/src/app/shared/components/breadcrumb.component.ts +++ b/ui-ngx/src/app/shared/components/breadcrumb.component.ts @@ -28,10 +28,11 @@ import { MenuSection, menuSectionMap } from '@core/services/menu.models'; import { MenuService } from '@core/services/menu.service'; @Component({ - selector: 'tb-breadcrumb', - templateUrl: './breadcrumb.component.html', - styleUrls: ['./breadcrumb.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'tb-breadcrumb', + templateUrl: './breadcrumb.component.html', + styleUrls: ['./breadcrumb.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: false }) export class BreadcrumbComponent implements OnInit, OnDestroy { diff --git a/ui-ngx/src/app/shared/components/button/copy-button.component.ts b/ui-ngx/src/app/shared/components/button/copy-button.component.ts index 6f2573ccbd..9f5617a4da 100644 --- a/ui-ngx/src/app/shared/components/button/copy-button.component.ts +++ b/ui-ngx/src/app/shared/components/button/copy-button.component.ts @@ -22,9 +22,10 @@ import { ThemePalette } from '@angular/material/core'; import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ - selector: 'tb-copy-button', - styleUrls: ['copy-button.component.scss'], - templateUrl: './copy-button.component.html' + selector: 'tb-copy-button', + styleUrls: ['copy-button.component.scss'], + templateUrl: './copy-button.component.html', + standalone: false }) export class CopyButtonComponent { diff --git a/ui-ngx/src/app/shared/components/button/toggle-password.component.ts b/ui-ngx/src/app/shared/components/button/toggle-password.component.ts index 28ba243e1e..b3a1ca1e70 100644 --- a/ui-ngx/src/app/shared/components/button/toggle-password.component.ts +++ b/ui-ngx/src/app/shared/components/button/toggle-password.component.ts @@ -17,9 +17,10 @@ import { AfterViewInit, Component, ElementRef } from '@angular/core'; @Component({ - selector: 'tb-toggle-password', - templateUrl: 'toggle-password.component.html', - styleUrls: [], + selector: 'tb-toggle-password', + templateUrl: 'toggle-password.component.html', + styleUrls: [], + standalone: false }) export class TogglePasswordComponent implements AfterViewInit { showPassword = false; diff --git a/ui-ngx/src/app/shared/components/button/widget-button-toggle.component.ts b/ui-ngx/src/app/shared/components/button/widget-button-toggle.component.ts index 62d3d9ff0c..488afa9a81 100644 --- a/ui-ngx/src/app/shared/components/button/widget-button-toggle.component.ts +++ b/ui-ngx/src/app/shared/components/button/widget-button-toggle.component.ts @@ -46,9 +46,10 @@ const initialButtonHeight = 60; const horizontalLayoutPadding = 10; @Component({ - selector: 'tb-widget-button-toggle', - templateUrl: './widget-button-toggle.component.html', - styleUrls: ['./widget-button-toggle.component.scss'] + selector: 'tb-widget-button-toggle', + templateUrl: './widget-button-toggle.component.html', + styleUrls: ['./widget-button-toggle.component.scss'], + standalone: false }) export class WidgetButtonToggleComponent implements OnInit, AfterViewInit, OnDestroy, OnChanges { diff --git a/ui-ngx/src/app/shared/components/button/widget-button.component.ts b/ui-ngx/src/app/shared/components/button/widget-button.component.ts index 213b5c2a47..7c4ef584d5 100644 --- a/ui-ngx/src/app/shared/components/button/widget-button.component.ts +++ b/ui-ngx/src/app/shared/components/button/widget-button.component.ts @@ -45,10 +45,11 @@ const horizontalLayoutPadding = 24; const verticalLayoutPadding = 16; @Component({ - selector: 'tb-widget-button', - templateUrl: './widget-button.component.html', - styleUrls: ['./widget-button.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'tb-widget-button', + templateUrl: './widget-button.component.html', + styleUrls: ['./widget-button.component.scss'], + encapsulation: ViewEncapsulation.None, + standalone: false }) export class WidgetButtonComponent implements OnInit, AfterViewInit, OnDestroy, OnChanges { diff --git a/ui-ngx/src/app/shared/components/cheatsheet.component.ts b/ui-ngx/src/app/shared/components/cheatsheet.component.ts index 93ae5c87b1..00fe6e5790 100644 --- a/ui-ngx/src/app/shared/components/cheatsheet.component.ts +++ b/ui-ngx/src/app/shared/components/cheatsheet.component.ts @@ -20,8 +20,8 @@ import { MousetrapInstance } from 'mousetrap'; import Mousetrap from 'mousetrap'; @Component({ - selector : 'tb-hotkeys-cheatsheet', - styles : [` + selector: 'tb-hotkeys-cheatsheet', + styles: [` .tb-hotkeys-container { display: table !important; position: fixed; @@ -114,7 +114,7 @@ import Mousetrap from 'mousetrap'; font-size: 1.2em; } } `], - template : `
diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.html b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.html index eda38cfa13..d738e0447a 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.html @@ -34,7 +34,7 @@
diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-instances.component.html b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-instances.component.html index b88cd297ce..f432533614 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-instances.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-instances.component.html @@ -30,7 +30,7 @@
-
+
-
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.html index ff3d709352..0cc88f5404 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.html @@ -20,7 +20,7 @@
-
+
{{ icon }}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-add-dialog.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-add-dialog.component.html index c1caf24348..1b5b3f1992 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-add-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/persistent-add-dialog.component.html @@ -39,10 +39,10 @@ widgets.persistent-table.method - + {{'widgets.persistent-table.method-error' | translate}} - + {{'widgets.persistent-table.white-space-error' | translate}} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.html index 5a8715adf9..b54bc91b6f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.html @@ -20,7 +20,7 @@
-
+
{{ icon }} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-appearance.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-appearance.component.html index 5c2ceca5f1..133e6f3f29 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-appearance.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-appearance.component.html @@ -90,7 +90,7 @@
{{ widgetButtonStateTranslationMap.get(state) | translate }}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-action-button-row.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-action-button-row.component.html index 63f59f169c..421d518a90 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-action-button-row.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-action-button-row.component.html @@ -27,7 +27,7 @@ warning - + widgets.maps.data-layer.tooltip-tag-actions
-
diff --git a/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.html b/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.html index 0ad5814a81..ef80df1e9a 100644 --- a/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.html @@ -108,7 +108,7 @@ color="primary" *ngIf="showNext" [disabled]="(isLoading$ | async)" - (click)="nextStep()">{{ 'action.next-with-label' | translate:{label: (getFormLabel(this.selectedIndex+1) | translate)} }} + (click)="nextStep()">{{ 'action.next-with-label' | translate:{label: (getFormLabel(selectedIndex+1) | translate)} }}
diff --git a/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.html b/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.html index ebbab8f20f..27433a3f2f 100644 --- a/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.html +++ b/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.html @@ -45,8 +45,8 @@
diff --git a/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-bundle-dialog.component.html b/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-bundle-dialog.component.html index 9aa4fa60c6..3845e417b0 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-bundle-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-bundle-dialog.component.html @@ -89,7 +89,7 @@ labelText="{{ 'admin.oauth2.clients' | translate }}" placeholderText="{{ 'admin.oauth2.add-client' | translate }}"> diff --git a/ui-ngx/src/app/modules/home/pages/ota-update/ota-update.component.html b/ui-ngx/src/app/modules/home/pages/ota-update/ota-update.component.html index 131ea43496..45478969f8 100644 --- a/ui-ngx/src/app/modules/home/pages/ota-update/ota-update.component.html +++ b/ui-ngx/src/app/modules/home/pages/ota-update/ota-update.component.html @@ -130,7 +130,7 @@
+ *ngIf="!(isAdd && entityForm.get('generateChecksum').value)"> ota-update.checksum-algorithm diff --git a/ui-ngx/src/app/modules/login/pages/login/reset-password-request.component.html b/ui-ngx/src/app/modules/login/pages/login/reset-password-request.component.html index e71f67fe7b..0314975b36 100644 --- a/ui-ngx/src/app/modules/login/pages/login/reset-password-request.component.html +++ b/ui-ngx/src/app/modules/login/pages/login/reset-password-request.component.html @@ -40,7 +40,7 @@
-