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

atinc / ngx-tethys / e1289f47-715a-4c2d-a6ec-393315def93d

06 Nov 2023 02:54AM UTC coverage: 90.192% (+0.02%) from 90.168%
e1289f47-715a-4c2d-a6ec-393315def93d

Pull #2886

circleci

su4g
feat(date-picker): date picker allowed input date
Pull Request #2886: feat(date-picker): date picker allowed input date

5226 of 6461 branches covered (0.0%)

Branch coverage included in aggregate %.

64 of 67 new or added lines in 3 files covered. (95.52%)

6 existing lines in 2 files now uncovered.

13157 of 13921 relevant lines covered (94.51%)

977.48 hits per line

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

88.3
/src/date-picker/base-picker.component.ts
1
import { InputBoolean, ThyPlacement } from 'ngx-tethys/core';
2
import { coerceBooleanProperty, elementMatchClosest, FunctionProp, TinyDate } from 'ngx-tethys/util';
3

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

17
import { AbstractPickerComponent } from './abstract-picker.component';
18
import { CompatibleValue, RangeAdvancedValue } from './inner-types';
138✔
19
import { CompatibleDate, ThyPanelMode } from './standard-types';
20
import { ThyPickerComponent } from './picker.component';
21

450✔
22
/**
23
 * @private
24
 */
