Commit f1193c1d5b082d13f62a25bda15dc3c335fff89b

Authored by Vladyslav_Prykhodko
1 parent 430e96cd

UI: Added new history time window type - interval

  1 +<!--
  2 +
  3 + Copyright © 2016-2021 The Thingsboard Authors
  4 +
  5 + Licensed under the Apache License, Version 2.0 (the "License");
  6 + you may not use this file except in compliance with the License.
  7 + You may obtain a copy of the License at
  8 +
  9 + http://www.apache.org/licenses/LICENSE-2.0
  10 +
  11 + Unless required by applicable law or agreed to in writing, software
  12 + distributed under the License is distributed on an "AS IS" BASIS,
  13 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14 + See the License for the specific language governing permissions and
  15 + limitations under the License.
  16 +
  17 +-->
  18 +<section class="interval-section" fxLayout="row" fxFlex>
  19 + <mat-form-field fxFlex>
  20 + <mat-label translate>timewindow.interval</mat-label>
  21 + <mat-select [disabled]="disabled" [(ngModel)]="modelValue" (ngModelChange)="onIntervalChange()">
  22 + <mat-option *ngFor="let interval of intervals" [value]="interval">
  23 + {{ timeIntervalTranslationMap.get(interval) | translate}}
  24 + </mat-option>
  25 + </mat-select>
  26 + </mat-form-field>
  27 +</section>
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +
  17 +:host {
  18 + min-width: 364px;
  19 +}
  1 +///
  2 +/// Copyright © 2016-2021 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { Component, forwardRef, Input, OnInit } from '@angular/core';
  18 +import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
  19 +import { QuickTimeInterval, QuickTimeIntervalTranslationMap } from '@shared/models/time/time.models';
  20 +
  21 +@Component({
  22 + selector: 'tb-quick-time-interval',
  23 + templateUrl: './quick-time-interval.component.html',
  24 + styleUrls: ['./quick-time-interval.component.scss'],
  25 + providers: [
  26 + {
  27 + provide: NG_VALUE_ACCESSOR,
  28 + useExisting: forwardRef(() => QuickTimeIntervalComponent),
  29 + multi: true
  30 + }
  31 + ]
  32 +})
  33 +export class QuickTimeIntervalComponent implements OnInit, ControlValueAccessor {
  34 +
  35 + private allIntervals = Object.values(QuickTimeInterval);
  36 +
  37 + modelValue: QuickTimeInterval;
  38 + timeIntervalTranslationMap = QuickTimeIntervalTranslationMap;
  39 +
  40 + rendered = false;
  41 +
  42 + @Input() disabled: boolean;
  43 +
  44 + @Input() onlyCurrentInterval = false;
  45 +
  46 + private propagateChange = (_: any) => {};
  47 +
  48 + constructor() {
  49 + }
  50 +
  51 + get intervals() {
  52 + if (this.onlyCurrentInterval) {
  53 + return this.allIntervals.filter(interval => interval.startsWith('TODAY_') || interval.startsWith('CURRENT_'));
  54 + }
  55 + return this.allIntervals;
  56 + }
  57 +
  58 + ngOnInit(): void {
  59 + }
  60 +
  61 + registerOnChange(fn: any): void {
  62 + this.propagateChange = fn;
  63 + }
  64 +
  65 + registerOnTouched(fn: any): void {
  66 + }
  67 +
  68 + setDisabledState(isDisabled: boolean): void {
  69 + this.disabled = isDisabled;
  70 + }
  71 +
  72 + writeValue(interval: QuickTimeInterval): void {
  73 + this.modelValue = interval;
  74 + this.rendered = true;
  75 + }
  76 +
  77 + onIntervalChange() {
  78 + this.propagateChange(this.modelValue);
  79 + }
  80 +}
@@ -65,6 +65,17 @@ @@ -65,6 +65,17 @@
65 style="padding-top: 8px;"></tb-datetime-period> 65 style="padding-top: 8px;"></tb-datetime-period>
66 </section> 66 </section>
67 </mat-radio-button> 67 </mat-radio-button>
  68 + <mat-radio-button [value]="historyTypes.INTERVAL" color="primary">
  69 + <section fxLayout="column">
  70 + <span translate>timewindow.interval</span>
  71 + <tb-quick-time-interval
  72 + formControlName="quickInterval"
  73 + [fxShow]="timewindowForm.get('history.historyType').value === historyTypes.INTERVAL"
  74 + [required]="timewindow.selectedTab === timewindowTypes.HISTORY &&
  75 + timewindowForm.get('history.historyType').value === historyTypes.INTERVAL"
  76 + style="padding-top: 8px; min-width: 364px"></tb-quick-time-interval>
  77 + </section>
  78 + </mat-radio-button>
