• 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

16.42
/src/avatar/avatar.component.ts
1
import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, HostBinding, Input, OnInit, Output } from '@angular/core';
2
import { SafeHtml } from '@angular/platform-browser';
3
import { coerceBooleanProperty, isString } from 'ngx-tethys/util';
4
import { useHostRenderer } from '@tethys/cdk/dom';
5
import { ThyAvatarService } from './avatar.service';
6
import { AvatarShortNamePipe, AvatarBgColorPipe, AvatarSrcPipe } from './avatar.pipe';
7
import { ThyIconComponent } from 'ngx-tethys/icon';
8
import { NgIf, NgClass, NgStyle } from '@angular/common';
9
import { InputBoolean } from 'ngx-tethys/core';
10

11
const sizeArray = [16, 22, 24, 28, 32, 36, 44, 48, 68, 110, 160];
1✔
12

1✔
13
export const DEFAULT_SIZE = 36;
1✔
14

15
export const thyAvatarSizeMap = {
16
    xxs: 22,
17
    xs: 24,
18
    sm: 32,
19
    md: 36,
20
    lg: 48
21
};
22

23
/** https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-loading */
24
export type ThyAvatarLoading = 'eager' | 'lazy';
25

1✔
26
/** https://wicg.github.io/priority-hints/#idl-index */
27
export type ThyAvatarFetchPriority = 'high' | 'low' | 'auto';
×
28

29
/**
30
 * 头像组件
31
 * @name thy-avatar
×
32
 * @order 10
33
 */
