From 7277a0939cc8ccac7e70a74a0f2cb43b8c6a4109 Mon Sep 17 00:00:00 2001 From: Ekaterina Chantsova Date: Thu, 28 Nov 2024 20:15:08 +0200 Subject: [PATCH] Timewindow: apply list of allowed grouping interval options --- ...terval-options-config-panel.component.html | 4 +- ...terval-options-config-panel.component.scss | 3 +- ...interval-options-config-panel.component.ts | 82 +++++++++-- .../time/time-intervals-list.component.html | 4 +- .../time/time-intervals-list.component.ts | 10 +- .../timewindow-config-dialog.component.html | 6 +- .../timewindow-config-dialog.component.ts | 138 +++++++++++------- .../time/timewindow-panel.component.html | 8 +- .../time/timewindow-panel.component.ts | 55 ++++--- .../src/app/shared/models/time/time.models.ts | 64 +++++++- .../assets/locale/locale.constant-en_US.json | 2 +- 11 files changed, 255 insertions(+), 121 deletions(-) diff --git a/ui-ngx/src/app/shared/components/time/interval-options-config-panel.component.html b/ui-ngx/src/app/shared/components/time/interval-options-config-panel.component.html index 8368ce29af..1778863a01 100644 --- a/ui-ngx/src/app/shared/components/time/interval-options-config-panel.component.html +++ b/ui-ngx/src/app/shared/components/time/interval-options-config-panel.component.html @@ -26,7 +26,7 @@
{{"timewindow.interval" | translate }}
{{"timewindow.allowed-agg-intervals" | translate }}
-
{{"timewindow.preferred-agg-interval" | translate }}
+
{{"timewindow.default-agg-interval" | translate }}
@@ -54,7 +54,7 @@
; + aggIntervalsConfig: TimewindowAggIntervalsConfig +} @Component({ selector: 'tb-interval-options-config-panel', @@ -47,7 +53,7 @@ export class IntervalOptionsConfigPanelComponent implements OnInit { allowedIntervals: Array; @Input() - allowedAggIntervals: TimewindowAllowedAggIntervalsConfig; + aggIntervalsConfig: TimewindowAggIntervalsConfig; @Input() intervalType: RealtimeWindowType | HistoryWindowType; @@ -56,7 +62,7 @@ export class IntervalOptionsConfigPanelComponent implements OnInit { timewindowType: TimewindowType; @Input() - onClose: (result: Array | null) => void; + onClose: (result: IntervalOptionsConfigPanelData | null) => void; @Input() popoverComponent: TbPopoverComponent; @@ -68,6 +74,8 @@ export class IntervalOptionsConfigPanelComponent implements OnInit { private timeIntervalTranslationMap = QuickTimeIntervalTranslationMap; + private destroyRef = inject(DestroyRef); + constructor(private fb: FormBuilder, private timeService: TimeService, private translate: TranslateService) {} @@ -86,22 +94,36 @@ export class IntervalOptionsConfigPanelComponent implements OnInit { } this.intervalOptionsConfigForm = this.fb.group({ - allowedIntervals: [this.allowedIntervals?.length ? this.allowedIntervals : this.allIntervalValues], intervals: this.fb.array([]) }); const intervalControls: Array = []; for (const interval of this.allIntervals) { - const intervalConfig: TimewindowAllowedAggIntervalOption = this.allowedAggIntervals?.hasOwnProperty(interval.value) + const intervalConfig: TimewindowAggIntervalOptions = this.aggIntervalsConfig?.hasOwnProperty(interval.value) ? this.allIntervalValues[interval.value] : null; - intervalControls.push(this.fb.group({ + const intervalEnabled = this.allowedIntervals?.length ? this.allowedIntervals.includes(interval.value) : true; + const intervalControl = this.fb.group({ name: [this.translate.instant(interval.name, interval.translateParams)], value: [interval.value], - enabled: [this.allowedIntervals?.length ? this.allowedIntervals.includes(interval.value) : true], - aggIntervals: [intervalConfig ? intervalConfig.aggIntervals : []], - preferredAggInterval: [intervalConfig ? intervalConfig.preferredAggInterval : null] - })); + enabled: [intervalEnabled], + aggIntervals: [{value: intervalConfig ? intervalConfig.aggIntervals : [], disabled: !(intervalEnabled && this.aggregation)}], + defaultAggInterval: [{value: intervalConfig ? intervalConfig.defaultAggInterval : null, disabled: !(intervalEnabled && this.aggregation)}], + }); + if (this.aggregation) { + intervalControl.get('enabled').valueChanges.pipe( + takeUntilDestroyed(this.destroyRef) + ).subscribe((intervalEnabled) => { + if (intervalEnabled) { + intervalControl.get('aggIntervals').enable({emitEvent: false}); + intervalControl.get('defaultAggInterval').enable({emitEvent: false}); + } else { + intervalControl.get('aggIntervals').disable({emitEvent: false}); + intervalControl.get('defaultAggInterval').disable({emitEvent: false}); + } + }); + } + intervalControls.push(intervalControl); } this.intervalOptionsConfigForm.setControl('intervals', this.fb.array(intervalControls), {emitEvent: false}); } @@ -132,9 +154,30 @@ export class IntervalOptionsConfigPanelComponent implements OnInit { update() { if (this.onClose) { - const allowedIntervals = this.intervalOptionsConfigForm.get('allowedIntervals').value; - // if full list selected returns empty for optimization - this.onClose(allowedIntervals?.length < this.allIntervals.length ? allowedIntervals : []); + const allowedIntervals: Array = []; + const aggIntervalsConfig: TimewindowAggIntervalsConfig = {}; + const intervalOptionsConfig = this.intervalOptionsConfigForm.get('intervals').value; + for (const interval of intervalOptionsConfig) { + if (interval.enabled) { + allowedIntervals.push(interval.value); + if (this.aggregation && (interval.aggIntervals.length || interval.defaultAggInterval)) { + const intervalParams: TimewindowAggIntervalOptions = {}; + if (interval.aggIntervals.length) { + intervalParams.aggIntervals = interval.aggIntervals; + } + if (interval.defaultAggInterval) { + intervalParams.defaultAggInterval = interval.defaultAggInterval; + } + aggIntervalsConfig[interval.value] = intervalParams; + } + } + } + console.log(aggIntervalsConfig); + this.onClose({ + // if full list selected returns empty for optimization + allowedIntervals: allowedIntervals?.length < this.allIntervals.length ? allowedIntervals : [], + aggIntervalsConfig + }); } } @@ -145,7 +188,14 @@ export class IntervalOptionsConfigPanelComponent implements OnInit { } reset() { - this.intervalOptionsConfigForm.reset(); + const intervalControls = this.intervalsFormArray.controls; + for (const interval of intervalControls) { + interval.patchValue({ + enabled: true, + aggIntervals: [], + defaultAggInterval: null, + }); + } this.intervalOptionsConfigForm.markAsDirty(); } diff --git a/ui-ngx/src/app/shared/components/time/time-intervals-list.component.html b/ui-ngx/src/app/shared/components/time/time-intervals-list.component.html index d6f101c030..ddcdd16fcb 100644 --- a/ui-ngx/src/app/shared/components/time/time-intervals-list.component.html +++ b/ui-ngx/src/app/shared/components/time/time-intervals-list.component.html @@ -15,11 +15,11 @@ limitations under the License. --> -
+
{{ predefinedName }} - + {{ interval.name | translate:interval.translateParams }} diff --git a/ui-ngx/src/app/shared/components/time/time-intervals-list.component.ts b/ui-ngx/src/app/shared/components/time/time-intervals-list.component.ts index 4deba4a271..b954f17390 100644 --- a/ui-ngx/src/app/shared/components/time/time-intervals-list.component.ts +++ b/ui-ngx/src/app/shared/components/time/time-intervals-list.component.ts @@ -67,7 +67,8 @@ export class TimeIntervalsListComponent implements OnInit, ControlValueAccessor @Input() appearance: MatFormFieldAppearance = 'fill'; - intervals: Array; + allIntervals: Array; + allIntervalValues: Array; timeintervalFormGroup: FormGroup; @@ -119,12 +120,13 @@ export class TimeIntervalsListComponent implements OnInit, ControlValueAccessor } private updateIntervalsList() { - this.intervals = this.timeService.getIntervals(this.min, this.max, this.useCalendarIntervals); + this.allIntervals = this.timeService.getIntervals(this.min, this.max, this.useCalendarIntervals); + this.allIntervalValues = this.allIntervals.map(interval => interval.value); } private setIntervals(intervals: Array) { this.timeintervalFormGroup.get('intervals').patchValue( - (this.setAllIfEmpty && !intervals?.length) ? this.intervals : intervals, + (this.setAllIfEmpty && !intervals?.length) ? this.allIntervalValues : intervals, {emitEvent: false}); } @@ -135,7 +137,7 @@ export class TimeIntervalsListComponent implements OnInit, ControlValueAccessor let value: Array; const intervals: Array = this.timeintervalFormGroup.get('intervals').value; - if (!this.returnEmptyIfAllSet || intervals.length < this.intervals.length) { + if (!this.returnEmptyIfAllSet || intervals.length < this.allIntervals.length) { value = intervals; } else { value = []; 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 4c5b250ba6..3574aff0b1 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 @@ -240,7 +240,8 @@ { const timewindowFormValue = this.timewindowForm.getRawValue(); - if (timewindowFormValue.history.historyType === HistoryWindowType.LAST_INTERVAL) { - return timewindowFormValue.history.timewindowMs; - } else if (timewindowFormValue.history.historyType === HistoryWindowType.INTERVAL) { - return quickTimeIntervalPeriod(timewindowFormValue.history.quickInterval); - } else if (timewindowFormValue.history.fixedTimewindow) { - return timewindowFormValue.history.fixedTimewindow.endTimeMs - - timewindowFormValue.history.fixedTimewindow.startTimeMs; - } else { - return DAY; - } + return realtimeAllowedAggIntervals(timewindowFormValue, timewindowFormValue.realtime.advancedParams); + } + + get historyAllowedAggIntervals(): Array { + const timewindowFormValue = this.timewindowForm.getRawValue(); + return historyAllowedAggIntervals(timewindowFormValue, timewindowFormValue.history.advancedParams); } openAggregationOptionsConfig($event: Event) { @@ -499,38 +527,32 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On } configureRealtimeLastIntervalOptions($event: Event) { - const resFn = (res) => { - this.timewindowForm.get('realtime.advancedParams.allowedLastIntervals').patchValue(res); - }; - this.openIntervalOptionsConfig($event, this.timewindowForm.get('realtime.advancedParams.allowedLastIntervals').value, - resFn, RealtimeWindowType.LAST_INTERVAL); + this.openIntervalOptionsConfig($event, + 'realtime.advancedParams.allowedLastIntervals', 'realtime.advancedParams.lastAggIntervalsConfig', + RealtimeWindowType.LAST_INTERVAL); } configureRealtimeQuickIntervalOptions($event: Event) { - const resFn = (res) => { - this.timewindowForm.get('realtime.advancedParams.allowedQuickIntervals').patchValue(res); - }; - this.openIntervalOptionsConfig($event, this.timewindowForm.get('realtime.advancedParams.allowedQuickIntervals').value, - resFn, RealtimeWindowType.INTERVAL, TimewindowType.REALTIME); + this.openIntervalOptionsConfig($event, + 'realtime.advancedParams.allowedQuickIntervals', 'realtime.advancedParams.quickAggIntervalsConfig', + RealtimeWindowType.INTERVAL, TimewindowType.REALTIME); } configureHistoryLastIntervalOptions($event: Event) { - const resFn = (res) => { - this.timewindowForm.get('history.advancedParams.allowedLastIntervals').patchValue(res); - }; - this.openIntervalOptionsConfig($event, this.timewindowForm.get('history.advancedParams.allowedLastIntervals').value, - resFn, HistoryWindowType.LAST_INTERVAL); + this.openIntervalOptionsConfig($event, + 'history.advancedParams.allowedLastIntervals', 'history.advancedParams.lastAggIntervalsConfig', + HistoryWindowType.LAST_INTERVAL); } configureHistoryQuickIntervalOptions($event: Event) { - const resFn = (res) => { - this.timewindowForm.get('history.advancedParams.allowedQuickIntervals').patchValue(res); - }; - this.openIntervalOptionsConfig($event, this.timewindowForm.get('history.advancedParams.allowedQuickIntervals').value, - resFn, HistoryWindowType.INTERVAL, TimewindowType.HISTORY); + this.openIntervalOptionsConfig($event, + 'history.advancedParams.allowedQuickIntervals', 'history.advancedParams.quickAggIntervalsConfig', + HistoryWindowType.INTERVAL, TimewindowType.HISTORY); } - private openIntervalOptionsConfig($event: Event, allowedIntervals: Array, resFn: (res) => void, + private openIntervalOptionsConfig($event: Event, + allowedIntervalsControlName: string, + aggIntervalsConfigControlName: string, intervalType: RealtimeWindowType | HistoryWindowType, timewindowType?: TimewindowType) { if ($event) { $event.stopPropagation(); @@ -543,12 +565,16 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On this.viewContainerRef, IntervalOptionsConfigPanelComponent, ['left', 'leftTop', 'leftBottom'], true, null, { aggregation: this.aggregation, - allowedIntervals: deepClone(allowedIntervals), + allowedIntervals: deepClone(this.timewindowForm.get(allowedIntervalsControlName).value), + aggIntervalsConfig: deepClone(this.timewindowForm.get(aggIntervalsConfigControlName).value), intervalType: intervalType, timewindowType: timewindowType, - onClose: (result: Array | null) => { + onClose: (result: IntervalOptionsConfigPanelData | null) => { intervalsConfigPopover.hide(); - resFn(result); + if (result) { + this.timewindowForm.get(allowedIntervalsControlName).patchValue(result.allowedIntervals); + this.timewindowForm.get(aggIntervalsConfigControlName).patchValue(result.aggIntervalsConfig); + } } }, {maxHeight: '500px', height: '100%'}, 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 68db208d0a..d59a206d73 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 @@ -140,7 +140,7 @@ *ngIf="timewindowForm.get('aggregation.type').value === aggregationTypes.NONE && (isEdit || !timewindow.hideAggInterval)">
{{ 'aggregation.limit' | translate }}
+ [required]="timewindowForm.get('aggregation.type').value === aggregationTypes.NONE">
@@ -150,7 +150,8 @@ ; realtimeAllowedQuickIntervals: Array; + historyAdvancedParams: TimewindowAdvancedParams; historyAllowedLastIntervals: Array; historyAllowedQuickIntervals: Array; allowedAggTypes: Array; @@ -436,46 +439,36 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O this.overlayRef.dispose(); } - minRealtimeAggInterval() { + get minRealtimeAggInterval() { return this.timeService.minIntervalLimit(this.currentRealtimeTimewindow()); } - maxRealtimeAggInterval() { + get maxRealtimeAggInterval() { return this.timeService.maxIntervalLimit(this.currentRealtimeTimewindow()); } - currentRealtimeTimewindow(): number { - const timeWindowFormValue = this.timewindowForm.getRawValue(); - switch (timeWindowFormValue.realtime.realtimeType) { - case RealtimeWindowType.LAST_INTERVAL: - return timeWindowFormValue.realtime.timewindowMs; - case RealtimeWindowType.INTERVAL: - return quickTimeIntervalPeriod(timeWindowFormValue.realtime.quickInterval); - default: - return DAY; - } + private currentRealtimeTimewindow(): number { + return currentRealtimeTimewindow(this.timewindowForm.getRawValue()); } - minHistoryAggInterval() { + get minHistoryAggInterval() { return this.timeService.minIntervalLimit(this.currentHistoryTimewindow()); } - maxHistoryAggInterval() { + get maxHistoryAggInterval() { return this.timeService.maxIntervalLimit(this.currentHistoryTimewindow()); } - currentHistoryTimewindow() { - const timewindowFormValue = this.timewindowForm.getRawValue(); - if (timewindowFormValue.history.historyType === HistoryWindowType.LAST_INTERVAL) { - return timewindowFormValue.history.timewindowMs; - } else if (timewindowFormValue.history.historyType === HistoryWindowType.INTERVAL) { - return quickTimeIntervalPeriod(timewindowFormValue.history.quickInterval); - } else if (timewindowFormValue.history.fixedTimewindow) { - return timewindowFormValue.history.fixedTimewindow.endTimeMs - - timewindowFormValue.history.fixedTimewindow.startTimeMs; - } else { - return DAY; - } + private currentHistoryTimewindow(): number { + return currentHistoryTimewindow(this.timewindowForm.getRawValue()); + } + + get realtimeAllowedAggIntervals(): Array { + return realtimeAllowedAggIntervals(this.timewindowForm.getRawValue(), this.realtimeAdvancedParams); + } + + get historyAllowedAggIntervals(): Array { + return historyAllowedAggIntervals(this.timewindowForm.getRawValue(), this.historyAdvancedParams); } openTimewindowConfig() { @@ -507,16 +500,20 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O this.historyDisableCustomGroupInterval = this.timewindow.history.disableCustomGroupInterval; if (this.timewindow.realtime.advancedParams) { + this.realtimeAdvancedParams = this.timewindow.realtime.advancedParams; this.realtimeAllowedLastIntervals = this.timewindow.realtime.advancedParams.allowedLastIntervals; this.realtimeAllowedQuickIntervals = this.timewindow.realtime.advancedParams.allowedQuickIntervals; } else { + this.realtimeAdvancedParams = null; this.realtimeAllowedLastIntervals = null; this.realtimeAllowedQuickIntervals = null; } if (this.timewindow.history.advancedParams) { + this.historyAdvancedParams = this.timewindow.history.advancedParams; this.historyAllowedLastIntervals = this.timewindow.history.advancedParams.allowedLastIntervals; this.historyAllowedQuickIntervals = this.timewindow.history.advancedParams.allowedQuickIntervals; } else { + this.historyAdvancedParams = null; this.historyAllowedLastIntervals = null; this.historyAllowedQuickIntervals = null; } 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 3cfc4c69c6..1b9c0c8dba 100644 --- a/ui-ngx/src/app/shared/models/time/time.models.ts +++ b/ui-ngx/src/app/shared/models/time/time.models.ts @@ -88,17 +88,19 @@ export class IntervalMath { export interface TimewindowAdvancedParams { allowedLastIntervals? : Array; allowedQuickIntervals? : Array; + lastAggIntervalsConfig? : TimewindowAggIntervalsConfig; + quickAggIntervalsConfig? : TimewindowAggIntervalsConfig; } export type TimewindowInterval = Interval | QuickTimeInterval; -export interface TimewindowAllowedAggIntervalsConfig { - [key: string]: TimewindowAllowedAggIntervalOption; +export interface TimewindowAggIntervalsConfig { + [key: string]: TimewindowAggIntervalOptions; } -export interface TimewindowAllowedAggIntervalOption { - aggIntervals: Array; - preferredAggInterval: TimewindowInterval; +export interface TimewindowAggIntervalOptions { + aggIntervals?: Array; + defaultAggInterval?: Interval; } export interface IntervalWindow { @@ -565,6 +567,58 @@ export const updateFormValuesOnTimewindowTypeChange = (selectedTab: TimewindowTy }); }; +export const currentRealtimeTimewindow = (timewindow: Timewindow): number => { + switch (timewindow.realtime.realtimeType) { + case RealtimeWindowType.LAST_INTERVAL: + return timewindow.realtime.timewindowMs; + case RealtimeWindowType.INTERVAL: + return quickTimeIntervalPeriod(timewindow.realtime.quickInterval); + default: + return DAY; + } +}; + +export const currentHistoryTimewindow = (timewindow: Timewindow): number => { + if (timewindow.history.historyType === HistoryWindowType.LAST_INTERVAL) { + return timewindow.history.timewindowMs; + } else if (timewindow.history.historyType === HistoryWindowType.INTERVAL) { + return quickTimeIntervalPeriod(timewindow.history.quickInterval); + } else if (timewindow.history.fixedTimewindow) { + return timewindow.history.fixedTimewindow.endTimeMs - + timewindow.history.fixedTimewindow.startTimeMs; + } else { + return DAY; + } +} + +export const realtimeAllowedAggIntervals = (timewindow: Timewindow, + advancedParams: TimewindowAdvancedParams): Array => { + if (timewindow.realtime.realtimeType === RealtimeWindowType.LAST_INTERVAL && + advancedParams?.lastAggIntervalsConfig?.hasOwnProperty(timewindow.realtime.timewindowMs) && + advancedParams.lastAggIntervalsConfig[timewindow.realtime.timewindowMs].aggIntervals?.length) { + return advancedParams.lastAggIntervalsConfig[timewindow.realtime.timewindowMs].aggIntervals; + } else if (timewindow.realtime.realtimeType === RealtimeWindowType.INTERVAL && + advancedParams?.quickAggIntervalsConfig?.hasOwnProperty(timewindow.realtime.quickInterval) && + advancedParams.quickAggIntervalsConfig[timewindow.realtime.quickInterval].aggIntervals?.length) { + return advancedParams.quickAggIntervalsConfig[timewindow.realtime.quickInterval].aggIntervals; + } + return []; +}; + +export const historyAllowedAggIntervals = (timewindow: Timewindow, + advancedParams: TimewindowAdvancedParams): Array => { + if (timewindow.history.historyType === HistoryWindowType.LAST_INTERVAL && + advancedParams?.lastAggIntervalsConfig?.hasOwnProperty(timewindow.history.timewindowMs) && + advancedParams.lastAggIntervalsConfig[timewindow.history.timewindowMs].aggIntervals?.length) { + return advancedParams.lastAggIntervalsConfig[timewindow.history.timewindowMs].aggIntervals; + } else if (timewindow.history.historyType === HistoryWindowType.INTERVAL && + advancedParams?.quickAggIntervalsConfig?.hasOwnProperty(timewindow.history.quickInterval) && + advancedParams.quickAggIntervalsConfig[timewindow.history.quickInterval].aggIntervals?.length) { + return advancedParams.quickAggIntervalsConfig[timewindow.history.quickInterval].aggIntervals; + } + return []; +}; + export const getTimezone = (tz: string): moment_.Moment => moment.tz(tz); export const calculateTsOffset = (timezone?: string): number => { 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 fc166eaa87..839bbaeb04 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -4710,7 +4710,7 @@ "allowed-aggregation-functions": "Allowed aggregation functions", "edit-intervals-list": "Edit intervals list", "allowed-agg-intervals": "Allowed grouping intervals", - "preferred-agg-interval": "Preferred intervals", + "default-agg-interval": "Default grouping interval", "edit-intervals-list-hint": "List of available interval options can be specified.", "edit-grouping-intervals-list-hint": "It is possible to configure the grouping intervals list and default grouping interval." },