diff --git a/ui-ngx/src/app/modules/common/modules-map.ts b/ui-ngx/src/app/modules/common/modules-map.ts index 794bdffd10..0cc3f5bb2f 100644 --- a/ui-ngx/src/app/modules/common/modules-map.ts +++ b/ui-ngx/src/app/modules/common/modules-map.ts @@ -337,7 +337,6 @@ import * as DatapointsLimitComponent from '@shared/components/time/datapoints-li import * as AggregationTypeSelectComponent from '@shared/components/time/aggregation/aggregation-type-select.component'; import * as AggregationOptionsConfigComponent from '@shared/components/time/aggregation/aggregation-options-config-panel.component'; import * as IntervalOptionsConfigPanelComponent from '@shared/components/time/interval-options-config-panel.component'; -import * as TimeIntervalsListComponent from '@shared/components/time/time-intervals-list.component'; import { IModulesMap } from '@modules/common/modules-map.models'; import { Observable, map, of } from 'rxjs'; @@ -478,7 +477,6 @@ class ModulesMap implements IModulesMap { '@shared/components/time/aggregation/aggregation-type-select.component': AggregationTypeSelectComponent, '@shared/components/time/aggregation/aggregation-options-config-panel.component': AggregationOptionsConfigComponent, '@shared/components/time/interval-options-config-panel.component': IntervalOptionsConfigPanelComponent, - '@shared/components/time/time-intervals-list.component': TimeIntervalsListComponent, '@shared/components/value-input.component': ValueInputComponent, '@shared/components/dashboard-autocomplete.component': DashboardAutocompleteComponent, '@shared/components/entity/entity-subtype-autocomplete.component': EntitySubTypeAutocompleteComponent, diff --git a/ui-ngx/src/app/shared/components/time/aggregation/grouping-interval-options.component.html b/ui-ngx/src/app/shared/components/time/aggregation/grouping-interval-options.component.html new file mode 100644 index 0000000000..5f9c37e3fb --- /dev/null +++ b/ui-ngx/src/app/shared/components/time/aggregation/grouping-interval-options.component.html @@ -0,0 +1,37 @@ + +
+ + + + {{ interval.name | translate:interval.translateParams }} + + + + + + + {{ interval.name | translate:interval.translateParams }} + + + +
diff --git a/ui-ngx/src/app/shared/components/time/time-intervals-list.component.scss b/ui-ngx/src/app/shared/components/time/aggregation/grouping-interval-options.component.scss similarity index 94% rename from ui-ngx/src/app/shared/components/time/time-intervals-list.component.scss rename to ui-ngx/src/app/shared/components/time/aggregation/grouping-interval-options.component.scss index 1fb09c65f5..0c47cfa574 100644 --- a/ui-ngx/src/app/shared/components/time/time-intervals-list.component.scss +++ b/ui-ngx/src/app/shared/components/time/aggregation/grouping-interval-options.component.scss @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -@import '../../../../scss/constants'; +@import '../../../../../scss/constants'; :host { diff --git a/ui-ngx/src/app/shared/components/time/time-intervals-list.component.ts b/ui-ngx/src/app/shared/components/time/aggregation/grouping-interval-options.component.ts similarity index 57% rename from ui-ngx/src/app/shared/components/time/time-intervals-list.component.ts rename to ui-ngx/src/app/shared/components/time/aggregation/grouping-interval-options.component.ts index b954f17390..304e885995 100644 --- a/ui-ngx/src/app/shared/components/time/time-intervals-list.component.ts +++ b/ui-ngx/src/app/shared/components/time/aggregation/grouping-interval-options.component.ts @@ -19,23 +19,28 @@ import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from import { TimeService } from '@core/services/time.service'; import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-field'; import { coerceBoolean, coerceNumber } from '@shared/decorators/coercion'; -import { Interval, TimeInterval } from '@shared/models/time/time.models'; +import { + Interval, + intervalValuesToTimeIntervals, + TimeInterval, + TimewindowAggIntervalOptions +} from '@shared/models/time/time.models'; import { isDefined } from '@core/utils'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ - selector: 'tb-time-intervals-list', - templateUrl: './time-intervals-list.component.html', - styleUrls: ['./time-intervals-list.component.scss'], + selector: 'tb-grouping-interval-options', + templateUrl: './grouping-interval-options.component.html', + styleUrls: ['./grouping-interval-options.component.scss'], providers: [ { provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TimeIntervalsListComponent), + useExisting: forwardRef(() => GroupingIntervalOptionsComponent), multi: true } ] }) -export class TimeIntervalsListComponent implements OnInit, ControlValueAccessor { +export class GroupingIntervalOptionsComponent implements OnInit, ControlValueAccessor { @Input() @coerceNumber() @@ -45,16 +50,6 @@ export class TimeIntervalsListComponent implements OnInit, ControlValueAccessor @coerceNumber() max: number; - @Input() predefinedName: string; - - @Input() - @coerceBoolean() - setAllIfEmpty = false; - - @Input() - @coerceBoolean() - returnEmptyIfAllSet = false; - @Input() @coerceBoolean() useCalendarIntervals = false; @@ -69,10 +64,11 @@ export class TimeIntervalsListComponent implements OnInit, ControlValueAccessor allIntervals: Array; allIntervalValues: Array; + selectedIntervals: Array; timeintervalFormGroup: FormGroup; - private modelValue: Array; + private modelValue: TimewindowAggIntervalOptions; private rendered = false; private propagateChangeValue: any; @@ -83,9 +79,13 @@ export class TimeIntervalsListComponent implements OnInit, ControlValueAccessor constructor(private timeService: TimeService, private fb: FormBuilder) { this.timeintervalFormGroup = this.fb.group({ - intervals: [ [] ] + aggIntervals: [ [] ], + defaultAggInterval: [ null ], }); - this.timeintervalFormGroup.get('intervals').valueChanges.pipe( + this.timeintervalFormGroup.get('aggIntervals').valueChanges.pipe( + takeUntilDestroyed() + ).subscribe(selectedIntervalValues => this.setSelectedIntervals(selectedIntervalValues)); + this.timeintervalFormGroup.valueChanges.pipe( takeUntilDestroyed() ).subscribe(() => this.updateView()); } @@ -113,10 +113,11 @@ export class TimeIntervalsListComponent implements OnInit, ControlValueAccessor } } - writeValue(intervals: Array): void { - this.modelValue = intervals; + writeValue(intervalOptions: TimewindowAggIntervalOptions): void { + this.modelValue = intervalOptions; this.rendered = true; - this.setIntervals(this.modelValue); + this.timeintervalFormGroup.get('defaultAggInterval').patchValue(intervalOptions.defaultAggInterval, { emitEvent: false }); + this.setIntervals(intervalOptions.aggIntervals); } private updateIntervalsList() { @@ -125,24 +126,41 @@ export class TimeIntervalsListComponent implements OnInit, ControlValueAccessor } private setIntervals(intervals: Array) { - this.timeintervalFormGroup.get('intervals').patchValue( - (this.setAllIfEmpty && !intervals?.length) ? this.allIntervalValues : intervals, + const selectedIntervals = !intervals?.length ? this.allIntervalValues : intervals; + this.timeintervalFormGroup.get('aggIntervals').patchValue( + selectedIntervals, {emitEvent: false}); + this.setSelectedIntervals(selectedIntervals); + } + + private setSelectedIntervals(selectedIntervalValues: Array) { + if (!selectedIntervalValues.length || selectedIntervalValues.length === this.allIntervalValues.length) { + this.selectedIntervals = this.allIntervals; + } else { + this.selectedIntervals = intervalValuesToTimeIntervals(selectedIntervalValues); + } + const defaultInterval: Interval = this.timeintervalFormGroup.get('defaultAggInterval').value; + if (defaultInterval && !selectedIntervalValues.includes(defaultInterval)) { + this.timeintervalFormGroup.get('defaultAggInterval').patchValue(null); + } } private updateView() { if (!this.rendered) { return; } - let value: Array; - const intervals: Array = this.timeintervalFormGroup.get('intervals').value; + let selectedIntervals: Array; + const intervals: Array = this.timeintervalFormGroup.get('aggIntervals').value; - if (!this.returnEmptyIfAllSet || intervals.length < this.allIntervals.length) { - value = intervals; + if (intervals.length < this.allIntervals.length) { + selectedIntervals = intervals; } else { - value = []; + selectedIntervals = []; } - this.modelValue = value; + this.modelValue = { + aggIntervals: selectedIntervals, + defaultAggInterval: this.timeintervalFormGroup.get('defaultAggInterval').value + }; this.propagateChange(this.modelValue); } 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 1778863a01..416602d0f6 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 @@ -25,8 +25,8 @@
{{"timewindow.interval" | translate }}
-
{{"timewindow.allowed-agg-intervals" | translate }}
-
{{"timewindow.default-agg-interval" | translate }}
+
{{"timewindow.allowed-agg-intervals" | translate }}
+
{{"timewindow.default-agg-interval" | translate }}
@@ -39,29 +39,15 @@
- - -
-
- - + appearance="outline"> +
diff --git a/ui-ngx/src/app/shared/components/time/interval-options-config-panel.component.scss b/ui-ngx/src/app/shared/components/time/interval-options-config-panel.component.scss index 09eae73ab9..42cf6ece74 100644 --- a/ui-ngx/src/app/shared/components/time/interval-options-config-panel.component.scss +++ b/ui-ngx/src/app/shared/components/time/interval-options-config-panel.component.scss @@ -30,12 +30,16 @@ flex: 1 1 30%; } &.tb-agg-interval { - flex: 1 1 35%; - width: 35%; - max-width: 35%; + flex: 1 1 70%; + width: 70%; + max-width: 70%; } } + .tb-form-table-header-cell.tb-agg-interval-header { + flex: 1 1 35%; + } + .tb-form-hint { flex-shrink: 0; } diff --git a/ui-ngx/src/app/shared/components/time/interval-options-config-panel.component.ts b/ui-ngx/src/app/shared/components/time/interval-options-config-panel.component.ts index e51c752719..ddce532192 100644 --- a/ui-ngx/src/app/shared/components/time/interval-options-config-panel.component.ts +++ b/ui-ngx/src/app/shared/components/time/interval-options-config-panel.component.ts @@ -100,26 +100,26 @@ export class IntervalOptionsConfigPanelComponent implements OnInit { const intervalControls: Array = []; for (const interval of this.allIntervals) { const intervalConfig: TimewindowAggIntervalOptions = this.aggIntervalsConfig?.hasOwnProperty(interval.value) - ? this.allIntervalValues[interval.value] + ? this.aggIntervalsConfig[interval.value] : null; - const intervalEnabled = this.allowedIntervals?.length ? this.allowedIntervals.includes(interval.value) : true; + const intervalEnabled = this.allowedIntervals?.length ? this.allowedIntervals.includes(interval.value) : false; const intervalControl = this.fb.group({ name: [this.translate.instant(interval.name, interval.translateParams)], value: [interval.value], enabled: [intervalEnabled], - aggIntervals: [{value: intervalConfig ? intervalConfig.aggIntervals : [], disabled: !(intervalEnabled && this.aggregation)}], - defaultAggInterval: [{value: intervalConfig ? intervalConfig.defaultAggInterval : null, disabled: !(intervalEnabled && this.aggregation)}], + aggIntervalsConfig: [{value: { + aggIntervals: intervalConfig?.aggIntervals ? intervalConfig.aggIntervals : [], + defaultAggInterval: intervalConfig?.defaultAggInterval ? 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}); + intervalControl.get('aggIntervalsConfig').enable({emitEvent: false}); } else { - intervalControl.get('aggIntervals').disable({emitEvent: false}); - intervalControl.get('defaultAggInterval').disable({emitEvent: false}); + intervalControl.get('aggIntervalsConfig').disable({emitEvent: false}); } }); } @@ -160,19 +160,18 @@ export class IntervalOptionsConfigPanelComponent implements OnInit { for (const interval of intervalOptionsConfig) { if (interval.enabled) { allowedIntervals.push(interval.value); - if (this.aggregation && (interval.aggIntervals.length || interval.defaultAggInterval)) { + if (this.aggregation && (interval.aggIntervalsConfig.aggIntervals.length || interval.aggIntervalsConfig.defaultAggInterval)) { const intervalParams: TimewindowAggIntervalOptions = {}; - if (interval.aggIntervals.length) { - intervalParams.aggIntervals = interval.aggIntervals; + if (interval.aggIntervalsConfig.aggIntervals.length) { + intervalParams.aggIntervals = interval.aggIntervalsConfig.aggIntervals; } - if (interval.defaultAggInterval) { - intervalParams.defaultAggInterval = interval.defaultAggInterval; + if (interval.aggIntervalsConfig.defaultAggInterval) { + intervalParams.defaultAggInterval = interval.aggIntervalsConfig.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 : [], @@ -192,8 +191,10 @@ export class IntervalOptionsConfigPanelComponent implements OnInit { for (const interval of intervalControls) { interval.patchValue({ enabled: true, - aggIntervals: [], - defaultAggInterval: null, + aggIntervalsConfig: { + 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 deleted file mode 100644 index ddcdd16fcb..0000000000 --- a/ui-ngx/src/app/shared/components/time/time-intervals-list.component.html +++ /dev/null @@ -1,27 +0,0 @@ - -
- - {{ predefinedName }} - - - {{ interval.name | translate:interval.translateParams }} - - - -
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 df32f4000d..9ba145df4a 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 @@ -26,7 +26,7 @@ import { realtimeAllowedAggIntervals, RealtimeWindowType, realtimeWindowTypeTranslations, - Timewindow, + Timewindow, TimewindowAggIntervalsConfig, TimewindowType, updateFormValuesOnTimewindowTypeChange } from '@shared/models/time/time.models'; @@ -235,6 +235,55 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On ? this.timewindow.hideTimezone : false ] }); + this.timewindowForm.get('realtime.timewindowMs').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((timewindowMs: number) => { + const lastAggIntervalsConfig:TimewindowAggIntervalsConfig = + this.timewindowForm.get('realtime.advancedParams.lastAggIntervalsConfig').value; + if (lastAggIntervalsConfig?.hasOwnProperty(timewindowMs) && + lastAggIntervalsConfig[timewindowMs].defaultAggInterval) { + this.timewindowForm.get('realtime.interval').patchValue( + lastAggIntervalsConfig[timewindowMs].defaultAggInterval, {emitEvent: false} + ); + } + }); + this.timewindowForm.get('realtime.quickInterval').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((quickInterval: number) => { + const quickAggIntervalsConfig:TimewindowAggIntervalsConfig = + this.timewindowForm.get('realtime.advancedParams.quickAggIntervalsConfig').value; + if (quickAggIntervalsConfig?.hasOwnProperty(quickInterval) && + quickAggIntervalsConfig[quickInterval].defaultAggInterval) { + this.timewindowForm.get('realtime.interval').patchValue( + quickAggIntervalsConfig[quickInterval].defaultAggInterval, {emitEvent: false} + ); + } + }); + this.timewindowForm.get('history.timewindowMs').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((timewindowMs: number) => { + const lastAggIntervalsConfig:TimewindowAggIntervalsConfig = + this.timewindowForm.get('history.advancedParams.lastAggIntervalsConfig').value; + if (lastAggIntervalsConfig?.hasOwnProperty(timewindowMs) && + lastAggIntervalsConfig[timewindowMs].defaultAggInterval) { + this.timewindowForm.get('history.interval').patchValue( + lastAggIntervalsConfig[timewindowMs].defaultAggInterval, {emitEvent: false} + ); + } + }); + this.timewindowForm.get('history.quickInterval').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((quickInterval: number) => { + const quickAggIntervalsConfig:TimewindowAggIntervalsConfig = + this.timewindowForm.get('history.advancedParams.quickAggIntervalsConfig').value; + if (quickAggIntervalsConfig?.hasOwnProperty(quickInterval) && + quickAggIntervalsConfig[quickInterval].defaultAggInterval) { + this.timewindowForm.get('history.interval').patchValue( + quickAggIntervalsConfig[quickInterval].defaultAggInterval, {emitEvent: false} + ); + } + }); + this.updateValidators(this.timewindowForm.get('aggregation.type').value); this.timewindowForm.get('aggregation.type').valueChanges.pipe( takeUntil(this.destroy$) 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 6553edd853..5dec11f619 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 @@ -298,6 +298,48 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O disabled: hideTimezone }] }); + + this.timewindowForm.get('realtime.timewindowMs').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((timewindowMs: number) => { + if (this.realtimeAdvancedParams?.lastAggIntervalsConfig?.hasOwnProperty(timewindowMs) && + this.realtimeAdvancedParams.lastAggIntervalsConfig[timewindowMs].defaultAggInterval) { + this.timewindowForm.get('realtime.interval').patchValue( + this.realtimeAdvancedParams.lastAggIntervalsConfig[timewindowMs].defaultAggInterval, {emitEvent: false} + ); + } + }); + this.timewindowForm.get('realtime.quickInterval').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((quickInterval: number) => { + if (this.realtimeAdvancedParams?.quickAggIntervalsConfig?.hasOwnProperty(quickInterval) && + this.realtimeAdvancedParams.quickAggIntervalsConfig[quickInterval].defaultAggInterval) { + this.timewindowForm.get('realtime.interval').patchValue( + this.realtimeAdvancedParams.quickAggIntervalsConfig[quickInterval].defaultAggInterval, {emitEvent: false} + ); + } + }); + this.timewindowForm.get('history.timewindowMs').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((timewindowMs: number) => { + if (this.historyAdvancedParams?.lastAggIntervalsConfig?.hasOwnProperty(timewindowMs) && + this.historyAdvancedParams.lastAggIntervalsConfig[timewindowMs].defaultAggInterval) { + this.timewindowForm.get('history.interval').patchValue( + this.historyAdvancedParams.lastAggIntervalsConfig[timewindowMs].defaultAggInterval, {emitEvent: false} + ); + } + }); + this.timewindowForm.get('history.quickInterval').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((quickInterval: number) => { + if (this.historyAdvancedParams?.quickAggIntervalsConfig?.hasOwnProperty(quickInterval) && + this.historyAdvancedParams.quickAggIntervalsConfig[quickInterval].defaultAggInterval) { + this.timewindowForm.get('history.interval').patchValue( + this.historyAdvancedParams.quickAggIntervalsConfig[quickInterval].defaultAggInterval, {emitEvent: false} + ); + } + }); + this.updateValidators(this.timewindowForm.get('aggregation.type').value); this.timewindowForm.get('aggregation.type').valueChanges.pipe( takeUntil(this.destroy$) diff --git a/ui-ngx/src/app/shared/shared.module.ts b/ui-ngx/src/app/shared/shared.module.ts index 3121642343..0ce96d1f01 100644 --- a/ui-ngx/src/app/shared/shared.module.ts +++ b/ui-ngx/src/app/shared/shared.module.ts @@ -221,7 +221,7 @@ import { DatapointsLimitComponent } from '@shared/components/time/datapoints-lim import { AggregationTypeSelectComponent } from '@shared/components/time/aggregation/aggregation-type-select.component'; import { AggregationOptionsConfigPanelComponent } from '@shared/components/time/aggregation/aggregation-options-config-panel.component'; import { IntervalOptionsConfigPanelComponent } from '@shared/components/time/interval-options-config-panel.component'; -import { TimeIntervalsListComponent } from '@shared/components/time/time-intervals-list.component'; +import { GroupingIntervalOptionsComponent } from '@shared/components/time/aggregation/grouping-interval-options.component'; export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) { return markedOptionsService; @@ -307,7 +307,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) TimewindowPanelComponent, TimewindowConfigDialogComponent, TimeintervalComponent, - TimeIntervalsListComponent, + GroupingIntervalOptionsComponent, TimezoneComponent, TimezonePanelComponent, QuickTimeIntervalComponent, @@ -518,7 +518,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) TimewindowPanelComponent, TimewindowConfigDialogComponent, TimeintervalComponent, - TimeIntervalsListComponent, + GroupingIntervalOptionsComponent, TimezoneComponent, TimezonePanelComponent, QuickTimeIntervalComponent, 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 839bbaeb04..c68fe15c35 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -80,7 +80,8 @@ "clear": "Clear", "upload": "Upload", "delete-anyway": "Delete anyway", - "delete-selected": "Delete selected" + "delete-selected": "Delete selected", + "set": "Set" }, "aggregation": { "aggregation": "Aggregation", @@ -4712,7 +4713,8 @@ "allowed-agg-intervals": "Allowed grouping 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." + "edit-grouping-intervals-list-hint": "It is possible to configure the grouping intervals list and default grouping interval.", + "all": "All" }, "tooltip": { "trigger": "Trigger",