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

atinc / ngx-tethys / 129e0fd3-b436-4e51-a99e-27a86ab79bed

14 Dec 2023 05:55AM UTC coverage: 90.399% (-0.009%) from 90.408%
129e0fd3-b436-4e51-a99e-27a86ab79bed

Pull #2969

circleci

luxiaobei
feat(property): property-item add thyEditingChange #INFR-10910
Pull Request #2969: feat(property): property-item add thyEditingChange #INFR-10910

5353 of 6582 branches covered (0.0%)

Branch coverage included in aggregate %.

5 of 5 new or added lines in 2 files covered. (100.0%)

20 existing lines in 5 files now uncovered.

13336 of 14092 relevant lines covered (94.64%)

972.82 hits per line

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

92.47
/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';
139✔
24
import {
139✔
25
    CompatibleDate,
139✔
26
    CompatiblePresets,
139✔
27
    DisabledDateFn,
139✔
28
    SupportTimeOptions,
139✔
29
    ThyDateChangeEvent,
139✔
30
    ThyDateGranularity,
139✔
31
    ThyPanelMode,
139✔
32
    ThyShortcutPosition,
139✔
33
    ThyShortcutPreset,
139✔
34
    ThyShortcutValue,
139✔
35
    ThyShortcutValueChange
139✔
36
} from '../../standard-types';
139✔
37
import { CalendarFooterComponent } from '../calendar/calendar-footer.component';
139✔
38
import { DateCarouselComponent } from '../date-carousel/date-carousel.component';
139✔
39
import { InnerPopupComponent } from './inner-popup.component';
40

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

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

236✔
74
    /**
117✔
75
     * 是否支持设置时间(时、分)
76
     */
236✔
77
    @Input() showTime: SupportTimeOptions | boolean;
148✔
78

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

390✔
84
    @Input() dateRender: FunctionProp<TemplateRef<Date> | string>;
85
    @Input() className: string;
86
    @Input() panelMode: ThyPanelMode | ThyPanelMode[];
138✔
87
    @Input() value: CompatibleValue;
92✔
88
    @Input() defaultPickerValue: CompatibleDate | number;
87✔
89

90
    @Input() showShortcut: boolean;
92✔
91

92!
92
    @Input() shortcutPresets: CompatiblePresets;
92✔
93

92✔
94
    @Input() shortcutPosition: ThyShortcutPosition;
92✔
95

92✔
96
    @Input() flexible: boolean;
92✔
97

34✔
98
    @Input() flexibleDateGranularity: ThyDateGranularity;
124✔
99

124✔
100
    @Output() readonly panelModeChange = new EventEmitter<ThyPanelMode | ThyPanelMode[]>();
124✔
101
    @Output() readonly calendarChange = new EventEmitter<CompatibleValue>();
124✔
102
    @Output() readonly valueChange = new EventEmitter<CompatibleValue | RangeAdvancedValue>();
124✔
103
    @Output() readonly resultOk = new EventEmitter<void>(); // Emitted when done with date selecting
8✔
104
    @Output() readonly showTimePickerChange = new EventEmitter<boolean>();
105
    /**
106
     * @deprecated
116✔
107
     */
108
    @Output() readonly shortcutValueChange = new EventEmitter<ThyShortcutValueChange>();
109
    @Output() readonly dateValueChange = new EventEmitter<ThyDateChangeEvent>();
110

111
    prefixCls = 'thy-calendar';
58✔
112
    showTimePicker = false;
119✔
113
    timeOptions: SupportTimeOptions | SupportTimeOptions[] | null;
119✔
114
    activeDate: TinyDate | TinyDate[];
119✔
115
    selectedValue: TinyDate[] = []; // Range ONLY
11✔
116
    hoverValue: TinyDate[] = []; // Range ONLY
117

118
    advancedSelectedValue: RangeAdvancedValue; // advanced ONLY
108✔
119

120
    flexibleActiveTab: DatePickerFlexibleTab = 'advanced';
121

122
    get hasTimePicker(): boolean {
123
        return !!this.showTime;
124
    }
125
    private partTypeMap: { [key: string]: number } = { left: 0, right: 1 };
