@dereekb/dbx-form 9.25.4 → 9.25.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@ import { Injectable, SkipSelf, Directive, Injector, Optional, Component, Inject,
5
5
  import { FieldType } from '@ngx-formly/material';
6
6
  import { switchMap, first, tap, map, distinctUntilChanged, shareReplay, of, combineLatestWith, BehaviorSubject, filter, combineLatest, EMPTY, startWith, throttleTime } from 'rxjs';
7
7
  import { filterMaybe, distinctUntilHasDifferentValues, SubscriptionObject, asObservableFromGetter, asObservable } from '@dereekb/rxjs';
8
- import { DateCellScheduleDayCode, expandDateCellScheduleDayCodesToDayOfWeekSet, dateCellTimingStartsAtForStartOfDay, dateCellTimingRelativeIndexFactory, dateCellDayOfWeekFactory, findMaxDate, findMinDate, isSameDateRange, isSameDateDay, isSameDate, dateCellTimingDateFactory, expandDateCellScheduleRange, formatToISO8601DayString, changeDateCellScheduleDateRangeToTimezone, isSameDateCellScheduleDateRange, dateCellTimingRelativeIndexArrayFactory, isInfiniteDateRange, copyDateCellScheduleDateFilterConfig, dateTimezoneUtcNormal, dateCellScheduleDateFilter, fullDateCellScheduleRange, dateCellTimingTimezoneNormalInstance, expandDateCellScheduleDayCodes, fullWeekDateCellScheduleDayCodes, dateCellScheduleDayCodesAreSetsEquivalent, simplifyDateCellScheduleDayCodes, isDateInDateRangeFunction, isDateWithinDateCellRangeFunction, dateCellScheduleEncodedWeek, dateCellTimingStartDateFactory, enabledDaysFromDateCellScheduleDayCodes, dateCellScheduleDayCodesFromEnabledDays, formatToMonthDayString, dateRange, DateRangeType } from '@dereekb/date';
8
+ import { DateCellScheduleDayCode, expandDateCellScheduleDayCodesToDayOfWeekSet, dateCellTimingStartsAtForStartOfDay, dateCellTimingRelativeIndexFactory, dateCellDayOfWeekFactory, dateTimezoneUtcNormal, findMaxDate, findMinDate, isSameDateRange, isSameDateDay, isSameDate, dateCellTimingDateFactory, expandDateCellScheduleRange, formatToISO8601DayString, changeDateCellScheduleDateRangeToTimezone, isSameDateCellScheduleDateRange, dateCellTimingRelativeIndexArrayFactory, isInfiniteDateRange, copyDateCellScheduleDateFilterConfig, SYSTEM_DATE_TIMEZONE_UTC_NORMAL_INSTANCE, dateCellScheduleDateFilter, fullDateCellScheduleRange, dateCellTimingTimezoneNormalInstance, expandDateCellScheduleDayCodes, fullWeekDateCellScheduleDayCodes, dateCellScheduleDayCodesAreSetsEquivalent, simplifyDateCellScheduleDayCodes, isDateInDateRangeFunction, isDateWithinDateCellRangeFunction, dateCellScheduleEncodedWeek, dateCellTimingStartDateFactory, enabledDaysFromDateCellScheduleDayCodes, dateCellScheduleDayCodesFromEnabledDays, formatToMonthDayString, dateRange, DateRangeType } from '@dereekb/date';
9
9
  import { isInAllowedDaysOfWeekSet, mapValuesToSet, unique, mergeArrays, iterableToArray, range, toggleInSet, removeFromSet, addToSet, isIndexNumberInIndexRangeFunction, minAndMaxNumber, getDaysOfWeekNames, reduceBooleansWithAnd, mergeObjects, KeyValueTypleValueFilter } from '@dereekb/util';
10
10
  import { ComponentStore } from '@ngrx/component-store';
11
11
  import { startOfDay, endOfDay, isBefore, endOfWeek } from 'date-fns';
@@ -112,6 +112,36 @@ function initialCalendarScheduleSelectionState() {
112
112
  cellContentFactory: defaultCalendarScheduleSelectionCellContentFactory
113
113
  };
114
114
  }
