• 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

3.51
/src/date-picker/picker.component.ts
1
import { getFlexiblePositions, ThyPlacement } from 'ngx-tethys/core';
2
import { TinyDate } from 'ngx-tethys/util';
3

4
import { CdkConnectedOverlay, CdkOverlayOrigin, ConnectedOverlayPositionChange } from '@angular/cdk/overlay';
5
import {
6
    AfterViewInit,
7
    ChangeDetectionStrategy,
8
    ChangeDetectorRef,
9
    Component,
10
    ElementRef,
11
    EventEmitter,
12
    Input,
13
    Output,
14
    ViewChild
1✔
15
} from '@angular/core';
16

17
import { NgClass, NgIf, NgTemplateOutlet } from '@angular/common';
×
18
import { ThyIconComponent } from 'ngx-tethys/icon';
19
import { ThyInputDirective } from 'ngx-tethys/input';
20
import { DateHelperService } from './date-helper.service';
×
21
import { CompatibleValue, RangePartType } from './inner-types';
×
22
import { getFlexibleAdvancedReadableValue } from './picker.util';
×
23
import { ThyDateGranularity } from './standard-types';
×
24

×
25
/**
×
26
 * @private
×
27
 */
×
28
@Component({
×
29
    selector: 'thy-picker',
×
30
    exportAs: 'thyPicker',
×
31
    templateUrl: './picker.component.html',
×
32
    changeDetection: ChangeDetectionStrategy.OnPush,
×
33
    standalone: true,
×
34
    imports: [CdkOverlayOrigin, ThyInputDirective, NgTemplateOutlet, NgIf, ThyIconComponent, NgClass, CdkConnectedOverlay]
35
})
36
export class ThyPickerComponent implements AfterViewInit {
×
37
    @Input() isRange = false;
×
38
    @Input() open: boolean | undefined = undefined;
×
39
    @Input() disabled: boolean;
40
    @Input() placeholder: string | string[];
41
    @Input() readonly: boolean;
42
    @Input() allowClear: boolean;
×
43
    @Input() autoFocus: boolean;
44
    @Input() className: string;
45
    @Input() format: string;
×
46
    @Input() size: 'sm' | 'xs' | 'lg' | 'md' | 'default';
47
    @Input() value: TinyDate | TinyDate[] | null;
48
    @Input() suffixIcon: string;
×
49
    @Input() placement: ThyPlacement = 'bottomLeft';
×
50
    @Input() flexible: boolean = false;
×
51
    @Input() flexibleDateGranularity: ThyDateGranularity;
×
52
    @Output() blur = new EventEmitter<Event>();
53
    @Output() readonly valueChange = new EventEmitter<TinyDate | TinyDate[] | null>();
×
54
    @Output() readonly openChange = new EventEmitter<boolean>(); // Emitted when overlay's open state change
×
55

×
56
    @ViewChild('origin', { static: true }) origin: CdkOverlayOrigin;
×
57
    @ViewChild(CdkConnectedOverlay, { static: true }) cdkConnectedOverlay: CdkConnectedOverlay;
58
    @ViewChild('pickerInput', { static: true }) pickerInput: ElementRef;
59

60
    prefixCls = 'thy-calendar';
61
    animationOpenState = false;
62
    overlayOpen = false; // Available when "open"=undefined
×
63
    overlayPositions = getFlexiblePositions(this.placement, 4);
×
64

×
65
    get realOpenState(): boolean {
×
66
        // The value that really decide the open state of overlay
67
        return this.isOpenHandledByUser() ? !!this.open : this.overlayOpen;
×
68
    }
×
69

70
    constructor(private changeDetector: ChangeDetectorRef, private dateHelper: DateHelperService, private element: ElementRef) {}
71

72
    ngAfterViewInit(): void {
×
73
        this.overlayPositions = getFlexiblePositions(this.placement, 4);
×
74
        if (this.autoFocus) {
75
            this.focus();
76
        }
77
    }
×
78

79
    focus(): void {
80
        this.pickerInput.nativeElement.focus();
×
81
    }
82

83
    onBlur(event: FocusEvent) {
×
84
        this.blur.emit(event);
85
    }
86

×
87
    showOverlay(): void {
×
88
        if (!this.realOpenState) {
×
89
            this.overlayOpen = true;
×
90
            if (this.realOpenState) {
91
                this.animationOpenState = true;
92
            }
×
93
            this.openChange.emit(this.overlayOpen);
94
            setTimeout(() => {
95
                if (this.cdkConnectedOverlay && this.cdkConnectedOverlay.overlayRef) {
×
96
                    this.cdkConnectedOverlay.overlayRef.updatePosition();
×
97
                }
98
            });
×
99
        }
×
100
    }
101

102
    hideOverlay(): void {
×
103
        if (this.realOpenState) {
104
            this.overlayOpen = false;
105
            if (!this.realOpenState) {
106
                this.animationOpenState = false;
107
            }
×
108
            this.openChange.emit(this.overlayOpen);
109
            this.focus();
110
        }
111
    }
×
112

×
113
    onClickInputBox(): void {
×
114
        if (!this.disabled && !this.readonly && !this.isOpenHandledByUser()) {
115
            this.showOverlay();
116
        }
×
117
    }
×
118

×
119
    onClickBackdrop(): void {
120
        this.hideOverlay();
121
    }
122

×
123
    onOverlayDetach(): void {
×
124
        this.hideOverlay();
125
    }
126

127
    onPositionChange(position: ConnectedOverlayPositionChange): void {
×
128
        this.changeDetector.detectChanges();
129
    }
130

131
    onClickClear(event: MouseEvent): void {
1✔
132
        event.preventDefault();
133
        event.stopPropagation();
134

135
        this.value = this.isRange ? [] : null;
136
        this.valueChange.emit(this.value);
1✔
137
    }
138

139
    getPartTypeIndex(partType: RangePartType): number {
140
        return { left: 0, right: 1 }[partType];
141
    }
142

143
    isEmptyValue(value: CompatibleValue | null): boolean {
144
        if (value === null) {
145
            return true;
146
        } else if (this.isRange) {
147
            return !value || !Array.isArray(value) || value.every(val => !val);
148
        } else {
149
            return !value;
150
        }
151
    }
152

153
    // Whether open state is permanently controlled by user himself
154
    isOpenHandledByUser(): boolean {
155
        return this.open !== undefined;
156
    }
157

158
    getReadableValue(): string | null {
159
        let value: TinyDate;
160
        if (this.isRange) {
1✔
161
            if (this.flexible && this.flexibleDateGranularity !== 'day') {
162
                return getFlexibleAdvancedReadableValue(this.value as TinyDate[], this.flexibleDateGranularity);
163
            } else {
164
                const start = this.value[0] ? this.dateHelper.format(this.value[0].nativeDate, this.format) : '';
165
                const end = this.value[1] ? this.dateHelper.format(this.value[1].nativeDate, this.format) : '';
166
                return start && end ? `${start} ~ ${end}` : null;
167
            }
168
        } else {
169
            value = this.value as TinyDate;
170
            return value ? this.dateHelper.format(value.nativeDate, this.format) : null;
171
        }
172
    }
173

174
    getPlaceholder(): string {
175
        return this.isRange && this.placeholder && Array.isArray(this.placeholder)
176
            ? (this.placeholder as string[]).join(' ~ ')
177
            : (this.placeholder as string);
178
    }
179
}
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