Debug settings changed approach to ControlValueAccessor and refactoring
This commit is contained in:
parent
04074b8baa
commit
02016487c7
@ -1,46 +0,0 @@
|
||||
<!--
|
||||
|
||||
Copyright © 2016-2024 The Thingsboard Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
<button mat-stroked-button
|
||||
*ngIf="!minifyMode else minifiedButton"
|
||||
class="tb-rounded-btn flex-1 w-36"
|
||||
color="primary"
|
||||
#matButton
|
||||
[class.active]="((isDebugAllActive$ | async) || debugFailures) && !disabled"
|
||||
[disabled]="disabled"
|
||||
(click)="openDebugStrategyPanel($event, matButton)">
|
||||
<mat-icon [color]="disabled ? 'inherit' : 'primary'">bug_report</mat-icon>
|
||||
<span *ngIf="!debugFailures && !(isDebugAllActive$ | async)" translate>common.disabled</span>
|
||||
<span *ngIf="(isDebugAllActive$ | async) && debugFailures" translate>debug-config.all</span>
|
||||
<span *ngIf="(isDebugAllActive$ | async) && !debugFailures">
|
||||
{{ !debugAll ? (debugAllUntil | durationLeft) : ('debug-config.min' | translate: { number: maxDebugModeDurationMinutes }) }}
|
||||
</span>
|
||||
<span *ngIf="!(isDebugAllActive$ | async) && debugFailures" translate>debug-config.failures</span>
|
||||
</button>
|
||||
<ng-template #minifiedButton>
|
||||
<button mat-icon-button
|
||||
class="mini-debug-btn"
|
||||
[disabled]="disabled"
|
||||
#matButton
|
||||
[matTooltip]="(isDebugAllActive$ | async) ? (debugAllUntil | durationLeft) : null"
|
||||
matTooltipPosition="above"
|
||||
(click)="openDebugStrategyPanel($event, matButton)">
|
||||
<mat-icon class="material-icons" [color]="((isDebugAllActive$ | async) || debugFailures) && !disabled ? 'primary' : 'inherit'">
|
||||
bug_report
|
||||
</mat-icon>
|
||||
</button>
|
||||
</ng-template>
|
||||
@ -1,20 +0,0 @@
|
||||
/**
|
||||
* Copyright © 2016-2024 The Thingsboard Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
:host {
|
||||
.mini-debug-btn {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
<!--
|
||||
|
||||
Copyright © 2016-2024 The Thingsboard Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
<button mat-stroked-button
|
||||
class="tb-rounded-btn flex-1 w-36"
|
||||
color="primary"
|
||||
#matButton
|
||||
[class.active]="((isDebugAllActive$ | async) || failuresEnabled) && !disabled"
|
||||
[disabled]="disabled"
|
||||
(click)="openDebugStrategyPanel($event, matButton)">
|
||||
<mat-icon [color]="debugSettingsFormGroup.disabled ? 'inherit' : 'primary'">bug_report</mat-icon>
|
||||
@if (failuresEnabled) {
|
||||
@if (isDebugAllActive$ | async) {
|
||||
{{ 'debug-config.all' | translate }}
|
||||
} @else {
|
||||
{{ 'debug-config.failures' | translate }}
|
||||
}
|
||||
} @else {
|
||||
@if (isDebugAllActive$ | async) {
|
||||
{{ !allEnabled ? (allEnabledUntil | durationLeft) : ('debug-config.min' | translate: { number: maxDebugModeDurationMinutes }) }}
|
||||
} @else {
|
||||
{{ 'common.disabled' | translate }}
|
||||
}
|
||||
}
|
||||
</button>
|
||||
@ -21,82 +21,128 @@ import {
|
||||
ViewContainerRef,
|
||||
DestroyRef,
|
||||
ChangeDetectionStrategy,
|
||||
EventEmitter,
|
||||
Output
|
||||
forwardRef
|
||||
} from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe';
|
||||
import { TbPopoverService } from '@shared/components/popover.service';
|
||||
import { MatButton } from '@angular/material/button';
|
||||
import { DebugConfigPanelComponent } from './debug-config-panel.component';
|
||||
import { DebugSettingsPanelComponent } from './debug-settings-panel.component';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { shareReplay, timer } from 'rxjs';
|
||||
import { SECOND } from '@shared/models/time/time.models';
|
||||
import { HasDebugConfig } from '@shared/models/entity.models';
|
||||
import { DebugSettings } from '@shared/models/entity.models';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { getCurrentAuthState } from '@core/auth/auth.selectors';
|
||||
import { AppState } from '@core/core.state';
|
||||
import { Store } from '@ngrx/store';
|
||||
import {
|
||||
ControlValueAccessor,
|
||||
FormBuilder,
|
||||
NG_VALUE_ACCESSOR,
|
||||
UntypedFormGroup,
|
||||
} from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-debug-config-button',
|
||||
templateUrl: './debug-config-button.component.html',
|
||||
styleUrls: ['./debug-config-button.component.scss'],
|
||||
selector: 'tb-debug-settings-button',
|
||||
templateUrl: './debug-settings-button.component.html',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
DurationLeftPipe,
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: forwardRef(() => DebugSettingsButtonComponent),
|
||||
multi: true
|
||||
},
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class DebugConfigButtonComponent {
|
||||
export class DebugSettingsButtonComponent implements ControlValueAccessor {
|
||||
|
||||
@Input() debugFailures = false;
|
||||
@Input() debugAll = false;
|
||||
@Input() debugAllUntil = 0;
|
||||
@Input() disabled = false;
|
||||
@Input() minifyMode = false;
|
||||
@Input() debugLimitsConfiguration: string;
|
||||
|
||||
@Output() onDebugConfigChanged = new EventEmitter<HasDebugConfig>();
|
||||
|
||||
isDebugAllActive$ = timer(0, SECOND).pipe(map(() => this.debugAllUntil > new Date().getTime() || this.debugAll), shareReplay(1));
|
||||
debugSettingsFormGroup: UntypedFormGroup;
|
||||
disabled = false;
|
||||
isDebugAllActive$ = timer(0, SECOND).pipe(map(() => this.allEnabledUntil > new Date().getTime() || this.allEnabled), shareReplay(1));
|
||||
|
||||
readonly maxDebugModeDurationMinutes = getCurrentAuthState(this.store).maxDebugModeDurationMinutes;
|
||||
|
||||
private onChange: (settings: DebugSettings) => void;
|
||||
|
||||
constructor(private popoverService: TbPopoverService,
|
||||
private renderer: Renderer2,
|
||||
private store: Store<AppState>,
|
||||
private viewContainerRef: ViewContainerRef,
|
||||
private destroyRef: DestroyRef,
|
||||
) {}
|
||||
private fb: FormBuilder,
|
||||
) {
|
||||
this.debugSettingsFormGroup = this.fb.group({
|
||||
failuresEnabled: [false],
|
||||
allEnabled: [false],
|
||||
allEnabledUntil: []
|
||||
});
|
||||
|
||||
this.debugSettingsFormGroup.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(value => {
|
||||
this.onChange(value);
|
||||
})
|
||||
}
|
||||
|
||||
get failuresEnabled(): boolean {
|
||||
return this.debugSettingsFormGroup.get('failuresEnabled').value;
|
||||
}
|
||||
|
||||
get allEnabled(): boolean {
|
||||
return this.debugSettingsFormGroup.get('allEnabled').value;
|
||||
}
|
||||
|
||||
get allEnabledUntil(): number {
|
||||
return this.debugSettingsFormGroup.get('allEnabledUntil').value;
|
||||
}
|
||||
|
||||
openDebugStrategyPanel($event: Event, matButton: MatButton): void {
|
||||
if ($event) {
|
||||
$event.stopPropagation();
|
||||
}
|
||||
const trigger = matButton._elementRef.nativeElement;
|
||||
const debugSettings = this.debugSettingsFormGroup.value;
|
||||
|
||||
if (this.popoverService.hasPopover(trigger)) {
|
||||
this.popoverService.hidePopover(trigger);
|
||||
} else {
|
||||
const debugStrategyPopover = this.popoverService.displayPopover(trigger, this.renderer,
|
||||
this.viewContainerRef, DebugConfigPanelComponent, 'bottom', true, null,
|
||||
this.viewContainerRef, DebugSettingsPanelComponent, 'bottom', true, null,
|
||||
{
|
||||
debugFailures: this.debugFailures,
|
||||
debugAll: this.debugAll,
|
||||
debugAllUntil: this.debugAllUntil,
|
||||
...debugSettings,
|
||||
maxDebugModeDurationMinutes: this.maxDebugModeDurationMinutes,
|
||||
debugLimitsConfiguration: this.debugLimitsConfiguration
|
||||
},
|
||||
{},
|
||||
{}, {}, true);
|
||||
debugStrategyPopover.tbComponentRef.instance.popover = debugStrategyPopover;
|
||||
debugStrategyPopover.tbComponentRef.instance.onConfigApplied.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((config: HasDebugConfig) => {
|
||||
this.onDebugConfigChanged.emit(config);
|
||||
debugStrategyPopover.tbComponentRef.instance.onConfigApplied.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((settings: DebugSettings) => {
|
||||
this.debugSettingsFormGroup.patchValue(settings);
|
||||
debugStrategyPopover.hide();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
registerOnChange(fn: (settings: DebugSettings) => void): void {
|
||||
this.onChange = fn;
|
||||
}
|
||||
|
||||
registerOnTouched(_: () => void): void {}
|
||||
|
||||
writeValue(settings: DebugSettings): void {
|
||||
this.debugSettingsFormGroup.patchValue(settings, {emitEvent: false});
|
||||
}
|
||||
|
||||
setDisabledState(isDisabled: boolean): void {
|
||||
this.disabled = isDisabled;
|
||||
this.debugSettingsFormGroup[isDisabled ? 'disable' : 'enable']({emitEvent: false});
|
||||
}
|
||||
}
|
||||
@ -19,10 +19,11 @@
|
||||
<div class="tb-form-panel-title" translate>debug-config.label</div>
|
||||
<div class="hint-container">
|
||||
<div class="tb-form-hint tb-primary-fill tb-flex center">
|
||||
<span *ngIf="debugLimitsConfiguration else noLimitHint">
|
||||
@if (debugLimitsConfiguration) {
|
||||
{{ 'debug-config.hint.main-limited' | translate: { msg: maxMessagesCount, sec: maxTimeFrameSec } }}
|
||||
</span>
|
||||
<ng-template #noLimitHint>{{ 'debug-config.hint.main' | translate }}</ng-template>
|
||||
} @else {
|
||||
{{ 'debug-config.hint.main' | translate }}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-3">
|
||||
@ -34,17 +35,19 @@
|
||||
<div class="flex justify-between align-center">
|
||||
<mat-slide-toggle class="mat-slide" [formControl]="debugAllControl">
|
||||
<div tb-hint-tooltip-icon="{{ 'debug-config.hint.all-messages' | translate }}">
|
||||
{{ 'debug-config.all-messages' | translate: { time: (isDebugAllActive$ | async) && !debugAll ? (debugAllUntil | durationLeft) : ('debug-config.min' | translate: { number: maxDebugModeDurationMinutes }) } }}
|
||||
{{ 'debug-config.all-messages' | translate: { time: (isDebugAllActive$ | async) && !allEnabled ? (allEnabledUntil | durationLeft) : ('debug-config.min' | translate: { number: maxDebugModeDurationMinutes }) } }}
|
||||
</div>
|
||||
</mat-slide-toggle>
|
||||
<button mat-icon-button *ngIf="(isDebugAllActive$ | async) && !debugAll"
|
||||
class="tb-mat-20"
|
||||
matTooltip="{{ 'action.reset' | translate }}"
|
||||
matTooltipPosition="above"
|
||||
color="primary"
|
||||
(click)="onReset()">
|
||||
<mat-icon class="material-icons">refresh</mat-icon>
|
||||
</button>
|
||||
@if ((isDebugAllActive$ | async) && !allEnabled) {
|
||||
<button mat-icon-button
|
||||
class="tb-mat-20"
|
||||
matTooltip="{{ 'action.reset' | translate }}"
|
||||
matTooltipPosition="above"
|
||||
color="primary"
|
||||
(click)="onReset()">
|
||||
<mat-icon class="material-icons">refresh</mat-icon>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end">
|
||||
@ -31,12 +31,13 @@ import { MINUTE, SECOND } from '@shared/models/time/time.models';
|
||||
import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe';
|
||||
import { shareReplay, timer } from 'rxjs';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { HasDebugConfig } from '@shared/models/entity.models';
|
||||
import { DebugSettings } from '@shared/models/entity.models';
|
||||
import { distinctUntilChanged, map, tap } from 'rxjs/operators';
|
||||
import { coerceBoolean } from '@shared/decorators/coercion';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-debug-config-panel',
|
||||
templateUrl: './debug-config-panel.component.html',
|
||||
selector: 'tb-debug-settings-panel',
|
||||
templateUrl: './debug-settings-panel.component.html',
|
||||
standalone: true,
|
||||
imports: [
|
||||
SharedModule,
|
||||
@ -45,12 +46,12 @@ import { distinctUntilChanged, map, tap } from 'rxjs/operators';
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class DebugConfigPanelComponent extends PageComponent implements OnInit {
|
||||
export class DebugSettingsPanelComponent extends PageComponent implements OnInit {
|
||||
|
||||
@Input() popover: TbPopoverComponent<DebugConfigPanelComponent>;
|
||||
@Input() debugFailures = false;
|
||||
@Input() debugAll = false;
|
||||
@Input() debugAllUntil = 0;
|
||||
@Input() popover: TbPopoverComponent<DebugSettingsPanelComponent>;
|
||||
@Input() @coerceBoolean() failuresEnabled = false;
|
||||
@Input() @coerceBoolean() allEnabled = false;
|
||||
@Input() allEnabledUntil = 0;
|
||||
@Input() maxDebugModeDurationMinutes: number;
|
||||
@Input() debugLimitsConfiguration: string;
|
||||
|
||||
@ -63,14 +64,14 @@ export class DebugConfigPanelComponent extends PageComponent implements OnInit {
|
||||
isDebugAllActive$ = timer(0, SECOND).pipe(
|
||||
map(() => {
|
||||
this.cd.markForCheck();
|
||||
return this.debugAllUntil > new Date().getTime() || this.debugAll;
|
||||
return this.allEnabledUntil > new Date().getTime() || this.allEnabled;
|
||||
}),
|
||||
distinctUntilChanged(),
|
||||
tap(isDebugOn => this.debugAllControl.patchValue(isDebugOn, { emitEvent: false })),
|
||||
shareReplay(1),
|
||||
);
|
||||
|
||||
onConfigApplied = new EventEmitter<HasDebugConfig>();
|
||||
onConfigApplied = new EventEmitter<DebugSettings>();
|
||||
|
||||
constructor(private fb: UntypedFormBuilder, private cd: ChangeDetectorRef) {
|
||||
super();
|
||||
@ -81,7 +82,7 @@ export class DebugConfigPanelComponent extends PageComponent implements OnInit {
|
||||
ngOnInit(): void {
|
||||
this.maxMessagesCount = this.debugLimitsConfiguration?.split(':')[0];
|
||||
this.maxTimeFrameSec = this.debugLimitsConfiguration?.split(':')[1];
|
||||
this.onFailuresControl.patchValue(this.debugFailures);
|
||||
this.onFailuresControl.patchValue(this.failuresEnabled);
|
||||
}
|
||||
|
||||
onCancel(): void {
|
||||
@ -90,22 +91,22 @@ export class DebugConfigPanelComponent extends PageComponent implements OnInit {
|
||||
|
||||
onApply(): void {
|
||||
this.onConfigApplied.emit({
|
||||
debugAll: this.debugAll,
|
||||
debugFailures: this.onFailuresControl.value,
|
||||
debugAllUntil: this.debugAllUntil
|
||||
allEnabled: this.allEnabled,
|
||||
failuresEnabled: this.onFailuresControl.value,
|
||||
allEnabledUntil: this.allEnabledUntil
|
||||
});
|
||||
}
|
||||
|
||||
onReset(): void {
|
||||
this.debugAll = true;
|
||||
this.debugAllUntil = new Date().getTime() + this.maxDebugModeDurationMinutes * MINUTE;
|
||||
this.allEnabled = true;
|
||||
this.allEnabledUntil = new Date().getTime() + this.maxDebugModeDurationMinutes * MINUTE;
|
||||
this.cd.markForCheck();
|
||||
}
|
||||
|
||||
private observeDebugAllChange(): void {
|
||||
this.debugAllControl.valueChanges.pipe(takeUntilDestroyed()).subscribe(value => {
|
||||
this.debugAllUntil = value? new Date().getTime() + this.maxDebugModeDurationMinutes * MINUTE : 0;
|
||||
this.debugAll = value;
|
||||
this.allEnabledUntil = value? new Date().getTime() + this.maxDebugModeDurationMinutes * MINUTE : 0;
|
||||
this.allEnabled = value;
|
||||
this.cd.markForCheck();
|
||||
});
|
||||
}
|
||||
@ -76,22 +76,6 @@
|
||||
<mat-hint></mat-hint>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="fields-element flex flex-1 flex-row xs:flex-col gt-xs:gap-4">
|
||||
<mat-form-field class="mat-block flex-1" appearance="fill" subscriptSizing="dynamic">
|
||||
<mat-label translate>tenant-profile.maximum-debug-duration-min</mat-label>
|
||||
<input matInput required min="0" step="1"
|
||||
formControlName="maxDebugModeDurationMinutes"
|
||||
type="number">
|
||||
<mat-error *ngIf="defaultTenantProfileConfigurationFormGroup.get('maxDebugModeDurationMinutes').hasError('required')">
|
||||
{{ 'tenant-profile.maximum-debug-duration-min-range' | translate }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="defaultTenantProfileConfigurationFormGroup.get('maxDebugModeDurationMinutes').hasError('min')">
|
||||
{{ 'tenant-profile.maximum-debug-duration-min-required' | translate }}
|
||||
</mat-error>
|
||||
<mat-hint></mat-hint>
|
||||
</mat-form-field>
|
||||
<div class="flex-1"></div>
|
||||
</div>
|
||||
<mat-expansion-panel class="configuration-panel">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-description class="flex items-stretch justify-end" translate>
|
||||
@ -370,6 +354,25 @@
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="fields-group">
|
||||
<legend class="group-title">
|
||||
{{ 'tenant-profile.debug' | translate }} <span translate>tenant-profile.unlimited</span>
|
||||
</legend>
|
||||
<div class="fields-element flex flex-1 flex-row xs:flex-col gt-xs:gap-4">
|
||||
<mat-form-field class="mat-block flex-1" appearance="fill" subscriptSizing="dynamic">
|
||||
<mat-label translate>tenant-profile.maximum-debug-duration-min</mat-label>
|
||||
<input matInput min="0" step="1"
|
||||
formControlName="maxDebugModeDurationMinutes"
|
||||
type="number">
|
||||
<mat-error *ngIf="defaultTenantProfileConfigurationFormGroup.get('maxDebugModeDurationMinutes').hasError('min')">
|
||||
{{ 'tenant-profile.maximum-debug-duration-min-range' | translate }}
|
||||
</mat-error>
|
||||
<mat-hint></mat-hint>
|
||||
</mat-form-field>
|
||||
<div class="flex-1"></div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="fields-group">
|
||||
<legend class="group-title">
|
||||
{{ 'tenant-profile.ota-files-in-bytes' | translate }} <span translate>tenant-profile.unlimited</span>
|
||||
|
||||
@ -85,7 +85,7 @@ export class DefaultTenantProfileConfigurationComponent implements ControlValueA
|
||||
tenantNotificationRequestsRateLimit: [null, []],
|
||||
tenantNotificationRequestsPerRuleRateLimit: [null, []],
|
||||
maxTransportMessages: [null, [Validators.required, Validators.min(0)]],
|
||||
maxDebugModeDurationMinutes: [null, [Validators.required, Validators.min(0)]],
|
||||
maxDebugModeDurationMinutes: [null, [Validators.min(0)]],
|
||||
maxTransportDataPoints: [null, [Validators.required, Validators.min(0)]],
|
||||
maxREExecutions: [null, [Validators.required, Validators.min(0)]],
|
||||
maxJSExecutions: [null, [Validators.required, Validators.min(0)]],
|
||||
|
||||
@ -35,13 +35,10 @@
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<section class="flex flex-row max-w-xs mb-5">
|
||||
<tb-debug-config-button
|
||||
<tb-debug-settings-button
|
||||
class="mr-2"
|
||||
[debugAll]="ruleNode.debugAll"
|
||||
[debugFailures]="ruleNode.debugFailures"
|
||||
[debugAllUntil]="ruleNode.debugAllUntil"
|
||||
formControlName="debugSettings"
|
||||
[debugLimitsConfiguration]="ruleChainDebugPerTenantLimitsConfiguration"
|
||||
(onDebugConfigChanged)="onDebugConfigChanged($event)"
|
||||
/>
|
||||
<button mat-stroked-button
|
||||
class="tb-rounded-btn flex-1"
|
||||
|
||||
@ -40,7 +40,6 @@ import { coerceBoolean } from '@shared/decorators/coercion';
|
||||
import { ServiceType } from '@shared/models/queue.models';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { getCurrentAuthState } from '@core/auth/auth.selectors';
|
||||
import { HasDebugConfig } from '@shared/models/entity.models';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-rule-node',
|
||||
@ -96,9 +95,7 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
|
||||
if (this.ruleNode) {
|
||||
this.ruleNodeFormGroup = this.fb.group({
|
||||
name: [this.ruleNode.name, [Validators.required, Validators.pattern('(.|\\s)*\\S(.|\\s)*'), Validators.maxLength(255)]],
|
||||
debugAll: [this.ruleNode.debugAll],
|
||||
debugFailures: [this.ruleNode.debugFailures],
|
||||
debugAllUntil: [this.ruleNode.debugAllUntil],
|
||||
debugSettings: [this.ruleNode.debugSettings],
|
||||
singletonMode: [this.ruleNode.singletonMode, []],
|
||||
configuration: [this.ruleNode.configuration, [Validators.required]],
|
||||
additionalInfo: this.fb.group(
|
||||
@ -208,11 +205,4 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
|
||||
isSingletonEditAllowed() {
|
||||
return this.ruleNode.component.clusteringMode === ComponentClusteringMode.USER_PREFERENCE;
|
||||
}
|
||||
|
||||
onDebugConfigChanged(config: HasDebugConfig): void {
|
||||
this.ruleNodeFormGroup.get('debugAllUntil').setValue(config.debugAllUntil);
|
||||
this.ruleNodeFormGroup.get('debugAll').setValue(config.debugAll);
|
||||
this.ruleNodeFormGroup.get('debugFailures').setValue(config.debugFailures);
|
||||
this.ruleNodeFormGroup.markAsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@ -575,9 +575,7 @@ export class RuleChainPageComponent extends PageComponent
|
||||
additionalInfo: ruleNode.additionalInfo,
|
||||
configuration: ruleNode.configuration,
|
||||
configurationVersion: isDefinedAndNotNull(ruleNode.configurationVersion) ? ruleNode.configurationVersion : 0,
|
||||
debugAll: ruleNode.debugAll,
|
||||
debugFailures: ruleNode.debugFailures,
|
||||
debugAllUntil: ruleNode.debugAllUntil,
|
||||
debugSettings: ruleNode.debugSettings,
|
||||
singletonMode: ruleNode.singletonMode,
|
||||
queueName: ruleNode.queueName,
|
||||
x: Math.round(ruleNode.additionalInfo.layoutX),
|
||||
@ -938,9 +936,7 @@ export class RuleChainPageComponent extends PageComponent
|
||||
name: node.name,
|
||||
configuration: deepClone(node.configuration),
|
||||
additionalInfo: node.additionalInfo ? deepClone(node.additionalInfo) : {},
|
||||
debugFailures: node.debugFailures,
|
||||
debugAllUntil: node.debugAllUntil,
|
||||
debugAll: node.debugAll,
|
||||
debugSettings: node.debugSettings,
|
||||
singletonMode: node.singletonMode,
|
||||
queueName: node.queueName
|
||||
};
|
||||
@ -1013,9 +1009,7 @@ export class RuleChainPageComponent extends PageComponent
|
||||
name: outputEdge.label,
|
||||
configuration: {},
|
||||
additionalInfo: {},
|
||||
debugFailures: false,
|
||||
debugAllUntil: 0,
|
||||
debugAll: false,
|
||||
debugSettings: {},
|
||||
singletonMode: false
|
||||
};
|
||||
outputNode.additionalInfo.layoutX = Math.round(destNode.x);
|
||||
@ -1061,9 +1055,7 @@ export class RuleChainPageComponent extends PageComponent
|
||||
configuration: {
|
||||
ruleChainId: ruleChain.id.id
|
||||
},
|
||||
debugFailures: false,
|
||||
debugAllUntil: 0,
|
||||
debugAll: false,
|
||||
debugSettings: {},
|
||||
singletonMode: false,
|
||||
x: Math.round(ruleChainNodeX),
|
||||
y: Math.round(ruleChainNodeY),
|
||||
@ -1483,9 +1475,7 @@ export class RuleChainPageComponent extends PageComponent
|
||||
: node.component.configurationVersion,
|
||||
configuration: node.configuration,
|
||||
additionalInfo: node.additionalInfo ? node.additionalInfo : {},
|
||||
debugFailures: node.debugFailures,
|
||||
debugAllUntil: node.debugAllUntil,
|
||||
debugAll: node.debugAll,
|
||||
debugSettings: node.debugSettings,
|
||||
singletonMode: node.singletonMode,
|
||||
queueName: node.queueName
|
||||
};
|
||||
|
||||
@ -33,7 +33,7 @@ import { RuleNodeLinkComponent } from './rule-node-link.component';
|
||||
import { LinkLabelsComponent } from '@home/pages/rulechain/link-labels.component';
|
||||
import { RuleNodeConfigComponent } from './rule-node-config.component';
|
||||
import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe';
|
||||
import { DebugConfigButtonComponent } from '@home/components/debug-config/debug-config-button.component';
|
||||
import { DebugSettingsButtonComponent } from '@home/components/debug-settings/debug-settings-button.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@ -63,7 +63,7 @@ import { DebugConfigButtonComponent } from '@home/components/debug-config/debug-
|
||||
HomeComponentsModule,
|
||||
RuleChainRoutingModule,
|
||||
DurationLeftPipe,
|
||||
DebugConfigButtonComponent
|
||||
DebugSettingsButtonComponent
|
||||
]
|
||||
})
|
||||
export class RuleChainModule { }
|
||||
|
||||
@ -649,18 +649,20 @@ export class ImportExportService {
|
||||
);
|
||||
}
|
||||
|
||||
private processOldRuleChainConnections(ruleChainImport: RuleChainImport): Observable<RuleChainImport> {
|
||||
ruleChainImport.ruleChain = this.prepareImport(ruleChainImport.ruleChain);
|
||||
const metadata = ruleChainImport.metadata;
|
||||
private processOldRuleChainConnections({ruleChain, metadata}: RuleChainImport): Observable<RuleChainImport> {
|
||||
ruleChain = this.prepareImport(ruleChain);
|
||||
metadata = {
|
||||
...metadata,
|
||||
nodes: metadata.nodes.map(({ debugMode, ...node }: RuleNode & { debugMode: boolean }) => {
|
||||
return debugMode ? { ...node, debugSettings: { failuresEnabled: true, allEnabled: true} } : node
|
||||
})
|
||||
};
|
||||
if ((metadata as any).ruleChainConnections) {
|
||||
const ruleChainNameResolveObservables: Observable<void>[] = [];
|
||||
for (const ruleChainConnection of (metadata as any).ruleChainConnections) {
|
||||
if (ruleChainConnection.targetRuleChainId && ruleChainConnection.targetRuleChainId.id) {
|
||||
const ruleChainNode: RuleNode = {
|
||||
name: '',
|
||||
debugFailures: false,
|
||||
debugAllUntil: 0,
|
||||
debugAll: false,
|
||||
singletonMode: false,
|
||||
type: 'org.thingsboard.rule.engine.flow.TbRuleChainInputNode',
|
||||
configuration: {
|
||||
@ -688,13 +690,13 @@ export class ImportExportService {
|
||||
}
|
||||
if (ruleChainNameResolveObservables.length) {
|
||||
return forkJoin(ruleChainNameResolveObservables).pipe(
|
||||
map(() => ruleChainImport)
|
||||
map(() => ({ruleChain, metadata}))
|
||||
);
|
||||
} else {
|
||||
return of(ruleChainImport);
|
||||
return of({ruleChain, metadata});
|
||||
}
|
||||
} else {
|
||||
return of(ruleChainImport);
|
||||
return of({ruleChain, metadata});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -193,10 +193,14 @@ export interface HasVersion {
|
||||
version?: number;
|
||||
}
|
||||
|
||||
export interface HasDebugConfig {
|
||||
debugAll?: boolean;
|
||||
debugFailures?: boolean;
|
||||
debugAllUntil?: number;
|
||||
export interface HasDebugSettings {
|
||||
debugSettings?: DebugSettings;
|
||||
}
|
||||
|
||||
export type VersionedEntity = EntityInfoData & HasVersion | RuleChainMetaData;
|
||||
export interface DebugSettings {
|
||||
failuresEnabled?: boolean;
|
||||
allEnabled?: boolean;
|
||||
allEnabledUntil?: number;
|
||||
}
|
||||
|
||||
export type VersionedEntity = EntityInfoData & HasVersion | RuleChainMetaData;
|
||||
|
||||
@ -27,13 +27,13 @@ import { AppState } from '@core/core.state';
|
||||
import { AbstractControl, UntypedFormGroup } from '@angular/forms';
|
||||
import { RuleChainType } from '@shared/models/rule-chain.models';
|
||||
import { DebugRuleNodeEventBody } from '@shared/models/event.models';
|
||||
import { HasDebugConfig } from '@shared/models/entity.models';
|
||||
import { HasDebugSettings } from '@shared/models/entity.models';
|
||||
|
||||
export interface RuleNodeConfiguration {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface RuleNode extends BaseData<RuleNodeId>, HasDebugConfig {
|
||||
export interface RuleNode extends BaseData<RuleNodeId>, HasDebugSettings {
|
||||
ruleChainId?: RuleChainId;
|
||||
type: string;
|
||||
name: string;
|
||||
@ -331,7 +331,7 @@ export interface RuleNodeComponentDescriptor extends ComponentDescriptor {
|
||||
configurationDescriptor?: RuleNodeConfigurationDescriptor;
|
||||
}
|
||||
|
||||
export interface FcRuleNodeType extends FcNode, HasDebugConfig {
|
||||
export interface FcRuleNodeType extends FcNode, HasDebugSettings {
|
||||
component?: RuleNodeComponentDescriptor;
|
||||
singletonMode?: boolean;
|
||||
queueName?: string;
|
||||
|
||||
@ -4402,6 +4402,7 @@
|
||||
"tenant-profiles": "Tenant profiles",
|
||||
"add": "Add tenant profile",
|
||||
"add-profile": "Add profile",
|
||||
"debug": "Debug",
|
||||
"edit": "Edit tenant profile",
|
||||
"tenant-profile-details": "Tenant profile details",
|
||||
"no-tenant-profiles-text": "No tenant profiles found",
|
||||
@ -4470,7 +4471,6 @@
|
||||
"maximum-ota-package-sum-data-size-required": "Maximum total size of OTA package files is required.",
|
||||
"maximum-ota-package-sum-data-size-range": "Maximum total size of OTA package files can't be negative",
|
||||
"maximum-debug-duration-min": "Maximum debug duration (min)",
|
||||
"maximum-debug-duration-min-required": "Maximum debug duration is required.",
|
||||
"maximum-debug-duration-min-range": "Maximum debug duration can't be negative",
|
||||
"rest-requests-for-tenant": "REST requests for tenant",
|
||||
"transport-tenant-telemetry-msg-rate-limit": "Transport tenant telemetry messages",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user