68 </mat-radio-group> 79 </mat-radio-group>
69 </div> 80 </div>
70 </section> 81 </section>
@@ -19,7 +19,7 @@ import { @@ -19,7 +19,7 @@ import {
19 aggregationTranslations, 19 aggregationTranslations,
20 AggregationType, 20 AggregationType,
21 DAY, 21 DAY,
22 - HistoryWindowType, 22 + HistoryWindowType, quickTimeIntervalPeriod,
23 Timewindow, 23 Timewindow,
24 TimewindowType 24 TimewindowType
25 } from '@shared/models/time/time.models'; 25 } from '@shared/models/time/time.models';
@@ -119,7 +119,12 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit { @@ -119,7 +119,12 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit {
119 value: this.timewindow.history && typeof this.timewindow.history.fixedTimewindow !== 'undefined' 119 value: this.timewindow.history && typeof this.timewindow.history.fixedTimewindow !== 'undefined'
120 ? this.timewindow.history.fixedTimewindow : null, 120 ? this.timewindow.history.fixedTimewindow : null,
121 disabled: hideInterval 121 disabled: hideInterval
122 - }) 122 + }),
  123 + quickInterval: this.fb.control({
  124 + value: this.timewindow.history && typeof this.timewindow.history.quickInterval !== 'undefined'
  125 + ? this.timewindow.history.quickInterval : null,
  126 + disabled: hideInterval
  127 + }),
