@elderbyte/ngx-starter 18.12.5 → 18.12.7

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/i18n/entity/elder-multi-translate-loader.mjs +4 -4
  2. package/esm2022/lib/common/utils/signal-input.mjs +3 -0
  3. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-anchor-controller.mjs +21 -0
  4. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-calendar-controller.mjs +24 -0
  5. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-controller.mjs +43 -0
  6. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-form-controller.mjs +69 -0
  7. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-select-controller.mjs +117 -0
  8. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-shift-controller.mjs +44 -0
  9. package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker.component.mjs +76 -127
  10. package/esm2022/lib/components/time/elder-interval-picker/interval-picker-binding/elder-interval-picker-binding.directive.mjs +41 -0
  11. package/esm2022/lib/components/time/elder-interval-picker/interval-picker-toggle/elder-interval-picker-toggle.component.mjs +144 -0
  12. package/esm2022/lib/components/time/elder-interval-picker/manager/interval-picker-state-manager.mjs +93 -0
  13. package/esm2022/lib/components/time/elder-interval-picker/model/anchor-state.mjs +54 -0
  14. package/esm2022/lib/components/time/elder-interval-picker/model/interval-state.mjs +37 -0
  15. package/esm2022/lib/components/time/elder-interval-picker/model/smart-shift-state.mjs +10 -0
  16. package/esm2022/lib/components/time/elder-interval-picker/presenter/interval-picker-presenter.mjs +96 -0
  17. package/esm2022/lib/components/time/elder-interval-picker/util/interval-picker-util.mjs +194 -0
  18. package/esm2022/lib/components/time/elder-time.module.mjs +5 -5
  19. package/fesm2022/elderbyte-ngx-starter.mjs +764 -888
  20. package/fesm2022/elderbyte-ngx-starter.mjs.map +1 -1
  21. package/lib/common/utils/signal-input.d.ts +2 -0
  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 +23 -33
  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
 
@@ -8603,8 +8603,8 @@ class ElderMultiTranslateHttpLoader {
8603
8603
  this._resourcesPrefix = _resourcesPrefix;
8604
8604
  }
