@elderbyte/ngx-starter 18.12.4 → 18.12.6

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 (49) hide show
  1. package/esm2022/lib/common/data/data-context/indexed-entities.mjs +13 -2
  2. package/esm2022/lib/common/selection/selection-model.mjs +4 -3
  3. package/esm2022/lib/components/data-view/common/selection/data-context-selection.directive.mjs +4 -2
  4. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-anchor-controller.mjs +21 -0
  5. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-calendar-controller.mjs +24 -0
  6. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-controller.mjs +43 -0
  7. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-form-controller.mjs +69 -0
  8. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-select-controller.mjs +117 -0
  9. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-shift-controller.mjs +44 -0
  10. package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker.component.mjs +87 -130
  11. package/esm2022/lib/components/time/elder-interval-picker/interval-picker-binding/elder-interval-picker-binding.directive.mjs +41 -0
  12. package/esm2022/lib/components/time/elder-interval-picker/interval-picker-toggle/elder-interval-picker-toggle.component.mjs +144 -0
  13. package/esm2022/lib/components/time/elder-interval-picker/manager/interval-picker-state-manager.mjs +93 -0
  14. package/esm2022/lib/components/time/elder-interval-picker/model/anchor-state.mjs +54 -0
  15. package/esm2022/lib/components/time/elder-interval-picker/model/interval-state.mjs +37 -0
  16. package/esm2022/lib/components/time/elder-interval-picker/model/smart-shift-state.mjs +10 -0
  17. package/esm2022/lib/components/time/elder-interval-picker/presenter/interval-picker-presenter.mjs +96 -0
  18. package/esm2022/lib/components/time/elder-interval-picker/util/interval-picker-util.mjs +194 -0
  19. package/esm2022/lib/components/time/elder-time.module.mjs +5 -5
  20. package/fesm2022/elderbyte-ngx-starter.mjs +789 -892
  21. package/fesm2022/elderbyte-ngx-starter.mjs.map +1 -1
  22. package/lib/components/time/elder-interval-picker/controller/interval-anchor-controller.d.ts +9 -0
  23. package/lib/components/time/elder-interval-picker/controller/interval-calendar-controller.d.ts +7 -0
  24. package/lib/components/time/elder-interval-picker/controller/interval-controller.d.ts +35 -0
  25. package/lib/components/time/elder-interval-picker/controller/interval-form-controller.d.ts +12 -0
  26. package/lib/components/time/elder-interval-picker/controller/interval-select-controller.d.ts +22 -0
  27. package/lib/components/time/elder-interval-picker/controller/interval-shift-controller.d.ts +13 -0
  28. package/lib/components/time/elder-interval-picker/elder-interval-picker.component.d.ts +26 -34
  29. package/lib/components/time/elder-interval-picker/{elder-interval-picker-binding.directive.d.ts → interval-picker-binding/elder-interval-picker-binding.directive.d.ts} +3 -4
  30. package/lib/components/time/elder-interval-picker/interval-picker-toggle/elder-interval-picker-toggle.component.d.ts +37 -0
  31. package/lib/components/time/elder-interval-picker/manager/interval-picker-state-manager.d.ts +46 -0
  32. package/lib/components/time/elder-interval-picker/model/anchor-state.d.ts +20 -0
  33. package/lib/components/time/elder-interval-picker/model/interval-state.d.ts +16 -0
  34. package/lib/components/time/elder-interval-picker/model/smart-shift-state.d.ts +8 -0
  35. package/lib/components/time/elder-interval-picker/presenter/interval-picker-presenter.d.ts +30 -0
  36. package/lib/components/time/elder-interval-picker/util/interval-picker-util.d.ts +20 -0
  37. package/lib/components/time/elder-time.module.d.ts +4 -4
  38. package/package.json +1 -1
  39. package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker-binding.directive.mjs +0 -40
  40. package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker-toggle/elder-interval-picker-toggle.component.mjs +0 -202
  41. package/esm2022/lib/components/time/elder-interval-picker/model/interval-picker-model-editor.mjs +0 -284
  42. package/esm2022/lib/components/time/elder-interval-picker/model/interval-picker-model.mjs +0 -445
  43. package/esm2022/lib/components/time/elder-interval-picker/model/plain-date-interval-message-renderer.mjs +0 -37
  44. package/esm2022/lib/components/time/elder-interval-picker/model/plain-temporal-duration-message-renderer.mjs +0 -25
  45. package/lib/components/time/elder-interval-picker/elder-interval-picker-toggle/elder-interval-picker-toggle.component.d.ts +0 -55
  46. package/lib/components/time/elder-interval-picker/model/interval-picker-model-editor.d.ts +0 -77
  47. package/lib/components/time/elder-interval-picker/model/interval-picker-model.d.ts +0 -113
  48. package/lib/components/time/elder-interval-picker/model/plain-date-interval-message-renderer.d.ts +0 -7
  49. package/lib/components/time/elder-interval-picker/model/plain-temporal-duration-message-renderer.d.ts +0 -4
@@ -1,11 +1,11 @@
1
1
  import * as i2$1 from '@angular/common';
2
2
  import { formatDate, CommonModule, formatCurrency, getCurrencySymbol, NgIf, AsyncPipe, NgFor, NgClass, NgTemplateOutlet, NgStyle, formatNumber, DecimalPipe, DatePipe, registerLocaleData, CurrencyPipe } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
- import { Pipe, LOCALE_ID, Inject, NgModule, Optional, SkipSelf, Directive, Output, Input, forwardRef, ViewChild, HostBinding, ViewChildren, ContentChild, Injectable, Component, ChangeDetectionStrategy, Host, APP_INITIALIZER, TemplateRef, HostListener, EventEmitter, input, ViewEncapsulation, InjectionToken, ContentChildren, signal, computed, model, output, effect, Self, untracked, booleanAttribute, ElementRef, viewChild, contentChild } from '@angular/core';
4
+ import { Pipe, LOCALE_ID, Inject, NgModule, Optional, SkipSelf, Directive, Output, Input, forwardRef, ViewChild, HostBinding, ViewChildren, ContentChild, Injectable, Component, ChangeDetectionStrategy, Host, APP_INITIALIZER, TemplateRef, HostListener, EventEmitter, input, ViewEncapsulation, InjectionToken, ContentChildren, signal, computed, model, output, effect, Self, ElementRef, booleanAttribute, viewChild, contentChild } from '@angular/core';
5
5
  import * as i1 from '@angular/platform-browser';
6
6
  import { Duration, Period, TemporalQueries, LocalTime, Instant, LocalDate, nativeJs, ZoneId, DateTimeFormatter, convert, ZonedDateTime, Temporal as Temporal$1 } from '@js-joda/core';
7
7
  import { LoggerFactory } from '@elderbyte/ts-logger';
8
- import { timer, defer, ReplaySubject, concat, finalize, exhaustMap, BehaviorSubject, Subject, switchMap, of, combineLatest, EMPTY, merge, throwError, forkJoin, mergeWith, Observable, from, toArray, zip, mergeMap as mergeMap$1, fromEvent, skipUntil, combineLatestWith as combineLatestWith$1, NEVER } from 'rxjs';
8
+ import { timer, defer, ReplaySubject, concat, finalize, exhaustMap, BehaviorSubject, Subject, switchMap, of, combineLatest, EMPTY, merge, throwError, forkJoin, mergeWith, Observable, from, toArray, zip, mergeMap as mergeMap$1, fromEvent, skipUntil, map as map$1, combineLatestWith as combineLatestWith$1, NEVER } from 'rxjs';
9
9
  import { tap, takeUntil, takeWhile, map, filter, distinctUntilChanged, debounceTime, catchError, first, take, switchMap as switchMap$1, mergeMap, expand, reduce, startWith, skip, delay, share, combineLatestWith, skipWhile, timeout } from 'rxjs/operators';
10
10
  import { Temporal } from '@js-temporal/polyfill';
11
11
  import * as i1$2 from '@angular/common/http';
@@ -22,7 +22,7 @@ import * as i1$a from '@angular/material/form-field';
22
22
  import { MatFormFieldControl, MatFormField, MatLabel, MatFormFieldModule, MatPrefix, MatHint, MatError, MatSuffix } from '@angular/material/form-field';
23
23
  import * as i1$3 from '@angular/router';
24
24
  import { RouterModule, NavigationEnd, RouterLinkActive, RouterLink, RouterOutlet, convertToParamMap, EventType } from '@angular/router';
25
- import * as i6 from '@angular/material/icon';
25
+ import * as i5 from '@angular/material/icon';
26
26
  import { MatIcon, MatIconModule } from '@angular/material/icon';
27
27
  import { MatSlideToggle, MatSlideToggleModule } from '@angular/material/slide-toggle';
28
28
  import * as i2$2 from '@elderbyte/ngx-simple-webstorage';
@@ -32,13 +32,13 @@ import { MatToolbar, MatToolbarRow, MatToolbarModule } from '@angular/material/t
32
32
  import { MatCard, MatCardModule, MatCardContent } from '@angular/material/card';
33
33
  import * as i4 from '@angular/material/core';
34
34
  import { MatRipple, MatRippleModule, MatOption, mixinColor, MatCommonModule, NativeDateAdapter, MAT_DATE_LOCALE, DateAdapter, MatNativeDateModule } from '@angular/material/core';
35
- import * as i8 from '@angular/material/button';
35
+ import * as i7 from '@angular/material/button';
36
36
  import { MatButtonModule, MatIconButton, MatButton, MatIconAnchor, MatAnchor } from '@angular/material/button';
37
37
  import * as i1$9 from '@angular/material/autocomplete';
38
38
  import { MatAutocompleteTrigger, MatAutocomplete, MatAutocompleteModule } from '@angular/material/autocomplete';
39
39
  import * as i1$7 from '@angular/material/chips';
40
40
  import { MatChipGrid, MatChipRow, MatChipRemove, MatChipInput, MatChipsModule, MatChip, MatChipAvatar, MatChipSet, MatChipTrailingIcon, MatChipListbox, MatChipOption } from '@angular/material/chips';
41
- import * as i4$1 from '@angular/material/input';
41
+ import * as i3$2 from '@angular/material/input';
42
42
  import { MatInput, MatInputModule } from '@angular/material/input';
43
43
  import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
44
44
  import { MatList, MatListSubheaderCssMatStyler, MatListItem, MatListModule } from '@angular/material/list';
@@ -53,7 +53,7 @@ import * as i1$b from '@angular/material/checkbox';
53
53
  import { MatCheckbox, MatCheckboxModule } from '@angular/material/checkbox';
54
54
  import * as i1$6 from '@angular/material/dialog';
55
55
  import { MatDialogClose, MAT_DIALOG_DATA, MatDialogConfig, MatDialogModule } from '@angular/material/dialog';
56
- import * as i10 from '@angular/material/menu';
56
+ import * as i9 from '@angular/material/menu';
57
57
  import { MatMenuTrigger, MatMenu, MatMenuItem, MatMenuModule } from '@angular/material/menu';
58
58
  import { MatTooltipModule, MatTooltip } from '@angular/material/tooltip';
59
59
  import { MatPaginator, MatPaginatorIntl, MatPaginatorModule } from '@angular/material/paginator';
@@ -70,15 +70,15 @@ import { Subject as Subject$1 } from 'rxjs/internal/Subject';
70
70
  import { MatProgressSpinnerModule, MatProgressSpinner } from '@angular/material/progress-spinner';
71
71
  import { trigger, state, style, transition, animate } from '@angular/animations';
72
72
  import { MatSidenavContainer, MatSidenav, MatSidenavContent, MatSidenavModule } from '@angular/material/sidenav';
73
- import * as i2$5 from '@angular/material/datepicker';
73
+ import * as i1$c from '@angular/material/datepicker';
74
74
  import { MatDatepicker, MatDatepickerInput, MatDatepickerToggle, MatDatepickerToggleIcon, MatDateRangeInput, MatStartDate, MatEndDate, MatDateRangePicker, DateRange, MatDatepickerModule, MatCalendar } from '@angular/material/datepicker';
75
75
  import { TemplatePortal } from '@angular/cdk/portal';
76
- import * as i1$c from '@angular/cdk/overlay';
76
+ import * as i1$d from '@angular/cdk/overlay';
77
77
  import { OverlayModule } from '@angular/cdk/overlay';
78
78
  import localeDECH from '@angular/common/locales/de-CH';
79
79
  import * as StreamSaver from 'streamsaver';
80
80
  import { MatAccordion, MatExpansionPanel, MatExpansionPanelHeader, MatExpansionPanelTitle, MatExpansionPanelDescription, MatExpansionModule } from '@angular/material/expansion';
81
- import * as i1$d from '@angular/material/tabs';
81
+ import * as i1$e from '@angular/material/tabs';
82
82
  import { MatTab } from '@angular/material/tabs';
83
83
  import { fetchEventSource, EventStreamContentType } from '@microsoft/fetch-event-source';
84
84
 
@@ -3415,14 +3415,25 @@ class IndexedEntities {
3415
3415
  */
3416
3416
  updateSome(updated) {
3417
3417
  const newData = [...this.entitiesSnapshot];
3418
+ let anyUpdated = false;
3419
+ const notFound = [];
3418
3420
  updated.forEach((update) => {
3419
3421
  const id = this.getItemId(update);
3420
3422
  const index = this.indexById(id);
3421
3423
  if (index != -1) {
3422
3424
  newData[index] = update;
3425
+ anyUpdated = true;
3426
+ }
3427
+ else {
3428
+ notFound.push(update);
3423
3429
  }
3424
3430
  });
3425
- this.setEntities(newData);
3431
+ if (notFound.length > 0) {
3432
+ this.log.warn('could not find all entities to update ' + notFound.length + '/' + updated.length, notFound);
3433
+ }
3434
+ if (anyUpdated) {
3435
+ this.setEntities(newData);
3436
+ }
3426
3437
  }
3427
3438
  append(append) {
3428
3439
  this.insert(append, this.entitiesSnapshot.length);
@@ -7885,8 +7896,9 @@ class SelectionModel {
7885
7896
  * *
7886
7897
  **************************************************************************/
7887
7898
  selectionChanged(origin) {
7888
- this.log.debug('selectionChanged triggerd by ' + origin);
7889
- this._selection.next(Array.from(this._selectionMap.values()));
7899
+ const selected = Array.from(this._selectionMap.values());
7900
+ this.log.debug('selectionChanged triggered by ' + origin, selected);
7901
+ this._selection.next(selected);
7890
7902
  }
7891
7903
  selectInternal(values) {
7892
7904
  values = values.filter((v) => this.isSelectable(v));
@@ -13846,7 +13858,9 @@ class DataContextSelectionDirective {
13846
13858
  else {
13847
13859
  const context = this.dataContext$.getValue();
13848
13860
  if (context) {
13849
- this.selectionModel.select(context.snapshot.data, 'masterToggle');
13861
+ const data = context.snapshot.data;
13862
+ this.log.debug('selecting all data', data);
13863
+ this.selectionModel.select(data, 'masterToggle');
13850
13864
  }
13851
13865
  }
13852
13866
  }
@@ -28868,821 +28882,823 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
28868
28882
  }]
28869
28883
  }] });
28870
28884
 
