1504 lines
		
	
	
		
			57 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			1504 lines
		
	
	
		
			57 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
///
 | 
						|
/// Copyright © 2016-2025 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 { TimeService } from '@core/services/time.service';
 | 
						|
import { deepClean, deepClone, isDefined, isDefinedAndNotNull, isNumeric, isUndefined } from '@app/core/utils';
 | 
						|
import moment_ from 'moment';
 | 
						|
import * as momentTz from 'moment-timezone';
 | 
						|
import { IntervalType } from '@shared/models/telemetry/telemetry.models';
 | 
						|
import { FormGroup } from '@angular/forms';
 | 
						|
 | 
						|
const moment = moment_;
 | 
						|
 | 
						|
export const SECOND = 1000;
 | 
						|
export const MINUTE = 60 * SECOND;
 | 
						|
export const HOUR = 60 * MINUTE;
 | 
						|
export const DAY = 24 * HOUR;
 | 
						|
export const WEEK = 7 * DAY;
 | 
						|
 | 
						|
export const AVG_MONTH = Math.floor(30.44 * DAY);
 | 
						|
 | 
						|
export const AVG_QUARTER = Math.floor(DAY * 365.2425 / 4);
 | 
						|
 | 
						|
export const YEAR = DAY * 365;
 | 
						|
 | 
						|
export type ComparisonDuration = moment_.unitOfTime.DurationConstructor | 'previousInterval' | 'customInterval';
 | 
						|
 | 
						|
export enum TimewindowType {
 | 
						|
  REALTIME,
 | 
						|
  HISTORY
 | 
						|
}
 | 
						|
 | 
						|
export enum RealtimeWindowType {
 | 
						|
  LAST_INTERVAL,
 | 
						|
  INTERVAL
 | 
						|
}
 | 
						|
 | 
						|
export enum HistoryWindowType {
 | 
						|
  LAST_INTERVAL,
 | 
						|
  FIXED,
 | 
						|
  INTERVAL,
 | 
						|
  FOR_ALL_TIME
 | 
						|
}
 | 
						|
 | 
						|
export const realtimeWindowTypeTranslations = new Map<RealtimeWindowType, string>([
 | 
						|
  [RealtimeWindowType.LAST_INTERVAL, 'timewindow.last'],
 | 
						|
  [RealtimeWindowType.INTERVAL, 'timewindow.relative']
 | 
						|
]);
 | 
						|
export const historyWindowTypeTranslations = new Map<HistoryWindowType, string>([
 | 
						|
  [HistoryWindowType.LAST_INTERVAL, 'timewindow.last'],
 | 
						|
  [HistoryWindowType.FIXED, 'timewindow.range'],
 | 
						|
  [HistoryWindowType.INTERVAL, 'timewindow.relative'],
 | 
						|
  [HistoryWindowType.FOR_ALL_TIME, 'timewindow.for-all-time']
 | 
						|
]);
 | 
						|
 | 
						|
export type Interval = number | IntervalType;
 | 
						|
 | 
						|