8605
8605
  getTranslation(lang) {
8606
- const requests = this._resourcesPrefix.map((resource) => {
8607
- resource = resource;
8606
+ const requests = this._resourcesPrefix.map((resourceArg) => {
8607
+ const resource = resourceArg;
8608
8608
  let path;
8609
8609
  if (resource.prefix) {
8610
8610
  path = `${resource.prefix}${lang}${resource.suffix || '.json'}`;
@@ -8633,7 +8633,7 @@ function simpleDeepMerge(target, source) {
8633
8633
  return target;
8634
8634
  }
8635
8635
  const output = { ...target };
8636
- Object.keys(source).forEach(key => {
8636
+ Object.keys(source).forEach((key) => {
8637
8637
  if (Array.isArray(source[key])) {
8638
8638
  output[key] = [...(target[key] || []), ...source[key]];
8639
8639
  }
@@ -28882,821 +28882,824 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
28882
28882
  }]
28883
28883
  }] });
28884
28884
 
28885
- class IntervalPickerModelEditor {
28886
- /***************************************************************************
28887
- * *
28888
- * Constructor *
28889
- * *
28890
- **************************************************************************/
28891
- constructor(model) {
28892
- this.model = model;
28885
+ const booleanTransformFn = (input) => coerceBooleanProperty(input);
28886
+
28887
+ class IntervalState {
28888
+ constructor(startDate, endDate, startTime, endTime) {
28889
+ this.startDate = startDate;
28890
+ this.endDate = endDate;
28891
+ this.startTime = startTime;
28892
+ this.endTime = endTime;
28893
+ this.startTime = this.startTime || Temporal.PlainTime.from('00:00');
28894
+ this.endTime = this.endTime || Temporal.PlainTime.from('00:00');
28893
28895
  }
28894
- /***************************************************************************
28895
- * *
28896
- * Date Shift API *
28897
- * *
28898
- **************************************************************************/
28899
- shiftMonth(months, staticMode = false) {
28900
- this.setDatesFromRange(this.dateRange().shiftMonths(months));
28901
- if (staticMode && this.calendarMode() !== 'months') {
28902
- this.setCalendarMode('days');
28903
- return;
28904
- }
28905
- this.resetTimeRange();
28906
- this.setCalendarMode('months');
28896
+ static createFromDateTimes(startDateTime, endDateTime) {
28897
+ return new IntervalState(startDateTime.toPlainDate(), endDateTime.toPlainDate(), startDateTime.toPlainTime(), endDateTime.toPlainTime());
28907
28898
  }
28908
- shiftDay(days) {
28909
- this.setDatesFromRange(this.dateRange().shiftDays(days));
28910
- if (this.calendarMode() === 'weeks' && (days === 7 || days === -7)) {
28911
- this.setCalendarMode('weeks');
28912
- return;
28899
+ get startDateTime() {
28900
+ return IntervalPickerUtil.createTemporalDateTime(this.startDate, this.startTime);
28901
+ }
28902
+ get endDateTime() {
28903
+ return IntervalPickerUtil.createTemporalDateTime(this.endDate, this.endTime);
28904
+ }
28905
+ withStartDate(newStartDate) {
28906
+ return new IntervalState(newStartDate, this.endDate, this.startTime, this.endTime);
28907
+ }
28908
+ withEndDate(newEndDate) {
28909
+ return new IntervalState(this.startDate, newEndDate, this.startTime, this.endTime);
28910
+ }
28911
+ withStartTime(newStartTime) {
28912
+ return new IntervalState(this.startDate, this.endDate, newStartTime, this.endTime);
28913
+ }
28914
+ withEndTime(newEndTime) {
28915
+ return new IntervalState(this.startDate, this.endDate, this.startTime, newEndTime);
28916
+ }
28917
+ withTime(newStartTime, newEndTime) {
28918
+ return new IntervalState(this.startDate, this.endDate, newStartTime, newEndTime);
28919
+ }
28920
+ }
28921
+
28922
+ class IntervalPickerUtil {
28923
+ static createElderInterval(intervalState) {
28924
+ let startInstant;
28925
+ let endInstant;
28926
+ try {
28927
+ const startDateTimeJS = TemporalUtil.getJSDateFromPlainDateTime(intervalState.startDateTime);
28928
+ startInstant = TimeUtil.instant(startDateTimeJS);
28929
+ }
28930
+ catch (e) {
28931
+ startInstant = null;
28932
+ }
28933
+ try {
28934
+ const endDateTimeJS = TemporalUtil.getJSDateFromPlainDateTime(intervalState.endDateTime);
28935
+ endInstant = TimeUtil.instant(endDateTimeJS);
28913
28936
  }
28914
- this.setCalendarMode('days');
28937
+ catch (e) {
28938
+ endInstant = null;
28939
+ }
28940
+ return new Interval(startInstant, endInstant);
28915
28941
  }
28916
- shiftYear(years, staticMode = false) {
28917
- this.setDatesFromRange(this.dateRange().shiftYears(years));
28918
- if (staticMode && this.calendarMode() !== 'years') {
28919
- this.setCalendarMode('days');
28920
- return;
28942
+ static transformToIntervalState(interval) {
28943
+ if (!interval) {
28944
+ return null;
28945
+ }
28946
+ const startDateTimeJS = interval.start ? TimeUtil.date(interval.start) : null;
28947
+ const endDateTimeJS = interval.end ? TimeUtil.date(interval.end) : null;
28948
+ let startDate = null;
28949
+ let endDate = null;
28950
+ let startTime = null;
28951
+ let endTime = null;
28952
+ try {
28953
+ const startDateTime = TemporalUtil.getPlainDateTimeFromJSDate(startDateTimeJS);
28954
+ startDate = startDateTime.toPlainDate();
28955
+ startTime = startDateTime.toPlainTime();
28956
+ }
28957
+ catch (e) {
28958
+ startDate = null;
28959
+ startTime = null;
28921
28960
  }
28922
- this.resetTimeRange();
28923
- this.setCalendarMode('years');
28961
+ try {
28962
+ const endDateTime = TemporalUtil.getPlainDateTimeFromJSDate(endDateTimeJS);
28963
+ endDate = endDateTime.toPlainDate();
28964
+ endTime = endDateTime.toPlainTime();
28965
+ }
28966
+ catch (e) {
28967
+ endDate = null;
28968
+ endTime = null;
28969
+ }
28970
+ return new IntervalState(startDate, endDate, startTime, endTime);
28924
28971
  }
28925
- /***************************************************************************
28926
- * *
28927
- * Time Shift API *
28928
- * *
28929
- **************************************************************************/
28930
- shiftTime(amount, unit) {
28931
- if (!this.isStartAndEndDatesSet()) {
28932
- return;
28972
+ static createTemporalDateTime(date, time) {
28973
+ if (!date) {
28974
+ return null;
28933
28975
  }
28934
- const newStartDateTime = this.startDateTime().add({ [unit]: amount });
28935
- const newEndDateTime = this.endDateTime().add({ [unit]: amount });
28936
- this.setDateRange(Temporal.PlainDate.from(newStartDateTime), Temporal.PlainDate.from(newEndDateTime));
28937
- this.setTimeRange(Temporal.PlainTime.from(newStartDateTime), Temporal.PlainTime.from(newEndDateTime));
28976
+ return Temporal.PlainDateTime.from({
28977
+ year: date.year,
28978
+ month: date.month,
28979
+ day: date.day,
28980
+ hour: time.hour,
28981
+ minute: time.minute,
28982
+ second: time.second,
28983
+ millisecond: time.millisecond,
28984
+ });
28938
28985
  }
28939
- smartShift(direction = 1) {
28940
- if (this.calendarMode() === 'quarters') {
28941
- const newRange = this.dateRange().shiftMonths(direction * 3);
28942
- this.setDatesFromRange(newRange);
28943
- return;
28986
+ static isIntervalEquals(interval1, interval2) {
28987
+ if (!interval1 && !interval2) {
28988
+ return true;
28944
28989
  }
28945
- if (this.calendarMode() === 'months') {
28946
- const newRange = this.dateRange().shiftMonths(direction);
28947
- this.setDatesFromRange(newRange);
28948
- return;
28990
+ if (!interval1 || !interval2) {
28991
+ return false;
28949
28992
  }
28950
- if (this.calendarMode() === 'years') {
28951
- const newRange = this.dateRange().shiftYears(direction);
28952
- this.setDatesFromRange(newRange);
28953
- return;
28993
+ return (this.isEquals(interval1.startDate, interval2.startDate) &&
28994
+ this.isEquals(interval1.endDate, interval2.endDate) &&
28995
+ this.isEquals(interval1.startTime, interval2.startTime) &&
28996
+ this.isEquals(interval1.endTime, interval2.endTime));
28997
+ }
28998
+ static isEquals(x, y) {
28999
+ if (!x && !y) {
29000
+ return true;
28954
29001
  }
28955
- if (this.calendarMode() === 'weeks') {
28956
- const newRange = this.dateRange().shiftDays(7 * direction);
28957
- this.setDatesFromRange(newRange);
28958
- return;
29002
+ if (!x || !y) {
29003
+ return false;
28959
29004
  }
28960
- const daysDiff = this.dateRange().getDurationInDays();
28961
- const newRange = this.dateRange().shiftDays(daysDiff * direction);
28962
- this.setDatesFromRange(newRange);
29005
+ return x.equals(y);
28963
29006
  }
28964
- /***************************************************************************
28965
- * *
28966
- * Date Selection API *
28967
- * *
28968
- **************************************************************************/
28969
- selectCurrentDay() {
28970
- this.setDatesFromRange(TemporalUtil.getCurrentDay(this.anchorDate()));
28971
- this.setCalendarMode('days');
28972
- this.resetTimeRange();
29007
+ static isIntervalWithStartAndEnd(interval) {
29008
+ return !!interval?.startDate && !!interval?.endDate;
28973
29009
  }
28974
- selectYesterday() {
28975
- this.setDatesFromRange(TemporalUtil.getYesterday(this.anchorDate()));
28976
- this.setCalendarMode('days');
28977
- this.resetTimeRange();
29010
+ static isOpenInterval(interval) {
29011
+ if (!interval) {
29012
+ return false;
29013
+ }
29014
+ return ((!!interval.startDate && !interval.endDate) || (!interval.startDate && !!interval.endDate));
28978
29015
  }
28979
- selectCurrentMonth() {
28980
- this.setDatesFromRange(TemporalUtil.getCurrentMonth(this.anchorDate()));
28981
- this.setCalendarMode('months');
28982
- this.resetTimeRange();
29016
+ static getDeltaHumanReadable(interval) {
29017
+ if (IntervalPickerUtil.isOpenInterval(interval)) {
29018
+ return '';
29019
+ }
29020
+ if (!IntervalPickerUtil.isIntervalWithStartAndEnd(interval)) {
29021
+ return '-';
29022
+ }
29023
+ const duration = interval.startDateTime.until(interval.endDateTime);
29024
+ const tmp = [];
29025
+ if (duration.days) {
29026
+ tmp.push(`${duration.days}d`);
29027
+ }
29028
+ if (duration.hours) {
29029
+ tmp.push(`${duration.hours}h`);
29030
+ }
29031
+ if (duration.minutes) {
29032
+ tmp.push(`${duration.minutes}min`);
29033
+ }
29034
+ if (duration.seconds) {
29035
+ tmp.push(`${duration.seconds}s`);
29036
+ }
29037
+ if (!tmp.length) {
29038
+ return '0s';
29039
+ }
29040
+ return tmp.join(', ');
28983
29041
  }
28984
- selectCurrentWeek() {
28985
- this.setDatesFromRange(TemporalUtil.getCurrentWeek(this.anchorDate()));
28986
- this.setCalendarMode('weeks');
28987
- this.resetTimeRange();
29042
+ static getSmartShiftMessage(mode, dateInterval) {
29043
+ if (!dateInterval) {
29044
+ return '-';
29045
+ }
29046
+ const startDate = dateInterval.startDate;
29047
+ const endDate = dateInterval.endDate;
29048
+ switch (mode) {
29049
+ case 'years':
29050
+ return `1y (${startDate.year})`;
29051
+ case 'quarters':
29052
+ return `Q${TemporalUtil.getQuarterForDate(startDate)}, ${startDate.year}`;
29053
+ case 'months':
29054
+ return `1m (${startDate.monthCode}, ${startDate.year})`;
29055
+ case 'weeks':
29056
+ return `1w (CW ${startDate.weekOfYear}, ${endDate.year})`;
29057
+ case 'days':
29058
+ return `${startDate.until(endDate).days}d`;
29059
+ case 'time':
29060
+ return `${this.getDeltaHumanReadable(dateInterval)}`;
29061
+ default:
29062
+ return `${startDate.until(endDate).days}d`;
29063
+ }
28988
29064
  }
28989
- selectPreviousWeek() {
28990
- this.setDatesFromRange(TemporalUtil.getPreviousWeek(this.anchorDate()));
28991
- this.setCalendarMode('weeks');
28992
- this.resetTimeRange();
29065
+ static isTimeSetAndNotMidnight(time) {
29066
+ if (!time) {
29067
+ return false;
29068
+ }
29069
+ if (time.hour === 0 && time.minute === 0 && time.second === 0) {
29070
+ return false;
29071
+ }
29072
+ return true;
28993
29073
  }
28994
- selectPreviousMonth() {
28995
- this.setDatesFromRange(TemporalUtil.getPreviousMonth(this.anchorDate()));
28996
- this.setCalendarMode('months');
28997
- this.resetTimeRange();
29074
+ static setMillisecondsToZero(interval) {
29075
+ 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 }));
28998
29076
  }
28999
- selectLastThirtyDaysExcludingToday() {
29000
- this.setDatesFromRange(TemporalUtil.getLastThirtyDays(this.anchorDate()));
29001
- this.setCalendarMode('days');
29002
- this.resetTimeRange();
29077
+ static roundUpToSeconds(time) {
29078
+ return time.with({
29079
+ second: time.second + 1,
29080
+ millisecond: 0,
29081
+ microsecond: 0,
29082
+ nanosecond: 0,
29083
+ });
29003
29084
  }
29004
- selectLastThirtyDaysIncludingToday() {
29005
- this.setDatesFromRange(TemporalUtil.getLastThirtyDaysIncludingToday(this.anchorDate()));
29006
- this.setCalendarMode('days');
29007
- this.resetTimeRange();
29085
+ static updateMatCalendarActiveDate(calendarStart, calendarEnd, startDate, endDate) {
29086
+ if (!calendarStart || !calendarEnd) {
29087
+ return;
29088
+ }
29089
+ if (!startDate && !endDate) {
29090
+ return;
29091
+ }
29092
+ setTimeout(() => {
29093
+ // timeout is needed to run calendar update last, otherwise there are issues
29094
+ if (startDate) {
29095
+ calendarStart.activeDate = TemporalUtil.getJSDateFromPlainDateTime(startDate);
29096
+ }
29097
+ if (endDate) {
29098
+ calendarEnd.activeDate = TemporalUtil.getJSDateFromPlainDateTime(endDate);
29099
+ }
29100
+ }, 0);
29008
29101
  }
29009
- selectCurrentYear() {
29010
- this.setDatesFromRange(TemporalUtil.getCurrentYear(this.anchorDate()));
29011
- this.setCalendarMode('years');
29012
- this.resetTimeRange();
29102
+ static updateMatCalendarTodayDate(calendarStart, calendarEnd) {
29103
+ if (!calendarStart || !calendarEnd) {
29104
+ return;
29105
+ }
29106
+ calendarStart.updateTodaysDate();
29107
+ calendarEnd.updateTodaysDate();
29013
29108
  }
29014
- selectPreviousYear() {
29015
- this.setDatesFromRange(TemporalUtil.getPreviousYear(this.anchorDate()));
29016
- this.setCalendarMode('years');
29017
- this.resetTimeRange();
29109
+ }
29110
+
29111
+ class AnchorState {
29112
+ constructor(fixedDate, fixedTime = Temporal.PlainTime.from('00:00'), referenceDateTime = IntervalPickerUtil.roundUpToSeconds(Temporal.Now.plainDateTimeISO())) {
29113
+ this.fixedDate = fixedDate;
29114
+ this.fixedTime = fixedTime;
29115
+ this.referenceDateTime = referenceDateTime;
29018
29116
  }
29019
- selectLast365Days() {
29020
- this.setDatesFromRange(TemporalUtil.getLast365Days(this.anchorDate()));
29021
- this.setCalendarMode('days');
29022
- this.resetTimeRange();
29117
+ static createFromDateTime(dateTime) {
29118
+ return new AnchorState(dateTime.toPlainDate(), dateTime.toPlainTime());
29023
29119
  }
29024
- selectCurrentQuarter() {
29025
- this.setDatesFromRange(TemporalUtil.getCurrentQuarter(this.anchorDate()));
29026
- this.setCalendarMode('quarters');
29027
- this.resetTimeRange();
29120
+ static createFromJsDate(date) {
29121
+ const dateTime = TemporalUtil.getPlainDateTimeFromJSDate(date);
29122
+ return new AnchorState(dateTime.toPlainDate(), dateTime.toPlainTime());
29028
29123
  }
29029
- selectPreviousQuarter() {
29030
- this.setDatesFromRange(TemporalUtil.getPreviousQuarter(this.anchorDate()));
29031
- this.setCalendarMode('quarters');
29032
- this.resetTimeRange();
29124
+ static empty() {
29125
+ return new AnchorState(null);
29033
29126
  }
29034
- selectLastSevenDaysExcludingToday() {
29035
- this.setDatesFromRange(TemporalUtil.getLastSevenDays(this.anchorDate()));
29036
- this.setCalendarMode('days');
29037
- this.resetTimeRange();
29127
+ withDate(date) {
29128
+ return new AnchorState(date, this.fixedTime);
29038
29129
  }
29039
- selectLastSevenDaysIncludingToday() {
29040
- this.setDatesFromRange(TemporalUtil.getLastSevenDaysIncludingToday(this.anchorDate()));
29041
- this.setCalendarMode('days');
29042
- this.resetTimeRange();
29130
+ withTime(time) {
29131
+ return new AnchorState(this.fixedDate, time);
29043
29132
  }
29044
- /***************************************************************************
29045
- * *
29046
- * Time Selection API *
29047
- * *
29048
- **************************************************************************/
29049
- // time range selections
29050
- selectLastHour() {
29051
- this.selectLastByDuration({ hours: 1 });
29133
+ withTimeMidnight() {
29134
+ return new AnchorState(this.fixedDate, Temporal.PlainTime.from('00:00'));
29052
29135
  }
29053
- selectLast24Hours() {
29054
- this.selectLastByDuration({ days: 1 });
29136
+ withReferenceDateTimeNow() {
29137
+ return new AnchorState(this.fixedDate, this.fixedTime, IntervalPickerUtil.roundUpToSeconds(Temporal.Now.plainDateTimeISO()));
29055
29138
  }
29056
- selectLastFiveMinutes() {
29057
- this.selectLastByDuration({ minutes: 5 });
29139
+ get fixedDateTime() {
29140
+ if (!this.fixedDate) {
29141
+ return null;
29142
+ }
29143
+ return IntervalPickerUtil.createTemporalDateTime(this.fixedDate, this.fixedTime);
29058
29144
  }
29059
- selectLastByDuration(duration) {
29060
- this.refreshBaseReferenceDateTime();
29061
- const end = this.anchorDateTime();
29062
- const start = end.subtract(duration);
29063
- const startPlainDate = Temporal.PlainDate.from(start);
29064
- const startPlainTime = Temporal.PlainTime.from(start);
29065
- this.setDateRange(startPlainDate, this.anchorDate());
29066
- this.setTimeRange(startPlainTime, this.anchorTime());
29067
- this.setCalendarMode('days');
29145
+ get isFixed() {
29146
+ return this.fixedDate !== null;
29068
29147
  }
29069
- /***************************************************************************
29070
- * *
29071
- * Private methods *
29072
- * *
29073
- **************************************************************************/
29074
- anchorTime() {
29075
- return this.model.anchorTime();
29148
+ get date() {
29149
+ return this.fixedDate || this.referenceDateTime.toPlainDate();
29076
29150
  }
29077
- anchorDate() {
29078
- return this.model.anchorDate();
29151
+ get time() {
29152
+ return this.fixedTime || this.referenceDateTime.toPlainTime();
29079
29153
  }
29080
- setCalendarMode(mode) {
29081
- this.model.calendarMode.set(mode);
29154
+ get dateTime() {
29155
+ return this.fixedDateTime || this.referenceDateTime;
29082
29156
  }
29083
- calendarMode() {
29084
- return this.model.calendarMode();
29157
+ get isTimeMidnight() {
29158
+ return this.fixedTime.hour === 0 && this.fixedTime.minute === 0 && this.fixedTime.second === 0;
29085
29159
  }
29086
- dateRange() {
29087
- return this.model.dateRange();
29160
+ }
29161
+
29162
+ class IntervalAnchorController {
29163
+ constructor(manager) {
29164
+ this.manager = manager;
29088
29165
  }
29089
- resetTimeRange() {
29090
- this.setTimeRange(Temporal.PlainTime.from('00:00'), Temporal.PlainTime.from('00:00'));
29166
+ resetAnchor() {
29167
+ this.manager.setAnchor(AnchorState.empty());
29091
29168
  }
29092
- setTimeRange(start, end) {
29093
- this.model.setStartTime(start);
29094
- this.model.setEndTime(end);
29169
+ resetAnchorTime() {
29170
+ this.manager.setAnchor(this.manager.anchorValue.withTimeMidnight());
29095
29171
  }
29096
- setDateRange(start, end) {
29097
- this.model.setStartDate(start);
29098
- this.model.setEndDate(end);
29172
+ setFixedAnchorPointToStartDateTime() {
29173
+ const startDateTime = this.manager.intervalValue?.startDateTime;
29174
+ this.manager.setAnchor(AnchorState.createFromDateTime(startDateTime));
29099
29175
  }
29100
- setDatesFromRange(range) {
29101
- this.setDateRange(range.start, range.end);
29176
+ setFixedAnchorPointToEndDateTime() {
29177
+ const endDateTime = this.manager.intervalValue?.endDateTime;
29178
+ this.manager.setAnchor(AnchorState.createFromDateTime(endDateTime));
29102
29179
  }
29103
- shiftSelectionToAnchorDate() {
29104
- if (!this.isStartAndEndDatesSet() || !this.fixedAnchorDate()) {
29180
+ }
29181
+
29182
+ class IntervalCalendarController {
29183
+ constructor(manager) {
29184
+ this.manager = manager;
29185
+ }
29186
+ setStartDateFromJSDate(date) {
29187
+ const startDate = TemporalUtil.getPlainDateFromJSDate(date);
29188
+ if (!this.manager.intervalValue) {
29189
+ this.manager.setInterval(new IntervalState(startDate, null));
29105
29190
  return;
29106
29191
  }
29107
- const range = this.dateRange();
29108
- const endDate = this.fixedAnchorDate();
29109
- const startDate = endDate.subtract({ days: range.getDurationInDays() });
29110
- this.setDateRange(startDate, endDate);
29111
- if (this.calendarMode() === 'months') {
29112
- this.selectCurrentMonth();
29113
- }
29114
- if (this.calendarMode() === 'years') {
29115
- this.selectCurrentYear();
29116
- }
29117
- if (this.calendarMode() === 'weeks') {
29118
- this.selectCurrentWeek();
29119
- }
29192
+ this.manager.setInterval(this.manager.intervalValue.withStartDate(startDate));
29120
29193
  }
29121
- fixedAnchorDate() {
29122
- return this.model.fixedAnchorDate();
29194
+ setEndDateFromJSDate(date) {
29195
+ const endDate = TemporalUtil.getPlainDateFromJSDate(date);
29196
+ if (!this.manager.intervalValue) {
29197
+ this.manager.setInterval(new IntervalState(null, endDate));
29198
+ return;
29199
+ }
29200
+ this.manager.setInterval(this.manager.intervalValue.withEndDate(endDate));
29123
29201
  }
29124
- fixedAnchorTime() {
29125
- return this.model.fixedAnchorTime();
29202
+ }
29203
+
29204
+ class IntervalFormController {
29205
+ constructor(manager) {
29206
+ this.manager = manager;
29207
+ this.log = LoggerFactory.getLogger(this.constructor.name);
29126
29208
  }
29127
- anchorDateTime() {
29128
- return this.model.anchorDateTime();
29209
+ setStartDateFromString(htmlString) {
29210
+ try {
29211
+ const plainDate = TemporalUtil.getPlainDateFromHtmlDateString(htmlString);
29212
+ const endDate = this.manager.intervalValue?.endDate || plainDate.add({ days: 1 });
29213
+ this.manager.setInterval(new IntervalState(plainDate, endDate));
29214
+ }
29215
+ catch (e) {
29216
+ this.log.warn('Incorrect date / time anchor form input. Could not set anchor.', htmlString);
29217
+ }
29129
29218
  }
29130
- startDateTime() {
29131
- return this.model.startDateTime();
29219
+ setEndDateFromString(htmlString) {
29220
+ try {
29221
+ const plainDate = TemporalUtil.getPlainDateFromHtmlDateString(htmlString);
29222
+ const startDate = this.manager.intervalValue?.startDate || plainDate.subtract({ days: 1 });
29223
+ this.manager.setInterval(new IntervalState(startDate, plainDate));
29224
+ }
29225
+ catch (e) {
29226
+ this.log.warn('Incorrect date / time anchor form input. Could not set anchor.', htmlString);
29227
+ }
29132
29228
  }
29133
- endDateTime() {
29134
- return this.model.endDateTime();
29229
+ setAnchorDateFromString(htmlString) {
29230
+ try {
29231
+ const plainDate = TemporalUtil.getPlainDateFromHtmlDateString(htmlString);
29232
+ this.manager.setAnchor(this.manager.anchorValue.withDate(plainDate));
29233
+ }
29234
+ catch (e) {
29235
+ this.log.warn('Incorrect date / time anchor form input. Could not set anchor.', htmlString);
29236
+ }
29135
29237
  }
29136
- isStartAndEndDatesSet() {
29137
- return this.model.isStartAndEndDatesSet();
29238
+ setAnchorTimeFromString(htmlString) {
29239
+ try {
29240
+ const plainTime = TemporalUtil.getPlainTimeFromHtmlTimeString(htmlString);
29241
+ this.manager.setAnchor(this.manager.anchorValue.withTime(plainTime));
29242
+ }
29243
+ catch (e) {
29244
+ this.log.warn('Incorrect date / time anchor form input. Could not set anchor.', htmlString);
29245
+ }
29138
29246
  }
29139
- shiftSelectionToAnchorTime() {
29140
- if (!this.isStartAndEndDatesSet() || !this.fixedAnchorTime()) {
29141
- return;
29247
+ setStartTimeFromString(timeStr) {
29248
+ try {
29249
+ const startTime = TemporalUtil.getPlainTimeFromHtmlTimeString(timeStr);
29250
+ const startDate = this.manager.intervalValue?.startDate || Temporal.Now.plainDateISO();
29251
+ this.manager.setInterval(new IntervalState(startDate, this.manager.intervalValue?.endDate || null, startTime, this.manager.intervalValue?.endTime || null));
29142
29252
  }
29143
- const duration = this.startDateTime().until(this.endDateTime());
29144
- const newStartDateTime = this.anchorDateTime().subtract(duration);
29145
- const newEndDateTime = this.anchorDateTime();
29146
- this.setDateRange(Temporal.PlainDate.from(newStartDateTime), Temporal.PlainDate.from(newEndDateTime));
29147
- this.setTimeRange(Temporal.PlainTime.from(newStartDateTime), Temporal.PlainTime.from(newEndDateTime));
29148
- if (this.calendarMode() === 'months') {
29149
- this.selectCurrentMonth();
29253
+ catch (e) {
29254
+ this.log.warn('Incorrect date / time form input. Could not set new Interval.', timeStr, e);
29150
29255
  }
29151
- if (this.calendarMode() === 'years') {
29152
- this.selectCurrentYear();
29256
+ }
29257
+ setEndTimeFromString(timeStr) {
29258
+ try {
29259
+ const endTime = TemporalUtil.getPlainTimeFromHtmlTimeString(timeStr);
29260
+ const endDate = this.manager.intervalValue?.endDate || Temporal.Now.plainDateISO();
29261
+ this.manager.setInterval(new IntervalState(this.manager.intervalValue?.startDate || null, endDate, this.manager.intervalValue?.startTime || null, endTime));
29153
29262
  }
29154
- if (this.calendarMode() === 'weeks') {
29155
- this.selectCurrentWeek();
29263
+ catch (e) {
29264
+ this.log.warn('Incorrect date / time form input. Could not set new Interval.', timeStr);
29156
29265
  }
29157
29266
  }
29158
- refreshBaseReferenceDateTime() {
29159
- const dateTime = Temporal.Now.zonedDateTimeISO();
29160
- const date = Temporal.PlainDate.from(dateTime);
29161
- const time = Temporal.PlainTime.from(dateTime);
29162
- this.model.baseReferenceDate.set(date);
29163
- this.model.baseReferenceTime.set(time);
29267
+ }
29268
+
29269
+ class SmartShiftState {
29270
+ constructor(duration, mode) {
29271
+ this.duration = duration;
29272
+ this.mode = mode;
29273
+ }
29274
+ static empty() {
29275
+ return new SmartShiftState(null, null);
29164
29276
  }
29165
29277
  }
29166
29278
 
29167
- class PlainDateIntervalMessageRenderer {
29168
- static toMessage(mode, dateInterval) {
29169
- if (!dateInterval) {
29170
- return '-';
29171
- }
29172
- const startDate = dateInterval.start;
29173
- const endDate = dateInterval.end;
29174
- switch (mode) {
29175
- case 'years':
29176
- return `1y (${startDate.year})`;
29177
- case 'quarters':
29178
- return `Q${TemporalUtil.getQuarterForDate(startDate)}, ${startDate.year}`;
29179
- case 'months':
29180
- return `1m (${startDate.monthCode}, ${startDate.year})`;
29181
- case 'weeks':
29182
- return `1w (CW ${this.calendarWeek(startDate)}, ${endDate.year})`;
29183
- case 'days':
29184
- return `${this.dateRangeInDays(dateInterval)}d`;
29185
- default:
29186
- return '?';
29187
- }
29279
+ class IntervalSelectController {
29280
+ constructor(manager) {
29281
+ this.manager = manager;
29188
29282
  }
29189
- static calendarWeek(date) {
29190
- if (!date) {
29191
- return null;
29192
- }
29193
- return date.weekOfYear;
29283
+ refreshAnchor() {
29284
+ this.manager.setAnchor(this.manager.anchorValue.withReferenceDateTimeNow());
29194
29285
  }
29195
- static dateRangeInDays(dateInterval) {
29196
- if (!dateInterval) {
29197
- return 0;
29198
- }
29199
- return dateInterval.getDurationInDays();
29286
+ setSmartShiftState(duration, mode) {
29287
+ this.manager.setSmartShift(new SmartShiftState(duration, mode));
29288
+ }
29289
+ selectCurrentDay() {
29290
+ this.refreshAnchor();
29291
+ const endDate = this.manager.anchorValue.date.add({ days: 1 });
29292
+ const startDate = endDate.subtract({ days: 1 });
29293
+ this.manager.setInterval(new IntervalState(startDate, endDate));
29294
+ this.setSmartShiftState(Temporal.Duration.from({ days: 1 }), 'days');
29295
+ }
29296
+ selectYesterday() {
29297
+ this.refreshAnchor();
29298
+ const endDate = this.manager.anchorValue.date;
29299
+ const startDate = endDate.subtract({ days: 1 });
29300
+ this.manager.setInterval(new IntervalState(startDate, endDate));
29301
+ this.setSmartShiftState(Temporal.Duration.from({ days: 1 }), 'days');
29302
+ }
29303
+ selectLastSevenDaysExcludingToday() {
29304
+ this.refreshAnchor();
29305
+ const endDate = this.manager.anchorValue.date;
29306
+ const startDate = endDate.subtract({ days: 7 });
29307
+ this.manager.setInterval(new IntervalState(startDate, endDate));
29308
+ this.setSmartShiftState(Temporal.Duration.from({ days: 7 }), 'days');
29309
+ }
29310
+ selectLastSevenDaysIncludingToday() {
29311
+ this.refreshAnchor();
29312
+ const endDate = this.manager.anchorValue.date.add({ days: 1 });
29313
+ const startDate = endDate.subtract({ days: 7 });
29314
+ this.manager.setInterval(new IntervalState(startDate, endDate));
29315
+ this.setSmartShiftState(Temporal.Duration.from({ days: 7 }), 'days');
29316
+ }
29317
+ selectLastThirtyDaysExcludingToday() {
29318
+ this.refreshAnchor();
29319
+ const endDate = this.manager.anchorValue.date;
29320
+ const startDate = endDate.subtract({ days: 30 });
29321
+ this.manager.setInterval(new IntervalState(startDate, endDate));
29322
+ this.setSmartShiftState(Temporal.Duration.from({ days: 30 }), 'days');
29323
+ }
29324
+ selectLastThirtyDaysIncludingToday() {
29325
+ this.refreshAnchor();
29326
+ const endDate = this.manager.anchorValue.date.add({ days: 1 });
29327
+ const startDate = endDate.subtract({ days: 30 });
29328
+ this.manager.setInterval(new IntervalState(startDate, endDate));
29329
+ this.setSmartShiftState(Temporal.Duration.from({ days: 30 }), 'days');
29330
+ }
29331
+ selectLast365daysExcludingToday() {
29332
+ this.refreshAnchor();
29333
+ const endDate = this.manager.anchorValue.date;
29334
+ const startDate = endDate.subtract({ days: 365 });
29335
+ this.manager.setInterval(new IntervalState(startDate, endDate));
29336
+ this.setSmartShiftState(Temporal.Duration.from({ days: 365 }), 'days');
29337
+ }
29338
+ selectLast365daysIncludingToday() {
29339
+ this.refreshAnchor();
29340
+ const endDate = this.manager.anchorValue.date.add({ days: 1 });
29341
+ const startDate = endDate.subtract({ days: 365 });
29342
+ this.manager.setInterval(new IntervalState(startDate, endDate));
29343
+ this.setSmartShiftState(Temporal.Duration.from({ days: 365 }), 'days');
29344
+ }
29345
+ selectLastFiveMinutes() {
29346
+ this.refreshAnchor();
29347
+ const anchorDateTime = this.manager.anchorValue.dateTime;
29348
+ const startDateTime = anchorDateTime.subtract({ minutes: 5 });
29349
+ this.manager.setInterval(IntervalState.createFromDateTimes(startDateTime, anchorDateTime));
29350
+ this.setSmartShiftState(Temporal.Duration.from({ minutes: 5 }), 'time');
29351
+ }
29352
+ selectLastHour() {
29353
+ this.refreshAnchor();
29354
+ const anchorDateTime = this.manager.anchorValue.dateTime;
29355
+ const startDateTime = anchorDateTime.subtract({ hours: 1 });
29356
+ this.manager.setInterval(IntervalState.createFromDateTimes(startDateTime, anchorDateTime));
29357
+ this.setSmartShiftState(Temporal.Duration.from({ hours: 1 }), 'time');
29358
+ }
29359
+ selectLast24Hours() {
29360
+ this.refreshAnchor();
29361
+ const anchorDateTime = this.manager.anchorValue.dateTime;
29362
+ const startDateTime = anchorDateTime.subtract({ hours: 24 });
29363
+ this.manager.setInterval(IntervalState.createFromDateTimes(startDateTime, anchorDateTime));
29364
+ this.setSmartShiftState(Temporal.Duration.from({ hours: 24 }), 'time');
29365
+ }
29366
+ selectCurrentWeek() {
29367
+ this.refreshAnchor();
29368
+ const range = TemporalUtil.getCurrentWeek(this.manager.anchorValue.date);
29369
+ this.manager.setInterval(new IntervalState(range.start, range.end));
29370
+ this.setSmartShiftState(Temporal.Duration.from({ days: 7 }), 'weeks');
29371
+ }
29372
+ selectCurrentMonth() {
29373
+ this.refreshAnchor();
29374
+ const range = TemporalUtil.getCurrentMonth(this.manager.anchorValue.date);
29375
+ this.manager.setInterval(new IntervalState(range.start, range.end));
29376
+ this.setSmartShiftState(Temporal.Duration.from({ months: 1 }), 'months');
29377
+ }
29378
+ selectCurrentQuarter() {
29379
+ this.refreshAnchor();
29380
+ const range = TemporalUtil.getCurrentQuarter(this.manager.anchorValue.date);
29381
+ this.manager.setInterval(new IntervalState(range.start, range.end));
29382
+ this.setSmartShiftState(Temporal.Duration.from({ months: 3 }), 'quarters');
29383
+ }
29384
+ selectCurrentYear() {
29385
+ this.refreshAnchor();
29386
+ const range = TemporalUtil.getCurrentYear(this.manager.anchorValue.date);
29387
+ this.manager.setInterval(new IntervalState(range.start, range.end));
29388
+ this.setSmartShiftState(Temporal.Duration.from({ years: 1 }), 'years');
29200
29389
  }
29201
29390
  }
29202
29391
 
29203
- class PlainTemporalDurationMessageRenderer {
29204
- static toMessage(duration) {
29205
- if (!duration) {
29206
- return '∞';
29207
- }
29208
- const tmp = [];
29209
- if (duration.days) {
29210
- tmp.push(`${duration.days}d`);
29211
- }
29212
- if (duration.hours) {
29213
- tmp.push(`${duration.hours}h`);
29214
- }
29215
- if (duration.minutes) {
29216
- tmp.push(`${duration.minutes}min`);
29217
- }
29218
- if (duration.seconds) {
29219
- tmp.push(`${duration.seconds}s`);
29220
- }
29221
- if (!tmp.length) {
29222
- return '0s';
29392
+ class IntervalShiftController {
29393
+ constructor(manager) {
29394
+ this.manager = manager;
29395
+ this.log = LoggerFactory.getLogger(this.constructor.name);
29396
+ }
29397
+ shiftDay(days) {
29398
+ 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));
29399
+ }
29400
+ shiftWeek(weeks) {
29401
+ 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));
29402
+ }
29403
+ shiftMonth(months) {
29404
+ 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));
29405
+ }
29406
+ shiftYear(years) {
29407
+ 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));
29408
+ }
29409
+ shiftMinute(minutes) {
29410
+ const newInterval = new IntervalState(this.manager.intervalValue.startDate, this.manager.intervalValue.endDate, this.manager.intervalValue.startTime?.add({ minutes }), this.manager.intervalValue.endTime?.add({ minutes }));
29411
+ this.manager.setInterval(newInterval);
29412
+ }
29413
+ shiftHour(hours) {
29414
+ 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 }));
29415
+ this.manager.setInterval(newInterval);
29416
+ }
29417
+ smartShift(direction = 1) {
29418
+ const state = this.manager.smartShiftValue;
29419
+ if (!state.duration) {
29420
+ this.log.warn('Cannot smart shift without a duration!');
29421
+ return;
29223
29422
  }
29224
- return tmp.join(', ');
29423
+ const duration = state.duration;
29424
+ const interval = this.manager.intervalValue;
29425
+ const newStartDateTime = direction === 1
29426
+ ? interval.startDateTime.add(duration)
29427
+ : interval.startDateTime.subtract(duration);
29428
+ const newEndDateTime = direction === 1 ? interval.endDateTime.add(duration) : interval.endDateTime.subtract(duration);
29429
+ const newInterval = IntervalState.createFromDateTimes(newStartDateTime, newEndDateTime);
29430
+ this.manager.setInterval(newInterval);
29225
29431
  }
29226
29432
  }
29227
29433
 
29228
- const defaultCalendarMode = 'days';
29229
- class IntervalPickerModel {
29434
+ class IntervalController {
29230
29435
  /***************************************************************************
29231
29436
  * *
29232
29437
  * Constructor *
29233
29438
  * *
29234
29439
  **************************************************************************/
29235
- constructor() {
29440
+ constructor(manager) {
29441
+ this.manager = manager;
29236
29442
  /***************************************************************************
29237
29443
  * *
29238
29444
  * Fields *
29239
29445
  * *
29240
29446
  **************************************************************************/
29241
29447
  this.log = LoggerFactory.getLogger(this.constructor.name);
29242
- this._dateChangeEmitter = new EventEmitter();
29243
- this.calendarMode = signal(defaultCalendarMode);
29244
- this._startDate = signal(null);
29245
- this._endDate = signal(null);
29246
- this._startTime = signal(Temporal.PlainTime.from('00:00'));
29247
- this._endTime = signal(Temporal.PlainTime.from('00:00'));
29248
- // Anchor
29249
- this.baseReferenceDate = signal(Temporal.Now.plainDateISO());
29250
- this.baseReferenceTime = signal(Temporal.Now.plainTimeISO());
29251
- this.fixedAnchorDate = signal(null);
29252
- this.fixedAnchorTime = signal(Temporal.PlainTime.from('00:00'));
29253
- this.isEmittingOnChange = signal(true);
29254
- this.isUpdatingIntervalOnAnchorChange = signal(false);
29255
- this._isInitialized = false;
29256
- this.isFixedAnchorDateSet = computed(() => {
29257
- return !!this.fixedAnchorDate();
29258
- });
29259
- this.anchorDate = computed(() => {
29260
- if (this.fixedAnchorDate()) {
29261
- return this.fixedAnchorDate();
29262
- }
29263
- return this.baseReferenceDate();
29264
- });
29265
- this.anchorTime = computed(() => {
29266
- if (this.fixedAnchorDate() && this.fixedAnchorTime()) {
29267
- return this.fixedAnchorTime();
29268
- }
29269
- return this.baseReferenceTime();
29270
- });
29271
- this.anchorDateTime = computed(() => {
29272
- return this.anchorDate().toPlainDateTime(this.anchorTime());
29273
- });
29274
- this.dateRange = computed(() => {
29275
- if (!this.isStartAndEndDatesSet()) {
29276
- return null;
29277
- }
29278
- return new TemporalPlainDateInterval(this.startDate(), this.endDate());
29279
- });
29280
- this.dateRangeForCalendar = computed(() => {
29281
- if (!this.isStartAndEndDatesSet()) {
29282
- return null;
29283
- }
29284
- const startDate = TemporalUtil.getJSDateFromPlainDateTime(this.startDate());
29285
- const endDate = TemporalUtil.getJSDateFromPlainDateTime(this.endDate());
29286
- return new DateRange(startDate, endDate);
29287
- });
29288
- this.isStartAndEndDatesEmpty = computed(() => {
29289
- return !this.startDate() && !this.endDate();
29290
- });
29291
- this.isStartAndEndDatesSet = computed(() => {
29292
- return !!(this.startDate() && this.endDate());
29293
- });
29294
- this.isRangeNotSet = computed(() => {
29295
- return !this.isStartAndEndDatesSet();
29296
- });
29297
- this.startDateTime = computed(() => {
29298
- if (!this.startDate()) {
29299
- return null;
29300
- }
29301
- if (this.startTime()) {
29302
- return this.startDate().toPlainDateTime(this.startTime());
29303
- }
29304
- return this.startDate();
29305
- });
29306
- this.endDateTime = computed(() => {
29307
- if (!this.endDate()) {
29308
- return null;
29309
- }
29310
- if (this.endTime()) {
29311
- return this.endDate().toPlainDateTime(this.endTime());
29312
- }
29313
- return this.endDate();
29314
- });
29315
- this.startDateAsJSDate = computed(() => {
29316
- if (!this.startDate()) {
29317
- return null;
29318
- }
29319
- return TemporalUtil.getJSDateFromPlainDateTime(this.startDate());
29320
- });
29321
- this.endDateAsJSDate = computed(() => {
29322
- if (!this.endDate()) {
29323
- return null;
29324
- }
29325
- return TemporalUtil.getJSDateFromPlainDateTime(this.endDate());
29326
- });
29327
- this.startDateTimeAsJSDate = computed(() => {
29328
- if (!this.startDateTime()) {
29329
- return null;
29330
- }
29331
- return TemporalUtil.getJSDateFromPlainDateTime(this.startDateTime());
29332
- });
29333
- this.endDateTimeAsJSDate = computed(() => {
29334
- if (!this.endDateTime()) {
29335
- return null;
29336
- }
29337
- return TemporalUtil.getJSDateFromPlainDateTime(this.endDateTime());
29338
- });
29339
- this.viewIntervalMessage = computed(() => PlainDateIntervalMessageRenderer.toMessage(this.calendarMode(), this.dateRange()));
29340
- this.deltaHumanReadable = computed(() => {
29341
- if (this.isStartAndEndDatesEmpty()) {
29342
- return '';
29343
- }
29344
- const duration = this.deltaAsTemporalDuration(this.startDateTime(), this.endDateTime());
29345
- return PlainTemporalDurationMessageRenderer.toMessage(duration);
29346
- });
29347
- this.getStartTimeString = computed(() => {
29348
- return TemporalUtil.getHtmlTimeStringFromPlainTime(this.startTime());
29349
- });
29350
- this.getEndTimeString = computed(() => {
29351
- return TemporalUtil.getHtmlTimeStringFromPlainTime(this.endTime());
29352
- });
29353
- this.getAnchorTimeString = computed(() => {
29354
- return TemporalUtil.getHtmlTimeStringFromPlainTime(this.fixedAnchorTime());
29355
- });
29356
- this.getAnchorPointAsLocaleDate = computed(() => {
29357
- const anchorPoint = this.fixedAnchorDate();
29358
- if (!anchorPoint) {
29359
- return null;
29360
- }
29361
- const jsDate = TemporalUtil.getJSDateFromPlainDateTime(anchorPoint);
29362
- const localeDate = TimeUtil.dateToLocalDate(jsDate);
29363
- return localeDate;
29364
- });
29365
- this.startDateHtmlString = computed(() => {
29366
- return TemporalUtil.getHtmlDateString(this.startDateTime());
29367
- });
29368
- this.endDateHtmlString = computed(() => {
29369
- return TemporalUtil.getHtmlDateString(this.endDateTime());
29370
- });
29371
- this.isStartTimeSetAndNotMidnight = computed(() => {
29372
- if (!this.startTime()) {
29373
- return false;
29374
- }
29375
- return (this.startTime().hour !== 0 || this.startTime().minute !== 0 || this.startTime().second !== 0);
29376
- });
29377
- this.isEndTimeSetAndNotMidnight = computed(() => {
29378
- if (!this.endTime()) {
29379
- return false;
29380
- }
29381
- return this.endTime().hour !== 0 || this.endTime().minute !== 0 || this.endTime().second !== 0;
29382
- });
29383
- this.isFixedAnchorTimeSetAndNotMidnight = computed(() => {
29384
- if (!this.fixedAnchorTime()) {
29385
- return false;
29386
- }
29387
- return (this.fixedAnchorTime().hour !== 0 ||
29388
- this.fixedAnchorTime().minute !== 0 ||
29389
- this.fixedAnchorTime().second !== 0);
29390
- });
29391
- this.editor = new IntervalPickerModelEditor(this);
29392
- effect(() => {
29393
- const startDateTime = this.startDateTime();
29394
- const endDateTime = this.endDateTime();
29395
- if (this.isEmittingOnChange()) {
29396
- this.emitMainDates(); // TODO Only emit if changed
29397
- }
29398
- });
29448
+ this.select = new IntervalSelectController(manager);
29449
+ this.shift = new IntervalShiftController(manager);
29450
+ this.form = new IntervalFormController(manager);
29451
+ this.calendar = new IntervalCalendarController(manager);
29452
+ this.anchor = new IntervalAnchorController(manager);
29399
29453
  }
29400
29454
  /***************************************************************************
29401
29455
  * *
29402
- * Properties *
29456
+ * Public API *
29403
29457
  * *
29404
29458
  **************************************************************************/
29405
- startDate() {
29406
- return this._startDate();
29459
+ clearInterval() {
29460
+ this.manager.setInterval(null);
29407
29461
  }
29408
- endDate() {
29409
- return this._endDate();
29410
- }
29411
- startTime() {
29412
- return this._startTime();
29462
+ clearEndTime() {
29463
+ this.manager.setInterval(this.manager.intervalValue.withEndTime(null));
29413
29464
  }
29414
- endTime() {
29415
- return this._endTime();
29465
+ clearStartTime() {
29466
+ this.manager.setInterval(this.manager.intervalValue.withStartTime(null));
29416
29467
  }
29468
+ manualEmit() { }
29469
+ }
29470
+
29471
+ class IntervalPickerStateManager {
29417
29472
  /***************************************************************************
29418
29473
  * *
29419
- * Public API *
29474
+ * Constructor *
29420
29475
  * *
29421
29476
  **************************************************************************/
29422
- setInitialized() {
29423
- this._isInitialized = true;
29424
- }
29425
- setStartDate(value) {
29426
- const current = untracked(this._startDate);
29427
- if (!TemporalUtil.equalPlainDates(current, value)) {
29428
- this._startDate.set(value);
29429
- }
29430
- }
29431
- setEndDate(value) {
29432
- const current = untracked(this._endDate);
29433
- if (!TemporalUtil.equalPlainDates(current, value)) {
29434
- this._endDate.set(value);
29435
- }
29436
- }
29437
- setStartTime(value) {
29438
- const current = untracked(this._startTime);
29439
- if (!TemporalUtil.equalPlainTimes(current, value)) {
29440
- this._startTime.set(value);
29441
- }
29442
- }
29443
- setEndTime(value) {
29444
- const current = untracked(this._endTime);
29445
- if (!TemporalUtil.equalPlainTimes(current, value)) {
29446
- this._endTime.set(value);
29447
- }
29448
- }
29449
- setStartDateFromHtmlString(htmlString) {
29450
- const date = TemporalUtil.getPlainDateFromHtmlDateString(htmlString);
29451
- if (!date) {
29452
- return;
29453
- }
29454
- this.calendarMode.set('days');
29455
- this.setStartDate(date);
29456
- }
29457
- setEndDateFromHtmlString(htmlString) {
29458
- const date = TemporalUtil.getPlainDateFromHtmlDateString(htmlString);
29459
- if (!date) {
29460
- return;
29461
- }
29462
- this.calendarMode.set('days');
29463
- this.setEndDate(date);
29477
+ constructor() {
29478
+ /***************************************************************************
29479
+ * *
29480
+ * Fields *
29481
+ * *
29482
+ **************************************************************************/
29483
+ this.log = LoggerFactory.getLogger(this.constructor.name);
29484
+ this._anchor = new BehaviorSubject(AnchorState.empty());
29485
+ this._interval = new BehaviorSubject(null);
29486
+ this._smartShift = new BehaviorSubject(null);
29487
+ this._intervalChange = new Subject();
29488
+ this.isInitialized = false;
29464
29489
  }
29465
- setInterval(value) {
29466
- this.setDateTimesFromElderInterval(value);
29490
+ /***************************************************************************
29491
+ * *
29492
+ * Properties *
29493
+ * *
29494
+ **************************************************************************/
29495
+ get interval$() {
29496
+ return this._interval.asObservable();
29467
29497
  }
29468
- setAnchorDateTime(value) {
29469
- this.setAnchorDateTimeFromJsDate(value);
29498
+ get anchor$() {
29499
+ return this._anchor.asObservable();
29470
29500
  }
29471
- setupEventEmitter(e) {
29472
- this._dateChangeEmitter = e;
29501
+ get smartShift$() {
29502
+ return this._smartShift.asObservable();
29473
29503
  }
29474
- setStartTimeFromString(timeStr) {
29475
- const time = TemporalUtil.getPlainTimeFromHtmlTimeString(timeStr);
29476
- if (time) {
29477
- this.setStartTime(time);
29478
- }
29479
- if (!untracked(this._startDate)) {
29480
- this.setStartDate(Temporal.Now.plainDateISO());
29481
- }
29482
- this.calendarMode.set('days');
29504
+ get intervalValue() {
29505
+ return this._interval.getValue();
29483
29506
  }
29484
- setEndTimeFromString(timeStr) {
29485
- const time = TemporalUtil.getPlainTimeFromHtmlTimeString(timeStr);
29486
- if (time) {
29487
- this.setEndTime(time);
29488
- }
29489
- if (!untracked(this._endDate)) {
29490
- this.setEndDate(Temporal.Now.plainDateISO());
29491
- }
29492
- this.calendarMode.set('days');
29493
- }
29494
- resetCalendarMode() {
29495
- this.calendarMode.set(defaultCalendarMode);
29507
+ get anchorValue() {
29508
+ return this._anchor.getValue();
29496
29509
  }
29497
- setAnchorDateTimeFromJsDate(dateTime) {
29498
- if (!dateTime) {
29499
- return;
29500
- }
29501
- const date = TemporalUtil.getPlainDateFromJSDate(dateTime);
29502
- const time = TemporalUtil.getPlainTimeFromJSDate(dateTime);
29503
- this.fixedAnchorDate.set(date);
29504
- this.fixedAnchorTime.set(time);
29505
- }
29506
- setFixedAnchorPointToStartDateTime() {
29507
- if (!this.startDate()) {
29508
- this.resetFixedAnchorPoint();
29509
- return;
29510
- }
29511
- if (this.startDate()) {
29512
- this.fixedAnchorDate.set(this.startDate());
29513
- }
29514
- if (this.startTime()) {
29515
- this.fixedAnchorTime.set(this.startTime());
29516
- }
29510
+ get smartShiftValue() {
29511
+ return this._smartShift.getValue();
29517
29512
  }
29518
- setFixedAnchorPointToEndDateTime() {
29519
- if (!this.endDate()) {
29520
- this.resetFixedAnchorPoint();
29521
- return;
29522
- }
29523
- if (this.endDate()) {
29524
- this.fixedAnchorDate.set(this.endDate());
29525
- }
29526
- if (this.endTime()) {
29527
- this.fixedAnchorTime.set(this.endTime());
29528
- }
29513
+ get intervalChange() {
29514
+ return this._intervalChange.asObservable();
29529
29515
  }
29530
- resetFixedAnchorPoint() {
29531
- this.fixedAnchorDate.set(null);
29532
- this.fixedAnchorTime.set(Temporal.PlainTime.from('00:00'));
29533
- if (this.isUpdatingIntervalOnAnchorChange() && this.isStartAndEndDatesSet()) {
29534
- this.shiftRangeEndToToday();
29535
- }
29516
+ /***************************************************************************
29517
+ * *
29518
+ * Public API *
29519
+ * *
29520
+ **************************************************************************/
29521
+ setAnchor(anchor) {
29522
+ this._anchor.next(anchor);
29536
29523
  }
29537
- setAnchorDateFromForm(dateArg) {
29538
- if (!dateArg) {
29539
- this.fixedAnchorDate.set(null);
29524
+ setExternalAnchor(TemporalDateTime) {
29525
+ if (!TemporalDateTime) {
29526
+ this.setAnchor(AnchorState.empty());
29540
29527
  return;
29541
29528
  }
29542
- const jsDate = TimeUtil.localDateToDate(dateArg);
29543
- const plainDate = TemporalUtil.getPlainDateFromJSDate(jsDate);
29544
- if (!plainDate) {
29545
- this.log.warn('Invalid date', plainDate);
29546
- return;
29547
- }
29548
- this.fixedAnchorDate.set(plainDate);
29549
- if (!this.isUpdatingIntervalOnAnchorChange()) {
29550
- return;
29551
- }
29552
- if (this.fixedAnchorDate()) {
29553
- this.editor.shiftSelectionToAnchorDate();
29554
- }
29529
+ this.setAnchor(AnchorState.createFromDateTime(TemporalDateTime));
29555
29530
  }
29556
- clearStartDateTime() {
29557
- this.setStartDate(null);
29558
- this.setStartTime(null);
29559
- }
29560
- clearEndDateTime() {
29561
- this.setEndDate(null);
29562
- this.setEndTime(null);
29563
- }
29564
- clearStartTime() {
29565
- this.setStartTime(null);
29566
- }
29567
- clearEndTime() {
29568
- this.setEndTime(null);
29569
- }
29570
- resetFixedAnchorTime() {
29571
- this.fixedAnchorTime.set(Temporal.PlainTime.from('00:00'));
29572
- }
29573
- setAnchorTimeFromForm(htmlString) {
29574
- const time = TemporalUtil.getPlainTimeFromHtmlTimeString(htmlString);
29575
- if (!time) {
29531
+ setExternalInterval(interval) {
29532
+ if (!interval) {
29533
+ this.setInterval(new IntervalState(null, null));
29576
29534
  return;
29577
29535
  }
29578
- if (!this.fixedAnchorDate()) {
29579
- this.fixedAnchorDate.set(Temporal.Now.plainDateISO());
29580
- }
29581
- this.fixedAnchorTime.set(time);
29582
- if (!this.isUpdatingIntervalOnAnchorChange()) {
29536
+ if (!interval) {
29537
+ this.setInterval(new IntervalState(null, null));
29583
29538
  return;
29584
29539
  }
29585
- if (this.fixedAnchorTime()) {
29586
- this.editor.shiftSelectionToAnchorTime();
29587
- }
29540
+ this.setInterval(interval);
29588
29541
  }
29589
- emitMainDates() {
29590
- if (!this._isInitialized) {
29591
- return;
29592
- }
29593
- const interval = this.createElderInterval();
29594
- this._dateChangeEmitter.emit(interval);
29542
+ setSmartShift(smartShift) {
29543
+ this._smartShift.next(smartShift);
29595
29544
  }
29596
- /***************************************************************************
29597
- * *
29598
- * Private methods *
29599
- * *
29600
- **************************************************************************/
29601
- setDateTimesFromElderInterval(interval) {
29602
- if (!interval) {
29603
- this.setStartDate(null);
29604
- this.setEndDate(null);
29545
+ setInterval(interval) {
29546
+ if (!this.isInitialized && !interval) {
29605
29547
  return;
29606
29548
  }
29607
- if (interval.start) {
29608
- const startDateAsJSDate = TimeUtil.date(interval.start);
29609
- this.setStartDate(TemporalUtil.getPlainDateFromJSDate(startDateAsJSDate));
29610
- this.setStartTime(TemporalUtil.getPlainTimeFromJSDate(startDateAsJSDate));
29611
- }
29612
- else {
29613
- this.setStartDate(null);
29614
- }
29615
- if (interval.end) {
29616
- const endDateAsJSDate = TimeUtil.date(interval.end);
29617
- this.setEndDate(TemporalUtil.getPlainDateFromJSDate(endDateAsJSDate));
29618
- this.setEndTime(TemporalUtil.getPlainTimeFromJSDate(endDateAsJSDate));
29619
- }
29620
- else {
29621
- this.setEndDate(null);
29622
- }
29623
- this.log.debug('Applied interval to picker model:', interval);
29624
- }
29625
- createElderInterval() {
29626
- let start, end = null;
29627
- if (this.startDateTime()) {
29628
- const jsDate = TemporalUtil.getJSDateFromPlainDateTime(this.startDateTime());
29629
- start = TimeUtil.instant(jsDate);
29630
- }
29631
- if (this.endDateTime()) {
29632
- const jsDate = TemporalUtil.getJSDateFromPlainDateTime(this.endDateTime());
29633
- end = TimeUtil.instant(jsDate);
29634
- }
29635
- if (!start && !end) {
29636
- return new Interval(null, null);
29637
- }
29638
- return new Interval(start, end);
29639
- }
29640
- shiftRangeEndToToday() {
29641
- if (!this.isStartAndEndDatesSet()) {
29549
+ if (this._interval.getValue() &&
29550
+ IntervalPickerUtil.isIntervalEquals(this._interval.getValue(), interval)) {
29642
29551
  return;
29643
29552
  }
29644
- const duration = this.startDate().until(this.endDate());
29645
- this.setEndDate(Temporal.Now.plainDateISO());
29646
- this.setStartDate(this.endDate().subtract(duration));
29553
+ const newInterval = interval ? IntervalPickerUtil.setMillisecondsToZero(interval) : null;
29554
+ this._interval.next(newInterval);
29555
+ this._intervalChange.next(newInterval);
29647
29556
  }
29648
- deltaAsTemporalDuration(startDateTime, endDateTime) {
29649
- if (!startDateTime || !endDateTime) {
29650
- return null;
29651
- }
29652
- return startDateTime.until(endDateTime);
29557
+ }
29558
+
29559
+ class IntervalPickerPresenter {
29560
+ constructor(interval$, anchor$, smartShift$) {
29561
+ this.startDateHtmlString = computed(() => {
29562
+ return TemporalUtil.getHtmlDateString(this.intervalState()?.startDate);
29563
+ });
29564
+ this.endDateHtmlString = computed(() => {
29565
+ return TemporalUtil.getHtmlDateString(this.intervalState()?.endDate);
29566
+ });
29567
+ this.anchorDateHtmlString = computed(() => {
29568
+ return TemporalUtil.getHtmlDateString(this.anchorState()?.fixedDate);
29569
+ });
29570
+ this.startTimeHtmlString = computed(() => {
29571
+ return TemporalUtil.getHtmlTimeStringFromPlainTime(this.intervalState()?.startTime);
29572
+ });
29573
+ this.endTimeHtmlString = computed(() => {
29574
+ return TemporalUtil.getHtmlTimeStringFromPlainTime(this.intervalState()?.endTime);
29575
+ });
29576
+ this.anchorTimeHtmlString = computed(() => {
29577
+ return TemporalUtil.getHtmlTimeStringFromPlainTime(this.anchorState()?.fixedTime);
29578
+ });
29579
+ this.isValidIntervalSet = computed(() => {
29580
+ return IntervalPickerUtil.isIntervalWithStartAndEnd(this.intervalState());
29581
+ });
29582
+ this.deltaHumanReadable = computed(() => {
29583
+ return IntervalPickerUtil.getDeltaHumanReadable(this.intervalState());
29584
+ });
29585
+ this.smartShiftMessage = computed(() => {
29586
+ try {
29587
+ return IntervalPickerUtil.getSmartShiftMessage(this.smartShiftState().mode, this.intervalState());
29588
+ }
29589
+ catch (e) {
29590
+ return '-';
29591
+ }
29592
+ });
29593
+ this.startDateTimeAsJSDate = computed(() => {
29594
+ if (!this.intervalState()?.startDateTime) {
29595
+ return null;
29596
+ }
29597
+ return TemporalUtil.getJSDateFromPlainDateTime(this.intervalState()?.startDateTime);
29598
+ });
29599
+ this.endDateTimeAsJSDate = computed(() => {
29600
+ if (!this.intervalState()?.endDateTime) {
29601
+ return null;
29602
+ }
29603
+ return TemporalUtil.getJSDateFromPlainDateTime(this.intervalState()?.endDateTime);
29604
+ });
29605
+ this.dateRangeForCalendar = computed(() => {
29606
+ const start = this.startDateTimeAsJSDate();
29607
+ const end = this.endDateTimeAsJSDate();
29608
+ return new DateRange(start, end);
29609
+ });
29610
+ this.isStartTimeSetAndNotMidnight = computed(() => {
29611
+ return IntervalPickerUtil.isTimeSetAndNotMidnight(this.intervalState()?.startTime);
29612
+ });
29613
+ this.isEndTimeSetAndNotMidnight = computed(() => {
29614
+ return IntervalPickerUtil.isTimeSetAndNotMidnight(this.intervalState()?.endTime);
29615
+ });
29616
+ this.isFixedAnchorDateSet = computed(() => {
29617
+ return this.anchorState().isFixed;
29618
+ });
29619
+ this.isAnchorTimeMidnight = computed(() => {
29620
+ return this.anchorState().isTimeMidnight;
29621
+ });
29622
+ this.isAnchorMenuDisabled = computed(() => {
29623
+ return !this.startDateHtmlString() && !this.endDateHtmlString() && !this.anchorState().isFixed;
29624
+ });
29625
+ this.calendarAnchorDateCssClassFn = (cellDate, view) => {
29626
+ const calendarAnchorDateCssClassFnBody = (cellDate, view) => {
29627
+ const anchorDate = this.anchorState()?.fixedDate;
29628
+ if (!anchorDate) {
29629
+ return '';
29630
+ }
29631
+ const date = TemporalUtil.getJSDateFromPlainDateTime(anchorDate);
29632
+ if (!date) {
29633
+ return '';
29634
+ }
29635
+ if (cellDate.getDate() === date.getDate() &&
29636
+ cellDate.getMonth() === date.getMonth() &&
29637
+ cellDate.getFullYear() === date.getFullYear()) {
29638
+ return 'elder-custom-anchor-date';
29639
+ }
29640
+ return '';
29641
+ };
29642
+ return calendarAnchorDateCssClassFnBody(cellDate, view);
29643
+ };
29644
+ this.intervalState = toSignal(interval$);
29645
+ this.anchorState = toSignal(anchor$);
29646
+ this.smartShiftState = toSignal(smartShift$);
29653
29647
  }
29654
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: IntervalPickerModel, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
29655
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: IntervalPickerModel }); }
29656
29648
  }
29657
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: IntervalPickerModel, decorators: [{
29658
- type: Injectable
29659
- }], ctorParameters: () => [] });
29660
29649
 
29661
29650
  class ElderIntervalPickerComponent {
29662
- set interval(value) {
29663
- this.model.setInterval(value);
29664
- }
29665
- set anchorDateTime(value) {
29666
- this.model.setAnchorDateTime(value);
29667
- }
29668
29651
  /***************************************************************************
29669
29652
  * *
29670
29653
  * Constructor *
29671
29654
  * *
29672
29655
  **************************************************************************/
29673
- constructor(model) {
29674
- this.model = model;
29656
+ constructor() {
29675
29657
  /***************************************************************************
29676
29658
  * *
29677
29659
  * Fields *
29678
29660
  * *
29679
29661
  **************************************************************************/
29680
29662
  this.log = LoggerFactory.getLogger(this.constructor.name);
29681
- this.emitOnChange = input(true, { transform: (v) => booleanAttribute(v) });
29682
- this.intervalInputMode = input('date-range');
29683
- this.showAnchor = input(false, { transform: (v) => booleanAttribute(v) });
29684
- this.anchorReadOnly = input(false, { transform: (v) => booleanAttribute(v) });
29685
- this.showResultText = input(true, { transform: (v) => booleanAttribute(v) });
29686
- this.showHelpText = input(false, { transform: (v) => booleanAttribute(v) });
29687
- this.lastExcludesToday = input(false, { transform: (v) => booleanAttribute(v) });
29688
- this.dateChange = new EventEmitter();
29689
- this.calendarAnchorDateCssClassFn = (cellDate, view) => {
29690
- return this.calendarAnchorDateCssClassFnBody(cellDate, view);
29691
- };
29692
- this.model.setupEventEmitter(this.dateChange);
29693
- effect(() => {
29694
- if (this.model.anchorDate()) {
29695
- this.updateMatCalendarTodayDate();
29663
+ this.emitType = input('interval');
29664
+ this.autoEmitMode = input(true, { transform: booleanTransformFn });
29665
+ this.intervalInputMode = input('date-time-range');
29666
+ this.showAnchor = input(false, { transform: booleanTransformFn });
29667
+ this.anchorReadOnly = input(false, { transform: booleanTransformFn });
29668
+ this.externalAnchorDateTime = input(Temporal.Now.plainDateTimeISO());
29669
+ this.externalInterval = input(null);
29670
+ this.manager = new IntervalPickerStateManager();
29671
+ this.controller = new IntervalController(this.manager);
29672
+ this.presenter = new IntervalPickerPresenter(this.manager.interval$, this.manager.anchor$, this.manager.smartShift$);
29673
+ this.manager.intervalChange.pipe(takeUntilDestroyed()).subscribe({
29674
+ next: (state) => this.tryUpdateMatCalendarActiveDate(state),
29675
+ });
29676
+ this.intervalChange = this.manager.intervalChange.pipe(map$1((srcInterval) => {
29677
+ if (!srcInterval) {
29678
+ return null;
29696
29679
  }
29680
+ const elderInterval = IntervalPickerUtil.createElderInterval(srcInterval);
29681
+ if (this.emitType() === 'iso') {
29682
+ console.log('emitting type iso', coerceIntervalIsoStr(elderInterval));
29683
+ return coerceIntervalIsoStr(elderInterval);
29684
+ }
29685
+ console.log('emitting type elder interval', elderInterval);
29686
+ return elderInterval;
29687
+ }));
29688
+ this.manager.anchor$.pipe(takeUntilDestroyed()).subscribe((anchor) => {
29689
+ IntervalPickerUtil.updateMatCalendarTodayDate(this.calendarStart, this.calendarEnd);
29697
29690
  });
29698
- effect(() => {
29699
- this.updateMatCalendarActiveDate(this.model.startDate(), this.model.endDate());
29691
+ const externalAnchorObservable = toObservable(this.externalAnchorDateTime);
29692
+ externalAnchorObservable.pipe(takeUntilDestroyed()).subscribe({
29693
+ next: (date) => {
29694
+ this.manager.setExternalAnchor(date);
29695
+ },
29696
+ });
29697
+ const externalIntervalObservable = toObservable(this.externalInterval);
29698
+ externalIntervalObservable.pipe(takeUntilDestroyed()).subscribe({
29699
+ next: (interval) => {
29700
+ const result = coerceInterval(interval);
29701
+ this.manager.setInterval(IntervalPickerUtil.transformToIntervalState(result || null));
29702
+ },
29700
29703
  });
29701
29704
  }
29702
29705
  /***************************************************************************
@@ -29705,10 +29708,11 @@ class ElderIntervalPickerComponent {
29705
29708
  * *
29706
29709
  **************************************************************************/
29707
29710
  ngAfterViewInit() {
29708
- this.model.isEmittingOnChange.set(this.emitOnChange());
29709
29711
  this.setupDateInputCalendarFocusPrevention();
29710
29712
  setTimeout(() => {
29711
- this.model.setInitialized();
29713
+ // this prevents ngmodel issue
29714
+ this.manager.isInitialized = true;
29715
+ console.log('externalInterval', this.externalInterval());
29712
29716
  }, 0);
29713
29717
  }
29714
29718
  ngOnDestroy() {
@@ -29716,7 +29720,7 @@ class ElderIntervalPickerComponent {
29716
29720
  }
29717
29721
  /***************************************************************************
29718
29722
  * *
29719
- * Public API *
29723
+ * Private methods *
29720
29724
  * *
29721
29725
  **************************************************************************/
29722
29726
  setupDateInputCalendarFocusPrevention() {
@@ -29741,43 +29745,6 @@ class ElderIntervalPickerComponent {
29741
29745
  nativeElementStart.addEventListener('focus', this.calendarElFocusEventHandler, true);
29742
29746
  nativeElementEnd.addEventListener('focus', this.calendarElFocusEventHandler, true);
29743
29747
  }
29744
- clearStartDateTime() {
29745
- this.model.clearStartDateTime();
29746
- this.model.resetCalendarMode();
29747
- if (this.emitOnChange()) {
29748
- this.model.emitMainDates();
29749
- }
29750
- }
29751
- clearEndDateTime() {
29752
- this.model.clearEndDateTime();
29753
- this.model.resetCalendarMode();
29754
- if (this.emitOnChange()) {
29755
- this.model.emitMainDates();
29756
- }
29757
- }
29758
- clearStartAndEndDateTimes() {
29759
- this.model.clearStartDateTime();
29760
- this.model.clearEndDateTime();
29761
- this.model.resetCalendarMode();
29762
- if (this.emitOnChange()) {
29763
- this.model.emitMainDates();
29764
- }
29765
- }
29766
- handleStartCalendarChange(changedDate) {
29767
- this.model.calendarMode.set('days');
29768
- const newPlainDate = TemporalUtil.getPlainDateFromJSDate(changedDate);
29769
- this.model.setStartDate(newPlainDate);
29770
- }
29771
- handleEndCalendarChange(changedDate) {
29772
- this.model.calendarMode.set('days');
29773
- const newPlainDate = TemporalUtil.getPlainDateFromJSDate(changedDate);
29774
- this.model.setEndDate(newPlainDate);
29775
- }
29776
- /***************************************************************************
29777
- * *
29778
- * Private methods *
29779
- * *
29780
- **************************************************************************/
29781
29748
  removeEventListeners() {
29782
29749
  if (!this.calendarStartElRef || !this.calendarEndElRef) {
29783
29750
  return;
@@ -29790,47 +29757,16 @@ class ElderIntervalPickerComponent {
29790
29757
  nativeElementStart.removeEventListener('focus', this.calendarElFocusEventHandler, true);
29791
29758
  nativeElementEnd.removeEventListener('focus', this.calendarElFocusEventHandler, true);
29792
29759
  }
29793
- calendarAnchorDateCssClassFnBody(cellDate, view) {
29794
- const anchorDate = this.model.fixedAnchorDate();
29795
- if (!anchorDate) {
29796
- return '';
29797
- }
29798
- const date = TemporalUtil.getJSDateFromPlainDateTime(anchorDate);
29799
- if (!date) {
29800
- return '';
29760
+ tryUpdateMatCalendarActiveDate(interval) {
29761
+ try {
29762
+ IntervalPickerUtil.updateMatCalendarActiveDate(this.calendarStart, this.calendarEnd, interval.startDate, interval.endDate);
29801
29763
  }
29802
- if (cellDate.getDate() === date.getDate() &&
29803
- cellDate.getMonth() === date.getMonth() &&
29804
- cellDate.getFullYear() === date.getFullYear()) {
29805
- return 'elder-custom-anchor-date';
29764
+ catch (e) {
29765
+ console.debug('Failed to update calendar active date', e);
29806
29766
  }
29807
- return '';
29808
29767
  }
29809
- updateMatCalendarActiveDate(startDate, endDate) {
29810
- if (!this.calendarStart || !this.calendarEnd) {
29811
- return;
29812
- }
29813
- if (!startDate && !endDate) {
29814
- return;
29815
- }
29816
- const calendarStart = this.calendarStart;
29817
- const calendarEnd = this.calendarEnd;
29818
- setTimeout(() => {
29819
- // timeout is needed to run calendar update last, otherwise there are issues
29820
- if (startDate) {
29821
- calendarStart.activeDate = TemporalUtil.getJSDateFromPlainDateTime(startDate);
29822
- }
29823
- if (endDate) {
29824
- calendarEnd.activeDate = TemporalUtil.getJSDateFromPlainDateTime(endDate);
29825
- }
29826
- }, 0);
29827
- }
29828
- updateMatCalendarTodayDate() {
29829
- this.calendarStart.updateTodaysDate();
29830
- this.calendarEnd.updateTodaysDate();
29831
- }
29832
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderIntervalPickerComponent, deps: [{ token: IntervalPickerModel }], target: i0.ɵɵFactoryTarget.Component }); }
29833
- 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: { emitType: { classPropertyName: "emitType", publicName: "emitType", isSignal: true, isRequired: false, transformFunction: null }, autoEmitMode: { classPropertyName: "autoEmitMode", publicName: "autoEmitMode", 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 }, 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\n mat-icon-button\n matSuffix\n [matMenuTriggerFor]=\"anchorMenu\"\n [disabled]=\"presenter.isAnchorMenuDisabled()\"\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]=\"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 }); }
29834
29770
  }
29835
29771
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderIntervalPickerComponent, decorators: [{
29836
29772
  type: Component,
@@ -29848,12 +29784,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
29848
29784
  FormsModule,
29849
29785
  MatButtonModule,
29850
29786
  MatCalendar,
29851
- ElderLocalDateInputComponent,
29852
29787
  MatTooltip,
29853
29788
  TranslateModule,
29854
29789
  MatMenuModule,
29855
- ], 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"] }]
29856
- }], ctorParameters: () => [{ type: IntervalPickerModel }], propDecorators: { calendarStart: [{
29790
+ ElderIntervalInputComponent,
29791
+ ], 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\n mat-icon-button\n matSuffix\n [matMenuTriggerFor]=\"anchorMenu\"\n [disabled]=\"presenter.isAnchorMenuDisabled()\"\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]=\"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"] }]
29792
+ }], ctorParameters: () => [], propDecorators: { intervalChange: [{
29793
+ type: Output
29794
+ }], calendarStart: [{
29857
29795
  type: ViewChild,
29858
29796
  args: ['rangeCalendarStart']
29859
29797
  }], calendarEnd: [{
@@ -29871,12 +29809,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
29871
29809
  }], endDateInput: [{
29872
29810
  type: ViewChild,
29873
29811
  args: ['endDateInput']
29874
- }], dateChange: [{
29875
- type: Output
29876
- }], interval: [{
29877
- type: Input
29878
- }], anchorDateTime: [{
29879
- type: Input
29880
29812
  }] } });
29881
29813
 
29882
29814
  class ElderOverlayOriginDirective {
@@ -30184,7 +30116,7 @@ class ElderOverlayComponent {
30184
30116
  const searchPanelPortal = new TemplatePortal(this.templateRef, this.viewContainer);
30185
30117
  return this._overlayRef.attach(searchPanelPortal);
30186
30118
  }
30187
- 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 }); }
30119
+ 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 }); }
30188
30120
  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: [
30189
30121
  {
30190
30122
  provide: ElderOverlayRef,
@@ -30221,7 +30153,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
30221
30153
  },
30222
30154
  ],
30223
30155
  }]
30224
- }], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: i1$c.Overlay }, { type: i1$c.OverlayPositionBuilder }], propDecorators: { templateRef: [{
30156
+ }], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: i1$d.Overlay }, { type: i1$d.OverlayPositionBuilder }], propDecorators: { templateRef: [{
30225
30157
  type: ViewChild,
30226
30158
  args: [TemplateRef, { static: true }]
30227
30159
  }], originX: [{
@@ -30254,133 +30186,77 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
30254
30186
 
30255
30187
  class ElderIntervalPickerToggleComponent {
30256
30188
  constructor() {
30257
- /***************************************************************************
30258
- * *
30259
- * Fields *
30260
- * *
30261
- **************************************************************************/
30262
30189
  this.log = LoggerFactory.getLogger(this.constructor.name);
30263
- this.intervalInputElement = signal(undefined);
30264
- this.emitOnChange = input(true, { transform: (v) => booleanAttribute(v) });
30265
- this.showAnchor = input(false, { transform: (v) => booleanAttribute(v) });
30266
- this.anchorReadOnly = input(false, { transform: (v) => booleanAttribute(v) });
30267
- this.disabled = input(false, { transform: (v) => booleanAttribute(v) });
30268
- this.buttonDisabled = computed(() => this.intervalInputDisabled() || this.disabled());
30269
- this.intervalInputDisabled = signal(false);
30270
- this.showResultText = input(true, { transform: (v) => booleanAttribute(v) });
30271
- this.showHelpText = input(true, { transform: (v) => booleanAttribute(v) });
30272
- this.lastExcludesToday = input(false, { transform: (v) => booleanAttribute(v) });
30273
- this.anchorDateTime = input(null);
30274
- this.inputInterval = null;
30275
- this.intervalInputMode = 'date-range'; // will be overwritten by connected element after view init
30190
+ this.connectedIntervalInput = null;
30191
+ this.intervalInputMode = signal('date-time-range');
30192
+ this.emitType = signal('interval');
30193
+ this.externalInterval = signal(null);
30194
+ this.showAnchor = input(false);
30195
+ this.anchorReadOnly = input(false);
30196
+ this.externalAnchorDateTime = input(null);
30197
+ this.disabled = booleanAttribute(false);
30276
30198
  }
30277
30199
  /***************************************************************************
30278
30200
  * *
30279
30201
  * Life Cycle *
30280
30202
  * *
30281
30203
  **************************************************************************/
30282
- ngOnDestroy() {
30283
- this.inputIntervalElSubscription.unsubscribe();
30284
- }
30285
30204
  ngAfterViewInit() {
30286
- const intervalControl = this.intervalInputElement();
30287
- if (intervalControl.disabled) {
30288
- this.intervalInputDisabled.set(true);
30205
+ if (!this.connectedIntervalInput) {
30206
+ this.log.error('ElderIntervalPickerToggleComponent: connectedIntervalInput is required.');
30207
+ return;
30289
30208
  }
30290
- this.inputIntervalElSubscription = intervalControl.valueUpdated.subscribe({
30291
- next: (value) => this.updateModelInterval(this.coerceInterval(value)),
30209
+ this.intervalInputMode.set(this.connectedIntervalInput.mode);
30210
+ this.emitType.set(this.connectedIntervalInput.valueAsIsoStr ? 'iso' : 'interval');
30211
+ this.connectedIntervalInput.valueChange.subscribe((interval) => {
30212
+ this.externalInterval.set(interval);
30292
30213
  });
30293
- this.intervalInputMode = intervalControl.mode;
30294
- this.updateModelInterval(this.readIntervalInputValue(intervalControl));
30214
+ if (this.connectedIntervalInput.value) {
30215
+ // this is necessary to set the value of the interval picker
30216
+ this.externalInterval.set(this.connectedIntervalInput.value);
30217
+ }
30295
30218
  }
30296
30219
  /***************************************************************************
30297
30220
  * *
30298
30221
  * Public API *
30299
30222
  * *
30300
30223
  **************************************************************************/
30301
- handleOverlayAttachedChange(attached) {
30302
- if (this.emitOnChange()) {
30303
- return;
30304
- }
30305
- this.updateModelFromIntervalInput();
30306
- }
30307
- updateModelFromIntervalInput() {
30308
- this.updateModelInterval(this.readIntervalInputValue(this.intervalInputElement()));
30224
+ setConnectedIntervalInput(intervalInput) {
30225
+ this.connectedIntervalInput = intervalInput;
30309
30226
  }
30310
30227
  handleIntervalPickerDateChange(interval) {
30311
- this.inputInterval = interval;
30312
- this.updateIntervalInputElement(this.inputInterval);
30313
- }
30314
- registerInputComponent(inputComponent) {
30315
- this.intervalInputElement.set(inputComponent);
30316
- }
30317
- /***************************************************************************
30318
- * *
30319
- * Private methods *
30320
- * *
30321
- **************************************************************************/
30322
- updateModelInterval(value) {
30323
- this.inputInterval = value;
30324
- this.connectedIntervalPicker.model.setInterval(value);
30325
- }
30326
- updateIntervalInputElement(interval) {
30327
- const intervalControl = this.intervalInputElement();
30328
- if (intervalControl) {
30329
- intervalControl.value = interval;
30330
- }
30331
- }
30332
- readIntervalInputValue(intervalComponent) {
30333
- if (intervalComponent) {
30334
- return this.coerceInterval(intervalComponent.value);
30335
- }
30336
- return undefined;
30337
- }
30338
- coerceInterval(value) {
30339
- if (value instanceof Interval) {
30340
- return value;
30341
- }
30342
- else if (value != undefined) {
30343
- return Interval.parse(value);
30344
- }
30345
- else {
30346
- return undefined;
30347
- }
30228
+ this.connectedIntervalInput.value = interval;
30348
30229
  }
30349
30230
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderIntervalPickerToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
30350
- 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: `
30231
+ 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: `
30351
30232
  <span style="padding-right: 8px">
30352
30233
  <button
30353
30234
  mat-icon-button
30354
30235
  [elderOverlayOrigin]="dateIntervalOverlay"
30355
30236
  [elderOverlayTrigger]="dateIntervalOverlay"
30356
- [disabled]="buttonDisabled()"
30357
- (click)="updateModelFromIntervalInput()"
30358
30237
  class="elder-control-icon-button mat-datepicker-toggle"
30359
30238
  >
30360
30239
  <mat-icon>date_range</mat-icon>
30361
30240
  </button>
30362
30241
  </span>
30363
30242
 
30364
- <elder-overlay #dateIntervalOverlay (attachedChange)="handleOverlayAttachedChange($event)">
30243
+ <elder-overlay #dateIntervalOverlay>
30365
30244
  <elder-dialog-panel>
30366
30245
  <div class="pb-md pt-xs">
30367
30246
  <elder-interval-picker
30368
30247
  #connectedIntervalPicker
30369
- [intervalInputMode]="intervalInputMode"
30370
- [emitOnChange]="emitOnChange()"
30371
- [interval]="inputInterval"
30372
- (dateChange)="handleIntervalPickerDateChange($event)"
30248
+ [intervalInputMode]="intervalInputMode()"
30249
+ (intervalChange)="handleIntervalPickerDateChange($event)"
30250
+ [externalInterval]="externalInterval()"
30373
30251
  [showAnchor]="showAnchor()"
30374
- [anchorDateTime]="anchorDateTime()"
30375
30252
  [anchorReadOnly]="anchorReadOnly()"
30376
- [showResultText]="showResultText()"
30377
- [showHelpText]="showHelpText()"
30378
- [lastExcludesToday]="lastExcludesToday()"
30253
+ [externalAnchorDateTime]="externalAnchorDateTime()"
30254
+ [emitType]="emitType()"
30379
30255
  ></elder-interval-picker>
30380
30256
  </div>
30381
30257
  </elder-dialog-panel>
30382
30258
  </elder-overlay>
30383
- `, 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 }); }
30259
+ `, isInline: true, dependencies: [{ kind: "component", type: ElderIntervalPickerComponent, selector: "elder-interval-picker", inputs: ["emitType", "autoEmitMode", "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 }); }
30384
30260
  }
30385
30261
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderIntervalPickerToggleComponent, decorators: [{
30386
30262
  type: Component,
@@ -30406,29 +30282,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
30406
30282
  mat-icon-button
30407
30283
  [elderOverlayOrigin]="dateIntervalOverlay"
30408
30284
  [elderOverlayTrigger]="dateIntervalOverlay"
30409
- [disabled]="buttonDisabled()"
30410
- (click)="updateModelFromIntervalInput()"
30411
30285
  class="elder-control-icon-button mat-datepicker-toggle"
30412
30286
  >
30413
30287
  <mat-icon>date_range</mat-icon>
30414
30288
  </button>
30415
30289
  </span>
30416
30290
 
30417
- <elder-overlay #dateIntervalOverlay (attachedChange)="handleOverlayAttachedChange($event)">
30291
+ <elder-overlay #dateIntervalOverlay>
30418
30292
  <elder-dialog-panel>
30419
30293
  <div class="pb-md pt-xs">
30420
30294
  <elder-interval-picker
30421
30295
  #connectedIntervalPicker
30422
- [intervalInputMode]="intervalInputMode"
30423
- [emitOnChange]="emitOnChange()"
30424
- [interval]="inputInterval"
30425
- (dateChange)="handleIntervalPickerDateChange($event)"
30296
+ [intervalInputMode]="intervalInputMode()"
30297
+ (intervalChange)="handleIntervalPickerDateChange($event)"
30298
+ [externalInterval]="externalInterval()"
30426
30299
  [showAnchor]="showAnchor()"
30427
- [anchorDateTime]="anchorDateTime()"
30428
30300
  [anchorReadOnly]="anchorReadOnly()"
30429
- [showResultText]="showResultText()"
30430
- [showHelpText]="showHelpText()"
30431
- [lastExcludesToday]="lastExcludesToday()"
30301
+ [externalAnchorDateTime]="externalAnchorDateTime()"
30302
+ [emitType]="emitType()"
30432
30303
  ></elder-interval-picker>
30433
30304
  </div>
30434
30305
  </elder-dialog-panel>
@@ -30439,6 +30310,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
30439
30310
  }], propDecorators: { connectedIntervalPicker: [{
30440
30311
  type: ViewChild,
30441
30312
  args: ['connectedIntervalPicker']
30313
+ }], connectedIntervalInput: [{
30314
+ type: Input
30315
+ }], disabled: [{
30316
+ type: Input
30442
30317
  }] } });
30443
30318
 
30444
30319
  class ElderIntervalPickerBindingDirective {
@@ -30456,9 +30331,10 @@ class ElderIntervalPickerBindingDirective {
30456
30331
  ngAfterContentInit() {
30457
30332
  if (!this.intervalInputComponent || !this.intervalPickerToggleComponent) {
30458
30333
  console.error('ElderIntervalPickerBindingDirective: Both components are required, IntervalInputComponent and IntervalPickerToggleComponent.');
30334
+ return;
30459
30335
  }
30336
+ this.intervalPickerToggleComponent.connectedIntervalInput = this.intervalInputComponent;
30460
30337
  this.intervalInputComponent.isDefaultDatePickerDisabled = true;
30461
- this.intervalPickerToggleComponent.registerInputComponent(this.intervalInputComponent);
30462
30338
  }
30463
30339
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderIntervalPickerBindingDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
30464
30340
  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 }); }
@@ -35090,7 +34966,7 @@ class ElderTabDirective {
35090
34966
  constructor(tab) {
35091
34967
  this.tab = tab;
35092
34968
  }
35093
- 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 }); }
34969
+ 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 }); }
35094
34970
  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 }); }
35095
34971
  }
35096
34972
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderTabDirective, decorators: [{
@@ -35099,7 +34975,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
35099
34975
  selector: '[elderTab]',
35100
34976
  standalone: true,
35101
34977
  }]
35102
- }], ctorParameters: () => [{ type: i1$d.MatTab }], propDecorators: { id: [{
34978
+ }], ctorParameters: () => [{ type: i1$e.MatTab }], propDecorators: { id: [{
35103
34979
  type: Input,
35104
34980
  args: ['elderTab']
35105
34981
  }] } });
@@ -35330,7 +35206,7 @@ class ElderTabGroupRoutingDirective {
35330
35206
  serializeIndexMarker(index) {
35331
35207
  return ElderTabGroupRoutingDirective.TAB_INDEX_PREFIX + String(index);
35332
35208
  }
35333
- 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 }); }
35209
+ 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 }); }
35334
35210
  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 }); }
35335
35211
  }
35336
35212
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderTabGroupRoutingDirective, decorators: [{
@@ -35340,7 +35216,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
35340
35216
  exportAs: 'elderTabGroupRouting',
35341
35217
  standalone: true,
35342
35218
  }]
35343
- }], ctorParameters: () => [{ type: ElderUrlFragmentParamsService }, { type: i1$d.MatTabGroup }], propDecorators: { tabGroupQueryParamKey: [{
35219
+ }], ctorParameters: () => [{ type: ElderUrlFragmentParamsService }, { type: i1$e.MatTabGroup }], propDecorators: { tabGroupQueryParamKey: [{
35344
35220
  type: Input,
35345
35221
  args: ['elderTabGroupRouting']
35346
35222
  }], tabs: [{