Commit b5444e6c2792ac2e483d4bc2d151679c61c65d5b
Merge branch 'vvlladd28-improvement/comparison-flot'
Showing
10 changed files
with
241 additions
and
115 deletions
@@ -16,14 +16,17 @@ | @@ -16,14 +16,17 @@ | ||
16 | 16 | ||
17 | import { SubscriptionData, SubscriptionDataHolder } from '@app/shared/models/telemetry/telemetry.models'; | 17 | import { SubscriptionData, SubscriptionDataHolder } from '@app/shared/models/telemetry/telemetry.models'; |
18 | import { | 18 | import { |
19 | - AggregationType, | 19 | + AggregationType, calculateIntervalComparisonEndTime, |
20 | calculateIntervalEndTime, | 20 | calculateIntervalEndTime, |
21 | - calculateIntervalStartTime, getCurrentTime, | ||
22 | - QuickTimeInterval, SubscriptionTimewindow | 21 | + calculateIntervalStartTime, |
22 | + getCurrentTime, | ||
23 | + getCurrentTimeForComparison, | ||
24 | + SubscriptionTimewindow | ||
23 | } from '@shared/models/time/time.models'; | 25 | } from '@shared/models/time/time.models'; |
24 | import { UtilsService } from '@core/services/utils.service'; | 26 | import { UtilsService } from '@core/services/utils.service'; |
25 | import { deepClone } from '@core/utils'; | 27 | import { deepClone } from '@core/utils'; |
26 | import Timeout = NodeJS.Timeout; | 28 | import Timeout = NodeJS.Timeout; |
29 | +import * as moment_ from 'moment'; | ||
27 | 30 | ||
28 | export declare type onAggregatedData = (data: SubscriptionData, detectChanges: boolean) => void; | 31 | export declare type onAggregatedData = (data: SubscriptionData, detectChanges: boolean) => void; |
29 | 32 | ||
@@ -85,7 +88,7 @@ export class DataAggregator { | @@ -85,7 +88,7 @@ export class DataAggregator { | ||
85 | private intervalTimeoutHandle: Timeout; | 88 | private intervalTimeoutHandle: Timeout; |
86 | private intervalScheduledTime: number; | 89 | private intervalScheduledTime: number; |
87 | 90 | ||
88 | - private startTs = this.subsTw.startTs + this.subsTw.tsOffset; | 91 | + private startTs: number; |
89 | private endTs: number; | 92 | private endTs: number; |
90 | private elapsed: number; | 93 | private elapsed: number; |
91 | 94 | ||
@@ -137,12 +140,7 @@ export class DataAggregator { | @@ -137,12 +140,7 @@ export class DataAggregator { | ||
137 | } | 140 | } |
138 | this.subsTw = subsTw; | 141 | this.subsTw = subsTw; |
139 | this.intervalScheduledTime = this.utils.currentPerfTime(); | 142 | this.intervalScheduledTime = this.utils.currentPerfTime(); |
140 | - this.startTs = this.subsTw.startTs + this.subsTw.tsOffset; | ||
141 | - if (this.subsTw.quickInterval) { | ||
142 | - this.endTs = calculateIntervalEndTime(this.subsTw.quickInterval, null, this.subsTw.timezone) + this.subsTw.tsOffset; | ||
143 | - } else { | ||
144 | - this.endTs = this.startTs + this.subsTw.aggregation.timeWindow; | ||
145 | - } | 143 | + this.calculateStartEndTs(); |
146 | this.elapsed = 0; | 144 | this.elapsed = 0; |
147 | this.aggregationTimeout = Math.max(this.subsTw.aggregation.interval, 1000); | 145 | this.aggregationTimeout = Math.max(this.subsTw.aggregation.interval, 1000); |
148 | this.resetPending = true; | 146 | this.resetPending = true; |
@@ -165,11 +163,7 @@ export class DataAggregator { | @@ -165,11 +163,7 @@ export class DataAggregator { | ||
165 | if (!this.dataReceived) { | 163 | if (!this.dataReceived) { |
166 | this.elapsed = 0; | 164 | this.elapsed = 0; |
167 | this.dataReceived = true; | 165 | this.dataReceived = true; |
168 | - if (this.subsTw.quickInterval) { | ||
169 | - this.endTs = calculateIntervalEndTime(this.subsTw.quickInterval, null, this.subsTw.timezone) + this.subsTw.tsOffset; | ||
170 | - } else { | ||
171 | - this.endTs = this.startTs + this.subsTw.aggregation.timeWindow; | ||
172 | - } | 166 | + this.calculateStartEndTs(); |
173 | } | 167 | } |
174 | if (this.resetPending) { | 168 | if (this.resetPending) { |
175 | this.resetPending = false; | 169 | this.resetPending = false; |
@@ -194,6 +188,21 @@ export class DataAggregator { | @@ -194,6 +188,21 @@ export class DataAggregator { | ||
194 | } | 188 | } |
195 | } | 189 | } |
196 | 190 | ||
191 | + private calculateStartEndTs() { | ||
192 | + this.startTs = this.subsTw.startTs + this.subsTw.tsOffset; | ||
193 | + if (this.subsTw.quickInterval) { | ||
194 | + if (this.subsTw.timeForComparison === 'previousInterval') { | ||
195 | + const currentDate = getCurrentTime(this.subsTw.timezone); | ||
196 | + this.endTs = calculateIntervalComparisonEndTime(this.subsTw.quickInterval, currentDate) + this.subsTw.tsOffset; | ||
197 | + } else { | ||
198 | + const currentDate = this.getCurrentTime(); | ||
199 | + this.endTs = calculateIntervalEndTime(this.subsTw.quickInterval, currentDate) + this.subsTw.tsOffset; | ||
200 | + } | ||
201 | + } else { | ||
202 | + this.endTs = this.startTs + this.subsTw.aggregation.timeWindow; | ||
203 | + } | ||
204 | + } | ||
205 | + | ||
197 | private onInterval(history?: boolean, detectChanges?: boolean) { | 206 | private onInterval(history?: boolean, detectChanges?: boolean) { |
198 | const now = this.utils.currentPerfTime(); | 207 | const now = this.utils.currentPerfTime(); |
199 | this.elapsed += now - this.intervalScheduledTime; | 208 | this.elapsed += now - this.intervalScheduledTime; |
@@ -207,7 +216,7 @@ export class DataAggregator { | @@ -207,7 +216,7 @@ export class DataAggregator { | ||
207 | if (delta || !this.data) { | 216 | if (delta || !this.data) { |
208 | const tickTs = delta * this.subsTw.aggregation.interval; | 217 | const tickTs = delta * this.subsTw.aggregation.interval; |
209 | if (this.subsTw.quickInterval) { | 218 | if (this.subsTw.quickInterval) { |
210 | - const currentDate = getCurrentTime(this.subsTw.timezone); | 219 | + const currentDate = this.getCurrentTime(); |
211 | this.startTs = calculateIntervalStartTime(this.subsTw.quickInterval, currentDate) + this.subsTw.tsOffset; | 220 | this.startTs = calculateIntervalStartTime(this.subsTw.quickInterval, currentDate) + this.subsTw.tsOffset; |
212 | this.endTs = calculateIntervalEndTime(this.subsTw.quickInterval, currentDate) + this.subsTw.tsOffset; | 221 | this.endTs = calculateIntervalEndTime(this.subsTw.quickInterval, currentDate) + this.subsTw.tsOffset; |
213 | } else { | 222 | } else { |
@@ -356,5 +365,13 @@ export class DataAggregator { | @@ -356,5 +365,13 @@ export class DataAggregator { | ||
356 | } | 365 | } |
357 | } | 366 | } |
358 | 367 | ||
368 | + private getCurrentTime() { | ||
369 | + if (this.subsTw.timeForComparison) { | ||
370 | + return getCurrentTimeForComparison(this.subsTw.timeForComparison as moment_.unitOfTime.DurationConstructor, this.subsTw.timezone); | ||
371 | + } else { | ||
372 | + return getCurrentTime(this.subsTw.timezone); | ||
373 | + } | ||
374 | + } | ||
375 | + | ||
359 | } | 376 | } |
360 | 377 |
@@ -419,8 +419,8 @@ export class EntityDataSubscription { | @@ -419,8 +419,8 @@ export class EntityDataSubscription { | ||
419 | latestTsOffsetChanged = this.subscriber.setTsOffset(this.latestTsOffset); | 419 | latestTsOffsetChanged = this.subscriber.setTsOffset(this.latestTsOffset); |
420 | } | 420 | } |
421 | if (latestTsOffsetChanged) { | 421 | if (latestTsOffsetChanged) { |
422 | - if (this.listener.initialPageDataChanged) { | ||
423 | - this.listener.initialPageDataChanged(this.pageData); | 422 | + if (this.listener.forceReInit) { |
423 | + this.listener.forceReInit(); | ||
424 | } | 424 | } |
425 | } else if (!this.subsCommand.isEmpty()) { | 425 | } else if (!this.subsCommand.isEmpty()) { |
426 | this.subscriber.subscriptionCommands = [this.subsCommand]; | 426 | this.subscriber.subscriptionCommands = [this.subsCommand]; |
@@ -428,8 +428,8 @@ export class EntityDataSubscription { | @@ -428,8 +428,8 @@ export class EntityDataSubscription { | ||
428 | } | 428 | } |
429 | } else if (this.datasourceType === DatasourceType.entityCount) { | 429 | } else if (this.datasourceType === DatasourceType.entityCount) { |
430 | if (this.subscriber.setTsOffset(this.latestTsOffset)) { | 430 | if (this.subscriber.setTsOffset(this.latestTsOffset)) { |
431 | - if (this.listener.initialPageDataChanged) { | ||
432 | - this.listener.initialPageDataChanged(this.pageData); | 431 | + if (this.listener.forceReInit) { |
432 | + this.listener.forceReInit(); | ||
433 | } | 433 | } |
434 | } | 434 | } |
435 | } else if (this.datasourceType === DatasourceType.function) { | 435 | } else if (this.datasourceType === DatasourceType.function) { |
@@ -40,6 +40,7 @@ export interface EntityDataListener { | @@ -40,6 +40,7 @@ export interface EntityDataListener { | ||
40 | datasourceIndex: number, pageLink: EntityDataPageLink) => void; | 40 | datasourceIndex: number, pageLink: EntityDataPageLink) => void; |
41 | dataUpdated: (data: DataSetHolder, datasourceIndex: number, dataIndex: number, dataKeyIndex: number, detectChanges: boolean) => void; | 41 | dataUpdated: (data: DataSetHolder, datasourceIndex: number, dataIndex: number, dataKeyIndex: number, detectChanges: boolean) => void; |
42 | initialPageDataChanged?: (nextPageData: PageData<EntityData>) => void; | 42 | initialPageDataChanged?: (nextPageData: PageData<EntityData>) => void; |
43 | + forceReInit?: () => void; | ||
43 | updateRealtimeSubscription?: () => SubscriptionTimewindow; | 44 | updateRealtimeSubscription?: () => SubscriptionTimewindow; |
44 | setRealtimeSubscription?: (subscriptionTimewindow: SubscriptionTimewindow) => void; | 45 | setRealtimeSubscription?: (subscriptionTimewindow: SubscriptionTimewindow) => void; |
45 | subscriptionOptions?: EntityDataSubscriptionOptions; | 46 | subscriptionOptions?: EntityDataSubscriptionOptions; |
@@ -209,6 +209,7 @@ export interface WidgetSubscriptionCallbacks { | @@ -209,6 +209,7 @@ export interface WidgetSubscriptionCallbacks { | ||
209 | onDataUpdateError?: (subscription: IWidgetSubscription, e: any) => void; | 209 | onDataUpdateError?: (subscription: IWidgetSubscription, e: any) => void; |
210 | onSubscriptionMessage?: (subscription: IWidgetSubscription, message: SubscriptionMessage) => void; | 210 | onSubscriptionMessage?: (subscription: IWidgetSubscription, message: SubscriptionMessage) => void; |
211 | onInitialPageDataChanged?: (subscription: IWidgetSubscription, nextPageData: PageData<EntityData>) => void; | 211 | onInitialPageDataChanged?: (subscription: IWidgetSubscription, nextPageData: PageData<EntityData>) => void; |
212 | + forceReInit?: () => void; | ||
212 | dataLoading?: (subscription: IWidgetSubscription) => void; | 213 | dataLoading?: (subscription: IWidgetSubscription) => void; |
213 | legendDataUpdated?: (subscription: IWidgetSubscription, detectChanges: boolean) => void; | 214 | legendDataUpdated?: (subscription: IWidgetSubscription, detectChanges: boolean) => void; |
214 | timeWindowUpdated?: (subscription: IWidgetSubscription, timeWindowConfig: Timewindow) => void; | 215 | timeWindowUpdated?: (subscription: IWidgetSubscription, timeWindowConfig: Timewindow) => void; |
@@ -269,6 +270,7 @@ export interface IWidgetSubscription { | @@ -269,6 +270,7 @@ export interface IWidgetSubscription { | ||
269 | hiddenData?: Array<{data: DataSet}>; | 270 | hiddenData?: Array<{data: DataSet}>; |
270 | timeWindowConfig?: Timewindow; | 271 | timeWindowConfig?: Timewindow; |
271 | timeWindow?: WidgetTimewindow; | 272 | timeWindow?: WidgetTimewindow; |
273 | + comparisonEnabled?: boolean; | ||
272 | comparisonTimeWindow?: WidgetTimewindow; | 274 | comparisonTimeWindow?: WidgetTimewindow; |
273 | 275 | ||
274 | alarms?: PageData<AlarmData>; | 276 | alarms?: PageData<AlarmData>; |
@@ -39,12 +39,12 @@ import { HttpErrorResponse } from '@angular/common/http'; | @@ -39,12 +39,12 @@ import { HttpErrorResponse } from '@angular/common/http'; | ||
39 | import { | 39 | import { |
40 | calculateIntervalEndTime, | 40 | calculateIntervalEndTime, |
41 | calculateIntervalStartTime, | 41 | calculateIntervalStartTime, |
42 | - calculateTsOffset, | 42 | + calculateTsOffset, ComparisonDuration, |
43 | createSubscriptionTimewindow, | 43 | createSubscriptionTimewindow, |
44 | createTimewindowForComparison, | 44 | createTimewindowForComparison, |
45 | - getCurrentTime, | 45 | + getCurrentTime, isHistoryTypeTimewindow, |
46 | SubscriptionTimewindow, | 46 | SubscriptionTimewindow, |
47 | - Timewindow, | 47 | + Timewindow, timewindowTypeChanged, |
48 | toHistoryTimewindow, | 48 | toHistoryTimewindow, |
49 | WidgetTimewindow | 49 | WidgetTimewindow |
50 | } from '@app/shared/models/time/time.models'; | 50 | } from '@app/shared/models/time/time.models'; |
@@ -107,7 +107,7 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -107,7 +107,7 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
107 | decimals: number; | 107 | decimals: number; |
108 | units: string; | 108 | units: string; |
109 | comparisonEnabled: boolean; | 109 | comparisonEnabled: boolean; |
110 | - timeForComparison: moment_.unitOfTime.DurationConstructor; | 110 | + timeForComparison: ComparisonDuration; |
111 | comparisonTimeWindow: WidgetTimewindow; | 111 | comparisonTimeWindow: WidgetTimewindow; |
112 | timewindowForComparison: SubscriptionTimewindow; | 112 | timewindowForComparison: SubscriptionTimewindow; |
113 | 113 | ||
@@ -198,6 +198,7 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -198,6 +198,7 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
198 | this.callbacks.onDataUpdateError = this.callbacks.onDataUpdateError || (() => {}); | 198 | this.callbacks.onDataUpdateError = this.callbacks.onDataUpdateError || (() => {}); |
199 | this.callbacks.onSubscriptionMessage = this.callbacks.onSubscriptionMessage || (() => {}); | 199 | this.callbacks.onSubscriptionMessage = this.callbacks.onSubscriptionMessage || (() => {}); |
200 | this.callbacks.onInitialPageDataChanged = this.callbacks.onInitialPageDataChanged || (() => {}); | 200 | this.callbacks.onInitialPageDataChanged = this.callbacks.onInitialPageDataChanged || (() => {}); |
201 | + this.callbacks.forceReInit = this.callbacks.forceReInit || (() => {}); | ||
201 | this.callbacks.dataLoading = this.callbacks.dataLoading || (() => {}); | 202 | this.callbacks.dataLoading = this.callbacks.dataLoading || (() => {}); |
202 | this.callbacks.legendDataUpdated = this.callbacks.legendDataUpdated || (() => {}); | 203 | this.callbacks.legendDataUpdated = this.callbacks.legendDataUpdated || (() => {}); |
203 | this.callbacks.timeWindowUpdated = this.callbacks.timeWindowUpdated || (() => {}); | 204 | this.callbacks.timeWindowUpdated = this.callbacks.timeWindowUpdated || (() => {}); |
@@ -228,7 +229,7 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -228,7 +229,7 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
228 | } | 229 | } |
229 | 230 | ||
230 | this.subscriptionTimewindow = null; | 231 | this.subscriptionTimewindow = null; |
231 | - this.comparisonEnabled = options.comparisonEnabled; | 232 | + this.comparisonEnabled = options.comparisonEnabled && isHistoryTypeTimewindow(this.timeWindowConfig); |
232 | if (this.comparisonEnabled) { | 233 | if (this.comparisonEnabled) { |
233 | this.timeForComparison = options.timeForComparison; | 234 | this.timeForComparison = options.timeForComparison; |
234 | 235 | ||
@@ -418,20 +419,13 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -418,20 +419,13 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
418 | this.dataLoaded(pageData, data1, datasourceIndex, pageLink, true); | 419 | this.dataLoaded(pageData, data1, datasourceIndex, pageLink, true); |
419 | }, | 420 | }, |
420 | initialPageDataChanged: this.initialPageDataChanged.bind(this), | 421 | initialPageDataChanged: this.initialPageDataChanged.bind(this), |
422 | + forceReInit: this.forceReInit.bind(this), | ||
421 | dataUpdated: this.dataUpdated.bind(this), | 423 | dataUpdated: this.dataUpdated.bind(this), |
422 | updateRealtimeSubscription: () => { | 424 | updateRealtimeSubscription: () => { |
423 | - if (this.comparisonEnabled && datasource.isAdditional) { | ||
424 | - return this.updateSubscriptionForComparison(); | ||
425 | - } else { | ||
426 | - return this.updateRealtimeSubscription(); | ||
427 | - } | 425 | + return this.updateRealtimeSubscription(); |
428 | }, | 426 | }, |
429 | setRealtimeSubscription: (subscriptionTimewindow) => { | 427 | setRealtimeSubscription: (subscriptionTimewindow) => { |
430 | - if (this.comparisonEnabled && datasource.isAdditional) { | ||
431 | - this.updateSubscriptionForComparison(subscriptionTimewindow); | ||
432 | - } else { | ||
433 | - this.updateRealtimeSubscription(deepClone(subscriptionTimewindow)); | ||
434 | - } | 428 | + this.updateRealtimeSubscription(deepClone(subscriptionTimewindow)); |
435 | } | 429 | } |
436 | }; | 430 | }; |
437 | this.entityDataListeners.push(listener); | 431 | this.entityDataListeners.push(listener); |
@@ -584,8 +578,9 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -584,8 +578,9 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
584 | if (this.type === widgetType.timeseries || this.type === widgetType.alarm) { | 578 | if (this.type === widgetType.timeseries || this.type === widgetType.alarm) { |
585 | if (this.useDashboardTimewindow) { | 579 | if (this.useDashboardTimewindow) { |
586 | if (!isEqual(this.timeWindowConfig, newDashboardTimewindow) && newDashboardTimewindow) { | 580 | if (!isEqual(this.timeWindowConfig, newDashboardTimewindow) && newDashboardTimewindow) { |
581 | + const isTimewindowTypeChanged = timewindowTypeChanged(this.timeWindowConfig, newDashboardTimewindow); | ||
587 | this.timeWindowConfig = deepClone(newDashboardTimewindow); | 582 | this.timeWindowConfig = deepClone(newDashboardTimewindow); |
588 | - this.update(); | 583 | + this.update(isTimewindowTypeChanged); |
589 | } | 584 | } |
590 | } | 585 | } |
591 | } else if (this.type === widgetType.latest) { | 586 | } else if (this.type === widgetType.latest) { |
@@ -614,8 +609,9 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -614,8 +609,9 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
614 | 609 | ||
615 | updateTimewindowConfig(newTimewindow: Timewindow): void { | 610 | updateTimewindowConfig(newTimewindow: Timewindow): void { |
616 | if (!this.useDashboardTimewindow) { | 611 | if (!this.useDashboardTimewindow) { |
612 | + const isTimewindowTypeChanged = timewindowTypeChanged(this.timeWindowConfig, newTimewindow); | ||
617 | this.timeWindowConfig = newTimewindow; | 613 | this.timeWindowConfig = newTimewindow; |
618 | - this.update(); | 614 | + this.update(isTimewindowTypeChanged); |
619 | } | 615 | } |
620 | } | 616 | } |
621 | 617 | ||
@@ -624,10 +620,11 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -624,10 +620,11 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
624 | this.ctx.dashboardTimewindowApi.onResetTimewindow(); | 620 | this.ctx.dashboardTimewindowApi.onResetTimewindow(); |
625 | } else { | 621 | } else { |
626 | if (this.originalTimewindow) { | 622 | if (this.originalTimewindow) { |
623 | + const isTimewindowTypeChanged = timewindowTypeChanged(this.timeWindowConfig, this.originalTimewindow); | ||
627 | this.timeWindowConfig = deepClone(this.originalTimewindow); | 624 | this.timeWindowConfig = deepClone(this.originalTimewindow); |
628 | this.originalTimewindow = null; | 625 | this.originalTimewindow = null; |
629 | this.callbacks.timeWindowUpdated(this, this.timeWindowConfig); | 626 | this.callbacks.timeWindowUpdated(this, this.timeWindowConfig); |
630 | - this.update(); | 627 | + this.update(isTimewindowTypeChanged); |
631 | } | 628 | } |
632 | } | 629 | } |
633 | } | 630 | } |
@@ -641,7 +638,8 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -641,7 +638,8 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
641 | } | 638 | } |
642 | this.timeWindowConfig = toHistoryTimewindow(this.timeWindowConfig, startTimeMs, endTimeMs, interval, this.ctx.timeService); | 639 | this.timeWindowConfig = toHistoryTimewindow(this.timeWindowConfig, startTimeMs, endTimeMs, interval, this.ctx.timeService); |
643 | this.callbacks.timeWindowUpdated(this, this.timeWindowConfig); | 640 | this.callbacks.timeWindowUpdated(this, this.timeWindowConfig); |
644 | - this.update(); | 641 | + const isTimewindowTypeChanged = timewindowTypeChanged(this.timeWindowConfig, this.originalTimewindow); |
642 | + this.update(isTimewindowTypeChanged); | ||
645 | } | 643 | } |
646 | } | 644 | } |
647 | 645 | ||
@@ -770,16 +768,20 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -770,16 +768,20 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
770 | } | 768 | } |
771 | } | 769 | } |
772 | 770 | ||
773 | - update() { | 771 | + update(isTimewindowTypeChanged = false) { |
774 | if (this.type !== widgetType.rpc) { | 772 | if (this.type !== widgetType.rpc) { |
775 | if (this.type === widgetType.alarm) { | 773 | if (this.type === widgetType.alarm) { |
776 | this.updateAlarmDataSubscription(); | 774 | this.updateAlarmDataSubscription(); |
777 | } else { | 775 | } else { |
778 | - if (this.hasDataPageLink) { | ||
779 | - this.updateDataSubscriptions(); | 776 | + if (this.type === widgetType.timeseries && this.options.comparisonEnabled && isTimewindowTypeChanged) { |
777 | + this.forceReInit(); | ||
780 | } else { | 778 | } else { |
781 | - this.notifyDataLoading(); | ||
782 | - this.dataSubscribe(); | 779 | + if (this.hasDataPageLink) { |
780 | + this.updateDataSubscriptions(); | ||
781 | + } else { | ||
782 | + this.notifyDataLoading(); | ||
783 | + this.dataSubscribe(); | ||
784 | + } | ||
783 | } | 785 | } |
784 | } | 786 | } |
785 | } | 787 | } |
@@ -1143,24 +1145,14 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -1143,24 +1145,14 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
1143 | private updateComparisonTimewindow() { | 1145 | private updateComparisonTimewindow() { |
1144 | this.comparisonTimeWindow.interval = this.timewindowForComparison.aggregation.interval || 1000; | 1146 | this.comparisonTimeWindow.interval = this.timewindowForComparison.aggregation.interval || 1000; |
1145 | this.comparisonTimeWindow.timezone = this.timewindowForComparison.timezone; | 1147 | this.comparisonTimeWindow.timezone = this.timewindowForComparison.timezone; |
1146 | - if (this.timewindowForComparison.realtimeWindowMs) { | ||
1147 | - this.comparisonTimeWindow.maxTime = moment(this.timeWindow.maxTime).subtract(1, this.timeForComparison).valueOf(); | ||
1148 | - this.comparisonTimeWindow.minTime = moment(this.timeWindow.minTime).subtract(1, this.timeForComparison).valueOf(); | ||
1149 | - } else if (this.timewindowForComparison.fixedWindow) { | 1148 | + if (this.timewindowForComparison.fixedWindow) { |
1150 | this.comparisonTimeWindow.maxTime = this.timewindowForComparison.fixedWindow.endTimeMs + this.timewindowForComparison.tsOffset; | 1149 | this.comparisonTimeWindow.maxTime = this.timewindowForComparison.fixedWindow.endTimeMs + this.timewindowForComparison.tsOffset; |
1151 | this.comparisonTimeWindow.minTime = this.timewindowForComparison.fixedWindow.startTimeMs + this.timewindowForComparison.tsOffset; | 1150 | this.comparisonTimeWindow.minTime = this.timewindowForComparison.fixedWindow.startTimeMs + this.timewindowForComparison.tsOffset; |
1152 | } | 1151 | } |
1153 | } | 1152 | } |
1154 | 1153 | ||
1155 | - private updateSubscriptionForComparison(subscriptionTimewindow?: SubscriptionTimewindow): SubscriptionTimewindow { | ||
1156 | - if (subscriptionTimewindow) { | ||
1157 | - this.timewindowForComparison = subscriptionTimewindow; | ||
1158 | - } else { | ||
1159 | - if (!this.subscriptionTimewindow) { | ||
1160 | - this.subscriptionTimewindow = this.updateRealtimeSubscription(); | ||
1161 | - } | ||
1162 | - this.timewindowForComparison = createTimewindowForComparison(this.subscriptionTimewindow, this.timeForComparison); | ||
1163 | - } | 1154 | + private updateSubscriptionForComparison(): SubscriptionTimewindow { |
1155 | + this.timewindowForComparison = createTimewindowForComparison(this.subscriptionTimewindow, this.timeForComparison); | ||
1164 | this.updateComparisonTimewindow(); | 1156 | this.updateComparisonTimewindow(); |
1165 | return this.timewindowForComparison; | 1157 | return this.timewindowForComparison; |
1166 | } | 1158 | } |
@@ -1169,6 +1161,10 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -1169,6 +1161,10 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
1169 | this.callbacks.onInitialPageDataChanged(this, nextPageData); | 1161 | this.callbacks.onInitialPageDataChanged(this, nextPageData); |
1170 | } | 1162 | } |
1171 | 1163 | ||
1164 | + private forceReInit() { | ||
1165 | + this.callbacks.forceReInit(); | ||
1166 | + } | ||
1167 | + | ||
1172 | private dataLoaded(pageData: PageData<EntityData>, | 1168 | private dataLoaded(pageData: PageData<EntityData>, |
1173 | data: Array<Array<DataSetHolder>>, | 1169 | data: Array<Array<DataSetHolder>>, |
1174 | datasourceIndex: number, pageLink: EntityDataPageLink, isUpdate: boolean) { | 1170 | datasourceIndex: number, pageLink: EntityDataPageLink, isUpdate: boolean) { |
@@ -20,6 +20,7 @@ | @@ -20,6 +20,7 @@ | ||
20 | import { DataKey, Datasource, DatasourceData, JsonSettingsSchema } from '@shared/models/widget.models'; | 20 | import { DataKey, Datasource, DatasourceData, JsonSettingsSchema } from '@shared/models/widget.models'; |
21 | import * as moment_ from 'moment'; | 21 | import * as moment_ from 'moment'; |
22 | import { DataKeyType } from "@shared/models/telemetry/telemetry.models"; | 22 | import { DataKeyType } from "@shared/models/telemetry/telemetry.models"; |
23 | +import { ComparisonDuration } from '@shared/models/time/time.models'; | ||
23 | 24 | ||
24 | export declare type ChartType = 'line' | 'pie' | 'bar' | 'state' | 'graph'; | 25 | export declare type ChartType = 'line' | 'pie' | 'bar' | 'state' | 'graph'; |
25 | 26 | ||
@@ -142,7 +143,7 @@ export interface TbFlotBaseSettings { | @@ -142,7 +143,7 @@ export interface TbFlotBaseSettings { | ||
142 | 143 | ||
143 | export interface TbFlotComparisonSettings { | 144 | export interface TbFlotComparisonSettings { |
144 | comparisonEnabled: boolean; | 145 | comparisonEnabled: boolean; |
145 | - timeForComparison: moment_.unitOfTime.DurationConstructor; | 146 | + timeForComparison: ComparisonDuration; |
146 | xaxisSecond: TbFlotSecondXAxisSettings; | 147 | xaxisSecond: TbFlotSecondXAxisSettings; |
147 | } | 148 | } |
148 | 149 | ||
@@ -543,7 +544,7 @@ const chartSettingsSchemaForComparison: JsonSettingsSchema = { | @@ -543,7 +544,7 @@ const chartSettingsSchemaForComparison: JsonSettingsSchema = { | ||
543 | timeForComparison: { | 544 | timeForComparison: { |
544 | title: 'Time to show historical data', | 545 | title: 'Time to show historical data', |
545 | type: 'string', | 546 | type: 'string', |
546 | - default: 'months' | 547 | + default: 'previousInterval' |
547 | }, | 548 | }, |
548 | xaxisSecond: { | 549 | xaxisSecond: { |
549 | title: 'Second X axis', | 550 | title: 'Second X axis', |
@@ -577,6 +578,10 @@ const chartSettingsSchemaForComparison: JsonSettingsSchema = { | @@ -577,6 +578,10 @@ const chartSettingsSchemaForComparison: JsonSettingsSchema = { | ||
577 | multiple: false, | 578 | multiple: false, |
578 | items: [ | 579 | items: [ |
579 | { | 580 | { |
581 | + value: 'previousInterval', | ||
582 | + label: 'Previous interval (default)' | ||
583 | + }, | ||
584 | + { | ||
580 | value: 'days', | 585 | value: 'days', |
581 | label: 'Day ago' | 586 | label: 'Day ago' |
582 | }, | 587 | }, |
@@ -586,7 +591,7 @@ const chartSettingsSchemaForComparison: JsonSettingsSchema = { | @@ -586,7 +591,7 @@ const chartSettingsSchemaForComparison: JsonSettingsSchema = { | ||
586 | }, | 591 | }, |
587 | { | 592 | { |
588 | value: 'months', | 593 | value: 'months', |
589 | - label: 'Month ago (default)' | 594 | + label: 'Month ago' |
590 | }, | 595 | }, |
591 | { | 596 | { |
592 | value: 'years', | 597 | value: 'years', |
@@ -74,6 +74,7 @@ export class TbFlot { | @@ -74,6 +74,7 @@ export class TbFlot { | ||
74 | private readonly utils: UtilsService; | 74 | private readonly utils: UtilsService; |
75 | 75 | ||
76 | private settings: TbFlotSettings; | 76 | private settings: TbFlotSettings; |
77 | + private comparisonEnabled: boolean; | ||
77 | 78 | ||
78 | private readonly tooltip: JQuery<any>; | 79 | private readonly tooltip: JQuery<any>; |
79 | 80 | ||
@@ -263,29 +264,7 @@ export class TbFlot { | @@ -263,29 +264,7 @@ export class TbFlot { | ||
263 | }; | 264 | }; |
264 | } | 265 | } |
265 | 266 | ||
266 | - if (this.settings.comparisonEnabled) { | ||
267 | - const xaxis = deepClone(this.xaxis); | ||
268 | - xaxis.position = 'top'; | ||
269 | - if (this.settings.xaxisSecond) { | ||
270 | - if (this.settings.xaxisSecond.showLabels === false) { | ||
271 | - xaxis.tickFormatter = () => { | ||
272 | - return ''; | ||
273 | - }; | ||
274 | - } | ||
275 | - xaxis.label = this.utils.customTranslation(this.settings.xaxisSecond.title, this.settings.xaxisSecond.title) || null; | ||
276 | - xaxis.position = this.settings.xaxisSecond.axisPosition; | ||
277 | - } | ||
278 | - xaxis.tickLength = 0; | ||
279 | - this.options.xaxes.push(xaxis); | ||
280 | - | ||
281 | - this.options.series = { | ||
282 | - stack: false | ||
283 | - }; | ||
284 | - } else { | ||
285 | - this.options.series = { | ||
286 | - stack: this.settings.stack === true | ||
287 | - }; | ||
288 | - } | 267 | + this.options.series = {}; |
289 | 268 | ||
290 | this.options.crosshair = { | 269 | this.options.crosshair = { |
291 | mode: 'x' | 270 | mode: 'x' |
@@ -364,7 +343,6 @@ export class TbFlot { | @@ -364,7 +343,6 @@ export class TbFlot { | ||
364 | 343 | ||
365 | // Experimental | 344 | // Experimental |
366 | this.animatedPie = this.settings.animatedPie === true; | 345 | this.animatedPie = this.settings.animatedPie === true; |
367 | - | ||
368 | } | 346 | } |
369 | 347 | ||
370 | if (this.ctx.defaultSubscription) { | 348 | if (this.ctx.defaultSubscription) { |
@@ -372,10 +350,29 @@ export class TbFlot { | @@ -372,10 +350,29 @@ export class TbFlot { | ||
372 | } | 350 | } |
373 | } | 351 | } |
374 | 352 | ||
375 | - | ||
376 | private init($element: JQuery<any>, subscription: IWidgetSubscription) { | 353 | private init($element: JQuery<any>, subscription: IWidgetSubscription) { |
377 | - this.subscription = subscription; | ||
378 | this.$element = $element; | 354 | this.$element = $element; |
355 | + this.subscription = subscription; | ||
356 | + this.comparisonEnabled = this.subscription ? this.subscription.comparisonEnabled : this.settings.comparisonEnabled; | ||
357 | + if (this.comparisonEnabled) { | ||
358 | + const xaxis = deepClone(this.xaxis); | ||
359 | + xaxis.position = 'top'; | ||
360 | + if (this.settings.xaxisSecond) { | ||
361 | + if (this.settings.xaxisSecond.showLabels === false) { | ||
362 | + xaxis.tickFormatter = () => { | ||
363 | + return ''; | ||
364 | + }; | ||
365 | + } | ||
366 | + xaxis.label = this.utils.customTranslation(this.settings.xaxisSecond.title, this.settings.xaxisSecond.title) || null; | ||
367 | + xaxis.position = this.settings.xaxisSecond.axisPosition; | ||
368 | + } | ||
369 | + xaxis.tickLength = 0; | ||
370 | + this.options.xaxes.push(xaxis); | ||
371 | + | ||
372 | + this.options.series.stack = false; | ||
373 | + } else { | ||
374 | + this.options.series.stack = this.settings.stack === true; | ||
375 | + } | ||
379 | const colors: string[] = []; | 376 | const colors: string[] = []; |
380 | this.yaxes = []; | 377 | this.yaxes = []; |
381 | const yaxesMap: {[units: string]: TbFlotAxisOptions} = {}; | 378 | const yaxesMap: {[units: string]: TbFlotAxisOptions} = {}; |
@@ -387,7 +384,7 @@ export class TbFlot { | @@ -387,7 +384,7 @@ export class TbFlot { | ||
387 | this.settings.dataKeysListForLabels.forEach((item) => { | 384 | this.settings.dataKeysListForLabels.forEach((item) => { |
388 | item.settings = {}; | 385 | item.settings = {}; |
389 | }); | 386 | }); |
390 | - subscription.datasources.forEach((item) => { | 387 | + this.subscription.datasources.forEach((item) => { |
391 | const datasource: Datasource = { | 388 | const datasource: Datasource = { |
392 | type: item.type, | 389 | type: item.type, |
393 | entityType: item.entityType, | 390 | entityType: item.entityType, |
@@ -425,7 +422,7 @@ export class TbFlot { | @@ -425,7 +422,7 @@ export class TbFlot { | ||
425 | fill: keySettings.fillLines === true | 422 | fill: keySettings.fillLines === true |
426 | }; | 423 | }; |
427 | 424 | ||
428 | - if (this.settings.stack && !this.settings.comparisonEnabled) { | 425 | + if (this.settings.stack && !this.comparisonEnabled) { |
429 | series.stack = !keySettings.excludeFromStacking; | 426 | series.stack = !keySettings.excludeFromStacking; |
430 | } else { | 427 | } else { |
431 | series.stack = false; | 428 | series.stack = false; |
@@ -557,7 +554,7 @@ export class TbFlot { | @@ -557,7 +554,7 @@ export class TbFlot { | ||
557 | } | 554 | } |
558 | this.options.xaxes[0].min = this.subscription.timeWindow.minTime; | 555 | this.options.xaxes[0].min = this.subscription.timeWindow.minTime; |
559 | this.options.xaxes[0].max = this.subscription.timeWindow.maxTime; | 556 | this.options.xaxes[0].max = this.subscription.timeWindow.maxTime; |
560 | - if (this.settings.comparisonEnabled) { | 557 | + if (this.comparisonEnabled) { |
561 | this.options.xaxes[1].min = this.subscription.comparisonTimeWindow.minTime; | 558 | this.options.xaxes[1].min = this.subscription.comparisonTimeWindow.minTime; |
562 | this.options.xaxes[1].max = this.subscription.comparisonTimeWindow.maxTime; | 559 | this.options.xaxes[1].max = this.subscription.comparisonTimeWindow.maxTime; |
563 | } | 560 | } |
@@ -636,7 +633,7 @@ export class TbFlot { | @@ -636,7 +633,7 @@ export class TbFlot { | ||
636 | 633 | ||
637 | this.options.xaxes[0].min = this.subscription.timeWindow.minTime; | 634 | this.options.xaxes[0].min = this.subscription.timeWindow.minTime; |
638 | this.options.xaxes[0].max = this.subscription.timeWindow.maxTime; | 635 | this.options.xaxes[0].max = this.subscription.timeWindow.maxTime; |
639 | - if (this.settings.comparisonEnabled) { | 636 | + if (this.comparisonEnabled) { |
640 | this.options.xaxes[1].min = this.subscription.comparisonTimeWindow.minTime; | 637 | this.options.xaxes[1].min = this.subscription.comparisonTimeWindow.minTime; |
641 | this.options.xaxes[1].max = this.subscription.comparisonTimeWindow.maxTime; | 638 | this.options.xaxes[1].max = this.subscription.comparisonTimeWindow.maxTime; |
642 | } | 639 | } |
@@ -654,7 +651,7 @@ export class TbFlot { | @@ -654,7 +651,7 @@ export class TbFlot { | ||
654 | } else { | 651 | } else { |
655 | this.plot.getOptions().xaxes[0].min = this.subscription.timeWindow.minTime; | 652 | this.plot.getOptions().xaxes[0].min = this.subscription.timeWindow.minTime; |
656 | this.plot.getOptions().xaxes[0].max = this.subscription.timeWindow.maxTime; | 653 | this.plot.getOptions().xaxes[0].max = this.subscription.timeWindow.maxTime; |
657 | - if (this.settings.comparisonEnabled) { | 654 | + if (this.comparisonEnabled) { |
658 | this.plot.getOptions().xaxes[1].min = this.subscription.comparisonTimeWindow.minTime; | 655 | this.plot.getOptions().xaxes[1].min = this.subscription.comparisonTimeWindow.minTime; |
659 | this.plot.getOptions().xaxes[1].max = this.subscription.comparisonTimeWindow.maxTime; | 656 | this.plot.getOptions().xaxes[1].max = this.subscription.comparisonTimeWindow.maxTime; |
660 | } | 657 | } |
@@ -1293,7 +1290,7 @@ export class TbFlot { | @@ -1293,7 +1290,7 @@ export class TbFlot { | ||
1293 | const results: TbFlotHoverInfo[] = [{ | 1290 | const results: TbFlotHoverInfo[] = [{ |
1294 | seriesHover: [] | 1291 | seriesHover: [] |
1295 | }]; | 1292 | }]; |
1296 | - if (this.settings.comparisonEnabled) { | 1293 | + if (this.comparisonEnabled) { |
1297 | results.push({ | 1294 | results.push({ |
1298 | seriesHover: [] | 1295 | seriesHover: [] |
1299 | }); | 1296 | }); |
@@ -857,6 +857,9 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI | @@ -857,6 +857,9 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI | ||
857 | onInitialPageDataChanged: (subscription, nextPageData) => { | 857 | onInitialPageDataChanged: (subscription, nextPageData) => { |
858 | this.reInit(); | 858 | this.reInit(); |
859 | }, | 859 | }, |
860 | + forceReInit: () => { | ||
861 | + this.reInit(); | ||
862 | + }, | ||
860 | dataLoading: (subscription) => { | 863 | dataLoading: (subscription) => { |
861 | if (this.loadingData !== subscription.loadingData) { | 864 | if (this.loadingData !== subscription.loadingData) { |
862 | this.loadingData = subscription.loadingData; | 865 | this.loadingData = subscription.loadingData; |
@@ -28,6 +28,8 @@ export const DAY = 24 * HOUR; | @@ -28,6 +28,8 @@ export const DAY = 24 * HOUR; | ||
28 | export const WEEK = 7 * DAY; | 28 | export const WEEK = 7 * DAY; |
29 | export const YEAR = DAY * 365; | 29 | export const YEAR = DAY * 365; |
30 | 30 | ||
31 | +export type ComparisonDuration = moment_.unitOfTime.DurationConstructor | 'previousInterval'; | ||
32 | + | ||
31 | export enum TimewindowType { | 33 | export enum TimewindowType { |
32 | REALTIME, | 34 | REALTIME, |
33 | HISTORY | 35 | HISTORY |
@@ -118,6 +120,7 @@ export interface SubscriptionTimewindow { | @@ -118,6 +120,7 @@ export interface SubscriptionTimewindow { | ||
118 | realtimeWindowMs?: number; | 120 | realtimeWindowMs?: number; |
119 | fixedWindow?: FixedWindow; | 121 | fixedWindow?: FixedWindow; |
120 | aggregation?: SubscriptionAggregation; | 122 | aggregation?: SubscriptionAggregation; |
123 | + timeForComparison?: ComparisonDuration; | ||
121 | } | 124 | } |
122 | 125 | ||
123 | export interface WidgetTimewindow { | 126 | export interface WidgetTimewindow { |
@@ -208,6 +211,14 @@ export function defaultTimewindow(timeService: TimeService): Timewindow { | @@ -208,6 +211,14 @@ export function defaultTimewindow(timeService: TimeService): Timewindow { | ||
208 | return timewindow; | 211 | return timewindow; |
209 | } | 212 | } |
210 | 213 | ||
214 | +function getTimewindowType(timewindow: Timewindow): TimewindowType { | ||
215 | + if (isUndefined(timewindow.selectedTab)) { | ||
216 | + return isDefined(timewindow.realtime) ? TimewindowType.REALTIME : TimewindowType.HISTORY; | ||
217 | + } else { | ||
218 | + return timewindow.selectedTab; | ||
219 | + } | ||
220 | +} | ||
221 | + | ||
211 | export function initModelFromDefaultTimewindow(value: Timewindow, timeService: TimeService): Timewindow { | 222 | export function initModelFromDefaultTimewindow(value: Timewindow, timeService: TimeService): Timewindow { |
212 | const model = defaultTimewindow(timeService); | 223 | const model = defaultTimewindow(timeService); |
213 | if (value) { | 224 | if (value) { |
@@ -215,15 +226,7 @@ export function initModelFromDefaultTimewindow(value: Timewindow, timeService: T | @@ -215,15 +226,7 @@ export function initModelFromDefaultTimewindow(value: Timewindow, timeService: T | ||
215 | model.hideAggregation = value.hideAggregation; | 226 | model.hideAggregation = value.hideAggregation; |
216 | model.hideAggInterval = value.hideAggInterval; | 227 | model.hideAggInterval = value.hideAggInterval; |
217 | model.hideTimezone = value.hideTimezone; | 228 | model.hideTimezone = value.hideTimezone; |
218 | - if (isUndefined(value.selectedTab)) { | ||
219 | - if (value.realtime) { | ||
220 | - model.selectedTab = TimewindowType.REALTIME; | ||
221 | - } else { | ||
222 | - model.selectedTab = TimewindowType.HISTORY; | ||
223 | - } | ||
224 | - } else { | ||
225 | - model.selectedTab = value.selectedTab; | ||
226 | - } | 229 | + model.selectedTab = getTimewindowType(value); |
227 | if (model.selectedTab === TimewindowType.REALTIME) { | 230 | if (model.selectedTab === TimewindowType.REALTIME) { |
228 | if (isDefined(value.realtime.interval)) { | 231 | if (isDefined(value.realtime.interval)) { |
229 | model.realtime.interval = value.realtime.interval; | 232 | model.realtime.interval = value.realtime.interval; |
@@ -318,6 +321,15 @@ export function toHistoryTimewindow(timewindow: Timewindow, startTimeMs: number, | @@ -318,6 +321,15 @@ export function toHistoryTimewindow(timewindow: Timewindow, startTimeMs: number, | ||
318 | return historyTimewindow; | 321 | return historyTimewindow; |
319 | } | 322 | } |
320 | 323 | ||
324 | +export function timewindowTypeChanged(newTimewindow: Timewindow, oldTimewindow: Timewindow): boolean { | ||
325 | + if (!newTimewindow || !oldTimewindow) { | ||
326 | + return false; | ||
327 | + } | ||
328 | + const newType = getTimewindowType(newTimewindow); | ||
329 | + const oldType = getTimewindowType(oldTimewindow); | ||
330 | + return newType !== oldType; | ||
331 | +} | ||
332 | + | ||
321 | export function calculateTsOffset(timezone?: string): number { | 333 | export function calculateTsOffset(timezone?: string): number { |
322 | if (timezone) { | 334 | if (timezone) { |
323 | const tz = getTimezone(timezone); | 335 | const tz = getTimezone(timezone); |
@@ -328,6 +340,10 @@ export function calculateTsOffset(timezone?: string): number { | @@ -328,6 +340,10 @@ export function calculateTsOffset(timezone?: string): number { | ||
328 | } | 340 | } |
329 | } | 341 | } |
330 | 342 | ||
343 | +export function isHistoryTypeTimewindow(timewindow: Timewindow): boolean { | ||
344 | + return getTimewindowType(timewindow) === TimewindowType.HISTORY; | ||
345 | +} | ||
346 | + | ||
331 | export function createSubscriptionTimewindow(timewindow: Timewindow, stDiff: number, stateData: boolean, | 347 | export function createSubscriptionTimewindow(timewindow: Timewindow, stDiff: number, stateData: boolean, |
332 | timeService: TimeService): SubscriptionTimewindow { | 348 | timeService: TimeService): SubscriptionTimewindow { |
333 | const subscriptionTimewindow: SubscriptionTimewindow = { | 349 | const subscriptionTimewindow: SubscriptionTimewindow = { |
@@ -352,10 +368,7 @@ export function createSubscriptionTimewindow(timewindow: Timewindow, stDiff: num | @@ -352,10 +368,7 @@ export function createSubscriptionTimewindow(timewindow: Timewindow, stDiff: num | ||
352 | limit: timewindow.aggregation.limit || timeService.getMaxDatapointsLimit() | 368 | limit: timewindow.aggregation.limit || timeService.getMaxDatapointsLimit() |
353 | }; | 369 | }; |
354 | } | 370 | } |
355 | - let selectedTab = timewindow.selectedTab; | ||
356 | - if (isUndefined(selectedTab)) { | ||
357 | - selectedTab = isDefined(timewindow.realtime) ? TimewindowType.REALTIME : TimewindowType.HISTORY; | ||
358 | - } | 371 | + const selectedTab = getTimewindowType(timewindow); |
359 | if (selectedTab === TimewindowType.REALTIME) { | 372 | if (selectedTab === TimewindowType.REALTIME) { |
360 | let realtimeType = timewindow.realtime.realtimeType; | 373 | let realtimeType = timewindow.realtime.realtimeType; |
361 | if (isUndefined(realtimeType)) { | 374 | if (isUndefined(realtimeType)) { |
@@ -553,22 +566,109 @@ export function quickTimeIntervalPeriod(interval: QuickTimeInterval): number { | @@ -553,22 +566,109 @@ export function quickTimeIntervalPeriod(interval: QuickTimeInterval): number { | ||
553 | } | 566 | } |
554 | } | 567 | } |
555 | 568 | ||
569 | +export function calculateIntervalComparisonStartTime(interval: QuickTimeInterval, | ||
570 | + currentDate: moment_.Moment): number { | ||
571 | + switch (interval) { | ||
572 | + case QuickTimeInterval.YESTERDAY: | ||
573 | + case QuickTimeInterval.DAY_BEFORE_YESTERDAY: | ||
574 | + case QuickTimeInterval.CURRENT_DAY: | ||
575 | + case QuickTimeInterval.CURRENT_DAY_SO_FAR: | ||
576 | + currentDate.subtract(1, 'days'); | ||
577 | + return currentDate.startOf('day').valueOf(); | ||
578 | + case QuickTimeInterval.THIS_DAY_LAST_WEEK: | ||
579 | + currentDate.subtract(1, 'weeks'); | ||
580 | + return currentDate.startOf('day').valueOf(); | ||
581 | + case QuickTimeInterval.PREVIOUS_WEEK: | ||
582 | + case QuickTimeInterval.CURRENT_WEEK: | ||
583 | + case QuickTimeInterval.CURRENT_WEEK_SO_FAR: | ||
584 | + currentDate.subtract(1, 'weeks'); | ||
585 | + return currentDate.startOf('week').valueOf(); | ||
586 | + case QuickTimeInterval.PREVIOUS_MONTH: | ||
587 | + case QuickTimeInterval.CURRENT_MONTH: | ||
588 | + case QuickTimeInterval.CURRENT_MONTH_SO_FAR: | ||
589 | + currentDate.subtract(1, 'months'); | ||
590 | + return currentDate.startOf('month').valueOf(); | ||
591 | + case QuickTimeInterval.PREVIOUS_YEAR: | ||
592 | + case QuickTimeInterval.CURRENT_YEAR: | ||
593 | + case QuickTimeInterval.CURRENT_YEAR_SO_FAR: | ||
594 | + currentDate.subtract(1, 'years'); | ||
595 | + return currentDate.startOf('year').valueOf(); | ||
596 | + case QuickTimeInterval.CURRENT_HOUR: | ||
597 | + currentDate.subtract(1, 'hour'); | ||
598 | + return currentDate.startOf('hour').valueOf(); | ||
599 | + } | ||
600 | +} | ||
601 | + | ||
602 | +export function calculateIntervalComparisonEndTime(interval: QuickTimeInterval, | ||
603 | + currentDate: moment_.Moment): number { | ||
604 | + switch (interval) { | ||
605 | + case QuickTimeInterval.YESTERDAY: | ||
606 | + case QuickTimeInterval.DAY_BEFORE_YESTERDAY: | ||
607 | + case QuickTimeInterval.CURRENT_DAY: | ||
608 | + currentDate.subtract(1, 'days'); | ||
609 | + return currentDate.endOf('day').valueOf(); | ||
610 | + case QuickTimeInterval.CURRENT_DAY_SO_FAR: | ||
611 | + return currentDate.subtract(1, 'days').valueOf(); | ||
612 | + case QuickTimeInterval.THIS_DAY_LAST_WEEK: | ||
613 | + currentDate.subtract(1, 'weeks'); | ||
614 | + return currentDate.endOf('day').valueOf(); | ||
615 | + case QuickTimeInterval.PREVIOUS_WEEK: | ||
616 | + case QuickTimeInterval.CURRENT_WEEK: | ||
617 | + currentDate.subtract(1, 'weeks'); | ||
618 | + return currentDate.endOf('week').valueOf(); | ||
619 | + case QuickTimeInterval.CURRENT_WEEK_SO_FAR: | ||
620 | + return currentDate.subtract(1, 'week').valueOf(); | ||
621 | + case QuickTimeInterval.PREVIOUS_MONTH: | ||
622 | + case QuickTimeInterval.CURRENT_MONTH: | ||
623 | + currentDate.subtract(1, 'months'); | ||
624 | + return currentDate.endOf('month').valueOf(); | ||
625 | + case QuickTimeInterval.CURRENT_MONTH_SO_FAR: | ||
626 | + return currentDate.subtract(1, 'month').valueOf(); | ||
627 | + case QuickTimeInterval.PREVIOUS_YEAR: | ||
628 | + case QuickTimeInterval.CURRENT_YEAR: | ||
629 | + currentDate.subtract(1, 'years'); | ||
630 | + return currentDate.endOf('year').valueOf(); | ||
631 | + case QuickTimeInterval.CURRENT_YEAR_SO_FAR: | ||
632 | + return currentDate.subtract(1, 'year').valueOf(); | ||
633 | + case QuickTimeInterval.CURRENT_HOUR: | ||
634 | + currentDate.subtract(1, 'hour'); | ||
635 | + return currentDate.endOf('hour').valueOf(); | ||
636 | + } | ||
637 | +} | ||
638 | + | ||
556 | export function createTimewindowForComparison(subscriptionTimewindow: SubscriptionTimewindow, | 639 | export function createTimewindowForComparison(subscriptionTimewindow: SubscriptionTimewindow, |
557 | - timeUnit: moment_.unitOfTime.DurationConstructor): SubscriptionTimewindow { | 640 | + timeUnit: ComparisonDuration): SubscriptionTimewindow { |
558 | const timewindowForComparison: SubscriptionTimewindow = { | 641 | const timewindowForComparison: SubscriptionTimewindow = { |
559 | fixedWindow: null, | 642 | fixedWindow: null, |
560 | realtimeWindowMs: null, | 643 | realtimeWindowMs: null, |
561 | - aggregation: subscriptionTimewindow.aggregation | 644 | + aggregation: subscriptionTimewindow.aggregation, |
645 | + tsOffset: subscriptionTimewindow.tsOffset | ||
562 | }; | 646 | }; |
563 | 647 | ||
564 | - if (subscriptionTimewindow.realtimeWindowMs) { | ||
565 | - timewindowForComparison.startTs = moment(subscriptionTimewindow.startTs).subtract(1, timeUnit).valueOf(); | ||
566 | - timewindowForComparison.realtimeWindowMs = subscriptionTimewindow.realtimeWindowMs; | ||
567 | - } else if (subscriptionTimewindow.fixedWindow) { | ||
568 | - const timeInterval = subscriptionTimewindow.fixedWindow.endTimeMs - subscriptionTimewindow.fixedWindow.startTimeMs; | ||
569 | - const endTimeMs = moment(subscriptionTimewindow.fixedWindow.endTimeMs).subtract(1, timeUnit).valueOf(); | ||
570 | - | ||
571 | - timewindowForComparison.startTs = endTimeMs - timeInterval; | 648 | + if (subscriptionTimewindow.fixedWindow) { |
649 | + let startTimeMs; | ||
650 | + let endTimeMs; | ||
651 | + if (timeUnit === 'previousInterval') { | ||
652 | + if (subscriptionTimewindow.quickInterval) { | ||
653 | + const startDate = moment(subscriptionTimewindow.fixedWindow.startTimeMs); | ||
654 | + const endDate = moment(subscriptionTimewindow.fixedWindow.endTimeMs); | ||
655 | + if (subscriptionTimewindow.timezone) { | ||
656 | + startDate.tz(subscriptionTimewindow.timezone); | ||
657 | + endDate.tz(subscriptionTimewindow.timezone); | ||
658 | + } | ||
659 | + startTimeMs = calculateIntervalComparisonStartTime(subscriptionTimewindow.quickInterval, startDate); | ||
660 | + endTimeMs = calculateIntervalComparisonEndTime(subscriptionTimewindow.quickInterval, endDate); | ||
661 | + } else { | ||
662 | + const timeInterval = subscriptionTimewindow.fixedWindow.endTimeMs - subscriptionTimewindow.fixedWindow.startTimeMs; | ||
663 | + endTimeMs = subscriptionTimewindow.fixedWindow.startTimeMs; | ||
664 | + startTimeMs = endTimeMs - timeInterval; | ||
665 | + } | ||
666 | + } else { | ||
667 | + const timeInterval = subscriptionTimewindow.fixedWindow.endTimeMs - subscriptionTimewindow.fixedWindow.startTimeMs; | ||
668 | + endTimeMs = moment(subscriptionTimewindow.fixedWindow.endTimeMs).subtract(1, timeUnit).valueOf(); | ||
669 | + startTimeMs = endTimeMs - timeInterval; | ||
670 | + } | ||
671 | + timewindowForComparison.startTs = startTimeMs; | ||
572 | timewindowForComparison.fixedWindow = { | 672 | timewindowForComparison.fixedWindow = { |
573 | startTimeMs: timewindowForComparison.startTs, | 673 | startTimeMs: timewindowForComparison.startTs, |
574 | endTimeMs | 674 | endTimeMs |
@@ -797,3 +897,7 @@ export function getCurrentTime(tz?: string): moment_.Moment { | @@ -797,3 +897,7 @@ export function getCurrentTime(tz?: string): moment_.Moment { | ||
797 | export function getTimezone(tz: string): moment_.Moment { | 897 | export function getTimezone(tz: string): moment_.Moment { |
798 | return moment.tz(tz); | 898 | return moment.tz(tz); |
799 | } | 899 | } |
900 | + | ||
901 | +export function getCurrentTimeForComparison(timeForComparison: moment_.unitOfTime.DurationConstructor, tz?: string): moment_.Moment { | ||
902 | + return getCurrentTime(tz).subtract(1, timeForComparison); | ||
903 | +} |
@@ -1798,6 +1798,7 @@ | @@ -1798,6 +1798,7 @@ | ||
1798 | "avg": "avg", | 1798 | "avg": "avg", |
1799 | "total": "total", | 1799 | "total": "total", |
1800 | "comparison-time-ago": { | 1800 | "comparison-time-ago": { |
1801 | + "previousInterval": "(previous interval)", | ||
1801 | "days": "(day ago)", | 1802 | "days": "(day ago)", |
1802 | "weeks": "(week ago)", | 1803 | "weeks": "(week ago)", |
1803 | "months": "(month ago)", | 1804 | "months": "(month ago)", |