This commit is contained in:
Adina Țeudan 2021-10-20 02:25:54 +03:00
parent be9988ca11
commit c71a3e65b6
8 changed files with 56 additions and 27 deletions

View File

@ -76,7 +76,11 @@
</div>
<div class="cell user-column">
<redaction-initials-avatar [user]="dossierTemplate.createdBy" [withName]="true"></redaction-initials-avatar>
<redaction-initials-avatar
[defaultValue]="'unknown' | translate"
[user]="dossierTemplate.createdBy"
[withName]="true"
></redaction-initials-avatar>
</div>
<div class="cell small-label">

View File

@ -1,5 +1,5 @@
<button [class.overlay]="showDot" mat-button>
<redaction-initials-avatar [user]="userId" [withName]="true" size="small"></redaction-initials-avatar>
<redaction-initials-avatar [user]="userService.currentUser$ | async" [withName]="true" size="small"></redaction-initials-avatar>
<mat-icon svgIcon="iqser:arrow-down"></mat-icon>
</button>
<div *ngIf="showDot" class="dot"></div>

View File

@ -1,4 +1,5 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { UserService } from '@services/user.service';
@Component({
selector: 'redaction-user-button',
@ -9,4 +10,6 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
export class UserButtonComponent {
@Input() userId: string;
@Input() showDot = false;
constructor(readonly userService: UserService) {}
}

View File

@ -4,7 +4,7 @@
[matTooltipPosition]="tooltipPosition"
[matTooltip]="userName"
>
{{ _user | name: { showInitials: true, defaultValue: ('initials-avatar.unassigned' | translate) } }}
{{ _user | name: { showInitials: true } }}
</div>
<div *ngIf="withName" [class.disabled]="disabled" class="clamp-2 username">
{{ userName }}

View File

@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, Input, OnChanges, OnDestroy } from '@angular/core';
import { ChangeDetectionStrategy, Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core';
import { UserService } from '@services/user.service';
import { AutoUnsubscribe } from '@iqser/common-ui';
import { User } from '@models/user';
@ -11,18 +11,16 @@ import { NamePipeOptions } from '@shared/pipes/name.pipe';
styleUrls: ['./initials-avatar.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class InitialsAvatarComponent extends AutoUnsubscribe implements OnChanges, OnDestroy {
export class InitialsAvatarComponent extends AutoUnsubscribe implements OnInit, OnChanges, OnDestroy {
@Input() color = 'lightgray';
@Input() size: 'small' | 'large' = 'small';
@Input() withName = false;
@Input() showYou = false;
@Input() tooltipPosition: 'below' | 'above' = 'above';
@Input() defaultValue = this._translateService.instant('initials-avatar.unassigned');
colorClass: string;
readonly namePipeOptions: NamePipeOptions = {
showYou: this.showYou,
defaultValue: this._translateService.instant('initials-avatar.unassigned'),
};
namePipeOptions: NamePipeOptions;
constructor(private readonly _userService: UserService, private readonly _translateService: TranslateService) {
super();
@ -44,7 +42,7 @@ export class InitialsAvatarComponent extends AutoUnsubscribe implements OnChange
}
get disabled(): boolean {
return this._user && !this._user.isActive;
return this._user && !this._isSystemUser && !this._user.isActive;
}
get isCurrentUser(): boolean {
@ -65,13 +63,23 @@ export class InitialsAvatarComponent extends AutoUnsubscribe implements OnChange
return `${this.color}-dark`;
}
private get _isSystemUser() {
return this._user?.id?.toLowerCase() === 'system';
}
ngOnChanges(): void {
const isSystemUser = this._user?.id?.toLowerCase() === 'system';
if (isSystemUser) {
if (this._isSystemUser) {
this.colorClass = 'primary-white primary';
return;
}
this.colorClass = this._colorClass;
}
ngOnInit(): void {
this.namePipeOptions = {
showYou: this.showYou,
defaultValue: this.defaultValue,
};
}
}

View File

@ -36,12 +36,13 @@ export class NamePipe implements PipeTransform {
transform(value?: User | string, options = this._defaultOptions): string {
let name;
if (!value || !isSystemUser(value)) {
name = this._getName(value) || options?.defaultValue;
} else {
name = 'System';
if (!value && options?.showInitials) {
return '?';
}
name = this._getName(value) || options?.defaultValue;
if (options?.showYou && this._isCurrentUser(value)) {
name = `${name} (${this._translateService.instant('initials-avatar.you')})`;
}

View File

@ -4,7 +4,7 @@ import jwt_decode from 'jwt-decode';
import { CreateUserRequest, IUser, ResetPasswordRequest, UpdateMyProfileRequest, UpdateProfileRequest } from '@redaction/red-ui-http';
import { wipeCaches } from '@redaction/red-cache';
import { BASE_HREF } from '../tokens';
import { Observable } from 'rxjs';
import { BehaviorSubject, Observable } from 'rxjs';
import { User } from '@models/user';
import { EntitiesService, List, mapEach, QueryParam, RequiredParam, Validate } from '@iqser/common-ui';
import { tap } from 'rxjs/operators';
@ -21,18 +21,20 @@ export interface ProfileModel {
providedIn: 'root',
})
export class UserService extends EntitiesService<User, IUser> {
readonly currentUser$: Observable<User>;
private readonly _currentUser$ = new BehaviorSubject<User>(null);
constructor(
protected readonly _injector: Injector,
@Inject(BASE_HREF) private readonly _baseHref: string,
private readonly _keycloakService: KeycloakService,
) {
super(_injector, User, 'user');
this.currentUser$ = this._currentUser$.asObservable();
}
private _currentUser: User;
get currentUser(): User {
return this._currentUser;
return this._currentUser$.value;
}
get managerUsers(): User[] {
@ -49,7 +51,7 @@ export class UserService extends EntitiesService<User, IUser> {
}
loadAll() {
const all$ = this._currentUser.isUserAdmin ? this.getUsers() : this.getUsers(true);
const all$ = this.currentUser.isUserAdmin ? this.getUsers() : this.getUsers(true);
return all$.pipe(
mapEach(user => new User(user, user.roles, user.userId)),
@ -59,16 +61,20 @@ export class UserService extends EntitiesService<User, IUser> {
async loadCurrentUser() {
const token = await this._keycloakService.getToken();
const decoded: { sub: string } = jwt_decode(token);
const userId = decoded.sub;
this._currentUser = new User(await this._keycloakService.loadUserProfile(true), this._keycloakService.getUserRoles(true), userId);
const decoded = jwt_decode(token);
const userId = (<{ sub: string }>decoded).sub;
const roles = this._keycloakService.getUserRoles(true).filter(role => role.startsWith('RED_'));
this.replace(new User(await this._keycloakService.loadUserProfile(true), roles, userId));
this._currentUser$.next(this.find(userId));
}
getNameForId(userId: string): string | undefined {
return this.find(userId)?.name;
}
hasAnyRole(requiredRoles: string[], user = this._currentUser): boolean {
hasAnyRole(requiredRoles: string[], user = this.currentUser): boolean {
if (requiredRoles?.length > 0) {
for (const role of requiredRoles) {
if (user.roles.indexOf(role) >= 0) {
@ -111,4 +117,11 @@ export class UserService extends EntitiesService<User, IUser> {
const queryParams = userIds.map<QueryParam>(userId => ({ key: 'userId', value: userId }));
return super.delete(userIds, this._defaultModelPath, queryParams);
}
find(id: string): User | undefined {
if (id?.toLowerCase() === 'system') {
return new User({ email: 'System' }, [], 'system');
}
return super.find(id);
}
}

View File

@ -19,11 +19,11 @@ export class AppStateGuard implements CanActivate {
async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
if (this._userService.currentUser.isUserAdmin) {
await this._userService.loadAllIfEmpty();
await this._userService.loadAll().toPromise();
}
if (this._userService.currentUser.isUser || this._userService.currentUser.isAdmin) {
await this._userService.loadAllIfEmpty();
await this._userService.loadAll().toPromise();
await this._dossierTemplatesService.loadAllIfEmpty();
await this._appStateService.loadDictionaryDataIfNecessary();
}