123 } 128 }
124 ), 129 ),
125 aggregation: this.fb.group( 130 aggregation: this.fb.group(
@@ -149,7 +154,8 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit { @@ -149,7 +154,8 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit {
149 historyType: timewindowFormValue.history.historyType, 154 historyType: timewindowFormValue.history.historyType,
150 timewindowMs: timewindowFormValue.history.timewindowMs, 155 timewindowMs: timewindowFormValue.history.timewindowMs,
151 interval: timewindowFormValue.history.interval, 156 interval: timewindowFormValue.history.interval,
152 - fixedTimewindow: timewindowFormValue.history.fixedTimewindow 157 + fixedTimewindow: timewindowFormValue.history.fixedTimewindow,
  158 + quickInterval: timewindowFormValue.history.quickInterval
153 }; 159 };
154 if (this.aggregation) { 160 if (this.aggregation) {
155 this.timewindow.aggregation = { 161 this.timewindow.aggregation = {
@@ -193,6 +199,8 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit { @@ -193,6 +199,8 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit {
193 const timewindowFormValue = this.timewindowForm.getRawValue(); 199 const timewindowFormValue = this.timewindowForm.getRawValue();
194 if (timewindowFormValue.history.historyType === HistoryWindowType.LAST_INTERVAL) { 200 if (timewindowFormValue.history.historyType === HistoryWindowType.LAST_INTERVAL) {
195 return timewindowFormValue.history.timewindowMs; 201 return timewindowFormValue.history.timewindowMs;
  202 + } else if (timewindowFormValue.history.historyType === HistoryWindowType.INTERVAL) {
  203 + return quickTimeIntervalPeriod(timewindowFormValue.history.quickInterval);
196 } else if (timewindowFormValue.history.fixedTimewindow) { 204 } else if (timewindowFormValue.history.fixedTimewindow) {
197 return timewindowFormValue.history.fixedTimewindow.endTimeMs - 205 return timewindowFormValue.history.fixedTimewindow.endTimeMs -
198 timewindowFormValue.history.fixedTimewindow.startTimeMs; 206 timewindowFormValue.history.fixedTimewindow.startTimeMs;
@@ -206,10 +214,12 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit { @@ -206,10 +214,12 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit {
206 this.timewindowForm.get('history.historyType').disable({emitEvent: false}); 214 this.timewindowForm.get('history.historyType').disable({emitEvent: false});
207 this.timewindowForm.get('history.timewindowMs').disable({emitEvent: false}); 215 this.timewindowForm.get('history.timewindowMs').disable({emitEvent: false});
208 this.timewindowForm.get('history.fixedTimewindow').disable({emitEvent: false}); 216 this.timewindowForm.get('history.fixedTimewindow').disable({emitEvent: false});
  217 + this.timewindowForm.get('history.quickInterval').disable({emitEvent: false});
209 } else { 218 } else {
210 this.timewindowForm.get('history.historyType').enable({emitEvent: false}); 219 this.timewindowForm.get('history.historyType').enable({emitEvent: false});
211 this.timewindowForm.get('history.timewindowMs').enable({emitEvent: false}); 220 this.timewindowForm.get('history.timewindowMs').enable({emitEvent: false});
212 this.timewindowForm.get('history.fixedTimewindow').enable({emitEvent: false}); 221 this.timewindowForm.get('history.fixedTimewindow').enable({emitEvent: false});
  222 + this.timewindowForm.get('history.quickInterval').enable({emitEvent: false});
213 } 223 }
214 this.timewindowForm.markAsDirty(); 224 this.timewindowForm.markAsDirty();
215 } 225 }
@@ -33,6 +33,7 @@ import { @@ -33,6 +33,7 @@ import {
33 cloneSelectedTimewindow, 33 cloneSelectedTimewindow,
34 HistoryWindowType, 34 HistoryWindowType,
35 initModelFromDefaultTimewindow, 35 initModelFromDefaultTimewindow,
  36 + QuickTimeIntervalTranslationMap,
36 Timewindow, 37 Timewindow,
37 TimewindowType 38 TimewindowType
38 } from '@shared/models/time/time.models'; 39 } from '@shared/models/time/time.models';
@@ -280,6 +281,8 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces @@ -280,6 +281,8 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces
280 if (this.innerValue.history.historyType === HistoryWindowType.LAST_INTERVAL) { 281 if (this.innerValue.history.historyType === HistoryWindowType.LAST_INTERVAL) {
281 this.innerValue.displayValue += this.translate.instant('timewindow.last-prefix') + ' ' + 282 this.innerValue.displayValue += this.translate.instant('timewindow.last-prefix') + ' ' +
282 this.millisecondsToTimeStringPipe.transform(this.innerValue.history.timewindowMs); 283 this.millisecondsToTimeStringPipe.transform(this.innerValue.history.timewindowMs);
  284 + } else if (this.innerValue.history.historyType === HistoryWindowType.INTERVAL) {
  285 + this.innerValue.displayValue += this.translate.instant(QuickTimeIntervalTranslationMap.get(this.innerValue.history.quickInterval));
283 } else { 286 } else {
284 const startString = this.datePipe.transform(this.innerValue.history.fixedTimewindow.startTimeMs, 'yyyy-MM-dd HH:mm:ss'); 287 const startString = this.datePipe.transform(this.innerValue.history.fixedTimewindow.startTimeMs, 'yyyy-MM-dd HH:mm:ss');
285 const endString = this.datePipe.transform(this.innerValue.history.fixedTimewindow.endTimeMs, 'yyyy-MM-dd HH:mm:ss'); 288 const endString = this.datePipe.transform(this.innerValue.history.fixedTimewindow.endTimeMs, 'yyyy-MM-dd HH:mm:ss');
@@ -27,6 +27,7 @@ export const SECOND = 1000; @@ -27,6 +27,7 @@ export const SECOND = 1000;
27 export const MINUTE = 60 * SECOND; 27 export const MINUTE = 60 * SECOND;
28 export const HOUR = 60 * MINUTE; 28 export const HOUR = 60 * MINUTE;
29 export const DAY = 24 * HOUR; 29 export const DAY = 24 * HOUR;
  30 +export const WEEK = 7 * DAY;
30 export const YEAR = DAY * 365; 31 export const YEAR = DAY * 365;
31 32
32 export enum TimewindowType { 33 export enum TimewindowType {
@@ -36,12 +37,14 @@ export enum TimewindowType { @@ -36,12 +37,14 @@ export enum TimewindowType {
36 37
37 export enum HistoryWindowType { 38 export enum HistoryWindowType {
38 LAST_INTERVAL, 39 LAST_INTERVAL,
39 - FIXED 40 + FIXED,
  41 + INTERVAL
40 } 42 }
41 43
42 export interface IntervalWindow { 44 export interface IntervalWindow {
43 interval?: number; 45 interval?: number;
44 timewindowMs?: number; 46 timewindowMs?: number;
  47 + quickInterval?: QuickTimeInterval;
45 } 48 }
46 49
47 export interface FixedWindow { 50 export interface FixedWindow {
@@ -111,6 +114,40 @@ export interface WidgetTimewindow { @@ -111,6 +114,40 @@ export interface WidgetTimewindow {
111 stDiff?: number; 114 stDiff?: number;
112 } 115 }
113 116
  117 +export enum QuickTimeInterval {
  118 + YESTERDAY = 'YESTERDAY',
  119 + DAY_BEFORE_YESTERDAY = 'DAY_BEFORE_YESTERDAY',
  120 + THIS_DAY_LAST_WEEK = 'THIS_DAY_LAST_WEEK',
  121 + PREVIOUS_WEEK = 'PREVIOUS_WEEK',
  122 + PREVIOUS_MONTH = 'PREVIOUS_MONTH',
  123 + PREVIOUS_YEAR = 'PREVIOUS_YEAR',
  124 + TODAY = 'TODAY',
  125 + TODAY_SO_FAR = 'TODAY_SO_FAR',
  126 + CURRENT_WEEK = 'CURRENT_WEEK',
  127 + CURRENT_WEEK_SO_FAR = 'CURRENT_WEEK_SO_WAR',
  128 + CURRENT_MONTH = 'CURRENT_MONTH',
  129 + CURRENT_MONTH_SO_FAR = 'CURRENT_MONTH_SO_FAR',
  130 + CURRENT_YEAR = 'CURRENT_YEAR',
  131 + CURRENT_YEAR_SO_FAR = 'CURRENT_YEAR_SO_FAR'
  132 +}
  133 +
  134 +export const QuickTimeIntervalTranslationMap = new Map<QuickTimeInterval, string>([
  135 + [QuickTimeInterval.YESTERDAY, 'timeinterval.predefined.yesterday'],
  136 + [QuickTimeInterval.DAY_BEFORE_YESTERDAY, 'timeinterval.predefined.day-before-yesterday'],
  137 + [QuickTimeInterval.THIS_DAY_LAST_WEEK, 'timeinterval.predefined.this-day-last-week'],
  138 + [QuickTimeInterval.PREVIOUS_WEEK, 'timeinterval.predefined.previous-week'],
  139 + [QuickTimeInterval.PREVIOUS_MONTH, 'timeinterval.predefined.previous-month'],
  140 + [QuickTimeInterval.PREVIOUS_YEAR, 'timeinterval.predefined.previous-year'],
  141 + [QuickTimeInterval.TODAY, 'timeinterval.predefined.today'],
  142 + [QuickTimeInterval.TODAY_SO_FAR, 'timeinterval.predefined.today-so-far'],
  143 + [QuickTimeInterval.CURRENT_WEEK, 'timeinterval.predefined.current-week'],
  144 + [QuickTimeInterval.CURRENT_WEEK_SO_FAR, 'timeinterval.predefined.current-week-so-far'],
  145 + [QuickTimeInterval.CURRENT_MONTH, 'timeinterval.predefined.current-month'],
  146 + [QuickTimeInterval.CURRENT_MONTH_SO_FAR, 'timeinterval.predefined.current-month-so-far'],
  147 + [QuickTimeInterval.CURRENT_YEAR, 'timeinterval.predefined.current-year'],
  148 + [QuickTimeInterval.CURRENT_YEAR_SO_FAR, 'timeinterval.predefined.current-year-so-far']
  149 +]);
  150 +
114 export function historyInterval(timewindowMs: number): Timewindow { 151 export function historyInterval(timewindowMs: number): Timewindow {
115 const timewindow: Timewindow = { 152 const timewindow: Timewindow = {
116 selectedTab: TimewindowType.HISTORY, 153 selectedTab: TimewindowType.HISTORY,
@@ -141,7 +178,8 @@ export function defaultTimewindow(timeService: TimeService): Timewindow { @@ -141,7 +178,8 @@ export function defaultTimewindow(timeService: TimeService): Timewindow {
141 fixedTimewindow: { 178 fixedTimewindow: {
142 startTimeMs: currentTime - DAY, 179 startTimeMs: currentTime - DAY,
143 endTimeMs: currentTime 180 endTimeMs: currentTime
144 - } 181 + },
  182 + quickInterval: QuickTimeInterval.TODAY
145 }, 183 },
146 aggregation: { 184 aggregation: {
147 type: AggregationType.AVG, 185 type: AggregationType.AVG,
@@ -178,6 +216,8 @@ export function initModelFromDefaultTimewindow(value: Timewindow, timeService: T @@ -178,6 +216,8 @@ export function initModelFromDefaultTimewindow(value: Timewindow, timeService: T
178 if (isUndefined(value.history.historyType)) { 216 if (isUndefined(value.history.historyType)) {
179 if (isDefined(value.history.timewindowMs)) { 217 if (isDefined(value.history.timewindowMs)) {
180 model.history.historyType = HistoryWindowType.LAST_INTERVAL; 218 model.history.historyType = HistoryWindowType.LAST_INTERVAL;
  219 + } else if (isDefined(value.history.quickInterval)) {
  220 + model.history.historyType = HistoryWindowType.INTERVAL;
181 } else { 221 } else {
182 model.history.historyType = HistoryWindowType.FIXED; 222 model.history.historyType = HistoryWindowType.FIXED;
183 } 223 }
@@ -186,6 +226,8 @@ export function initModelFromDefaultTimewindow(value: Timewindow, timeService: T @@ -186,6 +226,8 @@ export function initModelFromDefaultTimewindow(value: Timewindow, timeService: T
186 } 226 }
187 if (model.history.historyType === HistoryWindowType.LAST_INTERVAL) { 227 if (model.history.historyType === HistoryWindowType.LAST_INTERVAL) {
188 model.history.timewindowMs = value.history.timewindowMs; 228 model.history.timewindowMs = value.history.timewindowMs;
  229 + } else if (model.history.historyType === HistoryWindowType.INTERVAL) {
  230 + model.history.quickInterval = value.history.quickInterval;
189 } else { 231 } else {
190 model.history.fixedTimewindow.startTimeMs = value.history.fixedTimewindow.startTimeMs; 232 model.history.fixedTimewindow.startTimeMs = value.history.fixedTimewindow.startTimeMs;
191 model.history.fixedTimewindow.endTimeMs = value.history.fixedTimewindow.endTimeMs; 233 model.history.fixedTimewindow.endTimeMs = value.history.fixedTimewindow.endTimeMs;
@@ -281,7 +323,13 @@ export function createSubscriptionTimewindow(timewindow: Timewindow, stDiff: num @@ -281,7 +323,13 @@ export function createSubscriptionTimewindow(timewindow: Timewindow, stDiff: num
281 } else { 323 } else {
282 let historyType = timewindow.history.historyType; 324 let historyType = timewindow.history.historyType;
283 if (isUndefined(historyType)) { 325 if (isUndefined(historyType)) {
284 - historyType = isDefined(timewindow.history.timewindowMs) ? HistoryWindowType.LAST_INTERVAL : HistoryWindowType.FIXED; 326 + if (isDefined(timewindow.history.timewindowMs)) {
  327 + historyType = HistoryWindowType.LAST_INTERVAL;
  328 + } else if (isDefined(timewindow.history.quickInterval)) {
  329 + historyType = HistoryWindowType.INTERVAL;
  330 + } else {
  331 + historyType = HistoryWindowType.FIXED;
  332 + }
285 } 333 }
286 if (historyType === HistoryWindowType.LAST_INTERVAL) { 334 if (historyType === HistoryWindowType.LAST_INTERVAL) {
287 const currentTime = Date.now(); 335 const currentTime = Date.now();
@@ -290,6 +338,9 @@ export function createSubscriptionTimewindow(timewindow: Timewindow, stDiff: num @@ -290,6 +338,9 @@ export function createSubscriptionTimewindow(timewindow: Timewindow, stDiff: num
290 endTimeMs: currentTime 338 endTimeMs: currentTime
291 }; 339 };
292 aggTimewindow = timewindow.history.timewindowMs; 340 aggTimewindow = timewindow.history.timewindowMs;
  341 + } else if (historyType === HistoryWindowType.INTERVAL) {
  342 + subscriptionTimewindow.fixedWindow = createSubscriptionTimeWindowFromQuickKTimeInterval(timewindow.history.quickInterval);
  343 + aggTimewindow = subscriptionTimewindow.fixedWindow.endTimeMs - subscriptionTimewindow.fixedWindow.startTimeMs;
293 } else { 344 } else {
294 subscriptionTimewindow.fixedWindow = { 345 subscriptionTimewindow.fixedWindow = {
295 startTimeMs: timewindow.history.fixedTimewindow.startTimeMs, 346 startTimeMs: timewindow.history.fixedTimewindow.startTimeMs,
@@ -309,6 +360,102 @@ export function createSubscriptionTimewindow(timewindow: Timewindow, stDiff: num @@ -309,6 +360,102 @@ export function createSubscriptionTimewindow(timewindow: Timewindow, stDiff: num
309 return subscriptionTimewindow; 360 return subscriptionTimewindow;
310 } 361 }
311 362
  363 +export function createSubscriptionTimeWindowFromQuickKTimeInterval(interval: QuickTimeInterval): FixedWindow {
  364 + const currentDate = moment();
  365 + const timeWindow = {
  366 + startTimeMs: 0,
  367 + endTimeMs: 0
  368 + };
  369 + switch (interval) {
  370 + case QuickTimeInterval.YESTERDAY:
  371 + currentDate.subtract(1, 'days');
  372 + timeWindow.startTimeMs = currentDate.startOf('day').valueOf();
  373 + timeWindow.endTimeMs = currentDate.endOf('day').valueOf();
  374 + break;
  375 + case QuickTimeInterval.DAY_BEFORE_YESTERDAY:
  376 + currentDate.subtract(2, 'days');
  377 + timeWindow.startTimeMs = currentDate.startOf('day').valueOf();
  378 + timeWindow.endTimeMs = currentDate.endOf('day').valueOf();
  379 + break;
  380 + case QuickTimeInterval.THIS_DAY_LAST_WEEK:
  381 + currentDate.subtract(1, 'weeks');
  382 + timeWindow.startTimeMs = currentDate.startOf('day').valueOf();
  383 + timeWindow.endTimeMs = currentDate.endOf('day').valueOf();
  384 + break;
  385 + case QuickTimeInterval.PREVIOUS_WEEK:
  386 + currentDate.subtract(1, 'weeks');
  387 + timeWindow.startTimeMs = currentDate.startOf('week').valueOf();
  388 + timeWindow.endTimeMs = currentDate.endOf('week').valueOf();
  389 + break;
  390 + case QuickTimeInterval.PREVIOUS_MONTH:
  391 + currentDate.subtract(1, 'months');
  392 + timeWindow.startTimeMs = currentDate.startOf('month').valueOf();
  393 + timeWindow.endTimeMs = currentDate.endOf('month').valueOf();
  394 + break;
  395 + case QuickTimeInterval.PREVIOUS_YEAR:
  396 + currentDate.subtract(1, 'years');
  397 + timeWindow.startTimeMs = currentDate.startOf('year').valueOf();
  398 + timeWindow.endTimeMs = currentDate.endOf('year').valueOf();
  399 + break;
  400 + case QuickTimeInterval.TODAY:
  401 + timeWindow.startTimeMs = currentDate.startOf('day').valueOf();
  402 + timeWindow.endTimeMs = currentDate.endOf('day').valueOf();
  403 + break;
  404 + case QuickTimeInterval.TODAY_SO_FAR:
  405 + timeWindow.endTimeMs = currentDate.valueOf();
  406 + timeWindow.startTimeMs = currentDate.startOf('day').valueOf();
  407 + break;
  408 + case QuickTimeInterval.CURRENT_WEEK:
  409 + timeWindow.startTimeMs = currentDate.startOf('week').valueOf();
  410 + timeWindow.endTimeMs = currentDate.endOf('week').valueOf();
  411 + break;
  412 + case QuickTimeInterval.CURRENT_WEEK_SO_FAR:
  413 + timeWindow.endTimeMs = currentDate.valueOf();
  414 + timeWindow.startTimeMs = currentDate.startOf('week').valueOf();
  415 + break;
  416 + case QuickTimeInterval.CURRENT_MONTH:
  417 + timeWindow.startTimeMs = currentDate.startOf('month').valueOf();
  418 + timeWindow.endTimeMs = currentDate.endOf('month').valueOf();
  419 + break;
  420 + case QuickTimeInterval.CURRENT_MONTH_SO_FAR:
  421 + timeWindow.endTimeMs = currentDate.valueOf();
  422 + timeWindow.startTimeMs = currentDate.startOf('month').valueOf();
  423 + break;
  424 + case QuickTimeInterval.CURRENT_YEAR:
  425 + timeWindow.startTimeMs = currentDate.startOf('year').valueOf();
  426 + timeWindow.endTimeMs = currentDate.endOf('year').valueOf();
  427 + break;
  428 + case QuickTimeInterval.CURRENT_YEAR_SO_FAR:
  429 + timeWindow.endTimeMs = currentDate.valueOf();
  430 + timeWindow.startTimeMs = currentDate.startOf('year').valueOf();
  431 + break;
  432 + }
  433 + return timeWindow;
  434 +}
  435 +
  436 +export function quickTimeIntervalPeriod(interval: QuickTimeInterval): number {
  437 + switch (interval) {
  438 + case QuickTimeInterval.YESTERDAY:
  439 + case QuickTimeInterval.DAY_BEFORE_YESTERDAY:
  440 + case QuickTimeInterval.THIS_DAY_LAST_WEEK:
  441 + case QuickTimeInterval.TODAY:
  442 + case QuickTimeInterval.TODAY_SO_FAR:
  443 + return DAY;
  444 + case QuickTimeInterval.PREVIOUS_WEEK:
  445 + case QuickTimeInterval.CURRENT_WEEK:
  446 + case QuickTimeInterval.CURRENT_WEEK_SO_FAR:
  447 + return WEEK;
  448 + case QuickTimeInterval.PREVIOUS_MONTH:
  449 + case QuickTimeInterval.CURRENT_MONTH:
  450 + case QuickTimeInterval.CURRENT_MONTH_SO_FAR:
  451 + return DAY * 30;
  452 + case QuickTimeInterval.PREVIOUS_YEAR:
  453 + case QuickTimeInterval.CURRENT_YEAR:
  454 + case QuickTimeInterval.CURRENT_YEAR_SO_FAR:
  455 + return YEAR;
  456 + }
  457 +}
  458 +
312 export function createTimewindowForComparison(subscriptionTimewindow: SubscriptionTimewindow, 459 export function createTimewindowForComparison(subscriptionTimewindow: SubscriptionTimewindow,
313 timeUnit: moment_.unitOfTime.DurationConstructor): SubscriptionTimewindow { 460 timeUnit: moment_.unitOfTime.DurationConstructor): SubscriptionTimewindow {
314 const timewindowForComparison: SubscriptionTimewindow = { 461 const timewindowForComparison: SubscriptionTimewindow = {
@@ -358,6 +505,8 @@ export function cloneSelectedHistoryTimewindow(historyWindow: HistoryWindow): Hi @@ -358,6 +505,8 @@ export function cloneSelectedHistoryTimewindow(historyWindow: HistoryWindow): Hi
358 cloned.interval = historyWindow.interval; 505 cloned.interval = historyWindow.interval;
359 if (historyWindow.historyType === HistoryWindowType.LAST_INTERVAL) { 506 if (historyWindow.historyType === HistoryWindowType.LAST_INTERVAL) {
360 cloned.timewindowMs = historyWindow.timewindowMs; 507 cloned.timewindowMs = historyWindow.timewindowMs;
  508 + } else if (historyWindow.historyType === HistoryWindowType.INTERVAL) {
  509 + cloned.quickInterval = historyWindow.quickInterval;
361 } else if (historyWindow.historyType === HistoryWindowType.FIXED) { 510 } else if (historyWindow.historyType === HistoryWindowType.FIXED) {
362 cloned.fixedTimewindow = deepClone(historyWindow.fixedTimewindow); 511 cloned.fixedTimewindow = deepClone(historyWindow.fixedTimewindow);
363 } 512 }
@@ -375,7 +524,7 @@ export const defaultTimeIntervals = new Array<TimeInterval>( @@ -375,7 +524,7 @@ export const defaultTimeIntervals = new Array<TimeInterval>(
375 { 524 {
376 name: 'timeinterval.seconds-interval', 525 name: 'timeinterval.seconds-interval',
377 translateParams: {seconds: 1}, 526 translateParams: {seconds: 1},
378 - value: 1 * SECOND 527 + value: SECOND
379 }, 528 },
380 { 529 {
381 name: 'timeinterval.seconds-interval', 530 name: 'timeinterval.seconds-interval',
@@ -400,7 +549,7 @@ export const defaultTimeIntervals = new Array<TimeInterval>( @@ -400,7 +549,7 @@ export const defaultTimeIntervals = new Array<TimeInterval>(
400 { 549 {
401 name: 'timeinterval.minutes-interval', 550 name: 'timeinterval.minutes-interval',
402 translateParams: {minutes: 1}, 551 translateParams: {minutes: 1},
403 - value: 1 * MINUTE 552 + value: MINUTE
404 }, 553 },
405 { 554 {
406 name: 'timeinterval.minutes-interval', 555 name: 'timeinterval.minutes-interval',
@@ -430,7 +579,7 @@ export const defaultTimeIntervals = new Array<TimeInterval>( @@ -430,7 +579,7 @@ export const defaultTimeIntervals = new Array<TimeInterval>(
430 { 579 {
431 name: 'timeinterval.hours-interval', 580 name: 'timeinterval.hours-interval',
432 translateParams: {hours: 1}, 581 translateParams: {hours: 1},
433 - value: 1 * HOUR 582 + value: HOUR
434 }, 583 },
435 { 584 {
436 name: 'timeinterval.hours-interval', 585 name: 'timeinterval.hours-interval',
@@ -455,7 +604,7 @@ export const defaultTimeIntervals = new Array<TimeInterval>( @@ -455,7 +604,7 @@ export const defaultTimeIntervals = new Array<TimeInterval>(
455 { 604 {
456 name: 'timeinterval.days-interval', 605 name: 'timeinterval.days-interval',
457 translateParams: {days: 1}, 606 translateParams: {days: 1},
458 - value: 1 * DAY 607 + value: DAY
459 }, 608 },
460 { 609 {
461 name: 'timeinterval.days-interval', 610 name: 'timeinterval.days-interval',
@@ -140,6 +140,7 @@ import { TimezoneSelectComponent } from '@shared/components/time/timezone-select @@ -140,6 +140,7 @@ import { TimezoneSelectComponent } from '@shared/components/time/timezone-select
140 import { FileSizePipe } from '@shared/pipe/file-size.pipe'; 140 import { FileSizePipe } from '@shared/pipe/file-size.pipe';
141 import { WidgetsBundleSearchComponent } from '@shared/components/widgets-bundle-search.component'; 141 import { WidgetsBundleSearchComponent } from '@shared/components/widgets-bundle-search.component';
142 import { SelectableColumnsPipe } from '@shared/pipe/selectable-columns.pipe'; 142 import { SelectableColumnsPipe } from '@shared/pipe/selectable-columns.pipe';
  143 +import { QuickTimeIntervalComponent } from '@shared/components/time/quick-time-interval.component';
143 144
144 @NgModule({ 145 @NgModule({
145 providers: [ 146 providers: [
@@ -175,6 +176,7 @@ import { SelectableColumnsPipe } from '@shared/pipe/selectable-columns.pipe'; @@ -175,6 +176,7 @@ import { SelectableColumnsPipe } from '@shared/pipe/selectable-columns.pipe';
175 TimewindowComponent, 176 TimewindowComponent,
176 TimewindowPanelComponent, 177 TimewindowPanelComponent,
177 TimeintervalComponent, 178 TimeintervalComponent,
  179 + QuickTimeIntervalComponent,
178 DashboardSelectComponent, 180 DashboardSelectComponent,
179 DashboardSelectPanelComponent, 181 DashboardSelectPanelComponent,
180 DatetimePeriodComponent, 182 DatetimePeriodComponent,
@@ -302,6 +304,7 @@ import { SelectableColumnsPipe } from '@shared/pipe/selectable-columns.pipe'; @@ -302,6 +304,7 @@ import { SelectableColumnsPipe } from '@shared/pipe/selectable-columns.pipe';
302 TimewindowComponent, 304 TimewindowComponent,
303 TimewindowPanelComponent, 305 TimewindowPanelComponent,
304 TimeintervalComponent, 306 TimeintervalComponent,
  307 + QuickTimeIntervalComponent,
305 DashboardSelectComponent, 308 DashboardSelectComponent,
306 DatetimePeriodComponent, 309 DatetimePeriodComponent,
307 DatetimeComponent, 310 DatetimeComponent,
@@ -2111,7 +2111,23 @@ @@ -2111,7 +2111,23 @@
2111 "hours": "Hours", 2111 "hours": "Hours",
2112 "minutes": "Minutes", 2112 "minutes": "Minutes",
2113 "seconds": "Seconds", 2113 "seconds": "Seconds",
2114 - "advanced": "Advanced" 2114 + "advanced": "Advanced",
  2115 + "predefined": {
  2116 + "yesterday": "Yesterday",
  2117 + "day-before-yesterday": "Day before yesterday",
  2118 + "this-day-last-week": "This day last week",
  2119 + "previous-week": "Previous week",
  2120 + "previous-month": "Previous month",
  2121 + "previous-year": "Previous year",
  2122 + "today": "Today",
  2123 + "today-so-far": "Today so far",
  2124 + "current-week": "Current week",
  2125 + "current-week-so-far": "Current week so far",
  2126 + "current-month": "Current month",
  2127 + "current-month-so-far": "Current month so far",
  2128 + "current-year": "Current year",
  2129 + "current-year-so-far": "Current year so far"
  2130 + }
2115 }, 2131 },
2116 "timeunit": { 2132 "timeunit": {
2117 "seconds": "Seconds", 2133 "seconds": "Seconds",
@@ -2132,7 +2148,8 @@ @@ -2132,7 +2148,8 @@
2132 "date-range": "Date range", 2148 "date-range": "Date range",
2133 "last": "Last", 2149 "last": "Last",
2134 "time-period": "Time period", 2150 "time-period": "Time period",
2135 - "hide": "Hide" 2151 + "hide": "Hide",
  2152 + "interval": "Interval"
2136 }, 2153 },
2137 "user": { 2154 "user": {
2138 "user": "User", 2155 "user": "User",