diff --git a/ui-ngx/src/app/shared/components/aggregation/aggregation-options-config-panel.component.html b/ui-ngx/src/app/shared/components/aggregation/aggregation-options-config-panel.component.html index 35016c6a28..ce7494b856 100644 --- a/ui-ngx/src/app/shared/components/aggregation/aggregation-options-config-panel.component.html +++ b/ui-ngx/src/app/shared/components/aggregation/aggregation-options-config-panel.component.html @@ -15,10 +15,33 @@ limitations under the License. --> -
- - - {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }} - - -
+
+
{{ 'timewindow.edit-aggregation-functions-list' | translate }}
+
{{ 'timewindow.edit-aggregation-functions-list-hint' | translate }}
+
+
+
{{"timewindow.allowed-aggregation-functions" | translate }}
+
+
+ + + {{ aggregationTypesTranslations.get(aggregationTypes[type]) | translate }} + + +
+
+
+ + +
+
diff --git a/ui-ngx/src/app/shared/components/aggregation/aggregation-options-config-panel.component.scss b/ui-ngx/src/app/shared/components/aggregation/aggregation-options-config-panel.component.scss index b9dc294716..903097ba6b 100644 --- a/ui-ngx/src/app/shared/components/aggregation/aggregation-options-config-panel.component.scss +++ b/ui-ngx/src/app/shared/components/aggregation/aggregation-options-config-panel.component.scss @@ -13,5 +13,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +:host { + .tb-aggregation-options-form { + height: 100%; + max-width: 350px; + .tb-form-table { + overflow: hidden; + } + + .tb-form-table-body { + overflow-y: auto; + } + + .tb-form-hint { + flex-shrink: 0; + } + + .mdc-list { + display: flex; + flex-direction: column; + gap: 8px; + + .mat-mdc-list-item.mdc-list-item--with-leading-checkbox.mdc-list-item--with-one-line { + height: 40px; + } + } + } +} diff --git a/ui-ngx/src/app/shared/components/aggregation/aggregation-options-config-panel.component.ts b/ui-ngx/src/app/shared/components/aggregation/aggregation-options-config-panel.component.ts index 1b789a747c..bddbe3fba3 100644 --- a/ui-ngx/src/app/shared/components/aggregation/aggregation-options-config-panel.component.ts +++ b/ui-ngx/src/app/shared/components/aggregation/aggregation-options-config-panel.component.ts @@ -19,10 +19,6 @@ import { aggregationTranslations, AggregationType } from '@shared/models/time/ti import { FormBuilder, FormGroup } from '@angular/forms'; import { TbPopoverComponent } from '@shared/components/popover.component'; -export interface AggregationOptionsSelectionResult { - allowedAggregationTypes: AggregationType[] | null; -} - @Component({ selector: 'tb-aggregation-options-config-panel', templateUrl: './aggregation-options-config-panel.component.html', @@ -34,7 +30,7 @@ export class AggregationOptionsConfigPanelComponent implements OnInit { allowedAggregationTypes: Array; @Input() - onClose: (result: AggregationOptionsSelectionResult | null) => void; + onClose: (result: Array | null) => void; @Input() popoverComponent: TbPopoverComponent; @@ -43,7 +39,7 @@ export class AggregationOptionsConfigPanelComponent implements OnInit { aggregationTypes = AggregationType; - aggregations = Object.keys(AggregationType); + allAggregationTypes: Array = Object.values(AggregationType); aggregationTypesTranslations = aggregationTranslations; @@ -57,9 +53,9 @@ export class AggregationOptionsConfigPanelComponent implements OnInit { update() { if (this.onClose) { - this.onClose({ - allowedAggregationTypes: this.aggregationOptionsConfigForm.get('allowedAggregationTypes').value - }); + const allowedAggregationTypes = this.aggregationOptionsConfigForm.get('allowedAggregationTypes').value; + // if full list selected returns empty for optimization + this.onClose(allowedAggregationTypes?.length < this.allAggregationTypes.length ? allowedAggregationTypes : []); } } diff --git a/ui-ngx/src/app/shared/components/aggregation/aggregation-type-select.component.html b/ui-ngx/src/app/shared/components/aggregation/aggregation-type-select.component.html index b9a9cdd93e..5e80fc3237 100644 --- a/ui-ngx/src/app/shared/components/aggregation/aggregation-type-select.component.html +++ b/ui-ngx/src/app/shared/components/aggregation/aggregation-type-select.component.html @@ -15,7 +15,9 @@ limitations under the License. --> - + {{ label }} diff --git a/ui-ngx/src/app/shared/components/aggregation/aggregation-type-select.component.ts b/ui-ngx/src/app/shared/components/aggregation/aggregation-type-select.component.ts index 25ca4f34b4..7986a28f82 100644 --- a/ui-ngx/src/app/shared/components/aggregation/aggregation-type-select.component.ts +++ b/ui-ngx/src/app/shared/components/aggregation/aggregation-type-select.component.ts @@ -112,7 +112,7 @@ export class AggregationTypeSelectComponent implements ControlValueAccessor, OnI this.aggregationTypes = this.allowedAggregationTypes?.length ? this.allowedAggregationTypes : this.allAggregationTypes; const currentAggregationType: AggregationType = this.aggregationTypeFormGroup.get('aggregationType').value; if (currentAggregationType && !this.aggregationTypes.includes(currentAggregationType)) { - this.aggregationTypeFormGroup.get('aggregationType').patchValue(null, {emitEvent: true}); + this.aggregationTypeFormGroup.get('aggregationType').patchValue(this.aggregationTypes[0], {emitEvent: true}); } } } diff --git a/ui-ngx/src/app/shared/components/time/quick-time-interval.component.scss b/ui-ngx/src/app/shared/components/time/quick-time-interval.component.scss index de583225fb..f3cd8fdfeb 100644 --- a/ui-ngx/src/app/shared/components/time/quick-time-interval.component.scss +++ b/ui-ngx/src/app/shared/components/time/quick-time-interval.component.scss @@ -16,7 +16,7 @@ @import '../../../../scss/constants'; :host { - min-width: 355px; + min-width: 300px; display: block; @media #{$mat-xs} { diff --git a/ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.html b/ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.html index dbfb9e37ea..db6c207f8d 100644 --- a/ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.html +++ b/ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.html @@ -51,7 +51,7 @@ {{ 'timewindow.disable-custom-interval' | translate }} -
+
@@ -70,7 +70,7 @@
+ class="tb-form-row column-xs">
@@ -107,7 +107,7 @@ {{ 'timewindow.disable-custom-interval' | translate }}
-
+
{{ 'timewindow.hide' | translate }} @@ -124,7 +124,7 @@
-
+
{{ 'timewindow.hide' | translate }} @@ -140,7 +140,7 @@
-
+
{{ 'timewindow.hide' | translate }} @@ -168,8 +168,10 @@ - diff --git a/ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.ts b/ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.ts index f99dd02bf2..8ebd6395c9 100644 --- a/ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.ts +++ b/ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.ts @@ -31,13 +31,12 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { TimeService } from '@core/services/time.service'; -import { isDefined, isDefinedAndNotNull, mergeDeep } from '@core/utils'; +import { deepClone, isDefined, isDefinedAndNotNull, mergeDeep } from '@core/utils'; import { ToggleHeaderOption } from '@shared/components/toggle-header.component'; import { TranslateService } from '@ngx-translate/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; -import { TimezoneSelectionResult } from '@shared/components/time/timezone-panel.component'; import { TbPopoverService } from '@shared/components/popover.service'; import { AggregationOptionsConfigPanelComponent @@ -198,6 +197,8 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On limit: [ isDefined(aggregation?.limit) ? this.timewindow.aggregation.limit : null ] }), timezone: [ isDefined(this.timewindow.timezone) ? this.timewindow.timezone : null ], + allowedAggTypes: [ isDefinedAndNotNull(this.timewindow.allowedAggTypes) + ? this.timewindow.allowedAggTypes : null ], hideAggregation: [ isDefinedAndNotNull(this.timewindow.hideAggregation) ? this.timewindow.hideAggregation : false ], hideAggInterval: [ isDefinedAndNotNull(this.timewindow.hideAggInterval) @@ -289,6 +290,13 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On } } }); + this.timewindowForm.get('hideAggregation').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value: boolean) => { + if (value) { + this.timewindowForm.get('allowedAggTypes').patchValue([]); + } + }); } ngOnDestroy() { @@ -344,6 +352,11 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On update() { const timewindowFormValue = this.timewindowForm.getRawValue(); this.timewindow = mergeDeep(this.timewindow, timewindowFormValue); + if (timewindowFormValue.allowedAggTypes?.length) { + this.timewindow.allowedAggTypes = timewindowFormValue.allowedAggTypes; + } else { + delete this.timewindow.allowedAggTypes; + } if (!this.aggregation) { delete this.timewindow.aggregation; } @@ -405,18 +418,19 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On this.popoverService.hidePopover(trigger); } else { const aggregationConfigPopover = this.popoverService.displayPopover(trigger, this.renderer, - this.viewContainerRef, AggregationOptionsConfigPanelComponent, ['bottomRight', 'leftBottom'], true, null, + this.viewContainerRef, AggregationOptionsConfigPanelComponent, ['left', 'leftTop', 'leftBottom'], true, null, { - allowedAggregationTypes: null, - onClose: (result: TimezoneSelectionResult | null) => { + allowedAggregationTypes: deepClone(this.timewindowForm.get('allowedAggTypes').value), + onClose: (result: Array | null) => { aggregationConfigPopover.hide(); if (result) { - console.log(result); + this.timewindowForm.get('allowedAggTypes').patchValue(result); + this.timewindowForm.markAsDirty(); } } }, - {}, - {}, {}, false); + {maxHeight: '90vh', height: '100%'}, + {}, {}, true, () => {}, {padding: 0}); aggregationConfigPopover.tbComponentRef.instance.popoverComponent = aggregationConfigPopover; } this.cd.detectChanges(); diff --git a/ui-ngx/src/app/shared/components/time/timewindow-panel.component.html b/ui-ngx/src/app/shared/components/time/timewindow-panel.component.html index a76df1ffd1..703e8f98c7 100644 --- a/ui-ngx/src/app/shared/components/time/timewindow-panel.component.html +++ b/ui-ngx/src/app/shared/components/time/timewindow-panel.component.html @@ -126,7 +126,7 @@
{{ 'aggregation.aggregation' | translate }}
+ formControlName="type" [allowedAggregationTypes]="allowedAggTypes">
diff --git a/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts b/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts index 2037a3578b..0ddd3d9892 100644 --- a/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts +++ b/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts @@ -103,6 +103,8 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O historyIntervalSelectionAvailable: boolean; aggregationOptionsAvailable: boolean; + allowedAggTypes: Array; + private destroy$ = new Subject(); constructor(@Inject(TIMEWINDOW_PANEL_DATA) public data: TimewindowPanelData, @@ -122,6 +124,8 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O this.timezone = data.timezone; this.isEdit = data.isEdit; + this.allowedAggTypes = this.timewindow.allowedAggTypes; + if (!this.historyOnly) { this.timewindowTypeOptions.unshift({ name: this.translate.instant('timewindow.realtime'), @@ -366,6 +370,9 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O fixedTimewindow: timewindowFormValue.history.fixedTimewindow, quickInterval: timewindowFormValue.history.quickInterval, }}; + if (!this.timewindow.allowedAggTypes?.length) { + delete this.timewindow.allowedAggTypes; + } if (this.aggregation) { this.timewindow.aggregation = { type: timewindowFormValue.aggregation.type, @@ -508,6 +515,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O .subscribe((res) => { if (res) { this.timewindow = res; + this.allowedAggTypes = this.timewindow.allowedAggTypes; this.updateTimewindowForm(); } }); diff --git a/ui-ngx/src/app/shared/models/time/time.models.ts b/ui-ngx/src/app/shared/models/time/time.models.ts index 96093675f8..83cb5a6403 100644 --- a/ui-ngx/src/app/shared/models/time/time.models.ts +++ b/ui-ngx/src/app/shared/models/time/time.models.ts @@ -139,6 +139,7 @@ export interface Aggregation { export interface Timewindow { displayValue?: string; displayTimezoneAbbr?: string; + allowedAggTypes?: Array; hideAggregation?: boolean; hideAggInterval?: boolean; hideTimezone?: boolean; @@ -301,6 +302,9 @@ export const initModelFromDefaultTimewindow = (value: Timewindow, quickIntervalO historyOnly: boolean, timeService: TimeService): Timewindow => { const model = defaultTimewindow(timeService); if (value) { + if (value.allowedAggTypes?.length) { + model.allowedAggTypes = value.allowedAggTypes; + } model.hideAggregation = value.hideAggregation; model.hideAggInterval = value.hideAggInterval; model.hideTimezone = value.hideTimezone; @@ -429,7 +433,7 @@ export const toHistoryTimewindow = (timewindow: Timewindow, startTimeMs: number, aggType = AggregationType.AVG; limit = timeService.getMaxDatapointsLimit(); } - return { + const historyTimewindow: Timewindow = { hideAggregation: timewindow.hideAggregation || false, hideAggInterval: timewindow.hideAggInterval || false, hideTimezone: timewindow.hideTimezone || false, @@ -451,6 +455,10 @@ export const toHistoryTimewindow = (timewindow: Timewindow, startTimeMs: number, }, timezone: timewindow.timezone }; + if (timewindow.allowedAggTypes?.length) { + historyTimewindow.allowedAggTypes = timewindow.allowedAggTypes; + } + return historyTimewindow; }; export const timewindowTypeChanged = (newTimewindow: Timewindow, oldTimewindow: Timewindow): boolean => { @@ -898,6 +906,9 @@ export const createTimewindowForComparison = (subscriptionTimewindow: Subscripti export const cloneSelectedTimewindow = (timewindow: Timewindow): Timewindow => { const cloned: Timewindow = {}; + if (timewindow.allowedAggTypes?.length) { + cloned.allowedAggTypes = timewindow.allowedAggTypes; + } cloned.hideAggregation = timewindow.hideAggregation || false; cloned.hideAggInterval = timewindow.hideAggInterval || false; cloned.hideTimezone = timewindow.hideTimezone || false; diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index d4a8cffa53..6387c4a543 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -5216,7 +5216,10 @@ "hide-group-interval": "Hide grouping interval from end-users", "hide-max-values": "Hide max values from end-users", "hide-timezone": "Hide time zone from end-users", - "disable-custom-interval": "Disable custom interval selection" + "disable-custom-interval": "Disable custom interval selection", + "edit-aggregation-functions-list": "Edit aggregation functions list", + "edit-aggregation-functions-list-hint": "List of available options can be specified.", + "allowed-aggregation-functions": "Allowed aggregation functions" }, "tooltip": { "trigger": "Trigger",