refactoring

This commit is contained in:
mpetrov 2024-11-13 14:50:23 +02:00
parent 2933071a0f
commit 0a8e526d08
14 changed files with 87 additions and 107 deletions

View File

@ -19,12 +19,12 @@
class="tb-rounded-btn flex-1 w-36"
color="primary"
#matButton
[class.active]="(isDebugAllActive() || debugFailures) && !disabled"
[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()" translate>common.disabled</span>
<span *ngIf="isDebugAllActive() && debugFailures" translate>debug-config.all</span>
<span *ngIf="isDebugAllActive() && !debugFailures">{{ debugAllUntil | debugDurationLeft }}</span>
<span *ngIf="!isDebugAllActive() && debugFailures" translate>debug-config.failures</span>
<span *ngIf="!debugFailures && !(isDebugAllActive$ | async)" translate>common.disabled</span>
<span *ngIf="(isDebugAllActive$ | async) && debugFailures" translate>debug-config.all</span>
<span *ngIf="(isDebugAllActive$ | async) && !debugFailures">{{ debugAllUntil | durationLeft }}</span>
<span *ngIf="!(isDebugAllActive$ | async) && debugFailures" translate>debug-config.failures</span>
</button>

View File

@ -21,22 +21,20 @@ import {
ViewContainerRef,
DestroyRef,
ChangeDetectionStrategy,
ChangeDetectorRef,
EventEmitter,
Output
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { SharedModule } from '@shared/shared.module';
import { DebugDurationLeftPipe } from '@home/pages/rulechain/debug-duration-left.pipe';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe';
import { TbPopoverService } from '@shared/components/popover.service';
import { MatButton } from '@angular/material/button';
import { DebugConfigPanelComponent } from '@home/pages/rulechain/debug-config-panel.component';
import { DebugConfigPanelComponent } from './debug-config-panel.component';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { interval } from 'rxjs';
import { timer } from 'rxjs';
import { SECOND } from '@shared/models/time/time.models';
import { RuleNodeDebugConfig } from '@shared/models/rule-node.models';
import { HasDebugConfig } from '@shared/models/entity.models';
import { map } from 'rxjs/operators';
@Component({
selector: 'tb-debug-config-button',
@ -45,7 +43,7 @@ import { RuleNodeDebugConfig } from '@shared/models/rule-node.models';
imports: [
CommonModule,
SharedModule,
DebugDurationLeftPipe,
DurationLeftPipe,
],
changeDetection: ChangeDetectionStrategy.OnPush
})
@ -55,20 +53,18 @@ export class DebugConfigButtonComponent {
@Input() debugAll = false;
@Input() debugAllUntil = 0;
@Input() disabled = false;
@Input() maxRuleNodeDebugDurationMinutes: number;
@Input() ruleChainDebugPerTenantLimitsConfiguration: string;
@Output() onDebugConfigChanged = new EventEmitter<RuleNodeDebugConfig>()
@Output() onDebugConfigChanged = new EventEmitter<HasDebugConfig>();
constructor(protected store: Store<AppState>,
private popoverService: TbPopoverService,
isDebugAllActive$ = timer(0, SECOND).pipe(map(() => this.debugAllUntil > new Date().getTime()));
constructor(private popoverService: TbPopoverService,
private renderer: Renderer2,
private viewContainerRef: ViewContainerRef,
private destroyRef: DestroyRef,
private cdr: ChangeDetectorRef
) {
interval(SECOND)
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(() => this.cdr.markForCheck());
}
) {}
openDebugStrategyPanel($event: Event, matButton: MatButton): void {
if ($event) {
@ -84,19 +80,16 @@ export class DebugConfigButtonComponent {
debugFailures: this.debugFailures,
debugAll: this.debugAll,
debugAllUntil: this.debugAllUntil,
maxRuleNodeDebugDurationMinutes: this.maxRuleNodeDebugDurationMinutes,
ruleChainDebugPerTenantLimitsConfiguration: this.ruleChainDebugPerTenantLimitsConfiguration
},
{},
{}, {}, true);
debugStrategyPopover.tbComponentRef.instance.popover = debugStrategyPopover;
debugStrategyPopover.tbComponentRef.instance.onConfigApplied.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((config: RuleNodeDebugConfig) => {
debugStrategyPopover.tbComponentRef.instance.onConfigApplied.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((config: HasDebugConfig) => {
this.onDebugConfigChanged.emit(config);
this.cdr.markForCheck();
debugStrategyPopover.hide();
});
}
}
isDebugAllActive(): boolean {
return this.debugAllUntil > new Date().getTime();
}
}

View File

@ -27,23 +27,18 @@
</div>
<div class="flex flex-col gap-3">
<mat-slide-toggle class="mat-slide" [formControl]="onFailuresControl">
<mat-label tb-hint-tooltip-icon="{{ 'debug-config.hint.on-failure' | translate }}">
<div tb-hint-tooltip-icon="{{ 'debug-config.hint.on-failure' | translate }}">
{{ 'debug-config.on-failure' | translate }}
</mat-label>
</div>
</mat-slide-toggle>
<div class="flex justify-between align-center">
<mat-slide-toggle class="mat-slide" [formControl]="debugAllControl">
<mat-label tb-hint-tooltip-icon="{{ 'debug-config.hint.all-messages' | translate }}">
{{ 'debug-config.all-messages' | translate }} {{ '( ' }}
<span *ngIf="isDebugAllOn() else debugAllOffLabel">{{ debugAllUntil | debugDurationLeft }}</span>
<ng-template #debugAllOffLabel>
{{ maxRuleNodeDebugDurationMinutes + ' ' }} {{ ('debug-config.min' | translate) }}
</ng-template>
{{ ' )' }}
</mat-label>
<div tb-hint-tooltip-icon="{{ 'debug-config.hint.all-messages' | translate }}">
{{ 'debug-config.all-messages' | translate: { time: (isDebugAllActive$ | async) ? (debugAllUntil | durationLeft) : ('debug-config.min' | translate: { number: maxRuleNodeDebugDurationMinutes }) } }}
</div>
</mat-slide-toggle>
<button mat-icon-button *ngIf="isDebugAllOn()"
class="tb-mat-20 p-0 mr-2"
<button mat-icon-button *ngIf="(isDebugAllActive$ | async)"
class="tb-mat-20"
matTooltip="{{ 'action.reset' | translate }}"
matTooltipPosition="above"
color="primary"

View File

@ -18,24 +18,21 @@ import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
DestroyRef,
EventEmitter,
Input,
OnInit
} from '@angular/core';
import { PageComponent } from '@shared/components/page.component';
import { TbPopoverComponent } from '@shared/components/popover.component';
import { FormControl, UntypedFormBuilder } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { UntypedFormBuilder } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { SharedModule } from '@shared/shared.module';
import { getCurrentAuthState } from '@core/auth/auth.selectors';
import { RuleNodeDebugConfig } from '@shared/models/rule-node.models';
import { MINUTE, SECOND } from '@shared/models/time/time.models';
import { DebugDurationLeftPipe } from '@home/pages/rulechain/debug-duration-left.pipe';
import { interval } from 'rxjs';
import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe';
import { timer } from 'rxjs';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { HasDebugConfig } from '@shared/models/entity.models';
import { distinctUntilChanged, map, tap } from 'rxjs/operators';
@Component({
selector: 'tb-debug-config-panel',
@ -44,7 +41,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
imports: [
SharedModule,
CommonModule,
DebugDurationLeftPipe
DurationLeftPipe
],
changeDetection: ChangeDetectionStrategy.OnPush
})
@ -54,31 +51,35 @@ export class DebugConfigPanelComponent extends PageComponent implements OnInit {
@Input() debugFailures = false;
@Input() debugAll = false;
@Input() debugAllUntil = 0;
@Input() maxRuleNodeDebugDurationMinutes: number;
@Input() ruleChainDebugPerTenantLimitsConfiguration: string;
onFailuresControl: FormControl<boolean>;
debugAllControl: FormControl<boolean>;
onFailuresControl = this.fb.control(false);
debugAllControl = this.fb.control(false);
onConfigApplied = new EventEmitter<RuleNodeDebugConfig>()
maxMessagesCount: string;
maxTimeFrameSec: string;
readonly maxRuleNodeDebugDurationMinutes = getCurrentAuthState(this.store).maxRuleNodeDebugDurationMinutes;
readonly ruleChainDebugPerTenantLimitsConfiguration = getCurrentAuthState(this.store).ruleChainDebugPerTenantLimitsConfiguration;
readonly maxMessagesCount = this.ruleChainDebugPerTenantLimitsConfiguration?.split(':')[0];
readonly maxTimeFrameSec = this.ruleChainDebugPerTenantLimitsConfiguration?.split(':')[1];
isDebugAllActive$ = timer(0, SECOND).pipe(
map(() => {
this.cd.markForCheck();
return this.debugAllUntil > new Date().getTime()
}),
distinctUntilChanged(),
tap(isDebugOn => this.debugAllControl.patchValue(isDebugOn, { emitEvent: false }))
);
constructor(private fb: UntypedFormBuilder,
private destroyRef: DestroyRef,
private cdr: ChangeDetectorRef,
protected store: Store<AppState>) {
super(store);
onConfigApplied = new EventEmitter<HasDebugConfig>();
this.onFailuresControl = this.fb.control(false);
this.debugAllControl = this.fb.control(false);
constructor(private fb: UntypedFormBuilder, private cd: ChangeDetectorRef) {
super();
this.observeDebugAllChange();
}
ngOnInit(): void {
this.debugAllControl.patchValue(this.isDebugAllOn(), { emitEvent: false });
this.maxMessagesCount = this.ruleChainDebugPerTenantLimitsConfiguration?.split(':')[0];
this.maxTimeFrameSec = this.ruleChainDebugPerTenantLimitsConfiguration?.split(':')[1];
this.onFailuresControl.patchValue(this.debugFailures);
}
@ -99,22 +100,10 @@ export class DebugConfigPanelComponent extends PageComponent implements OnInit {
this.debugAllUntil = new Date().getTime() + this.maxRuleNodeDebugDurationMinutes * MINUTE;
}
isDebugAllOn(): boolean {
return this.debugAllUntil > new Date().getTime();
}
private observeDebugAllChange(): void {
interval(SECOND)
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(() => {
this.debugAllControl.patchValue(this.isDebugAllOn(), { emitEvent: false });
this.cdr.markForCheck();
});
this.debugAllControl.valueChanges.pipe(takeUntilDestroyed()).subscribe(value => {
this.debugAllUntil = value? new Date().getTime() + this.maxRuleNodeDebugDurationMinutes * MINUTE : 0;
this.debugAll = value;
this.cdr.markForCheck();
});
}
}

View File

@ -40,6 +40,8 @@
[debugAll]="ruleNode.debugAll"
[debugFailures]="ruleNode.debugFailures"
[debugAllUntil]="ruleNode.debugAllUntil"
[maxRuleNodeDebugDurationMinutes]="maxRuleNodeDebugDurationMinutes"
[ruleChainDebugPerTenantLimitsConfiguration]="ruleChainDebugPerTenantLimitsConfiguration"
(onDebugConfigChanged)="onDebugConfigChanged($event)"
/>
<button mat-stroked-button

View File

@ -29,7 +29,7 @@ import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { FcRuleNode, RuleNodeDebugConfig, RuleNodeType } from '@shared/models/rule-node.models';
import { FcRuleNode, RuleNodeType } from '@shared/models/rule-node.models';
import { EntityType } from '@shared/models/entity-type.models';
import { Subject } from 'rxjs';
import { RuleNodeConfigComponent } from './rule-node-config.component';
@ -39,6 +39,8 @@ import { ComponentClusteringMode } from '@shared/models/component-descriptor.mod
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',
@ -79,6 +81,9 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
ruleNodeFormGroup: UntypedFormGroup;
readonly maxRuleNodeDebugDurationMinutes = getCurrentAuthState(this.store).maxRuleNodeDebugDurationMinutes;
readonly ruleChainDebugPerTenantLimitsConfiguration = getCurrentAuthState(this.store).ruleChainDebugPerTenantLimitsConfiguration;
private destroy$ = new Subject<void>();
constructor(protected store: Store<AppState>,
@ -205,7 +210,7 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
return this.ruleNode.component.clusteringMode === ComponentClusteringMode.USER_PREFERENCE;
}
onDebugConfigChanged(config: RuleNodeDebugConfig): void {
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);

View File

@ -32,8 +32,8 @@ import { RuleNodeDetailsComponent } from './rule-node-details.component';
import { RuleNodeLinkComponent } from './rule-node-link.component';
import { LinkLabelsComponent } from '@home/pages/rulechain/link-labels.component';
import { RuleNodeConfigComponent } from './rule-node-config.component';
import { DebugDurationLeftPipe } from '@home/pages/rulechain/debug-duration-left.pipe';
import { DebugConfigButtonComponent } from '@home/pages/rulechain/debug-config-button.component';
import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe';
import { DebugConfigButtonComponent } from '@home/components/debug-config/debug-config-button.component';
@NgModule({
declarations: [
@ -62,7 +62,7 @@ import { DebugConfigButtonComponent } from '@home/pages/rulechain/debug-config-b
SharedModule,
HomeComponentsModule,
RuleChainRoutingModule,
DebugDurationLeftPipe,
DurationLeftPipe,
DebugConfigButtonComponent
]
})

View File

@ -191,3 +191,9 @@ export interface HasTenantId {
export interface HasVersion {
version?: number;
}
export interface HasDebugConfig {
debugAll: boolean;
debugFailures: boolean;
debugAllUntil: number;
}

View File

@ -27,19 +27,16 @@ 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 { TranslateService } from '@ngx-translate/core';
import { HasDebugConfig } from '@shared/models/entity.models';
export interface RuleNodeConfiguration {
[key: string]: any;
}
export interface RuleNode extends BaseData<RuleNodeId> {
export interface RuleNode extends BaseData<RuleNodeId>, HasDebugConfig {
ruleChainId?: RuleChainId;
type: string;
name: string;
debugAll: boolean;
debugFailures: boolean;
debugAllUntil: number;
singletonMode: boolean;
queueName?: string;
configurationVersion?: number;
@ -347,21 +344,12 @@ export interface FcRuleNode extends FcRuleNodeType {
ruleNodeId?: RuleNodeId;
additionalInfo?: any;
configuration?: RuleNodeConfiguration;
debugAll?: boolean;
debugFailures?: boolean;
debugAllUntil?: number;
error?: string;
highlighted?: boolean;
componentClazz?: string;
ruleChainType?: RuleChainType;
}
export interface RuleNodeDebugConfig {
debugAll: boolean;
debugFailures: boolean;
debugAllUntil: number;
}
export interface FcRuleEdge extends FcEdge {
labels?: string[];
}

View File

@ -15,22 +15,21 @@
///
import { Pipe, PipeTransform } from '@angular/core';
import { MINUTE } from '@shared/models/time/time.models';
import { TranslateService } from '@ngx-translate/core';
import { MillisecondsToTimeStringPipe } from '@shared/pipe/milliseconds-to-time-string.pipe';
import { MillisecondsToTimeStringPipe } from './milliseconds-to-time-string.pipe';
@Pipe({
name: 'debugDurationLeft',
name: 'durationLeft',
pure: false,
standalone: true,
})
export class DebugDurationLeftPipe implements PipeTransform {
export class DurationLeftPipe implements PipeTransform {
constructor(private translate: TranslateService, private millisecondsToTimeString: MillisecondsToTimeStringPipe) {
}
transform(debugAllUntil: number): string {
const time = this.millisecondsToTimeString.transform((debugAllUntil - new Date().getTime()), true, true);
return `${time} ` + this.translate.instant('common.left');
transform(untilTimestamp: number, shortFormat = true, onlyFirstDigit = true): string {
const time = this.millisecondsToTimeString.transform((untilTimestamp - new Date().getTime()), shortFormat, onlyFirstDigit) ?? 0;
return this.translate.instant('common.time-left', { time });
}
}

View File

@ -58,7 +58,9 @@ export class MillisecondsToTimeStringPipe implements PipeTransform {
for (const { value, key, shortKey } of timeUnits) {
if (value > 0) {
timeString += this.translate.instant(shortFormat ? `timewindow.${shortKey}` : `timewindow.${key}`, { [key]: value });
if (onlyFirstDigit) return timeString;
if (onlyFirstDigit) {
return timeString;
}
}
}

View File

@ -25,3 +25,4 @@ export * from './file-size.pipe';
export * from './selectable-columns.pipe';
export * from './image.pipe';
export * from './key-value-not-empty.pipe';
export * from './duration-left.pipe';

View File

@ -996,10 +996,10 @@
"type-sms-sent": "SMS sent"
},
"debug-config": {
"min": "min",
"min": "{{number}} min",
"label": "Debug configuration",
"on-failure": "Failures only (24/7)",
"all-messages": "All messages",
"all-messages": "All messages ({{time}})",
"failures": "Failures",
"all": "All",
"hint": {
@ -1045,7 +1045,7 @@
"open-details-page": "Open details page",
"not-found": "Not found",
"documentation": "Documentation",
"left": "left"
"time-left": "{{time}} left"
},
"content-type": {
"json": "Json",

View File

@ -1278,7 +1278,7 @@ pre.tb-highlight {
}
&.active:not(:disabled) {
border-color: $primary !important;
--mdc-outlined-button-outline-color: $primary;
}
&:disabled {