28871
- class IntervalPickerModelEditor {
28872
- /***************************************************************************
28873
- * *
28874
- * Constructor *
28875
- * *
28876
- **************************************************************************/
28877
- constructor(model) {
28878
- this.model = model;
28885
+ class IntervalState {
28886
+ constructor(startDate, endDate, startTime, endTime) {
28887
+ this.startDate = startDate;
28888
+ this.endDate = endDate;
28889
+ this.startTime = startTime;
28890
+ this.endTime = endTime;
28891
+ this.startTime = this.startTime || Temporal.PlainTime.from('00:00');
28892
+ this.endTime = this.endTime || Temporal.PlainTime.from('00:00');
28879
28893
  }
28880
- /***************************************************************************
28881
- * *
28882
- * Date Shift API *
28883
- * *
28884
- **************************************************************************/
28885
- shiftMonth(months, staticMode = false) {
28886
- this.setDatesFromRange(this.dateRange().shiftMonths(months));
28887
- if (staticMode && this.calendarMode() !== 'months') {
28888
- this.setCalendarMode('days');
28889
- return;
28890
- }
28891
- this.resetTimeRange();
28892
- this.setCalendarMode('months');
28894
+ static createFromDateTimes(startDateTime, endDateTime) {
28895
+ return new IntervalState(startDateTime.toPlainDate(), endDateTime.toPlainDate(), startDateTime.toPlainTime(), endDateTime.toPlainTime());
28893
28896
  }
28894
- shiftDay(days) {
28895
- this.setDatesFromRange(this.dateRange().shiftDays(days));
28896
- if (this.calendarMode() === 'weeks' && (days === 7 || days === -7)) {
28897
- this.setCalendarMode('weeks');
28898
- return;
28897
+ get startDateTime() {
28898
+ return IntervalPickerUtil.createTemporalDateTime(this.startDate, this.startTime);
28899
+ }
28900
+ get endDateTime() {
28901
+ return IntervalPickerUtil.createTemporalDateTime(this.endDate, this.endTime);
28902
+ }
28903
+ withStartDate(newStartDate) {
28904
+ return new IntervalState(newStartDate, this.endDate, this.startTime, this.endTime);
28905
+ }
28906
+ withEndDate(newEndDate) {
28907
+ return new IntervalState(this.startDate, newEndDate, this.startTime, this.endTime);
28908
+ }
28909
+ withStartTime(newStartTime) {
28910
+ return new IntervalState(this.startDate, this.endDate, newStartTime, this.endTime);
28911
+ }
28912
+ withEndTime(newEndTime) {
28913
+ return new IntervalState(this.startDate, this.endDate, this.startTime, newEndTime);
28914
+ }
28915
+ withTime(newStartTime, newEndTime) {
28916
+ return new IntervalState(this.startDate, this.endDate, newStartTime, newEndTime);
28917
+ }
28918
+ }
28919
+
28920
+ class IntervalPickerUtil {
28921
+ static createElderInterval(intervalState) {
28922
+ let startInstant;
28923
+ let endInstant;
28924
+ try {
28925
+ const startDateTimeJS = TemporalUtil.getJSDateFromPlainDateTime(intervalState.startDateTime);
28926
+ startInstant = TimeUtil.instant(startDateTimeJS);
28927
+ }
28928
+ catch (e) {
28929
+ startInstant = null;
28899
28930
  }
28900
- this.setCalendarMode('days');
28931
+ try {
28932
+ const endDateTimeJS = TemporalUtil.getJSDateFromPlainDateTime(intervalState.endDateTime);
28933
+ endInstant = TimeUtil.instant(endDateTimeJS);
28934
+ }
28935
+ catch (e) {
28936
+ endInstant = null;
28937
+ }
28938
+ return new Interval(startInstant, endInstant);
28901
28939
  }
28902
- shiftYear(years, staticMode = false) {
28903
- this.setDatesFromRange(this.dateRange().shiftYears(years));
28904
- if (staticMode && this.calendarMode() !== 'years') {
28905
- this.setCalendarMode('days');
28906
- return;
28940
+ static transformToIntervalState(interval) {
28941
+ if (!interval) {
28942
+ return null;
28943
+ }
28944
+ const startDateTimeJS = interval.start ? TimeUtil.date(interval.start) : null;
28945
+ const endDateTimeJS = interval.end ? TimeUtil.date(interval.end) : null;
28946
+ let startDate = null;
28947
+ let endDate = null;
28948
+ let startTime = null;
28949
+ let endTime = null;
28950
+ try {
28951
+ const startDateTime = TemporalUtil.getPlainDateTimeFromJSDate(startDateTimeJS);
28952
+ startDate = startDateTime.toPlainDate();
28953
+ startTime = startDateTime.toPlainTime();
28907
28954
  }
28908
- this.resetTimeRange();
28909
- this.setCalendarMode('years');
28955
+ catch (e) {
28956
+ startDate = null;
28957
+ startTime = null;
28958
+ }
28959
+ try {
28960
+ const endDateTime = TemporalUtil.getPlainDateTimeFromJSDate(endDateTimeJS);
28961
+ endDate = endDateTime.toPlainDate();
28962
+ endTime = endDateTime.toPlainTime();
28963
+ }
28964
+ catch (e) {
28965
+ endDate = null;
28966
+ endTime = null;
28967
+ }
28968
+ return new IntervalState(startDate, endDate, startTime, endTime);
28910
28969
  }
28911
- /***************************************************************************
28912
- * *
28913
- * Time Shift API *
28914
- * *
28915
- **************************************************************************/
28916
- shiftTime(amount, unit) {
28917
- if (!this.isStartAndEndDatesSet()) {
28918
- return;
28970
+ static createTemporalDateTime(date, time) {
28971
+ if (!date) {
28972
+ return null;
28919
28973
  }
28920
- const newStartDateTime = this.startDateTime().add({ [unit]: amount });
28921
- const newEndDateTime = this.endDateTime().add({ [unit]: amount });
28922
- this.setDateRange(Temporal.PlainDate.from(newStartDateTime), Temporal.PlainDate.from(newEndDateTime));
28923
- this.setTimeRange(Temporal.PlainTime.from(newStartDateTime), Temporal.PlainTime.from(newEndDateTime));
28974
+ return Temporal.PlainDateTime.from({
28975
+ year: date.year,
28976
+ month: date.month,
28977
+ day: date.day,
28978
+ hour: time.hour,
28979
+ minute: time.minute,
28980
+ second: time.second,
28981
+ millisecond: time.millisecond,
28982
+ });
28924
28983
  }
28925
- smartShift(direction = 1) {
28926
- if (this.calendarMode() === 'quarters') {
28927
- const newRange = this.dateRange().shiftMonths(direction * 3);
28928
- this.setDatesFromRange(newRange);
28929
- return;
28984
+ static isIntervalEquals(interval1, interval2) {
28985
+ if (!interval1 && !interval2) {
28986
+ return true;
28930
28987
  }
28931
- if (this.calendarMode() === 'months') {
28932
- const newRange = this.dateRange().shiftMonths(direction);
28933
- this.setDatesFromRange(newRange);
28934
- return;
28988
+ if (!interval1 || !interval2) {
28989
+ return false;
28935
28990
  }
28936
- if (this.calendarMode() === 'years') {
28937
- const newRange = this.dateRange().shiftYears(direction);
28938
- this.setDatesFromRange(newRange);
28939
- return;
28991
+ return (this.isEquals(interval1.startDate, interval2.startDate) &&
28992
+ this.isEquals(interval1.endDate, interval2.endDate) &&
28993
+ this.isEquals(interval1.startTime, interval2.startTime) &&
28994
+ this.isEquals(interval1.endTime, interval2.endTime));
28995
+ }
28996
+ static isEquals(x, y) {
28997
+ if (!x && !y) {
28998
+ return true;
28940
28999
  }
28941
- if (this.calendarMode() === 'weeks') {
28942
- const newRange = this.dateRange().shiftDays(7 * direction);
28943
- this.setDatesFromRange(newRange);
28944
- return;
29000
+ if (!x || !y) {
29001
+ return false;
28945
29002
  }
28946
- const daysDiff = this.dateRange().getDurationInDays();
28947
- const newRange = this.dateRange().shiftDays(daysDiff * direction);
28948
- this.setDatesFromRange(newRange);
29003
+ return x.equals(y);
28949
29004
  }
28950
- /***************************************************************************
28951
- * *
28952
- * Date Selection API *
28953
- * *
28954
- **************************************************************************/
28955
- selectCurrentDay() {
28956
- this.setDatesFromRange(TemporalUtil.getCurrentDay(this.anchorDate()));
28957
- this.setCalendarMode('days');
28958
- this.resetTimeRange();
29005
+ static isIntervalWithStartAndEnd(interval) {
29006
+ return !!interval?.startDate && !!interval?.endDate;
28959
29007
  }
28960
- selectYesterday() {
28961
- this.setDatesFromRange(TemporalUtil.getYesterday(this.anchorDate()));
28962
- this.setCalendarMode('days');
28963
- this.resetTimeRange();
29008
+ static isOpenInterval(interval) {
29009
+ if (!interval) {
29010
+ return false;
29011
+ }
29012
+ return ((!!interval.startDate && !interval.endDate) || (!interval.startDate && !!interval.endDate));
28964
29013
  }
28965
- selectCurrentMonth() {
28966
- this.setDatesFromRange(TemporalUtil.getCurrentMonth(this.anchorDate()));
28967
- this.setCalendarMode('months');
28968
- this.resetTimeRange();
29014
+ static getDeltaHumanReadable(interval) {
29015
+ if (IntervalPickerUtil.isOpenInterval(interval)) {
29016
+ return '';
29017
+ }
29018
+ if (!IntervalPickerUtil.isIntervalWithStartAndEnd(interval)) {
29019
+ return '-';
29020
+ }
29021
+ const duration = interval.startDateTime.until(interval.endDateTime);
29022
+ const tmp = [];
29023
+ if (duration.days) {
29024
+ tmp.push(`${duration.days}d`);
29025
+ }
29026
+ if (duration.hours) {
29027
+ tmp.push(`${duration.hours}h`);
29028
+ }
29029
+ if (duration.minutes) {
29030
+ tmp.push(`${duration.minutes}min`);
29031
+ }
29032
+ if (duration.seconds) {
29033
+ tmp.push(`${duration.seconds}s`);
29034
+ }
29035
+ if (!tmp.length) {
29036
+ return '0s';
29037
+ }
29038
+ return tmp.join(', ');
28969
29039
  }
28970
- selectCurrentWeek() {
28971
- this.setDatesFromRange(TemporalUtil.getCurrentWeek(this.anchorDate()));
28972
- this.setCalendarMode('weeks');
28973
- this.resetTimeRange();
29040
+ static getSmartShiftMessage(mode, dateInterval) {
29041
+ if (!dateInterval) {
29042
+ return '-';
29043
+ }
29044
+ const startDate = dateInterval.startDate;
29045
+ const endDate = dateInterval.endDate;
29046
+ switch (mode) {
29047
+ case 'years':
29048
+ return `1y (${startDate.year})`;
29049
+ case 'quarters':
29050
+ return `Q${TemporalUtil.getQuarterForDate(startDate)}, ${startDate.year}`;
29051
+ case 'months':
29052
+ return `1m (${startDate.monthCode}, ${startDate.year})`;
29053
+ case 'weeks':
29054
+ return `1w (CW ${startDate.weekOfYear}, ${endDate.year})`;
29055
+ case 'days':
29056
+ return `${startDate.until(endDate).days}d`;
29057
+ case 'time':
29058
+ return `${this.getDeltaHumanReadable(dateInterval)}`;
29059
+ default:
29060
+ return `${startDate.until(endDate).days}d`;
29061
+ }
28974
29062
  }
28975
- selectPreviousWeek() {
28976
- this.setDatesFromRange(TemporalUtil.getPreviousWeek(this.anchorDate()));
28977
- this.setCalendarMode('weeks');
28978
- this.resetTimeRange();
29063
+ static isTimeSetAndNotMidnight(time) {
29064
+ if (!time) {
29065
+ return false;
29066
+ }
29067
+ if (time.hour === 0 && time.minute === 0 && time.second === 0) {
29068
+ return false;
29069
+ }
29070
+ return true;
28979
29071
  }
28980
- selectPreviousMonth() {
28981
- this.setDatesFromRange(TemporalUtil.getPreviousMonth(this.anchorDate()));
28982
- this.setCalendarMode('months');
28983
- this.resetTimeRange();
29072
+ static setMillisecondsToZero(interval) {
29073
+ return new IntervalState(interval.startDate, interval.endDate, interval.startTime.with({ millisecond: 0, microsecond: 0, nanosecond: 0 }), interval.endTime.with({ millisecond: 0, microsecond: 0, nanosecond: 0 }));
28984
29074
  }
28985
- selectLastThirtyDaysExcludingToday() {
28986
- this.setDatesFromRange(TemporalUtil.getLastThirtyDays(this.anchorDate()));
28987
- this.setCalendarMode('days');
28988
- this.resetTimeRange();
29075
+ static roundUpToSeconds(time) {
29076
+ return time.with({
29077
+ second: time.second + 1,
29078
+ millisecond: 0,
29079
+ microsecond: 0,
29080
+ nanosecond: 0,
29081
+ });
28989
29082
  }
28990
- selectLastThirtyDaysIncludingToday() {
28991
- this.setDatesFromRange(TemporalUtil.getLastThirtyDaysIncludingToday(this.anchorDate()));
28992
- this.setCalendarMode('days');
28993
- this.resetTimeRange();
29083
+ static updateMatCalendarActiveDate(calendarStart, calendarEnd, startDate, endDate) {
29084
+ if (!calendarStart || !calendarEnd) {
29085
+ return;
29086
+ }
29087
+ if (!startDate && !endDate) {
29088
+ return;
29089
+ }
29090
+ setTimeout(() => {
29091
+ // timeout is needed to run calendar update last, otherwise there are issues
29092
+ if (startDate) {
29093
+ calendarStart.activeDate = TemporalUtil.getJSDateFromPlainDateTime(startDate);
29094
+ }
29095
+ if (endDate) {
29096
+ calendarEnd.activeDate = TemporalUtil.getJSDateFromPlainDateTime(endDate);
29097
+ }
29098
+ }, 0);
28994
29099
  }
28995
- selectCurrentYear() {
28996
- this.setDatesFromRange(TemporalUtil.getCurrentYear(this.anchorDate()));
28997
- this.setCalendarMode('years');
28998
- this.resetTimeRange();
29100
+ static updateMatCalendarTodayDate(calendarStart, calendarEnd) {
29101
+ if (!calendarStart || !calendarEnd) {
29102
+ return;
29103
+ }
29104
+ calendarStart.updateTodaysDate();
29105
+ calendarEnd.updateTodaysDate();
28999
29106
  }
29000
- selectPreviousYear() {
29001
- this.setDatesFromRange(TemporalUtil.getPreviousYear(this.anchorDate()));
29002
- this.setCalendarMode('years');
29003
- this.resetTimeRange();
29107
+ }
29108
+
29109
+ class AnchorState {
29110
+ constructor(fixedDate, fixedTime = Temporal.PlainTime.from('00:00'), referenceDateTime = IntervalPickerUtil.roundUpToSeconds(Temporal.Now.plainDateTimeISO())) {
29111
+ this.fixedDate = fixedDate;
29112
+ this.fixedTime = fixedTime;
29113
+ this.referenceDateTime = referenceDateTime;
29004
29114
  }
29005
- selectLast365Days() {
29006
- this.setDatesFromRange(TemporalUtil.getLast365Days(this.anchorDate()));
29007
- this.setCalendarMode('days');
29008
- this.resetTimeRange();
29115
+ static createFromDateTime(dateTime) {
29116
+ return new AnchorState(dateTime.toPlainDate(), dateTime.toPlainTime());
29009
29117
  }
29010
- selectCurrentQuarter() {
29011
- this.setDatesFromRange(TemporalUtil.getCurrentQuarter(this.anchorDate()));
29012
- this.setCalendarMode('quarters');
29013
- this.resetTimeRange();
29118
+ static createFromJsDate(date) {
29119
+ const dateTime = TemporalUtil.getPlainDateTimeFromJSDate(date);
29120
+ return new AnchorState(dateTime.toPlainDate(), dateTime.toPlainTime());
29014
29121
  }
29015
- selectPreviousQuarter() {
29016
- this.setDatesFromRange(TemporalUtil.getPreviousQuarter(this.anchorDate()));
29017
- this.setCalendarMode('quarters');
29018
- this.resetTimeRange();
29122
+ static empty() {
29123
+ return new AnchorState(null);
29019
29124
  }
29020
- selectLastSevenDaysExcludingToday() {
29021
- this.setDatesFromRange(TemporalUtil.getLastSevenDays(this.anchorDate()));
29022
- this.setCalendarMode('days');
29023
- this.resetTimeRange();
29125
+ withDate(date) {
29126
+ return new AnchorState(date, this.fixedTime);
29024
29127
  }
29025
- selectLastSevenDaysIncludingToday() {
29026
- this.setDatesFromRange(TemporalUtil.getLastSevenDaysIncludingToday(this.anchorDate()));
29027
- this.setCalendarMode('days');
29028
- this.resetTimeRange();
29128
+ withTime(time) {
29129
+ return new AnchorState(this.fixedDate, time);
29029
29130
  }
29030
- /***************************************************************************
29031
- * *
29032
- * Time Selection API *
29033
- * *
29034
- **************************************************************************/
29035
- // time range selections
29036
- selectLastHour() {
29037
- this.selectLastByDuration({ hours: 1 });
29131
+ withTimeMidnight() {
29132
+ return new AnchorState(this.fixedDate, Temporal.PlainTime.from('00:00'));
29038
29133
  }
29039
- selectLast24Hours() {
29040
- this.selectLastByDuration({ days: 1 });
29134
+ withReferenceDateTimeNow() {
29135
+ return new AnchorState(this.fixedDate, this.fixedTime, IntervalPickerUtil.roundUpToSeconds(Temporal.Now.plainDateTimeISO()));
29041
29136
  }
29042
- selectLastFiveMinutes() {
29043
- this.selectLastByDuration({ minutes: 5 });
29137
+ get fixedDateTime() {
29138
+ if (!this.fixedDate) {
29139
+ return null;
29140
+ }
29141
+ return IntervalPickerUtil.createTemporalDateTime(this.fixedDate, this.fixedTime);
29044
29142
  }
29045
- selectLastByDuration(duration) {
29046
- this.refreshBaseReferenceDateTime();
29047
- const end = this.anchorDateTime();
29048
- const start = end.subtract(duration);
29049
- const startPlainDate = Temporal.PlainDate.from(start);
29050
- const startPlainTime = Temporal.PlainTime.from(start);
29051
- this.setDateRange(startPlainDate, this.anchorDate());
29052
- this.setTimeRange(startPlainTime, this.anchorTime());
29053
- this.setCalendarMode('days');
29143
+ get isFixed() {
29144
+ return this.fixedDate !== null;
29054
29145
  }
29055
- /***************************************************************************
29056
- * *
29057
- * Private methods *
29058
- * *
29059
- **************************************************************************/
29060
- anchorTime() {
29061
- return this.model.anchorTime();
29146
+ get date() {
29147
+ return this.fixedDate || this.referenceDateTime.toPlainDate();
29062
29148
  }
29063
- anchorDate() {
29064
- return this.model.anchorDate();
29149
+ get time() {
29150
+ return this.fixedTime || this.referenceDateTime.toPlainTime();
29065
29151
  }
29066
- setCalendarMode(mode) {
29067
- this.model.calendarMode.set(mode);
29152
+ get dateTime() {
29153
+ return this.fixedDateTime || this.referenceDateTime;
29068
29154
  }
29069
- calendarMode() {
29070
- return this.model.calendarMode();
29155
+ get isTimeMidnight() {
29156
+ return this.fixedTime.hour === 0 && this.fixedTime.minute === 0 && this.fixedTime.second === 0;
29071
29157
  }
29072
- dateRange() {
29073
- return this.model.dateRange();
29158
+ }
29159
+
29160
+ class IntervalAnchorController {
29161
+ constructor(manager) {
29162
+ this.manager = manager;
29074
29163
  }
29075
- resetTimeRange() {
29076
- this.setTimeRange(Temporal.PlainTime.from('00:00'), Temporal.PlainTime.from('00:00'));
29164
+ resetAnchor() {
29165
+ this.manager.setAnchor(AnchorState.empty());
29077
29166
  }
29078
- setTimeRange(start, end) {
29079
- this.model.setStartTime(start);
29080
- this.model.setEndTime(end);
29167
+ resetAnchorTime() {
29168
+ this.manager.setAnchor(this.manager.anchorValue.withTimeMidnight());
29081
29169
  }
29082
- setDateRange(start, end) {
29083
- this.model.setStartDate(start);
29084
- this.model.setEndDate(end);
29170
+ setFixedAnchorPointToStartDateTime() {
29171
+ const startDateTime = this.manager.intervalValue?.startDateTime;
29172
+ this.manager.setAnchor(AnchorState.createFromDateTime(startDateTime));
29085
29173
  }
29086
- setDatesFromRange(range) {
29087
- this.setDateRange(range.start, range.end);
29174
+ setFixedAnchorPointToEndDateTime() {
29175
+ const endDateTime = this.manager.intervalValue?.endDateTime;
29176
+ this.manager.setAnchor(AnchorState.createFromDateTime(endDateTime));
29088
29177
  }
29089
- shiftSelectionToAnchorDate() {
29090
- if (!this.isStartAndEndDatesSet() || !this.fixedAnchorDate()) {
29178
+ }
29179
+
29180
+ class IntervalCalendarController {
29181
+ constructor(manager) {
29182
+ this.manager = manager;
29183
+ }
29184
+ setStartDateFromJSDate(date) {
29185
+ const startDate = TemporalUtil.getPlainDateFromJSDate(date);
29186
+ if (!this.manager.intervalValue) {
29187
+ this.manager.setInterval(new IntervalState(startDate, null));
29091
29188
  return;
29092
29189
  }
29093
- const range = this.dateRange();
29094
- const endDate = this.fixedAnchorDate();
29095
- const startDate = endDate.subtract({ days: range.getDurationInDays() });
29096
- this.setDateRange(startDate, endDate);
29097
- if (this.calendarMode() === 'months') {
29098
- this.selectCurrentMonth();
29099
- }
29100
- if (this.calendarMode() === 'years') {
29101
- this.selectCurrentYear();
29102
- }
29103
- if (this.calendarMode() === 'weeks') {
29104
- this.selectCurrentWeek();
29105
- }
29190
+ this.manager.setInterval(this.manager.intervalValue.withStartDate(startDate));
29106
29191
  }
29107
- fixedAnchorDate() {
29108
- return this.model.fixedAnchorDate();
29192
+ setEndDateFromJSDate(date) {
29193
+ const endDate = TemporalUtil.getPlainDateFromJSDate(date);
29194
+ if (!this.manager.intervalValue) {
29195
+ this.manager.setInterval(new IntervalState(null, endDate));
29196
+ return;
29197
+ }
29198
+ this.manager.setInterval(this.manager.intervalValue.withEndDate(endDate));
29109
29199
  }
29110
- fixedAnchorTime() {
29111
- return this.model.fixedAnchorTime();
29200
+ }
29201
+
29202
+ class IntervalFormController {
29203
+ constructor(manager) {
29204
+ this.manager = manager;
29205
+ this.log = LoggerFactory.getLogger(this.constructor.name);
29112
29206
  }
29113
- anchorDateTime() {
29114
- return this.model.anchorDateTime();
29207
+ setStartDateFromString(htmlString) {
29208
+ try {
29209
+ const plainDate = TemporalUtil.getPlainDateFromHtmlDateString(htmlString);
29210
+ const endDate = this.manager.intervalValue?.endDate || plainDate.add({ days: 1 });
29211
+ this.manager.setInterval(new IntervalState(plainDate, endDate));
29212
+ }
29213
+ catch (e) {
29214
+ this.log.warn('Incorrect date / time anchor form input. Could not set anchor.', htmlString);
29215
+ }
29115
29216
  }
29116
- startDateTime() {
29117
- return this.model.startDateTime();
29217
+ setEndDateFromString(htmlString) {
29218
+ try {
29219
+ const plainDate = TemporalUtil.getPlainDateFromHtmlDateString(htmlString);
29220
+ const startDate = this.manager.intervalValue?.startDate || plainDate.subtract({ days: 1 });
29221
+ this.manager.setInterval(new IntervalState(startDate, plainDate));
29222
+ }
29223
+ catch (e) {
29224
+ this.log.warn('Incorrect date / time anchor form input. Could not set anchor.', htmlString);
29225
+ }
29118
29226
  }
29119
- endDateTime() {
29120
- return this.model.endDateTime();
29227
+ setAnchorDateFromString(htmlString) {
29228
+ try {
29229
+ const plainDate = TemporalUtil.getPlainDateFromHtmlDateString(htmlString);
29230
+ this.manager.setAnchor(this.manager.anchorValue.withDate(plainDate));
29231
+ }
29232
+ catch (e) {
29233
+ this.log.warn('Incorrect date / time anchor form input. Could not set anchor.', htmlString);
29234
+ }
29121
29235
  }
29122
- isStartAndEndDatesSet() {
29123
- return this.model.isStartAndEndDatesSet();
29236
+ setAnchorTimeFromString(htmlString) {
29237
+ try {
29238
+ const plainTime = TemporalUtil.getPlainTimeFromHtmlTimeString(htmlString);
29239
+ this.manager.setAnchor(this.manager.anchorValue.withTime(plainTime));
29240
+ }
29241
+ catch (e) {
29242
+ this.log.warn('Incorrect date / time anchor form input. Could not set anchor.', htmlString);
29243
+ }
29124
29244
  }
29125
- shiftSelectionToAnchorTime() {
29126
- if (!this.isStartAndEndDatesSet() || !this.fixedAnchorTime()) {
29127
- return;
29245
+ setStartTimeFromString(timeStr) {
29246
+ try {
29247
+ const startTime = TemporalUtil.getPlainTimeFromHtmlTimeString(timeStr);
29248
+ const startDate = this.manager.intervalValue?.startDate || Temporal.Now.plainDateISO();
29249
+ this.manager.setInterval(new IntervalState(startDate, this.manager.intervalValue?.endDate || null, startTime, this.manager.intervalValue?.endTime || null));
29128
29250
  }
29129
- const duration = this.startDateTime().until(this.endDateTime());
29130
- const newStartDateTime = this.anchorDateTime().subtract(duration);
29131
- const newEndDateTime = this.anchorDateTime();
29132
- this.setDateRange(Temporal.PlainDate.from(newStartDateTime), Temporal.PlainDate.from(newEndDateTime));
29133
- this.setTimeRange(Temporal.PlainTime.from(newStartDateTime), Temporal.PlainTime.from(newEndDateTime));
29134
- if (this.calendarMode() === 'months') {
29135
- this.selectCurrentMonth();
29251
+ catch (e) {
29252
+ this.log.warn('Incorrect date / time form input. Could not set new Interval.', timeStr, e);
29136
29253
  }
29137
- if (this.calendarMode() === 'years') {
29138
- this.selectCurrentYear();
29254
+ }
29255
+ setEndTimeFromString(timeStr) {
29256
+ try {
29257
+ const endTime = TemporalUtil.getPlainTimeFromHtmlTimeString(timeStr);
29258
+ const endDate = this.manager.intervalValue?.endDate || Temporal.Now.plainDateISO();
29259
+ this.manager.setInterval(new IntervalState(this.manager.intervalValue?.startDate || null, endDate, this.manager.intervalValue?.startTime || null, endTime));
29139
29260
  }
29140
- if (this.calendarMode() === 'weeks') {
29141
- this.selectCurrentWeek();
29261
+ catch (e) {
29262
+ this.log.warn('Incorrect date / time form input. Could not set new Interval.', timeStr);
29142
29263
  }
29143
29264
  }
29144
- refreshBaseReferenceDateTime() {
29145
- const dateTime = Temporal.Now.zonedDateTimeISO();
29146
- const date = Temporal.PlainDate.from(dateTime);
29147
- const time = Temporal.PlainTime.from(dateTime);
29148
- this.model.baseReferenceDate.set(date);
29149
- this.model.baseReferenceTime.set(time);
29265
+ }
29266
+
29267
+ class SmartShiftState {
29268
+ constructor(duration, mode) {
29269
+ this.duration = duration;
29270
+ this.mode = mode;
29271
+ }
29272
+ static empty() {
29273
+ return new SmartShiftState(null, null);
29150
29274
  }
29151
29275
  }
29152
29276
 
29153
- class PlainDateIntervalMessageRenderer {
29154
- static toMessage(mode, dateInterval) {
29155
- if (!dateInterval) {
29156
- return '-';
29157
- }
29158
- const startDate = dateInterval.start;
29159
- const endDate = dateInterval.end;
29160
- switch (mode) {
29161
- case 'years':
29162
- return `1y (${startDate.year})`;
29163
- case 'quarters':
29164
- return `Q${TemporalUtil.getQuarterForDate(startDate)}, ${startDate.year}`;
29165
- case 'months':
29166
- return `1m (${startDate.monthCode}, ${startDate.year})`;
29167
- case 'weeks':
29168
- return `1w (CW ${this.calendarWeek(startDate)}, ${endDate.year})`;
29169
- case 'days':
29170
- return `${this.dateRangeInDays(dateInterval)}d`;
29171
- default:
29172
- return '?';
29173
- }
29277
+ class IntervalSelectController {
29278
+ constructor(manager) {
29279
+ this.manager = manager;
29174
29280
  }
29175
- static calendarWeek(date) {
29176
- if (!date) {
29177
- return null;
29178
- }
29179
- return date.weekOfYear;
29281
+ refreshAnchor() {
29282
+ this.manager.setAnchor(this.manager.anchorValue.withReferenceDateTimeNow());
29180
29283
  }
29181
- static dateRangeInDays(dateInterval) {
29182
- if (!dateInterval) {
29183
- return 0;
29184
- }
29185
- return dateInterval.getDurationInDays();
29284
+ setSmartShiftState(duration, mode) {
29285
+ this.manager.setSmartShift(new SmartShiftState(duration, mode));
29286
+ }
29287
+ selectCurrentDay() {
29288
+ this.refreshAnchor();
29289
+ const endDate = this.manager.anchorValue.date.add({ days: 1 });
29290
+ const startDate = endDate.subtract({ days: 1 });
29291
+ this.manager.setInterval(new IntervalState(startDate, endDate));
29292
+ this.setSmartShiftState(Temporal.Duration.from({ days: 1 }), 'days');
29293
+ }
29294
+ selectYesterday() {
29295
+ this.refreshAnchor();
29296
+ const endDate = this.manager.anchorValue.date;
29297
+ const startDate = endDate.subtract({ days: 1 });
29298
+ this.manager.setInterval(new IntervalState(startDate, endDate));
29299
+ this.setSmartShiftState(Temporal.Duration.from({ days: 1 }), 'days');
29300
+ }
29301
+ selectLastSevenDaysExcludingToday() {
29302
+ this.refreshAnchor();
29303
+ const endDate = this.manager.anchorValue.date;
29304
+ const startDate = endDate.subtract({ days: 7 });
29305
+ this.manager.setInterval(new IntervalState(startDate, endDate));
29306
+ this.setSmartShiftState(Temporal.Duration.from({ days: 7 }), 'days');
29307
+ }
29308
+ selectLastSevenDaysIncludingToday() {
29309
+ this.refreshAnchor();
29310
+ const endDate = this.manager.anchorValue.date.add({ days: 1 });
29311
+ const startDate = endDate.subtract({ days: 7 });
29312
+ this.manager.setInterval(new IntervalState(startDate, endDate));
29313
+ this.setSmartShiftState(Temporal.Duration.from({ days: 7 }), 'days');
29314
+ }
29315
+ selectLastThirtyDaysExcludingToday() {
29316
+ this.refreshAnchor();
29317
+ const endDate = this.manager.anchorValue.date;
29318
+ const startDate = endDate.subtract({ days: 30 });
29319
+ this.manager.setInterval(new IntervalState(startDate, endDate));
29320
+ this.setSmartShiftState(Temporal.Duration.from({ days: 30 }), 'days');
29321
+ }
29322
+ selectLastThirtyDaysIncludingToday() {
29323
+ this.refreshAnchor();
29324
+ const endDate = this.manager.anchorValue.date.add({ days: 1 });
29325
+ const startDate = endDate.subtract({ days: 30 });
29326
+ this.manager.setInterval(new IntervalState(startDate, endDate));
29327
+ this.setSmartShiftState(Temporal.Duration.from({ days: 30 }), 'days');
29328
+ }
29329
+ selectLast365daysExcludingToday() {
29330
+ this.refreshAnchor();
29331
+ const endDate = this.manager.anchorValue.date;
29332
+ const startDate = endDate.subtract({ days: 365 });
29333
+ this.manager.setInterval(new IntervalState(startDate, endDate));
29334
+ this.setSmartShiftState(Temporal.Duration.from({ days: 365 }), 'days');
29335
+ }
29336
+ selectLast365daysIncludingToday() {
29337
+ this.refreshAnchor();
29338
+ const endDate = this.manager.anchorValue.date.add({ days: 1 });
29339
+ const startDate = endDate.subtract({ days: 365 });
29340
+ this.manager.setInterval(new IntervalState(startDate, endDate));
29341
+ this.setSmartShiftState(Temporal.Duration.from({ days: 365 }), 'days');
29342
+ }
29343
+ selectLastFiveMinutes() {
29344
+ this.refreshAnchor();
29345
+ const anchorDateTime = this.manager.anchorValue.dateTime;
29346
+ const startDateTime = anchorDateTime.subtract({ minutes: 5 });
29347
+ this.manager.setInterval(IntervalState.createFromDateTimes(startDateTime, anchorDateTime));
29348
+ this.setSmartShiftState(Temporal.Duration.from({ minutes: 5 }), 'time');
29349
+ }
29350
+ selectLastHour() {
29351
+ this.refreshAnchor();
29352
+ const anchorDateTime = this.manager.anchorValue.dateTime;
29353
+ const startDateTime = anchorDateTime.subtract({ hours: 1 });
29354
+ this.manager.setInterval(IntervalState.createFromDateTimes(startDateTime, anchorDateTime));
29355
+ this.setSmartShiftState(Temporal.Duration.from({ hours: 1 }), 'time');
29356
+ }
29357
+ selectLast24Hours() {
29358
+ this.refreshAnchor();
29359
+ const anchorDateTime = this.manager.anchorValue.dateTime;
29360
+ const startDateTime = anchorDateTime.subtract({ hours: 24 });
29361
+ this.manager.setInterval(IntervalState.createFromDateTimes(startDateTime, anchorDateTime));
29362
+ this.setSmartShiftState(Temporal.Duration.from({ hours: 24 }), 'time');
29363
+ }
29364
+ selectCurrentWeek() {
29365
+ this.refreshAnchor();
29366
+ const range = TemporalUtil.getCurrentWeek(this.manager.anchorValue.date);
29367
+ this.manager.setInterval(new IntervalState(range.start, range.end));
29368
+ this.setSmartShiftState(Temporal.Duration.from({ days: 7 }), 'weeks');
29369
+ }
29370
+ selectCurrentMonth() {
29371
+ this.refreshAnchor();
29372
+ const range = TemporalUtil.getCurrentMonth(this.manager.anchorValue.date);
29373
+ this.manager.setInterval(new IntervalState(range.start, range.end));
29374
+ this.setSmartShiftState(Temporal.Duration.from({ months: 1 }), 'months');
29375
+ }
29376
+ selectCurrentQuarter() {
29377
+ this.refreshAnchor();
29378
+ const range = TemporalUtil.getCurrentQuarter(this.manager.anchorValue.date);
29379
+ this.manager.setInterval(new IntervalState(range.start, range.end));
29380
+ this.setSmartShiftState(Temporal.Duration.from({ months: 3 }), 'quarters');
29381
+ }
29382
+ selectCurrentYear() {
29383
+ this.refreshAnchor();
29384
+ const range = TemporalUtil.getCurrentYear(this.manager.anchorValue.date);
29385
+ this.manager.setInterval(new IntervalState(range.start, range.end));
29386
+ this.setSmartShiftState(Temporal.Duration.from({ years: 1 }), 'years');
29186
29387
  }
29187
29388
  }
29188
29389
 
29189
- class PlainTemporalDurationMessageRenderer {
29190
- static toMessage(duration) {
29191
- if (!duration) {
29192
- return '∞';
29193
- }
29194
- const tmp = [];
29195
- if (duration.days) {
29196
- tmp.push(`${duration.days}d`);
29197
- }
29198
- if (duration.hours) {
29199
- tmp.push(`${duration.hours}h`);
29200
- }
29201
- if (duration.minutes) {
29202
- tmp.push(`${duration.minutes}min`);
29203
- }
29204
- if (duration.seconds) {
29205
- tmp.push(`${duration.seconds}s`);
29206
- }
29207
- if (!tmp.length) {
29208
- return '0s';
29390
+ class IntervalShiftController {
29391
+ constructor(manager) {
29392
+ this.manager = manager;
29393
+ this.log = LoggerFactory.getLogger(this.constructor.name);
29394
+ }
29395
+ shiftDay(days) {
29396
+ this.manager.setInterval(new IntervalState(this.manager.intervalValue.startDate.add({ days }), this.manager.intervalValue.endDate.add({ days }), this.manager.intervalValue.startTime, this.manager.intervalValue.endTime));
29397
+ }
29398
+ shiftWeek(weeks) {
29399
+ this.manager.setInterval(new IntervalState(this.manager.intervalValue.startDate.add({ weeks }), this.manager.intervalValue.endDate.add({ weeks }), this.manager.intervalValue.startTime, this.manager.intervalValue.endTime));
29400
+ }
29401
+ shiftMonth(months) {
29402
+ this.manager.setInterval(new IntervalState(this.manager.intervalValue.startDate.add({ months }), this.manager.intervalValue.endDate.add({ months }), this.manager.intervalValue.startTime, this.manager.intervalValue.endTime));
29403
+ }
29404
+ shiftYear(years) {
29405
+ this.manager.setInterval(new IntervalState(this.manager.intervalValue.startDate.add({ years }), this.manager.intervalValue.endDate.add({ years }), this.manager.intervalValue.startTime, this.manager.intervalValue.endTime));
29406
+ }
29407
+ shiftMinute(minutes) {
29408
+ const newInterval = new IntervalState(this.manager.intervalValue.startDate, this.manager.intervalValue.endDate, this.manager.intervalValue.startTime?.add({ minutes }), this.manager.intervalValue.endTime?.add({ minutes }));
29409
+ this.manager.setInterval(newInterval);
29410
+ }
29411
+ shiftHour(hours) {
29412
+ const newInterval = new IntervalState(this.manager.intervalValue.startDate, this.manager.intervalValue.endDate, this.manager.intervalValue.startTime?.add({ hours: hours }), this.manager.intervalValue.endTime?.add({ hours: hours }));
29413
+ this.manager.setInterval(newInterval);
29414
+ }
29415
+ smartShift(direction = 1) {
29416
+ const state = this.manager.smartShiftValue;
29417
+ if (!state.duration) {
29418
+ this.log.warn('Cannot smart shift without a duration!');
29419
+ return;
29209
29420
  }
29210
- return tmp.join(', ');
29421
+ const duration = state.duration;
29422
+ const interval = this.manager.intervalValue;
29423
+ let newStartDateTime = direction === 1
29424
+ ? interval.startDateTime.add(duration)
29425
+ : interval.startDateTime.subtract(duration);
29426
+ let newEndDateTime = direction === 1 ? interval.endDateTime.add(duration) : interval.endDateTime.subtract(duration);
29427
+ const newInterval = IntervalState.createFromDateTimes(newStartDateTime, newEndDateTime);
29428
+ this.manager.setInterval(newInterval);
29211
29429
  }
29212
29430
  }
29213
29431
 
29214
- const defaultCalendarMode = 'days';
29215
- class IntervalPickerModel {
29432
+ class IntervalController {
29216
29433
  /***************************************************************************
29217
29434
  * *
29218
29435
  * Constructor *
29219
29436
  * *
29220
29437
  **************************************************************************/
29221
- constructor() {
29438
+ constructor(manager) {
29439
+ this.manager = manager;
29222
29440
  /***************************************************************************
29223
29441
  * *
29224
29442
  * Fields *
29225
29443
  * *
29226
29444
  **************************************************************************/
29227
29445
  this.log = LoggerFactory.getLogger(this.constructor.name);
29228
- this._dateChangeEmitter = new EventEmitter();
29229
- this.calendarMode = signal(defaultCalendarMode);
29230
- this._startDate = signal(null);
29231
- this._endDate = signal(null);
29232
- this._startTime = signal(Temporal.PlainTime.from('00:00'));
29233
- this._endTime = signal(Temporal.PlainTime.from('00:00'));
29234
- // Anchor
29235
- this.baseReferenceDate = signal(Temporal.Now.plainDateISO());
29236
- this.baseReferenceTime = signal(Temporal.Now.plainTimeISO());
29237
- this.fixedAnchorDate = signal(null);
29238
- this.fixedAnchorTime = signal(Temporal.PlainTime.from('00:00'));
29239
- this.isEmittingOnChange = signal(true);
29240
- this.isUpdatingIntervalOnAnchorChange = signal(false);
29241
- this._isInitialized = false;
29242
- this.isFixedAnchorDateSet = computed(() => {
29243
- return !!this.fixedAnchorDate();
29244
- });
29245
- this.anchorDate = computed(() => {
29246
- if (this.fixedAnchorDate()) {
29247
- return this.fixedAnchorDate();
29248
- }
29249
- return this.baseReferenceDate();
29250
- });
29251
- this.anchorTime = computed(() => {
29252
- if (this.fixedAnchorDate() && this.fixedAnchorTime()) {
29253
- return this.fixedAnchorTime();
29254
- }
29255
- return this.baseReferenceTime();
29256
- });
29257
- this.anchorDateTime = computed(() => {
29258
- return this.anchorDate().toPlainDateTime(this.anchorTime());
29259
- });
29260
- this.dateRange = computed(() => {
29261
- if (!this.isStartAndEndDatesSet()) {
29262
- return null;
29263
- }
29264
- return new TemporalPlainDateInterval(this.startDate(), this.endDate());
29265
- });
29266
- this.dateRangeForCalendar = computed(() => {
29267
- if (!this.isStartAndEndDatesSet()) {
29268
- return null;
29269
- }
29270
- const startDate = TemporalUtil.getJSDateFromPlainDateTime(this.startDate());
29271
- const endDate = TemporalUtil.getJSDateFromPlainDateTime(this.endDate());
29272
- return new DateRange(startDate, endDate);
29273
- });
29274
- this.isStartAndEndDatesEmpty = computed(() => {
29275
- return !this.startDate() && !this.endDate();
29276
- });
29277
- this.isStartAndEndDatesSet = computed(() => {
29278
- return !!(this.startDate() && this.endDate());
29279
- });
29280
- this.isRangeNotSet = computed(() => {
29281
- return !this.isStartAndEndDatesSet();
29282
- });
29283
- this.startDateTime = computed(() => {
29284
- if (!this.startDate()) {
29285
- return null;
29286
- }
29287
- if (this.startTime()) {
29288
- return this.startDate().toPlainDateTime(this.startTime());
29289
- }
29290
- return this.startDate();
29291
- });
29292
- this.endDateTime = computed(() => {
29293
- if (!this.endDate()) {
29294
- return null;
29295
- }
29296
- if (this.endTime()) {
29297
- return this.endDate().toPlainDateTime(this.endTime());
29298
- }
29299
- return this.endDate();
29300
- });
29301
- this.startDateAsJSDate = computed(() => {
29302
- if (!this.startDate()) {
29303
- return null;
29304
- }
29305
- return TemporalUtil.getJSDateFromPlainDateTime(this.startDate());
29306
- });
29307
- this.endDateAsJSDate = computed(() => {
29308
- if (!this.endDate()) {
29309
- return null;
29310
- }
29311
- return TemporalUtil.getJSDateFromPlainDateTime(this.endDate());
29312
- });
29313
- this.startDateTimeAsJSDate = computed(() => {
29314
- if (!this.startDateTime()) {
29315
- return null;
29316
- }
29317
- return TemporalUtil.getJSDateFromPlainDateTime(this.startDateTime());
29318
- });
29319
- this.endDateTimeAsJSDate = computed(() => {
29320
- if (!this.endDateTime()) {
29321
- return null;
29322
- }
29323
- return TemporalUtil.getJSDateFromPlainDateTime(this.endDateTime());
29324
- });
29325
- this.viewIntervalMessage = computed(() => PlainDateIntervalMessageRenderer.toMessage(this.calendarMode(), this.dateRange()));
29326
- this.deltaHumanReadable = computed(() => {
29327
- if (this.isStartAndEndDatesEmpty()) {
29328
- return '';
29329
- }
29330
- const duration = this.deltaAsTemporalDuration(this.startDateTime(), this.endDateTime());
29331
- return PlainTemporalDurationMessageRenderer.toMessage(duration);
29332
- });
29333
- this.getStartTimeString = computed(() => {
29334
- return TemporalUtil.getHtmlTimeStringFromPlainTime(this.startTime());
29335
- });
29336
- this.getEndTimeString = computed(() => {
29337
- return TemporalUtil.getHtmlTimeStringFromPlainTime(this.endTime());
29338
- });
29339
- this.getAnchorTimeString = computed(() => {
29340
- return TemporalUtil.getHtmlTimeStringFromPlainTime(this.fixedAnchorTime());
29341
- });
29342
- this.getAnchorPointAsLocaleDate = computed(() => {
29343
- const anchorPoint = this.fixedAnchorDate();
29344
- if (!anchorPoint) {
29345
- return null;
29346
- }
29347
- const jsDate = TemporalUtil.getJSDateFromPlainDateTime(anchorPoint);
29348
- const localeDate = TimeUtil.dateToLocalDate(jsDate);
29349
- return localeDate;
29350
- });
29351
- this.startDateHtmlString = computed(() => {
29352
- return TemporalUtil.getHtmlDateString(this.startDateTime());
29353
- });
29354
- this.endDateHtmlString = computed(() => {
29355
- return TemporalUtil.getHtmlDateString(this.endDateTime());
29356
- });
29357
- this.isStartTimeSetAndNotMidnight = computed(() => {
29358
- if (!this.startTime()) {
29359
- return false;
29360
- }
29361
- return (this.startTime().hour !== 0 || this.startTime().minute !== 0 || this.startTime().second !== 0);
29362
- });
29363
- this.isEndTimeSetAndNotMidnight = computed(() => {
29364
- if (!this.endTime()) {
29365
- return false;
29366
- }
29367
- return this.endTime().hour !== 0 || this.endTime().minute !== 0 || this.endTime().second !== 0;
29368
- });
29369
- this.isFixedAnchorTimeSetAndNotMidnight = computed(() => {
29370
- if (!this.fixedAnchorTime()) {
29371
- return false;
29372
- }
29373
- return (this.fixedAnchorTime().hour !== 0 ||
29374
- this.fixedAnchorTime().minute !== 0 ||
29375
- this.fixedAnchorTime().second !== 0);
29376
- });
29377
- this.editor = new IntervalPickerModelEditor(this);
29378
- effect(() => {
29379
- const startDateTime = this.startDateTime();
29380
- const endDateTime = this.endDateTime();
29381
- if (this.isEmittingOnChange()) {
29382
- this.emitMainDates(); // TODO Only emit if changed
29383
- }
29384
- });
29446
+ this.select = new IntervalSelectController(manager);
29447
+ this.shift = new IntervalShiftController(manager);
29448
+ this.form = new IntervalFormController(manager);
29449
+ this.calendar = new IntervalCalendarController(manager);
29450
+ this.anchor = new IntervalAnchorController(manager);
29385
29451
  }
29386
29452
  /***************************************************************************
29387
29453
  * *
29388
- * Properties *
29454
+ * Public API *
29389
29455
  * *
29390
29456
  **************************************************************************/
29391
- startDate() {
29392
- return this._startDate();
29393
- }
29394
- endDate() {
29395
- return this._endDate();
29457
+ clearInterval() {
29458
+ this.manager.setInterval(null);
29396
29459
  }
29397
- startTime() {
29398
- return this._startTime();
29460
+ clearEndTime() {
29461
+ this.manager.setInterval(this.manager.intervalValue.withEndTime(null));
29399
29462
  }
29400
- endTime() {
29401
- return this._endTime();
29463
+ clearStartTime() {
29464
+ this.manager.setInterval(this.manager.intervalValue.withStartTime(null));
29402
29465
  }
29466
+ manualEmit() { }
29467
+ }
29468
+
29469
+ class IntervalPickerStateManager {
29403
29470
  /***************************************************************************
29404
29471
  * *
29405
- * Public API *
29472
+ * Constructor *
29406
29473
  * *
29407
29474
  **************************************************************************/
29408
- setInitialized() {
29409
- this._isInitialized = true;
29410
- }
29411
- setStartDate(value) {
29412
- const current = untracked(this._startDate);
29413
- if (!TemporalUtil.equalPlainDates(current, value)) {
29414
- this._startDate.set(value);
29415
- }
29416
- }
29417
- setEndDate(value) {
29418
- const current = untracked(this._endDate);
29419
- if (!TemporalUtil.equalPlainDates(current, value)) {
29420
- this._endDate.set(value);
29421
- }
29422
- }
29423
- setStartTime(value) {
29424
- const current = untracked(this._startTime);
29425
- if (!TemporalUtil.equalPlainTimes(current, value)) {
29426
- this._startTime.set(value);
29427
- }
29428
- }
29429
- setEndTime(value) {
29430
- const current = untracked(this._endTime);
29431
- if (!TemporalUtil.equalPlainTimes(current, value)) {
29432
- this._endTime.set(value);
29433
- }
29434
- }
29435
- setStartDateFromHtmlString(htmlString) {
29436
- const date = TemporalUtil.getPlainDateFromHtmlDateString(htmlString);
29437
- if (!date) {
29438
- return;
29439
- }
29440
- this.calendarMode.set('days');
29441
- this.setStartDate(date);
29442
- }
29443
- setEndDateFromHtmlString(htmlString) {
29444
- const date = TemporalUtil.getPlainDateFromHtmlDateString(htmlString);
29445
- if (!date) {
29446
- return;
29447
- }
29448
- this.calendarMode.set('days');
29449
- this.setEndDate(date);
29450
- }
29451
- setInterval(value) {
29452
- this.setDateTimesFromElderInterval(value);
29453
- }
29454
- setAnchorDateTime(value) {
29455
- this.setAnchorDateTimeFromJsDate(value);
29475
+ constructor() {
29476
+ /***************************************************************************
29477
+ * *
29478
+ * Fields *
29479
+ * *
29480
+ **************************************************************************/
29481
+ this.log = LoggerFactory.getLogger(this.constructor.name);
29482
+ this._anchor = new BehaviorSubject(AnchorState.empty());
29483
+ this._interval = new BehaviorSubject(null);
29484
+ this._smartShift = new BehaviorSubject(null);
29485
+ this._intervalChange = new Subject();
29486
+ this.isInitialized = false;
29456
29487
  }
29457
- setupEventEmitter(e) {
29458
- this._dateChangeEmitter = e;
29488
+ /***************************************************************************
29489
+ * *
29490
+ * Properties *
29491
+ * *
29492
+ **************************************************************************/
29493
+ get interval$() {
29494
+ return this._interval.asObservable();
29459
29495
  }
29460
- setStartTimeFromString(timeStr) {
29461
- const time = TemporalUtil.getPlainTimeFromHtmlTimeString(timeStr);
29462
- if (time) {
29463
- this.setStartTime(time);
29464
- }
29465
- if (!untracked(this._startDate)) {
29466
- this.setStartDate(Temporal.Now.plainDateISO());
29467
- }
29468
- this.calendarMode.set('days');
29496
+ get anchor$() {
29497
+ return this._anchor.asObservable();
29469
29498
  }
29470
- setEndTimeFromString(timeStr) {
29471
- const time = TemporalUtil.getPlainTimeFromHtmlTimeString(timeStr);
29472
- if (time) {
29473
- this.setEndTime(time);
29474
- }
29475
- if (!untracked(this._endDate)) {
29476
- this.setEndDate(Temporal.Now.plainDateISO());
29477
- }
29478
- this.calendarMode.set('days');
29499
+ get smartShift$() {
29500
+ return this._smartShift.asObservable();
29479
29501
  }
29480
- resetCalendarMode() {
29481
- this.calendarMode.set(defaultCalendarMode);
29502
+ get intervalValue() {
29503
+ return this._interval.getValue();
29482
29504
  }
29483
- setAnchorDateTimeFromJsDate(dateTime) {
29484
- if (!dateTime) {
29485
- return;
29486
- }
29487
- const date = TemporalUtil.getPlainDateFromJSDate(dateTime);
29488
- const time = TemporalUtil.getPlainTimeFromJSDate(dateTime);
29489
- this.fixedAnchorDate.set(date);
29490
- this.fixedAnchorTime.set(time);
29505
+ get anchorValue() {
29506
+ return this._anchor.getValue();
29491
29507
  }
29492
- setFixedAnchorPointToStartDateTime() {
29493
- if (!this.startDate()) {
29494
- this.resetFixedAnchorPoint();
29495
- return;
29496
- }
29497
- if (this.startDate()) {
29498
- this.fixedAnchorDate.set(this.startDate());
29499
- }
29500
- if (this.startTime()) {
29501
- this.fixedAnchorTime.set(this.startTime());
29502
- }
29508
+ get smartShiftValue() {
29509
+ return this._smartShift.getValue();
29503
29510
  }
29504
- setFixedAnchorPointToEndDateTime() {
29505
- if (!this.endDate()) {
29506
- this.resetFixedAnchorPoint();
29507
- return;
29508
- }
29509
- if (this.endDate()) {
29510
- this.fixedAnchorDate.set(this.endDate());
29511
- }
29512
- if (this.endTime()) {
29513
- this.fixedAnchorTime.set(this.endTime());
29514
- }
29511
+ get intervalChange() {
29512
+ return this._intervalChange.asObservable();
29515
29513
  }
29516
- resetFixedAnchorPoint() {
29517
- this.fixedAnchorDate.set(null);
29518
- this.fixedAnchorTime.set(Temporal.PlainTime.from('00:00'));
29519
- if (this.isUpdatingIntervalOnAnchorChange() && this.isStartAndEndDatesSet()) {
29520
- this.shiftRangeEndToToday();
29521
- }
29514
+ /***************************************************************************
29515
+ * *
29516
+ * Public API *
29517
+ * *
29518
+ **************************************************************************/
29519
+ setAnchor(anchor) {
29520
+ this._anchor.next(anchor);
29522
29521
  }
29523
- setAnchorDateFromForm(dateArg) {
29524
- if (!dateArg) {
29525
- this.fixedAnchorDate.set(null);
29526
- return;
29527
- }
29528
- const jsDate = TimeUtil.localDateToDate(dateArg);
29529
- const plainDate = TemporalUtil.getPlainDateFromJSDate(jsDate);
29530
- if (!plainDate) {
29531
- this.log.warn('Invalid date', plainDate);
29522
+ setExternalAnchor(TemporalDateTime) {
29523
+ if (!TemporalDateTime) {
29524
+ this.setAnchor(AnchorState.empty());
29532
29525
  return;
29533
29526
  }
29534
- this.fixedAnchorDate.set(plainDate);
29535
- if (!this.isUpdatingIntervalOnAnchorChange()) {
29536
- return;
29537
- }
29538
- if (this.fixedAnchorDate()) {
29539
- this.editor.shiftSelectionToAnchorDate();
29540
- }
29541
- }
29542
- clearStartDateTime() {
29543
- this.setStartDate(null);
29544
- this.setStartTime(null);
29545
- }
29546
- clearEndDateTime() {
29547
- this.setEndDate(null);
29548
- this.setEndTime(null);
29549
- }
29550
- clearStartTime() {
29551
- this.setStartTime(null);
29552
- }
29553
- clearEndTime() {
29554
- this.setEndTime(null);
29527
+ this.setAnchor(AnchorState.createFromDateTime(TemporalDateTime));
29555
29528
  }
29556
- resetFixedAnchorTime() {
29557
- this.fixedAnchorTime.set(Temporal.PlainTime.from('00:00'));
29558
- }
29559
- setAnchorTimeFromForm(htmlString) {
29560
- const time = TemporalUtil.getPlainTimeFromHtmlTimeString(htmlString);
29561
- if (!time) {
29529
+ setExternalInterval(interval) {
29530
+ if (!interval) {
29531
+ this.setInterval(new IntervalState(null, null));
29562
29532
  return;
29563
29533
  }
29564
- if (!this.fixedAnchorDate()) {
29565
- this.fixedAnchorDate.set(Temporal.Now.plainDateISO());
29566
- }
29567
- this.fixedAnchorTime.set(time);
29568
- if (!this.isUpdatingIntervalOnAnchorChange()) {
29534
+ if (!interval) {
29535
+ this.setInterval(new IntervalState(null, null));
29569
29536
  return;
29570
29537
  }
29571
- if (this.fixedAnchorTime()) {
29572
- this.editor.shiftSelectionToAnchorTime();
29573
- }
29538
+ this.setInterval(interval);
29574
29539
  }
29575
- emitMainDates() {
29576
- if (!this._isInitialized) {
29577
- return;
29578
- }
29579
- const interval = this.createElderInterval();
29580
- this._dateChangeEmitter.emit(interval);
29540
+ setSmartShift(smartShift) {
29541
+ this._smartShift.next(smartShift);
29581
29542
  }
29582
- /***************************************************************************
29583
- * *
29584
- * Private methods *
29585
- * *
29586
- **************************************************************************/
29587
- setDateTimesFromElderInterval(interval) {
29588
- if (!interval) {
29589
- this.setStartDate(null);
29590
- this.setEndDate(null);
29543
+ setInterval(interval) {
29544
+ if (!this.isInitialized && !interval) {
29591
29545
  return;
29592
29546
  }
29593
- if (interval.start) {
29594
- const startDateAsJSDate = TimeUtil.date(interval.start);
29595
- this.setStartDate(TemporalUtil.getPlainDateFromJSDate(startDateAsJSDate));
29596
- this.setStartTime(TemporalUtil.getPlainTimeFromJSDate(startDateAsJSDate));
29597
- }
29598
- else {
29599
- this.setStartDate(null);
29600
- }
29601
- if (interval.end) {
29602
- const endDateAsJSDate = TimeUtil.date(interval.end);
29603
- this.setEndDate(TemporalUtil.getPlainDateFromJSDate(endDateAsJSDate));
29604
- this.setEndTime(TemporalUtil.getPlainTimeFromJSDate(endDateAsJSDate));
29605
- }
29606
- else {
29607
- this.setEndDate(null);
29608
- }
29609
- this.log.debug('Applied interval to picker model:', interval);
29610
- }
29611
- createElderInterval() {
29612
- let start, end = null;
29613
- if (this.startDateTime()) {
29614
- const jsDate = TemporalUtil.getJSDateFromPlainDateTime(this.startDateTime());
29615
- start = TimeUtil.instant(jsDate);
29616
- }
29617
- if (this.endDateTime()) {
29618
- const jsDate = TemporalUtil.getJSDateFromPlainDateTime(this.endDateTime());
29619
- end = TimeUtil.instant(jsDate);
29620
- }
29621
- if (!start && !end) {
29622
- return new Interval(null, null);
29623
- }
29624
- return new Interval(start, end);
29625
- }
29626
- shiftRangeEndToToday() {
29627
- if (!this.isStartAndEndDatesSet()) {
29547
+ if (this._interval.getValue() &&
29548
+ IntervalPickerUtil.isIntervalEquals(this._interval.getValue(), interval)) {
29628
29549
  return;
29629
29550
  }
29630
- const duration = this.startDate().until(this.endDate());
29631
- this.setEndDate(Temporal.Now.plainDateISO());
29632
- this.setStartDate(this.endDate().subtract(duration));
29551
+ const newInterval = interval ? IntervalPickerUtil.setMillisecondsToZero(interval) : null;
29552
+ this._interval.next(newInterval);
29553
+ this._intervalChange.next(newInterval);
29633
29554
  }
29634
- deltaAsTemporalDuration(startDateTime, endDateTime) {
29635
- if (!startDateTime || !endDateTime) {
29636
- return null;
29637
- }
29638
- return startDateTime.until(endDateTime);
29555
+ }
29556
+
29557
+ class IntervalPickerPresenter {
29558
+ constructor(interval$, anchor$, smartShift$) {
29559
+ this.startDateHtmlString = computed(() => {
29560
+ return TemporalUtil.getHtmlDateString(this.intervalState()?.startDate);
29561
+ });
29562
+ this.endDateHtmlString = computed(() => {
29563
+ return TemporalUtil.getHtmlDateString(this.intervalState()?.endDate);
29564
+ });
29565
+ this.anchorDateHtmlString = computed(() => {
29566
+ return TemporalUtil.getHtmlDateString(this.anchorState()?.fixedDate);
29567
+ });
29568
+ this.startTimeHtmlString = computed(() => {
29569
+ return TemporalUtil.getHtmlTimeStringFromPlainTime(this.intervalState()?.startTime);
29570
+ });
29571
+ this.endTimeHtmlString = computed(() => {
29572
+ return TemporalUtil.getHtmlTimeStringFromPlainTime(this.intervalState()?.endTime);
29573
+ });
29574
+ this.anchorTimeHtmlString = computed(() => {
29575
+ return TemporalUtil.getHtmlTimeStringFromPlainTime(this.anchorState()?.fixedTime);
29576
+ });
29577
+ this.isValidIntervalSet = computed(() => {
29578
+ return IntervalPickerUtil.isIntervalWithStartAndEnd(this.intervalState());
29579
+ });
29580
+ this.deltaHumanReadable = computed(() => {
29581
+ return IntervalPickerUtil.getDeltaHumanReadable(this.intervalState());
29582
+ });
29583
+ this.smartShiftMessage = computed(() => {
29584
+ try {
29585
+ return IntervalPickerUtil.getSmartShiftMessage(this.smartShiftState().mode, this.intervalState());
29586
+ }
29587
+ catch (e) {
29588
+ return '-';
29589
+ }
29590
+ });
29591
+ this.startDateTimeAsJSDate = computed(() => {
29592
+ if (!this.intervalState()?.startDateTime) {
29593
+ return null;
29594
+ }
29595
+ return TemporalUtil.getJSDateFromPlainDateTime(this.intervalState()?.startDateTime);
29596
+ });
29597
+ this.endDateTimeAsJSDate = computed(() => {
29598
+ if (!this.intervalState()?.endDateTime) {
29599
+ return null;
29600
+ }
29601
+ return TemporalUtil.getJSDateFromPlainDateTime(this.intervalState()?.endDateTime);
29602
+ });
29603
+ this.dateRangeForCalendar = computed(() => {
29604
+ const start = this.startDateTimeAsJSDate();
29605
+ const end = this.endDateTimeAsJSDate();
29606
+ return new DateRange(start, end);
29607
+ });
29608
+ this.isStartTimeSetAndNotMidnight = computed(() => {
29609
+ return IntervalPickerUtil.isTimeSetAndNotMidnight(this.intervalState()?.startTime);
29610
+ });
29611
+ this.isEndTimeSetAndNotMidnight = computed(() => {
29612
+ return IntervalPickerUtil.isTimeSetAndNotMidnight(this.intervalState()?.endTime);
29613
+ });
29614
+ this.isFixedAnchorDateSet = computed(() => {
29615
+ return this.anchorState().isFixed;
29616
+ });
29617
+ this.isAnchorTimeMidnight = computed(() => {
29618
+ return this.anchorState().isTimeMidnight;
29619
+ });
29620
+ this.isAnchorMenuDisabled = computed(() => {
29621
+ return !this.startDateHtmlString() && !this.endDateHtmlString() && !this.anchorState().isFixed;
29622
+ });
29623
+ this.calendarAnchorDateCssClassFn = (cellDate, view) => {
29624
+ const calendarAnchorDateCssClassFnBody = (cellDate, view) => {
29625
+ const anchorDate = this.anchorState()?.fixedDate;
29626
+ if (!anchorDate) {
29627
+ return '';
29628
+ }
29629
+ const date = TemporalUtil.getJSDateFromPlainDateTime(anchorDate);
29630
+ if (!date) {
29631
+ return '';
29632
+ }
29633
+ if (cellDate.getDate() === date.getDate() &&
29634
+ cellDate.getMonth() === date.getMonth() &&
29635
+ cellDate.getFullYear() === date.getFullYear()) {
29636
+ return 'elder-custom-anchor-date';
29637
+ }
29638
+ return '';
29639
+ };
29640
+ return calendarAnchorDateCssClassFnBody(cellDate, view);
29641
+ };
29642
+ this.intervalState = toSignal(interval$);
29643
+ this.anchorState = toSignal(anchor$);
29644
+ this.smartShiftState = toSignal(smartShift$);
29639
29645
  }
29640
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: IntervalPickerModel, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
29641
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: IntervalPickerModel }); }
29642
29646
  }
29643
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: IntervalPickerModel, decorators: [{
29644
- type: Injectable
29645
- }], ctorParameters: () => [] });
29646
29647
 
29647
29648
  class ElderIntervalPickerComponent {
29648
- set interval(value) {
29649
- this.model.setInterval(value);
29650
- }
29651
- set anchorDateTime(value) {
29652
- this.model.setAnchorDateTime(value);
29653
- }
29654
29649
  /***************************************************************************
29655
29650
  * *
29656
29651
  * Constructor *
29657
29652
  * *
29658
29653
  **************************************************************************/
29659
- constructor(model) {
29660
- this.model = model;
29654
+ constructor() {
29661
29655
  /***************************************************************************
29662
29656
  * *
29663
29657
  * Fields *
29664
29658
  * *
29665
29659
  **************************************************************************/
29666
29660
  this.log = LoggerFactory.getLogger(this.constructor.name);
29667
- this.emitOnChange = input(true, { transform: (v) => booleanAttribute(v) });
29668
- this.intervalInputMode = input('date-range');
29669
- this.showAnchor = input(false, { transform: (v) => booleanAttribute(v) });
29670
- this.anchorReadOnly = input(false, { transform: (v) => booleanAttribute(v) });
29671
- this.showResultText = input(true, { transform: (v) => booleanAttribute(v) });
29672
- this.showHelpText = input(false, { transform: (v) => booleanAttribute(v) });
29673
- this.lastExcludesToday = input(false, { transform: (v) => booleanAttribute(v) });
29674
- this.dateChange = new EventEmitter();
29675
- this.calendarAnchorDateCssClassFn = (cellDate, view) => {
29676
- return this.calendarAnchorDateCssClassFnBody(cellDate, view);
29677
- };
29678
- this.model.setupEventEmitter(this.dateChange);
29679
- effect(() => {
29680
- if (this.model.anchorDate()) {
29681
- this.updateMatCalendarTodayDate();
29661
+ this.autoEmitMode = true;
29662
+ this.emitOnChange = true;
29663
+ this.emitType = 'interval';
29664
+ this.intervalInputMode = input('date-time-range');
29665
+ this.showAnchor = input(false);
29666
+ this.anchorReadOnly = input(false);
29667
+ this.externalAnchorDateTime = input(Temporal.Now.plainDateTimeISO());
29668
+ this.externalInterval = input(null);
29669
+ this.manager = new IntervalPickerStateManager();
29670
+ this.controller = new IntervalController(this.manager);
29671
+ this.presenter = new IntervalPickerPresenter(this.manager.interval$, this.manager.anchor$, this.manager.smartShift$);
29672
+ this.manager.intervalChange.pipe(takeUntilDestroyed()).subscribe({
29673
+ next: (state) => this.tryUpdateMatCalendarActiveDate(state),
29674
+ });
29675
+ this.intervalChange = this.manager.intervalChange.pipe(map$1((srcInterval) => {
29676
+ if (!srcInterval) {
29677
+ return null;
29682
29678
  }
29679
+ const elderInterval = IntervalPickerUtil.createElderInterval(srcInterval);
29680
+ if (this.emitType === 'iso') {
29681
+ console.log('emitting type iso', coerceIntervalIsoStr(elderInterval));
29682
+ return coerceIntervalIsoStr(elderInterval);
29683
+ }
29684
+ console.log('emitting type elder interval', elderInterval);
29685
+ return elderInterval;
29686
+ }));
29687
+ this.manager.anchor$.pipe(takeUntilDestroyed()).subscribe((anchor) => {
29688
+ IntervalPickerUtil.updateMatCalendarTodayDate(this.calendarStart, this.calendarEnd);
29683
29689
  });
29684
- effect(() => {
29685
- this.updateMatCalendarActiveDate(this.model.startDate(), this.model.endDate());
29690
+ const externalAnchorObservable = toObservable(this.externalAnchorDateTime);
29691
+ externalAnchorObservable.pipe(takeUntilDestroyed()).subscribe({
29692
+ next: (date) => {
29693
+ this.manager.setExternalAnchor(date);
29694
+ },
29695
+ });
29696
+ const externalIntervalObservable = toObservable(this.externalInterval);
29697
+ externalIntervalObservable.pipe(takeUntilDestroyed()).subscribe({
29698
+ next: (interval) => {
29699
+ const result = coerceInterval(interval);
29700
+ this.manager.setInterval(IntervalPickerUtil.transformToIntervalState(result || null));
29701
+ },
29686
29702
  });
29687
29703
  }
29688
29704
  /***************************************************************************
@@ -29690,19 +29706,21 @@ class ElderIntervalPickerComponent {
29690
29706
  * Life Cycle *
29691
29707
  * *
29692
29708
  **************************************************************************/
29709
+ ngOnInit() { }
29710
+ ngOnDestroy() {
29711
+ this.removeEventListeners();
29712
+ }
29693
29713
  ngAfterViewInit() {
29694
- this.model.isEmittingOnChange.set(this.emitOnChange());
29695
29714
  this.setupDateInputCalendarFocusPrevention();
29696
29715
  setTimeout(() => {
29697
- this.model.setInitialized();
29716
+ // this prevents ngmodel issue
29717
+ this.manager.isInitialized = true;
29718
+ console.log('externalInterval', this.externalInterval());
29698
29719
  }, 0);
29699
29720
  }
29700
- ngOnDestroy() {
29701
- this.removeEventListeners();
29702
- }
29703
29721
  /***************************************************************************
29704
29722
  * *
29705
- * Public API *
29723
+ * Private methods *
29706
29724
  * *
29707
29725
  **************************************************************************/
29708
29726
  setupDateInputCalendarFocusPrevention() {
@@ -29727,43 +29745,6 @@ class ElderIntervalPickerComponent {
29727
29745
  nativeElementStart.addEventListener('focus', this.calendarElFocusEventHandler, true);
29728
29746
  nativeElementEnd.addEventListener('focus', this.calendarElFocusEventHandler, true);
29729
29747
  }
29730
- clearStartDateTime() {
29731
- this.model.clearStartDateTime();
29732
- this.model.resetCalendarMode();
29733
- if (this.emitOnChange()) {
29734
- this.model.emitMainDates();
29735
- }
29736
- }
29737
- clearEndDateTime() {
29738
- this.model.clearEndDateTime();
29739
- this.model.resetCalendarMode();
29740
- if (this.emitOnChange()) {
29741
- this.model.emitMainDates();
29742
- }
29743
- }
29744
- clearStartAndEndDateTimes() {
29745
- this.model.clearStartDateTime();
29746
- this.model.clearEndDateTime();
29747
- this.model.resetCalendarMode();
29748
- if (this.emitOnChange()) {
29749
- this.model.emitMainDates();
29750
- }
29751
- }
29752
- handleStartCalendarChange(changedDate) {
29753
- this.model.calendarMode.set('days');
29754
- const newPlainDate = TemporalUtil.getPlainDateFromJSDate(changedDate);
29755
- this.model.setStartDate(newPlainDate);
29756
- }
29757
- handleEndCalendarChange(changedDate) {
29758
- this.model.calendarMode.set('days');
29759
- const newPlainDate = TemporalUtil.getPlainDateFromJSDate(changedDate);
29760
- this.model.setEndDate(newPlainDate);
29761
- }
29762
- /***************************************************************************
29763
- * *
29764
- * Private methods *
29765
- * *
29766
- **************************************************************************/
29767
29748
  removeEventListeners() {
29768
29749
  if (!this.calendarStartElRef || !this.calendarEndElRef) {
29769
29750
  return;
@@ -29776,47 +29757,16 @@ class ElderIntervalPickerComponent {
29776
29757
  nativeElementStart.removeEventListener('focus', this.calendarElFocusEventHandler, true);
29777
29758
  nativeElementEnd.removeEventListener('focus', this.calendarElFocusEventHandler, true);
29778
29759
  }
29779
- calendarAnchorDateCssClassFnBody(cellDate, view) {
29780
- const anchorDate = this.model.fixedAnchorDate();
29781
- if (!anchorDate) {
29782
- return '';
29783
- }
29784
- const date = TemporalUtil.getJSDateFromPlainDateTime(anchorDate);
29785
- if (!date) {
29786
- return '';
29787
- }
29788
- if (cellDate.getDate() === date.getDate() &&
29789
- cellDate.getMonth() === date.getMonth() &&
29790
- cellDate.getFullYear() === date.getFullYear()) {
29791
- return 'elder-custom-anchor-date';
29792
- }
29793
- return '';
29794
- }
29795
- updateMatCalendarActiveDate(startDate, endDate) {
29796
- if (!this.calendarStart || !this.calendarEnd) {
29797
- return;
29760
+ tryUpdateMatCalendarActiveDate(interval) {
29761
+ try {
29762
+ IntervalPickerUtil.updateMatCalendarActiveDate(this.calendarStart, this.calendarEnd, interval.startDate, interval.endDate);
29798
29763
  }
29799
- if (!startDate && !endDate) {
29800
- return;
29764
+ catch (e) {
29765
+ console.debug('Failed to update calendar active date', e);
29801
29766
  }
29802
- const calendarStart = this.calendarStart;
29803
- const calendarEnd = this.calendarEnd;
29804
- setTimeout(() => {
29805
- // timeout is needed to run calendar update last, otherwise there are issues
29806
- if (startDate) {
29807
- calendarStart.activeDate = TemporalUtil.getJSDateFromPlainDateTime(startDate);
29808
- }
29809
- if (endDate) {
29810
- calendarEnd.activeDate = TemporalUtil.getJSDateFromPlainDateTime(endDate);
29811
- }
29812
- }, 0);
29813
- }
29814
- updateMatCalendarTodayDate() {
29815
- this.calendarStart.updateTodaysDate();
29816
- this.calendarEnd.updateTodaysDate();
29817
29767
  }
29818
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderIntervalPickerComponent, deps: [{ token: IntervalPickerModel }], target: i0.ɵɵFactoryTarget.Component }); }
29819
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.5", type: ElderIntervalPickerComponent, isStandalone: true, selector: "elder-interval-picker", inputs: { emitOnChange: { classPropertyName: "emitOnChange", publicName: "emitOnChange", isSignal: true, isRequired: false, transformFunction: null }, intervalInputMode: { classPropertyName: "intervalInputMode", publicName: "intervalInputMode", isSignal: true, isRequired: false, transformFunction: null }, showAnchor: { classPropertyName: "showAnchor", publicName: "showAnchor", isSignal: true, isRequired: false, transformFunction: null }, anchorReadOnly: { classPropertyName: "anchorReadOnly", publicName: "anchorReadOnly", isSignal: true, isRequired: false, transformFunction: null }, showResultText: { classPropertyName: "showResultText", publicName: "showResultText", isSignal: true, isRequired: false, transformFunction: null }, showHelpText: { classPropertyName: "showHelpText", publicName: "showHelpText", isSignal: true, isRequired: false, transformFunction: null }, lastExcludesToday: { classPropertyName: "lastExcludesToday", publicName: "lastExcludesToday", isSignal: true, isRequired: false, transformFunction: null }, interval: { classPropertyName: "interval", publicName: "interval", isSignal: false, isRequired: false, transformFunction: null }, anchorDateTime: { classPropertyName: "anchorDateTime", publicName: "anchorDateTime", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange" }, providers: [IntervalPickerModel, { provide: DateAdapter, useClass: CustomDateAdapter }], viewQueries: [{ propertyName: "calendarStart", first: true, predicate: ["rangeCalendarStart"], descendants: true }, { propertyName: "calendarEnd", first: true, predicate: ["rangeCalendarEnd"], descendants: true }, { propertyName: "calendarStartElRef", first: true, predicate: ["rangeCalendarStart"], descendants: true, read: ElementRef }, { propertyName: "calendarEndElRef", first: true, predicate: ["rangeCalendarEnd"], descendants: true, read: ElementRef }, { propertyName: "startDateInput", first: true, predicate: ["startDateInput"], descendants: true }, { propertyName: "endDateInput", first: true, predicate: ["endDateInput"], descendants: true }], ngImport: i0, template: "<div class=\"interval-picker-component p-md layout-col gap-xxl\">\n <div class=\"layout-row gap-xxl place-between-start\" style=\"gap: 5%\">\n <div class=\"layout-col gap-md pt-xs\">\n <ng-container *ngTemplateOutlet=\"intervalSelector\"></ng-container>\n </div>\n <div class=\"layout-col\">\n <!-- smart shift -->\n <div class=\"layout-row place-around-center\">\n <button mat-icon-button (click)=\"model.editor.smartShift(-1)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ model.viewIntervalMessage() }}</span>\n <button mat-icon-button (click)=\"model.editor.smartShift(1)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- calendars and input controls -->\n <ng-container *ngTemplateOutlet=\"calendarsTemplate\"></ng-container>\n </div>\n <div class=\"pt-xs\" style=\"width: 25%\">\n <div class=\"layout-col gap-lg\">\n <div class=\"layout-col gap-xs place-start-start\">\n @if (showHelpText()) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectSmartInterval' | translate }}</h5>\n }\n <!-- select current -->\n <button mat-button (click)=\"model.editor.selectCurrentWeek()\">\n {{ 'intervalPicker.currentPeriod.week' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectCurrentMonth()\">\n {{ 'intervalPicker.currentPeriod.month' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectCurrentQuarter()\">\n {{ 'intervalPicker.currentPeriod.quarter' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectCurrentYear()\">\n {{ 'intervalPicker.currentPeriod.year' | translate }}\n </button>\n </div>\n <div class=\"fixed-shifts-container\">\n <ng-container *ngTemplateOutlet=\"fixedShifts\"></ng-container>\n </div>\n </div>\n </div>\n </div>\n <div class=\"layout-row place-between-center gap-xxl pt-sm\">\n <div>\n @if (showAnchor()) {\n <ng-container *ngTemplateOutlet=\"anchorInputField\"></ng-container>\n }\n </div>\n @if (showResultText()) {\n <!-- result interval -->\n <div class=\"layout-col place-center-center\">\n <div class=\"date-interval mat-caption pt-xs\">\n @if (model.startDateTimeAsJSDate()) {\n {{ model.startDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.startDateNotSet' | translate }}\n }\n <span> - </span>\n @if (model.endDateTimeAsJSDate()) {\n {{ model.endDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.endDateNotSet' | translate }}\n }\n </div>\n <div>\n <span class=\"mat-caption\">{{ model.deltaHumanReadable() || '&nbsp;' }}</span>\n </div>\n </div>\n }\n <div class=\"layout-row gap-lg\">\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"clearStartAndEndDateTimes()\"\n [disabled]=\"model.isStartAndEndDatesEmpty()\"\n >\n {{ 'intervalPicker.clear' | translate }}\n </button>\n\n @if (!this.emitOnChange()) {\n <button color=\"primary\" mat-raised-button (click)=\"model.emitMainDates()\">\n {{ 'actions.ok' | translate }}\n </button>\n }\n </div>\n </div>\n</div>\n\n<ng-template #intervalSelector>\n <div class=\"layout-col\">\n @if (showHelpText()) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectAbsoluteInterval' | translate }}</h5>\n }\n <div class=\"layout-row select-buttons-container gap-sm\">\n <div class=\"layout-col gap-xs place-start-stretch\">\n <button mat-button (click)=\"model.editor.selectCurrentDay()\">\n @if (model.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.anchorDay' | translate }}\n } @else {\n {{ 'intervalPicker.today' | translate }}\n }\n </button>\n <button mat-button (click)=\"model.editor.selectYesterday()\">\n @if (model.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.last' | translate }} 1 {{ 'intervalPicker.day' | translate }}\n } @else {\n {{ 'intervalPicker.yesterday' | translate }}\n }\n </button>\n @if (lastExcludesToday()) {\n <button mat-button (click)=\"model.editor.selectLastSevenDaysExcludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectLastThirtyDaysExcludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n } @else {\n <button mat-button (click)=\"model.editor.selectLastSevenDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectLastThirtyDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n }\n @if (intervalInputMode() === 'date-time-range') {\n <div class=\"pt-sm\"></div>\n <button mat-button (click)=\"model.editor.selectLastFiveMinutes()\">\n {{ 'intervalPicker.last' | translate }} 5 {{ 'intervalPicker.minutes' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectLastHour()\">\n {{ 'intervalPicker.last' | translate }} {{ 'intervalPicker.hour' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectLast24Hours()\">\n {{ 'intervalPicker.last' | translate }} 24 {{ 'intervalPicker.hours' | translate }}\n </button>\n }\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #calendarsTemplate>\n <div class=\"layout-row place-around-center\" style=\"align-items: flex-start; min-height: 280px\">\n <mat-calendar\n #rangeCalendarStart\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"model.dateRangeForCalendar()\"\n (selectedChange)=\"handleStartCalendarChange($event)\"\n [maxDate]=\"model.endDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n <mat-calendar\n #rangeCalendarEnd\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"model.dateRangeForCalendar()\"\n (selectedChange)=\"handleEndCalendarChange($event)\"\n [minDate]=\"model.startDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n </div>\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startDate' | translate }}</mat-label>\n <input\n #startDateInput\n name=\"startDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"model.startDateHtmlString()\"\n (ngModelChange)=\"model.setStartDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearStartDateTime()\"\n [disabled]=\"!this.model.startDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endDate' | translate }}</mat-label>\n <input\n #endDateInput\n name=\"endDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"model.endDateHtmlString()\"\n (ngModelChange)=\"model.setEndDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearEndDateTime()\"\n [disabled]=\"!this.model.endDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n <br />\n @if (intervalInputMode() === 'date-time-range') {\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startTime' | translate }}</mat-label>\n <input\n name=\"startTimeInput\"\n matInput\n type=\"time\"\n #startTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"model.getStartTimeString()\"\n (ngModelChange)=\"model.setStartTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.model.clearStartTime()\"\n [disabled]=\"!this.model.isStartTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endTime' | translate }}</mat-label>\n <input\n name=\"endTimeInput\"\n matInput\n type=\"time\"\n #endTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"model.getEndTimeString()\"\n (ngModelChange)=\"model.setEndTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.model.clearEndTime()\"\n [disabled]=\"!this.model.isEndTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n }\n</ng-template>\n\n<ng-template #fixedShifts>\n @if (showHelpText()) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.shiftInterval' | translate }}</h5>\n }\n <div class=\"layout-col place-start-stretch\">\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"model.editor.shiftDay(-1)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.day' | translate }}</span>\n <button mat-icon-button (click)=\"model.editor.shiftDay(1)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"model.editor.shiftMonth(-1, true)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.month' | translate }}</span>\n <button mat-icon-button (click)=\"model.editor.shiftMonth(1, true)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"model.editor.shiftYear(-1, true)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.year' | translate }}</span>\n <button mat-icon-button (click)=\"model.editor.shiftYear(1, true)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n\n @if (intervalInputMode() === 'date-time-range') {\n <!-- shift minute -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"model.editor.shiftTime(-1, 'minutes')\"\n [disabled]=\"model.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.minute' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"model.editor.shiftTime(1, 'minutes')\"\n [disabled]=\"model.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- shift hour -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"model.editor.shiftTime(-1, 'hours')\"\n [disabled]=\"model.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.hour' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"model.editor.shiftTime(1, 'hours')\"\n [disabled]=\"model.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #anchorInputField>\n <div class=\"layout-row flex-none gap-md\">\n <mat-menu #anchorMenu=\"matMenu\">\n @if (model.startDate()) {\n <button\n mat-menu-item\n (click)=\"model.setFixedAnchorPointToEndDateTime()\"\n [disabled]=\"!model.endDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">login</mat-icon>\n <span>{{ 'intervalPicker.endDate' | translate }}</span>\n </button>\n }\n @if (model.endDate()) {\n <button\n mat-menu-item\n (click)=\"model.setFixedAnchorPointToStartDateTime()\"\n [disabled]=\"!model.startDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">logout</mat-icon>\n <span>{{ 'intervalPicker.startDate' | translate }}</span>\n </button>\n }\n @if (model.fixedAnchorDate()) {\n <button\n mat-menu-item\n (click)=\"this.model.resetFixedAnchorPoint()\"\n [disabled]=\"!model.fixedAnchorDate() || anchorReadOnly()\"\n >\n <mat-icon>close</mat-icon>\n <span>{{ 'intervalPicker.clear' | translate }}</span>\n </button>\n }\n </mat-menu>\n\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorDate' | translate }}</mat-label>\n <elder-local-date-input\n name=\"anchorDateInput\"\n (valueUpdated)=\"model.setAnchorDateFromForm($event)\"\n [value]=\"model.getAnchorPointAsLocaleDate()\"\n [readonly]=\"anchorReadOnly()\"\n >\n </elder-local-date-input>\n @if (!anchorReadOnly()) {\n <button\n mat-icon-button\n matSuffix\n [matMenuTriggerFor]=\"anchorMenu\"\n [disabled]=\"model.isStartAndEndDatesEmpty() && !model.fixedAnchorDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">more_horiz</mat-icon>\n </button>\n }\n </mat-form-field>\n @if (intervalInputMode() === 'date-time-range') {\n <mat-form-field class=\"input-control-container-short\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorTime' | translate }}</mat-label>\n <input\n matInput\n name=\"anchorTimeInput\"\n type=\"time\"\n #anchorTimeControl=\"ngModel\"\n step=\"1\"\n [readonly]=\"anchorReadOnly()\"\n [ngModel]=\"model.getAnchorTimeString()\"\n (ngModelChange)=\"model.setAnchorTimeFromForm($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.model.resetFixedAnchorTime()\"\n [disabled]=\"!model.isFixedAnchorTimeSetAndNotMidnight() || anchorReadOnly()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n }\n </div>\n</ng-template>\n", styles: [".interval-picker-component{min-width:840px;max-width:100%}.fixed-shifts-container{max-width:160px}.input-control-container{width:192px;max-width:100%}.input-control-container-short{width:140px;max-width:100%}.select-buttons-container button{white-space:nowrap;text-align:left;justify-content:flex-start}::ng-deep .interval-picker-component .mat-calendar-body-cell.elder-custom-anchor-date .mat-calendar-body-cell-content{border-radius:50%;background-color:#def;background-color:#b4d2ebbf}\n"], dependencies: [{ kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i2$5.MatCalendar, selector: "mat-calendar", inputs: ["headerComponent", "startAt", "startView", "selected", "minDate", "maxDate", "dateFilter", "dateClass", "comparisonStart", "comparisonEnd", "startDateAccessibleName", "endDateAccessibleName"], outputs: ["selectedChange", "yearSelected", "monthSelected", "viewChanged", "_userSelection", "_userDragDrop"], exportAs: ["matCalendar"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$a.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$a.MatLabel, selector: "mat-label" }, { kind: "directive", type: i1$a.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i2$1.DatePipe, name: "date" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: FormsModule }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i8.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i8.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: ElderLocalDateInputComponent, selector: "elder-local-date-input", inputs: ["zone", "autoDatePicker", "arrows", "today", "center", "datePickerTouchUi", "allowNull", "datePickerEnabled", "isoValue", "dateValue", "isoDateValue"], outputs: ["blurred", "valueUpdatedBlur", "isoValueChange", "dateValueChange", "isoDateValueChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i10.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i10.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i10.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
29768
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderIntervalPickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
29769
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.5", type: ElderIntervalPickerComponent, isStandalone: true, selector: "elder-interval-picker", inputs: { autoEmitMode: { classPropertyName: "autoEmitMode", publicName: "autoEmitMode", isSignal: false, isRequired: false, transformFunction: null }, emitOnChange: { classPropertyName: "emitOnChange", publicName: "emitOnChange", isSignal: false, isRequired: false, transformFunction: null }, emitType: { classPropertyName: "emitType", publicName: "emitType", isSignal: false, isRequired: false, transformFunction: null }, intervalInputMode: { classPropertyName: "intervalInputMode", publicName: "intervalInputMode", isSignal: true, isRequired: false, transformFunction: null }, showAnchor: { classPropertyName: "showAnchor", publicName: "showAnchor", isSignal: true, isRequired: false, transformFunction: null }, anchorReadOnly: { classPropertyName: "anchorReadOnly", publicName: "anchorReadOnly", isSignal: true, isRequired: false, transformFunction: null }, externalAnchorDateTime: { classPropertyName: "externalAnchorDateTime", publicName: "externalAnchorDateTime", isSignal: true, isRequired: false, transformFunction: null }, externalInterval: { classPropertyName: "externalInterval", publicName: "externalInterval", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { intervalChange: "intervalChange" }, providers: [{ provide: DateAdapter, useClass: CustomDateAdapter }], viewQueries: [{ propertyName: "calendarStart", first: true, predicate: ["rangeCalendarStart"], descendants: true }, { propertyName: "calendarEnd", first: true, predicate: ["rangeCalendarEnd"], descendants: true }, { propertyName: "calendarStartElRef", first: true, predicate: ["rangeCalendarStart"], descendants: true, read: ElementRef }, { propertyName: "calendarEndElRef", first: true, predicate: ["rangeCalendarEnd"], descendants: true, read: ElementRef }, { propertyName: "startDateInput", first: true, predicate: ["startDateInput"], descendants: true }, { propertyName: "endDateInput", first: true, predicate: ["endDateInput"], descendants: true }], ngImport: i0, template: "<div class=\"interval-picker-component p-md layout-col gap-xxl\">\n <div class=\"layout-row gap-xxl place-between-start\" style=\"gap: 5%\">\n <div class=\"layout-col gap-md pt-xs\">\n <div class=\"layout-col\">\n <div class=\"layout-row select-buttons-container gap-sm\">\n <div class=\"layout-col gap-xs place-start-stretch\">\n <button mat-button (click)=\"controller.select.selectCurrentDay()\">\n @if (presenter.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.anchorDay' | translate }}\n } @else {\n {{ 'intervalPicker.today' | translate }}\n }\n </button>\n <button mat-button (click)=\"controller.select.selectYesterday()\">\n @if (presenter.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.last' | translate }} 1 {{ 'intervalPicker.day' | translate }}\n } @else {\n {{ 'intervalPicker.yesterday' | translate }}\n }\n </button>\n <button mat-button (click)=\"controller.select.selectLastSevenDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7\n {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectLastThirtyDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30\n {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectLast365daysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 365\n {{ 'intervalPicker.days' | translate }}\n </button>\n @if (intervalInputMode() === 'date-time-range') {\n <div class=\"pt-sm\"></div>\n <button mat-button (click)=\"controller.select.selectLastFiveMinutes()\">\n {{ 'intervalPicker.last' | translate }} 5\n {{ 'intervalPicker.minutes' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectLastHour()\">\n {{ 'intervalPicker.last' | translate }} {{ 'intervalPicker.hour' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectLast24Hours()\">\n {{ 'intervalPicker.last' | translate }} 24\n {{ 'intervalPicker.hours' | translate }}\n </button>\n }\n </div>\n </div>\n </div>\n </div>\n <div class=\"layout-col\">\n <!-- smart shift -->\n <div class=\"layout-row place-around-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.smartShift(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ presenter.smartShiftMessage() }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.smartShift(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- calendars and input controls -->\n <div\n class=\"layout-row place-around-center\"\n style=\"align-items: flex-start; min-height: 280px\"\n >\n <mat-calendar\n #rangeCalendarStart\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"presenter.dateRangeForCalendar()\"\n (selectedChange)=\"controller.calendar.setStartDateFromJSDate($event)\"\n [maxDate]=\"presenter.endDateTimeAsJSDate()\"\n [dateClass]=\"presenter.calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n <mat-calendar\n #rangeCalendarEnd\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"presenter.dateRangeForCalendar()\"\n (selectedChange)=\"controller.calendar.setEndDateFromJSDate($event)\"\n [minDate]=\"presenter.startDateTimeAsJSDate()\"\n [dateClass]=\"presenter.calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n </div>\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startDate' | translate }}</mat-label>\n <input\n #startDateInput\n name=\"startDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"presenter.startDateHtmlString()\"\n (ngModelChange)=\"controller.form.setStartDateFromString($event)\"\n />\n </mat-form-field>\n </div>\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endDate' | translate }}</mat-label>\n <input\n #endDateInput\n name=\"endDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"presenter.endDateHtmlString()\"\n (ngModelChange)=\"controller.form.setEndDateFromString($event)\"\n />\n </mat-form-field>\n </div>\n </div>\n @if (intervalInputMode() === 'date-time-range') {\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startTime' | translate }}</mat-label>\n <input\n name=\"startTimeInput\"\n matInput\n type=\"time\"\n #startTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"presenter.startTimeHtmlString()\"\n (ngModelChange)=\"controller.form.setStartTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"controller.clearStartTime()\"\n [disabled]=\"!presenter.isStartTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endTime' | translate }}</mat-label>\n <input\n name=\"endTimeInput\"\n matInput\n type=\"time\"\n #endTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"presenter.endTimeHtmlString()\"\n (ngModelChange)=\"controller.form.setEndTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"controller.clearEndTime()\"\n [disabled]=\"!presenter.isEndTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n }\n <br />\n </div>\n <div class=\"pt-xs\" style=\"width: 25%\">\n <div class=\"layout-col gap-lg\">\n <div class=\"layout-col gap-xs place-start-start\">\n <!-- select current -->\n <button mat-button (click)=\"controller.select.selectCurrentWeek()\">\n {{ 'intervalPicker.currentPeriod.week' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectCurrentMonth()\">\n {{ 'intervalPicker.currentPeriod.month' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectCurrentQuarter()\">\n {{ 'intervalPicker.currentPeriod.quarter' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectCurrentYear()\">\n {{ 'intervalPicker.currentPeriod.year' | translate }}\n </button>\n </div>\n <div class=\"fixed-shifts-container\">\n <div class=\"layout-col place-start-stretch\">\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftDay(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.day' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftDay(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftMonth(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.month' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftMonth(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftYear(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.year' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftYear(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n\n @if (true) {\n <!-- shift minute -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftMinute(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.minute' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftMinute(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- shift hour -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftHour(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.hour' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftHour(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n<div class=\"layout-row place-between-center gap-xxl pt-sm\">\n <div>\n @if (showAnchor()) {\n <div class=\"layout-row flex-none gap-md\">\n <mat-menu #anchorMenu=\"matMenu\">\n @if (presenter.startDateHtmlString()) {\n <button\n mat-menu-item\n (click)=\"controller.anchor.setFixedAnchorPointToEndDateTime()\"\n [disabled]=\"!presenter.startDateHtmlString()\"\n >\n <mat-icon class=\"material-symbols-outlined\">login</mat-icon>\n <span>{{ 'intervalPicker.endDate' | translate }}</span>\n </button>\n }\n @if (presenter.endDateHtmlString()) {\n <button\n mat-menu-item\n (click)=\"controller.anchor.setFixedAnchorPointToStartDateTime()\"\n [disabled]=\"!presenter.endDateHtmlString()\"\n >\n <mat-icon class=\"material-symbols-outlined\">logout</mat-icon>\n <span>{{ 'intervalPicker.startDate' | translate }}</span>\n </button>\n }\n @if (presenter.isFixedAnchorDateSet()) {\n <button\n mat-menu-item\n (click)=\"controller.anchor.resetAnchor()\"\n [disabled]=\"!presenter.isFixedAnchorDateSet() || anchorReadOnly()\"\n >\n <mat-icon>close</mat-icon>\n <span>{{ 'intervalPicker.clear' | translate }}</span>\n </button>\n }\n </mat-menu>\n\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorDate' | translate }}</mat-label>\n <input\n #startDateInput\n name=\"anchorDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"presenter.anchorDateHtmlString()\"\n (ngModelChange)=\"controller.form.setAnchorDateFromString($event)\"\n [readonly]=\"anchorReadOnly()\"\n />\n @if (!anchorReadOnly()) {\n <button mat-icon-button matSuffix [matMenuTriggerFor]=\"anchorMenu\" [disabled]=\"presenter.isAnchorMenuDisabled()\">\n <mat-icon class=\"material-symbols-outlined\">more_horiz</mat-icon>\n </button>\n }\n </mat-form-field>\n @if (intervalInputMode() === 'date-time-range') {\n <mat-form-field class=\"input-control-container-short\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorTime' | translate }}</mat-label>\n <input\n matInput\n name=\"anchorTimeInput\"\n type=\"time\"\n #anchorTimeControl=\"ngModel\"\n step=\"1\"\n [readonly]=\"anchorReadOnly()\"\n [ngModel]=\"presenter.anchorTimeHtmlString()\"\n (ngModelChange)=\"controller.form.setAnchorTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"controller.anchor.resetAnchorTime()\"\n [disabled]=\"anchorReadOnly() || presenter.isAnchorTimeMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n }\n </div>\n }\n </div>\n <!-- result interval -->\n <div class=\"layout-col place-center-center\">\n <div class=\"date-interval mat-caption pt-xs\">\n @if (presenter.startDateTimeAsJSDate()) {\n {{ presenter.startDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.startDateNotSet' | translate }}\n }\n <span> - </span>\n @if (presenter.endDateTimeAsJSDate()) {\n {{ presenter.endDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.endDateNotSet' | translate }}\n }\n </div>\n <div>\n <span class=\"mat-caption\">{{ presenter.deltaHumanReadable() || '&nbsp;' }}</span>\n </div>\n </div>\n <div class=\"layout-row gap-lg\">\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"controller.clearInterval()\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n {{ 'intervalPicker.clear' | translate }}\n </button>\n\n @if (!this.autoEmitMode) {\n <button color=\"primary\" mat-raised-button (click)=\"controller.manualEmit()\">\n {{ 'actions.ok' | translate }}\n </button>\n }\n </div>\n</div>\n", styles: [".interval-picker-component{min-width:840px;max-width:100%}.fixed-shifts-container{max-width:160px}.input-control-container{width:192px;max-width:100%}.input-control-container-short{width:140px;max-width:100%}.select-buttons-container button{white-space:nowrap;text-align:left;justify-content:flex-start}::ng-deep .interval-picker-component .mat-calendar-body-cell.elder-custom-anchor-date .mat-calendar-body-cell-content{border-radius:50%;background-color:#def;background-color:#b4d2ebbf}\n"], dependencies: [{ kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i1$c.MatCalendar, selector: "mat-calendar", inputs: ["headerComponent", "startAt", "startView", "selected", "minDate", "maxDate", "dateFilter", "dateClass", "comparisonStart", "comparisonEnd", "startDateAccessibleName", "endDateAccessibleName"], outputs: ["selectedChange", "yearSelected", "monthSelected", "viewChanged", "_userSelection", "_userDragDrop"], exportAs: ["matCalendar"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$a.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$a.MatLabel, selector: "mat-label" }, { kind: "directive", type: i1$a.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i2$1.DatePipe, name: "date" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: FormsModule }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i7.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i7.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i9.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i9.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i9.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
29820
29770
  }
29821
29771
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderIntervalPickerComponent, decorators: [{
29822
29772
  type: Component,
@@ -29834,12 +29784,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
29834
29784
  FormsModule,
29835
29785
  MatButtonModule,
29836
29786
  MatCalendar,
29837
- ElderLocalDateInputComponent,
29838
29787
  MatTooltip,
29839
29788
  TranslateModule,
29840
29789
  MatMenuModule,
29841
- ], providers: [IntervalPickerModel, { provide: DateAdapter, useClass: CustomDateAdapter }], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"interval-picker-component p-md layout-col gap-xxl\">\n <div class=\"layout-row gap-xxl place-between-start\" style=\"gap: 5%\">\n <div class=\"layout-col gap-md pt-xs\">\n <ng-container *ngTemplateOutlet=\"intervalSelector\"></ng-container>\n </div>\n <div class=\"layout-col\">\n <!-- smart shift -->\n <div class=\"layout-row place-around-center\">\n <button mat-icon-button (click)=\"model.editor.smartShift(-1)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ model.viewIntervalMessage() }}</span>\n <button mat-icon-button (click)=\"model.editor.smartShift(1)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- calendars and input controls -->\n <ng-container *ngTemplateOutlet=\"calendarsTemplate\"></ng-container>\n </div>\n <div class=\"pt-xs\" style=\"width: 25%\">\n <div class=\"layout-col gap-lg\">\n <div class=\"layout-col gap-xs place-start-start\">\n @if (showHelpText()) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectSmartInterval' | translate }}</h5>\n }\n <!-- select current -->\n <button mat-button (click)=\"model.editor.selectCurrentWeek()\">\n {{ 'intervalPicker.currentPeriod.week' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectCurrentMonth()\">\n {{ 'intervalPicker.currentPeriod.month' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectCurrentQuarter()\">\n {{ 'intervalPicker.currentPeriod.quarter' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectCurrentYear()\">\n {{ 'intervalPicker.currentPeriod.year' | translate }}\n </button>\n </div>\n <div class=\"fixed-shifts-container\">\n <ng-container *ngTemplateOutlet=\"fixedShifts\"></ng-container>\n </div>\n </div>\n </div>\n </div>\n <div class=\"layout-row place-between-center gap-xxl pt-sm\">\n <div>\n @if (showAnchor()) {\n <ng-container *ngTemplateOutlet=\"anchorInputField\"></ng-container>\n }\n </div>\n @if (showResultText()) {\n <!-- result interval -->\n <div class=\"layout-col place-center-center\">\n <div class=\"date-interval mat-caption pt-xs\">\n @if (model.startDateTimeAsJSDate()) {\n {{ model.startDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.startDateNotSet' | translate }}\n }\n <span> - </span>\n @if (model.endDateTimeAsJSDate()) {\n {{ model.endDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.endDateNotSet' | translate }}\n }\n </div>\n <div>\n <span class=\"mat-caption\">{{ model.deltaHumanReadable() || '&nbsp;' }}</span>\n </div>\n </div>\n }\n <div class=\"layout-row gap-lg\">\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"clearStartAndEndDateTimes()\"\n [disabled]=\"model.isStartAndEndDatesEmpty()\"\n >\n {{ 'intervalPicker.clear' | translate }}\n </button>\n\n @if (!this.emitOnChange()) {\n <button color=\"primary\" mat-raised-button (click)=\"model.emitMainDates()\">\n {{ 'actions.ok' | translate }}\n </button>\n }\n </div>\n </div>\n</div>\n\n<ng-template #intervalSelector>\n <div class=\"layout-col\">\n @if (showHelpText()) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectAbsoluteInterval' | translate }}</h5>\n }\n <div class=\"layout-row select-buttons-container gap-sm\">\n <div class=\"layout-col gap-xs place-start-stretch\">\n <button mat-button (click)=\"model.editor.selectCurrentDay()\">\n @if (model.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.anchorDay' | translate }}\n } @else {\n {{ 'intervalPicker.today' | translate }}\n }\n </button>\n <button mat-button (click)=\"model.editor.selectYesterday()\">\n @if (model.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.last' | translate }} 1 {{ 'intervalPicker.day' | translate }}\n } @else {\n {{ 'intervalPicker.yesterday' | translate }}\n }\n </button>\n @if (lastExcludesToday()) {\n <button mat-button (click)=\"model.editor.selectLastSevenDaysExcludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectLastThirtyDaysExcludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n } @else {\n <button mat-button (click)=\"model.editor.selectLastSevenDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectLastThirtyDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n }\n @if (intervalInputMode() === 'date-time-range') {\n <div class=\"pt-sm\"></div>\n <button mat-button (click)=\"model.editor.selectLastFiveMinutes()\">\n {{ 'intervalPicker.last' | translate }} 5 {{ 'intervalPicker.minutes' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectLastHour()\">\n {{ 'intervalPicker.last' | translate }} {{ 'intervalPicker.hour' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectLast24Hours()\">\n {{ 'intervalPicker.last' | translate }} 24 {{ 'intervalPicker.hours' | translate }}\n </button>\n }\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #calendarsTemplate>\n <div class=\"layout-row place-around-center\" style=\"align-items: flex-start; min-height: 280px\">\n <mat-calendar\n #rangeCalendarStart\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"model.dateRangeForCalendar()\"\n (selectedChange)=\"handleStartCalendarChange($event)\"\n [maxDate]=\"model.endDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n <mat-calendar\n #rangeCalendarEnd\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"model.dateRangeForCalendar()\"\n (selectedChange)=\"handleEndCalendarChange($event)\"\n [minDate]=\"model.startDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n </div>\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startDate' | translate }}</mat-label>\n <input\n #startDateInput\n name=\"startDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"model.startDateHtmlString()\"\n (ngModelChange)=\"model.setStartDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearStartDateTime()\"\n [disabled]=\"!this.model.startDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endDate' | translate }}</mat-label>\n <input\n #endDateInput\n name=\"endDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"model.endDateHtmlString()\"\n (ngModelChange)=\"model.setEndDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearEndDateTime()\"\n [disabled]=\"!this.model.endDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n <br />\n @if (intervalInputMode() === 'date-time-range') {\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startTime' | translate }}</mat-label>\n <input\n name=\"startTimeInput\"\n matInput\n type=\"time\"\n #startTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"model.getStartTimeString()\"\n (ngModelChange)=\"model.setStartTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.model.clearStartTime()\"\n [disabled]=\"!this.model.isStartTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endTime' | translate }}</mat-label>\n <input\n name=\"endTimeInput\"\n matInput\n type=\"time\"\n #endTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"model.getEndTimeString()\"\n (ngModelChange)=\"model.setEndTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.model.clearEndTime()\"\n [disabled]=\"!this.model.isEndTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n }\n</ng-template>\n\n<ng-template #fixedShifts>\n @if (showHelpText()) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.shiftInterval' | translate }}</h5>\n }\n <div class=\"layout-col place-start-stretch\">\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"model.editor.shiftDay(-1)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.day' | translate }}</span>\n <button mat-icon-button (click)=\"model.editor.shiftDay(1)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"model.editor.shiftMonth(-1, true)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.month' | translate }}</span>\n <button mat-icon-button (click)=\"model.editor.shiftMonth(1, true)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"model.editor.shiftYear(-1, true)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.year' | translate }}</span>\n <button mat-icon-button (click)=\"model.editor.shiftYear(1, true)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n\n @if (intervalInputMode() === 'date-time-range') {\n <!-- shift minute -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"model.editor.shiftTime(-1, 'minutes')\"\n [disabled]=\"model.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.minute' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"model.editor.shiftTime(1, 'minutes')\"\n [disabled]=\"model.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- shift hour -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"model.editor.shiftTime(-1, 'hours')\"\n [disabled]=\"model.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.hour' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"model.editor.shiftTime(1, 'hours')\"\n [disabled]=\"model.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #anchorInputField>\n <div class=\"layout-row flex-none gap-md\">\n <mat-menu #anchorMenu=\"matMenu\">\n @if (model.startDate()) {\n <button\n mat-menu-item\n (click)=\"model.setFixedAnchorPointToEndDateTime()\"\n [disabled]=\"!model.endDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">login</mat-icon>\n <span>{{ 'intervalPicker.endDate' | translate }}</span>\n </button>\n }\n @if (model.endDate()) {\n <button\n mat-menu-item\n (click)=\"model.setFixedAnchorPointToStartDateTime()\"\n [disabled]=\"!model.startDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">logout</mat-icon>\n <span>{{ 'intervalPicker.startDate' | translate }}</span>\n </button>\n }\n @if (model.fixedAnchorDate()) {\n <button\n mat-menu-item\n (click)=\"this.model.resetFixedAnchorPoint()\"\n [disabled]=\"!model.fixedAnchorDate() || anchorReadOnly()\"\n >\n <mat-icon>close</mat-icon>\n <span>{{ 'intervalPicker.clear' | translate }}</span>\n </button>\n }\n </mat-menu>\n\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorDate' | translate }}</mat-label>\n <elder-local-date-input\n name=\"anchorDateInput\"\n (valueUpdated)=\"model.setAnchorDateFromForm($event)\"\n [value]=\"model.getAnchorPointAsLocaleDate()\"\n [readonly]=\"anchorReadOnly()\"\n >\n </elder-local-date-input>\n @if (!anchorReadOnly()) {\n <button\n mat-icon-button\n matSuffix\n [matMenuTriggerFor]=\"anchorMenu\"\n [disabled]=\"model.isStartAndEndDatesEmpty() && !model.fixedAnchorDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">more_horiz</mat-icon>\n </button>\n }\n </mat-form-field>\n @if (intervalInputMode() === 'date-time-range') {\n <mat-form-field class=\"input-control-container-short\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorTime' | translate }}</mat-label>\n <input\n matInput\n name=\"anchorTimeInput\"\n type=\"time\"\n #anchorTimeControl=\"ngModel\"\n step=\"1\"\n [readonly]=\"anchorReadOnly()\"\n [ngModel]=\"model.getAnchorTimeString()\"\n (ngModelChange)=\"model.setAnchorTimeFromForm($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.model.resetFixedAnchorTime()\"\n [disabled]=\"!model.isFixedAnchorTimeSetAndNotMidnight() || anchorReadOnly()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n }\n </div>\n</ng-template>\n", styles: [".interval-picker-component{min-width:840px;max-width:100%}.fixed-shifts-container{max-width:160px}.input-control-container{width:192px;max-width:100%}.input-control-container-short{width:140px;max-width:100%}.select-buttons-container button{white-space:nowrap;text-align:left;justify-content:flex-start}::ng-deep .interval-picker-component .mat-calendar-body-cell.elder-custom-anchor-date .mat-calendar-body-cell-content{border-radius:50%;background-color:#def;background-color:#b4d2ebbf}\n"] }]
29842
- }], ctorParameters: () => [{ type: IntervalPickerModel }], propDecorators: { calendarStart: [{
29790
+ ElderIntervalInputComponent,
29791
+ MatMenuModule,
29792
+ ], changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: DateAdapter, useClass: CustomDateAdapter }], template: "<div class=\"interval-picker-component p-md layout-col gap-xxl\">\n <div class=\"layout-row gap-xxl place-between-start\" style=\"gap: 5%\">\n <div class=\"layout-col gap-md pt-xs\">\n <div class=\"layout-col\">\n <div class=\"layout-row select-buttons-container gap-sm\">\n <div class=\"layout-col gap-xs place-start-stretch\">\n <button mat-button (click)=\"controller.select.selectCurrentDay()\">\n @if (presenter.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.anchorDay' | translate }}\n } @else {\n {{ 'intervalPicker.today' | translate }}\n }\n </button>\n <button mat-button (click)=\"controller.select.selectYesterday()\">\n @if (presenter.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.last' | translate }} 1 {{ 'intervalPicker.day' | translate }}\n } @else {\n {{ 'intervalPicker.yesterday' | translate }}\n }\n </button>\n <button mat-button (click)=\"controller.select.selectLastSevenDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7\n {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectLastThirtyDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30\n {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectLast365daysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 365\n {{ 'intervalPicker.days' | translate }}\n </button>\n @if (intervalInputMode() === 'date-time-range') {\n <div class=\"pt-sm\"></div>\n <button mat-button (click)=\"controller.select.selectLastFiveMinutes()\">\n {{ 'intervalPicker.last' | translate }} 5\n {{ 'intervalPicker.minutes' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectLastHour()\">\n {{ 'intervalPicker.last' | translate }} {{ 'intervalPicker.hour' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectLast24Hours()\">\n {{ 'intervalPicker.last' | translate }} 24\n {{ 'intervalPicker.hours' | translate }}\n </button>\n }\n </div>\n </div>\n </div>\n </div>\n <div class=\"layout-col\">\n <!-- smart shift -->\n <div class=\"layout-row place-around-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.smartShift(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ presenter.smartShiftMessage() }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.smartShift(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- calendars and input controls -->\n <div\n class=\"layout-row place-around-center\"\n style=\"align-items: flex-start; min-height: 280px\"\n >\n <mat-calendar\n #rangeCalendarStart\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"presenter.dateRangeForCalendar()\"\n (selectedChange)=\"controller.calendar.setStartDateFromJSDate($event)\"\n [maxDate]=\"presenter.endDateTimeAsJSDate()\"\n [dateClass]=\"presenter.calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n <mat-calendar\n #rangeCalendarEnd\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"presenter.dateRangeForCalendar()\"\n (selectedChange)=\"controller.calendar.setEndDateFromJSDate($event)\"\n [minDate]=\"presenter.startDateTimeAsJSDate()\"\n [dateClass]=\"presenter.calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n </div>\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startDate' | translate }}</mat-label>\n <input\n #startDateInput\n name=\"startDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"presenter.startDateHtmlString()\"\n (ngModelChange)=\"controller.form.setStartDateFromString($event)\"\n />\n </mat-form-field>\n </div>\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endDate' | translate }}</mat-label>\n <input\n #endDateInput\n name=\"endDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"presenter.endDateHtmlString()\"\n (ngModelChange)=\"controller.form.setEndDateFromString($event)\"\n />\n </mat-form-field>\n </div>\n </div>\n @if (intervalInputMode() === 'date-time-range') {\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startTime' | translate }}</mat-label>\n <input\n name=\"startTimeInput\"\n matInput\n type=\"time\"\n #startTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"presenter.startTimeHtmlString()\"\n (ngModelChange)=\"controller.form.setStartTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"controller.clearStartTime()\"\n [disabled]=\"!presenter.isStartTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endTime' | translate }}</mat-label>\n <input\n name=\"endTimeInput\"\n matInput\n type=\"time\"\n #endTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"presenter.endTimeHtmlString()\"\n (ngModelChange)=\"controller.form.setEndTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"controller.clearEndTime()\"\n [disabled]=\"!presenter.isEndTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n }\n <br />\n </div>\n <div class=\"pt-xs\" style=\"width: 25%\">\n <div class=\"layout-col gap-lg\">\n <div class=\"layout-col gap-xs place-start-start\">\n <!-- select current -->\n <button mat-button (click)=\"controller.select.selectCurrentWeek()\">\n {{ 'intervalPicker.currentPeriod.week' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectCurrentMonth()\">\n {{ 'intervalPicker.currentPeriod.month' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectCurrentQuarter()\">\n {{ 'intervalPicker.currentPeriod.quarter' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectCurrentYear()\">\n {{ 'intervalPicker.currentPeriod.year' | translate }}\n </button>\n </div>\n <div class=\"fixed-shifts-container\">\n <div class=\"layout-col place-start-stretch\">\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftDay(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.day' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftDay(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftMonth(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.month' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftMonth(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftYear(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.year' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftYear(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n\n @if (true) {\n <!-- shift minute -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftMinute(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.minute' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftMinute(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- shift hour -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftHour(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.hour' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftHour(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n<div class=\"layout-row place-between-center gap-xxl pt-sm\">\n <div>\n @if (showAnchor()) {\n <div class=\"layout-row flex-none gap-md\">\n <mat-menu #anchorMenu=\"matMenu\">\n @if (presenter.startDateHtmlString()) {\n <button\n mat-menu-item\n (click)=\"controller.anchor.setFixedAnchorPointToEndDateTime()\"\n [disabled]=\"!presenter.startDateHtmlString()\"\n >\n <mat-icon class=\"material-symbols-outlined\">login</mat-icon>\n <span>{{ 'intervalPicker.endDate' | translate }}</span>\n </button>\n }\n @if (presenter.endDateHtmlString()) {\n <button\n mat-menu-item\n (click)=\"controller.anchor.setFixedAnchorPointToStartDateTime()\"\n [disabled]=\"!presenter.endDateHtmlString()\"\n >\n <mat-icon class=\"material-symbols-outlined\">logout</mat-icon>\n <span>{{ 'intervalPicker.startDate' | translate }}</span>\n </button>\n }\n @if (presenter.isFixedAnchorDateSet()) {\n <button\n mat-menu-item\n (click)=\"controller.anchor.resetAnchor()\"\n [disabled]=\"!presenter.isFixedAnchorDateSet() || anchorReadOnly()\"\n >\n <mat-icon>close</mat-icon>\n <span>{{ 'intervalPicker.clear' | translate }}</span>\n </button>\n }\n </mat-menu>\n\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorDate' | translate }}</mat-label>\n <input\n #startDateInput\n name=\"anchorDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"presenter.anchorDateHtmlString()\"\n (ngModelChange)=\"controller.form.setAnchorDateFromString($event)\"\n [readonly]=\"anchorReadOnly()\"\n />\n @if (!anchorReadOnly()) {\n <button mat-icon-button matSuffix [matMenuTriggerFor]=\"anchorMenu\" [disabled]=\"presenter.isAnchorMenuDisabled()\">\n <mat-icon class=\"material-symbols-outlined\">more_horiz</mat-icon>\n </button>\n }\n </mat-form-field>\n @if (intervalInputMode() === 'date-time-range') {\n <mat-form-field class=\"input-control-container-short\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorTime' | translate }}</mat-label>\n <input\n matInput\n name=\"anchorTimeInput\"\n type=\"time\"\n #anchorTimeControl=\"ngModel\"\n step=\"1\"\n [readonly]=\"anchorReadOnly()\"\n [ngModel]=\"presenter.anchorTimeHtmlString()\"\n (ngModelChange)=\"controller.form.setAnchorTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"controller.anchor.resetAnchorTime()\"\n [disabled]=\"anchorReadOnly() || presenter.isAnchorTimeMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n }\n </div>\n }\n </div>\n <!-- result interval -->\n <div class=\"layout-col place-center-center\">\n <div class=\"date-interval mat-caption pt-xs\">\n @if (presenter.startDateTimeAsJSDate()) {\n {{ presenter.startDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.startDateNotSet' | translate }}\n }\n <span> - </span>\n @if (presenter.endDateTimeAsJSDate()) {\n {{ presenter.endDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.endDateNotSet' | translate }}\n }\n </div>\n <div>\n <span class=\"mat-caption\">{{ presenter.deltaHumanReadable() || '&nbsp;' }}</span>\n </div>\n </div>\n <div class=\"layout-row gap-lg\">\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"controller.clearInterval()\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n {{ 'intervalPicker.clear' | translate }}\n </button>\n\n @if (!this.autoEmitMode) {\n <button color=\"primary\" mat-raised-button (click)=\"controller.manualEmit()\">\n {{ 'actions.ok' | translate }}\n </button>\n }\n </div>\n</div>\n", styles: [".interval-picker-component{min-width:840px;max-width:100%}.fixed-shifts-container{max-width:160px}.input-control-container{width:192px;max-width:100%}.input-control-container-short{width:140px;max-width:100%}.select-buttons-container button{white-space:nowrap;text-align:left;justify-content:flex-start}::ng-deep .interval-picker-component .mat-calendar-body-cell.elder-custom-anchor-date .mat-calendar-body-cell-content{border-radius:50%;background-color:#def;background-color:#b4d2ebbf}\n"] }]
29793
+ }], ctorParameters: () => [], propDecorators: { intervalChange: [{
29794
+ type: Output
29795
+ }], autoEmitMode: [{
29796
+ type: Input
29797
+ }], emitOnChange: [{
29798
+ type: Input
29799
+ }], emitType: [{
29800
+ type: Input
29801
+ }], calendarStart: [{
29843
29802
  type: ViewChild,
29844
29803
  args: ['rangeCalendarStart']
29845
29804
  }], calendarEnd: [{
@@ -29857,12 +29816,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
29857
29816
  }], endDateInput: [{
29858
29817
  type: ViewChild,
29859
29818
  args: ['endDateInput']
29860
- }], dateChange: [{
29861
- type: Output
29862
- }], interval: [{
29863
- type: Input
29864
- }], anchorDateTime: [{
29865
- type: Input
29866
29819
  }] } });
29867
29820
 
29868
29821
  class ElderOverlayOriginDirective {
@@ -30170,7 +30123,7 @@ class ElderOverlayComponent {
30170
30123
  const searchPanelPortal = new TemplatePortal(this.templateRef, this.viewContainer);
30171
30124
  return this._overlayRef.attach(searchPanelPortal);
30172
30125
  }
30173
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderOverlayComponent, deps: [{ token: i0.ViewContainerRef }, { token: i1$c.Overlay }, { token: i1$c.OverlayPositionBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
30126
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderOverlayComponent, deps: [{ token: i0.ViewContainerRef }, { token: i1$d.Overlay }, { token: i1$d.OverlayPositionBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
30174
30127
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.5", type: ElderOverlayComponent, isStandalone: true, selector: "elder-overlay", inputs: { originX: "originX", originY: "originY", overlayX: "overlayX", overlayY: "overlayY", offsetY: "offsetY", offsetX: "offsetX", backdrop: "backdrop", backdropVisible: "backdropVisible", origin: "origin", positionStrategy: "positionStrategy", overlaySize: "overlaySize" }, outputs: { keydownEvents: "keydownEvents", attachedChange: "attachedChange" }, providers: [
30175
30128
  {
30176
30129
  provide: ElderOverlayRef,
@@ -30207,7 +30160,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
30207
30160
  },
30208
30161
  ],
30209
30162
  }]
30210
- }], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: i1$c.Overlay }, { type: i1$c.OverlayPositionBuilder }], propDecorators: { templateRef: [{
30163
+ }], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: i1$d.Overlay }, { type: i1$d.OverlayPositionBuilder }], propDecorators: { templateRef: [{
30211
30164
  type: ViewChild,
30212
30165
  args: [TemplateRef, { static: true }]
30213
30166
  }], originX: [{
@@ -30240,133 +30193,77 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
30240
30193
 
30241
30194
  class ElderIntervalPickerToggleComponent {
30242
30195
  constructor() {
30243
- /***************************************************************************
30244
- * *
30245
- * Fields *
30246
- * *
30247
- **************************************************************************/
30248
30196
  this.log = LoggerFactory.getLogger(this.constructor.name);
30249
- this.intervalInputElement = signal(undefined);
30250
- this.emitOnChange = input(true, { transform: (v) => booleanAttribute(v) });
30251
- this.showAnchor = input(false, { transform: (v) => booleanAttribute(v) });
30252
- this.anchorReadOnly = input(false, { transform: (v) => booleanAttribute(v) });
30253
- this.disabled = input(false, { transform: (v) => booleanAttribute(v) });
30254
- this.buttonDisabled = computed(() => this.intervalInputDisabled() || this.disabled());
30255
- this.intervalInputDisabled = signal(false);
30256
- this.showResultText = input(true, { transform: (v) => booleanAttribute(v) });
30257
- this.showHelpText = input(true, { transform: (v) => booleanAttribute(v) });
30258
- this.lastExcludesToday = input(false, { transform: (v) => booleanAttribute(v) });
30259
- this.anchorDateTime = input(null);
30260
- this.inputInterval = null;
30261
- this.intervalInputMode = 'date-range'; // will be overwritten by connected element after view init
30197
+ this.connectedIntervalInput = null;
30198
+ this.intervalInputMode = signal('date-time-range');
30199
+ this.emitType = signal('interval');
30200
+ this.externalInterval = signal(null);
30201
+ this.showAnchor = input(false);
30202
+ this.anchorReadOnly = input(false);
30203
+ this.externalAnchorDateTime = input(null);
30204
+ this.disabled = booleanAttribute(false);
30262
30205
  }
30263
30206
  /***************************************************************************
30264
30207
  * *
30265
30208
  * Life Cycle *
30266
30209
  * *
30267
30210
  **************************************************************************/
30268
- ngOnDestroy() {
30269
- this.inputIntervalElSubscription.unsubscribe();
30270
- }
30271
30211
  ngAfterViewInit() {
30272
- const intervalControl = this.intervalInputElement();
30273
- if (intervalControl.disabled) {
30274
- this.intervalInputDisabled.set(true);
30212
+ if (!this.connectedIntervalInput) {
30213
+ this.log.error('ElderIntervalPickerToggleComponent: connectedIntervalInput is required.');
30214
+ return;
30275
30215
  }
30276
- this.inputIntervalElSubscription = intervalControl.valueUpdated.subscribe({
30277
- next: (value) => this.updateModelInterval(this.coerceInterval(value)),
30216
+ this.intervalInputMode.set(this.connectedIntervalInput.mode);
30217
+ this.emitType.set(this.connectedIntervalInput.valueAsIsoStr ? 'iso' : 'interval');
30218
+ this.connectedIntervalInput.valueChange.subscribe((interval) => {
30219
+ this.externalInterval.set(interval);
30278
30220
  });
30279
- this.intervalInputMode = intervalControl.mode;
30280
- this.updateModelInterval(this.readIntervalInputValue(intervalControl));
30221
+ if (this.connectedIntervalInput.value) {
30222
+ // this is necessary to set the value of the interval picker
30223
+ this.externalInterval.set(this.connectedIntervalInput.value);
30224
+ }
30281
30225
  }
30282
30226
  /***************************************************************************
30283
30227
  * *
30284
30228
  * Public API *
30285
30229
  * *
30286
30230
  **************************************************************************/
30287
- handleOverlayAttachedChange(attached) {
30288
- if (this.emitOnChange()) {
30289
- return;
30290
- }
30291
- this.updateModelFromIntervalInput();
30292
- }
30293
- updateModelFromIntervalInput() {
30294
- this.updateModelInterval(this.readIntervalInputValue(this.intervalInputElement()));
30231
+ setConnectedIntervalInput(intervalInput) {
30232
+ this.connectedIntervalInput = intervalInput;
30295
30233
  }
30296
30234
  handleIntervalPickerDateChange(interval) {
30297
- this.inputInterval = interval;
30298
- this.updateIntervalInputElement(this.inputInterval);
30299
- }
30300
- registerInputComponent(inputComponent) {
30301
- this.intervalInputElement.set(inputComponent);
30302
- }
30303
- /***************************************************************************
30304
- * *
30305
- * Private methods *
30306
- * *
30307
- **************************************************************************/
30308
- updateModelInterval(value) {
30309
- this.inputInterval = value;
30310
- this.connectedIntervalPicker.model.setInterval(value);
30311
- }
30312
- updateIntervalInputElement(interval) {
30313
- const intervalControl = this.intervalInputElement();
30314
- if (intervalControl) {
30315
- intervalControl.value = interval;
30316
- }
30317
- }
30318
- readIntervalInputValue(intervalComponent) {
30319
- if (intervalComponent) {
30320
- return this.coerceInterval(intervalComponent.value);
30321
- }
30322
- return undefined;
30323
- }
30324
- coerceInterval(value) {
30325
- if (value instanceof Interval) {
30326
- return value;
30327
- }
30328
- else if (value != undefined) {
30329
- return Interval.parse(value);
30330
- }
30331
- else {
30332
- return undefined;
30333
- }
30235
+ this.connectedIntervalInput.value = interval;
30334
30236
  }
30335
30237
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderIntervalPickerToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
30336
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.5", type: ElderIntervalPickerToggleComponent, isStandalone: true, selector: "elder-interval-picker-toggle", inputs: { emitOnChange: { classPropertyName: "emitOnChange", publicName: "emitOnChange", isSignal: true, isRequired: false, transformFunction: null }, showAnchor: { classPropertyName: "showAnchor", publicName: "showAnchor", isSignal: true, isRequired: false, transformFunction: null }, anchorReadOnly: { classPropertyName: "anchorReadOnly", publicName: "anchorReadOnly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, showResultText: { classPropertyName: "showResultText", publicName: "showResultText", isSignal: true, isRequired: false, transformFunction: null }, showHelpText: { classPropertyName: "showHelpText", publicName: "showHelpText", isSignal: true, isRequired: false, transformFunction: null }, lastExcludesToday: { classPropertyName: "lastExcludesToday", publicName: "lastExcludesToday", isSignal: true, isRequired: false, transformFunction: null }, anchorDateTime: { classPropertyName: "anchorDateTime", publicName: "anchorDateTime", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "connectedIntervalPicker", first: true, predicate: ["connectedIntervalPicker"], descendants: true }], ngImport: i0, template: `
30238
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.5", type: ElderIntervalPickerToggleComponent, isStandalone: true, selector: "elder-interval-picker-toggle", inputs: { connectedIntervalInput: { classPropertyName: "connectedIntervalInput", publicName: "connectedIntervalInput", isSignal: false, isRequired: false, transformFunction: null }, showAnchor: { classPropertyName: "showAnchor", publicName: "showAnchor", isSignal: true, isRequired: false, transformFunction: null }, anchorReadOnly: { classPropertyName: "anchorReadOnly", publicName: "anchorReadOnly", isSignal: true, isRequired: false, transformFunction: null }, externalAnchorDateTime: { classPropertyName: "externalAnchorDateTime", publicName: "externalAnchorDateTime", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "connectedIntervalPicker", first: true, predicate: ["connectedIntervalPicker"], descendants: true }], ngImport: i0, template: `
30337
30239
  <span style="padding-right: 8px">
30338
30240
  <button
30339
30241
  mat-icon-button
30340
30242
  [elderOverlayOrigin]="dateIntervalOverlay"
30341
30243
  [elderOverlayTrigger]="dateIntervalOverlay"
30342
- [disabled]="buttonDisabled()"
30343
- (click)="updateModelFromIntervalInput()"
30344
30244
  class="elder-control-icon-button mat-datepicker-toggle"
30345
30245
  >
30346
30246
  <mat-icon>date_range</mat-icon>
30347
30247
  </button>
30348
30248
  </span>
30349
30249
 
30350
- <elder-overlay #dateIntervalOverlay (attachedChange)="handleOverlayAttachedChange($event)">
30250
+ <elder-overlay #dateIntervalOverlay>
30351
30251
  <elder-dialog-panel>
30352
30252
  <div class="pb-md pt-xs">
30353
30253
  <elder-interval-picker
30354
30254
  #connectedIntervalPicker
30355
- [intervalInputMode]="intervalInputMode"
30356
- [emitOnChange]="emitOnChange()"
30357
- [interval]="inputInterval"
30358
- (dateChange)="handleIntervalPickerDateChange($event)"
30255
+ [intervalInputMode]="intervalInputMode()"
30256
+ (intervalChange)="handleIntervalPickerDateChange($event)"
30257
+ [externalInterval]="externalInterval()"
30359
30258
  [showAnchor]="showAnchor()"
30360
- [anchorDateTime]="anchorDateTime()"
30361
30259
  [anchorReadOnly]="anchorReadOnly()"
30362
- [showResultText]="showResultText()"
30363
- [showHelpText]="showHelpText()"
30364
- [lastExcludesToday]="lastExcludesToday()"
30260
+ [externalAnchorDateTime]="externalAnchorDateTime()"
30261
+ [emitType]="emitType()"
30365
30262
  ></elder-interval-picker>
30366
30263
  </div>
30367
30264
  </elder-dialog-panel>
30368
30265
  </elder-overlay>
30369
- `, isInline: true, dependencies: [{ kind: "component", type: ElderIntervalPickerComponent, selector: "elder-interval-picker", inputs: ["emitOnChange", "intervalInputMode", "showAnchor", "anchorReadOnly", "showResultText", "showHelpText", "lastExcludesToday", "interval", "anchorDateTime"], outputs: ["dateChange"] }, { kind: "component", type: ElderOverlayComponent, selector: "elder-overlay", inputs: ["originX", "originY", "overlayX", "overlayY", "offsetY", "offsetX", "backdrop", "backdropVisible", "origin", "positionStrategy", "overlaySize"], outputs: ["keydownEvents", "attachedChange"], exportAs: ["elderOverlay"] }, { kind: "component", type: ElderDialogPanelComponent, selector: "elder-dialog-panel" }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: ElderOverlayTriggerDirective, selector: "[elderOverlayTrigger]", inputs: ["elderOverlayTrigger", "elderOverlayTriggerType", "elderOverlayTriggerEnabled"] }, { kind: "directive", type: ElderOverlayOriginDirective, selector: "[elderOverlayOrigin]", inputs: ["elderOverlayOrigin"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
30266
+ `, isInline: true, dependencies: [{ kind: "component", type: ElderIntervalPickerComponent, selector: "elder-interval-picker", inputs: ["autoEmitMode", "emitOnChange", "emitType", "intervalInputMode", "showAnchor", "anchorReadOnly", "externalAnchorDateTime", "externalInterval"], outputs: ["intervalChange"] }, { kind: "component", type: ElderOverlayComponent, selector: "elder-overlay", inputs: ["originX", "originY", "overlayX", "overlayY", "offsetY", "offsetX", "backdrop", "backdropVisible", "origin", "positionStrategy", "overlaySize"], outputs: ["keydownEvents", "attachedChange"], exportAs: ["elderOverlay"] }, { kind: "component", type: ElderDialogPanelComponent, selector: "elder-dialog-panel" }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: ElderOverlayTriggerDirective, selector: "[elderOverlayTrigger]", inputs: ["elderOverlayTrigger", "elderOverlayTriggerType", "elderOverlayTriggerEnabled"] }, { kind: "directive", type: ElderOverlayOriginDirective, selector: "[elderOverlayOrigin]", inputs: ["elderOverlayOrigin"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
30370
30267
  }
30371
30268
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderIntervalPickerToggleComponent, decorators: [{
30372
30269
  type: Component,
@@ -30392,29 +30289,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
30392
30289
  mat-icon-button
30393
30290
  [elderOverlayOrigin]="dateIntervalOverlay"
30394
30291
  [elderOverlayTrigger]="dateIntervalOverlay"
30395
- [disabled]="buttonDisabled()"
30396
- (click)="updateModelFromIntervalInput()"
30397
30292
  class="elder-control-icon-button mat-datepicker-toggle"
30398
30293
  >
30399
30294
  <mat-icon>date_range</mat-icon>
30400
30295
  </button>
30401
30296
  </span>
30402
30297
 
30403
- <elder-overlay #dateIntervalOverlay (attachedChange)="handleOverlayAttachedChange($event)">
30298
+ <elder-overlay #dateIntervalOverlay>
30404
30299
  <elder-dialog-panel>
30405
30300
  <div class="pb-md pt-xs">
30406
30301
  <elder-interval-picker
30407
30302
  #connectedIntervalPicker
30408
- [intervalInputMode]="intervalInputMode"
30409
- [emitOnChange]="emitOnChange()"
30410
- [interval]="inputInterval"
30411
- (dateChange)="handleIntervalPickerDateChange($event)"
30303
+ [intervalInputMode]="intervalInputMode()"
30304
+ (intervalChange)="handleIntervalPickerDateChange($event)"
30305
+ [externalInterval]="externalInterval()"
30412
30306
  [showAnchor]="showAnchor()"
30413
- [anchorDateTime]="anchorDateTime()"
30414
30307
  [anchorReadOnly]="anchorReadOnly()"
30415
- [showResultText]="showResultText()"
30416
- [showHelpText]="showHelpText()"
30417
- [lastExcludesToday]="lastExcludesToday()"
30308
+ [externalAnchorDateTime]="externalAnchorDateTime()"
30309
+ [emitType]="emitType()"
30418
30310
  ></elder-interval-picker>
30419
30311
  </div>
30420
30312
  </elder-dialog-panel>
@@ -30425,6 +30317,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
30425
30317
  }], propDecorators: { connectedIntervalPicker: [{
30426
30318
  type: ViewChild,
30427
30319
  args: ['connectedIntervalPicker']
30320
+ }], connectedIntervalInput: [{
30321
+ type: Input
30322
+ }], disabled: [{
30323
+ type: Input
30428
30324
  }] } });
30429
30325
 
30430
30326
  class ElderIntervalPickerBindingDirective {
@@ -30442,9 +30338,10 @@ class ElderIntervalPickerBindingDirective {
30442
30338
  ngAfterContentInit() {
30443
30339
  if (!this.intervalInputComponent || !this.intervalPickerToggleComponent) {
30444
30340
  console.error('ElderIntervalPickerBindingDirective: Both components are required, IntervalInputComponent and IntervalPickerToggleComponent.');
30341
+ return;
30445
30342
  }
30343
+ this.intervalPickerToggleComponent.connectedIntervalInput = this.intervalInputComponent;
30446
30344
  this.intervalInputComponent.isDefaultDatePickerDisabled = true;
30447
- this.intervalPickerToggleComponent.registerInputComponent(this.intervalInputComponent);
30448
30345
  }
30449
30346
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderIntervalPickerBindingDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
30450
30347
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.5", type: ElderIntervalPickerBindingDirective, isStandalone: true, selector: "[elderIntervalPickerBinding]", queries: [{ propertyName: "intervalInputComponent", first: true, predicate: ElderIntervalInputComponent, descendants: true }, { propertyName: "intervalPickerToggleComponent", first: true, predicate: ElderIntervalPickerToggleComponent, descendants: true }], ngImport: i0 }); }
@@ -35076,7 +34973,7 @@ class ElderTabDirective {
35076
34973
  constructor(tab) {
35077
34974
  this.tab = tab;
35078
34975
  }
35079
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderTabDirective, deps: [{ token: i1$d.MatTab }], target: i0.ɵɵFactoryTarget.Directive }); }
34976
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderTabDirective, deps: [{ token: i1$e.MatTab }], target: i0.ɵɵFactoryTarget.Directive }); }
35080
34977
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.5", type: ElderTabDirective, isStandalone: true, selector: "[elderTab]", inputs: { id: ["elderTab", "id"] }, ngImport: i0 }); }
35081
34978
  }
35082
34979
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderTabDirective, decorators: [{
@@ -35085,7 +34982,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
35085
34982
  selector: '[elderTab]',
35086
34983
  standalone: true,
35087
34984
  }]
35088
- }], ctorParameters: () => [{ type: i1$d.MatTab }], propDecorators: { id: [{
34985
+ }], ctorParameters: () => [{ type: i1$e.MatTab }], propDecorators: { id: [{
35089
34986
  type: Input,
35090
34987
  args: ['elderTab']
35091
34988
  }] } });
@@ -35316,7 +35213,7 @@ class ElderTabGroupRoutingDirective {
35316
35213
  serializeIndexMarker(index) {
35317
35214
  return ElderTabGroupRoutingDirective.TAB_INDEX_PREFIX + String(index);
35318
35215
  }
35319
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderTabGroupRoutingDirective, deps: [{ token: ElderUrlFragmentParamsService }, { token: i1$d.MatTabGroup }], target: i0.ɵɵFactoryTarget.Directive }); }
35216
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderTabGroupRoutingDirective, deps: [{ token: ElderUrlFragmentParamsService }, { token: i1$e.MatTabGroup }], target: i0.ɵɵFactoryTarget.Directive }); }
35320
35217
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.5", type: ElderTabGroupRoutingDirective, isStandalone: true, selector: "[elderTabGroupRouting]", inputs: { tabGroupQueryParamKey: ["elderTabGroupRouting", "tabGroupQueryParamKey"] }, queries: [{ propertyName: "tabs", predicate: MatTab }, { propertyName: "elderTabs", predicate: ElderTabDirective }], exportAs: ["elderTabGroupRouting"], ngImport: i0 }); }
35321
35218
  }
35322
35219
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderTabGroupRoutingDirective, decorators: [{
@@ -35326,7 +35223,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
35326
35223
  exportAs: 'elderTabGroupRouting',
35327
35224
  standalone: true,
35328
35225
  }]
35329
- }], ctorParameters: () => [{ type: ElderUrlFragmentParamsService }, { type: i1$d.MatTabGroup }], propDecorators: { tabGroupQueryParamKey: [{
35226
+ }], ctorParameters: () => [{ type: ElderUrlFragmentParamsService }, { type: i1$e.MatTabGroup }], propDecorators: { tabGroupQueryParamKey: [{
35330
35227
  type: Input,
35331
35228
  args: ['elderTabGroupRouting']
35332
35229
  }], tabs: [{