diff --git a/ui-ngx/src/app/modules/common/modules-map.ts b/ui-ngx/src/app/modules/common/modules-map.ts index b5ff3f5f33..b188abbafe 100644 --- a/ui-ngx/src/app/modules/common/modules-map.ts +++ b/ui-ngx/src/app/modules/common/modules-map.ts @@ -337,6 +337,7 @@ import * as TimezoneComponent from '@shared/components/time/timezone.component'; import * as TimezonePanelComponent from '@shared/components/time/timezone-panel.component'; import * as DatapointsLimitComponent from '@shared/components/time/datapoints-limit.component'; import * as AggregationTypeSelectComponent from '@shared/components/aggregation/aggregation-type-select.component'; +import * as AggregationOptionsConfigComponent from '@shared/components/aggregation/aggregation-options-config-panel.component'; import { IModulesMap } from '@modules/common/modules-map.models'; @@ -470,8 +471,9 @@ class ModulesMap implements IModulesMap { '@shared/components/time/timezone-select.component': TimezoneSelectComponent, '@shared/components/time/timezone.component': TimezoneComponent, '@shared/components/time/timezone-panel.component': TimezonePanelComponent, - '@shared/components/time/datapoints-limit': DatapointsLimitComponent, - '@shared/components/aggregation/aggregation-type-select': AggregationTypeSelectComponent, + '@shared/components/time/datapoints-limit.component': DatapointsLimitComponent, + '@shared/components/aggregation/aggregation-type-select.component': AggregationTypeSelectComponent, + '@shared/components/aggregation/aggregation-options-config-panel.component': AggregationOptionsConfigComponent, '@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/aggregation/aggregation-options-config-panel.component.html b/ui-ngx/src/app/shared/components/aggregation/aggregation-options-config-panel.component.html new file mode 100644 index 0000000000..35016c6a28 --- /dev/null +++ b/ui-ngx/src/app/shared/components/aggregation/aggregation-options-config-panel.component.html @@ -0,0 +1,24 @@ + +
+ + + {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | 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 new file mode 100644 index 0000000000..b9dc294716 --- /dev/null +++ b/ui-ngx/src/app/shared/components/aggregation/aggregation-options-config-panel.component.scss @@ -0,0 +1,17 @@ +/** + * 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. + */ + + 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 new file mode 100644 index 0000000000..1b789a747c --- /dev/null +++ b/ui-ngx/src/app/shared/components/aggregation/aggregation-options-config-panel.component.ts @@ -0,0 +1,72 @@ +/// +/// 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, OnInit } from '@angular/core'; +import { aggregationTranslations, AggregationType } from '@shared/models/time/time.models'; +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', + styleUrls: ['./aggregation-options-config-panel.component.scss'] +}) +export class AggregationOptionsConfigPanelComponent implements OnInit { + + @Input() + allowedAggregationTypes: Array; + + @Input() + onClose: (result: AggregationOptionsSelectionResult | null) => void; + + @Input() + popoverComponent: TbPopoverComponent; + + aggregationOptionsConfigForm: FormGroup; + + aggregationTypes = AggregationType; + + aggregations = Object.keys(AggregationType); + + aggregationTypesTranslations = aggregationTranslations; + + constructor(private fb: FormBuilder) {} + + ngOnInit(): void { + this.aggregationOptionsConfigForm = this.fb.group({ + allowedAggregationTypes: [this.allowedAggregationTypes] + }); + } + + update() { + if (this.onClose) { + this.onClose({ + allowedAggregationTypes: this.aggregationOptionsConfigForm.get('allowedAggregationTypes').value + }); + } + } + + cancel() { + if (this.onClose) { + this.onClose(null); + } + } + +} 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 401ae7f16a..b9a9cdd93e 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 @@ -22,4 +22,7 @@ {{ displayAggregationTypeFn(type) }} + + + diff --git a/ui-ngx/src/app/shared/components/aggregation/aggregation-type-select.component.scss b/ui-ngx/src/app/shared/components/aggregation/aggregation-type-select.component.scss index ddc2385dfa..4e08e7fc73 100644 --- a/ui-ngx/src/app/shared/components/aggregation/aggregation-type-select.component.scss +++ b/ui-ngx/src/app/shared/components/aggregation/aggregation-type-select.component.scss @@ -26,4 +26,10 @@ .mat-mdc-select-value { min-width: 100px; } + .mat-mdc-form-field-has-icon-suffix .mat-mdc-text-field-wrapper:has(.mat-mdc-form-field-icon-suffix:empty) { + padding-right: 12px; + } + .mat-mdc-form-field-icon-suffix:empty { + padding: 0; + } } 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 69ce692403..dbfb9e37ea 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 @@ -169,6 +169,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 6eda855cb5..f99dd02bf2 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 @@ -14,9 +14,8 @@ /// limitations under the License. /// -import { Component, Inject, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectorRef, Component, Inject, OnDestroy, OnInit, Renderer2, ViewContainerRef } from '@angular/core'; import { - aggregationTranslations, AggregationType, DAY, HistoryWindowType, @@ -38,6 +37,11 @@ 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 +} from '@shared/components/aggregation/aggregation-options-config-panel.component'; export interface TimewindowConfigDialogData { quickIntervalOnly: boolean; @@ -112,7 +116,11 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On protected store: Store, public fb: FormBuilder, private timeService: TimeService, - private translate: TranslateService) { + private translate: TranslateService, + private popoverService: TbPopoverService, + private renderer: Renderer2, + private cd: ChangeDetectorRef, + public viewContainerRef: ViewContainerRef) { super(store); this.quickIntervalOnly = data.quickIntervalOnly; this.aggregation = data.aggregation; @@ -388,4 +396,30 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On } } + openAggregationOptionsConfig($event: Event) { + if ($event) { + $event.stopPropagation(); + } + const trigger = ($event.target || $event.srcElement || $event.currentTarget) as Element; + if (this.popoverService.hasPopover(trigger)) { + this.popoverService.hidePopover(trigger); + } else { + const aggregationConfigPopover = this.popoverService.displayPopover(trigger, this.renderer, + this.viewContainerRef, AggregationOptionsConfigPanelComponent, ['bottomRight', 'leftBottom'], true, null, + { + allowedAggregationTypes: null, + onClose: (result: TimezoneSelectionResult | null) => { + aggregationConfigPopover.hide(); + if (result) { + console.log(result); + } + } + }, + {}, + {}, {}, false); + aggregationConfigPopover.tbComponentRef.instance.popoverComponent = aggregationConfigPopover; + } + this.cd.detectChanges(); + } + } 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 d29bc63f53..2037a3578b 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 @@ -16,7 +16,6 @@ import { Component, Inject, InjectionToken, OnDestroy, OnInit, ViewContainerRef } from '@angular/core'; import { - aggregationTranslations, AggregationType, DAY, HistoryWindowType, diff --git a/ui-ngx/src/app/shared/shared.module.ts b/ui-ngx/src/app/shared/shared.module.ts index 23dc3e5a8f..2da898bd44 100644 --- a/ui-ngx/src/app/shared/shared.module.ts +++ b/ui-ngx/src/app/shared/shared.module.ts @@ -231,6 +231,7 @@ import { CountryData } from '@shared/models/country.models'; import { SvgXmlComponent } from '@shared/components/svg-xml.component'; import { DatapointsLimitComponent } from '@shared/components/time/datapoints-limit.component'; import { AggregationTypeSelectComponent } from '@shared/components/aggregation/aggregation-type-select.component'; +import { AggregationOptionsConfigPanelComponent } from '@shared/components/aggregation/aggregation-options-config-panel.component'; export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) { return markedOptionsService; @@ -322,6 +323,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) QuickTimeIntervalComponent, DatapointsLimitComponent, AggregationTypeSelectComponent, + AggregationOptionsConfigPanelComponent, DashboardSelectComponent, DashboardSelectPanelComponent, DatetimePeriodComponent, @@ -539,6 +541,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) QuickTimeIntervalComponent, DatapointsLimitComponent, AggregationTypeSelectComponent, + AggregationOptionsConfigPanelComponent, DashboardSelectComponent, DatetimePeriodComponent, DatetimeComponent,