• 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

8.05
/src/date-picker/abstract-picker.component.ts
1
import {
2
    AbstractControlValueAccessor,
3
    Constructor,
4
    InputBoolean,
5
    mixinDisabled,
6
    mixinTabIndex,
7
    ThyCanDisable,
8
    ThyHasTabIndex
1✔
9
} from 'ngx-tethys/core';
10
import { coerceBooleanProperty, TinyDate } from 'ngx-tethys/util';
11
import { Subject } from 'rxjs';
12

1✔
13
import {
14
    ChangeDetectorRef,
×
15
    Directive,
×
16
    EventEmitter,
17
    Input,
18
    OnChanges,
19
    OnDestroy,
×
20
    OnInit,
21
    Output,
22
    SimpleChanges,
×
23
    ViewChild
24
} from '@angular/core';
25
import { ControlValueAccessor } from '@angular/forms';
×
26

27
import { CompatibleValue, RangeAdvancedValue } from './inner-types';
28
import { ThyPickerComponent } from './picker.component';
×
29
import { makeValue, transformDateValue } from './picker.util';
30
import {
31
    CompatibleDate,
×
32
    DateEntry,
33
    DisabledDateFn,
34
    ThyDateRangeEntry,
×
35
    ThyPanelMode,
×
36
    ThyShortcutPosition,
×
37
    CompatiblePresets,
×
38
    ThyShortcutValueChange,
×
39
    ThyDateGranularity
×
40
} from './standard-types';
×
41

×
42
const _MixinBase: Constructor<ThyHasTabIndex> & Constructor<ThyCanDisable> & typeof AbstractControlValueAccessor = mixinTabIndex(
×
43
    mixinDisabled(AbstractControlValueAccessor)
×
44
);
×
45

×
46
/**
×
47
 * @private
×
48
 */
