• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

atinc / ngx-tethys / 5b1fad8c-226e-4691-8621-013ec5877dd1

pending completion
5b1fad8c-226e-4691-8621-013ec5877dd1

Pull #2748

circleci

minlovehua
fix(date-picker): should get the correct presets value when time passes #INFR-8552
Pull Request #2748: fix(date-picker): should get the correct presets value when time passes #INFR-8552

5102 of 6313 branches covered (80.82%)

Branch coverage included in aggregate %.

12 of 12 new or added lines in 3 files covered. (100.0%)

12902 of 13658 relevant lines covered (94.46%)

966.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.41
/src/date-picker/lib/popups/date-popup.component.ts
1
import { endOfDay, startOfDay } from 'date-fns';
2
import { FunctionProp, TinyDate, TinyDateCompareGrain, helpers, isFunction, isUndefinedOrNull, sortRangeValue } from 'ngx-tethys/util';
3

4
import {
5
    ChangeDetectionStrategy,
6
    ChangeDetectorRef,
7
    Component,
8
    EventEmitter,
9
    Input,
10
    OnChanges,
11
    OnInit,
12
    Output,
13
    SimpleChanges,
14
    TemplateRef
15
} from '@angular/core';
16

17
import { NgFor, NgIf, NgTemplateOutlet } from '@angular/common';
18
import { FormsModule } from '@angular/forms';
1✔
19
import { ThyButtonIconComponent } from 'ngx-tethys/button';
20
import { ThyNavComponent, ThyNavItemDirective } from 'ngx-tethys/nav';
1✔
21
import { ThyDatePickerConfigService } from '../../date-picker.service';
22
import { CompatibleValue, DatePickerFlexibleTab, RangeAdvancedValue, RangePartType } from '../../inner-types';
23
import { dateAddAmount, getShortcutValue, hasValue, makeValue, transformDateValue } from '../../picker.util';
115✔
24
import {
115✔
25
    CompatibleDate,
115✔
26
    CompatiblePresets,
115✔
27
    DisabledDateFn,
115✔
28
    SupportTimeOptions,
115✔
29
    ThyDateGranularity,
115✔
30
    ThyPanelMode,
115✔
31
    ThyShortcutPosition,
115✔
32
    ThyShortcutPreset,
115✔
33
    ThyShortcutValue,
115✔
34
    ThyShortcutValueChange
115✔
35
} from '../../standard-types';
115✔
36
import { CalendarFooterComponent } from '../calendar/calendar-footer.component';
115✔
37
import { DateCarouselComponent } from '../date-carousel/date-carousel.component';
115✔
38
import { InnerPopupComponent } from './inner-popup.component';
39

40
/**
1✔
41
 * @private
1✔
42
 */