115
+ /**
116
+ * This is used in cases where the dates in the min/max date range need to be shifted to the filter's timezone.
117
+ *
118
+ * This is because the index factory is always in system timezone, but when selecting all/none with a filter we need to use the filter's timezone.
119
+ *
120
+ * @param x
121
+ * @returns
122
+ */
123
+ function calendarScheduleMinAndMaxDateRangeRelativeToFilter(x) {
124
+ var _a;
125
+ let input = x;
126
+ if (((_a = x.filter) === null || _a === void 0 ? void 0 : _a.timezone) && x.minMaxDateRange != null) {
127
+ const filterNormal = dateTimezoneUtcNormal(x.filter.timezone);
128
+ const transformFn = filterNormal.transformFunction('systemDateToTargetDate');
129
+ input = {
130
+ filter: x.filter,
131
+ minMaxDateRange: {
132
+ start: x.minMaxDateRange.start ? transformFn(x.minMaxDateRange.start) : undefined,
133
+ end: x.minMaxDateRange.end ? transformFn(x.minMaxDateRange.end) : undefined
134
+ }
135
+ };
136
+ }
137
+ return calendarScheduleMinAndMaxDateRange(input);
138
+ }
139
+ function calendarScheduleMinAndMaxDateRange(x) {
140
+ return {
141
+ start: calendarScheduleMinDate(x) || undefined,
142
+ end: calendarScheduleMaxDate(x) || undefined
143
+ };
144
+ }
115
145
  function calendarScheduleMinDate(x) {
116
146
  var _a, _b;
117
147
  return findMaxDate([(_a = x.filter) === null || _a === void 0 ? void 0 : _a.start, (_b = x.minMaxDateRange) === null || _b === void 0 ? void 0 : _b.start]);
@@ -120,12 +150,6 @@ function calendarScheduleMaxDate(x) {
120
150
  var _a, _b;
121
151
  return findMinDate([(_a = x.filter) === null || _a === void 0 ? void 0 : _a.end, (_b = x.minMaxDateRange) === null || _b === void 0 ? void 0 : _b.end]);
122
152
  }
123
- function calendarScheduleMinAndMaxDateRange(x) {
124
- return {
125
- start: calendarScheduleMinDate(x) || undefined,
126
- end: calendarScheduleMaxDate(x) || undefined
127
- };
128
- }
129
153
  function calendarScheduleStartBeingUsedFromFilter(x) {
130
154
  var _a;
131
155
  return x.computeSelectionResultRelativeToFilter && ((_a = x.filter) === null || _a === void 0 ? void 0 : _a.start) != null; // may be using either
@@ -322,7 +346,6 @@ function updateStateWithMinMaxDateRange(state, minMaxDateRange) {
322
346
  return updateStateWithFilter(state, state.filter);
323
347
  }
324
348
  function updateStateWithFilter(state, inputFilter) {
325
- var _a, _b;
326
349
  const { computedExclusions: exclusions, minMaxDateRange, systemTimezone } = state;
327
350
  let isEnabledFilterDay = () => true;
328
351
  let filter = null;
@@ -332,21 +355,34 @@ function updateStateWithFilter(state, inputFilter) {
332
355
  let filterStart = null; // the start date that will be used/set on the filter.
333
356
  if (inputFilter) {
334
357
  filter = copyDateCellScheduleDateFilterConfig(inputFilter); // copy filter
358
+ let nextFilterTimezone; // only set if inputFilter.start or inputFilter.startsAt
335
359
  // configure filter start
336
360
  if (inputFilter.start) {
337
361
  filterStart = inputFilter.start;
362
+ // if no timezone is specified, then use the system timezone and align filterStart to the start of the day.
363
+ if (!inputFilter.timezone) {
364
+ filterStart = SYSTEM_DATE_TIMEZONE_UTC_NORMAL_INSTANCE.startOfDayInTargetTimezone(inputFilter.startsAt);
365
+ nextFilterTimezone = systemTimezone;
366
+ }
367
+ else {
368
+ nextFilterTimezone = inputFilter.timezone;
369
+ }
338
370
  }
339
371
  else if (inputFilter.startsAt) {
340
372
  if (inputFilter.timezone) {
373
+ // if no timezone is provided, use startsAt as-is
341
374
  const timezoneNormal = dateTimezoneUtcNormal(inputFilter.timezone);
342
375
  filterStart = timezoneNormal.startOfDayInTargetTimezone(inputFilter.startsAt);
376
+ nextFilterTimezone = inputFilter.timezone;
343
377
  }
344
378
  else {
345
- filterStart = inputFilter.startsAt;
346
- filter.timezone = systemTimezone;
379
+ // set to the start of today in the system timezone.
380
+ filterStart = SYSTEM_DATE_TIMEZONE_UTC_NORMAL_INSTANCE.startOfDayInTargetTimezone(inputFilter.startsAt);
381
+ nextFilterTimezone = systemTimezone;
347
382
  }
348
383
  }
349
384
  filter.start = filterStart !== null && filterStart !== void 0 ? filterStart : undefined;
385
+ filter.timezone = nextFilterTimezone;
350
386
  // configure exclusions
351
387
  if (exclusions === null || exclusions === void 0 ? void 0 : exclusions.length) {
352
388
  enabledFilter = Object.assign(Object.assign({}, filter), { ex: unique(mergeArrays([filter.ex, exclusions])) });
@@ -369,17 +405,46 @@ function updateStateWithFilter(state, inputFilter) {
369
405
  * If the input filter has a start date, use that as the relative start to ensure indexes are compared the same,
370
406
  * otherwise use the state's start. This is important for the index calculations.
371
407
  */
372
- enabledFilter.start = (_a = filter === null || filter === void 0 ? void 0 : filter.start) !== null && _a !== void 0 ? _a : state.start;
408
+ let finalEnabledStart;
409
+ let finalEnabledTimezone;
410
+ // filter?.start ?? state.start;
411
+ if (!enabledFilter.start) {
412
+ // use the current state's start, but make sure it is in the proper timezone.
413
+ if (enabledFilter.timezone) {
414
+ const timezoneNormal = dateTimezoneUtcNormal(enabledFilter.timezone);
415
+ finalEnabledStart = timezoneNormal.startOfDayInTargetTimezone(state.start); // get the start of the day for the current start
416
+ finalEnabledTimezone = enabledFilter.timezone;
417
+ }
418
+ else {
419
+ finalEnabledStart = state.start;
420
+ finalEnabledTimezone = systemTimezone;
421
+ }
422
+ }
423
+ else if (!enabledFilter.timezone) {
424
+ finalEnabledTimezone = systemTimezone;
425
+ const timezoneNormal = dateTimezoneUtcNormal(finalEnabledTimezone);
426
+ finalEnabledStart = timezoneNormal.startOfDayInTargetTimezone(enabledFilter.start); // get the start of the day for the target timezone
427
+ }
428
+ else {
429
+ finalEnabledStart = enabledFilter.start;
430
+ finalEnabledTimezone = enabledFilter.timezone;
431
+ }
432
+ enabledFilter.start = finalEnabledStart;
433
+ enabledFilter.timezone = finalEnabledTimezone;
373
434
  // create the filter
374
435
  isEnabledFilterDay = dateCellScheduleDateFilter(enabledFilter);
375
436
  }
376
437
  state = Object.assign(Object.assign({}, state), { filter, isEnabledFilterDay });
377
438
  // For the same reason as above, use the filter's start date as the relative start if applicable.
378
439
  if (filter && filter.start) {
379
- const start = filter.start;
380
- state.start = start;
381
- state.indexFactory = dateCellTimingRelativeIndexFactory({ startsAt: start, timezone: (_b = filter.timezone) !== null && _b !== void 0 ? _b : systemTimezone });
382
- state.indexDayOfWeek = dateCellDayOfWeekFactory(start);
440
+ let startForSystemTimezone = filter.start;
441
+ if (filter.timezone) {
442
+ const timezoneNormal = dateTimezoneUtcNormal(filter.timezone);
443
+ startForSystemTimezone = timezoneNormal.systemDateToTargetDate(filter.start); // get the start of the day for the system timezone
444
+ }
445
+ state.start = startForSystemTimezone;
446
+ state.indexFactory = dateCellTimingRelativeIndexFactory({ startsAt: startForSystemTimezone, timezone: systemTimezone });
447
+ state.indexDayOfWeek = dateCellDayOfWeekFactory(startForSystemTimezone);
383
448
  }
384
449
  // attempt to re-apply the initial selection state once filter is applied
385
450
  if (state.initialSelectionState) {
@@ -497,7 +562,7 @@ function finalizeUpdateStateWithChangedScheduleDays(previousState, nextState) {
497
562
  function updateStateWithChangedDates(state, change) {
498
563
  var _a;
499
564
  const { allowedDaysOfWeek, indexFactory, indexDayOfWeek, inputStart: currentInputStart, inputEnd: currentInputEnd, minMaxDateRange, filter } = state;
500
- const { start: minDate, end: maxDate } = calendarScheduleMinAndMaxDateRange(state);
565
+ const { start: minDate, end: maxDate } = calendarScheduleMinAndMaxDateRangeRelativeToFilter(state);
501
566
  let inputStart = currentInputStart;
502
567
  let inputEnd = currentInputEnd;
503
568
  /**
@@ -582,8 +647,8 @@ function noSelectionCalendarScheduleSelectionState(state) {
582
647
  return finalizeNewCalendarScheduleSelectionState(Object.assign(Object.assign({}, state), { toggledIndexes: new Set(), inputStart: null, inputEnd: null }));
583
648
  }
584
649
  function updateStateWithChangedRange(state, change) {
585
- const { inputStart: currentInputStart, inputEnd: currentInputEnd, indexFactory, minMaxDateRange } = state;
586
- const { start: minDate, end: maxDate } = minMaxDateRange !== null && minMaxDateRange !== void 0 ? minMaxDateRange : {};
650
+ const { inputStart: currentInputStart, inputEnd: currentInputEnd, indexFactory } = state;
651
+ const { start: minDate, end: maxDate } = calendarScheduleMinAndMaxDateRange(state);
587
652
  const inputStart = startOfDay(change.inputStart);
588
653
  const inputEnd = startOfDay(change.inputEnd); // midnight of the last day
589
654
  const isValidRange = minDate != null || maxDate != null ? isDateInDateRangeFunction({ start: minDate !== null && minDate !== void 0 ? minDate : undefined, end: maxDate !== null && maxDate !== void 0 ? maxDate : undefined }) : () => true;
@@ -625,7 +690,7 @@ function isEnabledDayInCalendarScheduleSelectionState(state) {
625
690
  };
626
691
  }
627
692
  function computeScheduleSelectionValue(state) {
628
- const { indexFactory, allowedDaysOfWeek, effectiveScheduleDays, indexDayOfWeek, computeSelectionResultRelativeToFilter, filter, systemTimezone } = state;
693
+ const { indexFactory: systemIndexFactory, allowedDaysOfWeek, effectiveScheduleDays, indexDayOfWeek, computeSelectionResultRelativeToFilter, filter, systemTimezone } = state;
629
694
  let timezone = systemTimezone;
630
695
  const rangeAndExclusion = computeScheduleSelectionRangeAndExclusion(state);
631
696
  if (rangeAndExclusion == null) {
@@ -639,12 +704,16 @@ function computeScheduleSelectionValue(state) {
639
704
  // If computeSelectionResultRelativeToFilter is true, then we need to offset the values to be relative to that start.
640
705
  if (computeSelectionResultRelativeToFilter && (filter === null || filter === void 0 ? void 0 : filter.start)) {
641
706
  start = filter.start; // always start at the filter's start date
707
+ let startInSystemTimezone = start;
642
708
  if (filter.timezone) {
643
709
  timezone = filter.timezone;
644
710
  const filterNormal = dateTimezoneUtcNormal(timezone);
645
711
  end = filterNormal.startOfDayInTargetTimezone(end);
712
+ startInSystemTimezone = filterNormal.systemDateToTargetDate(start); // convert the start to the system timezone normal for deriving the index
646
713
  }
647
- const filterStartIndexOffset = indexFactory(rangeStart) - indexFactory(start);
714
+ const rangeStartIndex = systemIndexFactory(rangeStart);
715
+ const startIndex = systemIndexFactory(startInSystemTimezone);
716
+ const filterStartIndexOffset = rangeStartIndex - startIndex;
648
717
  filterOffsetExcludedRange = range(0, filterStartIndexOffset);
649
718
  indexOffset = indexOffset - filterStartIndexOffset;
650
719
  }