126

403✔
127
    [property: string]: any;
403✔
128

114✔
129
    endPanelMode: ThyPanelMode | ThyPanelMode[];
114✔
130

131
    innerShortcutPresets: ThyShortcutPreset[];
403✔
132

204✔
133
    disableTimeConfirm = false;
166✔
134

135
    constructor(private cdr: ChangeDetectorRef, private datePickerConfigService: ThyDatePickerConfigService) {}
204✔
136

137
    setProperty<T extends keyof DatePopupComponent>(key: T, value: this[T]): void {
138
        this[key] = value;
199✔
139
        this.cdr.markForCheck();
140
    }
403✔
141

142
    ngOnInit(): void {
143
        this.initShortcutPresets();
138✔
144
        this.initPanelMode();
21✔
145
        if (this.flexible && this.flexibleDateGranularity === 'day') {
13✔
146
            this.flexibleActiveTab = 'custom';
147
        }
148
        if (this.defaultPickerValue && !hasValue(this.value)) {
8✔
149
            const { value } = transformDateValue(this.defaultPickerValue);
150
            this.value = makeValue(value, this.isRange);
151
        }
152
        this.updateActiveDate();
117✔
153
        this.initDisabledDate();
48✔
154
        if (this.isRange && this.flexible && this.value) {
155
            this.advancedSelectedValue = {
156
                begin: this.value[0],
69✔
157
                end: this.value[1],
158
                dateGranularity: this.flexibleDateGranularity
159
            };
160
        }
161
    }
162

163
    ngOnChanges(changes: SimpleChanges): void {
164
        if (changes.panelMode) {
138✔
165
            if (helpers.isArray(this.panelMode)) {
15✔
166
                this.endPanelMode = [...this.panelMode];
15✔
167
            } else {
168
                this.endPanelMode = this.panelMode;
138✔
169
            }
13✔
170
        }
13✔
171
        if (changes.defaultPickerValue) {
172
            this.updateActiveDate();
138✔
173
        }
5✔
174
        if (changes.value && changes.value.currentValue) {
175
            this.updateActiveDate();
138✔
176
        }
19,584✔
177
    }
19,584✔
178

1,932✔
179
    initShortcutPresets(): void {
180
        const { shortcutRangesPresets, shortcutDatePresets, showShortcut } = this.datePickerConfigService;
19,584✔
181

1,555✔
182
        this.showShortcut =
183
            ['date', 'date,date'].includes(this.panelMode.toString()) && isUndefinedOrNull(this.showShortcut)
19,584✔
184
                ? showShortcut
618✔
185
                : this.showShortcut;
186

19,584✔
187
        if (this.showShortcut) {
188
            if (!this.shortcutPresets) {
189
                this.shortcutPresets = this.isRange ? shortcutRangesPresets : shortcutDatePresets;
190
            }
62✔
191

62✔
192
            this.innerShortcutPresets = isFunction(this.shortcutPresets) ? this.shortcutPresets() : this.shortcutPresets;
193
            if (this.innerShortcutPresets.length) {
194
                const minDate: TinyDate = this.getMinTinyDate();
5✔
195
                const maxDate: TinyDate = this.getMaxTinyDate();
5✔
196

5✔
197
                const minTime = minDate ? minDate.getTime() : null;
198
                const maxTime = maxDate ? maxDate.getTime() : null;
199

2!
200
                if (this.isRange) {
2✔
201
                    this.innerShortcutPresets.forEach((preset: ThyShortcutPreset) => {
202
                        const begin: number | Date = getShortcutValue(preset.value[0]);
203
                        const beginTime: number = new TinyDate(startOfDay(begin)).getTime();
1!
204

205
                        const end: number | Date = getShortcutValue(preset.value[1]);
×
206
                        const endTime: number = new TinyDate(endOfDay(end)).getTime();
×
207

×
208
                        if ((minDate && endTime < minTime) || (maxDate && beginTime > maxTime)) {
209
                            preset.disabled = true;
210
                        } else {
×
211
                            preset.disabled = false;
212
                        }
213
                    });
214
                } else {
215
                    this.innerShortcutPresets.forEach((preset: ThyShortcutPreset) => {
11✔
216
                        const singleValue: number | Date = getShortcutValue(preset.value as ThyShortcutValue);
1✔
217
                        const singleTime: number = new TinyDate(singleValue).getTime();
218

219
                        if ((minDate && singleTime < minTime) || (maxDate && singleTime > maxTime)) {
10✔
220
                            preset.disabled = true;
221
                        } else {
11✔
222
                            preset.disabled = false;
223
                        }
224
                    });
34✔
225
                }
10✔
226
            }
10✔
227
        }
228
    }