export class IntervalMath {
 | 
						|
  public static max(...values: Interval[]): Interval {
 | 
						|
    const numberArr = values.map(v => IntervalMath.numberValue(v));
 | 
						|
    const index = numberArr.indexOf(Math.max(...numberArr));
 | 
						|
    return values[index];
 | 
						|
  }
 | 
						|
 | 
						|
  public static min(...values: Interval[]): Interval {
 | 
						|
    const numberArr = values.map(v => IntervalMath.numberValue(v));
 | 
						|
    const index = numberArr.indexOf(Math.min(...numberArr));
 | 
						|
    return values[index];
 | 
						|
  }
 | 
						|
 | 
						|
  public static numberValue(value: Interval): number {
 | 
						|
    return typeof value === 'number' ? value : IntervalTypeValuesMap.get(value);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
export interface TimewindowAdvancedParams {
 | 
						|
  allowedLastIntervals? : Array<Interval>;
 | 
						|
  allowedQuickIntervals? : Array<QuickTimeInterval>;
 | 
						|
  lastAggIntervalsConfig? : TimewindowAggIntervalsConfig;
 | 
						|
  quickAggIntervalsConfig? : TimewindowAggIntervalsConfig;
 | 
						|
}
 | 
						|
 | 
						|
export type TimewindowInterval = Interval | QuickTimeInterval;
 | 
						|
 | 
						|
export interface TimewindowAggIntervalsConfig {
 | 
						|
  [key: string]: TimewindowAggIntervalOptions;
 | 
						|
}
 | 
						|
 | 
						|
export interface TimewindowAggIntervalOptions {
 | 
						|
  aggIntervals?: Array<Interval>;
 | 
						|
  defaultAggInterval?: Interval;
 | 
						|
}
 | 
						|
 | 
						|
export interface IntervalWindow {
 | 
						|
  interval?: Interval;
 | 
						|
  timewindowMs?: number;
 | 
						|
  quickInterval?: QuickTimeInterval;
 | 
						|
  disableCustomInterval?: boolean;
 | 
						|
  disableCustomGroupInterval?: boolean;
 | 
						|
  hideInterval?: boolean;
 | 
						|
  hideLastInterval?: boolean;
 | 
						|
  hideQuickInterval?: boolean;
 | 
						|
  hideFixedInterval?: boolean;
 | 
						|
  advancedParams?: TimewindowAdvancedParams
 | 
						|
}
 | 
						|
 | 
						|
export interface RealtimeWindow extends IntervalWindow{
 | 
						|
  realtimeType?: RealtimeWindowType;
 | 
						|
}
 | 
						|
 | 
						|
export interface FixedWindow {
 | 
						|
  startTimeMs: number;
 | 
						|
  endTimeMs: number;
 | 
						|
}
 | 
						|
 | 
						|
export interface HistoryWindow extends IntervalWindow {
 | 
						|
  historyType?: HistoryWindowType;
 | 
						|
  fixedTimewindow?: FixedWindow;
 | 
						|
}
 | 
						|
 | 
						|
export enum AggregationType {
 | 
						|
  MIN = 'MIN',
 | 
						|
  MAX = 'MAX',
 | 
						|
  AVG = 'AVG',
 | 
						|
  SUM = 'SUM',
 | 
						|
  COUNT = 'COUNT',
 | 
						|
  NONE = 'NONE'
 | 
						|
}
 | 
						|
 | 
						|
export const aggregationTranslations = new Map<AggregationType, string>(
 | 
						|
  [
 | 
						|
    [AggregationType.MIN, 'aggregation.min'],
 | 
						|
    [AggregationType.MAX, 'aggregation.max'],
 | 
						|
    [AggregationType.AVG, 'aggregation.avg'],
 | 
						|
    [AggregationType.SUM, 'aggregation.sum'],
 | 
						|
    [AggregationType.COUNT, 'aggregation.count'],
 | 
						|
    [AggregationType.NONE, 'aggregation.none'],
 | 
						|
  ]
 | 
						|
);
 | 
						|
 | 
						|
export interface Aggregation {
 | 
						|
  interval?: Interval;
 | 
						|
  type: AggregationType;
 | 
						|
  limit: number;
 | 
						|
}
 | 
						|
 | 
						|
export interface Timewindow {
 | 
						|
  displayValue?: string;
 | 
						|
  displayTimezoneAbbr?: string;
 | 
						|
  allowedAggTypes?: Array<AggregationType>;
 | 
						|
  hideAggregation?: boolean;
 | 
						|
  hideAggInterval?: boolean;
 | 
						|
  hideTimezone?: boolean;
 | 
						|
  selectedTab?: TimewindowType;
 | 
						|
  realtime?: RealtimeWindow;
 | 
						|
  history?: HistoryWindow;
 | 
						|
  aggregation?: Aggregation;
 | 
						|
  timezone?: string;
 | 
						|
}
 | 
						|
 | 
						|
export interface SubscriptionAggregation extends Aggregation {
 | 
						|
  interval?: Interval;
 | 
						|
  timeWindow?: number;
 | 
						|
  stateData?: boolean;
 | 
						|
}
 | 
						|
 | 
						|
export interface SubscriptionTimewindow {
 | 
						|
  startTs?: number;
 | 
						|
  quickInterval?: QuickTimeInterval;
 | 
						|
  timezone?: string;
 | 
						|
  tsOffset?: number;
 | 
						|
  realtimeWindowMs?: number;
 | 
						|
  fixedWindow?: FixedWindow;
 | 
						|
  aggregation?: SubscriptionAggregation;
 | 
						|
  timeForComparison?: ComparisonDuration;
 | 
						|
}
 | 
						|
 | 
						|
export interface WidgetTimewindow {
 | 
						|
  minTime?: number;
 | 
						|
  maxTime?: number;
 | 
						|
  interval?: Interval;
 | 
						|
  timezone?: string;
 | 
						|
  tsOffset?: number;
 | 
						|
  stDiff?: number;
 | 
						|
}
 | 
						|
 | 
						|
export interface TimewindowIntervalOption {
 | 
						|
  name: string;
 | 
						|
  translateParams?: {[key: string]: any};
 | 
						|
  value: TimewindowInterval;
 | 
						|
}
 | 
						|
 | 
						|
export enum QuickTimeInterval {
 | 
						|
  YESTERDAY = 'YESTERDAY',
 | 
						|
  DAY_BEFORE_YESTERDAY = 'DAY_BEFORE_YESTERDAY',
 | 
						|
  THIS_DAY_LAST_WEEK = 'THIS_DAY_LAST_WEEK',
 | 
						|
  PREVIOUS_WEEK = 'PREVIOUS_WEEK',
 | 
						|
  PREVIOUS_WEEK_ISO = 'PREVIOUS_WEEK_ISO',
 | 
						|
  PREVIOUS_MONTH = 'PREVIOUS_MONTH',
 | 
						|
  PREVIOUS_QUARTER = 'PREVIOUS_QUARTER',
 | 
						|
  PREVIOUS_HALF_YEAR = 'PREVIOUS_HALF_YEAR',
 | 
						|
  PREVIOUS_YEAR = 'PREVIOUS_YEAR',
 | 
						|
  CURRENT_HOUR = 'CURRENT_HOUR',
 | 
						|
  CURRENT_DAY = 'CURRENT_DAY',
 | 
						|
  CURRENT_DAY_SO_FAR = 'CURRENT_DAY_SO_FAR',
 | 
						|
  CURRENT_WEEK = 'CURRENT_WEEK',
 | 
						|
  CURRENT_WEEK_ISO = 'CURRENT_WEEK_ISO',
 | 
						|
  CURRENT_WEEK_SO_FAR = 'CURRENT_WEEK_SO_FAR',
 | 
						|
  CURRENT_WEEK_ISO_SO_FAR = 'CURRENT_WEEK_ISO_SO_FAR',
 | 
						|
  CURRENT_MONTH = 'CURRENT_MONTH',
 | 
						|
  CURRENT_MONTH_SO_FAR = 'CURRENT_MONTH_SO_FAR',
 | 
						|
  CURRENT_QUARTER = 'CURRENT_QUARTER',
 | 
						|
  CURRENT_QUARTER_SO_FAR = 'CURRENT_QUARTER_SO_FAR',
 | 
						|
  CURRENT_HALF_YEAR = 'CURRENT_HALF_YEAR',
 | 
						|
  CURRENT_HALF_YEAR_SO_FAR = 'CURRENT_HALF_YEAR_SO_FAR',
 | 
						|
  CURRENT_YEAR = 'CURRENT_YEAR',
 | 
						|
  CURRENT_YEAR_SO_FAR = 'CURRENT_YEAR_SO_FAR'
 | 
						|
}
 | 
						|
 | 
						|
export const QuickTimeIntervalTranslationMap = new Map<QuickTimeInterval, string>([
 | 
						|
  [QuickTimeInterval.YESTERDAY, 'timeinterval.predefined.yesterday'],
 | 
						|
  [QuickTimeInterval.DAY_BEFORE_YESTERDAY, 'timeinterval.predefined.day-before-yesterday'],
 | 
						|
  [QuickTimeInterval.THIS_DAY_LAST_WEEK, 'timeinterval.predefined.this-day-last-week'],
 | 
						|
  [QuickTimeInterval.PREVIOUS_WEEK, 'timeinterval.predefined.previous-week'],
 | 
						|
  [QuickTimeInterval.PREVIOUS_WEEK_ISO, 'timeinterval.predefined.previous-week-iso'],
 | 
						|
  [QuickTimeInterval.PREVIOUS_MONTH, 'timeinterval.predefined.previous-month'],
 | 
						|
  [QuickTimeInterval.PREVIOUS_QUARTER, 'timeinterval.predefined.previous-quarter'],
 | 
						|
  [QuickTimeInterval.PREVIOUS_HALF_YEAR, 'timeinterval.predefined.previous-half-year'],
 | 
						|
  [QuickTimeInterval.PREVIOUS_YEAR, 'timeinterval.predefined.previous-year'],
 | 
						|
  [QuickTimeInterval.CURRENT_HOUR, 'timeinterval.predefined.current-hour'],
 | 
						|
  [QuickTimeInterval.CURRENT_DAY, 'timeinterval.predefined.current-day'],
 | 
						|
  [QuickTimeInterval.CURRENT_DAY_SO_FAR, 'timeinterval.predefined.current-day-so-far'],
 | 
						|
  [QuickTimeInterval.CURRENT_WEEK, 'timeinterval.predefined.current-week'],
 | 
						|
  [QuickTimeInterval.CURRENT_WEEK_ISO, 'timeinterval.predefined.current-week-iso'],
 | 
						|
  [QuickTimeInterval.CURRENT_WEEK_SO_FAR, 'timeinterval.predefined.current-week-so-far'],
 | 
						|
  [QuickTimeInterval.CURRENT_WEEK_ISO_SO_FAR, 'timeinterval.predefined.current-week-iso-so-far'],
 | 
						|
  [QuickTimeInterval.CURRENT_MONTH, 'timeinterval.predefined.current-month'],
 | 
						|
  [QuickTimeInterval.CURRENT_MONTH_SO_FAR, 'timeinterval.predefined.current-month-so-far'],
 | 
						|
  [QuickTimeInterval.CURRENT_QUARTER, 'timeinterval.predefined.current-quarter'],
 | 
						|
  [QuickTimeInterval.CURRENT_QUARTER_SO_FAR, 'timeinterval.predefined.current-quarter-so-far'],
 | 
						|
  [QuickTimeInterval.CURRENT_HALF_YEAR, 'timeinterval.predefined.current-half-year'],
 | 
						|
  [QuickTimeInterval.CURRENT_HALF_YEAR_SO_FAR, 'timeinterval.predefined.current-half-year-so-far'],
 | 
						|
  [QuickTimeInterval.CURRENT_YEAR, 'timeinterval.predefined.current-year'],
 | 
						|
  [QuickTimeInterval.CURRENT_YEAR_SO_FAR, 'timeinterval.predefined.current-year-so-far']
 | 
						|
]);
 | 
						|
 | 
						|
export const IntervalTypeValuesMap = new Map<IntervalType, number>([
 | 
						|
  [IntervalType.WEEK, WEEK],
 | 
						|
  [IntervalType.WEEK_ISO, WEEK],
 | 
						|
  [IntervalType.MONTH, AVG_MONTH],
 | 
						|
  [IntervalType.QUARTER, AVG_QUARTER]
 | 
						|
]);
 | 
						|
 | 
						|
export const forAllTimeInterval = (): Timewindow => ({
 | 
						|
  selectedTab: TimewindowType.HISTORY,
 | 
						|
  history: {
 | 
						|
    historyType: HistoryWindowType.FOR_ALL_TIME
 | 
						|
  }
 | 
						|
});
 | 
						|
 | 
						|
export const historyInterval = (timewindowMs: number): Timewindow => ({
 | 
						|
  selectedTab: TimewindowType.HISTORY,
 | 
						|
  history: {
 | 
						|
    historyType: HistoryWindowType.LAST_INTERVAL,
 | 
						|
    timewindowMs
 | 
						|
  }
 | 
						|
});
 | 
						|
 | 
						|
export const defaultTimewindow = (timeService: TimeService): Timewindow => {
 | 
						|
  const currentTime = moment().valueOf();
 | 
						|
  return {
 | 
						|
    selectedTab: TimewindowType.REALTIME,
 | 
						|
    realtime: {
 | 
						|
      realtimeType: RealtimeWindowType.LAST_INTERVAL,
 | 
						|
      interval: SECOND,
 | 
						|
      timewindowMs: MINUTE,
 | 
						|
      quickInterval: QuickTimeInterval.CURRENT_DAY,
 | 
						|
    },
 | 
						|
    history: {
 | 
						|
      historyType: HistoryWindowType.LAST_INTERVAL,
 | 
						|
      interval: SECOND,
 | 
						|
      timewindowMs: MINUTE,
 | 
						|
      fixedTimewindow: {
 | 
						|
        startTimeMs: currentTime - DAY,
 | 
						|
        endTimeMs: currentTime
 | 
						|
      },
 | 
						|
      quickInterval: QuickTimeInterval.CURRENT_DAY,
 | 
						|
    },
 | 
						|
    aggregation: {
 | 
						|
      type: AggregationType.AVG,
 | 
						|
      limit: Math.floor(timeService.getMaxDatapointsLimit() / 2)
 | 
						|
    }
 | 
						|
  };
 | 
						|
};
 | 
						|
 | 
						|
const getTimewindowType = (timewindow: Timewindow): TimewindowType => {
 | 
						|
  if (isUndefined(timewindow.selectedTab)) {
 | 
						|
    return isDefined(timewindow.realtime) ? TimewindowType.REALTIME : TimewindowType.HISTORY;
 | 
						|
  } else {
 | 
						|
    return timewindow.selectedTab;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
export const initModelFromDefaultTimewindow = (value: Timewindow, quickIntervalOnly: boolean,
 | 
						|
                                               historyOnly: boolean, timeService: TimeService, hasAggregation: boolean): Timewindow => {
 | 
						|
  const model = defaultTimewindow(timeService);
 | 
						|
  if (value) {
 | 
						|
    if (value.allowedAggTypes?.length) {
 | 
						|
      model.allowedAggTypes = value.allowedAggTypes;
 | 
						|
    }
 | 
						|
    if (value.hideAggregation) {
 | 
						|
      model.hideAggregation = value.hideAggregation;
 | 
						|
    }
 | 
						|
    if (value.hideAggInterval) {
 | 
						|
      model.hideAggInterval = value.hideAggInterval;
 | 
						|
    }
 | 
						|
    if (value.hideTimezone) {
 | 
						|
      model.hideTimezone = value.hideTimezone;
 | 
						|
    }
 | 
						|
 | 
						|
    model.selectedTab = getTimewindowType(value);
 | 
						|
 | 
						|
    // for backward compatibility
 | 
						|
    if ((value as any).hideInterval) {
 | 
						|
      model.realtime.hideInterval = (value as any).hideInterval;
 | 
						|
      model.history.hideInterval = (value as any).hideInterval;
 | 
						|
      delete (value as any).hideInterval;
 | 
						|
    }
 | 
						|
    if ((value as any).hideLastInterval) {
 | 
						|
      model.realtime.hideLastInterval = (value as any).hideLastInterval;
 | 
						|
      delete (value as any).hideLastInterval;
 | 
						|
    }
 | 
						|
    if ((value as any).hideQuickInterval) {
 | 
						|
      model.realtime.hideQuickInterval = (value as any).hideQuickInterval;
 | 
						|
      delete (value as any).hideQuickInterval;
 | 
						|
    }
 | 
						|
 | 
						|
    if (isDefined(value.realtime)) {
 | 
						|
      if (value.realtime.hideInterval) {
 | 
						|
        model.realtime.hideInterval = value.realtime.hideInterval;
 | 
						|
      }
 | 
						|
      if (value.realtime.hideLastInterval) {
 | 
						|
        model.realtime.hideLastInterval = value.realtime.hideLastInterval;
 | 
						|
      }
 | 
						|
      if (value.realtime.hideQuickInterval) {
 | 
						|
        model.realtime.hideQuickInterval = value.realtime.hideQuickInterval;
 | 
						|
      }
 | 
						|
      if (value.realtime.disableCustomInterval) {
 | 
						|
        model.realtime.disableCustomInterval = value.realtime.disableCustomInterval;
 | 
						|
      }
 | 
						|
      if (value.realtime.disableCustomGroupInterval) {
 | 
						|
        model.realtime.disableCustomGroupInterval = value.realtime.disableCustomGroupInterval;
 | 
						|
      }
 | 
						|
 | 
						|
      if (isDefined(value.realtime.interval)) {
 | 
						|
        model.realtime.interval = value.realtime.interval;
 | 
						|
      }
 | 
						|
      if (isUndefined(value.realtime.realtimeType)) {
 | 
						|
        if (isDefined(value.realtime.quickInterval)) {
 | 
						|
          model.realtime.realtimeType = RealtimeWindowType.INTERVAL;
 | 
						|
        } else {
 | 
						|
          model.realtime.realtimeType = RealtimeWindowType.LAST_INTERVAL;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        model.realtime.realtimeType = value.realtime.realtimeType;
 | 
						|
      }
 | 
						|
      if (isDefined(value.realtime.quickInterval)) {
 | 
						|
        model.realtime.quickInterval = value.realtime.quickInterval;
 | 
						|
      }
 | 
						|
      if (isDefined(value.realtime.timewindowMs)) {
 | 
						|
        model.realtime.timewindowMs = value.realtime.timewindowMs;
 | 
						|
      }
 | 
						|
 | 
						|
      if (value.realtime.advancedParams) {
 | 
						|
        model.realtime.advancedParams = value.realtime.advancedParams;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (isDefined(value.history)) {
 | 
						|
      if (value.history.hideInterval) {
 | 
						|
        model.history.hideInterval = value.history.hideInterval;
 | 
						|
      }
 | 
						|
      if (value.history.hideLastInterval) {
 | 
						|
        model.history.hideLastInterval = value.history.hideLastInterval;
 | 
						|
      }
 | 
						|
      if (value.history.hideFixedInterval) {
 | 
						|
        model.history.hideFixedInterval = value.history.hideFixedInterval;
 | 
						|
      }
 | 
						|
      if (value.history.hideQuickInterval) {
 | 
						|
        model.history.hideQuickInterval = value.history.hideQuickInterval;
 | 
						|
      }
 | 
						|
      if (value.history.disableCustomInterval) {
 | 
						|
        model.history.disableCustomInterval = value.history.disableCustomInterval;
 | 
						|
      }
 | 
						|
      if (value.history.disableCustomGroupInterval) {
 | 
						|
        model.history.disableCustomGroupInterval = value.history.disableCustomGroupInterval;
 | 
						|
      }
 | 
						|
 | 
						|
      if (isDefined(value.history.interval)) {
 | 
						|
        model.history.interval = value.history.interval;
 | 
						|
      }
 | 
						|
      if (isUndefined(value.history.historyType)) {
 | 
						|
        if (isDefined(value.history.timewindowMs)) {
 | 
						|
          model.history.historyType = HistoryWindowType.LAST_INTERVAL;
 | 
						|
        } else if (isDefined(value.history.quickInterval)) {
 | 
						|
          model.history.historyType = HistoryWindowType.INTERVAL;
 | 
						|
        } else {
 | 
						|
          model.history.historyType = HistoryWindowType.FIXED;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        model.history.historyType = value.history.historyType;
 | 
						|
      }
 | 
						|
      if (isDefined(value.history.timewindowMs)) {
 | 
						|
        model.history.timewindowMs = value.history.timewindowMs;
 | 
						|
      }
 | 
						|
      if (isDefined(value.history.quickInterval)) {
 | 
						|
        model.history.quickInterval = value.history.quickInterval;
 | 
						|
      }
 | 
						|
      if (isDefinedAndNotNull(value.history.fixedTimewindow)) {
 | 
						|
        if (isDefined(value.history.fixedTimewindow.startTimeMs)) {
 | 
						|
          model.history.fixedTimewindow.startTimeMs = value.history.fixedTimewindow.startTimeMs;
 | 
						|
        }
 | 
						|
        if (isDefined(value.history.fixedTimewindow.endTimeMs)) {
 | 
						|
          model.history.fixedTimewindow.endTimeMs = value.history.fixedTimewindow.endTimeMs;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (value.history.advancedParams) {
 | 
						|
        model.history.advancedParams = value.history.advancedParams;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (value.aggregation) {
 | 
						|
      if (value.aggregation.type) {
 | 
						|
        model.aggregation.type = value.aggregation.type;
 | 
						|
      }
 | 
						|
      model.aggregation.limit = value.aggregation.limit || Math.floor(timeService.getMaxDatapointsLimit() / 2);
 | 
						|
    }
 | 
						|
    if (value.timezone) {
 | 
						|
      model.timezone = value.timezone;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (quickIntervalOnly) {
 | 
						|
    model.realtime.realtimeType = RealtimeWindowType.INTERVAL;
 | 
						|
  }
 | 
						|
  if (historyOnly) {
 | 
						|
    model.selectedTab = TimewindowType.HISTORY;
 | 
						|
  }
 | 
						|
  return clearTimewindowConfig(model, quickIntervalOnly, historyOnly, hasAggregation);
 | 
						|
};
 | 
						|
 | 
						|
export const toHistoryTimewindow = (timewindow: Timewindow, startTimeMs: number, endTimeMs: number,
 | 
						|
                                    interval: Interval, timeService: TimeService): Timewindow => {
 | 
						|
  if (timewindow.history) {
 | 
						|
    interval = isDefined(interval) ? interval : timewindow.history.interval;
 | 
						|
  } else if (timewindow.realtime) {
 | 
						|
    interval = timewindow.realtime.interval;
 | 
						|
  }  else {
 | 
						|
    interval = 0;
 | 
						|
  }
 | 
						|
  let aggType: AggregationType;
 | 
						|
  let limit: number;
 | 
						|
  if (timewindow.aggregation) {
 | 
						|
    aggType = timewindow.aggregation.type || AggregationType.AVG;
 | 
						|
    limit = timewindow.aggregation.limit || timeService.getMaxDatapointsLimit();
 | 
						|
  } else {
 | 
						|
    aggType = AggregationType.AVG;
 | 
						|
    limit = timeService.getMaxDatapointsLimit();
 | 
						|
  }
 | 
						|
  const historyTimewindow: Timewindow = {
 | 
						|
    hideAggregation: timewindow.hideAggregation || false,
 | 
						|
    hideAggInterval: timewindow.hideAggInterval || false,
 | 
						|
    hideTimezone: timewindow.hideTimezone || false,
 | 
						|
    selectedTab: TimewindowType.HISTORY,
 | 
						|
    history: {
 | 
						|
      historyType: HistoryWindowType.FIXED,
 | 
						|
      fixedTimewindow: {
 | 
						|
        startTimeMs,
 | 
						|
        endTimeMs
 | 
						|
      },
 | 
						|
      interval: timeService.boundIntervalToTimewindow(endTimeMs - startTimeMs, interval, AggregationType.AVG),
 | 
						|
      hideInterval: timewindow.history?.hideInterval || false,
 | 
						|
      hideLastInterval: timewindow.history?.hideLastInterval || false,
 | 
						|
      hideQuickInterval: timewindow.history?.hideQuickInterval || false
 | 
						|
    },
 | 
						|
    aggregation: {
 | 
						|
      type: aggType,
 | 
						|
      limit
 | 
						|
    },
 | 
						|
    timezone: timewindow.timezone
 | 
						|
  };
 | 
						|
  if (timewindow.history?.disableCustomInterval) {
 | 
						|
    historyTimewindow.history.disableCustomInterval = timewindow.history.disableCustomInterval;
 | 
						|
  }
 | 
						|
  if (timewindow.history?.disableCustomGroupInterval) {
 | 
						|
    historyTimewindow.history.disableCustomGroupInterval = timewindow.history.disableCustomGroupInterval;
 | 
						|
  }
 | 
						|
  if (timewindow.history?.advancedParams) {
 | 
						|
    historyTimewindow.history.advancedParams = timewindow.history.advancedParams;
 | 
						|
  }
 | 
						|
  if (timewindow.allowedAggTypes?.length) {
 | 
						|
    historyTimewindow.allowedAggTypes = timewindow.allowedAggTypes;
 | 
						|
  }
 | 
						|
  return historyTimewindow;
 | 
						|
};
 | 
						|
 | 
						|
export const timewindowTypeChanged = (newTimewindow: Timewindow, oldTimewindow: Timewindow): boolean => {
 | 
						|
  if (!newTimewindow || !oldTimewindow) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  const newType = getTimewindowType(newTimewindow);
 | 
						|
  const oldType = getTimewindowType(oldTimewindow);
 | 
						|
  return newType !== oldType;
 | 
						|
};
 | 
						|
 | 
						|
export const updateFormValuesOnTimewindowTypeChange = (selectedTab: TimewindowType,
 | 
						|
                                                       quickIntervalOnly: boolean, timewindowForm: FormGroup,
 | 
						|
                                                       realtimeDisableCustomInterval: boolean, historyDisableCustomInterval: boolean,
 | 
						|
                                                       realtimeAdvancedParams?: TimewindowAdvancedParams,
 | 
						|
                                                       historyAdvancedParams?: TimewindowAdvancedParams) => {
 | 
						|
  const timewindowFormValue = timewindowForm.getRawValue();
 | 
						|
  if (selectedTab === TimewindowType.REALTIME) {
 | 
						|
    if (timewindowFormValue.history.historyType !== HistoryWindowType.FIXED
 | 
						|
      && !(quickIntervalOnly && timewindowFormValue.history.historyType === HistoryWindowType.LAST_INTERVAL)) {
 | 
						|
      if (Object.keys(RealtimeWindowType).includes(HistoryWindowType[timewindowFormValue.history.historyType])) {
 | 
						|
        timewindowForm.get('realtime.realtimeType').patchValue(RealtimeWindowType[HistoryWindowType[timewindowFormValue.history.historyType]]);
 | 
						|
      }
 | 
						|
      if (!realtimeDisableCustomInterval ||
 | 
						|
          !realtimeAdvancedParams?.allowedLastIntervals?.length || realtimeAdvancedParams.allowedLastIntervals.includes(timewindowFormValue.history.timewindowMs)) {
 | 
						|
        timewindowForm.get('realtime.timewindowMs').patchValue(timewindowFormValue.history.timewindowMs);
 | 
						|
      }
 | 
						|
      if (realtimeAdvancedParams?.allowedQuickIntervals?.includes(timewindowFormValue.history.quickInterval) ||
 | 
						|
        (!realtimeAdvancedParams?.allowedQuickIntervals?.length && timewindowFormValue.history.quickInterval.startsWith('CURRENT'))) {
 | 
						|
        timewindowForm.get('realtime.quickInterval').patchValue(timewindowFormValue.history.quickInterval);
 | 
						|
      }
 | 
						|
      const defaultAggInterval = realtimeDefaultAggInterval(timewindowForm.getRawValue(), realtimeAdvancedParams);
 | 
						|
      const allowedAggIntervals = realtimeAllowedAggIntervals(timewindowForm.getRawValue(), realtimeAdvancedParams);
 | 
						|
      if (defaultAggInterval || !allowedAggIntervals.length || allowedAggIntervals.includes(timewindowFormValue.history.interval)) {
 | 
						|
        setTimeout(() => timewindowForm.get('realtime.interval').patchValue(
 | 
						|
          defaultAggInterval ?? timewindowFormValue.history.interval
 | 
						|
        ));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    timewindowForm.get('history.historyType').patchValue(HistoryWindowType[RealtimeWindowType[timewindowFormValue.realtime.realtimeType]]);
 | 
						|
    if (!historyDisableCustomInterval ||
 | 
						|
        !historyAdvancedParams?.allowedLastIntervals?.length || historyAdvancedParams.allowedLastIntervals?.includes(timewindowFormValue.realtime.timewindowMs)) {
 | 
						|
      timewindowForm.get('history.timewindowMs').patchValue(timewindowFormValue.realtime.timewindowMs);
 | 
						|
    }
 | 
						|
    if (!historyAdvancedParams?.allowedQuickIntervals?.length || historyAdvancedParams.allowedQuickIntervals?.includes(timewindowFormValue.realtime.quickInterval)) {
 | 
						|
      timewindowForm.get('history.quickInterval').patchValue(timewindowFormValue.realtime.quickInterval);
 | 
						|
    }
 | 
						|
    const defaultAggInterval = historyDefaultAggInterval(timewindowForm.getRawValue(), historyAdvancedParams);
 | 
						|
    const allowedAggIntervals = historyAllowedAggIntervals(timewindowForm.getRawValue(), historyAdvancedParams);
 | 
						|
    if (defaultAggInterval || !allowedAggIntervals.length || allowedAggIntervals.includes(timewindowFormValue.realtime.interval)) {
 | 
						|
      setTimeout(() => timewindowForm.get('history.interval').patchValue(
 | 
						|
        defaultAggInterval ?? timewindowFormValue.realtime.interval
 | 
						|
      ));
 | 
						|
    }
 | 
						|
  }
 | 
						|
  timewindowForm.patchValue({
 | 
						|
    aggregation: {
 | 
						|
      type: timewindowFormValue.aggregation.type,
 | 
						|
      limit: timewindowFormValue.aggregation.limit
 | 
						|
    },
 | 
						|
    timezone: timewindowFormValue.timezone
 | 
						|
  });
 | 
						|
};
 | 
						|
 | 
						|
export const currentRealtimeTimewindow = (timewindow: Timewindow): number => {
 | 
						|
  switch (timewindow.realtime.realtimeType) {
 | 
						|
    case RealtimeWindowType.LAST_INTERVAL:
 | 
						|
      return timewindow.realtime.timewindowMs;
 | 
						|
    case RealtimeWindowType.INTERVAL:
 | 
						|
      return quickTimeIntervalPeriod(timewindow.realtime.quickInterval);
 | 
						|
    default:
 | 
						|
      return DAY;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
export const currentHistoryTimewindow = (timewindow: Timewindow): number => {
 | 
						|
  if (timewindow.history.historyType === HistoryWindowType.LAST_INTERVAL) {
 | 
						|
    return timewindow.history.timewindowMs;
 | 
						|
  } else if (timewindow.history.historyType === HistoryWindowType.INTERVAL) {
 | 
						|
    return quickTimeIntervalPeriod(timewindow.history.quickInterval);
 | 
						|
  } else if (timewindow.history.fixedTimewindow) {
 | 
						|
    return timewindow.history.fixedTimewindow.endTimeMs -
 | 
						|
      timewindow.history.fixedTimewindow.startTimeMs;
 | 
						|
  } else {
 | 
						|
    return DAY;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
export const realtimeAllowedAggIntervals = (timewindow: Timewindow,
 | 
						|
                                            advancedParams: TimewindowAdvancedParams): Array<Interval> => {
 | 
						|
  if (timewindow.realtime.realtimeType === RealtimeWindowType.LAST_INTERVAL &&
 | 
						|
    advancedParams?.lastAggIntervalsConfig?.hasOwnProperty(timewindow.realtime.timewindowMs) &&
 | 
						|
    advancedParams.lastAggIntervalsConfig[timewindow.realtime.timewindowMs].aggIntervals?.length) {
 | 
						|
    return advancedParams.lastAggIntervalsConfig[timewindow.realtime.timewindowMs].aggIntervals;
 | 
						|
  } else if (timewindow.realtime.realtimeType === RealtimeWindowType.INTERVAL &&
 | 
						|
    advancedParams?.quickAggIntervalsConfig?.hasOwnProperty(timewindow.realtime.quickInterval) &&
 | 
						|
    advancedParams.quickAggIntervalsConfig[timewindow.realtime.quickInterval].aggIntervals?.length) {
 | 
						|
    return advancedParams.quickAggIntervalsConfig[timewindow.realtime.quickInterval].aggIntervals;
 | 
						|
  }
 | 
						|
  return [];
 | 
						|
};
 | 
						|
 | 
						|
export const historyAllowedAggIntervals = (timewindow: Timewindow,
 | 
						|
                                            advancedParams: TimewindowAdvancedParams): Array<Interval> => {
 | 
						|
  if (timewindow.history.historyType === HistoryWindowType.LAST_INTERVAL &&
 | 
						|
    advancedParams?.lastAggIntervalsConfig?.hasOwnProperty(timewindow.history.timewindowMs) &&
 | 
						|
    advancedParams.lastAggIntervalsConfig[timewindow.history.timewindowMs].aggIntervals?.length) {
 | 
						|
    return advancedParams.lastAggIntervalsConfig[timewindow.history.timewindowMs].aggIntervals;
 | 
						|
  } else if (timewindow.history.historyType === HistoryWindowType.INTERVAL &&
 | 
						|
    advancedParams?.quickAggIntervalsConfig?.hasOwnProperty(timewindow.history.quickInterval) &&
 | 
						|
    advancedParams.quickAggIntervalsConfig[timewindow.history.quickInterval].aggIntervals?.length) {
 | 
						|
    return advancedParams.quickAggIntervalsConfig[timewindow.history.quickInterval].aggIntervals;
 | 
						|
  }
 | 
						|
  return [];
 | 
						|
};
 | 
						|
 | 
						|
export const realtimeDefaultAggInterval = (timewindow: Timewindow,
 | 
						|
                                            advancedParams: TimewindowAdvancedParams): Interval => {
 | 
						|
  if (timewindow.realtime.realtimeType === RealtimeWindowType.LAST_INTERVAL &&
 | 
						|
    advancedParams?.lastAggIntervalsConfig?.hasOwnProperty(timewindow.realtime.timewindowMs) &&
 | 
						|
    advancedParams.lastAggIntervalsConfig[timewindow.realtime.timewindowMs].defaultAggInterval) {
 | 
						|
    return advancedParams.lastAggIntervalsConfig[timewindow.realtime.timewindowMs].defaultAggInterval;
 | 
						|
  } else if (timewindow.realtime.realtimeType === RealtimeWindowType.INTERVAL &&
 | 
						|
    advancedParams?.quickAggIntervalsConfig?.hasOwnProperty(timewindow.realtime.quickInterval) &&
 | 
						|
    advancedParams.quickAggIntervalsConfig[timewindow.realtime.quickInterval].defaultAggInterval) {
 | 
						|
    return advancedParams.quickAggIntervalsConfig[timewindow.realtime.quickInterval].defaultAggInterval;
 | 
						|
  }
 | 
						|
  return null;
 | 
						|
};
 | 
						|
 | 
						|
export const historyDefaultAggInterval = (timewindow: Timewindow,
 | 
						|
                                            advancedParams: TimewindowAdvancedParams): Interval => {
 | 
						|
  if (timewindow.history.historyType === HistoryWindowType.LAST_INTERVAL &&
 | 
						|
    advancedParams?.lastAggIntervalsConfig?.hasOwnProperty(timewindow.history.timewindowMs) &&
 | 
						|
    advancedParams.lastAggIntervalsConfig[timewindow.history.timewindowMs].defaultAggInterval) {
 | 
						|
    return advancedParams.lastAggIntervalsConfig[timewindow.history.timewindowMs].defaultAggInterval;
 | 
						|
  } else if (timewindow.history.historyType === HistoryWindowType.INTERVAL &&
 | 
						|
    advancedParams?.quickAggIntervalsConfig?.hasOwnProperty(timewindow.history.quickInterval) &&
 | 
						|
    advancedParams.quickAggIntervalsConfig[timewindow.history.quickInterval].defaultAggInterval) {
 | 
						|
    return advancedParams.quickAggIntervalsConfig[timewindow.history.quickInterval].defaultAggInterval;
 | 
						|
  }
 | 
						|
  return null;
 | 
						|
};
 | 
						|
 | 
						|
export const getTimezone = (tz: string): moment_.Moment => moment.tz(tz);
 | 
						|
 | 
						|
export const calculateTsOffset = (timezone?: string): number => {
 | 
						|
  if (timezone) {
 | 
						|
    const tz = getTimezone(timezone);
 | 
						|
    const localOffset = moment().utcOffset();
 | 
						|
    return (tz.utcOffset() - localOffset) * 60 * 1000;
 | 
						|
  } else {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
export const isHistoryTypeTimewindow = (timewindow: Timewindow): boolean => getTimewindowType(timewindow) === TimewindowType.HISTORY;
 | 
						|
 | 
						|
export const getCurrentTime = (tz?: string): moment_.Moment => {
 | 
						|
  if (tz) {
 | 
						|
    return moment().tz(tz);
 | 
						|
  } else {
 | 
						|
    return moment();
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
const getSubscriptionRealtimeWindowFromTimeInterval = (interval: QuickTimeInterval, tz?: string): number => {
 | 
						|
  let currentDate;
 | 
						|
  switch (interval) {
 | 
						|
    case QuickTimeInterval.CURRENT_HOUR:
 | 
						|
      return HOUR;
 | 
						|
    case QuickTimeInterval.CURRENT_DAY:
 | 
						|
    case QuickTimeInterval.CURRENT_DAY_SO_FAR:
 | 
						|
      return DAY;
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_ISO:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_SO_FAR:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_ISO_SO_FAR:
 | 
						|
      return WEEK;
 | 
						|
    case QuickTimeInterval.CURRENT_MONTH:
 | 
						|
    case QuickTimeInterval.CURRENT_MONTH_SO_FAR:
 | 
						|
      currentDate = getCurrentTime(tz);
 | 
						|
      return currentDate.clone().endOf('month').add(1, 'milliseconds').diff(currentDate.clone().startOf('month'));
 | 
						|
    case QuickTimeInterval.CURRENT_QUARTER:
 | 
						|
    case QuickTimeInterval.CURRENT_QUARTER_SO_FAR:
 | 
						|
      currentDate = getCurrentTime(tz);
 | 
						|
      return currentDate.clone().endOf('quarter').add(1, 'milliseconds').diff(currentDate.clone().startOf('quarter'));
 | 
						|
    case QuickTimeInterval.CURRENT_HALF_YEAR:
 | 
						|
    case QuickTimeInterval.CURRENT_HALF_YEAR_SO_FAR:
 | 
						|
      currentDate = getCurrentTime(tz);
 | 
						|
      if (currentDate.get('quarter') < 3) {
 | 
						|
        return currentDate.clone().set('quarter', 2).endOf('quarter').add(1, 'milliseconds').diff(currentDate.clone().startOf('year'));
 | 
						|
      } else {
 | 
						|
        return currentDate.clone().endOf('year').add(1, 'milliseconds').diff(currentDate.clone().set('quarter', 3).startOf('quarter'));
 | 
						|
      }
 | 
						|
    case QuickTimeInterval.CURRENT_YEAR:
 | 
						|
    case QuickTimeInterval.CURRENT_YEAR_SO_FAR:
 | 
						|
      currentDate = getCurrentTime(tz);
 | 
						|
      return currentDate.clone().endOf('year').add(1, 'milliseconds').diff(currentDate.clone().startOf('year'));
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
export const calculateIntervalStartTime = (interval: QuickTimeInterval, currentDate: moment_.Moment): moment_.Moment => {
 | 
						|
  switch (interval) {
 | 
						|
    case QuickTimeInterval.YESTERDAY:
 | 
						|
      currentDate.subtract(1, 'days');
 | 
						|
      return currentDate.startOf('day');
 | 
						|
    case QuickTimeInterval.DAY_BEFORE_YESTERDAY:
 | 
						|
      currentDate.subtract(2, 'days');
 | 
						|
      return currentDate.startOf('day');
 | 
						|
    case QuickTimeInterval.THIS_DAY_LAST_WEEK:
 | 
						|
      currentDate.subtract(1, 'weeks');
 | 
						|
      return currentDate.startOf('day');
 | 
						|
    case QuickTimeInterval.PREVIOUS_WEEK:
 | 
						|
      currentDate.subtract(1, 'weeks');
 | 
						|
      return currentDate.startOf('week');
 | 
						|
    case QuickTimeInterval.PREVIOUS_WEEK_ISO:
 | 
						|
      currentDate.subtract(1, 'weeks');
 | 
						|
      return currentDate.startOf('isoWeek');
 | 
						|
    case QuickTimeInterval.PREVIOUS_MONTH:
 | 
						|
      currentDate.subtract(1, 'months');
 | 
						|
      return currentDate.startOf('month');
 | 
						|
    case QuickTimeInterval.PREVIOUS_QUARTER:
 | 
						|
      currentDate.subtract(1, 'quarter');
 | 
						|
      return currentDate.startOf('quarter');
 | 
						|
    case QuickTimeInterval.PREVIOUS_HALF_YEAR:
 | 
						|
      if (currentDate.get('quarter') < 3) {
 | 
						|
        return currentDate.startOf('year').subtract(2, 'quarters');
 | 
						|
      } else {
 | 
						|
        return currentDate.startOf('year');
 | 
						|
      }
 | 
						|
    case QuickTimeInterval.PREVIOUS_YEAR:
 | 
						|
      currentDate.subtract(1, 'years');
 | 
						|
      return currentDate.startOf('year');
 | 
						|
    case QuickTimeInterval.CURRENT_HOUR:
 | 
						|
      return currentDate.startOf('hour');
 | 
						|
    case QuickTimeInterval.CURRENT_DAY:
 | 
						|
    case QuickTimeInterval.CURRENT_DAY_SO_FAR:
 | 
						|
      return currentDate.startOf('day');
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_SO_FAR:
 | 
						|
      return currentDate.startOf('week');
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_ISO:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_ISO_SO_FAR:
 | 
						|
      return currentDate.startOf('isoWeek');
 | 
						|
    case QuickTimeInterval.CURRENT_MONTH:
 | 
						|
    case QuickTimeInterval.CURRENT_MONTH_SO_FAR:
 | 
						|
      return currentDate.startOf('month');
 | 
						|
    case QuickTimeInterval.CURRENT_QUARTER:
 | 
						|
    case QuickTimeInterval.CURRENT_QUARTER_SO_FAR:
 | 
						|
      return currentDate.startOf('quarter');
 | 
						|
    case QuickTimeInterval.CURRENT_HALF_YEAR:
 | 
						|
    case QuickTimeInterval.CURRENT_HALF_YEAR_SO_FAR:
 | 
						|
      if (currentDate.get('quarter') < 3) {
 | 
						|
        return currentDate.startOf('year');
 | 
						|
      } else {
 | 
						|
        return currentDate.clone().set('quarter', 3).startOf('quarter');
 | 
						|
      }
 | 
						|
    case QuickTimeInterval.CURRENT_YEAR:
 | 
						|
    case QuickTimeInterval.CURRENT_YEAR_SO_FAR:
 | 
						|
      return currentDate.startOf('year');
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
export const calculateIntervalEndTime = (interval: QuickTimeInterval, startDate: moment_.Moment, tz?: string): number => {
 | 
						|
  switch (interval) {
 | 
						|
    case QuickTimeInterval.YESTERDAY:
 | 
						|
    case QuickTimeInterval.DAY_BEFORE_YESTERDAY:
 | 
						|
    case QuickTimeInterval.THIS_DAY_LAST_WEEK:
 | 
						|
    case QuickTimeInterval.CURRENT_DAY:
 | 
						|
      return startDate.add(1, 'day').valueOf();
 | 
						|
    case QuickTimeInterval.PREVIOUS_WEEK:
 | 
						|
    case QuickTimeInterval.PREVIOUS_WEEK_ISO:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_ISO:
 | 
						|
      return startDate.add(1, 'week').valueOf();
 | 
						|
    case QuickTimeInterval.PREVIOUS_MONTH:
 | 
						|
    case QuickTimeInterval.CURRENT_MONTH:
 | 
						|
      return startDate.add(1, 'month').valueOf();
 | 
						|
    case QuickTimeInterval.PREVIOUS_QUARTER:
 | 
						|
    case QuickTimeInterval.CURRENT_QUARTER:
 | 
						|
      return startDate.add(1, 'quarter').valueOf();
 | 
						|
    case QuickTimeInterval.PREVIOUS_HALF_YEAR:
 | 
						|
    case QuickTimeInterval.CURRENT_HALF_YEAR:
 | 
						|
      return startDate.add(2, 'quarters').valueOf();
 | 
						|
    case QuickTimeInterval.PREVIOUS_YEAR:
 | 
						|
    case QuickTimeInterval.CURRENT_YEAR:
 | 
						|
      return startDate.add(1, 'year').valueOf();
 | 
						|
    case QuickTimeInterval.CURRENT_HOUR:
 | 
						|
      return startDate.add(1, 'hour').valueOf();
 | 
						|
    case QuickTimeInterval.CURRENT_DAY_SO_FAR:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_SO_FAR:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_ISO_SO_FAR:
 | 
						|
    case QuickTimeInterval.CURRENT_MONTH_SO_FAR:
 | 
						|
    case QuickTimeInterval.CURRENT_QUARTER_SO_FAR:
 | 
						|
    case QuickTimeInterval.CURRENT_HALF_YEAR_SO_FAR:
 | 
						|
    case QuickTimeInterval.CURRENT_YEAR_SO_FAR:
 | 
						|
      return getCurrentTime(tz).valueOf();
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
export const calculateIntervalStartEndTime = (interval: QuickTimeInterval, tz?: string): [number, number] => {
 | 
						|
  const startEndTs: [number, number] = [0, 0];
 | 
						|
  const currentDate = getCurrentTime(tz);
 | 
						|
  const startDate = calculateIntervalStartTime(interval, currentDate);
 | 
						|
  startEndTs[0] = startDate.valueOf();
 | 
						|
  const endDate = calculateIntervalEndTime(interval, startDate, tz);
 | 
						|
  startEndTs[1] = endDate.valueOf();
 | 
						|
  return startEndTs;
 | 
						|
};
 | 
						|
 | 
						|
export const createSubscriptionTimewindow = (timewindow: Timewindow, stDiff: number, stateData: boolean,
 | 
						|
                                             timeService: TimeService): SubscriptionTimewindow => {
 | 
						|
  const subscriptionTimewindow: SubscriptionTimewindow = {
 | 
						|
    fixedWindow: null,
 | 
						|
    realtimeWindowMs: null,
 | 
						|
    aggregation: {
 | 
						|
      interval: SECOND,
 | 
						|
      limit: timeService.getMaxDatapointsLimit(),
 | 
						|
      type: AggregationType.AVG
 | 
						|
    },
 | 
						|
    timezone: timewindow.timezone || getDefaultTimezone(),
 | 
						|
    tsOffset: calculateTsOffset(timewindow.timezone)
 | 
						|
  };
 | 
						|
  let aggTimewindow: number;
 | 
						|
  if (stateData) {
 | 
						|
    subscriptionTimewindow.aggregation.type = AggregationType.NONE;
 | 
						|
    subscriptionTimewindow.aggregation.stateData = true;
 | 
						|
  }
 | 
						|
  if (isDefined(timewindow.aggregation) && !stateData) {
 | 
						|
    subscriptionTimewindow.aggregation = {
 | 
						|
      type: timewindow.aggregation.type || AggregationType.AVG,
 | 
						|
      limit: timewindow.aggregation.limit || timeService.getMaxDatapointsLimit()
 | 
						|
    };
 | 
						|
  }
 | 
						|
  const selectedTab = getTimewindowType(timewindow);
 | 
						|
  if (selectedTab === TimewindowType.REALTIME) {
 | 
						|
    let realtimeType = timewindow.realtime.realtimeType;
 | 
						|
    if (isUndefined(realtimeType)) {
 | 
						|
      if (isDefined(timewindow.realtime.quickInterval)) {
 | 
						|
        realtimeType = RealtimeWindowType.INTERVAL;
 | 
						|
      } else {
 | 
						|
        realtimeType = RealtimeWindowType.LAST_INTERVAL;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (realtimeType === RealtimeWindowType.INTERVAL) {
 | 
						|
      subscriptionTimewindow.realtimeWindowMs =
 | 
						|
        getSubscriptionRealtimeWindowFromTimeInterval(timewindow.realtime.quickInterval, timewindow.timezone);
 | 
						|
      subscriptionTimewindow.quickInterval = timewindow.realtime.quickInterval;
 | 
						|
      const currentDate = getCurrentTime(timewindow.timezone);
 | 
						|
      subscriptionTimewindow.startTs = calculateIntervalStartTime(timewindow.realtime.quickInterval, currentDate).valueOf();
 | 
						|
    } else {
 | 
						|
      subscriptionTimewindow.realtimeWindowMs = timewindow.realtime.timewindowMs;
 | 
						|
      const currentDate = getCurrentTime(timewindow.timezone);
 | 
						|
      subscriptionTimewindow.startTs = currentDate.valueOf() + stDiff - subscriptionTimewindow.realtimeWindowMs;
 | 
						|
    }
 | 
						|
    subscriptionTimewindow.aggregation.interval =
 | 
						|
      subscriptionTimewindow.aggregation.type === AggregationType.NONE
 | 
						|
      ? SECOND
 | 
						|
      : (!!timewindow.realtime.interval ? timewindow.realtime.interval :
 | 
						|
          timeService.boundIntervalToTimewindow(subscriptionTimewindow.realtimeWindowMs, timewindow.realtime.interval,
 | 
						|
              subscriptionTimewindow.aggregation.type));
 | 
						|
 | 
						|
    aggTimewindow = subscriptionTimewindow.realtimeWindowMs;
 | 
						|
  } else {
 | 
						|
    let historyType = timewindow.history.historyType;
 | 
						|
    if (isUndefined(historyType)) {
 | 
						|
      if (isDefined(timewindow.history.timewindowMs)) {
 | 
						|
        historyType = HistoryWindowType.LAST_INTERVAL;
 | 
						|
      } else if (isDefined(timewindow.history.quickInterval)) {
 | 
						|
        historyType = HistoryWindowType.INTERVAL;
 | 
						|
      } else {
 | 
						|
        historyType = HistoryWindowType.FIXED;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (historyType === HistoryWindowType.LAST_INTERVAL) {
 | 
						|
      const currentDate = getCurrentTime(timewindow.timezone);
 | 
						|
      const currentTime = currentDate.valueOf();
 | 
						|
      subscriptionTimewindow.fixedWindow = {
 | 
						|
        startTimeMs: currentTime - timewindow.history.timewindowMs,
 | 
						|
        endTimeMs: currentTime
 | 
						|
      };
 | 
						|
      aggTimewindow = timewindow.history.timewindowMs;
 | 
						|
    } else if (historyType === HistoryWindowType.INTERVAL) {
 | 
						|
      const startEndTime = calculateIntervalStartEndTime(timewindow.history.quickInterval, timewindow.timezone);
 | 
						|
      subscriptionTimewindow.fixedWindow = {
 | 
						|
        startTimeMs: startEndTime[0],
 | 
						|
        endTimeMs: startEndTime[1]
 | 
						|
      };
 | 
						|
      aggTimewindow = subscriptionTimewindow.fixedWindow.endTimeMs - subscriptionTimewindow.fixedWindow.startTimeMs;
 | 
						|
      subscriptionTimewindow.quickInterval = timewindow.history.quickInterval;
 | 
						|
    } else {
 | 
						|
      subscriptionTimewindow.fixedWindow = {
 | 
						|
        startTimeMs: timewindow.history.fixedTimewindow.startTimeMs - subscriptionTimewindow.tsOffset,
 | 
						|
        endTimeMs: timewindow.history.fixedTimewindow.endTimeMs - subscriptionTimewindow.tsOffset
 | 
						|
      };
 | 
						|
      aggTimewindow = subscriptionTimewindow.fixedWindow.endTimeMs - subscriptionTimewindow.fixedWindow.startTimeMs;
 | 
						|
    }
 | 
						|
    subscriptionTimewindow.startTs = subscriptionTimewindow.fixedWindow.startTimeMs;
 | 
						|
    subscriptionTimewindow.aggregation.interval =
 | 
						|
      subscriptionTimewindow.aggregation.type === AggregationType.NONE
 | 
						|
      ? SECOND
 | 
						|
      : (!!timewindow.history.interval ? timewindow.history.interval :
 | 
						|
          timeService.boundIntervalToTimewindow(aggTimewindow, timewindow.history.interval,
 | 
						|
            subscriptionTimewindow.aggregation.type));
 | 
						|
  }
 | 
						|
  const aggregation = subscriptionTimewindow.aggregation;
 | 
						|
  aggregation.timeWindow = aggTimewindow;
 | 
						|
  if (aggregation.type !== AggregationType.NONE) {
 | 
						|
    aggregation.limit = calculateIntervalsCount(subscriptionTimewindow.startTs, aggTimewindow,
 | 
						|
      subscriptionTimewindow.aggregation.interval, timewindow.timezone);
 | 
						|
  }
 | 
						|
  return subscriptionTimewindow;
 | 
						|
};
 | 
						|
 | 
						|
export const quickTimeIntervalPeriod = (interval: QuickTimeInterval): number => {
 | 
						|
  switch (interval) {
 | 
						|
    case QuickTimeInterval.CURRENT_HOUR:
 | 
						|
      return HOUR;
 | 
						|
    case QuickTimeInterval.YESTERDAY:
 | 
						|
    case QuickTimeInterval.DAY_BEFORE_YESTERDAY:
 | 
						|
    case QuickTimeInterval.THIS_DAY_LAST_WEEK:
 | 
						|
    case QuickTimeInterval.CURRENT_DAY:
 | 
						|
    case QuickTimeInterval.CURRENT_DAY_SO_FAR:
 | 
						|
      return DAY;
 | 
						|
    case QuickTimeInterval.PREVIOUS_WEEK:
 | 
						|
    case QuickTimeInterval.PREVIOUS_WEEK_ISO:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_ISO:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_SO_FAR:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_ISO_SO_FAR:
 | 
						|
      return WEEK;
 | 
						|
    case QuickTimeInterval.PREVIOUS_MONTH:
 | 
						|
    case QuickTimeInterval.CURRENT_MONTH:
 | 
						|
    case QuickTimeInterval.CURRENT_MONTH_SO_FAR:
 | 
						|
      return DAY * 30;
 | 
						|
    case QuickTimeInterval.PREVIOUS_QUARTER:
 | 
						|
    case QuickTimeInterval.CURRENT_QUARTER:
 | 
						|
    case QuickTimeInterval.CURRENT_QUARTER_SO_FAR:
 | 
						|
      return DAY * 30 * 3;
 | 
						|
    case QuickTimeInterval.PREVIOUS_HALF_YEAR:
 | 
						|
    case QuickTimeInterval.CURRENT_HALF_YEAR:
 | 
						|
    case QuickTimeInterval.CURRENT_HALF_YEAR_SO_FAR:
 | 
						|
      return DAY * 30 * 6;
 | 
						|
    case QuickTimeInterval.PREVIOUS_YEAR:
 | 
						|
    case QuickTimeInterval.CURRENT_YEAR:
 | 
						|
    case QuickTimeInterval.CURRENT_YEAR_SO_FAR:
 | 
						|
      return YEAR;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
export const calculateIntervalComparisonStartTime = (interval: QuickTimeInterval,
 | 
						|
                                                     startDate: moment_.Moment): moment_.Moment => {
 | 
						|
  switch (interval) {
 | 
						|
    case QuickTimeInterval.YESTERDAY:
 | 
						|
    case QuickTimeInterval.DAY_BEFORE_YESTERDAY:
 | 
						|
    case QuickTimeInterval.CURRENT_DAY:
 | 
						|
    case QuickTimeInterval.CURRENT_DAY_SO_FAR:
 | 
						|
      startDate.subtract(1, 'days');
 | 
						|
      return startDate.startOf('day');
 | 
						|
    case QuickTimeInterval.THIS_DAY_LAST_WEEK:
 | 
						|
      startDate.subtract(1, 'weeks');
 | 
						|
      return startDate.startOf('day');
 | 
						|
    case QuickTimeInterval.PREVIOUS_WEEK:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_SO_FAR:
 | 
						|
      startDate.subtract(1, 'weeks');
 | 
						|
      return startDate.startOf('week');
 | 
						|
    case QuickTimeInterval.PREVIOUS_WEEK_ISO:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_ISO:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_ISO_SO_FAR:
 | 
						|
      startDate.subtract(1, 'weeks');
 | 
						|
      return startDate.startOf('isoWeek');
 | 
						|
    case QuickTimeInterval.PREVIOUS_MONTH:
 | 
						|
    case QuickTimeInterval.CURRENT_MONTH:
 | 
						|
    case QuickTimeInterval.CURRENT_MONTH_SO_FAR:
 | 
						|
      startDate.subtract(1, 'months');
 | 
						|
      return startDate.startOf('month');
 | 
						|
    case QuickTimeInterval.PREVIOUS_QUARTER:
 | 
						|
    case QuickTimeInterval.CURRENT_QUARTER:
 | 
						|
    case QuickTimeInterval.CURRENT_QUARTER_SO_FAR:
 | 
						|
      startDate.subtract(1, 'quarters');
 | 
						|
      return startDate.startOf('quarter');
 | 
						|
    case QuickTimeInterval.PREVIOUS_HALF_YEAR:
 | 
						|
    case QuickTimeInterval.CURRENT_HALF_YEAR:
 | 
						|
    case QuickTimeInterval.CURRENT_HALF_YEAR_SO_FAR:
 | 
						|
      startDate.subtract(2, 'quarters');
 | 
						|
      if (startDate.get('quarter') < 3) {
 | 
						|
        return startDate.startOf('year');
 | 
						|
      } else {
 | 
						|
        return startDate.clone().set('quarter', 3).startOf('quarter');
 | 
						|
      }
 | 
						|
    case QuickTimeInterval.PREVIOUS_YEAR:
 | 
						|
    case QuickTimeInterval.CURRENT_YEAR:
 | 
						|
    case QuickTimeInterval.CURRENT_YEAR_SO_FAR:
 | 
						|
      startDate.subtract(1, 'years');
 | 
						|
      return startDate.startOf('year');
 | 
						|
    case QuickTimeInterval.CURRENT_HOUR:
 | 
						|
      startDate.subtract(1, 'hour');
 | 
						|
      return startDate.startOf('hour');
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
export const calculateIntervalComparisonEndTime = (interval: QuickTimeInterval,
 | 
						|
                                                   comparisonStartDate: moment_.Moment,
 | 
						|
                                                   endDate: moment_.Moment): number => {
 | 
						|
  switch (interval) {
 | 
						|
    case QuickTimeInterval.CURRENT_DAY_SO_FAR:
 | 
						|
      return endDate.subtract(1, 'days').valueOf();
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_SO_FAR:
 | 
						|
    case QuickTimeInterval.CURRENT_WEEK_ISO_SO_FAR:
 | 
						|
      return endDate.subtract(1, 'week').valueOf();
 | 
						|
    case QuickTimeInterval.CURRENT_MONTH_SO_FAR:
 | 
						|
      return endDate.subtract(1, 'month').valueOf();
 | 
						|
    case QuickTimeInterval.CURRENT_QUARTER_SO_FAR:
 | 
						|
      return endDate.subtract(1, 'quarter').valueOf();
 | 
						|
    case QuickTimeInterval.CURRENT_HALF_YEAR_SO_FAR:
 | 
						|
      return endDate.subtract(2, 'quarters').valueOf();
 | 
						|
    case QuickTimeInterval.CURRENT_YEAR_SO_FAR:
 | 
						|
      return endDate.subtract(1, 'year').valueOf();
 | 
						|
    default:
 | 
						|
      return calculateIntervalEndTime(interval, comparisonStartDate);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
export const createTimewindowForComparison = (subscriptionTimewindow: SubscriptionTimewindow,
 | 
						|
                                              timeUnit: ComparisonDuration, customIntervalValue: number): SubscriptionTimewindow => {
 | 
						|
  const timewindowForComparison: SubscriptionTimewindow = {
 | 
						|
    fixedWindow: null,
 | 
						|
    realtimeWindowMs: null,
 | 
						|
    aggregation: subscriptionTimewindow.aggregation,
 | 
						|
    tsOffset: subscriptionTimewindow.tsOffset,
 | 
						|
    timezone: subscriptionTimewindow.timezone
 | 
						|
  };
 | 
						|
 | 
						|
  if (subscriptionTimewindow.fixedWindow) {
 | 
						|
    let startTimeMs: number;
 | 
						|
    let endTimeMs: number;
 | 
						|
    if (timeUnit === 'previousInterval') {
 | 
						|
      if (subscriptionTimewindow.quickInterval) {
 | 
						|
        const startDate = moment(subscriptionTimewindow.fixedWindow.startTimeMs);
 | 
						|
        const endDate = moment(subscriptionTimewindow.fixedWindow.endTimeMs);
 | 
						|
        if (subscriptionTimewindow.timezone) {
 | 
						|
          startDate.tz(subscriptionTimewindow.timezone);
 | 
						|
          endDate.tz(subscriptionTimewindow.timezone);
 | 
						|
        }
 | 
						|
        const comparisonStartDate = calculateIntervalComparisonStartTime(subscriptionTimewindow.quickInterval, startDate);
 | 
						|
        startTimeMs = comparisonStartDate.valueOf();
 | 
						|
        endTimeMs = calculateIntervalComparisonEndTime(subscriptionTimewindow.quickInterval, comparisonStartDate, endDate);
 | 
						|
      } else {
 | 
						|
        const timeInterval = subscriptionTimewindow.fixedWindow.endTimeMs - subscriptionTimewindow.fixedWindow.startTimeMs;
 | 
						|
        endTimeMs = subscriptionTimewindow.fixedWindow.startTimeMs;
 | 
						|
        startTimeMs = endTimeMs - timeInterval;
 | 
						|
      }
 | 
						|
    } else if (timeUnit === 'customInterval') {
 | 
						|
      if (isNumeric(customIntervalValue) && isFinite(customIntervalValue) && customIntervalValue > 0) {
 | 
						|
        const timeInterval = subscriptionTimewindow.fixedWindow.endTimeMs - subscriptionTimewindow.fixedWindow.startTimeMs;
 | 
						|
        endTimeMs = subscriptionTimewindow.fixedWindow.endTimeMs - Math.round(customIntervalValue);
 | 
						|
        startTimeMs = endTimeMs - timeInterval;
 | 
						|
      } else {
 | 
						|
        endTimeMs = subscriptionTimewindow.fixedWindow.endTimeMs;
 | 
						|
        startTimeMs = subscriptionTimewindow.fixedWindow.startTimeMs;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      const timeInterval = subscriptionTimewindow.fixedWindow.endTimeMs - subscriptionTimewindow.fixedWindow.startTimeMs;
 | 
						|
      endTimeMs = moment(subscriptionTimewindow.fixedWindow.endTimeMs).subtract(1, timeUnit).valueOf();
 | 
						|
      startTimeMs = endTimeMs - timeInterval;
 | 
						|
    }
 | 
						|
    timewindowForComparison.startTs = startTimeMs;
 | 
						|
    timewindowForComparison.fixedWindow = {
 | 
						|
      startTimeMs: timewindowForComparison.startTs,
 | 
						|
      endTimeMs
 | 
						|
    };
 | 
						|
  }
 | 
						|
 | 
						|
  return timewindowForComparison;
 | 
						|
};
 | 
						|
 | 
						|
export const cloneSelectedTimewindow = (timewindow: Timewindow): Timewindow => {
 | 
						|
  const cloned: Timewindow = {};
 | 
						|
  if (timewindow.allowedAggTypes?.length) {
 | 
						|
    cloned.allowedAggTypes = timewindow.allowedAggTypes;
 | 
						|
  }
 | 
						|
  if (timewindow.hideAggregation) {
 | 
						|
    cloned.hideAggregation = timewindow.hideAggregation;
 | 
						|
  }
 | 
						|
  if (timewindow.hideAggInterval) {
 | 
						|
    cloned.hideAggInterval = timewindow.hideAggInterval;
 | 
						|
  }
 | 
						|
  if (timewindow.hideTimezone) {
 | 
						|
    cloned.hideTimezone = timewindow.hideTimezone;
 | 
						|
  }
 | 
						|
  if (isDefined(timewindow.selectedTab)) {
 | 
						|
    cloned.selectedTab = timewindow.selectedTab;
 | 
						|
  }
 | 
						|
  if (isDefined(timewindow.realtime)) {
 | 
						|
    cloned.realtime = deepClone(timewindow.realtime);
 | 
						|
  }
 | 
						|
  if (isDefined(timewindow.history)) {
 | 
						|
    cloned.history = deepClone(timewindow.history);
 | 
						|
  }
 | 
						|
  if (isDefined(timewindow.aggregation)) {
 | 
						|
    cloned.aggregation = deepClone(timewindow.aggregation);
 | 
						|
  }
 | 
						|
  if (timewindow.timezone) {
 | 
						|
    cloned.timezone = timewindow.timezone;
 | 
						|
  }
 | 
						|
  return cloned;
 | 
						|
};
 | 
						|
 | 
						|
export const clearTimewindowConfig = (timewindow: Timewindow, quickIntervalOnly: boolean,
 | 
						|
                                      historyOnly: boolean, hasAggregation: boolean, hasTimezone = true): Timewindow => {
 | 
						|
  if (timewindow.selectedTab === TimewindowType.REALTIME) {
 | 
						|
    if (quickIntervalOnly || timewindow.realtime.realtimeType === RealtimeWindowType.INTERVAL) {
 | 
						|
      delete timewindow.realtime.timewindowMs;
 | 
						|
    } else {
 | 
						|
      delete timewindow.realtime.quickInterval;
 | 
						|
    }
 | 
						|
 | 
						|
    delete timewindow.history?.historyType;
 | 
						|
    delete timewindow.history?.timewindowMs;
 | 
						|
    delete timewindow.history?.fixedTimewindow;
 | 
						|
    delete timewindow.history?.quickInterval;
 | 
						|
 | 
						|
    delete timewindow.history?.interval;
 | 
						|
    if (!hasAggregation) {
 | 
						|
      delete timewindow.realtime.interval;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    if (timewindow.history.historyType === HistoryWindowType.LAST_INTERVAL) {
 | 
						|
      delete timewindow.history.fixedTimewindow;
 | 
						|
      delete timewindow.history.quickInterval;
 | 
						|
    } else if (timewindow.history.historyType === HistoryWindowType.FIXED) {
 | 
						|
      delete timewindow.history.timewindowMs;
 | 
						|
      delete timewindow.history.quickInterval;
 | 
						|
    } else if (timewindow.history.historyType === HistoryWindowType.INTERVAL) {
 | 
						|
      delete timewindow.history.timewindowMs;
 | 
						|
      delete timewindow.history.fixedTimewindow;
 | 
						|
    } else {
 | 
						|
      delete timewindow.history.timewindowMs;
 | 
						|
      delete timewindow.history.fixedTimewindow;
 | 
						|
      delete timewindow.history.quickInterval;
 | 
						|
    }
 | 
						|
 | 
						|
    delete timewindow.realtime?.realtimeType;
 | 
						|
    delete timewindow.realtime?.timewindowMs;
 | 
						|
    delete timewindow.realtime?.quickInterval;
 | 
						|
 | 
						|
    delete timewindow.realtime?.interval;
 | 
						|
    if (!hasAggregation) {
 | 
						|
      delete timewindow.history.interval;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (!hasAggregation) {
 | 
						|
    delete timewindow.aggregation;
 | 
						|
  }
 | 
						|
 | 
						|
  if (historyOnly) {
 | 
						|
    delete timewindow.realtime;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!hasTimezone) {
 | 
						|
    delete timewindow.timezone;
 | 
						|
  }
 | 
						|
  return deepClean(timewindow);
 | 
						|
};
 | 
						|
 | 
						|
export interface TimeInterval {
 | 
						|
  name: string;
 | 
						|
  translateParams: {[key: string]: any};
 | 
						|
  value: Interval;
 | 
						|
}
 | 
						|
 | 
						|
export const defaultTimeIntervals = new Array<TimeInterval>(
 | 
						|
  {
 | 
						|
    name: 'timeinterval.seconds-interval',
 | 
						|
    translateParams: {seconds: 1},
 | 
						|
    value: SECOND
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.seconds-interval',
 | 
						|
    translateParams: {seconds: 5},
 | 
						|
    value: 5 * SECOND
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.seconds-interval',
 | 
						|
    translateParams: {seconds: 10},
 | 
						|
    value: 10 * SECOND
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.seconds-interval',
 | 
						|
    translateParams: {seconds: 15},
 | 
						|
    value: 15 * SECOND
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.seconds-interval',
 | 
						|
    translateParams: {seconds: 30},
 | 
						|
    value: 30 * SECOND
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.minutes-interval',
 | 
						|
    translateParams: {minutes: 1},
 | 
						|
    value: MINUTE
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.minutes-interval',
 | 
						|
    translateParams: {minutes: 2},
 | 
						|
    value: 2 * MINUTE
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.minutes-interval',
 | 
						|
    translateParams: {minutes: 5},
 | 
						|
    value: 5 * MINUTE
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.minutes-interval',
 | 
						|
    translateParams: {minutes: 10},
 | 
						|
    value: 10 * MINUTE
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.minutes-interval',
 | 
						|
    translateParams: {minutes: 15},
 | 
						|
    value: 15 * MINUTE
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.minutes-interval',
 | 
						|
    translateParams: {minutes: 30},
 | 
						|
    value: 30 * MINUTE
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.hours-interval',
 | 
						|
    translateParams: {hours: 1},
 | 
						|
    value: HOUR
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.hours-interval',
 | 
						|
    translateParams: {hours: 2},
 | 
						|
    value: 2 * HOUR
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.hours-interval',
 | 
						|
    translateParams: {hours: 5},
 | 
						|
    value: 5 * HOUR
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.hours-interval',
 | 
						|
    translateParams: {hours: 10},
 | 
						|
    value: 10 * HOUR
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.hours-interval',
 | 
						|
    translateParams: {hours: 12},
 | 
						|
    value: 12 * HOUR
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.days-interval',
 | 
						|
    translateParams: {days: 1},
 | 
						|
    value: DAY
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.days-interval',
 | 
						|
    translateParams: {days: 7},
 | 
						|
    value: 7 * DAY
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.type.week',
 | 
						|
    translateParams: {},
 | 
						|
    value: IntervalType.WEEK
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.type.week-iso',
 | 
						|
    translateParams: {},
 | 
						|
    value: IntervalType.WEEK_ISO
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.days-interval',
 | 
						|
    translateParams: {days: 30},
 | 
						|
    value: 30 * DAY
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.type.month',
 | 
						|
    translateParams: {},
 | 
						|
    value: IntervalType.MONTH
 | 
						|
  },
 | 
						|
  {
 | 
						|
    name: 'timeinterval.type.quarter',
 | 
						|
    translateParams: {},
 | 
						|
    value: IntervalType.QUARTER
 | 
						|
  }
 | 
						|
);
 | 
						|
 | 
						|
export const intervalValuesToTimeIntervals = (intervalValues: Array<Interval>): Array<TimeInterval> => {
 | 
						|
  return defaultTimeIntervals.filter(interval => intervalValues.includes(interval.value));
 | 
						|
}
 | 
						|
 | 
						|
export enum TimeUnit {
 | 
						|
  SECONDS = 'SECONDS',
 | 
						|
  MINUTES = 'MINUTES',
 | 
						|
  HOURS = 'HOURS',
 | 
						|
  DAYS = 'DAYS'
 | 
						|
}
 | 
						|
 | 
						|
export enum TimeUnitMilli {
 | 
						|
  MILLISECONDS = 'MILLISECONDS'
 | 
						|
}
 | 
						|
 | 
						|
export type FullTimeUnit = TimeUnit | TimeUnitMilli;
 | 
						|
 | 
						|
export const timeUnitTranslationMap = new Map<FullTimeUnit, string>(
 | 
						|
  [
 | 
						|
    [TimeUnitMilli.MILLISECONDS, 'timeunit.milliseconds'],
 | 
						|
    [TimeUnit.SECONDS, 'timeunit.seconds'],
 | 
						|
    [TimeUnit.MINUTES, 'timeunit.minutes'],
 | 
						|
    [TimeUnit.HOURS, 'timeunit.hours'],
 | 
						|
    [TimeUnit.DAYS, 'timeunit.days']
 | 
						|
  ]
 | 
						|
);
 | 
						|
 | 
						|
export interface TimezoneInfo {
 | 
						|
  id: string;
 | 
						|
  name: string;
 | 
						|
  offset: string;
 | 
						|
  nOffset: number;
 | 
						|
  abbr: string;
 | 
						|
}
 | 
						|
 | 
						|
let timezones: TimezoneInfo[] = null;
 | 
						|
let defaultTimezone: string = null;
 | 
						|
 | 
						|
export const getTimezones = (): TimezoneInfo[] => {
 | 
						|
  if (!timezones) {
 | 
						|
    timezones = momentTz.tz.names().map((zoneName) => {
 | 
						|
      const tz = momentTz.tz(zoneName);
 | 
						|
      return {
 | 
						|
        id: zoneName,
 | 
						|
        name: zoneName.replace(/_/g, ' '),
 | 
						|
        offset: `UTC${tz.format('Z')}`,
 | 
						|
        nOffset: tz.utcOffset(),
 | 
						|
        abbr: tz.zoneAbbr()
 | 
						|
      };
 | 
						|
    });
 | 
						|
  }
 | 
						|
  return timezones;
 | 
						|
};
 | 
						|
 | 
						|
export const getDefaultTimezone = (): string => {
 | 
						|
  if (!defaultTimezone) {
 | 
						|
    defaultTimezone = momentTz.tz.guess();
 | 
						|
  }
 | 
						|
  return defaultTimezone;
 | 
						|
};
 | 
						|
export const getTimezoneInfo = (timezoneId: string, defaultTimezoneId?: string, userTimezoneByDefault?: boolean): TimezoneInfo => {
 | 
						|
  const timezoneList = getTimezones();
 | 
						|
  let foundTimezone = timezoneId ? timezoneList.find(timezoneInfo => timezoneInfo.id === timezoneId) : null;
 | 
						|
  if (!foundTimezone) {
 | 
						|
    if (userTimezoneByDefault) {
 | 
						|
      const userTimezone = getDefaultTimezone();
 | 
						|
      foundTimezone = timezoneList.find(timezoneInfo => timezoneInfo.id === userTimezone);
 | 
						|
    } else if (defaultTimezoneId) {
 | 
						|
      foundTimezone = timezoneList.find(timezoneInfo => timezoneInfo.id === defaultTimezoneId);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return foundTimezone;
 | 
						|
};
 | 
						|
 | 
						|
export const getDefaultTimezoneInfo = (): TimezoneInfo => {
 | 
						|
  const userTimezone = getDefaultTimezone();
 | 
						|
  return getTimezoneInfo(userTimezone);
 | 
						|
};
 | 
						|
 | 
						|
export const getTime = (ts: number, tz?: string): moment_.Moment => {
 | 
						|
  if (tz) {
 | 
						|
    return moment(ts).tz(tz);
 | 
						|
  } else {
 | 
						|
    return moment(ts);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
export const calculateIntervalsCount = (startTs: number, timewindow: number, interval: Interval, tz?: string): number => {
 | 
						|
  if (typeof interval === 'number') {
 | 
						|
    return Math.ceil(timewindow / interval);
 | 
						|
  } else {
 | 
						|
    const current = getTime(startTs, tz);
 | 
						|
    const endDate = getTime(startTs + timewindow, tz);
 | 
						|
    let startInterval = startIntervalDate(current, interval);
 | 
						|
    let endInterval = endIntervalDate(current, interval);
 | 
						|
    let count = 0;
 | 
						|
    while (startInterval.isBefore(endDate)) {
 | 
						|
      count++;
 | 
						|
      endInterval.add(1, 'milliseconds');
 | 
						|
      startInterval = startIntervalDate(endInterval, interval);
 | 
						|
      endInterval = endIntervalDate(endInterval, interval);
 | 
						|
    }
 | 
						|
    return count;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
export const startIntervalDate = (current: moment_.Moment, interval: IntervalType): moment_.Moment => {
 | 
						|
  switch (interval) {
 | 
						|
    case IntervalType.WEEK:
 | 
						|
      return current.clone().startOf('week');
 | 
						|
    case IntervalType.WEEK_ISO:
 | 
						|
      return current.clone().startOf('isoWeek');
 | 
						|
    case IntervalType.MONTH:
 | 
						|
      return current.clone().startOf('month');
 | 
						|
    case IntervalType.QUARTER:
 | 
						|
      return current.clone().startOf('quarter');
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
export const endIntervalDate = (current: moment_.Moment, interval: IntervalType): moment_.Moment => {
 | 
						|
  switch (interval) {
 | 
						|
    case IntervalType.WEEK:
 | 
						|
      return current.clone().endOf('week');
 | 
						|
    case IntervalType.WEEK_ISO:
 | 
						|
      return current.clone().endOf('isoWeek');
 | 
						|
    case IntervalType.MONTH:
 | 
						|
      return current.clone().endOf('month');
 | 
						|
    case IntervalType.QUARTER:
 | 
						|
      return current.clone().endOf('quarter');
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
export const calculateAggIntervalWithSubscriptionTimeWindow
 | 
						|
  = (subsTw: SubscriptionTimewindow, endTs: number, timestamp: number, aggType?: AggregationType): [number, number] => {
 | 
						|
  if ((aggType || subsTw.aggregation.type) === AggregationType.NONE) {
 | 
						|
    return [timestamp, timestamp];
 | 
						|
  } else {
 | 
						|
    return calculateInterval(subsTw.startTs, endTs, subsTw.aggregation.interval, subsTw.tsOffset, subsTw.timezone, timestamp);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
export const calculateAggIntervalWithWidgetTimeWindow
 | 
						|
  = (widgetTimeWindow: WidgetTimewindow, timestamp: number): [number, number] =>
 | 
						|
  calculateInterval(widgetTimeWindow.minTime - widgetTimeWindow.tsOffset,
 | 
						|
    widgetTimeWindow.maxTime, widgetTimeWindow.interval, widgetTimeWindow.tsOffset, widgetTimeWindow.timezone, timestamp);
 | 
						|
 | 
						|
export const calculateInterval = (startTime: number, endTime: number,
 | 
						|
                                  interval: Interval, tsOffset: number, timezone: string, timestamp: number): [number, number] => {
 | 
						|
  let startIntervalTs: number;
 | 
						|
  let endIntervalTs: number;
 | 
						|
  if (typeof interval === 'number') {
 | 
						|
    const startTs = startTime + tsOffset;
 | 
						|
    startIntervalTs = startTs + Math.floor((timestamp - startTs) / interval) * interval;
 | 
						|
    endIntervalTs = startIntervalTs + interval;
 | 
						|
  } else {
 | 
						|
    const time = getTime(timestamp, timezone);
 | 
						|
    let startInterval = startIntervalDate(time, interval);
 | 
						|
    const start = getTime(startTime, timezone);
 | 
						|
    if (start.isAfter(startInterval)) {
 | 
						|
      startInterval = start;
 | 
						|
    }
 | 
						|
    const endInterval = endIntervalDate(time, interval).add(1, 'milliseconds');
 | 
						|
    startIntervalTs = startInterval.valueOf() + tsOffset;
 | 
						|
    endIntervalTs = endInterval.valueOf() + tsOffset;
 | 
						|
  }
 | 
						|
  endIntervalTs = Math.min(endIntervalTs, endTime);
 | 
						|
  return [startIntervalTs, endIntervalTs];
 | 
						|
};
 | 
						|
 | 
						|
export const getCurrentTimeForComparison = (timeForComparison: moment_.unitOfTime.DurationConstructor, tz?: string): moment_.Moment =>
 | 
						|
  getCurrentTime(tz).subtract(1, timeForComparison);
 | 
						|
 | 
						|
export const getTimePageLinkInterval = (timewindow: Timewindow): {startTime?: number; endTime?: number} => {
 | 
						|
  const interval: {startTime?: number; endTime?: number} = {};
 | 
						|
  switch (timewindow.history.historyType) {
 | 
						|
    case HistoryWindowType.LAST_INTERVAL:
 | 
						|
      const currentTime = Date.now();
 | 
						|
      interval.startTime = currentTime - timewindow.history.timewindowMs;
 | 
						|
      interval.endTime = currentTime;
 | 
						|
      break;
 | 
						|
    case HistoryWindowType.FIXED:
 | 
						|
      interval.startTime = timewindow.history.fixedTimewindow.startTimeMs;
 | 
						|
      interval.endTime = timewindow.history.fixedTimewindow.endTimeMs;
 | 
						|
      break;
 | 
						|
    case HistoryWindowType.INTERVAL:
 | 
						|
      const startEndTime = calculateIntervalStartEndTime(timewindow.history.quickInterval);
 | 
						|
      interval.startTime = startEndTime[0];
 | 
						|
      interval.endTime = startEndTime[1];
 | 
						|
      break;
 | 
						|
    case HistoryWindowType.FOR_ALL_TIME:
 | 
						|
      interval.startTime = null;
 | 
						|
      interval.endTime = null;
 | 
						|
      break;
 | 
						|
  }
 | 
						|
  return interval;
 | 
						|
}
 |