Timewindow: move datapoints limit to a separate component
This commit is contained in:
parent
37ac8cac44
commit
2e52c50b80
@ -337,6 +337,7 @@ import * as RuleChainSelectComponent from '@shared/components/rule-chain/rule-ch
|
||||
import { IModulesMap } from '@modules/common/modules-map.models';
|
||||
import { TimezoneComponent } from '@shared/components/time/timezone.component';
|
||||
import { TimezonePanelComponent } from '@shared/components/time/timezone-panel.component';
|
||||
import { DatapointsLimitComponent } from '@shared/components/time/datapoints-limit.component';
|
||||
|
||||
declare const System;
|
||||
|
||||
@ -470,6 +471,7 @@ 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/value-input.component': ValueInputComponent,
|
||||
'@shared/components/dashboard-autocomplete.component': DashboardAutocompleteComponent,
|
||||
'@shared/components/entity/entity-subtype-autocomplete.component': EntitySubTypeAutocompleteComponent,
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<div [formGroup]="datapointsLimitFormGroup" class="limit-slider-container" fxLayout="row" fxLayoutAlign="start center">
|
||||
<mat-slider fxFlex
|
||||
min="{{minDatapointsLimit()}}"
|
||||
max="{{maxDatapointsLimit()}}">
|
||||
<input matSliderThumb formControlName="limit" [value]="datapointsLimitFormGroup.get('limit').value"/>
|
||||
</mat-slider>
|
||||
<mat-form-field class="limit-slider-value" subscriptSizing="dynamic" appearance="outline">
|
||||
<input matInput formControlName="limit" type="number" step="1"
|
||||
[value]="datapointsLimitFormGroup.get('limit').value"
|
||||
min="{{minDatapointsLimit()}}"
|
||||
max="{{maxDatapointsLimit()}}"/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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 "../../../../scss/constants";
|
||||
|
||||
.limit-slider-container {
|
||||
width: 100%;
|
||||
.limit-slider-value {
|
||||
margin-left: 16px;
|
||||
min-width: 25px;
|
||||
max-width: 106px;
|
||||
}
|
||||
mat-form-field input[type=number] {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media #{$mat-gt-sm} {
|
||||
.limit-slider-container {
|
||||
> label {
|
||||
margin-right: 16px;
|
||||
width: min-content;
|
||||
max-width: 40%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,138 @@
|
||||
///
|
||||
/// 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, forwardRef, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
import { getTimezoneInfo } from '@shared/models/time/time.models';
|
||||
import { TimeService } from '@core/services/time.service';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-datapoints-limit',
|
||||
templateUrl: './datapoints-limit.component.html',
|
||||
styleUrls: ['./datapoints-limit.component.scss'],
|
||||
providers: [{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: forwardRef(() => DatapointsLimitComponent),
|
||||
multi: true
|
||||
}]
|
||||
})
|
||||
export class DatapointsLimitComponent implements ControlValueAccessor, OnInit, OnDestroy {
|
||||
|
||||
datapointsLimitFormGroup: UntypedFormGroup;
|
||||
|
||||
modelValue: number | null;
|
||||
|
||||
private requiredValue: boolean;
|
||||
get required(): boolean {
|
||||
return this.requiredValue;
|
||||
}
|
||||
@Input()
|
||||
set required(value: boolean) {
|
||||
const newVal = coerceBooleanProperty(value);
|
||||
if (this.requiredValue !== newVal) {
|
||||
this.requiredValue = newVal;
|
||||
this.updateValidators();
|
||||
}
|
||||
}
|
||||
|
||||
@Input()
|
||||
disabled: boolean;
|
||||
|
||||
private propagateChange = (v: any) => { };
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
constructor(private fb: FormBuilder,
|
||||
private timeService: TimeService) {
|
||||
}
|
||||
|
||||
registerOnChange(fn: any): void {
|
||||
this.propagateChange = fn;
|
||||
}
|
||||
|
||||
registerOnTouched(fn: any): void {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.datapointsLimitFormGroup = this.fb.group({
|
||||
limit: [null]
|
||||
});
|
||||
this.datapointsLimitFormGroup.get('limit').valueChanges.pipe(
|
||||
takeUntil(this.destroy$)
|
||||
).subscribe((value) => {
|
||||
this.updateView(value);
|
||||
});
|
||||
}
|
||||
|
||||
updateValidators() {
|
||||
if (this.datapointsLimitFormGroup) {
|
||||
this.datapointsLimitFormGroup.get('limit').setValidators(this.required
|
||||
? [Validators.required, Validators.min(this.minDatapointsLimit()),
|
||||
Validators.max(this.maxDatapointsLimit())]
|
||||
: []);
|
||||
this.datapointsLimitFormGroup.get('limit').updateValueAndValidity();
|
||||
}
|
||||
}
|
||||
|
||||
setDisabledState(isDisabled: boolean): void {
|
||||
this.disabled = isDisabled;
|
||||
if (this.disabled) {
|
||||
this.datapointsLimitFormGroup.disable({emitEvent: false});
|
||||
} else {
|
||||
this.datapointsLimitFormGroup.enable({emitEvent: false});
|
||||
}
|
||||
}
|
||||
|
||||
private checkLimit(limit?: number): number {
|
||||
if (!limit || limit < this.minDatapointsLimit()) {
|
||||
return this.minDatapointsLimit();
|
||||
} else if (limit > this.maxDatapointsLimit()) {
|
||||
return this.maxDatapointsLimit();
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
|
||||
writeValue(value: number | null): void {
|
||||
this.modelValue = this.checkLimit(value);
|
||||
this.datapointsLimitFormGroup.patchValue(
|
||||
{ limit: this.modelValue }, {emitEvent: false}
|
||||
);
|
||||
}
|
||||
|
||||
updateView(value: number | null) {
|
||||
if (this.modelValue !== value) {
|
||||
this.modelValue = value;
|
||||
this.propagateChange(this.modelValue);
|
||||
}
|
||||
}
|
||||
|
||||
minDatapointsLimit() {
|
||||
return this.timeService.getMinDatapointsLimit();
|
||||
}
|
||||
|
||||
maxDatapointsLimit() {
|
||||
return this.timeService.getMaxDatapointsLimit();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
}
|
||||
@ -173,19 +173,11 @@
|
||||
<mat-slide-toggle class="mat-slide" formControlName="hideAggInterval">
|
||||
{{ 'timewindow.hide' | translate }}
|
||||
</mat-slide-toggle>
|
||||
<div formGroupName="aggregation" class="limit-slider-container" fxLayout="row" fxLayoutAlign="start center">
|
||||
<mat-slider fxFlex
|
||||
min="{{minDatapointsLimit()}}"
|
||||
max="{{maxDatapointsLimit()}}">
|
||||
<input matSliderThumb formControlName="limit"/>
|
||||
</mat-slider>
|
||||
<mat-form-field class="limit-slider-value" subscriptSizing="dynamic" appearance="outline">
|
||||
<input matInput formControlName="limit" type="number" step="1"
|
||||
[value]="timewindowForm.get('aggregation.limit').value"
|
||||
min="{{minDatapointsLimit()}}"
|
||||
max="{{maxDatapointsLimit()}}"/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<ng-container formGroupName="aggregation">
|
||||
<tb-datapoints-limit formControlName="limit"
|
||||
[required]="timewindowForm.get('aggregation.type').value === aggregationTypes.NONE">
|
||||
</tb-datapoints-limit>
|
||||
</ng-container>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
@ -191,7 +191,7 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On
|
||||
}),
|
||||
aggregation: this.fb.group({
|
||||
type: [ isDefined(aggregation?.type) ? this.timewindow.aggregation.type : null ],
|
||||
limit: [ isDefined(aggregation?.limit) ? this.checkLimit(this.timewindow.aggregation.limit) : null ]
|
||||
limit: [ isDefined(aggregation?.limit) ? this.timewindow.aggregation.limit : null ]
|
||||
}),
|
||||
timezone: [ isDefined(this.timewindow.timezone) ? this.timewindow.timezone : null ],
|
||||
hideAggregation: [ isDefinedAndNotNull(this.timewindow.hideAggregation)
|
||||
@ -292,15 +292,6 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
private checkLimit(limit?: number): number {
|
||||
if (!limit || limit < this.minDatapointsLimit()) {
|
||||
return this.minDatapointsLimit();
|
||||
} else if (limit > this.maxDatapointsLimit()) {
|
||||
return this.maxDatapointsLimit();
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
|
||||
private updateValidators(aggType: AggregationType) {
|
||||
if (aggType !== AggregationType.NONE) {
|
||||
this.timewindowForm.get('aggregation.limit').clearValidators();
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
@import "../../../../scss/constants";
|
||||
|
||||
:host {
|
||||
background-color: #fff;
|
||||
@ -32,32 +31,10 @@
|
||||
|
||||
tb-timeinterval,
|
||||
tb-quick-time-interval,
|
||||
tb-datetime-period {
|
||||
tb-datetime-period,
|
||||
tb-datapoints-limit {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.limit-slider-container {
|
||||
width: 100%;
|
||||
.limit-slider-value {
|
||||
margin-left: 16px;
|
||||
min-width: 25px;
|
||||
max-width: 106px;
|
||||
}
|
||||
mat-form-field input[type=number] {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media #{$mat-gt-sm} {
|
||||
.limit-slider-container {
|
||||
> label {
|
||||
margin-right: 16px;
|
||||
width: min-content;
|
||||
max-width: 40%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -137,19 +137,9 @@
|
||||
<section class="tb-form-row column-xs space-between same-padding"
|
||||
*ngIf="timewindowForm.get('aggregation.type').value === aggregationTypes.NONE && (isEdit || !timewindow.hideAggInterval)">
|
||||
<div>{{ 'aggregation.limit' | translate }}</div>
|
||||
<div class="limit-slider-container" fxLayout="row" fxLayoutAlign="start center">
|
||||
<mat-slider fxFlex
|
||||
min="{{minDatapointsLimit()}}"
|
||||
max="{{maxDatapointsLimit()}}">
|
||||
<input matSliderThumb formControlName="limit"/>
|
||||
</mat-slider>
|
||||
<mat-form-field class="limit-slider-value" subscriptSizing="dynamic" appearance="outline">
|
||||
<input matInput formControlName="limit" type="number" step="1"
|
||||
[value]="timewindowForm.get('aggregation.limit').value"
|
||||
min="{{minDatapointsLimit()}}"
|
||||
max="{{maxDatapointsLimit()}}"/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<tb-datapoints-limit formControlName="limit"
|
||||
[required]="timewindowForm.get('aggregation.type').value === aggregationTypes.NONE">
|
||||
</tb-datapoints-limit>
|
||||
</section>
|
||||
</ng-container>
|
||||
|
||||
|
||||
@ -275,7 +275,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
|
||||
disabled: hideAggregation
|
||||
}],
|
||||
limit: [{
|
||||
value: isDefined(aggregation?.limit) ? this.checkLimit(aggregation.limit) : null,
|
||||
value: isDefined(aggregation?.limit) ? aggregation.limit : null,
|
||||
disabled: hideAggInterval
|
||||
}, []]
|
||||
}),
|
||||
@ -303,15 +303,6 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
private checkLimit(limit?: number): number {
|
||||
if (!limit || limit < this.minDatapointsLimit()) {
|
||||
return this.minDatapointsLimit();
|
||||
} else if (limit > this.maxDatapointsLimit()) {
|
||||
return this.maxDatapointsLimit();
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
|
||||
private updateValidators(aggType: AggregationType) {
|
||||
if (aggType !== AggregationType.NONE) {
|
||||
this.timewindowForm.get('aggregation.limit').clearValidators();
|
||||
|
||||
@ -228,6 +228,7 @@ import { ScadaSymbolInputComponent } from '@shared/components/image/scada-symbol
|
||||
import { CountryAutocompleteComponent } from '@shared/components/country-autocomplete.component';
|
||||
import { CountryData } from '@shared/models/country.models';
|
||||
import { SvgXmlComponent } from '@shared/components/svg-xml.component';
|
||||
import { DatapointsLimitComponent } from '@shared/components/time/datapoints-limit.component';
|
||||
|
||||
export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) {
|
||||
return markedOptionsService;
|
||||
@ -317,6 +318,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
|
||||
TimezoneComponent,
|
||||
TimezonePanelComponent,
|
||||
QuickTimeIntervalComponent,
|
||||
DatapointsLimitComponent,
|
||||
DashboardSelectComponent,
|
||||
DashboardSelectPanelComponent,
|
||||
DatetimePeriodComponent,
|
||||
@ -529,6 +531,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
|
||||
TimezoneComponent,
|
||||
TimezonePanelComponent,
|
||||
QuickTimeIntervalComponent,
|
||||
DatapointsLimitComponent,
|
||||
DashboardSelectComponent,
|
||||
DatetimePeriodComponent,
|
||||
DatetimeComponent,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user