Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@
[user]="ascent.createdBy"
styleClass="mr-2"
size="large"
shape="circle"
/>
<a
class="username"
Expand Down Expand Up @@ -302,7 +301,6 @@
[user]="ascent.createdBy"
styleClass="mr-2"
size="large"
shape="circle"
/>
}
<div class="name-with-line">
Expand Down Expand Up @@ -438,7 +436,6 @@
[user]="ascent.createdBy"
styleClass="mr-3"
size="large"
shape="circle"
/>
}
<div class="name-with-line">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
[user]="comment.createdBy"
[imageFallback]="comment.isDeleted ? 'assets/user.png' : null"
size="large"
shape="circle"
/>
<div class="flex flex-column gap-1 flex-grow-1">
<div class="flex justify-content-between">
Expand Down
1 change: 0 additions & 1 deletion client/src/app/modules/core/menu/menu.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
data-cy="auth-menu-button"
styleClass="mr-2"
size="normal"
shape="circle"
/>
}
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@
"
styleClass="mr-2"
size="normal"
shape="circle"
></p-avatar>
<div class="search-result-description">
<div class="search-result-name">{{ searchable.area.name }}</div>
Expand Down Expand Up @@ -92,7 +91,6 @@
"
styleClass="mr-2"
size="normal"
shape="circle"
></p-avatar>
<div class="search-result-description">
<div class="search-result-name">{{ searchable.sector.name }}</div>
Expand Down Expand Up @@ -122,7 +120,6 @@
"
styleClass="mr-2"
size="normal"
shape="circle"
></p-avatar>
<div class="search-result-description">
<div class="search-result-name">{{ searchable.crag.name }}</div>
Expand All @@ -143,7 +140,6 @@
[user]="searchable.user"
styleClass="mr-2"
size="normal"
shape="circle"
/>
<div class="search-result-description">
<div class="search-result-name">{{ searchable.user.fullname }}</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@
[user]="ranking.user"
styleClass="mr-2"
size="large"
shape="circle"
/>
<a
class="username"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
@if (imageUrl) {
@if (previewEnabled) {
<p-image
[src]="previewImageUrl"
[preview]="true"
[previewImageSrc]="previewImageUrl"
[alt]="ariaLabel"
imageClass="lc-user-avatar-preview-thumb"
[styleClass]="previewStyleClass"
>
<ng-template #indicator>
<i class="pi pi-eye"></i>
</ng-template>
</p-image>
} @else if (imageUrl) {
<p-avatar
[image]="imageUrl"
[size]="size"
[shape]="shape"
shape="circle"
[styleClass]="styleClass"
[attr.aria-label]="ariaLabel"
/>
Expand All @@ -11,7 +24,7 @@
[label]="initials"
[style]="gradientStyle"
[size]="size"
[shape]="shape"
shape="circle"
[styleClass]="fallbackClasses"
[attr.aria-label]="ariaLabel"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,43 @@
font-weight: 600;
border: none;
}

:host ::ng-deep p-image.lc-user-avatar-preview {
display: inline-flex;
width: fit-content;
cursor: pointer;
line-height: 0;
position: relative;
border-radius: 50%;
overflow: hidden;

> img {
display: block;
object-fit: cover;
border-radius: 50%;
}

&.lc-user-avatar-preview--normal > img {
width: 2rem;
height: 2rem;
}

&.lc-user-avatar-preview--large > img {
width: 3rem;
height: 3rem;
}

&.lc-user-avatar-preview--xlarge > img {
width: 4rem;
height: 4rem;
}

.p-image-preview-mask {
position: absolute;
inset: 0;
width: 100% !important;
height: 100% !important;
border-radius: 50%;
margin: 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,32 @@ import {
SimpleChanges,
} from '@angular/core';
import { AvatarModule } from 'primeng/avatar';
import { ImageModule } from 'primeng/image';
import { User } from '../../../../models/user';
import {
userAvatarGradientCss,
userInitials,
} from '../../../../utility/misc/user-avatar-gradient';

/**
* Renders a user avatar using one of three template branches:
*
* 1. `p-image` (preview) — when `[preview]` is true and the user has an avatar file.
* PrimeNG Avatar has no fullscreen preview; `p-image` provides the same click-to-zoom
* behaviour as gallery images. Both `[src]` and `[previewImageSrc]` are set to
* `thumbnailXL`: the former for the inline circle, the latter for the fullscreen overlay
* (PrimeNG falls back to `[src]` when `[previewImageSrc]` is omitted).
*
* 2. `p-avatar` with `[image]` — default when the user has an avatar and preview is off.
* Uses the configurable `thumbnail` input (usually `thumbnailS` or `thumbnailM`) so lists
* stay lightweight.
*
* 3. `p-avatar` with `[label]` — when there is no image URL (no avatar and no imageFallback).
* Shows generated initials on a deterministic gradient background.
*/
@Component({
selector: 'lc-user-avatar',
imports: [AvatarModule],
imports: [AvatarModule, ImageModule],
templateUrl: './user-avatar.component.html',
styleUrl: './user-avatar.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
Expand All @@ -23,12 +40,16 @@ export class UserAvatarComponent implements OnChanges {
@Input() user: User | null | undefined;
@Input() thumbnail: 'thumbnailS' | 'thumbnailM' = 'thumbnailS';
@Input() size: 'normal' | 'large' | 'xlarge' = 'normal';
@Input() shape: 'circle' | 'square' = 'circle';
@Input() styleClass = '';
/** When set (e.g. deleted comment), always show this image and ignore avatar / initials. */
@Input() imageFallback: string | null | undefined;
/** Opens a fullscreen image preview when the user has an avatar. */
@Input() preview = false;

imageUrl: string | null = null;
previewImageUrl: string | null = null;
previewEnabled = false;
previewStyleClass = '';
initials = '';
gradientStyle: Record<string, string> = {};
fallbackClasses = '';
Expand All @@ -51,5 +72,13 @@ export class UserAvatarComponent implements OnChanges {
.join(' ');
this.ariaLabel =
u?.fullname?.trim() || `${first} ${last}`.trim() || this.initials;
this.previewImageUrl = u?.avatar?.thumbnailXL ?? null;
this.previewEnabled = this.preview && !!this.previewImageUrl;
const previewClasses = [
'lc-user-avatar-preview',
`lc-user-avatar-preview--${this.size}`,
this.styleClass,
];
this.previewStyleClass = previewClasses.filter(Boolean).join(' ');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<lc-user-avatar
[user]="user"
size="xlarge"
shape="circle"
styleClass="mr-3"
[preview]="true"
/>
}
{{ user?.firstname }} {{ user?.lastname }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
[user]="user"
thumbnail="thumbnailM"
size="xlarge"
shape="circle"
styleClass="mr-2"
/>
</div>
Expand Down
Loading