Browse Source

Added debug settings service

pull/12811/head
mpetrov 2 years ago
parent
commit
3d3a8ffc05
  1. 61
      ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table-config.ts
  2. 11
      ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table.component.ts
  3. 2
      ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings-button.component.html
  4. 46
      ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings-button.component.ts
  5. 68
      ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings.service.ts
  6. 4
      ui-ngx/src/app/modules/home/components/home-components.module.ts
  7. 11
      ui-ngx/src/app/shared/models/entity.models.ts
  8. 2
      ui-ngx/src/app/shared/shared.module.ts

61
ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table-config.ts

@ -29,10 +29,7 @@ import { AppState } from '@core/core.state';
import { getCurrentAuthState, getCurrentAuthUser } from '@core/auth/auth.selectors';
import { DestroyRef, Renderer2 } from '@angular/core';
import { EntityDebugSettings } from '@shared/models/entity.models';
import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { TbPopoverService } from '@shared/components/popover.service';
import { EntityDebugSettingsPanelComponent } from '@home/components/entity/debug/entity-debug-settings-panel.component';
import { CalculatedFieldsService } from '@core/http/calculated-fields.service';
import { catchError, filter, switchMap, tap } from 'rxjs/operators';
import {
@ -53,6 +50,7 @@ import {
} from './components/public-api';
import { ImportExportService } from '@shared/import-export/import-export.service';
import { isObject } from '@core/utils';
import { EntityDebugSettingsService } from '@home/components/entity/debug/entity-debug-settings.service';
export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedField, PageLink> {
@ -71,12 +69,11 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
private dialog: MatDialog,
public entityId: EntityId = null,
private store: Store<AppState>,
private durationLeft: DurationLeftPipe,
private popoverService: TbPopoverService,
private destroyRef: DestroyRef,
private renderer: Renderer2,
public entityName: string,
private importExportService: ImportExportService
private importExportService: ImportExportService,
private entityDebugSettingsService: EntityDebugSettingsService,
) {
super();
this.tableTitle = this.translate.instant('entity.type-calculated-fields');
@ -131,10 +128,10 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
},
{
name: '',
nameFunction: entity => this.getDebugConfigLabel(entity?.debugSettings),
nameFunction: entity => this.entityDebugSettingsService.getDebugConfigLabel(entity?.debugSettings),
icon: 'mdi:bug',
isEnabled: () => true,
iconFunction: ({ debugSettings }) => this.isDebugActive(debugSettings?.allEnabledUntil) || debugSettings?.failuresEnabled ? 'mdi:bug' : 'mdi:bug-outline',
iconFunction: ({ debugSettings }) => this.entityDebugSettingsService.isDebugActive(debugSettings?.allEnabledUntil) || debugSettings?.failuresEnabled ? 'mdi:bug' : 'mdi:bug-outline',
onAction: ($event, entity) => this.onOpenDebugConfig($event, entity),
},
{
@ -160,26 +157,20 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
if ($event) {
$event.stopPropagation();
}
const trigger = $event.target as Element;
if (this.popoverService.hasPopover(trigger)) {
this.popoverService.hidePopover(trigger);
} else {
const debugStrategyPopover = this.popoverService.displayPopover(trigger, this.renderer,
viewContainerRef, EntityDebugSettingsPanelComponent, 'bottom', true, null,
{
debugLimitsConfiguration: this.calculatedFieldsDebugPerTenantLimitsConfiguration,
maxDebugModeDuration: this.maxDebugModeDuration,
entityLabel: this.translate.instant('debug-settings.calculated-field'),
additionalActionConfig,
...debugSettings
},
{},
{}, {}, true);
debugStrategyPopover.tbComponentRef.instance.onSettingsApplied.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((settings: EntityDebugSettings) => {
this.onDebugConfigChanged(id.id, settings);
debugStrategyPopover.hide();
});
}
this.entityDebugSettingsService.viewContainerRef = viewContainerRef;
this.entityDebugSettingsService.renderer = this.renderer;
this.entityDebugSettingsService.openDebugStrategyPanel({
debugSettings,
debugConfig: {
debugLimitsConfiguration: this.calculatedFieldsDebugPerTenantLimitsConfiguration,
maxDebugModeDuration: this.maxDebugModeDuration,
entityLabel: this.translate.instant('debug-settings.calculated-field'),
additionalActionConfig,
},
onSettingsAppliedFn: settings => this.onDebugConfigChanged(id.id, settings)
}, $event.target as Element);
}
private editCalculatedField(calculatedField: CalculatedField, isDirty = false): void {
@ -239,20 +230,6 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
.subscribe(() => this.updateData());
}
private getDebugConfigLabel(debugSettings: EntityDebugSettings): string {
const isDebugActive = this.isDebugActive(debugSettings?.allEnabledUntil);
if (!isDebugActive) {
return debugSettings?.failuresEnabled ? this.translate.instant('debug-settings.failures') : this.translate.instant('common.disabled');
} else {
return this.durationLeft.transform(debugSettings?.allEnabledUntil);
}
}
private isDebugActive(allEnabledUntil: number): boolean {
return allEnabledUntil > new Date().getTime();
}
private onDebugConfigChanged(id: string, debugSettings: EntityDebugSettings): void {
this.calculatedFieldsService.getCalculatedFieldById(id).pipe(
switchMap(field => this.calculatedFieldsService.saveCalculatedField({ ...field, debugSettings })),

11
ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table.component.ts

@ -31,10 +31,9 @@ import { MatDialog } from '@angular/material/dialog';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { CalculatedFieldsTableConfig } from '@home/components/calculated-fields/calculated-fields-table-config';
import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe';
import { TbPopoverService } from '@shared/components/popover.service';
import { CalculatedFieldsService } from '@core/http/calculated-fields.service';
import { ImportExportService } from '@shared/import-export/import-export.service';
import { EntityDebugSettingsService } from '@home/components/entity/debug/entity-debug-settings.service';
@Component({
selector: 'tb-calculated-fields-table',
@ -56,11 +55,10 @@ export class CalculatedFieldsTableComponent {
private translate: TranslateService,
private dialog: MatDialog,
private store: Store<AppState>,
private durationLeft: DurationLeftPipe,
private popoverService: TbPopoverService,
private cd: ChangeDetectorRef,
private renderer: Renderer2,
private importExportService: ImportExportService,
private entityDebugSettingsService: EntityDebugSettingsService,
private destroyRef: DestroyRef) {
effect(() => {
@ -71,12 +69,11 @@ export class CalculatedFieldsTableComponent {
this.dialog,
this.entityId(),
this.store,
this.durationLeft,
this.popoverService,
this.destroyRef,
this.renderer,
this.entityName(),
this.importExportService
this.importExportService,
this.entityDebugSettingsService,
);
this.cd.markForCheck();
}

2
ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings-button.component.html

@ -21,7 +21,7 @@
#matButton
[class.active]="((isDebugAllActive$ | async) || failuresEnabled) && !disabled"
[disabled]="disabled"
(click)="openDebugStrategyPanel($event, matButton)">
(click)="onOpenDebugStrategyPanel($event, matButton)">
<mat-icon [color]="debugSettingsFormGroup.disabled ? 'inherit' : 'primary'">bug_report</mat-icon>
@if (isDebugAllActive$ | async) {
{{ (allEnabled$ | async) === false ? (allEnabledUntil | durationLeft) : (maxDebugModeDuration | milliSecondsToTimeString: true : true) }}

46
ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings-button.component.ts

@ -20,15 +20,11 @@ import {
Component,
forwardRef,
Input,
Renderer2,
ViewContainerRef
} 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 { EntityDebugSettingsPanelComponent } from './entity-debug-settings-panel.component';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { BehaviorSubject, of, shareReplay, timer } from 'rxjs';
import { SECOND, MINUTE } from '@shared/models/time/time.models';
@ -38,6 +34,7 @@ import { getCurrentAuthState } from '@core/auth/auth.selectors';
import { AppState } from '@core/core.state';
import { Store } from '@ngrx/store';
import { ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR } from '@angular/forms';
import { EntityDebugSettingsService } from '@home/components/entity/debug/entity-debug-settings.service';
@Component({
selector: 'tb-entity-debug-settings-button',
@ -54,6 +51,7 @@ import { ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR } from '@angular/f
useExisting: forwardRef(() => EntityDebugSettingsButtonComponent),
multi: true
},
EntityDebugSettingsService
],
changeDetection: ChangeDetectionStrategy.OnPush
})
@ -92,11 +90,9 @@ export class EntityDebugSettingsButtonComponent implements ControlValueAccessor
private propagateChange: (settings: EntityDebugSettings) => void = () => {};
constructor(private popoverService: TbPopoverService,
private renderer: Renderer2,
private store: Store<AppState>,
private viewContainerRef: ViewContainerRef,
constructor(private store: Store<AppState>,
private fb: FormBuilder,
private entityDebugSettingsService: EntityDebugSettingsService,
private cd : ChangeDetectorRef,
) {
this.debugSettingsFormGroup.valueChanges.pipe(
@ -118,33 +114,23 @@ export class EntityDebugSettingsButtonComponent implements ControlValueAccessor
return this.debugSettingsFormGroup.get('allEnabledUntil').value;
}
openDebugStrategyPanel($event: Event, matButton: MatButton): void {
onOpenDebugStrategyPanel($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, EntityDebugSettingsPanelComponent, 'bottom', true, null,
{
...debugSettings,
maxDebugModeDuration: this.maxDebugModeDuration,
debugLimitsConfiguration: this.debugLimitsConfiguration,
entityLabel: this.entityLabel,
additionalActionConfig: this.additionalActionConfig,
},
{},
{}, {}, true);
debugStrategyPopover.tbComponentRef.instance.onSettingsApplied.subscribe((settings: EntityDebugSettings) => {
this.entityDebugSettingsService.openDebugStrategyPanel({
debugSettings: this.debugSettingsFormGroup.value,
debugConfig: {
maxDebugModeDuration: this.maxDebugModeDuration,
debugLimitsConfiguration: this.debugLimitsConfiguration,
entityLabel: this.entityLabel,
additionalActionConfig: this.additionalActionConfig,
},
onSettingsAppliedFn: settings => {
this.debugSettingsFormGroup.patchValue(settings);
this.cd.markForCheck();
debugStrategyPopover.hide();
});
}
}
}, matButton._elementRef.nativeElement);
}
registerOnChange(fn: (settings: EntityDebugSettings) => void): void {

68
ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings.service.ts

@ -0,0 +1,68 @@
///
/// 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 { Injectable, Optional, Renderer2, ViewContainerRef } from '@angular/core';
import { EntityDebugSettingsPanelComponent } from '@home/components/entity/debug/entity-debug-settings-panel.component';
import { EntityDebugSettingPanelConfig, EntityDebugSettings } from '@shared/models/entity.models';
import { TbPopoverService } from '@shared/components/popover.service';
import { TranslateService } from '@ngx-translate/core';
import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe';
@Injectable()
export class EntityDebugSettingsService {
constructor(
private popoverService: TbPopoverService,
@Optional() public renderer: Renderer2,
@Optional() public viewContainerRef: ViewContainerRef,
private translate: TranslateService,
private durationLeft: DurationLeftPipe,
) {}
openDebugStrategyPanel(panelConfig: EntityDebugSettingPanelConfig, trigger: Element): void {
if (this.popoverService.hasPopover(trigger)) {
this.popoverService.hidePopover(trigger);
} else {
const debugStrategyPopover = this.popoverService.displayPopover(trigger, this.renderer,
this.viewContainerRef, EntityDebugSettingsPanelComponent, 'bottom', true, null,
{
...panelConfig.debugSettings,
...panelConfig.debugConfig,
},
{},
{}, {}, true);
debugStrategyPopover.tbComponentRef.instance.onSettingsApplied.subscribe(settings => {
panelConfig.onSettingsAppliedFn(settings);
debugStrategyPopover.hide();
});
}
}
getDebugConfigLabel(debugSettings: EntityDebugSettings): string {
const isDebugActive = this.isDebugActive(debugSettings?.allEnabledUntil);
if (!isDebugActive) {
return debugSettings?.failuresEnabled ? this.translate.instant('debug-settings.failures') : this.translate.instant('common.disabled');
} else {
return this.durationLeft.transform(debugSettings?.allEnabledUntil);
}
}
isDebugActive(allEnabledUntil: number): boolean {
return allEnabledUntil > new Date().getTime();
}
}

4
ui-ngx/src/app/modules/home/components/home-components.module.ts

@ -184,7 +184,6 @@ import {
import { EntityChipsComponent } from '@home/components/entity/entity-chips.component';
import { DashboardViewComponent } from '@home/components/dashboard-view/dashboard-view.component';
import { CalculatedFieldsTableComponent } from '@home/components/calculated-fields/calculated-fields-table.component';
import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe';
import { CalculatedFieldDialogComponent } from '@home/components/calculated-fields/components/dialog/calculated-field-dialog.component';
import {
EntityDebugSettingsButtonComponent
@ -204,6 +203,7 @@ import {
import {
CalculatedFieldTestArgumentsComponent
} from '@home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component';
import { EntityDebugSettingsService } from '@home/components/entity/debug/entity-debug-settings.service';
@NgModule({
declarations:
@ -504,7 +504,7 @@ import {
providers: [
WidgetComponentService,
CustomDialogService,
DurationLeftPipe,
EntityDebugSettingsService,
{provide: EMBED_DASHBOARD_DIALOG_TOKEN, useValue: EmbedDashboardDialogComponent},
{provide: COMPLEX_FILTER_PREDICATE_DIALOG_COMPONENT_TOKEN, useValue: ComplexFilterPredicateDialogComponent},
{provide: DASHBOARD_PAGE_COMPONENT_TOKEN, useValue: DashboardPageComponent},

11
ui-ngx/src/app/shared/models/entity.models.ts

@ -203,6 +203,17 @@ export interface EntityDebugSettings {
allEnabledUntil?: number;
}
export interface EntityDebugSettingPanelConfig {
debugSettings: EntityDebugSettings;
debugConfig: {
maxDebugModeDuration: number;
debugLimitsConfiguration: string;
entityLabel?: string;
additionalActionConfig?: AdditionalDebugActionConfig;
}
onSettingsAppliedFn: (settings: EntityDebugSettings) => void;
}
export interface EntityTestScriptResult {
output: string;
error: string;

2
ui-ngx/src/app/shared/shared.module.ts

@ -225,6 +225,7 @@ import { GroupingIntervalOptionsComponent } from '@shared/components/time/aggreg
import { JsFuncModulesComponent } from '@shared/components/js-func-modules.component';
import { JsFuncModuleRowComponent } from '@shared/components/js-func-module-row.component';
import { EntityKeyAutocompleteComponent } from '@shared/components/entity/entity-key-autocomplete.component';
import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe';
export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) {
return markedOptionsService;
@ -244,6 +245,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
ShortNumberPipe,
ImagePipe,
CustomTranslatePipe,
DurationLeftPipe,
{
provide: FlowInjectionToken,
useValue: Flow

Loading…
Cancel
Save