Merge branch 'rc' of github.com:thingsboard/thingsboard into cf-fixes
This commit is contained in:
commit
5ee6d41f77
@ -30,13 +30,12 @@ import org.thingsboard.server.common.msg.queue.TbCallback;
|
||||
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.CalculatedFieldStateProto;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCalculatedFieldMsg;
|
||||
import org.thingsboard.server.queue.TbQueueAdmin;
|
||||
import org.thingsboard.server.queue.TbQueueCallback;
|
||||
import org.thingsboard.server.queue.TbQueueMsgHeaders;
|
||||
import org.thingsboard.server.queue.TbQueueMsgMetadata;
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
|
||||
import org.thingsboard.server.queue.common.state.KafkaQueueStateService;
|
||||
import org.thingsboard.server.queue.common.consumer.PartitionedQueueConsumerManager;
|
||||
import org.thingsboard.server.queue.common.state.KafkaQueueStateService;
|
||||
import org.thingsboard.server.queue.discovery.PartitionService;
|
||||
import org.thingsboard.server.queue.discovery.QueueKey;
|
||||
import org.thingsboard.server.queue.kafka.TbKafkaProducerTemplate;
|
||||
@ -59,7 +58,6 @@ public class KafkaCalculatedFieldStateService extends AbstractCalculatedFieldSta
|
||||
|
||||
private final TbRuleEngineQueueFactory queueFactory;
|
||||
private final PartitionService partitionService;
|
||||
private final TbQueueAdmin queueAdmin;
|
||||
|
||||
@Value("${queue.calculated_fields.poll_interval:25}")
|
||||
private long pollInterval;
|
||||
@ -94,7 +92,7 @@ public class KafkaCalculatedFieldStateService extends AbstractCalculatedFieldSta
|
||||
}
|
||||
})
|
||||
.consumerCreator((config, partitionId) -> queueFactory.createCalculatedFieldStateConsumer())
|
||||
.queueAdmin(queueAdmin)
|
||||
.queueAdmin(queueFactory.getCalculatedFieldQueueAdmin())
|
||||
.consumerExecutor(eventConsumer.getConsumerExecutor())
|
||||
.scheduler(eventConsumer.getScheduler())
|
||||
.taskExecutor(eventConsumer.getTaskExecutor())
|
||||
|
||||
@ -42,7 +42,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.CalculatedFieldLinke
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.CalculatedFieldTelemetryMsgProto;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCalculatedFieldMsg;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCalculatedFieldNotificationMsg;
|
||||
import org.thingsboard.server.queue.TbQueueAdmin;
|
||||
import org.thingsboard.server.queue.TbQueueConsumer;
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
|
||||
import org.thingsboard.server.queue.common.consumer.PartitionedQueueConsumerManager;
|
||||
@ -81,7 +80,6 @@ public class DefaultTbCalculatedFieldConsumerService extends AbstractConsumerSer
|
||||
private long packProcessingTimeout;
|
||||
|
||||
private final TbRuleEngineQueueFactory queueFactory;
|
||||
private final TbQueueAdmin queueAdmin;
|
||||
private final CalculatedFieldStateService stateService;
|
||||
|
||||
public DefaultTbCalculatedFieldConsumerService(TbRuleEngineQueueFactory tbQueueFactory,
|
||||
@ -94,12 +92,10 @@ public class DefaultTbCalculatedFieldConsumerService extends AbstractConsumerSer
|
||||
ApplicationEventPublisher eventPublisher,
|
||||
JwtSettingsService jwtSettingsService,
|
||||
CalculatedFieldCache calculatedFieldCache,
|
||||
TbQueueAdmin queueAdmin,
|
||||
CalculatedFieldStateService stateService) {
|
||||
super(actorContext, tenantProfileCache, deviceProfileCache, assetProfileCache, calculatedFieldCache, apiUsageStateService, partitionService,
|
||||
eventPublisher, jwtSettingsService);
|
||||
this.queueFactory = tbQueueFactory;
|
||||
this.queueAdmin = queueAdmin;
|
||||
this.stateService = stateService;
|
||||
}
|
||||
|
||||
@ -114,7 +110,7 @@ public class DefaultTbCalculatedFieldConsumerService extends AbstractConsumerSer
|
||||
.pollInterval(pollInterval)
|
||||
.msgPackProcessor(this::processMsgs)
|
||||
.consumerCreator((config, partitionId) -> queueFactory.createToCalculatedFieldMsgConsumer())
|
||||
.queueAdmin(queueAdmin)
|
||||
.queueAdmin(queueFactory.getCalculatedFieldQueueAdmin())
|
||||
.consumerExecutor(consumersExecutor)
|
||||
.scheduler(scheduler)
|
||||
.taskExecutor(mgmtExecutor)
|
||||
|
||||
@ -121,14 +121,14 @@ public class AssetProfileEdgeTest extends AbstractEdgeTest {
|
||||
Assert.assertNull(assetProfile.getDefaultRuleChainId());
|
||||
Assert.assertEquals(edgeRuleChainId, assetProfile.getDefaultEdgeRuleChainId());
|
||||
|
||||
// delete profile
|
||||
edgeImitator.expectMessageAmount(1);
|
||||
// delete profile and delete relation messages
|
||||
edgeImitator.expectMessageAmount(2);
|
||||
doDelete("/api/assetProfile/" + assetProfile.getUuidId())
|
||||
.andExpect(status().isOk());
|
||||
Assert.assertTrue(edgeImitator.waitForMessages());
|
||||
AbstractMessage latestMessage = edgeImitator.getLatestMessage();
|
||||
Assert.assertTrue(latestMessage instanceof AssetProfileUpdateMsg);
|
||||
AssetProfileUpdateMsg assetProfileUpdateMsg = (AssetProfileUpdateMsg) latestMessage;
|
||||
Optional<AssetProfileUpdateMsg> assetDeleteMsgOpt = edgeImitator.findMessageByType(AssetProfileUpdateMsg.class);
|
||||
Assert.assertTrue(assetDeleteMsgOpt.isPresent());
|
||||
AssetProfileUpdateMsg assetProfileUpdateMsg = assetDeleteMsgOpt.get();
|
||||
Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, assetProfileUpdateMsg.getMsgType());
|
||||
Assert.assertEquals(assetProfile.getUuidId().getMostSignificantBits(), assetProfileUpdateMsg.getIdMSB());
|
||||
Assert.assertEquals(assetProfile.getUuidId().getLeastSignificantBits(), assetProfileUpdateMsg.getIdLSB());
|
||||
|
||||
@ -327,14 +327,14 @@ public class DeviceProfileEdgeTest extends AbstractEdgeTest {
|
||||
Assert.assertNotNull(deviceProfile);
|
||||
Assert.assertEquals("Device Profile On Edge", deviceProfile.getName());
|
||||
|
||||
// delete profile
|
||||
edgeImitator.expectMessageAmount(1);
|
||||
// delete profile and delete relation messages
|
||||
edgeImitator.expectMessageAmount(2);
|
||||
doDelete("/api/deviceProfile/" + deviceProfile.getUuidId())
|
||||
.andExpect(status().isOk());
|
||||
Assert.assertTrue(edgeImitator.waitForMessages());
|
||||
AbstractMessage latestMessage = edgeImitator.getLatestMessage();
|
||||
Assert.assertTrue(latestMessage instanceof DeviceProfileUpdateMsg);
|
||||
DeviceProfileUpdateMsg deviceProfileUpdateMsg = (DeviceProfileUpdateMsg) latestMessage;
|
||||
Optional<DeviceProfileUpdateMsg> deviceDeleteMsgOpt = edgeImitator.findMessageByType(DeviceProfileUpdateMsg.class);
|
||||
Assert.assertTrue(deviceDeleteMsgOpt.isPresent());
|
||||
DeviceProfileUpdateMsg deviceProfileUpdateMsg = deviceDeleteMsgOpt.get();
|
||||
Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, deviceProfileUpdateMsg.getMsgType());
|
||||
Assert.assertEquals(deviceProfile.getUuidId().getMostSignificantBits(), deviceProfileUpdateMsg.getIdMSB());
|
||||
Assert.assertEquals(deviceProfile.getUuidId().getLeastSignificantBits(), deviceProfileUpdateMsg.getIdLSB());
|
||||
|
||||
@ -53,7 +53,6 @@ import org.thingsboard.server.gen.transport.TransportProtos;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.EdqsEventMsg;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.FromEdqsMsg;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdqsMsg;
|
||||
import org.thingsboard.server.queue.TbQueueAdmin;
|
||||
import org.thingsboard.server.queue.TbQueueHandler;
|
||||
import org.thingsboard.server.queue.TbQueueResponseTemplate;
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
|
||||
@ -92,7 +91,6 @@ public class EdqsProcessor implements TbQueueHandler<TbProtoQueueMsg<ToEdqsMsg>,
|
||||
private final EdqsPartitionService partitionService;
|
||||
private final ConfigurableApplicationContext applicationContext;
|
||||
private final EdqsStateService stateService;
|
||||
private final TbQueueAdmin queueAdmin;
|
||||
|
||||
private PartitionedQueueConsumerManager<TbProtoQueueMsg<ToEdqsMsg>> eventConsumer;
|
||||
private TbQueueResponseTemplate<TbProtoQueueMsg<ToEdqsMsg>, TbProtoQueueMsg<FromEdqsMsg>> responseTemplate;
|
||||
@ -143,7 +141,7 @@ public class EdqsProcessor implements TbQueueHandler<TbProtoQueueMsg<ToEdqsMsg>,
|
||||
consumer.commit();
|
||||
})
|
||||
.consumerCreator((config, partitionId) -> queueFactory.createEdqsMsgConsumer(EdqsQueue.EVENTS))
|
||||
.queueAdmin(queueAdmin)
|
||||
.queueAdmin(queueFactory.getEdqsQueueAdmin())
|
||||
.consumerExecutor(consumersExecutor)
|
||||
.taskExecutor(taskExecutor)
|
||||
.scheduler(scheduler)
|
||||
|
||||
@ -30,7 +30,6 @@ import org.thingsboard.server.edqs.processor.EdqsProducer;
|
||||
import org.thingsboard.server.edqs.util.VersionsStore;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.EdqsEventMsg;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdqsMsg;
|
||||
import org.thingsboard.server.queue.TbQueueAdmin;
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
|
||||
import org.thingsboard.server.queue.common.consumer.PartitionedQueueConsumerManager;
|
||||
import org.thingsboard.server.queue.common.consumer.QueueConsumerManager;
|
||||
@ -56,7 +55,6 @@ public class KafkaEdqsStateService implements EdqsStateService {
|
||||
private final EdqsConfig config;
|
||||
private final EdqsPartitionService partitionService;
|
||||
private final EdqsQueueFactory queueFactory;
|
||||
private final TbQueueAdmin queueAdmin;
|
||||
private final TopicService topicService;
|
||||
@Autowired @Lazy
|
||||
private EdqsProcessor edqsProcessor;
|
||||
@ -92,7 +90,7 @@ public class KafkaEdqsStateService implements EdqsStateService {
|
||||
consumer.commit();
|
||||
})
|
||||
.consumerCreator((config, partitionId) -> queueFactory.createEdqsMsgConsumer(EdqsQueue.STATE))
|
||||
.queueAdmin(queueAdmin)
|
||||
.queueAdmin(queueFactory.getEdqsQueueAdmin())
|
||||
.consumerExecutor(eventConsumer.getConsumerExecutor())
|
||||
.taskExecutor(eventConsumer.getTaskExecutor())
|
||||
.scheduler(eventConsumer.getScheduler())
|
||||
|
||||
@ -17,6 +17,7 @@ package org.thingsboard.server.queue.edqs;
|
||||
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.FromEdqsMsg;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdqsMsg;
|
||||
import org.thingsboard.server.queue.TbQueueAdmin;
|
||||
import org.thingsboard.server.queue.TbQueueConsumer;
|
||||
import org.thingsboard.server.queue.TbQueueProducer;
|
||||
import org.thingsboard.server.queue.TbQueueResponseTemplate;
|
||||
@ -32,4 +33,6 @@ public interface EdqsQueueFactory {
|
||||
|
||||
TbQueueResponseTemplate<TbProtoQueueMsg<ToEdqsMsg>, TbProtoQueueMsg<FromEdqsMsg>> createEdqsResponseTemplate();
|
||||
|
||||
TbQueueAdmin getEdqsQueueAdmin();
|
||||
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ import org.thingsboard.server.common.stats.StatsFactory;
|
||||
import org.thingsboard.server.common.stats.StatsType;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.FromEdqsMsg;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdqsMsg;
|
||||
import org.thingsboard.server.queue.TbQueueAdmin;
|
||||
import org.thingsboard.server.queue.TbQueueConsumer;
|
||||
import org.thingsboard.server.queue.TbQueueProducer;
|
||||
import org.thingsboard.server.queue.TbQueueResponseTemplate;
|
||||
@ -39,6 +40,7 @@ public class InMemoryEdqsQueueFactory implements EdqsQueueFactory {
|
||||
private final InMemoryStorage storage;
|
||||
private final EdqsConfig edqsConfig;
|
||||
private final StatsFactory statsFactory;
|
||||
private final TbQueueAdmin queueAdmin;
|
||||
|
||||
@Override
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdqsMsg>> createEdqsMsgConsumer(EdqsQueue queue) {
|
||||
@ -76,4 +78,9 @@ public class InMemoryEdqsQueueFactory implements EdqsQueueFactory {
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TbQueueAdmin getEdqsQueueAdmin() {
|
||||
return queueAdmin;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ import org.thingsboard.server.common.stats.StatsType;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.FromEdqsMsg;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdqsMsg;
|
||||
import org.thingsboard.server.queue.TbQueueAdmin;
|
||||
import org.thingsboard.server.queue.TbQueueConsumer;
|
||||
import org.thingsboard.server.queue.TbQueueProducer;
|
||||
import org.thingsboard.server.queue.TbQueueResponseTemplate;
|
||||
@ -126,4 +127,9 @@ public class KafkaEdqsQueueFactory implements EdqsQueueFactory {
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TbQueueAdmin getEdqsQueueAdmin() {
|
||||
return edqsEventsAdmin;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -160,7 +160,7 @@ public class TbKafkaConsumerTemplate<T extends TbQueueMsg> extends AbstractTbQue
|
||||
int partition = record.partition();
|
||||
Long endOffset = endOffsets.get(partition);
|
||||
if (endOffset == null) {
|
||||
log.warn("End offset not found for {} [{}]", record.topic(), partition);
|
||||
log.debug("End offset not found for {} [{}]", record.topic(), partition);
|
||||
return;
|
||||
}
|
||||
log.trace("[{}-{}] Got record offset {}, expected end offset: {}", record.topic(), partition, record.offset(), endOffset - 1);
|
||||
|
||||
@ -138,6 +138,11 @@ public class InMemoryMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE
|
||||
return new InMemoryTbQueueConsumer<>(storage, topicService.buildTopicName(calculatedFieldSettings.getEventTopic()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TbQueueAdmin getCalculatedFieldQueueAdmin() {
|
||||
return queueAdmin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToCalculatedFieldMsg>> createToCalculatedFieldMsgProducer() {
|
||||
return new InMemoryTbQueueProducer<>(storage, topicService.buildTopicName(calculatedFieldSettings.getEventTopic()));
|
||||
|
||||
@ -526,6 +526,11 @@ public class KafkaMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngi
|
||||
return consumerBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TbQueueAdmin getCalculatedFieldQueueAdmin() {
|
||||
return cfAdmin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCalculatedFieldMsg>> createToCalculatedFieldMsgProducer() {
|
||||
TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder<TbProtoQueueMsg<ToCalculatedFieldMsg>> requestBuilder = TbKafkaProducerTemplate.builder();
|
||||
|
||||
@ -321,6 +321,11 @@ public class KafkaTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory {
|
||||
return consumerBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TbQueueAdmin getCalculatedFieldQueueAdmin() {
|
||||
return cfAdmin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCalculatedFieldMsg>> createToCalculatedFieldMsgProducer() {
|
||||
TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder<TbProtoQueueMsg<ToCalculatedFieldMsg>> requestBuilder = TbKafkaProducerTemplate.builder();
|
||||
|
||||
@ -29,6 +29,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateSer
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
|
||||
import org.thingsboard.server.queue.TbQueueAdmin;
|
||||
import org.thingsboard.server.queue.TbQueueConsumer;
|
||||
import org.thingsboard.server.queue.TbQueueProducer;
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate;
|
||||
@ -122,6 +123,8 @@ public interface TbRuleEngineQueueFactory extends TbUsageStatsClientQueueFactory
|
||||
|
||||
TbQueueConsumer<TbProtoQueueMsg<ToCalculatedFieldMsg>> createToCalculatedFieldMsgConsumer();
|
||||
|
||||
TbQueueAdmin getCalculatedFieldQueueAdmin();
|
||||
|
||||
TbQueueProducer<TbProtoQueueMsg<ToCalculatedFieldMsg>> createToCalculatedFieldMsgProducer();
|
||||
|
||||
TbQueueConsumer<TbProtoQueueMsg<ToCalculatedFieldNotificationMsg>> createToCalculatedFieldNotificationMsgConsumer();
|
||||
|
||||
@ -195,7 +195,9 @@ public class BaseTimeseriesService implements TimeseriesService {
|
||||
}
|
||||
if (saveLatest) {
|
||||
latestFutures.add(Futures.transform(timeseriesLatestDao.saveLatest(tenantId, entityId, tsKvEntry), version -> {
|
||||
if (version != null) {
|
||||
edqsService.onUpdate(tenantId, ObjectType.LATEST_TS_KV, new LatestTsKv(entityId, tsKvEntry, version));
|
||||
}
|
||||
return version;
|
||||
}, MoreExecutors.directExecutor()));
|
||||
}
|
||||
|
||||
@ -15,17 +15,15 @@
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
<div class="flex max-w-sm flex-col gap-3 p-2">
|
||||
<div class="flex w-96 flex-col gap-3 p-2">
|
||||
<div class="tb-form-panel-title" translate>debug-settings.label</div>
|
||||
@if (debugLimitsConfiguration) {
|
||||
<div class="hint-container">
|
||||
<div class="tb-form-hint tb-primary-fill tb-flex center">
|
||||
@if (debugLimitsConfiguration) {
|
||||
{{ 'debug-settings.hint.main-limited' | translate: { entity: entityLabel ?? ('debug-settings.entity' | translate), msg: maxMessagesCount, time: (maxTimeFrameDuration | milliSecondsToTimeString: true : true) } }}
|
||||
} @else {
|
||||
{{ 'debug-settings.hint.main' | translate }}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-3">
|
||||
<mat-slide-toggle class="mat-slide" [formControl]="onFailuresControl">
|
||||
<div tb-hint-tooltip-icon="{{ 'debug-settings.hint.on-failure' | translate }}">
|
||||
@ -33,12 +31,12 @@
|
||||
</div>
|
||||
</mat-slide-toggle>
|
||||
<div class="align-center flex justify-between">
|
||||
<mat-slide-toggle class="mat-slide" [formControl]="debugAllControl">
|
||||
<mat-slide-toggle class="mat-slide" [formControl]="debugAllControl" (change)="debugAllControl.markAsTouched()">
|
||||
<div tb-hint-tooltip-icon="{{ 'debug-settings.hint.all-messages' | translate }}">
|
||||
{{ 'debug-settings.all-messages' | translate: { time: (isDebugAllActive$ | async) && !allEnabled ? (allEnabledUntil | durationLeft) : (maxDebugModeDuration | milliSecondsToTimeString: true : true) } }}
|
||||
{{ 'debug-settings.all-messages' | translate: { time: (isDebugAllActive$ | async) && !allEnabled && debugAllControl.untouched ? (allEnabledUntil | durationLeft) : (maxDebugModeDuration | milliSecondsToTimeString: true : true) } }}
|
||||
</div>
|
||||
</mat-slide-toggle>
|
||||
<button mat-icon-button *ngIf="(isDebugAllActive$ | async) && !allEnabled"
|
||||
<button mat-icon-button *ngIf="(isDebugAllActive$ | async) && !allEnabled && debugAllControl.untouched"
|
||||
class="tb-mat-20"
|
||||
matTooltip="{{ 'action.reset' | translate }}"
|
||||
matTooltipPosition="above"
|
||||
|
||||
@ -127,19 +127,23 @@ export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDia
|
||||
actionSourceId: [this.action.actionSourceId, Validators.required],
|
||||
columnIndex: [{value: this.checkColumnIndex(this.action.columnIndex), disabled: true}, Validators.required],
|
||||
name: [this.action.name, [this.validateActionName(), Validators.required]],
|
||||
buttonType: [isDefinedAndNotNull(this.action.buttonType) ? this.action.buttonType : WidgetHeaderActionButtonType.icon, []],
|
||||
showIcon: [isDefinedAndNotNull(this.action.showIcon) ? this.action.showIcon : true, []],
|
||||
buttonType: [{ value: this.action.buttonType ?? WidgetHeaderActionButtonType.icon, disabled: true}, []],
|
||||
showIcon: [{ value: this.action.showIcon ?? true, disabled: true}, []],
|
||||
icon: [this.action.icon, Validators.required],
|
||||
buttonColor: [isDefinedAndNotNull(this.action.buttonColor) ? this.action.buttonColor : 'rgba(0, 0, 0, 0.87)', []],
|
||||
buttonFillColor: [isDefinedAndNotNull(this.action.buttonFillColor) ? this.action.buttonFillColor : '#3F52DD', []],
|
||||
buttonBorderColor: [isDefinedAndNotNull(this.action.buttonBorderColor) ? this.action.buttonBorderColor : '#3F52DD', []],
|
||||
customButtonStyle: [isDefinedAndNotNull(this.action.customButtonStyle) ? this.action.customButtonStyle : null, []],
|
||||
buttonColor: [{ value: this.action.buttonColor ?? 'rgba(0, 0, 0, 0.87)', disabled: true}, []],
|
||||
buttonFillColor: [{ value: this.action.buttonFillColor ?? '#3F52DD', disabled: true}, []],
|
||||
buttonBorderColor: [{ value: this.action.buttonBorderColor ?? '#3F52DD', disabled: true}, []],
|
||||
customButtonStyle: [{ value: this.action.customButtonStyle ?? {}, disabled: true}, []],
|
||||
useShowWidgetActionFunction: [this.action.useShowWidgetActionFunction],
|
||||
showWidgetActionFunction: [this.action.showWidgetActionFunction || 'return true;'],
|
||||
widgetAction: [actionDescriptorToAction(toWidgetActionDescriptor(this.action)), Validators.required]
|
||||
});
|
||||
this.updateShowWidgetActionForm();
|
||||
if (this.widgetActionFormGroup.get('actionSourceId').value === 'headerButton') {
|
||||
this.widgetActionFormGroup.get('buttonType').enable({emitEvent: false});
|
||||
this.widgetActionFormGroup.get('buttonColor').enable({emitEvent: false});
|
||||
this.widgetHeaderButtonValidators();
|
||||
}
|
||||
this.widgetActionFormGroup.get('actionSourceId').valueChanges.pipe(
|
||||
takeUntilDestroyed(this.destroyRef)
|
||||
).subscribe((value) => {
|
||||
@ -151,6 +155,17 @@ export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDia
|
||||
} else {
|
||||
this.widgetActionFormGroup.get('columnIndex').disable();
|
||||
}
|
||||
if (value === 'headerButton') {
|
||||
this.widgetActionFormGroup.get('buttonType').enable({emitEvent: false});
|
||||
this.widgetActionFormGroup.get('buttonColor').enable({emitEvent: false});
|
||||
this.widgetHeaderButtonValidators();
|
||||
} else {
|
||||
this.widgetActionFormGroup.get('buttonType').disable({emitEvent: false});
|
||||
this.widgetActionFormGroup.get('showIcon').disable({emitEvent: false});
|
||||
this.widgetActionFormGroup.get('buttonColor').disable({emitEvent: false});
|
||||
this.widgetActionFormGroup.get('buttonFillColor').disable({emitEvent: false});
|
||||
this.widgetActionFormGroup.get('buttonBorderColor').disable({emitEvent: false});
|
||||
}
|
||||
});
|
||||
this.widgetActionFormGroup.get('useShowWidgetActionFunction').valueChanges.pipe(
|
||||
takeUntilDestroyed(this.destroyRef)
|
||||
@ -185,10 +200,12 @@ export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDia
|
||||
this.widgetActionFormGroup.get('buttonFillColor').enable({emitEvent: false});
|
||||
break;
|
||||
case WidgetHeaderActionButtonType.stroked:
|
||||
this.widgetActionFormGroup.get('showIcon').enable({emitEvent: false});
|
||||
this.widgetActionFormGroup.get('buttonBorderColor').enable({emitEvent: false});
|
||||
break;
|
||||
case WidgetHeaderActionButtonType.flat:
|
||||
this.widgetActionFormGroup.get('showIcon').enable({emitEvent: false});
|
||||
this.widgetActionFormGroup.get('buttonFillColor').enable({emitEvent: false});
|
||||
this.widgetActionFormGroup.get('buttonBorderColor').enable({emitEvent: false});
|
||||
break;
|
||||
case WidgetHeaderActionButtonType.miniFab:
|
||||
this.widgetActionFormGroup.get('buttonFillColor').enable({emitEvent: false});
|
||||
|
||||
@ -109,11 +109,10 @@
|
||||
[style]="action.customButtonStyle"
|
||||
[class.!hidden]="isEdit"
|
||||
[class.mr-2]="!last"
|
||||
[style.background-color]="action.buttonFillColor"
|
||||
(click)="action.onAction($event)"
|
||||
matTooltip="{{ action.displayName }}"
|
||||
matTooltipPosition="above">
|
||||
<tb-icon [style.color]="action.buttonColor">{{ action.icon }}</tb-icon>
|
||||
<tb-icon>{{ action.icon }}</tb-icon>
|
||||
</button>
|
||||
}
|
||||
@case (widgetHeaderActionButtonType.basic) {
|
||||
@ -123,46 +122,41 @@
|
||||
(click)="action.onAction($event)"
|
||||
matTooltip="{{ action.displayName }}"
|
||||
matTooltipPosition="above">
|
||||
<tb-icon matButtonIcon *ngIf="action.showIcon" [style.color]="action.buttonColor">{{ action.icon }}</tb-icon>
|
||||
<span [style.color]="action.buttonColor">{{ action.displayName }}</span>
|
||||
<tb-icon matButtonIcon *ngIf="action.showIcon">{{ action.icon }}</tb-icon>
|
||||
<span>{{ action.displayName }}</span>
|
||||
</button>
|
||||
}
|
||||
@case (widgetHeaderActionButtonType.raised) {
|
||||
<button [class.!hidden]="isEdit" mat-raised-button
|
||||
[class.mr-2]="!last"
|
||||
[style]="action.customButtonStyle"
|
||||
[style.background-color]="action.buttonFillColor"
|
||||
(click)="action.onAction($event)"
|
||||
matTooltip="{{ action.displayName }}"
|
||||
matTooltipPosition="above">
|
||||
<tb-icon matButtonIcon *ngIf="action.showIcon" [style.color]="action.buttonColor">{{ action.icon }}</tb-icon>
|
||||
<span [style.color]="action.buttonColor">{{ action.displayName }}</span>
|
||||
<tb-icon matButtonIcon *ngIf="action.showIcon">{{ action.icon }}</tb-icon>
|
||||
<span>{{ action.displayName }}</span>
|
||||
</button>
|
||||
}
|
||||
@case (widgetHeaderActionButtonType.stroked) {
|
||||
<button [class.!hidden]="isEdit" mat-stroked-button
|
||||
[class.mr-2]="!last"
|
||||
[style]="action.customButtonStyle"
|
||||
[style.border-color]="action.buttonBorderColor"
|
||||
[style.background-color]="action.buttonFillColor"
|
||||
(click)="action.onAction($event)"
|
||||
matTooltip="{{ action.displayName }}"
|
||||
matTooltipPosition="above">
|
||||
<tb-icon matButtonIcon *ngIf="action.showIcon" [style.color]="action.buttonColor">{{ action.icon }}</tb-icon>
|
||||
<span [style.color]="action.buttonColor">{{ action.displayName }}</span>
|
||||
<tb-icon matButtonIcon *ngIf="action.showIcon">{{ action.icon }}</tb-icon>
|
||||
<span>{{ action.displayName }}</span>
|
||||
</button>
|
||||
}
|
||||
@case (widgetHeaderActionButtonType.flat) {
|
||||
<button [class.!hidden]="isEdit" mat-flat-button
|
||||
[class.mr-2]="!last"
|
||||
[style]="action.customButtonStyle"
|
||||
[style.background-color]="action.buttonFillColor"
|
||||
[style.border-color]="action.buttonBorderColor"
|
||||
(click)="action.onAction($event)"
|
||||
matTooltip="{{ action.displayName }}"
|
||||
matTooltipPosition="above">
|
||||
<tb-icon matButtonIcon *ngIf="action.showIcon" [style.color]="action.buttonColor">{{ action.icon }}</tb-icon>
|
||||
<span [style.color]="action.buttonColor">{{ action.displayName }}</span>
|
||||
<tb-icon matButtonIcon *ngIf="action.showIcon">{{ action.icon }}</tb-icon>
|
||||
<span>{{ action.displayName }}</span>
|
||||
</button>
|
||||
}
|
||||
@default {
|
||||
@ -172,7 +166,7 @@
|
||||
(click)="action.onAction($event)"
|
||||
matTooltip="{{ action.displayName }}"
|
||||
matTooltipPosition="above">
|
||||
<tb-icon [style.color]="action.buttonColor">{{ action.icon }}</tb-icon>
|
||||
<tb-icon>{{ action.icon }}</tb-icon>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,6 +44,7 @@ import {
|
||||
widgetActionSources,
|
||||
WidgetActionType,
|
||||
WidgetComparisonSettings,
|
||||
WidgetHeaderActionButtonType,
|
||||
WidgetMobileActionDescriptor,
|
||||
WidgetMobileActionType,
|
||||
WidgetResource,
|
||||
@ -301,10 +302,13 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
|
||||
buttonType: descriptor.buttonType,
|
||||
showIcon: descriptor.showIcon,
|
||||
icon: descriptor.icon,
|
||||
buttonColor: descriptor.buttonColor,
|
||||
buttonFillColor: descriptor.buttonFillColor,
|
||||
buttonBorderColor: descriptor.buttonBorderColor,
|
||||
customButtonStyle: descriptor.customButtonStyle,
|
||||
customButtonStyle: this.headerButtonStyle(
|
||||
descriptor.buttonType,
|
||||
descriptor.customButtonStyle,
|
||||
descriptor.buttonColor,
|
||||
descriptor.buttonFillColor,
|
||||
descriptor.buttonBorderColor
|
||||
),
|
||||
descriptor,
|
||||
useShowWidgetHeaderActionFunction,
|
||||
showWidgetHeaderActionFunction,
|
||||
@ -359,6 +363,39 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
|
||||
}
|
||||
}
|
||||
|
||||
headerButtonStyle(buttonType: WidgetHeaderActionButtonType = WidgetHeaderActionButtonType.icon,
|
||||
customButtonStyle:{[key: string]: string},
|
||||
buttonColor: string = 'rgba(0,0,0,0.87)',
|
||||
backgroundColor: string,
|
||||
borderColor: string) {
|
||||
const buttonStyle = {};
|
||||
switch (buttonType) {
|
||||
case WidgetHeaderActionButtonType.basic:
|
||||
buttonStyle['--mdc-text-button-label-text-color'] = buttonColor;
|
||||
break;
|
||||
case WidgetHeaderActionButtonType.raised:
|
||||
buttonStyle['--mdc-protected-button-label-text-color'] = buttonColor;
|
||||
buttonStyle['--mdc-protected-button-container-color'] = backgroundColor;
|
||||
break;
|
||||
case WidgetHeaderActionButtonType.stroked:
|
||||
buttonStyle['--mdc-outlined-button-label-text-color'] = buttonColor;
|
||||
buttonStyle['--mdc-outlined-button-outline-color'] = borderColor;
|
||||
break;
|
||||
case WidgetHeaderActionButtonType.flat:
|
||||
buttonStyle['--mdc-filled-button-label-text-color'] = buttonColor;
|
||||
buttonStyle['--mdc-filled-button-container-color'] = backgroundColor;
|
||||
break;
|
||||
case WidgetHeaderActionButtonType.miniFab:
|
||||
buttonStyle['--mat-fab-small-foreground-color'] = buttonColor;
|
||||
buttonStyle['--mdc-fab-small-container-color'] = backgroundColor;
|
||||
break;
|
||||
default:
|
||||
buttonStyle['--mat-icon-color'] = buttonColor;
|
||||
break;
|
||||
}
|
||||
return {...buttonStyle, ...customButtonStyle};
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
for (const propName of Object.keys(changes)) {
|
||||
const change = changes[propName];
|
||||
|
||||
@ -132,7 +132,7 @@ export interface WidgetHeaderAction extends IWidgetAction {
|
||||
buttonColor?: string;
|
||||
buttonFillColor?: string;
|
||||
buttonBorderColor?: string;
|
||||
customButtonStyle?: string;
|
||||
customButtonStyle?: {[key: string]: string};
|
||||
useShowWidgetHeaderActionFunction: boolean;
|
||||
showWidgetHeaderActionFunction: CompiledTbFunction<ShowWidgetHeaderActionFunction>;
|
||||
}
|
||||
|
||||
@ -45,9 +45,9 @@
|
||||
<tb-calculated-fields-table [active]="calculatedFieldsTab.isActive" [entityId]="entity.id" [entityName]="entity.name"/>
|
||||
</mat-tab>
|
||||
<mat-tab *ngIf="entity" #alarmRules="matTab"
|
||||
label="{{'device-profile.alarm-rules-with-count' | translate:
|
||||
{count: this.detailsForm.get('profileData.alarms').value?.length ? this.detailsForm.get('profileData.alarms').value.length : 0}
|
||||
}}">
|
||||
label="{{ this.detailsForm.get('profileData.alarms').value?.length
|
||||
? ('device-profile.alarm-rules-with-count' | translate: { count: this.detailsForm.get('profileData.alarms').value.length })
|
||||
: 'device-profile.alarm-rules' | translate }}">
|
||||
<div class="mat-padding" [formGroup]="detailsForm" *ngIf="alarmRules.isActive">
|
||||
<div formGroupName="profileData">
|
||||
<tb-device-profile-alarms formControlName="alarms" [deviceProfileId]="entity.id"></tb-device-profile-alarms>
|
||||
|
||||
@ -780,7 +780,7 @@ export interface WidgetActionDescriptor extends WidgetAction {
|
||||
buttonColor?: string;
|
||||
buttonFillColor?: string;
|
||||
buttonBorderColor?: string;
|
||||
customButtonStyle?: string;
|
||||
customButtonStyle?: {[key: string]: string};
|
||||
displayName?: string;
|
||||
useShowWidgetActionFunction?: boolean;
|
||||
showWidgetActionFunction?: TbFunction;
|
||||
|
||||
@ -991,7 +991,7 @@
|
||||
"type-sms-sent": "SMS sent"
|
||||
},
|
||||
"debug-settings": {
|
||||
"label": "Debug configuration",
|
||||
"label": "Debug Configuration",
|
||||
"on-failure": "Failures only (24/7)",
|
||||
"all-messages": "All messages ({{time}})",
|
||||
"failures": "Failures",
|
||||
@ -999,10 +999,9 @@
|
||||
"rule-node": "rule node",
|
||||
"calculated-field": "calculated field",
|
||||
"hint": {
|
||||
"main": "All node debug messages rate limited with:",
|
||||
"main-limited": "All {{entity}} debug messages will be rate-limited, with a maximum of {{msg}} messages allowed per {{time}}.",
|
||||
"on-failure": "Save all failure debug events without time limit.",
|
||||
"all-messages": "Save all debug events during time limit."
|
||||
"main-limited": "No more than {{msg}} {{entity}} debug messages per {{time}} will be recorded.",
|
||||
"on-failure": "Log all debug messages.",
|
||||
"all-messages": "Log error messages only. "
|
||||
}
|
||||
},
|
||||
"calculated-fields": {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user