43
@Component({
44
    changeDetection: ChangeDetectionStrategy.OnPush,
114✔
45
    // eslint-disable-next-line @angular-eslint/component-selector
114✔
46
    selector: 'date-popup',
114!
47
    exportAs: 'datePopup',
×
48
    templateUrl: './date-popup.component.html',
49
    standalone: true,
114✔
50
    imports: [
1✔
51
        NgIf,
1✔
52
        NgFor,
53
        ThyNavComponent,
114✔
54
        ThyNavItemDirective,
114✔
55
        ThyButtonIconComponent,
114✔
56
        DateCarouselComponent,
7✔
57
        FormsModule,
58
        NgTemplateOutlet,
59
        InnerPopupComponent,
60
        CalendarFooterComponent
61
    ]
62
})
63
export class DatePopupComponent implements OnChanges, OnInit {
64
    @Input() isRange: boolean;
189✔
65
    @Input() showWeek: boolean;
96✔
66

40✔
67
    @Input() format: string;
68
    @Input() disabledDate: DisabledDateFn;
69
    @Input() minDate: Date | number;
56✔
70
    @Input() maxDate: Date | number;
71
    @Input() showToday: boolean;
72

189✔
73
    /**
96✔
74
     * 是否支持设置时间(时、分)
75
     */
189✔
76
    @Input() showTime: SupportTimeOptions | boolean;
116✔
77

78
    /**
79
     * 是否展示时间(时、分)
80
     */
114✔
81
    @Input() mustShowTime: boolean;
114✔
82

326✔
83
    @Input() dateRender: FunctionProp<TemplateRef<Date> | string>;
84
    @Input() className: string;
85
    @Input() panelMode: ThyPanelMode | ThyPanelMode[];
114✔
86
    @Input() value: CompatibleValue;
78✔
87
    @Input() defaultPickerValue: CompatibleDate | number;
73✔
88

89
    @Input() showShortcut: boolean;
78✔
90

78!
91
    @Input() shortcutPresets: CompatiblePresets;
78✔
92

78✔
93
    @Input() shortcutPosition: ThyShortcutPosition;
78✔
94

78✔
95
    @Input() flexible: boolean;
78✔
96

30✔
97
    @Input() flexibleDateGranularity: ThyDateGranularity;
108✔
98

108✔
99
    @Output() readonly panelModeChange = new EventEmitter<ThyPanelMode | ThyPanelMode[]>();
108✔
100
    @Output() readonly calendarChange = new EventEmitter<CompatibleValue>();
108✔
101
    @Output() readonly valueChange = new EventEmitter<CompatibleValue | RangeAdvancedValue>();
108✔
102
    @Output() readonly resultOk = new EventEmitter<void>(); // Emitted when done with date selecting
11✔
103
    @Output() readonly showTimePickerChange = new EventEmitter<boolean>();
104
    @Output() readonly shortcutValueChange = new EventEmitter<ThyShortcutValueChange>();
105

97✔
106
    prefixCls = 'thy-calendar';
107
    showTimePicker = false;
108
    timeOptions: SupportTimeOptions | SupportTimeOptions[] | null;
109
    activeDate: TinyDate | TinyDate[];
110
    selectedValue: TinyDate[] = []; // Range ONLY
48✔
111
    hoverValue: TinyDate[] = []; // Range ONLY
98✔
112

98✔
113
    advancedSelectedValue: RangeAdvancedValue; // advanced ONLY
98✔
114

11✔
115
    flexibleActiveTab: DatePickerFlexibleTab = 'advanced';
116

117
    get hasTimePicker(): boolean {
87✔
118
        return !!this.showTime;
119
    }
120
    private partTypeMap: { [key: string]: number } = { left: 0, right: 1 };
121

122
    [property: string]: any;
123

124
    endPanelMode: ThyPanelMode | ThyPanelMode[];
125

326✔
126
    innerShortcutPresets: ThyShortcutPreset[];
326✔
127

91✔
128
    disableTimeConfirm = false;
91✔
129

130
    constructor(private cdr: ChangeDetectorRef, private datePickerConfigService: ThyDatePickerConfigService) {}
326✔
131

168✔
132
    setProperty<T extends keyof DatePopupComponent>(key: T, value: this[T]): void {
136✔
133
        this[key] = value;
134
        this.cdr.markForCheck();
168✔
135
    }
136

137
    ngOnInit(): void {
158✔
138
        this.initShortcutPresets();
139
        this.initPanelMode();
326✔
140
        if (this.flexible && this.flexibleDateGranularity === 'day') {
141
            this.flexibleActiveTab = 'custom';
142
        }
114✔
143
        if (this.defaultPickerValue && !hasValue(this.value)) {
18✔
144
            const { value } = transformDateValue(this.defaultPickerValue);
11✔
145
            this.value = makeValue(value, this.isRange);
146
        }
147
        this.updateActiveDate();
7✔
148
        this.initDisabledDate();
149
        if (this.isRange && this.flexible && this.value) {
150
            this.advancedSelectedValue = {
151
                begin: this.value[0],
96✔
152
                end: this.value[1],
40✔
153
                dateGranularity: this.flexibleDateGranularity
154
            };
155
        }
56✔
156
    }
157

158
    ngOnChanges(changes: SimpleChanges): void {
159
        if (changes.panelMode) {
160
            if (helpers.isArray(this.panelMode)) {
161
                this.endPanelMode = [...this.panelMode];
162
            } else {
163
                this.endPanelMode = this.panelMode;
114✔
164
            }
14✔
165
        }
14✔
166
        if (changes.defaultPickerValue) {
167
            this.updateActiveDate();
114✔
168
        }
13✔
169
        if (changes.value && changes.value.currentValue) {
13✔
170
            this.updateActiveDate();
171
        }
114✔
172
    }
5✔
173

174
    initShortcutPresets(): void {
114✔
175
        const { shortcutRangesPresets, shortcutDatePresets, showShortcut } = this.datePickerConfigService;
16,662✔
176

16,662✔
177
        this.showShortcut =
1,848✔
178
            ['date', 'date,date'].includes(this.panelMode.toString()) && isUndefinedOrNull(this.showShortcut)
179
                ? showShortcut
16,662✔
180
                : this.showShortcut;
1,651✔
181

182
        if (this.showShortcut) {
16,662✔
183
            if (!this.shortcutPresets) {
618✔
184
                this.shortcutPresets = this.isRange ? shortcutRangesPresets : shortcutDatePresets;
185
            }
16,662✔
186

187
            this.innerShortcutPresets = isFunction(this.shortcutPresets) ? this.shortcutPresets() : this.shortcutPresets;
188
            if (this.innerShortcutPresets.length) {
189
                const minDate: TinyDate = this.getMinTinyDate();
23✔
190
                const maxDate: TinyDate = this.getMaxTinyDate();
23✔
191

192
                const minTime = minDate ? minDate.getTime() : null;
193
                const maxTime = maxDate ? maxDate.getTime() : null;
5✔
194

5✔
195
                if (this.isRange) {
5✔
196
                    this.innerShortcutPresets.forEach((preset: ThyShortcutPreset) => {
197
                        const begin: number | Date = getShortcutValue(preset.value[0]);
198
                        const beginTime: number = new TinyDate(startOfDay(begin)).getTime();
1!
199

1✔
200
                        const end: number | Date = getShortcutValue(preset.value[1]);
1✔
201
                        const endTime: number = new TinyDate(endOfDay(end)).getTime();
202

203
                        if ((minDate && endTime < minTime) || (maxDate && beginTime > maxTime)) {
1!
204
                            preset.disabled = true;
205
                        } else {
×
206
                            preset.disabled = false;
×
207
                        }
×
208
                    });
209
                } else {
210
                    this.innerShortcutPresets.forEach((preset: ThyShortcutPreset) => {
×
211
                        const singleValue: number | Date = getShortcutValue(preset.value as ThyShortcutValue);
212
                        const singleTime: number = new TinyDate(singleValue).getTime();
213

214
                        if ((minDate && singleTime < minTime) || (maxDate && singleTime > maxTime)) {
215
                            preset.disabled = true;
11✔
216
                        } else {
1✔
217
                            preset.disabled = false;
218
                        }
219
                    });
10✔
220
                }
221
            }
11✔
222
        }
223
    }
224

34✔
225
    updateActiveDate() {
10✔
226
        this.clearHoverValue();
10✔
227
        if (!this.value) {
228
            const { value } = transformDateValue(this.defaultPickerValue);
229
            this.value = makeValue(value, this.isRange);
24✔
230
        }
231
        if (this.isRange) {
232
            if (!this.flexible || this.flexibleDateGranularity === 'day') {
233
                this.selectedValue = this.value as TinyDate[];
17!
234
            }
235
            this.activeDate = this.normalizeRangeValue(this.value as TinyDate[], this.getPanelMode(this.endPanelMode) as ThyPanelMode);
236
        } else {
237
            this.activeDate = this.value as TinyDate;
17✔
238
        }
239
        this.isDisableTimeConfirm();
240
    }
241

2✔
242
    initPanelMode() {
243
        if (!this.endPanelMode) {
244
            if (helpers.isArray(this.panelMode)) {
3✔
245
                this.endPanelMode = [...this.panelMode];
3!
246
            } else {
3✔
247
                this.endPanelMode = this.panelMode;
248
            }
249
        } else {
×
250
            if (helpers.isArray(this.endPanelMode)) {
251
                this.panelMode = [...this.endPanelMode];
3✔
252
            } else {
253
                this.panelMode = this.endPanelMode;
254
            }
255
        }
256
    }
257

258
    initDisabledDate(): void {
3✔
259
        let minDate: TinyDate;
260
        let maxDate: TinyDate;
3✔
261
        let disabledDateFn: DisabledDateFn;
262
        if (this.minDate) {
263
            const { value } = transformDateValue(this.minDate);
26✔
264
            minDate = new TinyDate(value as Date);
265
        }
18✔
266
        if (this.maxDate) {
18✔
267
            const { value } = transformDateValue(this.maxDate);
18✔
268
            maxDate = new TinyDate(value as Date);
269
        }
9✔
270
        if (this.disabledDate) {
9✔
271
            disabledDateFn = this.disabledDate;
9✔
272
        }
273
        this.disabledDate = d => {
9!
274
            let expression = false;
275
            if (minDate) {
9✔
276
                expression = d < minDate.startOfDay().nativeDate;
9✔
277
            }
9✔
278
            if (maxDate && !expression) {
9✔
279
                expression = d > maxDate.endOfDay().nativeDate;
280
            }
281
            if (disabledDateFn && typeof disabledDateFn === 'function' && !expression) {
282
                expression = disabledDateFn(d);
9✔
283
            }
9✔
284
            return expression;
9✔
285
        };
286
    }
287

288
    onShowTimePickerChange(show: boolean): void {
8✔
289
        this.showTimePicker = show;
8✔
290
        this.showTimePickerChange.emit(show);
291
    }
292

293
    onClickOk(): void {
13✔
294
        this.setValue(this.value);
2✔
295
        this.valueChange.emit(this.value);
296
        this.resultOk.emit();
11✔
297
    }
11✔
298

11✔
299
    onClickRemove(): void {
11✔
300
        this.value = this.isRange ? [] : null;
11✔
301
        this.setValue(this.value);
8✔
302
        this.valueChange.emit(this.value);
303
    }
304

3✔
305
    onDayHover(value: TinyDate): void {
306
        if (this.isRange && this.selectedValue[0] && !this.selectedValue[1]) {
307
            // When right value is selected, don't do hover
308
            const base = this.selectedValue[0]; // Use the left of selected value as the base to decide later hoverValue
708!
309
            if (base.isBeforeDay(value)) {
×
310
                this.hoverValue = [base, value];
×
311
            } else {
×
312
                this.hoverValue = [value, base];
×
313
            }
314
        }
×
315
    }
316

317
    onPanelModeChange(mode: ThyPanelMode, partType?: RangePartType): void {
708✔
318
        if (this.isRange) {
319
            (this.panelMode as ThyPanelMode[])[this.getPartTypeIndex(partType)] = mode;
320
        } else {
321
            this.panelMode = mode;
893✔
322
        }
603✔
323
        this.panelModeChange.emit(this.panelMode);
324
    }
325

290✔
326
    onHeaderChange(value: TinyDate, partType?: RangePartType): void {
327
        if (this.isRange) {
328
            this.activeDate[this.getPartTypeIndex(partType)] = value;
329
            this.activeDate = this.normalizeRangeValue(
353✔
330
                this.activeDate as TinyDate[],
208✔
331
                this.getPanelMode(this.endPanelMode, partType) as ThyPanelMode
208✔
332
            );
333
        } else {
334
            this.activeDate = value;
145✔
335
        }
336
    }
337

338
    onSelectTime(value: TinyDate, partType?: RangePartType): void {
353✔
339
        if (this.isRange) {
208✔
340
            // TODO:range picker set time
341
        } else {
342
            this.setValue(new TinyDate(value.nativeDate));
145✔
343
        }
344
    }
345

273✔
346
    selectTab(active: DatePickerFlexibleTab) {
1,039✔
347
        this.flexibleActiveTab = active;
348
    }
349

158✔
350
    clearFlexibleValue() {
351
        this.flexibleDateGranularity = null;
352
        if (this.flexibleActiveTab === 'advanced') {
158✔
353
            this.advancedSelectedValue = {};
354
        } else {
355
            this.selectedValue = [];
335✔
356
        }
357
        this.valueChange.emit({
358
            begin: null,
55✔
359
            end: null,
55✔
360
            dateGranularity: this.flexibleDateGranularity
1✔
361
        });
1✔
362
    }
363

364
    changeValueFromAdvancedSelect(value: RangeAdvancedValue) {
365
        this.valueChange.emit(value);
366
        // clear custom date when select a advanced date
367
        this.selectedValue = [];
368
    }
54✔
369

30✔
370
    changeValueFromSelect(value: TinyDate, partType?: RangePartType): void {
371
        if (this.isRange) {
372
            // clear advanced date when select a custom date
55✔
373
            this.advancedSelectedValue = {};
374

×
375
            const [left, right] = this.selectedValue as TinyDate[];
187✔
376

377
            if ((!left && !right) || (left && right)) {
378
                // If totally full or empty, clean up && re-assign left first
379
                this.hoverValue = this.selectedValue = [value];
380
                this.selectedValue = [new TinyDate(startOfDay(this.selectedValue[0].nativeDate))];
381
                this.calendarChange.emit([this.selectedValue[0].clone()]);
187✔
382
            } else if (left && !right) {
187✔
383
                // If one of them is empty, assign the other one and sort, then set the final values
187✔
384
                this.clearHoverValue(); // Clean up
187✔
385
                this.setRangeValue('right', value);
187✔
386
                this.selectedValue = sortRangeValue(this.selectedValue); // Sort
145✔
387
                this.selectedValue = [
388
                    new TinyDate(startOfDay(this.selectedValue[0].nativeDate)),
187✔
389
                    new TinyDate(endOfDay(this.selectedValue[1].nativeDate))
6✔
390
                ];
391
                this.activeDate = this.normalizeRangeValue(
187✔
392
                    this.selectedValue,
393
                    this.getPanelMode(this.endPanelMode, partType) as ThyPanelMode
394
                );
9✔
395
                this.setValue(this.cloneRangeDate(this.selectedValue));
9✔
396
                this.calendarChange.emit(this.cloneRangeDate(this.selectedValue));
397
            }
398
        } else {
37✔
399
            const updatedValue = this.updateHourMinute(value);
400
            this.setValue(updatedValue);
401
        }
381✔
402
    }
316✔
403

404
    private updateHourMinute(value: TinyDate): TinyDate {
65✔
405
        if (!this.value) {
65✔
406
            return value;
65✔
407
        }
65✔
408
        const originDate = this.value as TinyDate;
16✔
409
        const dateTime = [value.getHours(), value.getMinutes(), value.getSeconds()];
410
        const originDateTime = [originDate.getHours(), originDate.getMinutes(), originDate.getSeconds()];
411

49✔
412
        const isEqualTime = dateTime.toString() === originDateTime.toString();
413
        if (isEqualTime) {
414
            return value;
415
        } else {
15✔
416
            return value.setHms(originDateTime[0], originDateTime[1], originDateTime[2]);
15✔
417
        }
15✔
418
    }
15✔
419

15✔
420
    enablePrevNext(direction: 'prev' | 'next', partType?: RangePartType): boolean {
10✔
421
        if (this.isRange && this.panelMode === this.endPanelMode) {
10✔
422
            const [start, end] = this.activeDate as TinyDate[];
10✔
423
            const showMiddle = !start.addMonths(1).isSame(end, 'month'); // One month diff then don't show middle prev/next
10✔
424
            if ((partType === 'left' && direction === 'next') || (partType === 'right' && direction === 'prev')) {
10!
425
                return showMiddle;
×
426
            }
427
            return true;
10✔
428
        } else {
1✔
429
            return true;
430
        }
9✔
431
    }
1✔
432

433
    getPanelMode(panelMode: ThyPanelMode | ThyPanelMode[], partType?: RangePartType): ThyPanelMode {
8✔
434
        if (this.isRange) {
1✔
435
            return panelMode[this.getPartTypeIndex(partType)] as ThyPanelMode;
436
        } else {
7✔
437
            return panelMode as ThyPanelMode;
438
        }
439
    }
5✔
440

5!
441
    getValueBySelector(partType?: RangePartType): TinyDate {
×
442
        if (this.isRange) {
443
            const valueShow = this.selectedValue; // Use the real time value that without decorations when timepicker is shown up
5✔
444
            return (valueShow as TinyDate[])[this.getPartTypeIndex(partType)];
445
        } else {
446
            return this.value as TinyDate;
447
        }
18✔
448
    }
2✔
449

450
    getActiveDate(partType?: RangePartType): TinyDate {
16✔
451
        if (this.isRange) {
16✔
452
            return this.activeDate[this.getPartTypeIndex(partType)];
1✔
453
        } else {
454
            return this.activeDate as TinyDate;
455
        }
15✔
456
    }
10✔
457

10✔
458
    getPartTypeIndex(partType: RangePartType = 'left'): number {
10!
459
        return this.partTypeMap[partType];
10✔
460
    }
461

462
    private getMinTinyDate() {
463
        return this.minDate ? new TinyDate(transformDateValue(this.minDate).value as Date) : null;
10✔
464
    }
465

466
    private getMaxTinyDate() {
467
        return this.maxDate ? new TinyDate(transformDateValue(this.maxDate).value as Date) : null;
5✔
468
    }
5✔
469

5✔
470
    private clearHoverValue(): void {
471
        this.hoverValue = [];
15✔
472
    }
15✔
473

474
    private setValue(value: CompatibleValue): void {
475
        this.value = value;
476
        if (this.isRange && this.flexible) {
477
            this.flexibleDateGranularity = 'day';
478
            this.valueChange.emit({
448✔
479
                begin: value[0],
480
                end: value[1],
1✔
481
                dateGranularity: this.flexibleDateGranularity
482
            });
483
        } else {
484
            if (!this.showTime || !this.showTimePicker) {
1✔
485
                this.valueChange.emit(this.value);
486
            }
487
        }
488
        this.isDisableTimeConfirm();
489
    }
490

491
    private normalizeRangeValue(value: TinyDate[], mode: ThyPanelMode = 'month'): TinyDate[] {
492
        const headerModes: { [key in ThyPanelMode]?: ThyPanelMode } = {
493
            week: 'month',
494
            date: 'month',
495
            month: 'year',
496
            year: 'decade'
497
        };
498
        const headerMode = headerModes[mode];
499
        const [start, end] = value;
500
        const newStart = start || new TinyDate();
501
        let newEnd = end;
502
        if (!newEnd) {
503
            newEnd = dateAddAmount(newStart, 1, headerMode);
504
        }
505
        if (newStart.isSame(end, headerMode as TinyDateCompareGrain)) {
506
            newEnd = dateAddAmount(newStart, 1, headerMode);
507
        }
508
        return [newStart, newEnd];
509
    }
510

511
    private setRangeValue(partType: RangePartType, value: TinyDate): void {
512
        const ref = (this.selectedValue = this.cloneRangeDate(this.selectedValue as TinyDate[]));
1✔
513
        ref[this.getPartTypeIndex(partType)] = value;
514
    }
515

516
    private cloneRangeDate(value: TinyDate[]): TinyDate[] {
517
        return [value[0] && value[0].clone(), value[1] && value[1].clone()] as TinyDate[];
518
    }
519

520
    private isDisableTimeConfirm() {
521
        if (this.isRange || !this.showTime) {
522
            return;
523
        }
524

525
        const date: TinyDate = this.value ? (this.value as TinyDate) : new TinyDate();
526
        const minDate: TinyDate = this.getMinTinyDate();
527
        const maxDate: TinyDate = this.getMaxTinyDate();
528

529
        if ((minDate && date.getTime() < minDate.getTime()) || (maxDate && date.getTime() > maxDate.getTime())) {
530
            this.disableTimeConfirm = true;
531
        } else {
532
            this.disableTimeConfirm = false;
533
        }
534
    }
535

536
    private getSelectedShortcutPreset(date: CompatibleValue): CompatibleValue {
537
        const minDate: TinyDate = this.getMinTinyDate();
538
        const maxDate: TinyDate = this.getMaxTinyDate();
539

540
        const minTime: number = (minDate && minDate.getTime()) || null;
541
        const maxTime: number = (maxDate && maxDate.getTime()) || null;
542

543
        if (helpers.isArray(date)) {
544
            const startDate: TinyDate = date[0];
545
            const endDate: TinyDate = date[1];
546

547
            const startTime: number = startDate.getTime();
548
            const endTime: number = endDate.getTime();
549

550
            if ((maxDate && startTime > maxTime) || (minDate && endTime < minTime)) {
551
                return [];
552
            }
553

554
            if (minDate && startTime < minTime && maxDate && endTime > maxTime) {
555
                return [minDate, maxDate];
556
            }
557

558
            if (minDate && startTime < minTime) {
559
                return [minDate, endDate];
560
            }
561

562
            if (maxDate && endTime > maxTime) {
563
                return [startDate, maxDate];
564
            }
565

566
            return date;
567
        } else {
568
            const singleTime: number = date.getTime();
569

570
            if ((minDate && singleTime < minTime) || (maxDate && singleTime > maxTime)) {
571
                return null;
572
            }
573

574
            return date;
575
        }
576
    }
577

578
    shortcutSetValue(shortcutPresets: ThyShortcutPreset) {
579
        if (shortcutPresets.disabled) {
580
            return;
581
        }
582

583
        const { value } = shortcutPresets;
584
        if (!value) {
585
            return;
586
        }
587

588
        let selectedPresetValue: CompatibleValue;
589
        if (helpers.isArray(value)) {
590
            const begin: number | Date = getShortcutValue(value[0]);
591
            const end: number | Date = getShortcutValue(value[1]);
592

593
            if (begin && end) {
594
                this.selectedValue = this.getSelectedShortcutPreset([
595
                    new TinyDate(startOfDay(begin)),
596
                    new TinyDate(endOfDay(end))
597
                ]) as TinyDate[];
598

599
                selectedPresetValue = this.cloneRangeDate(this.selectedValue);
600
            }
601
        } else {
602
            const singleDate: number | Date = getShortcutValue(value);
603
            const singleTinyDate: TinyDate = this.updateHourMinute(new TinyDate(singleDate));
604
            selectedPresetValue = this.getSelectedShortcutPreset(singleTinyDate) as TinyDate;
605
        }
606

607
        this.setValue(selectedPresetValue);
608
        this.shortcutValueChange.emit({
609
            value: selectedPresetValue,
610
            triggerPresets: shortcutPresets
611
        });
612
    }
613

614
    public trackByFn(index: number) {
615
        return index;
616
    }
617
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc