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

atinc / ngx-tethys / d9ae709b-3c27-4b69-b125-b8b80b54f90b

pending completion
d9ae709b-3c27-4b69-b125-b8b80b54f90b

Pull #2757

circleci

mengshuicmq
fix: fix code review
Pull Request #2757: feat(color-picker): color-picker support disabled (#INFR-8645)

98 of 6315 branches covered (1.55%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

2392 of 13661 relevant lines covered (17.51%)

83.12 hits per line

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

7.84
/src/date-picker/abstract-picker.directive.ts
1
import { InputBoolean, InputNumber, ThyPlacement } from 'ngx-tethys/core';
2
import { ThyPopover, ThyPopoverConfig } from 'ngx-tethys/popover';
3
import { coerceBooleanProperty, FunctionProp, warnDeprecation } from 'ngx-tethys/util';
4
import { fromEvent, Observable, Subject } from 'rxjs';
5
import { debounceTime, mapTo, takeUntil, tap } from 'rxjs/operators';
6

7
import { coerceArray } from '@angular/cdk/coercion';
8
import {
9
    AfterViewInit,
10
    ChangeDetectorRef,
11
    Directive,
12
    ElementRef,
13
    EventEmitter,
14
    Input,
1✔
15
    OnChanges,
16
    OnDestroy,
×
17
    OnInit,
18
    Output,
19
    SimpleChange,
×
20
    TemplateRef
21
} from '@angular/core';
22

×
23
import { AbstractPickerComponent } from './abstract-picker.component';
×
24
import { DatePopupComponent } from './lib/popups/date-popup.component';
25
import { ThyPanelMode, ThyShortcutValueChange } from './standard-types';
×
26
import { CompatibleValue } from './inner-types';
27

28
/**
×
29
 * @private
×
30
 */
31
@Directive()
×
32
export abstract class PickerDirective extends AbstractPickerComponent implements OnInit, AfterViewInit, OnDestroy, OnChanges {
33
    showWeek = false;
34

×
35
    @Input() thyDateRender: FunctionProp<TemplateRef<Date> | string>;
×
36

×
37
    /**
×
38
     * 模式
39
     * @type decade | year | month | date
40
     */
×
41
    @Input() thyMode: ThyPanelMode = 'date';
42

×
43
    panelMode: ThyPanelMode | ThyPanelMode[];
44

45
    /**
×
46
     * @type EventEmitter<ThyPanelMode | ThyPanelMode[]>
47
     */
48
    @Output() readonly thyOnPanelChange = new EventEmitter<ThyPanelMode | ThyPanelMode[]>();
49

50
    /**
51
     * @type EventEmitter<Date[]>
52
     */
53
    @Output() readonly thyOnCalendarChange = new EventEmitter<Date[]>();
54

55
    private _showTime: object | boolean;
56
    @Input() get thyShowTime(): object | boolean {
57
        return this._showTime;
58
    }
59
    set thyShowTime(value: object | boolean) {
60
        this._showTime = typeof value === 'object' ? value : coerceBooleanProperty(value);
61
    }
62

63
    /**
64
     * 是否展示时间(时、分)
65
     * @default false
66
     */
67
    @Input() @InputBoolean() thyMustShowTime = false;
68

69
    /**
70
     * 弹出位置
71
     * @type top | topLeft | topRight | bottom | bottomLeft | bottomRight | left | leftTop | leftBottom | right | rightTop | rightBottom
72
     */
73
    @Input() thyPlacement: ThyPlacement = 'bottom';
×
74

×
75
    private offset = 4;
×
76

×
77
    /**
×
78
     * 弹出 DatePicker 的偏移量
×
79
     * @default 4
80
     */
×
81
    @Input()
82
    @InputNumber()
×
83
    set thyOffset(value: number) {
84
        if (typeof ngDevMode === 'undefined' || ngDevMode) {
×
85
            warnDeprecation(`thyOffset parameter will be deprecated, please use thyPopoverOptions instead.`);
×
86
        }
×
87
        this.offset = value;
88
    }
×
89

90
    private hasBackdrop = true;
91

×
92
    /**
×
93
     * 是否有幕布
94
     * @default false
95
     */
×
96
    @Input()
97
    @InputBoolean()
98
    set thyHasBackdrop(value: boolean) {
99
        if (typeof ngDevMode === 'undefined' || ngDevMode) {
×
100
            warnDeprecation(`thyHasBackdrop parameter will be deprecated, please use thyPopoverOptions instead.`);
101
        }
102
        this.hasBackdrop = value;
×
103
    }
×
104

×
105
    /**
106
     * popover 的其他参数
107
     */
108
    @Input() thyPopoverOptions: ThyPopoverConfig;
109

×
110
    /**
×
111
     * 是否阻止冒泡
×
112
     */
×
113
    @Input() @InputBoolean() thyStopPropagation = true;
×
114

×
115
    private destroy$ = new Subject<void>();
×
116
    private el: HTMLElement = this.elementRef.nativeElement;
×
117
    readonly $click: Observable<boolean> = fromEvent(this.el, 'click').pipe(
×
118
        tap(e => {
×
119
            if (this.thyStopPropagation) {
×
120
                e.stopPropagation();
×
121
            }
×
122
        }),
×
123
        mapTo(true)
×
124
    );
×
125

×
126
    ngOnInit() {
×
127
        this.thyMode = this.thyMode || 'date';
128
        this.flexible = this.thyMode === 'flexible';
129

130
        if (this.isRange) {
131
            this.panelMode = this.flexible ? ['date', 'date'] : [this.thyMode, this.thyMode];
×
132
        } else {
×
133
            this.panelMode = this.thyMode;
134
        }
135
        this.showWeek = this.thyMode === 'week';
×
136
    }
×
137

138
    private openOverlay(): void {
139
        const popoverRef = this.thyPopover.open(
×
140
            DatePopupComponent,
×
141
            Object.assign(
×
142
                {
×
143
                    origin: this.el,
144
                    hasBackdrop: this.hasBackdrop,
145
                    backdropClass: 'thy-overlay-transparent-backdrop',
146
                    offset: this.offset,
147
                    initialState: {
×
148
                        isRange: this.isRange,
149
                        panelMode: this.panelMode,
150
                        showWeek: this.showWeek,
151
                        value: this.thyValue,
×
152
                        showTime: this.thyShowTime,
×
153
                        mustShowTime: this.withTime,
154
                        format: this.thyFormat,
155
                        dateRender: this.thyDateRender,
156
                        disabledDate: this.thyDisabledDate,
×
157
                        placeholder: this.thyPlaceHolder,
158
                        className: this.thyPanelClassName,
1✔
159
                        defaultPickerValue: this.thyDefaultPickerValue,
160
                        minDate: this.thyMinDate,
161
                        maxDate: this.thyMaxDate,
162
                        showShortcut: this.thyShowShortcut,
163
                        shortcutPresets: this.shortcutPresets,
1✔
164
                        shortcutPosition: this.shortcutPosition,
165
                        flexible: this.flexible,
166
                        flexibleDateGranularity: this.flexibleDateGranularity
167
                    },
168
                    placement: this.thyPlacement
169
                },
170
                this.thyPopoverOptions
171
            )
172
        );
173
        if (popoverRef) {
174
            const componentInstance = popoverRef.componentInstance;
175
            componentInstance.valueChange.pipe(takeUntil(this.destroy$)).subscribe((event: CompatibleValue) => this.onValueChange(event));
176
            componentInstance.calendarChange.pipe(takeUntil(this.destroy$)).subscribe((event: CompatibleValue) => {
177
                const rangeValue = coerceArray(event).map(x => x.nativeDate);
1✔
178
                this.thyOnCalendarChange.emit(rangeValue);
179
            });
180
            componentInstance.showTimePickerChange
181
                .pipe(takeUntil(this.destroy$))
1✔
182
                .subscribe((event: boolean) => this.onShowTimePickerChange(event));
183
            // eslint-disable-next-line max-len
184
            componentInstance.ngOnChanges({ value: {} as SimpleChange }); // dynamically created components don't call ngOnChanges, manual call
185
            componentInstance.shortcutValueChange?.pipe(takeUntil(this.destroy$)).subscribe((event: ThyShortcutValueChange) => {
186
                this.thyShortcutValueChange.emit(event);
1✔
187
            });
188
            popoverRef
189
                .afterOpened()
190
                .pipe(takeUntil(this.destroy$))
191
                .subscribe(() => this.thyOpenChange.emit(true));
1✔
192
            popoverRef
193
                .afterClosed()
194
                .pipe(takeUntil(this.destroy$))
195
                .subscribe(() => this.thyOpenChange.emit(false));
1✔
196
        }
197
    }
198

199
    closeOverlay(): void {
200
        this.thyPopover.close();
201
    }
202

203
    initActionSubscribe(): void {
204
        this.$click.pipe(debounceTime(50), takeUntil(this.destroy$)).subscribe(() => {
205
            if (!this.thyDisabled && !this.thyReadonly) {
206
                this.openOverlay();
207
            }
208
        });
209
    }
210

211
    constructor(public elementRef: ElementRef, public cdr: ChangeDetectorRef, private thyPopover: ThyPopover) {
212
        super(cdr);
213
    }
214

215
    ngAfterViewInit(): void {
216
        this.setDefaultTimePickerState();
217
        this.initActionSubscribe();
218
    }
219

220
    ngOnDestroy(): void {
221
        this.destroy$.next();
222
        this.destroy$.complete();
223
    }
224

225
    onValueChange(value: CompatibleValue): void {
226
        this.restoreTimePickerState(value);
227
        super.onValueChange(value);
228
        if (!this.flexible) {
229
            this.closeOverlay();
230
        }
231
    }
232

233
    // Displays the time directly when the time must be displayed by default
234
    setDefaultTimePickerState() {
235
        this.withTime = this.thyMustShowTime;
236
    }
237

238
    // Restore after clearing time to select whether the original picker time is displayed or not
239
    restoreTimePickerState(value: CompatibleValue | null) {
240
        if (!value) {
241
            this.withTime = this.thyMustShowTime || this.originWithTime;
242
        }
243
    }
244
    onShowTimePickerChange(show: boolean): void {
245
        this.withTime = show;
246
    }
247
}
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