@c8y/ngx-components 1024.1.8 → 1024.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/fesm2022/c8y-ngx-components-bookmarks.mjs +33 -23
  2. package/fesm2022/c8y-ngx-components-bookmarks.mjs.map +1 -1
  3. package/fesm2022/c8y-ngx-components-context-dashboard.mjs +2 -2
  4. package/fesm2022/c8y-ngx-components-context-dashboard.mjs.map +1 -1
  5. package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs +65 -25
  6. package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs.map +1 -1
  7. package/fesm2022/c8y-ngx-components-datapoint-selector.mjs +363 -38
  8. package/fesm2022/c8y-ngx-components-datapoint-selector.mjs.map +1 -1
  9. package/fesm2022/c8y-ngx-components-device-profile.mjs +27 -9
  10. package/fesm2022/c8y-ngx-components-device-profile.mjs.map +1 -1
  11. package/fesm2022/c8y-ngx-components-echart-models.mjs.map +1 -1
  12. package/fesm2022/c8y-ngx-components-echart.mjs +796 -123
  13. package/fesm2022/c8y-ngx-components-echart.mjs.map +1 -1
  14. package/fesm2022/c8y-ngx-components-global-context.mjs +391 -54
  15. package/fesm2022/c8y-ngx-components-global-context.mjs.map +1 -1
  16. package/fesm2022/c8y-ngx-components-protocol-opcua.mjs +9 -11
  17. package/fesm2022/c8y-ngx-components-protocol-opcua.mjs.map +1 -1
  18. package/fesm2022/c8y-ngx-components-remote-access-data.mjs +43 -0
  19. package/fesm2022/c8y-ngx-components-remote-access-data.mjs.map +1 -1
  20. package/fesm2022/c8y-ngx-components-remote-access-ssh-remote-access-ssh-endpoint-modal.mjs +17 -3
  21. package/fesm2022/c8y-ngx-components-remote-access-ssh-remote-access-ssh-endpoint-modal.mjs.map +1 -1
  22. package/fesm2022/c8y-ngx-components-remote-access-terminal-viewer.mjs +179 -41
  23. package/fesm2022/c8y-ngx-components-remote-access-terminal-viewer.mjs.map +1 -1
  24. package/fesm2022/c8y-ngx-components-repository-firmware.mjs +5 -4
  25. package/fesm2022/c8y-ngx-components-repository-firmware.mjs.map +1 -1
  26. package/fesm2022/c8y-ngx-components-repository-software.mjs +10 -4
  27. package/fesm2022/c8y-ngx-components-repository-software.mjs.map +1 -1
  28. package/fesm2022/c8y-ngx-components-time-context.mjs +146 -20
  29. package/fesm2022/c8y-ngx-components-time-context.mjs.map +1 -1
  30. package/fesm2022/c8y-ngx-components-trusted-certificates.mjs +5 -4
  31. package/fesm2022/c8y-ngx-components-trusted-certificates.mjs.map +1 -1
  32. package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs +6 -5
  33. package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs.map +1 -1
  34. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs +198 -24
  35. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs.map +1 -1
  36. package/fesm2022/c8y-ngx-components.mjs +109 -36
  37. package/fesm2022/c8y-ngx-components.mjs.map +1 -1
  38. package/locales/de.po +141 -13
  39. package/locales/es.po +141 -13
  40. package/locales/fr.po +141 -13
  41. package/locales/ja_JP.po +140 -14
  42. package/locales/ko.po +141 -13
  43. package/locales/locales.pot +139 -11
  44. package/locales/nl.po +141 -13
  45. package/locales/pl.po +141 -13
  46. package/locales/pt_BR.po +141 -13
  47. package/locales/zh_CN.po +141 -13
  48. package/locales/zh_TW.po +141 -13
  49. package/package.json +1 -1
  50. package/types/c8y-ngx-components-bookmarks.d.ts +7 -7
  51. package/types/c8y-ngx-components-bookmarks.d.ts.map +1 -1
  52. package/types/c8y-ngx-components-datapoint-explorer-view.d.ts +4 -1
  53. package/types/c8y-ngx-components-datapoint-explorer-view.d.ts.map +1 -1
  54. package/types/c8y-ngx-components-datapoint-selector.d.ts +93 -5
  55. package/types/c8y-ngx-components-datapoint-selector.d.ts.map +1 -1
  56. package/types/c8y-ngx-components-device-profile.d.ts +5 -2
  57. package/types/c8y-ngx-components-device-profile.d.ts.map +1 -1
  58. package/types/c8y-ngx-components-echart-models.d.ts +25 -3
  59. package/types/c8y-ngx-components-echart-models.d.ts.map +1 -1
  60. package/types/c8y-ngx-components-echart.d.ts +65 -5
  61. package/types/c8y-ngx-components-echart.d.ts.map +1 -1
  62. package/types/c8y-ngx-components-global-context.d.ts +187 -7
  63. package/types/c8y-ngx-components-global-context.d.ts.map +1 -1
  64. package/types/c8y-ngx-components-protocol-opcua.d.ts.map +1 -1
  65. package/types/c8y-ngx-components-remote-access-data.d.ts +19 -0
  66. package/types/c8y-ngx-components-remote-access-data.d.ts.map +1 -1
  67. package/types/c8y-ngx-components-remote-access-ssh-remote-access-ssh-endpoint-modal.d.ts +10 -3
  68. package/types/c8y-ngx-components-remote-access-ssh-remote-access-ssh-endpoint-modal.d.ts.map +1 -1
  69. package/types/c8y-ngx-components-remote-access-terminal-viewer.d.ts +20 -2
  70. package/types/c8y-ngx-components-remote-access-terminal-viewer.d.ts.map +1 -1
  71. package/types/c8y-ngx-components-repository-firmware.d.ts.map +1 -1
  72. package/types/c8y-ngx-components-repository-software.d.ts +2 -0
  73. package/types/c8y-ngx-components-repository-software.d.ts.map +1 -1
  74. package/types/c8y-ngx-components-time-context.d.ts +50 -8
  75. package/types/c8y-ngx-components-time-context.d.ts.map +1 -1
  76. package/types/c8y-ngx-components-trusted-certificates.d.ts.map +1 -1
  77. package/types/c8y-ngx-components-widgets-implementations-alarms.d.ts +1 -0
  78. package/types/c8y-ngx-components-widgets-implementations-alarms.d.ts.map +1 -1
  79. package/types/c8y-ngx-components-widgets-implementations-asset-table.d.ts.map +1 -1
  80. package/types/c8y-ngx-components-widgets-implementations-datapoints-graph.d.ts +25 -0
  81. package/types/c8y-ngx-components-widgets-implementations-datapoints-graph.d.ts.map +1 -1
  82. package/types/c8y-ngx-components-widgets-implementations-datapoints-list.d.ts +1 -0
  83. package/types/c8y-ngx-components-widgets-implementations-datapoints-list.d.ts.map +1 -1
  84. package/types/c8y-ngx-components-widgets-implementations-scada.d.ts +2 -0
  85. package/types/c8y-ngx-components-widgets-implementations-scada.d.ts.map +1 -1
  86. package/types/c8y-ngx-components.d.ts +55 -12
  87. package/types/c8y-ngx-components.d.ts.map +1 -1
@@ -1,18 +1,21 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, inject, DestroyRef, model, ViewChild, Input, Component } from '@angular/core';
2
+ import { Injectable, inject, DestroyRef, signal, model, ViewChild, Input, Component } from '@angular/core';
3
3
  import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
4
  import * as i3 from '@angular/forms';
5
5
  import { FormBuilder } from '@angular/forms';
6
6
  import * as i1 from '@c8y/ngx-components';
7
7
  import { AGGREGATION_LIMITS, CoreModule, DateTimePickerModule, AggregationPickerComponent } from '@c8y/ngx-components';
8
- import { RealtimeControlComponent } from '@c8y/ngx-components/global-context';
8
+ import { TimeSeriesMigrationService, AUTO_AGGREGATION_DATAPOINTS, AGGREGATION_POPOVER_TEXT, TIMING, RealtimeControlComponent } from '@c8y/ngx-components/global-context';
9
9
  import { INTERVALS, TimeSpanInMs, INTERVAL_TITLES, IntervalPickerComponent } from '@c8y/ngx-components/interval-picker';
10
+ import { gettext } from '@c8y/ngx-components/gettext';
10
11
  import { BsDatepickerModule } from 'ngx-bootstrap/datepicker';
11
12
  import * as i4 from 'ngx-bootstrap/dropdown';
12
13
  import { BsDropdownModule, BsDropdownDirective } from 'ngx-bootstrap/dropdown';
13
14
  import * as i5 from 'ngx-bootstrap/tooltip';
14
15
  import { TooltipModule } from 'ngx-bootstrap/tooltip';
15
- import { interval } from 'rxjs';
16
+ import * as i6 from 'ngx-bootstrap/popover';
17
+ import { PopoverModule } from 'ngx-bootstrap/popover';
18
+ import { debounceTime, interval } from 'rxjs';
16
19
  import { aggregationType } from '@c8y/client';
17
20
  import * as i2 from '@angular/common';
18
21
 
@@ -98,6 +101,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
98
101
  // TODO: REMOVE THIS FILE
