Commit 338ba338 authored by Florent Poittevin's avatar Florent Poittevin Committed by Alicia.DeDiosFuente
Browse files

feat(contributor): [DLCM-1960] avoid call on contributor avatar when missing...

parent 9d0e9fc4
......@@ -7,7 +7,7 @@
[resId]="getPersonResId()"
[resourceLogoNameSpace]="userAvatarActionNameSpace"
[resourceLogoState]="userState"
[user]="getUser()"
[userInfo]="getUser()"
[isAvatarMissing]="isAvatarPresent() | isFalse"
></dlcm-shared-avatar-upload-wrapper-container>
<div [solidifySpinner]="isLoadingPersonObs | async"
......
......@@ -2,7 +2,7 @@
class="avatar-wrapper"
>
<dlcm-shared-avatar [photoUser]="photoUser"
[user]="user"
[userInfo]="user"
></dlcm-shared-avatar>
<solidify-icon *ngIf="mode === 'horizontal'"
[iconName]="iconNameEnum.down"
......
......@@ -16,6 +16,7 @@ import {SharedDatafileQuickStatusPresentational} from "@shared/components/presen
import {SharedProgressBarPresentational} from "@shared/components/presentationals/shared-progress-bar/shared-progress-bar.presentational";
import {DataTableComponentEnum} from "@shared/enums/data-table-component.enum";
import {DataTableComponentHelper} from "@shared/helpers/data-table-component.helper";
import {UserInfoDataTableColumn} from "@shared/models/user-info-data-table-column.model";
import {
DataTableComponent,
DataTableComponentInput,
......@@ -50,23 +51,11 @@ export const dataTableComponentSolidify: MappingObject<DataTableComponent> = {
[DataTableComponentEnum.logo]: {
componentType: SharedLogoWrapperContainer,
inputs: [
{
key: "id",
valueType: ValueType.isResId,
},
{
key: "isUser",
valueType: ValueType.isAttributeOnCol,
attributeOnCol: "isUser",
},
{
key: "user",
valueType: ValueType.isRowData,
},
{
key: "resourceContainer",
valueType: ValueType.isRowData,
},
{
key: "logoNamespace",
valueType: ValueType.isAttributeOnCol,
......@@ -78,9 +67,18 @@ export const dataTableComponentSolidify: MappingObject<DataTableComponent> = {
attributeOnCol: "resourceState",
},
{
key: "skipIfAvatarMissing",
valueType: ValueType.isAttributeOnCol,
attributeOnCol: "skipIfAvatarMissing",
key: "userInfo",
valueType: ValueType.isRowData,
},
{
key: "idResource",
valueType: ValueType.isCallback,
callbackValue: (rowData, col: UserInfoDataTableColumn<any>) => col.idResource(rowData),
},
{
key: "isLogoPresent",
valueType: ValueType.isCallback,
callbackValue: (rowData, col: UserInfoDataTableColumn<any>) => col.isLogoPresent(rowData),
},
],
} as DataTableComponent,
......
......@@ -24,6 +24,7 @@ import {
AbstractListRoutable,
DataTableColumns,
DataTableFieldTypeEnum,
isNotNullNorUndefined,
OrderEnum,
RouterExtensionService,
} from "solidify-frontend";
......@@ -72,6 +73,8 @@ export class AdminInstitutionListRoutable extends AbstractListRoutable<Instituti
component: DataTableComponentHelper.get(DataTableComponentEnum.logo),
isUser: false,
skipIfAvatarMissing: true,
idResource: (institution: Institution) => institution.resId,
isLogoPresent: (institution: Institution) => isNotNullNorUndefined(institution.logo),
} as DataTableColumns<Institution>,
{
field: "name",
......
......@@ -30,6 +30,7 @@ import {
AbstractListRoutable,
DataTableColumns,
DataTableFieldTypeEnum,
isNotNullNorUndefined,
OrderEnum,
RouterExtensionService,
} from "solidify-frontend";
......@@ -82,6 +83,8 @@ export class AdminOrganizationalUnitListRoutable extends AbstractListRoutable<Or
component: DataTableComponentHelper.get(DataTableComponentEnum.logo),
isUser: false,
skipIfAvatarMissing: true,
idResource: (organizationalUnit: OrganizationalUnit) => organizationalUnit.resId,
isLogoPresent: (organizationalUnit: OrganizationalUnit) => isNotNullNorUndefined(organizationalUnit.logo),
} as DataTableColumns<OrganizationalUnit>,
{
field: "name",
......
......@@ -11,7 +11,7 @@
[resId]="getPersonResId()"
[resourceLogoNameSpace]="userAvatarActionNameSpace"
[resourceLogoState]="userState"
[user]="getUser()"
[userInfo]="getUser()"
[isAvatarMissing]="isAvatarPresent | isFalse"
class="avatar"
></dlcm-shared-avatar-upload-wrapper-container>
......
......@@ -27,11 +27,12 @@ import {DataTableComponentEnum} from "@shared/enums/data-table-component.enum";
import {LabelTranslateEnum} from "@shared/enums/label-translate.enum";
import {StateEnum} from "@shared/enums/state.enum";
import {DataTableComponentHelper} from "@shared/helpers/data-table-component.helper";
import {UserInfoDataTableColumn} from "@shared/models/user-info-data-table-column.model";
import {
AbstractListRoutable,
ButtonColorEnum,
DataTableColumns,
DataTableFieldTypeEnum,
isNotNullNorUndefined,
OrderEnum,
RouterExtensionService,
} from "solidify-frontend";
......@@ -101,8 +102,9 @@ export class AdminUserListRoutable extends AbstractListRoutable<User, AdminUserS
isSortable: false,
component: DataTableComponentHelper.get(DataTableComponentEnum.logo),
isUser: true,
skipIfAvatarMissing: true,
} as DataTableColumns<User>,
idResource: (user: User) => user.person?.resId,
isLogoPresent: (user: User) => isNotNullNorUndefined(user.person?.avatar),
} as UserInfoDataTableColumn<User>,
{
field: "lastName",
header: LabelTranslateEnum.lastName,
......
......@@ -2,10 +2,24 @@
[formGroup]="form"
>
<solidify-detail-presentation [centerTemplate]="centerTemplate"
[leftTemplate]="leftTemplate"
[iconName]="iconNameEnum.contributor"
[rightTemplate]="rightTemplate"
></solidify-detail-presentation>
<ng-template #leftTemplate>
<dlcm-shared-logo-wrapper-container *ngIf="model | isNotNullNorUndefined"
[idResource]="model.resId"
[logoNamespace]="userAvatarActionNameSpace"
[logoState]="userState"
[isUser]="true"
[userInfo]="model"
[isLogoPresent]="model.avatar | isNotNullNorUndefined"
[large]="true"
class="avatar"
></dlcm-shared-logo-wrapper-container>
</ng-template>
<ng-template #centerTemplate>
<mat-form-field [appearance]="appearanceInputMaterial"
......
......@@ -7,11 +7,14 @@ import {
Output,
} from "@angular/core";
import {FormBuilder} from "@angular/forms";
import {AppUserAction} from "@app/stores/user/app-user.action";
import {AppUserState} from "@app/stores/user/app-user.state";
import {Contributor} from "@models";
import {IconNameEnum} from "@shared/enums/icon-name.enum";
import {LabelTranslateEnum} from "@shared/enums/label-translate.enum";
import {BaseFormDefinition} from "@shared/models/base-form-definition.model";
import {SecurityService} from "@shared/services/security.service";
import {ResourceLogoNameSpace} from "@shared/stores/resource-logo/resource-logo-namespace.model";
import {
BehaviorSubject,
Observable,
......@@ -33,6 +36,9 @@ import {
export class PreservationSpaceContributorFormPresentational extends AbstractFormPresentational<Contributor> {
formDefinition: FormComponentFormDefinition = new FormComponentFormDefinition();
userAvatarActionNameSpace: ResourceLogoNameSpace = AppUserAction;
userState: typeof AppUserState = AppUserState;
protected readonly _navigatePersonBS: BehaviorSubject<void | undefined> = new BehaviorSubject<void | undefined>(undefined);
@Output("navigatePerson")
readonly navigatePersonObs: Observable<void | undefined> = ObservableUtil.asObservable(this._navigatePersonBS);
......
......@@ -25,10 +25,12 @@ import {LabelTranslateEnum} from "@shared/enums/label-translate.enum";
import {RoutesEnum} from "@shared/enums/routes.enum";
import {StateEnum} from "@shared/enums/state.enum";
import {DataTableComponentHelper} from "@shared/helpers/data-table-component.helper";
import {UserInfoDataTableColumn} from "@shared/models/user-info-data-table-column.model";
import {SecurityService} from "@shared/services/security.service";
import {
AbstractListRoutable,
DataTableFieldTypeEnum,
isNotNullNorUndefined,
OrderEnum,
RouterExtensionService,
} from "solidify-frontend";
......@@ -84,7 +86,9 @@ export class PreservationSpaceContributorListRoutable extends AbstractListRoutab
isSortable: false,
component: DataTableComponentHelper.get(DataTableComponentEnum.logo),
isUser: true,
},
idResource: (contributor: Contributor) => contributor.resId,
isLogoPresent: (contributor: Contributor) => isNotNullNorUndefined(contributor.avatar),
} as UserInfoDataTableColumn<Contributor>,
{
field: "lastName",
header: LabelTranslateEnum.lastName,
......
......@@ -49,6 +49,7 @@ import {
DataTableColumns,
DataTableFieldTypeEnum,
DialogUtil,
isNotNullNorUndefined,
isNullOrUndefined,
MARK_AS_TRANSLATABLE,
MemoizedUtil,
......@@ -210,6 +211,8 @@ export class PreservationSpaceOrganizationalUnitListRoutable extends AbstractLis
component: DataTableComponentHelper.get(DataTableComponentEnum.logo),
isUser: false,
skipIfAvatarMissing: true,
idResource: (organizationalUnit: OrganizationalUnit) => organizationalUnit.resId,
isLogoPresent: (organizationalUnit: OrganizationalUnit) => isNotNullNorUndefined(organizationalUnit.logo),
} as DataTableColumns<OrganizationalUnit>,
{
field: "name",
......
......@@ -59,6 +59,10 @@ export interface BaseResourceLogo extends BaseResource {
logo?: Logo;
}
export interface BaseResourceAvatar extends BaseResource {
avatar?: Logo;
}
export interface AccessOrganizationalUnit extends AccessOrganizationalUnitPartial, BaseResource {
}
......@@ -125,7 +129,7 @@ export interface ChangeInfo extends ChangeInfoPartial {
export interface Collection extends CollectionPartial {
}
export interface Contributor extends ContributorPartial, BaseResource {
export interface Contributor extends ContributorPartial, BaseResource, UserInfo, BaseResourceAvatar {
}
export interface AdditionalFieldsForm {
......@@ -252,11 +256,10 @@ export interface OrganizationalUnit extends OrganizationalUnitPartial, BaseResou
export interface Page extends PagePartial {
}
export interface Person extends PersonPartial, BaseResource {
export interface Person extends PersonPartial, BaseResourceAvatar {
organizationalUnits?: AccessOrganizationalUnit[];
institutions?: Institution[];
hasAuthenticatedOrcid?: boolean;
avatar?: Logo;
}
export interface Preingest extends PreingestPartial {
......@@ -306,7 +309,14 @@ export interface SystemProperty extends SystemPropertyPartial, BaseResource {
orcidClientId: string;
}
export interface User extends UserPartial, BaseResource {
export interface UserInfo {
resId?: string;
firstName?: string;
lastName?: string;
externalUid?: string;
}
export interface User extends UserPartial, BaseResource, UserInfo {
person?: Person;
accessToken?: string;
refreshToken?: string;
......
......@@ -11,7 +11,7 @@
>
</div>
<ng-template #noPhoto>
<dlcm-shared-avatar [user]="user"
<dlcm-shared-avatar [userInfo]="userInfo"
class="avatar-initial"
></dlcm-shared-avatar>
</ng-template>
......
......@@ -13,7 +13,7 @@ import {DomSanitizer} from "@angular/platform-browser";
import {ActivatedRoute} from "@angular/router";
import {AppUserAction} from "@app/stores/user/app-user.action";
import {AppUserState} from "@app/stores/user/app-user.state";
import {User} from "@models";
import {UserInfo} from "@models";
import {
Actions,
Store,
......@@ -46,7 +46,7 @@ import {
})
export class SharedAvatarUploadWrapperContainer extends SharedAbstractImageUploadWrapperContainer implements OnInit {
@Input()
user: User;
userInfo: UserInfo;
@Input()
resourceLogoState: typeof AppUserState | typeof AdminUserState;
......@@ -110,7 +110,7 @@ export class SharedAvatarUploadWrapperContainer extends SharedAbstractImageUploa
}
override fileChangeEvent(event: any): void {
if (this.resourceLogoNameSpace === adminUserActionNameSpace && this.user.externalUid === MemoizedUtil.selectSnapshot(this._store, AppUserState, state => state.current.externalUid)) {
if (this.resourceLogoNameSpace === adminUserActionNameSpace && this.userInfo.externalUid === MemoizedUtil.selectSnapshot(this._store, AppUserState, state => state.current.externalUid)) {
// need to refresh user profile
this.dispatchFileEventAndRefreshProfile(event);
} else {
......
......@@ -2,11 +2,15 @@
[solidifySpinnerStrokeWidth]="2"
[solidifySpinner]="isLoading"
>
<dlcm-shared-avatar *ngIf="isUser; else isImage"
[user]="user"
[photoUser]="photo"
class="avatar-initial"
></dlcm-shared-avatar>
<ng-template [ngIf]="isUser"
[ngIfElse]="isImage"
>
<dlcm-shared-avatar [userInfo]="userInfo"
class="avatar-initial"
[photoUser]="photo"
[large]="large"
></dlcm-shared-avatar>
</ng-template>
<ng-template #isImage>
<dlcm-shared-image-display *ngIf="sanitizeUrl(photo); else fallback"
......
......@@ -11,10 +11,7 @@ import {
DomSanitizer,
SafeResourceUrl,
} from "@angular/platform-browser";
import {
BaseResourceLogo,
User,
} from "@models";
import {UserInfo} from "@models";
import {
Actions,
Store,
......@@ -31,9 +28,9 @@ import {
} from "rxjs/operators";
import {
BaseResource,
isFalse,
isNotNullNorUndefined,
isNullOrUndefined,
isTrue,
MappingObjectUtil,
MemoizedUtil,
} from "solidify-frontend";
......@@ -46,9 +43,8 @@ import {MappingObject} from "solidify-frontend/lib/models";
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SharedLogoWrapperContainer<TResource extends BaseResource> extends SharedAbstractContainer implements OnChanges, OnInit {
// COMPONENT TO USE ONLY ON DATATABLE
// COMPONENT FOR DATATABLE
_idResource: string;
isLoading: boolean = true;
@Input()
......@@ -58,25 +54,27 @@ export class SharedLogoWrapperContainer<TResource extends BaseResource> extends
logoState: any;
@Input()
isUser: boolean = false;
isUser: boolean;
@Input()
user: User;
userInfo: UserInfo;
@Input()
resourceContainer: BaseResourceLogo;
private _idResource: string;
@Input()
set id(id: string) {
this._idResource = id;
set idResource(idResource: string) {
this._idResource = idResource;
}
get id(): string {
get idResource(): string {
return this._idResource;
}
@Input()
skipIfAvatarMissing: boolean = false;
isLogoPresent: boolean = true;
@Input()
large: boolean;
listPhotosObs: Observable<MappingObject<string>>;
......@@ -91,28 +89,22 @@ export class SharedLogoWrapperContainer<TResource extends BaseResource> extends
ngOnInit(): void {
super.ngOnInit();
this._loadPhoto(this.logoNamespace, this.id, this.user, this.resourceContainer);
this._loadPhoto(this.logoNamespace, this.idResource, this.userInfo);
}
ngOnChanges(changes: SimpleChanges): void {
this._loadPhoto(this.logoNamespace, changes?.id?.currentValue, changes?.user?.currentValue, changes?.resourceContainer?.currentValue);
this._loadPhoto(this.logoNamespace, this.idResource, this.userInfo);
}
private _loadPhoto(logoNamespace: ResourceLogoNameSpace, id: string, user: User, resourceContainer: BaseResourceLogo): void {
if (isNotNullNorUndefined(logoNamespace) && isNotNullNorUndefined(id)) {
if (isTrue(this.skipIfAvatarMissing) && ((this.isUser && isNullOrUndefined(user?.person?.avatar)) || !this.isUser && isNullOrUndefined(resourceContainer?.logo))) {
private _loadPhoto(logoNamespace: ResourceLogoNameSpace, idResource: string, userInfo: UserInfo): void {
if (isNotNullNorUndefined(logoNamespace) && (isNotNullNorUndefined(idResource) || isNotNullNorUndefined(userInfo))) {
if (isFalse(this.isLogoPresent)) {
this.isLoading = false;
return;
}
this.photo = undefined;
this.isLoading = true;
//in case of user, the id_resource has to be changed from user to person.resId
if (this.isUser && !isNullOrUndefined(this.user.person)) {
this._idResource = user.person.resId;
}
this.listPhotosObs = MemoizedUtil.select(this._store, this.logoState, (state: ResourceLogoStateModel<TResource>) => state.listLogo);
this.getLogo();
}
......
......@@ -30,3 +30,13 @@ $avatar-size: 45px;
:host(.is-photo) {
background-color: transparent;
}
:host(.is-large) {
$avatar-size: 300px;
height: $avatar-size;
width: $avatar-size;
.avatar {
font-size: 70px;
}
}
......@@ -9,7 +9,7 @@ import {
SafeResourceUrl,
} from "@angular/platform-browser";
import {SharedAbstractPresentational} from "@app/shared/components/presentationals/shared-abstract/shared-abstract.presentational";
import {User} from "@models";
import {UserInfo} from "@models";
import {isNullOrUndefined} from "solidify-frontend";
@Component({
......@@ -19,16 +19,16 @@ import {isNullOrUndefined} from "solidify-frontend";
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SharedAvatarPresentational extends SharedAbstractPresentational {
private _user: User;
private _userInfo: UserInfo;
@Input()
set user(value: User) {
this._user = value;
set userInfo(value: UserInfo) {
this._userInfo = value;
this.computeInitial();
}
get user(): User {
return this._user;
get userInfo(): UserInfo {
return this._userInfo;
}
@HostBinding("class.is-photo")
......@@ -47,6 +47,10 @@ export class SharedAvatarPresentational extends SharedAbstractPresentational {
return this._photoUserSanitize;
}
@Input()
@HostBinding("class.is-large")
large: boolean = false;
private readonly DEFAULT_INITIAL: string = "";
initial: string = this.DEFAULT_INITIAL;
......@@ -56,10 +60,10 @@ export class SharedAvatarPresentational extends SharedAbstractPresentational {
}
computeInitial(): void {
if (isNullOrUndefined(this._user)) {
if (isNullOrUndefined(this._userInfo)) {
this.initial = this.DEFAULT_INITIAL;
} else {
this.initial = this._user.firstName.substring(0, 1) + this._user.lastName.substring(0, 1);
this.initial = this._userInfo.firstName.substring(0, 1) + this._userInfo.lastName.substring(0, 1);
}
}
......
import {UserInfo} from "@models";
import {DataTableColumns} from "solidify-frontend";
export interface UserInfoDataTableColumn<T extends UserInfo> extends DataTableColumns<T> {
idResource: (model: T) => string;
isLogoPresent: (model: T) => boolean;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment