10 changed files with 223 additions and 71 deletions
@ -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(); |
|||
} |
|||
|
|||
} |
|||
Loading…
Reference in new issue