99
102
  class TimeContextComponent {
100
103
  #destroyRef;
104
+ #timeSeriesMigrationService;
101
105
  constructor(widgetTimeContextDateRangeService) {
102
106
  this.widgetTimeContextDateRangeService = widgetTimeContextDateRangeService;
103
107
  this.timeContext = {};
@@ -106,13 +110,27 @@ class TimeContextComponent {
106
110
  showSeconds: false,
107
111
  showSpinners: false
108
112
  };
113
+ this.enableAutoAggregation = false;
109
114
  this.datapointExplorerService = inject(DatapointExplorerService);
110
115
  this.formBuilder = inject(FormBuilder);
111
116
  this.#destroyRef = inject(DestroyRef);
117
+ this.#timeSeriesMigrationService = inject(TimeSeriesMigrationService);
112
118
  this.DATE_FORMAT = 'short';
113
119
  this.INTERVAL_TITLES = INTERVAL_TITLES;
114
120
  this.REALTIME_INTERVAL = 1000;
121
+ this.AUTO_AGGREGATION_DATAPOINTS = AUTO_AGGREGATION_DATAPOINTS;
122
+ this.AGGREGATION_POPOVER = AGGREGATION_POPOVER_TEXT;
123
+ this.KEEP_DATA_ON_ZOOM_IN_POPOVER = gettext('When enabled, the chart reloads data at a finer or coarser interval as you zoom in or out, so it always shows the number of points you set. When disabled, it reuses the already loaded data.');
124
+ /** Whether auto-aggregation mode is active. */
125
+ this.isAutoModeActive = signal(false, ...(ngDevMode ? [{ debugName: "isAutoModeActive" }] : /* istanbul ignore next */ []));
126
+ /**
127
+ * The "Auto" aggregation option requires the tenant to be migrated to time series
128
+ * (auto mode uses `aggregationInterval`, unsupported on non-migrated tenants).
129
+ */
130
+ this.isTimeSeriesMigrated = signal(false, ...(ngDevMode ? [{ debugName: "isTimeSeriesMigrated" }] : /* istanbul ignore next */ []));
115
131
  this.form = this.createForm(this.datapointExplorerService.getDefaultContext());
132
+ /** Last datapoints value applied to the context; restored when the field is left empty. */
133
+ this.lastAppliedDatapoints = AUTO_AGGREGATION_DATAPOINTS.DEFAULT;
116
134
  this.valuesSignal = toSignal(this.form.controls.currentDateContextFromDate.valueChanges, {
117
135
  initialValue: this.form.controls.currentDateContextFromDate.value
118
136
  });
@@ -123,9 +141,14 @@ class TimeContextComponent {
123
141
  const context = this.datapointExplorerService.getDefaultContext(this.timeContext);
124
142
  const { disabledAggregations } = this.datapointExplorerService.calculateAggregation(context.date, context.aggregation);
125
143
  this.disabledAggregations = disabledAggregations;
144
+ this.#timeSeriesMigrationService
145
+ .isTimeSeriesMigrated()
146
+ .then(isMigrated => this.isTimeSeriesMigrated.set(isMigrated));
126
147
  this.subscribeToIntervalChange();
127
148
  this.subscribeToRealtimeChange();
128
149
  this.subscribeToAggregationChange();
150
+ this.subscribeToDatapointsChange();
151
+ this.subscribeToKeepDataOnZoomInChange();
129
152
  }
130
153
  ngOnChanges(changes) {
131
154
  if (changes.changedDateContext && changes.changedDateContext.currentValue) {
@@ -141,23 +164,42 @@ class TimeContextComponent {
141
164
  newDateTo !== currentFormValues.currentDateContextToDate ||
142
165
  this.changedDateContext.interval !== currentFormValues.currentDateContextInterval ||
143
166
  this.changedDateContext.realtime !== currentFormValues.realtime ||
144
- this.changedDateContext.aggregation !== currentFormValues.aggregation;
167
+ this.changedDateContext.aggregation !== currentFormValues.aggregation ||
168
+ !!this.changedDateContext.autoAggregation !== currentFormValues.autoAggregationEnabled;
145
169
  if (!hasActualChanges) {
146
170
  return;
147
171
  }
148
172
  // Don't emit when update comes from parent (avoid infinite loop)
173
+ const incomingAutoAggregation = this.changedDateContext.autoAggregation ?? null;
174
+ this.isAutoModeActive.set(!!incomingAutoAggregation);
149
175
  this.update({
150
176
  date: [this.changedDateContext.dateFrom, this.changedDateContext.dateTo],
151
177
  interval: this.changedDateContext.interval,
152
178
  realtime: this.changedDateContext.realtime || false,
153
- aggregation: this.changedDateContext.aggregation
179
+ aggregation: incomingAutoAggregation ? null : this.changedDateContext.aggregation,
180
+ autoAggregation: incomingAutoAggregation
154
181
  }, false);
155
182
  if (this.changedDateContext.realtime) {
156
183
  this.form.controls.aggregation.disable();
157
184
  }
158
185
  }
159
186
  }
187
+ /** Called by the aggregation picker's (autoModeChange) output. */
188
+ onAutoModeChange(isAuto) {
189
+ this.isAutoModeActive.set(isAuto);
190
+ this.update({
191
+ date: [
192
+ new Date(this.form.value.currentDateContextFromDate),
193
+ new Date(this.form.value.currentDateContextToDate)
194
+ ],
195
+ interval: this.form.value.currentDateContextInterval,
196
+ realtime: this.form.value.realtime,
197
+ aggregation: isAuto ? null : this.form.value.aggregation,
198
+ autoAggregation: isAuto ? this.buildAutoAggregationConfig() : null
199
+ });
200
+ }
160
201
  applyDatetimeContext() {
202
+ const isAuto = this.isAutoModeActive();
161
203
  this.update({
162
204
  date: [
163
205
  new Date(this.form.controls.temporaryUserSelectedFromDate.value),
@@ -165,7 +207,8 @@ class TimeContextComponent {
165
207
  ],
166
208
  interval: 'custom',
167
209
  realtime: this.form.value.realtime,
168
- aggregation: this.form.value.aggregation
210
+ aggregation: isAuto ? null : this.form.value.aggregation,
211
+ autoAggregation: isAuto ? this.buildAutoAggregationConfig() : null
169
212
  });
170
213
  }
171
214
  stopRealtime() {
@@ -202,7 +245,8 @@ class TimeContextComponent {
202
245
  date,
203
246
  interval,
204
247
  realtime: this.form.value.realtime,
205
- aggregation: this.form.value.aggregation
248
+ aggregation: this.isAutoModeActive() ? null : this.form.value.aggregation,
249
+ autoAggregation: this.isAutoModeActive() ? this.buildAutoAggregationConfig() : null
206
250
  });
207
251
  });
208
252
  }
@@ -223,6 +267,10 @@ class TimeContextComponent {
223
267
  this.form.controls.aggregation.valueChanges
224
268
  .pipe(takeUntilDestroyed(this.#destroyRef))
225
269
  .subscribe(aggregation => {
270
+ // Skip during auto mode transitions — onAutoModeChange handles the update
271
+ if (this.isAutoModeActive()) {
272
+ return;
273
+ }
226
274
  this.update({
227
275
  date: [
228
276
  new Date(this.form.value.currentDateContextFromDate),
@@ -230,10 +278,73 @@ class TimeContextComponent {
230
278
  ],
231
279
  interval: this.form.value.currentDateContextInterval,
232
280
  realtime: this.form.value.realtime,
233
- aggregation
281
+ aggregation,
282
+ autoAggregation: null
234
283
  });
235
284
  });
236
285
  }
286
+ subscribeToDatapointsChange() {
287
+ this.form.controls.autoAggregationDatapoints.valueChanges
288
+ .pipe(takeUntilDestroyed(this.#destroyRef), debounceTime(TIMING.TYPING_DEBOUNCE))
289
+ .subscribe(datapoints => {
290
+ if (!this.isAutoModeActive()) {
291
+ return;
292
+ }
293
+ // Skip while the field is empty or out of range — the user is still typing. Rewriting
294
+ // or emitting a clamped value here would snap the field back mid-edit;
295
+ // commitDatapoints() (blur) commits a valid value instead.
296
+ if (!this.isValidDatapoints(datapoints)) {
297
+ return;
298
+ }
299
+ this.emitAutoAggregationUpdate();
300
+ });
301
+ }
302
+ isValidDatapoints(value) {
303
+ return (typeof value === 'number' &&
304
+ !Number.isNaN(value) &&
305
+ value >= AUTO_AGGREGATION_DATAPOINTS.MIN &&
306
+ value <= AUTO_AGGREGATION_DATAPOINTS.MAX);
307
+ }
308
+ clampToDatapointsBounds(value) {
309
+ return Math.min(AUTO_AGGREGATION_DATAPOINTS.MAX, Math.max(AUTO_AGGREGATION_DATAPOINTS.MIN, value));
310
+ }
311
+ subscribeToKeepDataOnZoomInChange() {
312
+ this.form.controls.autoAggregationKeepDataOnZoomIn.valueChanges
313
+ .pipe(takeUntilDestroyed(this.#destroyRef))
314
+ .subscribe(() => {
315
+ if (!this.isAutoModeActive()) {
316
+ return;
317
+ }
318
+ this.emitAutoAggregationUpdate();
319
+ });
320
+ }
321
+ emitAutoAggregationUpdate() {
322
+ this.update({
323
+ date: [
324
+ new Date(this.form.value.currentDateContextFromDate),
325
+ new Date(this.form.value.currentDateContextToDate)
326
+ ],
327
+ interval: this.form.value.currentDateContextInterval,
328
+ realtime: this.form.value.realtime,
329
+ aggregation: null,
330
+ autoAggregation: this.buildAutoAggregationConfig()
331
+ });
332
+ }
333
+ /**
334
+ * Builds the auto-aggregation config from the current form state, clamped to the allowed
335
+ * range. Falls back to the last applied value while the field is empty (mid-edit).
336
+ *
337
+ * Reads control values instead of `this.form.value`: a control's valueChanges fires before
338
+ * the parent group recomputes its cached value, so the group value is stale inside the
339
+ * subscriptions that call this method.
340
+ */
341
+ buildAutoAggregationConfig() {
342
+ const datapoints = this.clampToDatapointsBounds(this.form.controls.autoAggregationDatapoints.value ?? this.lastAppliedDatapoints);
343
+ return {
344
+ datapoints,
345
+ keepDataOnZoomIn: this.form.controls.autoAggregationKeepDataOnZoomIn.value ?? true
346
+ };
347
+ }
237
348
  onRealtimeValueChange(realtime) {
238
349
  let dateTimeContext;
239
350
  if (this.form.value.currentDateContextInterval !== 'custom') {
@@ -246,11 +357,13 @@ class TimeContextComponent {
246
357
  const dateFrom = new Date(dateTo.valueOf() - currentTimeSpanInMs);
247
358
  dateTimeContext = [dateFrom, dateTo];
248
359
  }
360
+ this.isAutoModeActive.set(false);
249
361
  this.update({
250
362
  date: dateTimeContext,
251
363
  interval: this.form.value.currentDateContextInterval,
252
364
  realtime,
253
- aggregation: null
365
+ aggregation: null,
366
+ autoAggregation: null
254
367
  });
255
368
  }
256
369
  startRealtime() {
@@ -274,10 +387,10 @@ class TimeContextComponent {
274
387
  }, false); // Don't emit during automatic realtime ticks
275
388
  });
276
389
  }
277
- update({ date, interval, realtime, aggregation }, shouldEmit = true) {
278
- const { selectedAggregation, disabledAggregations } = this.datapointExplorerService.calculateAggregation(date, aggregation);
390
+ update({ date, interval, realtime, aggregation, autoAggregation = null }, shouldEmit = true) {
391
+ const { selectedAggregation, disabledAggregations } = this.datapointExplorerService.calculateAggregation(date, autoAggregation ? null : aggregation);
279
392
  this.disabledAggregations = disabledAggregations;
280
- this.updateFormValues({ date, interval, realtime, aggregation: selectedAggregation }, shouldEmit);
393
+ this.updateFormValues({ date, interval, realtime, aggregation: selectedAggregation, autoAggregation }, shouldEmit);
281
394
  }
282
395
  createForm(context) {
283
396
  return this.formBuilder.group({
@@ -287,10 +400,13 @@ class TimeContextComponent {
287
400
  currentDateContextToDate: context.date[1].toISOString(),
288
401
  currentDateContextInterval: context.interval || 'custom',
289
402
  realtime: context.realtime,
290
- aggregation: context.aggregation
403
+ aggregation: context.aggregation,
404
+ autoAggregationEnabled: false,
405
+ autoAggregationDatapoints: AUTO_AGGREGATION_DATAPOINTS.DEFAULT,
406
+ autoAggregationKeepDataOnZoomIn: true
291
407
  });
292
408
  }
293
- updateFormValues({ date, interval, realtime, aggregation }, shouldEmit = true) {
409
+ updateFormValues({ date, interval, realtime, aggregation, autoAggregation = null }, shouldEmit = true) {
294
410
  const newFormValues = {
295
411
  temporaryUserSelectedFromDate: date[0].toISOString(),
296
412
  temporaryUserSelectedToDate: date[1].toISOString(),
@@ -298,17 +414,24 @@ class TimeContextComponent {
298
414
  currentDateContextToDate: date[1].toISOString(),
299
415
  realtime,
300
416
  currentDateContextInterval: interval || 'custom',
301
- aggregation: aggregation || null
417
+ aggregation: autoAggregation ? null : aggregation || null,
418
+ autoAggregation
302
419
  };
303
420
  if (shouldEmit) {
304
421
  this.context.set(newFormValues);
305
422
  }
306
- this.form.patchValue(newFormValues, {
307
- emitEvent: false
308
- });
423
+ if (autoAggregation?.datapoints != null) {
424
+ this.lastAppliedDatapoints = this.clampToDatapointsBounds(autoAggregation.datapoints);
425
+ }
426
+ this.form.patchValue({
427
+ ...newFormValues,
428
+ autoAggregationEnabled: !!autoAggregation,
429
+ autoAggregationDatapoints: autoAggregation?.datapoints ?? this.form.value.autoAggregationDatapoints,
430
+ autoAggregationKeepDataOnZoomIn: autoAggregation?.keepDataOnZoomIn ?? this.form.value.autoAggregationKeepDataOnZoomIn
431
+ }, { emitEvent: false });
309
432
  }
310
433
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: TimeContextComponent, deps: [{ token: i1.WidgetTimeContextDateRangeService }], target: i0.ɵɵFactoryTarget.Component }); }
311
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: TimeContextComponent, isStandalone: true, selector: "c8y-time-context", inputs: { changedDateContext: { classPropertyName: "changedDateContext", publicName: "changedDateContext", isSignal: false, isRequired: false, transformFunction: null }, controlsAvailable: { classPropertyName: "controlsAvailable", publicName: "controlsAvailable", isSignal: false, isRequired: false, transformFunction: null }, timeContext: { classPropertyName: "timeContext", publicName: "timeContext", isSignal: false, isRequired: false, transformFunction: null }, timePickerConfig: { classPropertyName: "timePickerConfig", publicName: "timePickerConfig", isSignal: false, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { context: "contextChange" }, viewQueries: [{ propertyName: "dropdown", first: true, predicate: BsDropdownDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (controlsAvailable) {\n <ng-container\n [ngTemplateOutlet]=\"dateTimePicker\"\n [ngTemplateOutletContext]=\"{\n date: [form.value.currentDateContextFromDate, form.value.currentDateContextToDate]\n }\"\n ></ng-container>\n} @else {\n <c8y-action-bar-item\n [groupId]=\"'timeContext'\"\n [inGroupPriority]=\"1\"\n [placement]=\"'left'\"\n >\n <ng-container\n [ngTemplateOutlet]=\"dateTimePicker\"\n [ngTemplateOutletContext]=\"{\n date: [form.value.currentDateContextFromDate, form.value.currentDateContextToDate]\n }\"\n ></ng-container>\n </c8y-action-bar-item>\n}\n\n<ng-template\n #dateTimePicker\n let-date=\"date\"\n>\n <form\n class=\"d-flex gap-8 p-l-xs-16 p-r-xs-16 m-t-xs-8 m-b-xs-8\"\n [formGroup]=\"form\"\n >\n <ng-container>\n @if (date) {\n <div\n class=\"dropdown flex-grow\"\n #dropdown=\"bs-dropdown\"\n dropdown\n [insideClick]=\"true\"\n >\n <button\n class=\"dropdown-toggle form-control l-h-tight d-flex a-i-center\"\n attr.aria-label=\"{{ date[0] | c8yDate: DATE_FORMAT }} \u2014 {{\n date[1] | c8yDate: DATE_FORMAT\n }}\"\n tooltip=\"{{ date[0] | c8yDate: DATE_FORMAT }} \u2014 {{ date[1] | c8yDate: DATE_FORMAT }}\"\n placement=\"top\"\n container=\"body\"\n data-cy=\"widget-time-context--date-picker-dropdown-button\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n dropdownToggle\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"schedule1\"\n ></i>\n <div class=\"d-col text-left fit-w\">\n <span\n class=\"text-12\"\n data-cy=\"widget-time-context--selected-interval\"\n >\n {{ INTERVAL_TITLES[form.controls.currentDateContextInterval.value] | translate }}\n </span>\n <span\n class=\"text-10 text-muted text-truncate\"\n data-cy=\"widget-time-context--selected-time-range\"\n >\n {{ date[0] | c8yDate: DATE_FORMAT }} \u2014 {{ date[1] | c8yDate: DATE_FORMAT }}\n </span>\n </div>\n <span class=\"caret m-r-16 m-l-4\"></span>\n </button>\n\n <ul\n class=\"dropdown-menu dropdown-menu-wide dropdown-menu--date-range\"\n *dropdownMenu\n >\n <c8y-interval-picker\n class=\"d-contents\"\n formControlName=\"currentDateContextInterval\"\n ></c8y-interval-picker>\n\n @if (form.controls.currentDateContextInterval.value === 'custom') {\n <div class=\"p-l-16 p-r-16\">\n <c8y-form-group\n [ngClass]=\"form.controls.temporaryUserSelectedFromDate.errors ? 'has-error' : ''\"\n >\n <label\n [title]=\"'From`date`' | translate\"\n for=\"temporaryUserSelectedFromDate\"\n translate\n >\n From`date`\n </label>\n <c8y-date-time-picker\n id=\"temporaryUserSelectedFromDate\"\n [maxDate]=\"form.value.temporaryUserSelectedToDate\"\n [config]=\"timePickerConfig\"\n [placeholder]=\"'From`date`' | translate\"\n [formControl]=\"form.controls.temporaryUserSelectedFromDate\"\n [ngClass]=\"\n form.controls.temporaryUserSelectedFromDate.errors ? 'has-error' : ''\n \"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"form.controls.temporaryUserSelectedFromDate.errors\">\n <c8y-message\n name=\"dateAfterRangeMax\"\n [text]=\"'This date is after the latest allowed date.' | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateTime\"\n [text]=\"'This date is invalid.' | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n\n <c8y-form-group\n [ngClass]=\"form.controls.temporaryUserSelectedToDate.errors ? 'has-error' : ''\"\n >\n <label\n [title]=\"'To`date`' | translate\"\n for=\"temporaryUserSelectedToDate\"\n translate\n >\n To`date`\n </label>\n <c8y-date-time-picker\n id=\"temporaryUserSelectedToDate\"\n [minDate]=\"form.value.temporaryUserSelectedFromDate\"\n [config]=\"timePickerConfig\"\n [placeholder]=\"'To`date`' | translate\"\n [formControl]=\"form.controls.temporaryUserSelectedToDate\"\n [ngClass]=\"form.controls.temporaryUserSelectedToDate.errors ? 'has-error' : ''\"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"form.controls.temporaryUserSelectedToDate.errors\">\n <c8y-message\n name=\"dateBeforeRangeMin\"\n [text]=\"'This date is before the earliest allowed date.' | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateTime\"\n [text]=\"'This date is invalid.' | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n </div>\n\n <div class=\"p-16 d-flex gap-8 separator-top\">\n <button\n class=\"btn btn-default btn-sm flex-grow\"\n title=\"{{ 'Reset' | translate }}\"\n type=\"button\"\n (click)=\"dropdown.isOpen = false\"\n [disabled]=\"form.value.realtime\"\n translate\n >\n Reset\n </button>\n\n <button\n class=\"btn btn-primary btn-sm flex-grow\"\n title=\"{{ 'Apply' | translate }}\"\n type=\"button\"\n (click)=\"applyDatetimeContext(); dropdown.isOpen = false\"\n [disabled]=\"\n (form.pristine && form.untouched) || form.invalid || form.value.realtime\n \"\n translate\n >\n Apply\n </button>\n </div>\n }\n </ul>\n </div>\n }\n </ng-container>\n\n <div class=\"input-group w-auto\">\n <c8y-realtime-control\n class=\"form-control p-0 flex-no-grow w-auto\"\n formControlName=\"realtime\"\n ></c8y-realtime-control>\n\n @if (controlsAvailable ? controlsAvailable.aggregation : true) {\n <c8y-aggregation-picker\n formControlName=\"aggregation\"\n [disabledAggregations]=\"disabledAggregations\"\n ></c8y-aggregation-picker>\n }\n </div>\n </form>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "component", type: i1.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: i1.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i1.MessageDirective, selector: "c8y-message", inputs: ["name", "text"] }, { kind: "component", type: i1.MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage", "additionalMessages"] }, { kind: "component", type: i1.AggregationPickerComponent, selector: "c8y-aggregation-picker", inputs: ["disabledAggregations"] }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i1.DateTimePickerComponent, selector: "c8y-date-time-picker", inputs: ["minDate", "maxDate", "placeholder", "dateInputFormat", "adaptivePosition", "size", "dateType", "config"], outputs: ["onDateSelected"] }, { kind: "ngmodule", type: BsDatepickerModule }, { kind: "ngmodule", type: DateTimePickerModule }, { kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i4.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i4.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i4.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "component", type: IntervalPickerComponent, selector: "c8y-interval-picker", inputs: ["INTERVALS"] }, { kind: "component", type: RealtimeControlComponent, selector: "c8y-realtime-control" }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i1.DatePipe, name: "c8yDate" }] }); }
434
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: TimeContextComponent, isStandalone: true, selector: "c8y-time-context", inputs: { changedDateContext: { classPropertyName: "changedDateContext", publicName: "changedDateContext", isSignal: false, isRequired: false, transformFunction: null }, controlsAvailable: { classPropertyName: "controlsAvailable", publicName: "controlsAvailable", isSignal: false, isRequired: false, transformFunction: null }, timeContext: { classPropertyName: "timeContext", publicName: "timeContext", isSignal: false, isRequired: false, transformFunction: null }, timePickerConfig: { classPropertyName: "timePickerConfig", publicName: "timePickerConfig", isSignal: false, isRequired: false, transformFunction: null }, enableAutoAggregation: { classPropertyName: "enableAutoAggregation", publicName: "enableAutoAggregation", isSignal: false, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { context: "contextChange" }, viewQueries: [{ propertyName: "dropdown", first: true, predicate: BsDropdownDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (controlsAvailable) {\n <ng-container\n [ngTemplateOutlet]=\"dateTimePicker\"\n [ngTemplateOutletContext]=\"{\n date: [form.value.currentDateContextFromDate, form.value.currentDateContextToDate]\n }\"\n ></ng-container>\n} @else {\n <c8y-action-bar-item\n [groupId]=\"'timeContext'\"\n [inGroupPriority]=\"1\"\n [placement]=\"'left'\"\n itemClass=\"navbar-form\"\n >\n <ng-container\n [ngTemplateOutlet]=\"dateTimePicker\"\n [ngTemplateOutletContext]=\"{\n date: [form.value.currentDateContextFromDate, form.value.currentDateContextToDate]\n }\"\n ></ng-container>\n </c8y-action-bar-item>\n}\n\n<ng-template\n #dateTimePicker\n let-date=\"date\"\n>\n <form\n class=\"d-flex gap-8 p-l-xs-16 p-r-xs-16 m-t-xs-8 m-b-xs-8\"\n [formGroup]=\"form\"\n >\n <ng-container>\n @if (date) {\n <div\n class=\"dropdown flex-grow\"\n #dropdown=\"bs-dropdown\"\n dropdown\n [insideClick]=\"true\"\n >\n <button\n class=\"dropdown-toggle form-control l-h-tight d-flex a-i-center\"\n attr.aria-label=\"{{ date[0] | c8yDate: DATE_FORMAT }} \u2014 {{\n date[1] | c8yDate: DATE_FORMAT\n }}\"\n tooltip=\"{{ date[0] | c8yDate: DATE_FORMAT }} \u2014 {{ date[1] | c8yDate: DATE_FORMAT }}\"\n placement=\"top\"\n container=\"body\"\n data-cy=\"widget-time-context--date-picker-dropdown-button\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n dropdownToggle\n >\n <i\n class=\"m-r-8\"\n c8yIcon=\"schedule1\"\n ></i>\n <div class=\"d-col text-left fit-w\">\n <span\n class=\"text-muted fit-w text-10 l-h-1\"\n data-cy=\"widget-time-context--selected-interval\"\n >\n {{ INTERVAL_TITLES[form.controls.currentDateContextInterval.value] | translate }}\n </span>\n <span\n class=\"text-bold text-12 fit-w l-h-1 text-truncate\"\n data-cy=\"widget-time-context--selected-time-range\"\n >\n {{ date[0] | c8yDate: DATE_FORMAT }} \u2014 {{ date[1] | c8yDate: DATE_FORMAT }}\n </span>\n </div>\n <span class=\"caret m-r-16 m-l-4\"></span>\n </button>\n\n <ul\n class=\"dropdown-menu dropdown-menu-wide dropdown-menu--date-range\"\n *dropdownMenu\n >\n <c8y-interval-picker\n class=\"d-contents\"\n formControlName=\"currentDateContextInterval\"\n ></c8y-interval-picker>\n\n @if (form.controls.currentDateContextInterval.value === 'custom') {\n <div class=\"p-l-16 p-r-16\">\n <c8y-form-group\n [ngClass]=\"form.controls.temporaryUserSelectedFromDate.errors ? 'has-error' : ''\"\n >\n <label\n [title]=\"'From`date`' | translate\"\n for=\"temporaryUserSelectedFromDate\"\n translate\n >\n From`date`\n </label>\n <c8y-date-time-picker\n id=\"temporaryUserSelectedFromDate\"\n [maxDate]=\"form.value.temporaryUserSelectedToDate\"\n [config]=\"timePickerConfig\"\n [placeholder]=\"'From`date`' | translate\"\n [formControl]=\"form.controls.temporaryUserSelectedFromDate\"\n [ngClass]=\"\n form.controls.temporaryUserSelectedFromDate.errors ? 'has-error' : ''\n \"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"form.controls.temporaryUserSelectedFromDate.errors\">\n <c8y-message\n name=\"dateAfterRangeMax\"\n [text]=\"'This date is after the latest allowed date.' | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateTime\"\n [text]=\"'This date is invalid.' | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n\n <c8y-form-group\n [ngClass]=\"form.controls.temporaryUserSelectedToDate.errors ? 'has-error' : ''\"\n >\n <label\n [title]=\"'To`date`' | translate\"\n for=\"temporaryUserSelectedToDate\"\n translate\n >\n To`date`\n </label>\n <c8y-date-time-picker\n id=\"temporaryUserSelectedToDate\"\n [minDate]=\"form.value.temporaryUserSelectedFromDate\"\n [config]=\"timePickerConfig\"\n [placeholder]=\"'To`date`' | translate\"\n [formControl]=\"form.controls.temporaryUserSelectedToDate\"\n [ngClass]=\"form.controls.temporaryUserSelectedToDate.errors ? 'has-error' : ''\"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"form.controls.temporaryUserSelectedToDate.errors\">\n <c8y-message\n name=\"dateBeforeRangeMin\"\n [text]=\"'This date is before the earliest allowed date.' | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateTime\"\n [text]=\"'This date is invalid.' | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n </div>\n\n <div class=\"p-16 d-flex gap-8 separator-top\">\n <button\n class=\"btn btn-default btn-sm flex-grow\"\n title=\"{{ 'Reset' | translate }}\"\n type=\"button\"\n (click)=\"dropdown.isOpen = false\"\n [disabled]=\"form.value.realtime\"\n translate\n >\n Reset\n </button>\n\n <button\n class=\"btn btn-primary btn-sm flex-grow\"\n title=\"{{ 'Apply' | translate }}\"\n type=\"button\"\n (click)=\"applyDatetimeContext(); dropdown.isOpen = false\"\n [disabled]=\"\n (form.pristine && form.untouched) || form.invalid || form.value.realtime\n \"\n translate\n >\n Apply\n </button>\n </div>\n }\n </ul>\n </div>\n }\n </ng-container>\n\n <div class=\"input-group w-auto\">\n <c8y-realtime-control\n class=\"form-control p-0 flex-no-grow w-auto\"\n formControlName=\"realtime\"\n ></c8y-realtime-control>\n\n @if (enableAutoAggregation && isTimeSeriesMigrated()) {\n <c8y-aggregation-picker\n formControlName=\"aggregation\"\n [showAutoMode]=\"true\"\n [autoModeActive]=\"isAutoModeActive()\"\n [autoPoints]=\"form.value.autoAggregationDatapoints\"\n [autoKeepPointCount]=\"form.value.autoAggregationKeepDataOnZoomIn\"\n [disabledAggregations]=\"disabledAggregations\"\n (autoModeChange)=\"onAutoModeChange($event)\"\n >\n <div\n class=\"d-col\"\n autoAggregationOptions\n >\n <div class=\"d-flex a-i-center gap-8\">\n <label class=\"m-b-0 m-r-8\">\n {{ 'Points per chart' | translate }}\n </label>\n <input\n class=\"form-control input-sm\"\n style=\"width: 80px\"\n [attr.title]=\"\n 'Enter a value between {{ min }} and {{ max }}.'\n | translate\n : {\n min: AUTO_AGGREGATION_DATAPOINTS.MIN,\n max: AUTO_AGGREGATION_DATAPOINTS.MAX\n }\n \"\n [attr.aria-label]=\"'Points per chart' | translate\"\n type=\"number\"\n [min]=\"AUTO_AGGREGATION_DATAPOINTS.MIN\"\n [max]=\"AUTO_AGGREGATION_DATAPOINTS.MAX\"\n [step]=\"AUTO_AGGREGATION_DATAPOINTS.STEP\"\n [formControl]=\"form.controls.autoAggregationDatapoints\"\n />\n </div>\n <label\n class=\"c8y-switch m-b-0 m-t-8 text-nowrap\"\n [title]=\"'Keep point count on zoom' | translate\"\n >\n <input\n type=\"checkbox\"\n [formControl]=\"form.controls.autoAggregationKeepDataOnZoomIn\"\n data-cy=\"time-context--auto-aggregation-keep-data-on-zoom-in\"\n />\n <span></span>\n <span class=\"text-12\">{{ 'Keep point count on zoom' | translate }}</span>\n <button\n class=\"btn-help btn-help--sm m-l-4\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"KEEP_DATA_ON_ZOOM_IN_POPOVER | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </label>\n </div>\n </c8y-aggregation-picker>\n } @else if (\n enableAutoAggregation || (controlsAvailable ? controlsAvailable.aggregation : true)\n ) {\n <c8y-aggregation-picker\n formControlName=\"aggregation\"\n [disabledAggregations]=\"disabledAggregations\"\n ></c8y-aggregation-picker>\n }\n\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"AGGREGATION_POPOVER | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </form>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "component", type: i1.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.MinValidationDirective, selector: "[min]", inputs: ["min"] }, { kind: "directive", type: i1.MaxValidationDirective, selector: "[max]", inputs: ["max"] }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i3.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "component", type: i1.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i1.MessageDirective, selector: "c8y-message", inputs: ["name", "text"] }, { kind: "component", type: i1.MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage", "additionalMessages"] }, { kind: "component", type: i1.AggregationPickerComponent, selector: "c8y-aggregation-picker", inputs: ["disabledAggregations", "autoPoints", "autoKeepPointCount", "showAutoMode", "autoModeActive"], outputs: ["autoModeChange"] }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i1.DateTimePickerComponent, selector: "c8y-date-time-picker", inputs: ["minDate", "maxDate", "placeholder", "dateInputFormat", "adaptivePosition", "size", "dateType", "config"], outputs: ["onDateSelected"] }, { kind: "ngmodule", type: BsDatepickerModule }, { kind: "ngmodule", type: DateTimePickerModule }, { kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i4.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i4.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i4.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "directive", type: i6.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "component", type: IntervalPickerComponent, selector: "c8y-interval-picker", inputs: ["INTERVALS"] }, { kind: "component", type: RealtimeControlComponent, selector: "c8y-realtime-control" }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i1.DatePipe, name: "c8yDate" }] }); }
312
435
  }
313
436
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: TimeContextComponent, decorators: [{
314
437
  type: Component,
@@ -319,9 +442,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
319
442
  BsDropdownModule,
320
443
  AggregationPickerComponent,
321
444
  TooltipModule,
445
+ PopoverModule,
322
446
  IntervalPickerComponent,
323
447
  RealtimeControlComponent
324
- ], template: "@if (controlsAvailable) {\n <ng-container\n [ngTemplateOutlet]=\"dateTimePicker\"\n [ngTemplateOutletContext]=\"{\n date: [form.value.currentDateContextFromDate, form.value.currentDateContextToDate]\n }\"\n ></ng-container>\n} @else {\n <c8y-action-bar-item\n [groupId]=\"'timeContext'\"\n [inGroupPriority]=\"1\"\n [placement]=\"'left'\"\n >\n <ng-container\n [ngTemplateOutlet]=\"dateTimePicker\"\n [ngTemplateOutletContext]=\"{\n date: [form.value.currentDateContextFromDate, form.value.currentDateContextToDate]\n }\"\n ></ng-container>\n </c8y-action-bar-item>\n}\n\n<ng-template\n #dateTimePicker\n let-date=\"date\"\n>\n <form\n class=\"d-flex gap-8 p-l-xs-16 p-r-xs-16 m-t-xs-8 m-b-xs-8\"\n [formGroup]=\"form\"\n >\n <ng-container>\n @if (date) {\n <div\n class=\"dropdown flex-grow\"\n #dropdown=\"bs-dropdown\"\n dropdown\n [insideClick]=\"true\"\n >\n <button\n class=\"dropdown-toggle form-control l-h-tight d-flex a-i-center\"\n attr.aria-label=\"{{ date[0] | c8yDate: DATE_FORMAT }} \u2014 {{\n date[1] | c8yDate: DATE_FORMAT\n }}\"\n tooltip=\"{{ date[0] | c8yDate: DATE_FORMAT }} \u2014 {{ date[1] | c8yDate: DATE_FORMAT }}\"\n placement=\"top\"\n container=\"body\"\n data-cy=\"widget-time-context--date-picker-dropdown-button\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n dropdownToggle\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"schedule1\"\n ></i>\n <div class=\"d-col text-left fit-w\">\n <span\n class=\"text-12\"\n data-cy=\"widget-time-context--selected-interval\"\n >\n {{ INTERVAL_TITLES[form.controls.currentDateContextInterval.value] | translate }}\n </span>\n <span\n class=\"text-10 text-muted text-truncate\"\n data-cy=\"widget-time-context--selected-time-range\"\n >\n {{ date[0] | c8yDate: DATE_FORMAT }} \u2014 {{ date[1] | c8yDate: DATE_FORMAT }}\n </span>\n </div>\n <span class=\"caret m-r-16 m-l-4\"></span>\n </button>\n\n <ul\n class=\"dropdown-menu dropdown-menu-wide dropdown-menu--date-range\"\n *dropdownMenu\n >\n <c8y-interval-picker\n class=\"d-contents\"\n formControlName=\"currentDateContextInterval\"\n ></c8y-interval-picker>\n\n @if (form.controls.currentDateContextInterval.value === 'custom') {\n <div class=\"p-l-16 p-r-16\">\n <c8y-form-group\n [ngClass]=\"form.controls.temporaryUserSelectedFromDate.errors ? 'has-error' : ''\"\n >\n <label\n [title]=\"'From`date`' | translate\"\n for=\"temporaryUserSelectedFromDate\"\n translate\n >\n From`date`\n </label>\n <c8y-date-time-picker\n id=\"temporaryUserSelectedFromDate\"\n [maxDate]=\"form.value.temporaryUserSelectedToDate\"\n [config]=\"timePickerConfig\"\n [placeholder]=\"'From`date`' | translate\"\n [formControl]=\"form.controls.temporaryUserSelectedFromDate\"\n [ngClass]=\"\n form.controls.temporaryUserSelectedFromDate.errors ? 'has-error' : ''\n \"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"form.controls.temporaryUserSelectedFromDate.errors\">\n <c8y-message\n name=\"dateAfterRangeMax\"\n [text]=\"'This date is after the latest allowed date.' | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateTime\"\n [text]=\"'This date is invalid.' | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n\n <c8y-form-group\n [ngClass]=\"form.controls.temporaryUserSelectedToDate.errors ? 'has-error' : ''\"\n >\n <label\n [title]=\"'To`date`' | translate\"\n for=\"temporaryUserSelectedToDate\"\n translate\n >\n To`date`\n </label>\n <c8y-date-time-picker\n id=\"temporaryUserSelectedToDate\"\n [minDate]=\"form.value.temporaryUserSelectedFromDate\"\n [config]=\"timePickerConfig\"\n [placeholder]=\"'To`date`' | translate\"\n [formControl]=\"form.controls.temporaryUserSelectedToDate\"\n [ngClass]=\"form.controls.temporaryUserSelectedToDate.errors ? 'has-error' : ''\"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"form.controls.temporaryUserSelectedToDate.errors\">\n <c8y-message\n name=\"dateBeforeRangeMin\"\n [text]=\"'This date is before the earliest allowed date.' | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateTime\"\n [text]=\"'This date is invalid.' | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n </div>\n\n <div class=\"p-16 d-flex gap-8 separator-top\">\n <button\n class=\"btn btn-default btn-sm flex-grow\"\n title=\"{{ 'Reset' | translate }}\"\n type=\"button\"\n (click)=\"dropdown.isOpen = false\"\n [disabled]=\"form.value.realtime\"\n translate\n >\n Reset\n </button>\n\n <button\n class=\"btn btn-primary btn-sm flex-grow\"\n title=\"{{ 'Apply' | translate }}\"\n type=\"button\"\n (click)=\"applyDatetimeContext(); dropdown.isOpen = false\"\n [disabled]=\"\n (form.pristine && form.untouched) || form.invalid || form.value.realtime\n \"\n translate\n >\n Apply\n </button>\n </div>\n }\n </ul>\n </div>\n }\n </ng-container>\n\n <div class=\"input-group w-auto\">\n <c8y-realtime-control\n class=\"form-control p-0 flex-no-grow w-auto\"\n formControlName=\"realtime\"\n ></c8y-realtime-control>\n\n @if (controlsAvailable ? controlsAvailable.aggregation : true) {\n <c8y-aggregation-picker\n formControlName=\"aggregation\"\n [disabledAggregations]=\"disabledAggregations\"\n ></c8y-aggregation-picker>\n }\n </div>\n </form>\n</ng-template>\n" }]
448
+ ], template: "@if (controlsAvailable) {\n <ng-container\n [ngTemplateOutlet]=\"dateTimePicker\"\n [ngTemplateOutletContext]=\"{\n date: [form.value.currentDateContextFromDate, form.value.currentDateContextToDate]\n }\"\n ></ng-container>\n} @else {\n <c8y-action-bar-item\n [groupId]=\"'timeContext'\"\n [inGroupPriority]=\"1\"\n [placement]=\"'left'\"\n itemClass=\"navbar-form\"\n >\n <ng-container\n [ngTemplateOutlet]=\"dateTimePicker\"\n [ngTemplateOutletContext]=\"{\n date: [form.value.currentDateContextFromDate, form.value.currentDateContextToDate]\n }\"\n ></ng-container>\n </c8y-action-bar-item>\n}\n\n<ng-template\n #dateTimePicker\n let-date=\"date\"\n>\n <form\n class=\"d-flex gap-8 p-l-xs-16 p-r-xs-16 m-t-xs-8 m-b-xs-8\"\n [formGroup]=\"form\"\n >\n <ng-container>\n @if (date) {\n <div\n class=\"dropdown flex-grow\"\n #dropdown=\"bs-dropdown\"\n dropdown\n [insideClick]=\"true\"\n >\n <button\n class=\"dropdown-toggle form-control l-h-tight d-flex a-i-center\"\n attr.aria-label=\"{{ date[0] | c8yDate: DATE_FORMAT }} \u2014 {{\n date[1] | c8yDate: DATE_FORMAT\n }}\"\n tooltip=\"{{ date[0] | c8yDate: DATE_FORMAT }} \u2014 {{ date[1] | c8yDate: DATE_FORMAT }}\"\n placement=\"top\"\n container=\"body\"\n data-cy=\"widget-time-context--date-picker-dropdown-button\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n dropdownToggle\n >\n <i\n class=\"m-r-8\"\n c8yIcon=\"schedule1\"\n ></i>\n <div class=\"d-col text-left fit-w\">\n <span\n class=\"text-muted fit-w text-10 l-h-1\"\n data-cy=\"widget-time-context--selected-interval\"\n >\n {{ INTERVAL_TITLES[form.controls.currentDateContextInterval.value] | translate }}\n </span>\n <span\n class=\"text-bold text-12 fit-w l-h-1 text-truncate\"\n data-cy=\"widget-time-context--selected-time-range\"\n >\n {{ date[0] | c8yDate: DATE_FORMAT }} \u2014 {{ date[1] | c8yDate: DATE_FORMAT }}\n </span>\n </div>\n <span class=\"caret m-r-16 m-l-4\"></span>\n </button>\n\n <ul\n class=\"dropdown-menu dropdown-menu-wide dropdown-menu--date-range\"\n *dropdownMenu\n >\n <c8y-interval-picker\n class=\"d-contents\"\n formControlName=\"currentDateContextInterval\"\n ></c8y-interval-picker>\n\n @if (form.controls.currentDateContextInterval.value === 'custom') {\n <div class=\"p-l-16 p-r-16\">\n <c8y-form-group\n [ngClass]=\"form.controls.temporaryUserSelectedFromDate.errors ? 'has-error' : ''\"\n >\n <label\n [title]=\"'From`date`' | translate\"\n for=\"temporaryUserSelectedFromDate\"\n translate\n >\n From`date`\n </label>\n <c8y-date-time-picker\n id=\"temporaryUserSelectedFromDate\"\n [maxDate]=\"form.value.temporaryUserSelectedToDate\"\n [config]=\"timePickerConfig\"\n [placeholder]=\"'From`date`' | translate\"\n [formControl]=\"form.controls.temporaryUserSelectedFromDate\"\n [ngClass]=\"\n form.controls.temporaryUserSelectedFromDate.errors ? 'has-error' : ''\n \"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"form.controls.temporaryUserSelectedFromDate.errors\">\n <c8y-message\n name=\"dateAfterRangeMax\"\n [text]=\"'This date is after the latest allowed date.' | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateTime\"\n [text]=\"'This date is invalid.' | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n\n <c8y-form-group\n [ngClass]=\"form.controls.temporaryUserSelectedToDate.errors ? 'has-error' : ''\"\n >\n <label\n [title]=\"'To`date`' | translate\"\n for=\"temporaryUserSelectedToDate\"\n translate\n >\n To`date`\n </label>\n <c8y-date-time-picker\n id=\"temporaryUserSelectedToDate\"\n [minDate]=\"form.value.temporaryUserSelectedFromDate\"\n [config]=\"timePickerConfig\"\n [placeholder]=\"'To`date`' | translate\"\n [formControl]=\"form.controls.temporaryUserSelectedToDate\"\n [ngClass]=\"form.controls.temporaryUserSelectedToDate.errors ? 'has-error' : ''\"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"form.controls.temporaryUserSelectedToDate.errors\">\n <c8y-message\n name=\"dateBeforeRangeMin\"\n [text]=\"'This date is before the earliest allowed date.' | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateTime\"\n [text]=\"'This date is invalid.' | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n </div>\n\n <div class=\"p-16 d-flex gap-8 separator-top\">\n <button\n class=\"btn btn-default btn-sm flex-grow\"\n title=\"{{ 'Reset' | translate }}\"\n type=\"button\"\n (click)=\"dropdown.isOpen = false\"\n [disabled]=\"form.value.realtime\"\n translate\n >\n Reset\n </button>\n\n <button\n class=\"btn btn-primary btn-sm flex-grow\"\n title=\"{{ 'Apply' | translate }}\"\n type=\"button\"\n (click)=\"applyDatetimeContext(); dropdown.isOpen = false\"\n [disabled]=\"\n (form.pristine && form.untouched) || form.invalid || form.value.realtime\n \"\n translate\n >\n Apply\n </button>\n </div>\n }\n </ul>\n </div>\n }\n </ng-container>\n\n <div class=\"input-group w-auto\">\n <c8y-realtime-control\n class=\"form-control p-0 flex-no-grow w-auto\"\n formControlName=\"realtime\"\n ></c8y-realtime-control>\n\n @if (enableAutoAggregation && isTimeSeriesMigrated()) {\n <c8y-aggregation-picker\n formControlName=\"aggregation\"\n [showAutoMode]=\"true\"\n [autoModeActive]=\"isAutoModeActive()\"\n [autoPoints]=\"form.value.autoAggregationDatapoints\"\n [autoKeepPointCount]=\"form.value.autoAggregationKeepDataOnZoomIn\"\n [disabledAggregations]=\"disabledAggregations\"\n (autoModeChange)=\"onAutoModeChange($event)\"\n >\n <div\n class=\"d-col\"\n autoAggregationOptions\n >\n <div class=\"d-flex a-i-center gap-8\">\n <label class=\"m-b-0 m-r-8\">\n {{ 'Points per chart' | translate }}\n </label>\n <input\n class=\"form-control input-sm\"\n style=\"width: 80px\"\n [attr.title]=\"\n 'Enter a value between {{ min }} and {{ max }}.'\n | translate\n : {\n min: AUTO_AGGREGATION_DATAPOINTS.MIN,\n max: AUTO_AGGREGATION_DATAPOINTS.MAX\n }\n \"\n [attr.aria-label]=\"'Points per chart' | translate\"\n type=\"number\"\n [min]=\"AUTO_AGGREGATION_DATAPOINTS.MIN\"\n [max]=\"AUTO_AGGREGATION_DATAPOINTS.MAX\"\n [step]=\"AUTO_AGGREGATION_DATAPOINTS.STEP\"\n [formControl]=\"form.controls.autoAggregationDatapoints\"\n />\n </div>\n <label\n class=\"c8y-switch m-b-0 m-t-8 text-nowrap\"\n [title]=\"'Keep point count on zoom' | translate\"\n >\n <input\n type=\"checkbox\"\n [formControl]=\"form.controls.autoAggregationKeepDataOnZoomIn\"\n data-cy=\"time-context--auto-aggregation-keep-data-on-zoom-in\"\n />\n <span></span>\n <span class=\"text-12\">{{ 'Keep point count on zoom' | translate }}</span>\n <button\n class=\"btn-help btn-help--sm m-l-4\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"KEEP_DATA_ON_ZOOM_IN_POPOVER | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </label>\n </div>\n </c8y-aggregation-picker>\n } @else if (\n enableAutoAggregation || (controlsAvailable ? controlsAvailable.aggregation : true)\n ) {\n <c8y-aggregation-picker\n formControlName=\"aggregation\"\n [disabledAggregations]=\"disabledAggregations\"\n ></c8y-aggregation-picker>\n }\n\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"AGGREGATION_POPOVER | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </form>\n</ng-template>\n" }]
325
449
  }], ctorParameters: () => [{ type: i1.WidgetTimeContextDateRangeService }], propDecorators: { changedDateContext: [{
326
450
  type: Input
327
451
  }], controlsAvailable: [{
@@ -330,6 +454,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
330
454
  type: Input
331
455
  }], timePickerConfig: [{
332
456
  type: Input
457
+ }], enableAutoAggregation: [{
458
+ type: Input
333
459
  }], dropdown: [{
334
460
  type: ViewChild,
335
461
  args: [BsDropdownDirective]