278 lines
6.7 KiB
TypeScript
278 lines
6.7 KiB
TypeScript
|
|
///
|
||
|
|
/// Copyright © 2016-2019 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 { ChangeDetectorRef, Component, forwardRef, Input, OnInit } from '@angular/core';
|
||
|
|
import {
|
||
|
|
ControlValueAccessor,
|
||
|
|
FormControl,
|
||
|
|
NG_VALIDATORS,
|
||
|
|
NG_VALUE_ACCESSOR,
|
||
|
|
Validator
|
||
|
|
} from '@angular/forms';
|
||
|
|
import { Timewindow } from '@shared/models/time/time.models';
|
||
|
|
import { TimeInterval, TimeService } from '@core/services/time.service';
|
||
|
|
|
||
|
|
@Component({
|
||
|
|
selector: 'tb-timeinterval',
|
||
|
|
templateUrl: './timeinterval.component.html',
|
||
|
|
styleUrls: ['./timeinterval.component.scss'],
|
||
|
|
providers: [
|
||
|
|
{
|
||
|
|
provide: NG_VALUE_ACCESSOR,
|
||
|
|
useExisting: forwardRef(() => TimeintervalComponent),
|
||
|
|
multi: true
|
||
|
|
}
|
||
|
|
]
|
||
|
|
})
|
||
|
|
export class TimeintervalComponent implements OnInit, ControlValueAccessor {
|
||
|
|
|
||
|
|
minValue: number;
|
||
|
|
maxValue: number;
|
||
|
|
|
||
|
|
@Input()
|
||
|
|
set min(min: number) {
|
||
|
|
if (typeof min !== 'undefined' && min !== this.minValue) {
|
||
|
|
this.minValue = min;
|
||
|
|
this.updateView();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@Input()
|
||
|
|
set max(max: number) {
|
||
|
|
if (typeof max !== 'undefined' && max !== this.maxValue) {
|
||
|
|
this.maxValue = max;
|
||
|
|
this.updateView();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@Input() predefinedName: string;
|
||
|
|
@Input() disabled: boolean;
|
||
|
|
|
||
|
|
days = 0;
|
||
|
|
hours = 0;
|
||
|
|
mins = 1;
|
||
|
|
secs = 0;
|
||
|
|
|
||
|
|
intervalMs = 0;
|
||
|
|
modelValue: number;
|
||
|
|
|
||
|
|
advanced = false;
|
||
|
|
rendered = false;
|
||
|
|
|
||
|
|
intervals: Array<TimeInterval>;
|
||
|
|
|
||
|
|
private propagateChange = (_: any) => {};
|
||
|
|
|
||
|
|
constructor(private timeService: TimeService) {
|
||
|
|
}
|
||
|
|
|
||
|
|
ngOnInit(): void {
|
||
|
|
this.boundInterval();
|
||
|
|
}
|
||
|
|
|
||
|
|
registerOnChange(fn: any): void {
|
||
|
|
this.propagateChange = fn;
|
||
|
|
}
|
||
|
|
|
||
|
|
registerOnTouched(fn: any): void {
|
||
|
|
}
|
||
|
|
|
||
|
|
setDisabledState(isDisabled: boolean): void {
|
||
|
|
this.disabled = isDisabled;
|
||
|
|
}
|
||
|
|
|
||
|
|
writeValue(intervalMs: number): void {
|
||
|
|
this.modelValue = intervalMs;
|
||
|
|
this.rendered = true;
|
||
|
|
if (typeof this.modelValue !== 'undefined') {
|
||
|
|
const min = this.timeService.boundMinInterval(this.minValue);
|
||
|
|
const max = this.timeService.boundMaxInterval(this.maxValue);
|
||
|
|
if (this.modelValue >= min && this.modelValue <= max) {
|
||
|
|
this.advanced = !this.timeService.matchesExistingInterval(this.minValue, this.maxValue, this.modelValue);
|
||
|
|
this.setIntervalMs(this.modelValue);
|
||
|
|
} else {
|
||
|
|
this.boundInterval();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
setIntervalMs(intervalMs: number) {
|
||
|
|
if (!this.advanced) {
|
||
|
|
this.intervalMs = intervalMs;
|
||
|
|
}
|
||
|
|
const intervalSeconds = Math.floor(intervalMs / 1000);
|
||
|
|
this.days = Math.floor(intervalSeconds / 86400);
|
||
|
|
this.hours = Math.floor((intervalSeconds % 86400) / 3600);
|
||
|
|
this.mins = Math.floor(((intervalSeconds % 86400) % 3600) / 60);
|
||
|
|
this.secs = intervalSeconds % 60;
|
||
|
|
}
|
||
|
|
|
||
|
|
boundInterval() {
|
||
|
|
const min = this.timeService.boundMinInterval(this.minValue);
|
||
|
|
const max = this.timeService.boundMaxInterval(this.maxValue);
|
||
|
|
this.intervals = this.timeService.getIntervals(this.minValue, this.maxValue);
|
||
|
|
if (this.rendered) {
|
||
|
|
let newIntervalMs = this.modelValue;
|
||
|
|
if (newIntervalMs < min) {
|
||
|
|
newIntervalMs = min;
|
||
|
|
} else if (newIntervalMs > max) {
|
||
|
|
newIntervalMs = max;
|
||
|
|
}
|
||
|
|
if (!this.advanced) {
|
||
|
|
newIntervalMs = this.timeService.boundToPredefinedInterval(min, max, newIntervalMs);
|
||
|
|
}
|
||
|
|
if (newIntervalMs !== this.modelValue) {
|
||
|
|
this.setIntervalMs(newIntervalMs);
|
||
|
|
this.updateView();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
updateView() {
|
||
|
|
if (!this.rendered) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
let value = null;
|
||
|
|
let intervalMs;
|
||
|
|
if (!this.advanced) {
|
||
|
|
intervalMs = this.intervalMs;
|
||
|
|
if (!intervalMs || isNaN(intervalMs)) {
|
||
|
|
intervalMs = this.calculateIntervalMs();
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
intervalMs = this.calculateIntervalMs();
|
||
|
|
}
|
||
|
|
if (!isNaN(intervalMs) && intervalMs > 0) {
|
||
|
|
value = intervalMs;
|
||
|
|
}
|
||
|
|
this.modelValue = value;
|
||
|
|
this.propagateChange(this.modelValue);
|
||
|
|
this.boundInterval();
|
||
|
|
}
|
||
|
|
|
||
|
|
calculateIntervalMs(): number {
|
||
|
|
return (this.days * 86400 +
|
||
|
|
this.hours * 3600 +
|
||
|
|
this.mins * 60 +
|
||
|
|
this.secs) * 1000;
|
||
|
|
}
|
||
|
|
|
||
|
|
onIntervalMsChange() {
|
||
|
|
this.updateView();
|
||
|
|
}
|
||
|
|
|
||
|
|
onAdvancedChange() {
|
||
|
|
if (!this.advanced) {
|
||
|
|
this.intervalMs = this.calculateIntervalMs();
|
||
|
|
} else {
|
||
|
|
let intervalMs = this.intervalMs;
|
||
|
|
if (!intervalMs || isNaN(intervalMs)) {
|
||
|
|
intervalMs = this.calculateIntervalMs();
|
||
|
|
}
|
||
|
|
this.setIntervalMs(intervalMs);
|
||
|
|
}
|
||
|
|
this.updateView();
|
||
|
|
}
|
||
|
|
|
||
|
|
onTimeInputChange(type: string) {
|
||
|
|
switch (type) {
|
||
|
|
case 'secs':
|
||
|
|
setTimeout(() => this.onSecsChange(), 0);
|
||
|
|
break;
|
||
|
|
case 'mins':
|
||
|
|
setTimeout(() => this.onMinsChange(), 0);
|
||
|
|
break;
|
||
|
|
case 'hours':
|
||
|
|
setTimeout(() => this.onHoursChange(), 0);
|
||
|
|
break;
|
||
|
|
case 'days':
|
||
|
|
setTimeout(() => this.onDaysChange(), 0);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
onSecsChange() {
|
||
|
|
if (typeof this.secs === 'undefined') {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (this.secs < 0) {
|
||
|
|
if ((this.days + this.hours + this.mins) > 0) {
|
||
|
|
this.secs = this.secs + 60;
|
||
|
|
this.mins--;
|
||
|
|
this.onMinsChange();
|
||
|
|
} else {
|
||
|
|
this.secs = 0;
|
||
|
|
}
|
||
|
|
} else if (this.secs >= 60) {
|
||
|
|
this.secs = this.secs - 60;
|
||
|
|
this.mins++;
|
||
|
|
this.onMinsChange();
|
||
|
|
}
|
||
|
|
this.updateView();
|
||
|
|
}
|
||
|
|
|
||
|
|
onMinsChange() {
|
||
|
|
if (typeof this.mins === 'undefined') {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (this.mins < 0) {
|
||
|
|
if ((this.days + this.hours) > 0) {
|
||
|
|
this.mins = this.mins + 60;
|
||
|
|
this.hours--;
|
||
|
|
this.onHoursChange();
|
||
|
|
} else {
|
||
|
|
this.mins = 0;
|
||
|
|
}
|
||
|
|
} else if (this.mins >= 60) {
|
||
|
|
this.mins = this.mins - 60;
|
||
|
|
this.hours++;
|
||
|
|
this.onHoursChange();
|
||
|
|
}
|
||
|
|
this.updateView();
|
||
|
|
}
|
||
|
|
|
||
|
|
onHoursChange() {
|
||
|
|
if (typeof this.hours === 'undefined') {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (this.hours < 0) {
|
||
|
|
if (this.days > 0) {
|
||
|
|
this.hours = this.hours + 24;
|
||
|
|
this.days--;
|
||
|
|
this.onDaysChange();
|
||
|
|
} else {
|
||
|
|
this.hours = 0;
|
||
|
|
}
|
||
|
|
} else if (this.hours >= 24) {
|
||
|
|
this.hours = this.hours - 24;
|
||
|
|
this.days++;
|
||
|
|
this.onDaysChange();
|
||
|
|
}
|
||
|
|
this.updateView();
|
||
|
|
}
|
||
|
|
|
||
|
|
onDaysChange() {
|
||
|
|
if (typeof this.days === 'undefined') {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (this.days < 0) {
|
||
|
|
this.days = 0;
|
||
|
|
}
|
||
|
|
this.updateView();
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|