229

24✔
230
    updateActiveDate() {
231
        this.clearHoverValue();
232
        if (!this.value) {
233
            const { value } = transformDateValue(this.defaultPickerValue);
24!
234
            this.value = makeValue(value, this.isRange);
235
        }
236
        if (this.isRange) {
237
            if (!this.flexible || this.flexibleDateGranularity === 'day') {
24✔
238
                this.selectedValue = this.value as TinyDate[];
239
            }
240
            this.activeDate = this.normalizeRangeValue(this.value as TinyDate[], this.getPanelMode(this.endPanelMode) as ThyPanelMode);
241
        } else {
2✔
242
            this.activeDate = this.value as TinyDate;
243
        }
244
        this.isDisableTimeConfirm();
3✔
245
    }
3!
246

3✔
247
    initPanelMode() {
248
        if (!this.endPanelMode) {
249
            if (helpers.isArray(this.panelMode)) {
×
250
                this.endPanelMode = [...this.panelMode];
251
            } else {
3✔
252
                this.endPanelMode = this.panelMode;
253
            }
254
        } else {
255
            if (helpers.isArray(this.endPanelMode)) {
256
                this.panelMode = [...this.endPanelMode];
257
            } else {
258
                this.panelMode = this.endPanelMode;
5✔
259
            }
260
        }
5✔
261
    }
5✔
262

263
    initDisabledDate(): void {
264
        let minDate: TinyDate;
265
        let maxDate: TinyDate;
266
        let disabledDateFn: DisabledDateFn;
32✔
267
        if (this.minDate) {
268
            const { value } = transformDateValue(this.minDate);
20✔
269
            minDate = new TinyDate(value as Date);
20✔
270
        }
20✔
271
        if (this.maxDate) {
272
            const { value } = transformDateValue(this.maxDate);
10✔
273
            maxDate = new TinyDate(value as Date);
10✔
274
        }
10✔
275
        if (this.disabledDate) {
276
            disabledDateFn = this.disabledDate;
10!
277
        }
278
        this.disabledDate = d => {
10✔
279
            let expression = false;
10✔
280
            if (minDate) {
10✔
281
                expression = d < minDate.startOfDay().nativeDate;
10✔
282
            }
283
            if (maxDate && !expression) {
284
                expression = d > maxDate.endOfDay().nativeDate;
285
            }
10✔
286
            if (disabledDateFn && typeof disabledDateFn === 'function' && !expression) {
10✔
287
                expression = disabledDateFn(d);
10✔
288
            }
10✔
289
            return expression;
290
        };
291
    }
292

293
    onShowTimePickerChange(show: boolean): void {
294
        this.showTimePicker = show;
12✔
295
        this.showTimePickerChange.emit(show);
12✔
296
    }
12✔
297

298
    onClickOk(): void {
299
        this.setValue(this.value);
300
        this.valueChange.emit(this.value);
301
        this.resultOk.emit();
302
    }
19✔
303

8✔
304
    onClickRemove(): void {
305
        this.value = this.isRange ? [] : null;
11✔
306
        this.valueChange.emit(this.value);
11✔
307
    }
11✔
308

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

×
321
    onPanelModeChange(mode: ThyPanelMode, partType?: RangePartType): void {
×
322
        if (this.isRange) {
323
            (this.panelMode as ThyPanelMode[])[this.getPartTypeIndex(partType)] = mode;
×
324
        } else {
325
            this.panelMode = mode;
326
        }
850✔
327
        this.panelModeChange.emit(this.panelMode);
328
    }
329

330
    onHeaderChange(value: TinyDate, partType?: RangePartType): void {
1,072✔
331
        if (this.isRange) {
724✔
332
            this.activeDate[this.getPartTypeIndex(partType)] = value;
333
            this.activeDate = this.normalizeRangeValue(
334
                this.activeDate as TinyDate[],
348✔
335
                this.getPanelMode(this.endPanelMode, partType) as ThyPanelMode
336
            );
337
        } else {
338
            this.activeDate = value;
424✔
339
        }
250✔
340
    }
250✔
341

342
    onSelectTime(value: TinyDate, partType?: RangePartType): void {
343
        if (this.isRange) {
174✔
344
            // TODO:range picker set time
345
        } else {
346
            this.setValue(new TinyDate(value.nativeDate));
347
        }
424✔
348
    }
250✔
349

350
    selectTab(active: DatePickerFlexibleTab) {
351
        this.flexibleActiveTab = active;
174✔
352
    }
353

354
    clearFlexibleValue() {
325✔
355
        this.flexibleDateGranularity = null;
1,245✔
356
        if (this.flexibleActiveTab === 'advanced') {
357
            this.advancedSelectedValue = {};
358
        } else {
199✔
359
            this.selectedValue = [];
360
        }
361
        this.valueChange.emit({
199✔
362
            begin: null,
363
            end: null,
364
            dateGranularity: this.flexibleDateGranularity
413✔
365
        });
366
    }
367

71✔
368
    changeValueFromAdvancedSelect(value: RangeAdvancedValue) {
71✔
369
        this.valueChange.emit(value);
1✔
370
        // clear custom date when select a advanced date
1✔
371
        this.selectedValue = [];
372
        this.dateValueChange.emit({
373
            value: [value.begin, value.end]
374
        });
375
    }
376

377
    changeValueFromSelect(value: TinyDate, partType?: RangePartType): void {
70✔
378
        if (this.isRange) {
39✔
379
            // clear advanced date when select a custom date
380
            this.advancedSelectedValue = {};
381

71✔
382
            const [left, right] = this.selectedValue as TinyDate[];
383

×
384
            if ((!left && !right) || (left && right)) {
224✔
385
                // If totally full or empty, clean up && re-assign left first
386
                this.hoverValue = this.selectedValue = [value];
387
                this.selectedValue = [new TinyDate(startOfDay(this.selectedValue[0].nativeDate))];
388
                this.calendarChange.emit([this.selectedValue[0].clone()]);
389
            } else if (left && !right) {
390
                // If one of them is empty, assign the other one and sort, then set the final values
224✔
391
                this.clearHoverValue(); // Clean up
224✔
392
                this.setRangeValue('right', value);
224✔
393
                this.selectedValue = sortRangeValue(this.selectedValue); // Sort
224✔
394
                this.selectedValue = [
224✔
395
                    new TinyDate(startOfDay(this.selectedValue[0].nativeDate)),
186✔
396
                    new TinyDate(endOfDay(this.selectedValue[1].nativeDate))
397
                ];
224✔
398
                this.activeDate = this.normalizeRangeValue(
399
                    this.selectedValue,
400
                    this.getPanelMode(this.endPanelMode, partType) as ThyPanelMode
10✔
401
                );
10✔
402
                this.setValue(this.cloneRangeDate(this.selectedValue));
403
                this.calendarChange.emit(this.cloneRangeDate(this.selectedValue));
404
                this.dateValueChange.emit({
53✔
405
                    value: this.cloneRangeDate(this.selectedValue)
406
                });
407
            }
474✔
408
        } else {
387✔
409
            const updatedValue = this.updateHourMinute(value);
410
            this.setValue(updatedValue);
87✔
411
            this.dateValueChange.emit({
87✔
412
                value: updatedValue
87✔
413
            });
87✔
414
        }
16✔
415
    }
416

417
    private updateHourMinute(value: TinyDate): TinyDate {
71✔
418
        if (!this.value) {
419
            return value;
420
        }
421
        const originDate = this.value as TinyDate;
20✔
422
        const dateTime = [value.getHours(), value.getMinutes(), value.getSeconds()];
20✔
423
        const originDateTime = [originDate.getHours(), originDate.getMinutes(), originDate.getSeconds()];
20✔
424

20✔
425
        const isEqualTime = dateTime.toString() === originDateTime.toString();
20✔
426
        if (isEqualTime) {
13✔
427
            return value;
13✔
428
        } else {
13✔
429
            return value.setHms(originDateTime[0], originDateTime[1], originDateTime[2]);
13✔
430
        }
13!
UNCOV
431
    }
×
432

433
    enablePrevNext(direction: 'prev' | 'next', partType?: RangePartType): boolean {
13✔
434
        if (this.isRange && this.panelMode === this.endPanelMode) {
1✔
435
            const [start, end] = this.activeDate as TinyDate[];
436
            const showMiddle = !start.addMonths(1).isSame(end, 'month'); // One month diff then don't show middle prev/next
12✔
437
            if ((partType === 'left' && direction === 'next') || (partType === 'right' && direction === 'prev')) {
1✔
438
                return showMiddle;
439
            }
11✔
440
            return true;
1✔
441
        } else {
442
            return true;
10✔
443
        }
444
    }
445

7✔
446
    getPanelMode(panelMode: ThyPanelMode | ThyPanelMode[], partType?: RangePartType): ThyPanelMode {
7!
UNCOV
447
        if (this.isRange) {
×
448
            return panelMode[this.getPartTypeIndex(partType)] as ThyPanelMode;
449
        } else {
7✔
450
            return panelMode as ThyPanelMode;
451
        }
452
    }
453

23✔
454
    getValueBySelector(partType?: RangePartType): TinyDate {
2✔
455
        if (this.isRange) {
456
            const valueShow = this.selectedValue; // Use the real time value that without decorations when timepicker is shown up
21✔
457
            return (valueShow as TinyDate[])[this.getPartTypeIndex(partType)];
21✔
458
        } else {
1✔
459
            return this.value as TinyDate;
460
        }
461
    }
20✔
462

13✔
463
    getActiveDate(partType?: RangePartType): TinyDate {
13✔
464
        if (this.isRange) {
13!
465
            return this.activeDate[this.getPartTypeIndex(partType)];
13✔
466
        } else {
467
            return this.activeDate as TinyDate;
468
        }
469
    }
13✔
470

471
    getPartTypeIndex(partType: RangePartType = 'left'): number {
472
        return this.partTypeMap[partType];
473
    }
7✔
474

7✔
475
    private getMinTinyDate() {
7✔
476
        return this.minDate ? new TinyDate(transformDateValue(this.minDate).value as Date) : null;
477
    }
20✔
478

479
    private getMaxTinyDate() {
480
        return this.maxDate ? new TinyDate(transformDateValue(this.maxDate).value as Date) : null;
481
    }
20✔
482

20✔
483
    private clearHoverValue(): void {
20✔
484
        this.hoverValue = [];
485
    }
486

487
    private setValue(value: CompatibleValue): void {
488
        this.value = value;
540✔
489
        if (this.isRange && this.flexible) {
490
            this.flexibleDateGranularity = 'day';
1✔
491
            this.valueChange.emit({
492
                begin: value[0],
493
                end: value[1],
494
                dateGranularity: this.flexibleDateGranularity
1✔
495
            });
496
        } else {
497
            if (!this.showTime || !this.showTimePicker) {
498
                this.valueChange.emit(this.value);
499
            }
500
        }
501
        this.isDisableTimeConfirm();
502
    }
503

504
    private normalizeRangeValue(value: TinyDate[], mode: ThyPanelMode = 'month'): TinyDate[] {
505
        const headerModes: { [key in ThyPanelMode]?: ThyPanelMode } = {
506
            week: 'month',
507
            date: 'month',
508
            month: 'year',
509
            year: 'decade'
510
        };
511
        const headerMode = headerModes[mode];
512
        const [start, end] = value;
513
        const newStart = start || new TinyDate();
514
        let newEnd = end;
515
        if (!newEnd || newStart.isSame(end, headerMode as TinyDateCompareGrain)) {
516
            newEnd = dateAddAmount(newStart, 1, headerMode);
517
        }
518
        return [newStart, newEnd];
519
    }
520

521
    private setRangeValue(partType: RangePartType, value: TinyDate): void {
522
        const ref = (this.selectedValue = this.cloneRangeDate(this.selectedValue as TinyDate[]));
523
        ref[this.getPartTypeIndex(partType)] = value;
1✔
524
    }
525

526
    private cloneRangeDate(value: TinyDate[]): TinyDate[] {
527
        return [value[0] && value[0].clone(), value[1] && value[1].clone()] as TinyDate[];
528
    }
529

530
    private isDisableTimeConfirm() {
531
        if (this.isRange || !this.showTime) {
532
            return;
533
        }
534

535
        const date: TinyDate = this.value ? (this.value as TinyDate) : new TinyDate();
536
        const minDate: TinyDate = this.getMinTinyDate();
537
        const maxDate: TinyDate = this.getMaxTinyDate();
538

539
        if ((minDate && date.getTime() < minDate.getTime()) || (maxDate && date.getTime() > maxDate.getTime())) {
540
            this.disableTimeConfirm = true;
541
        } else {
542
            this.disableTimeConfirm = false;
543
        }
544
    }
545

546
    private getSelectedShortcutPreset(date: CompatibleValue): CompatibleValue {
547
        const minDate: TinyDate = this.getMinTinyDate();
548
        const maxDate: TinyDate = this.getMaxTinyDate();
549

550
        const minTime: number = (minDate && minDate.getTime()) || null;
551
        const maxTime: number = (maxDate && maxDate.getTime()) || null;
552

553
        if (helpers.isArray(date)) {
554
            const startDate: TinyDate = date[0];
555
            const endDate: TinyDate = date[1];
556

557
            const startTime: number = startDate.getTime();
558
            const endTime: number = endDate.getTime();
559

560
            if ((maxDate && startTime > maxTime) || (minDate && endTime < minTime)) {
561
                return [];
562
            }
563

564
            if (minDate && startTime < minTime && maxDate && endTime > maxTime) {
565
                return [minDate, maxDate];
566
            }
567

568
            if (minDate && startTime < minTime) {
569
                return [minDate, endDate];
570
            }
571

572
            if (maxDate && endTime > maxTime) {
573
                return [startDate, maxDate];
574
            }
575

576
            return date;
577
        } else {
578
            const singleTime: number = date.getTime();
579

580
            if ((minDate && singleTime < minTime) || (maxDate && singleTime > maxTime)) {
581
                return null;
582
            }
583

584
            return date;
585
        }
586
    }
587

588
    shortcutSetValue(shortcutPresets: ThyShortcutPreset) {
589
        if (shortcutPresets.disabled) {
590
            return;
591
        }
592

593
        const { value } = shortcutPresets;
594
        if (!value) {
595
            return;
596
        }
597

598
        let selectedPresetValue: CompatibleValue;
599
        if (helpers.isArray(value)) {
600
            const begin: number | Date = getShortcutValue(value[0]);
601
            const end: number | Date = getShortcutValue(value[1]);
602

603
            if (begin && end) {
604
                this.selectedValue = this.getSelectedShortcutPreset([
605
                    new TinyDate(startOfDay(begin)),
606
                    new TinyDate(endOfDay(end))
607
                ]) as TinyDate[];
608

609
                selectedPresetValue = this.cloneRangeDate(this.selectedValue);
610
            }
611
        } else {
612
            const singleDate: number | Date = getShortcutValue(value);
613
            const singleTinyDate: TinyDate = this.updateHourMinute(new TinyDate(singleDate));
614
            selectedPresetValue = this.getSelectedShortcutPreset(singleTinyDate) as TinyDate;
615
        }
616
        this.shortcutValueChange.emit({
617
            value: selectedPresetValue,
618
            triggerPresets: shortcutPresets
619
        });
620
        this.setValue(selectedPresetValue);
621
        this.dateValueChange.emit({
622
            value: helpers.isArray(value) ? this.selectedValue : selectedPresetValue,
623
            triggerPreset: shortcutPresets
624
        });
625
    }
626

627
    public trackByFn(index: number) {
628
        return index;
629
    }
630
}
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