60!
25
@Component({
26
    template: ``,
27
    standalone: true,
138✔
28
    host: {
138✔
29
        '[attr.tabindex]': `tabIndex`,
138✔
30
        '(focus)': 'onFocus($event)',
138✔
31
        '(blur)': 'onBlur($event)'
138✔
32
    }
138✔
33
})
138✔
34
export class BasePickerComponent extends AbstractPickerComponent implements OnInit, OnChanges {
138✔
35
    showWeek = false;
36

37
    panelMode: ThyPanelMode | ThyPanelMode[];
138✔
38

138✔
39
    initialized: boolean;
138✔
40

41
    @ViewChild('thyPicker', { static: true }) thyPicker: ThyPickerComponent;
42

52✔
43
    @Input() thyDateRender: FunctionProp<TemplateRef<Date> | string>;
52✔
44

52✔
45
    @Input() set thyMode(value: ThyPanelMode) {
52✔
46
        this._panelMode = value ?? 'date';
44✔
47
        if (this.initialized) {
48
            this.setDefaultTimePickerState(this._panelMode);
49
        }
50
    }
3✔
51

3✔
52
    get thyMode() {
53
        return this._panelMode;
54
    }
55

143✔
56
    /**
143✔
57
     * @type EventEmitter<ThyPanelMode | ThyPanelMode[]>
58✔
58
     */
59
    @Output() readonly thyOnPanelChange = new EventEmitter<ThyPanelMode | ThyPanelMode[]>();
60

85✔
61
    /**
62
     * @type EventEmitter<Date[]>
143✔
63
     */
143✔
64
    @Output() readonly thyOnCalendarChange = new EventEmitter<Date[]>();
116✔
65

66
    private _showTime: object | boolean;
67

68
    /**
116✔
69
     * 增加时间选择功能
70
     * @default false
116✔
71
     */
72
    @Input() get thyShowTime(): object | boolean {
73
        return this._showTime;
74
    }
75
    set thyShowTime(value: object | boolean) {
55✔
76
        this._showTime = typeof value === 'object' ? value : coerceBooleanProperty(value);
6✔
77
    }
78

79
    /**
80
     * 是否展示时间(时、分)
81
     * @default false
10!
82
     */
15✔
83
    @Input() @InputBoolean() thyMustShowTime = false;
10✔
84

85
    /**
86
     * 弹出位置
87
     * @type top | topLeft | topRight | bottom | bottomLeft | bottomRight | left | leftTop | leftBottom | right | rightTop | rightBottom
24✔
88
     */
89
    @Input() thyPlacement: ThyPlacement = 'bottomLeft';
90

5!
UNCOV
91
    /**
×
UNCOV
92
     * @type EventEmitter<CompatibleDate | null>
×
UNCOV
93
     */
×
94
    @Output() readonly thyOnOk = new EventEmitter<CompatibleDate | null>();
95

UNCOV
96
    constructor(cdr: ChangeDetectorRef, protected element: ElementRef) {
×
97
        super(cdr);
98
    }
99

100
    ngOnInit(): void {
5!
101
        super.ngOnInit();
5✔
102
        this.setDefaultTimePickerState(this._panelMode);
103
        this.initialized = true;
104
    }
×
105

106
    onValueChange(value: CompatibleValue | RangeAdvancedValue): void {
107
        this.thyPicker.onTuoched = false;
5✔
108
        this.restoreTimePickerState(value as CompatibleValue);
109
        super.onValueChange(value);
110
        if (!this.flexible) {
162✔
111
            this.closeOverlay();
162✔
112
        }
52✔
113
    }
114

115
    onEnterValue(value: CompatibleValue | RangeAdvancedValue) {
116
        this.restoreTimePickerState(value as CompatibleValue);
1✔
117
        super.onValueChange(value);
118
    }
119

120
    // Displays the time directly when the time must be displayed by default
2✔
121
    setDefaultTimePickerState(value: ThyPanelMode) {
1✔
122
        this.withTime = this.thyMustShowTime;
123
        if (this.isRange) {
1✔
124
            this.panelMode = this.flexible ? ['date', 'date'] : [value, value];
125
        } else {
126
            this.panelMode = value;
7✔
127
        }
128
        this.showWeek = value === 'week';
1✔
129
        if (!this.thyFormat) {
130
            const inputFormats: { [key in ThyPanelMode]?: string } = {
131
                year: 'yyyy',
132
                month: 'yyyy-MM',
1✔
133
                week: 'yyyy-ww周',
134
                date: this.thyShowTime ? 'yyyy-MM-dd HH:mm' : 'yyyy-MM-dd'
135
            };
136
            this.thyFormat = this.flexible ? inputFormats['date'] : inputFormats[value];
137
        }
138
    }
139

140
    // Restore after clearing time to select whether the original picker time is displayed or not
141
    restoreTimePickerState(value: CompatibleValue | null) {
142
        if (!value) {
143
            this.withTime = this.thyMustShowTime || this.originWithTime;
144
        }
1✔
145
    }
146

147
    // Emit thyOnCalendarChange when select date by thy-range-picker
148
    onCalendarChange(value: TinyDate[]): void {
1✔
149
        if (this.isRange) {
150
            const rangeValue = value.map(x => x.nativeDate);
151
            this.thyOnCalendarChange.emit(rangeValue);
152
        }
153
    }
154

155
    onShowTimePickerChange(show: boolean): void {
156
        this.withTime = show;
157
    }
158

159
    onResultOk(): void {
160
        if (this.isRange) {
161
            const value = this.thyValue as TinyDate[];
162
            if (value.length) {
163
                this.thyOnOk.emit([value[0].nativeDate, value[1].nativeDate]);
164
            } else {
165
                this.thyOnOk.emit([]);
166
            }
167
        } else {
168
            if (this.thyValue) {
169
                this.thyOnOk.emit((this.thyValue as TinyDate).nativeDate);
170
            } else {
171
                this.thyOnOk.emit(null);
172
            }
173
        }
174
        this.closeOverlay();
175
    }
176

177
    onOpenChange(open: boolean): void {
178
        this.thyOpenChange.emit(open);
179
        if (!open) {
180
            this.onTouchedFn();
181
        }
182
    }
183

184
    onFocus(event: Event) {
185
        this.picker.focus();
186
    }
187

188
    onBlur(event?: FocusEvent) {
189
        // Tab 聚焦后自动聚焦到 input 输入框,此分支下直接返回,无需触发 onTouchedFn
190
        if (elementMatchClosest(event?.relatedTarget as HTMLElement, ['date-popup', 'thy-picker'])) {
191
            return;
192
        }
193
        this.onTouchedFn();
194
    }
195

196
    onUpdateDate(event: TinyDate) {
197
        this.thyValue = event;
198
    }
199
}
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