34
@Component({
×
35
    selector: 'thy-avatar',
×
36
    templateUrl: './avatar.component.html',
37
    changeDetection: ChangeDetectionStrategy.OnPush,
38
    standalone: true,
×
39
    imports: [NgIf, NgClass, NgStyle, ThyIconComponent, AvatarShortNamePipe, AvatarBgColorPipe, AvatarSrcPipe]
40
})
41
export class ThyAvatarComponent implements OnInit {
42
    _src: string;
×
43
    _name: string;
44
    _size: number;
45
    _showRemove = false;
×
46

47
    public avatarSrc: string;
48
    public avatarName?: string;
×
49
    public avatarNameSafeHtml?: SafeHtml;
×
50

51
    @HostBinding('class.thy-avatar') _isAvatar = true;
52

×
53
    /**
54
     * * 已废弃,请使用 thyRemove
×
55
     * @deprecated
56
     */
57
    @Output() thyOnRemove = new EventEmitter();
×
58

×
59
    /**
×
60
     *  移除按钮的事件, 当 thyRemovable 为 true 时起作用
×
61
     */
×
62
    @Output() thyRemove = new EventEmitter();
×
63

×
64
    /**
65
     *  头像 img 加载 error 时触发
66
     */
×
67
    @Output() thyError: EventEmitter<Event> = new EventEmitter<Event>();
68

69
    /**
×
70
     * 是否展示人员名称
×
71
     * @default false
72
     */
73
    @Input() @InputBoolean() thyShowName: boolean;
×
74

75
    /**
76
     * 头像路径地址, 默认为全路径,如果不是全路径,可以通过自定义服务 ThyAvatarService,重写 srcTransform 方法实现转换
77
     *
×
78
     */
×
79
    @Input()
×
80
    set thySrc(value: string) {
81
        this._setAvatarSrc(value);
82
    }
×
83

×
84
    /**
85
     * 人员名称(可设置自定义名称,需通过自定义服务 ThyAvatarService,重写 nameTransform 方法去实现转换)
86
     */
87
    @Input()
×
88
    set thyName(value: string) {
×
89
        // this._name = value;
×
90
        this._setAvatarName(value);
×
91
    }
×
92

×
93
    /**
×
94
     * 头像大小
×
95
     * @type 16 | 22 | 24 | 28 | 32 | 36 | 44 | 48 | 68 | 110 | 160 | xxs(22px) | xs(24px) | sm(32px) | md(36px) | lg(48px)
96
     * @default md
97
     */
×
98
    @Input()
×
99
    set thySize(value: number | string) {
100
        if (thyAvatarSizeMap[value]) {
×
101
            this._setAvatarSize(thyAvatarSizeMap[value]);
102
        } else {
103
            this._setAvatarSize((value as number) * 1);
×
104
        }
×
105
    }
106

107
    /**
×
108
     * 已废弃,请使用 thyRemovable
×
109
     * @deprecated
110
     * @default false
1✔
111
     */
112
    @Input()
113
    @InputBoolean()
114
    set thyShowRemove(value: boolean) {
1✔
115
        this._showRemove = coerceBooleanProperty(value);
116
    }
117

118
    /**
119
     * 是否展示移除按钮
120
     * @default false
121
     */
122
    @Input()
123
    @InputBoolean()
124
    set thyRemovable(value: boolean) {
125
        this._showRemove = coerceBooleanProperty(value);
126
    }
127

128
    /**
129
     * 图片自定义类
130
     */
131
    @Input() thyImgClass: string;
1✔
132

133
    /**
134
     * 是否禁用
135
     * @default false
1✔
136
     */
137
    @Input() @InputBoolean() thyDisabled: boolean;
138

139
    /**
140
     * 图片加载策略
1✔
141
     * @type eager(立即加载) | lazy(延迟加载)
142
     */
143
    @Input() thyLoading?: ThyAvatarLoading;
144

145
    /**
1✔
146
     * 图片加载优先级
147
     * @type auto(默认) | high(高) | low(低)
148
     */
149
    @Input() thyFetchPriority?: ThyAvatarFetchPriority;
1✔
150

151
    private _setAvatarSize(size: number) {
152
        if (sizeArray.indexOf(size) > -1) {
153
            this._size = size;
154
        } else {
155
            this._size = this.findClosestSize(sizeArray, size);
156
        }
157
        this.hostRenderer.updateClass([`thy-avatar-${this._size}`]);
158
    }
159

160
    private findClosestSize(sizeArray: number[], currentSize: number): number {
161
        let closestValue = sizeArray[0];
162
        let closestDifference = Math.abs(closestValue - currentSize);
163

164
        for (let i = 1; i < sizeArray.length; i++) {
165
            const currentDifference = Math.abs(sizeArray[i] - currentSize);
166
            if (currentDifference <= closestDifference) {
167
                closestValue = sizeArray[i];
168
                closestDifference = currentDifference;
169
            }
170
        }
171

172
        return closestValue;
173
    }
174

175
    private _setAvatarSrc(src: string) {
176
        if (src && this.thyAvatarService.ignoreAvatarSrcPaths.indexOf(src) < 0) {
177
            this._src = src;
178
        } else {
179
            this._src = null;
180
        }
181
    }
182

183
    private _setAvatarName(value: string) {
184
        const name = this.thyAvatarService.nameTransform(value);
185
        if (isString(name)) {
186
            this.avatarName = name as string;
187
        } else {
188
            this.avatarName = value;
189
            this.avatarNameSafeHtml = name;
190
        }
191
    }
192

193
    private hostRenderer = useHostRenderer();
194

195
    constructor(private thyAvatarService: ThyAvatarService, public elementRef: ElementRef) {}
196

197
    ngOnInit() {
198
        if (!this._size) {
199
            this._setAvatarSize(DEFAULT_SIZE);
200
        }
201
        this.hostRenderer.updateClass([`thy-avatar-${this._size}`]);
202
    }
203

204
    remove($event: Event) {
205
        this.thyOnRemove.emit($event);
206
        this.thyRemove.emit($event);
207
    }
208

209
    avatarImgError($event: Event) {
210
        this._setAvatarSrc(null);
211
        this.thyError.emit($event);
212
    }
213
}
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