diff --git a/ui-ngx/src/app/modules/home/components/debug-config/debug-config-button.component.html b/ui-ngx/src/app/modules/home/components/debug-config/debug-config-button.component.html deleted file mode 100644 index bdaf2de487..0000000000 --- a/ui-ngx/src/app/modules/home/components/debug-config/debug-config-button.component.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - diff --git a/ui-ngx/src/app/modules/home/components/debug-config/debug-config-button.component.scss b/ui-ngx/src/app/modules/home/components/debug-config/debug-config-button.component.scss deleted file mode 100644 index 06fcba27be..0000000000 --- a/ui-ngx/src/app/modules/home/components/debug-config/debug-config-button.component.scss +++ /dev/null @@ -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); - } -} diff --git a/ui-ngx/src/app/modules/home/components/debug-config/debug-config-button.component.ts b/ui-ngx/src/app/modules/home/components/debug-config/debug-config-button.component.ts deleted file mode 100644 index c1a93d8ed9..0000000000 --- a/ui-ngx/src/app/modules/home/components/debug-config/debug-config-button.component.ts +++ /dev/null @@ -1,102 +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. -/// - -import { - Component, - Input, - Renderer2, - ViewContainerRef, - DestroyRef, - ChangeDetectionStrategy, - EventEmitter, - Output -} 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 { 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 { map } from 'rxjs/operators'; -import { getCurrentAuthState } from '@core/auth/auth.selectors'; -import { AppState } from '@core/core.state'; -import { Store } from '@ngrx/store'; - -@Component({ - selector: 'tb-debug-config-button', - templateUrl: './debug-config-button.component.html', - styleUrls: ['./debug-config-button.component.scss'], - standalone: true, - imports: [ - CommonModule, - SharedModule, - DurationLeftPipe, - ], - changeDetection: ChangeDetectionStrategy.OnPush -}) -export class DebugConfigButtonComponent { - - @Input() debugFailures = false; - @Input() debugAll = false; - @Input() debugAllUntil = 0; - @Input() disabled = false; - @Input() minifyMode = false; - @Input() debugLimitsConfiguration: string; - - @Output() onDebugConfigChanged = new EventEmitter(); - - isDebugAllActive$ = timer(0, SECOND).pipe(map(() => this.debugAllUntil > new Date().getTime() || this.debugAll), shareReplay(1)); - - readonly maxDebugModeDurationMinutes = getCurrentAuthState(this.store).maxDebugModeDurationMinutes; - - constructor(private popoverService: TbPopoverService, - private renderer: Renderer2, - private store: Store, - private viewContainerRef: ViewContainerRef, - private destroyRef: DestroyRef, - ) {} - - openDebugStrategyPanel($event: Event, matButton: MatButton): void { - if ($event) { - $event.stopPropagation(); - } - const trigger = matButton._elementRef.nativeElement; - if (this.popoverService.hasPopover(trigger)) { - this.popoverService.hidePopover(trigger); - } else { - const debugStrategyPopover = this.popoverService.displayPopover(trigger, this.renderer, - this.viewContainerRef, DebugConfigPanelComponent, 'bottom', true, null, - { - debugFailures: this.debugFailures, - debugAll: this.debugAll, - debugAllUntil: this.debugAllUntil, - 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.hide(); - }); - } - } -} diff --git a/ui-ngx/src/app/modules/home/components/debug-config/debug-config-panel.component.ts b/ui-ngx/src/app/modules/home/components/debug-config/debug-config-panel.component.ts deleted file mode 100644 index 7ad88955ba..0000000000 --- a/ui-ngx/src/app/modules/home/components/debug-config/debug-config-panel.component.ts +++ /dev/null @@ -1,112 +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. -/// - -import { - ChangeDetectionStrategy, - ChangeDetectorRef, - Component, - EventEmitter, - Input, - OnInit -} from '@angular/core'; -import { PageComponent } from '@shared/components/page.component'; -import { TbPopoverComponent } from '@shared/components/popover.component'; -import { UntypedFormBuilder } from '@angular/forms'; -import { CommonModule } from '@angular/common'; -import { SharedModule } from '@shared/shared.module'; -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 { distinctUntilChanged, map, tap } from 'rxjs/operators'; - -@Component({ - selector: 'tb-debug-config-panel', - templateUrl: './debug-config-panel.component.html', - standalone: true, - imports: [ - SharedModule, - CommonModule, - DurationLeftPipe - ], - changeDetection: ChangeDetectionStrategy.OnPush -}) -export class DebugConfigPanelComponent extends PageComponent implements OnInit { - - @Input() popover: TbPopoverComponent; - @Input() debugFailures = false; - @Input() debugAll = false; - @Input() debugAllUntil = 0; - @Input() maxDebugModeDurationMinutes: number; - @Input() debugLimitsConfiguration: string; - - onFailuresControl = this.fb.control(false); - debugAllControl = this.fb.control(false); - - maxMessagesCount: string; - maxTimeFrameSec: string; - - isDebugAllActive$ = timer(0, SECOND).pipe( - map(() => { - this.cd.markForCheck(); - return this.debugAllUntil > new Date().getTime() || this.debugAll; - }), - distinctUntilChanged(), - tap(isDebugOn => this.debugAllControl.patchValue(isDebugOn, { emitEvent: false })), - shareReplay(1), - ); - - onConfigApplied = new EventEmitter(); - - constructor(private fb: UntypedFormBuilder, private cd: ChangeDetectorRef) { - super(); - - this.observeDebugAllChange(); - } - - ngOnInit(): void { - this.maxMessagesCount = this.debugLimitsConfiguration?.split(':')[0]; - this.maxTimeFrameSec = this.debugLimitsConfiguration?.split(':')[1]; - this.onFailuresControl.patchValue(this.debugFailures); - } - - onCancel(): void { - this.popover?.hide(); - } - - onApply(): void { - this.onConfigApplied.emit({ - debugAll: this.debugAll, - debugFailures: this.onFailuresControl.value, - debugAllUntil: this.debugAllUntil - }); - } - - onReset(): void { - this.debugAll = true; - this.debugAllUntil = 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.cd.markForCheck(); - }); - } -} diff --git a/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.html b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.html new file mode 100644 index 0000000000..b779ae1e4c --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.html @@ -0,0 +1,32 @@ + + diff --git a/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.ts b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.ts new file mode 100644 index 0000000000..a344e93683 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.ts @@ -0,0 +1,155 @@ +/// +/// 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. +/// + +import { ChangeDetectionStrategy, 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 { DebugSettingsPanelComponent } from './debug-settings-panel.component'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { of, shareReplay, timer } from 'rxjs'; +import { SECOND } from '@shared/models/time/time.models'; +import { DebugSettings } from '@shared/models/entity.models'; +import { map, startWith, switchMap, takeWhile } 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 } from '@angular/forms'; + +@Component({ + 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 DebugSettingsButtonComponent implements ControlValueAccessor { + + @Input() debugLimitsConfiguration: string; + + debugSettingsFormGroup = this.fb.group({ + failuresEnabled: [false], + allEnabled: [false], + allEnabledUntil: [] + }); + + disabled = false; + + isDebugAllActive$ = this.debugSettingsFormGroup.get('allEnabled').valueChanges.pipe( + startWith(this.debugSettingsFormGroup.get('allEnabled').value), + switchMap(value => { + if (value) { + return of(true); + } else { + return timer(0, SECOND).pipe( + map(() => this.allEnabledUntil > new Date().getTime()), + takeWhile(value => value, true) + ); + } + }), + takeUntilDestroyed(), + shareReplay(1) + ); + + readonly maxDebugModeDurationMinutes = getCurrentAuthState(this.store).maxDebugModeDurationMinutes; + + private propagateChange: (settings: DebugSettings) => void; + + constructor(private popoverService: TbPopoverService, + private renderer: Renderer2, + private store: Store, + private viewContainerRef: ViewContainerRef, + private fb: FormBuilder, + ) { + this.debugSettingsFormGroup.valueChanges.pipe( + takeUntilDestroyed() + ).subscribe(value => { + this.propagateChange(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, DebugSettingsPanelComponent, 'bottom', true, null, + { + ...debugSettings, + maxDebugModeDurationMinutes: this.maxDebugModeDurationMinutes, + debugLimitsConfiguration: this.debugLimitsConfiguration + }, + {}, + {}, {}, true); + debugStrategyPopover.tbComponentRef.instance.popover = debugStrategyPopover; + debugStrategyPopover.tbComponentRef.instance.onSettingsApplied.subscribe((settings: DebugSettings) => { + this.debugSettingsFormGroup.patchValue(settings); + debugStrategyPopover.hide(); + }); + } + } + + registerOnChange(fn: (settings: DebugSettings) => void): void { + this.propagateChange = fn; + } + + registerOnTouched(_: () => void): void {} + + writeValue(settings: DebugSettings): void { + this.debugSettingsFormGroup.patchValue(settings, {emitEvent: false}); + this.debugSettingsFormGroup.get('allEnabled').updateValueAndValidity({onlySelf: true}); + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.debugSettingsFormGroup.disable({emitEvent: false}); + } else { + this.debugSettingsFormGroup.enable({emitEvent: false}); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/debug-config/debug-config-panel.component.html b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-panel.component.html similarity index 83% rename from ui-ngx/src/app/modules/home/components/debug-config/debug-config-panel.component.html rename to ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-panel.component.html index 379ad579eb..5fe0aa2546 100644 --- a/ui-ngx/src/app/modules/home/components/debug-config/debug-config-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-panel.component.html @@ -15,14 +15,15 @@ limitations under the License. --> -
+
debug-config.label
- + @if (debugLimitsConfiguration) { {{ 'debug-config.hint.main-limited' | translate: { msg: maxMessagesCount, sec: maxTimeFrameSec } }} - - {{ 'debug-config.hint.main' | translate }} + } @else { + {{ 'debug-config.hint.main' | translate }} + }
@@ -31,13 +32,13 @@ {{ 'debug-config.on-failure' | 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 }) } }}
-
-
- - tenant-profile.maximum-debug-duration-min - - - {{ 'tenant-profile.maximum-debug-duration-min-range' | translate }} - - - {{ 'tenant-profile.maximum-debug-duration-min-required' | translate }} - - - -
-
@@ -370,6 +354,25 @@
+
+ + {{ 'tenant-profile.debug' | translate }} + +
+ + tenant-profile.maximum-debug-duration-min + + + {{ 'tenant-profile.maximum-debug-duration-min-range' | translate }} + + + +
+
+
+
{{ 'tenant-profile.ota-files-in-bytes' | translate }} tenant-profile.unlimited diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts index c715a978b2..98c382b479 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts @@ -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)]], diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html index 5ae72a8880..13cc24a7b7 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html @@ -34,14 +34,11 @@ {{ 'rulenode.name-max-length' | translate }} -
- +