×
49
@Directive()
×
50
export abstract class AbstractPickerComponent extends _MixinBase implements OnInit, OnChanges, OnDestroy, ControlValueAccessor {
×
51
    thyValue: CompatibleValue | null;
52

53
    /**
×
54
     * 模式
×
55
     * @type decade | year | month | date | week | flexible
×
56
     */
57
    @Input() thyMode: ThyPanelMode = 'date';
58

×
59
    /**
60
     * 是否显示清除按钮
61
     */
×
62
    @Input() @InputBoolean() thyAllowClear = true;
63

64
    /**
×
65
     * 是否自动获取焦点
×
66
     * @default false
67
     */
68
    @Input() @InputBoolean() thyAutoFocus = false;
69

×
70
    @Input() @InputBoolean() thyOpen: boolean;
×
71

72
    @Input() thyDisabledDate: DisabledDateFn;
73

×
74
    /**
75
     * 最小值
76
     * @type Date | number
77
     */
×
78
    @Input() thyMinDate: Date | number;
79

×
80
    /**
81
     * 最大值
82
     * @type Date | number
83
     */
×
84
    @Input() thyMaxDate: Date | number;
85

×
86
    /**
87
     * 输入框提示文字
88
     * @type string | string[]
89
     */
×
90
    @Input() thyPlaceHolder: string | string[];
91

×
92
    /**
93
     * 是否只读
94
     * @default false
95
     */
×
96
    @Input() @InputBoolean() thyReadonly: boolean;
97

×
98
    /**
99
     * 选择器 className
100
     */
101
    @Input() thyOriginClassName: string;
×
102

103
    /**
×
104
     * 弹出层 className
105
     */
106
    @Input() thyPanelClassName: string;
107

×
108
    /**
109
     * 输入框的大小
×
110
     * @type xs | sm | md | lg | default
111
     */
112
    @Input() thySize: 'lg' | 'md' | 'sm' | 'xs' | 'default' = 'default';
×
113

×
114
    /**
×
115
     * 展示的日期格式
×
116
     * @default yyyy-MM-dd
×
117
     */
×
118
    @Input() thyFormat: string;
×
119

×
120
    /**
×
121
     * @description.en-us only for range picker, Whether to automatically take the beginning and ending unixTime of the day
×
122
     * @description.zh-cn 是否取值开始日期的00:00以及截止日期的24:00
×
123
     * @default false
124
     */
125
    @Input() @InputBoolean() thyAutoStartAndEnd = false;
×
126

127
    /**
128
     * 面板默认日期
129
     * @type CompatibleDate | number | null
130
     */
131
    @Input() thyDefaultPickerValue: CompatibleDate | number | null = null;
×
132

×
133
    /**
134
     * 自定义的后缀图标
×
135
     */
136
    @Input() thySuffixIcon = 'calendar';
137

×
138
    /**
×
139
     * 是否展示快捷选项面板
×
140
     * @default false
141
     */
×
142
    @Input() @InputBoolean() thyShowShortcut: boolean;
×
143

144
    /**
145
     * 快捷选项面板的显示位置
×
146
     * @type left | bottom
147
     */
148
    @Input() set thyShortcutPosition(position: ThyShortcutPosition) {
149
        if (!!position) {
150
            this.shortcutPosition = position;
×
151
        }
×
152
    }
×
153

154
    /**
155
     * 自定义快捷选项
×
156
     * @type ThyShortcutPreset[]
×
157
     */
158
    @Input() set thyShortcutPresets(presets: CompatiblePresets) {
159
        this.shortcutPresets = presets;
160
    }
161

162
    @Output() readonly thyShortcutValueChange = new EventEmitter<ThyShortcutValueChange>();
×
163

×
164
    @Output() readonly thyOpenChange = new EventEmitter<boolean>();
165

166
    @ViewChild(ThyPickerComponent, { static: true }) public picker: ThyPickerComponent;
×
167

×
168
    /**
×
169
     * 是否禁用
×
170
     * @default false
×
171
     */
172
    @Input()
173
    @InputBoolean()
×
174
    get thyDisabled(): boolean {
×
175
        return this.disabled;
×
176
    }
×
177
    set thyDisabled(value: boolean) {
×
178
        this.disabled = coerceBooleanProperty(value);
×
179
    }
180

181
    disabled = false;
×
182

183
    shortcutPosition: ThyShortcutPosition = 'left';
184

×
185
    shortcutPresets: CompatiblePresets;
×
186

187
    isRange: boolean;
188

×
189
    withTime: boolean;
×
190

191
    flexible: boolean;
×
192

193
    flexibleDateGranularity: ThyDateGranularity;
194

×
195
    protected destroyed$: Subject<void> = new Subject();
196
    protected isCustomPlaceHolder = false;
1✔
197
    private onlyEmitDate = false;
198
    protected originWithTime: boolean;
199

1✔
200
    get realOpenState(): boolean {
201
        return this.picker.realOpenState;
202
    }
203

204
    initValue(): void {
205
        this.thyValue = this.isRange ? [] : null;
206
    }
207

208
    constructor(public cdr: ChangeDetectorRef) {
209
        super();
210
    }
211

212
    ngOnInit(): void {
213
        this.setDefaultPlaceHolder();
214
        this.initValue();
215
        this.isFlexible();
216
    }
217

218
    isFlexible() {
219
        this.flexible = this.thyMode === 'flexible';
220
    }
221

222
    onShortcutValueChange(event: ThyShortcutValueChange) {
223
        this.thyShortcutValueChange.emit(event);
224
    }
225

1✔
226
    ngOnChanges(changes: SimpleChanges): void {
227
        if (changes.thyPlaceHolder && changes.thyPlaceHolder.firstChange && typeof this.thyPlaceHolder !== 'undefined') {
228
            this.isCustomPlaceHolder = true;
229
        }
1✔
230
    }
231

232
    ngOnDestroy(): void {
233
        this.destroyed$.next();
1✔
234
        this.destroyed$.complete();
235
    }
236

237
    closeOverlay(): void {
1✔
238
        this.picker.hideOverlay();
239
    }
240

241
    getAutoStartAndEndValue(begin: TinyDate, end: TinyDate) {
1✔
242
        let value: { begin: number; end: number };
243
        switch (this.thyMode) {
244
            case 'date':
245
                value = {
1✔
246
                    begin: begin.startOfDay().getUnixTime(),
247
                    end: end.endOfDay().getUnixTime()
248
                };
249
                break;
1✔
250
            case 'week':
251
                value = {
252
                    begin: begin.startOfWeek().getUnixTime(),
253
                    end: end.endOfWeek().getUnixTime()
254
                };
1✔
255
                break;
256
            case 'month':
257
                value = {
258
                    begin: begin.startOfMonth().getUnixTime(),
259
                    end: end.endOfMonth().getUnixTime()
260
                };
261
                break;
262
            case 'year':
263
                value = {
264
                    begin: begin.startOfYear().getUnixTime(),
265
                    end: end.endOfYear().getUnixTime()
266
                };
267
                break;
268
            default:
269
                value = {
270
                    begin: begin.startOfDay().getUnixTime(),
271
                    end: end.endOfDay().getUnixTime()
272
                };
273
                break;
274
        }
275
        return value;
276
    }
277

278
    onValueChange(originalValue: CompatibleValue | RangeAdvancedValue): void {
279
        this.setFormatRule();
280
        const { value, withTime, flexibleDateGranularity } = transformDateValue(originalValue);
281
        this.flexibleDateGranularity = flexibleDateGranularity;
282
        this.setValue(value);
283
        if (this.isRange) {
284
            const vAsRange: any = this.thyValue;
285
            let value = { begin: null, end: null } as ThyDateRangeEntry;
286
            if (vAsRange.length) {
287
                const [begin, end] = vAsRange as TinyDate[];
288
                if (this.thyAutoStartAndEnd) {
289
                    value = this.getAutoStartAndEndValue(begin, end);
290
                } else {
291
                    value = {
292
                        begin: begin.getUnixTime(),
293
                        end: end.getUnixTime()
294
                    };
295
                }
296
            }
297
            if (this.flexible) {
298
                value.granularity = flexibleDateGranularity;
299
            }
300
            this.onChangeFn(value);
301
        } else {
302
            const value = { date: null, with_time: this.withTime ? 1 : 0 } as DateEntry;
303
            if (this.thyValue) {
304
                value.date = (this.thyValue as TinyDate).getUnixTime();
305
            }
306
            if (this.onlyEmitDate) {
307
                this.onChangeFn(value.date);
308
            } else {
309
                this.onChangeFn(value);
310
            }
311
        }
312
    }
313

314
    setFormatRule() {
315
        if (!this.thyFormat) {
316
            if (this.withTime) {
317
                this.thyFormat = 'yyyy-MM-dd HH:mm';
318
            } else {
319
                if (!this.onlyEmitDate) {
320
                    this.thyFormat = 'yyyy-MM-dd';
321
                }
322
            }
323
        }
324
    }
325

326
    onOpenChange(open: boolean): void {
327
        this.thyOpen = open;
328
        this.thyOpenChange.emit(open);
329
    }
330

331
    onChangeFn: (val: CompatibleDate | DateEntry | ThyDateRangeEntry | number | null) => void = () => void 0;
332

333
    writeValue(originalValue: CompatibleDate | ThyDateRangeEntry): void {
334
        const { value, withTime, flexibleDateGranularity } = transformDateValue(originalValue);
335
        this.flexibleDateGranularity = flexibleDateGranularity;
336
        if (this.flexible && value && (value as Date[]).length) {
337
            if (!this.flexibleDateGranularity) {
338
                this.flexibleDateGranularity = 'day';
339
            }
340
        }
341

342
        this.setValue(value);
343
        this.setTimePickerState(withTime);
344
        this.onlyEmitDate = typeof withTime === 'undefined';
345
        this.originWithTime = withTime;
346
        this.setFormatRule();
347
        this.cdr.markForCheck();
348
    }
349

350
    setTimePickerState(withTime: boolean): void {
351
        this.withTime = withTime;
352
    }
353

354
    setDisabledState(disabled: boolean): void {
355
        this.thyDisabled = disabled;
356
        this.cdr.markForCheck();
357
    }
358

359
    private setDefaultPlaceHolder(): void {
360
        if (!this.isCustomPlaceHolder) {
361
            this.thyPlaceHolder = this.isRange ? ['开始日期', '结束日期'] : '请选择日期';
362
        }
363
        this.cdr.markForCheck();
364
    }
365

366
    public setValue(value: CompatibleDate): void {
367
        this.thyValue = makeValue(value, this.isRange);
368
    }
369
}
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