From 6b3c6c2dda579a8d6e99b69c8b5fa8e9fe37bd10 Mon Sep 17 00:00:00 2001 From: Luca Giamminonni Date: Fri, 29 Apr 2022 15:34:57 +0200 Subject: [PATCH 1/3] [CST-5307] Fixed lint --- src/app/core/profile/model/researcher-profile.model.ts | 2 +- src/app/core/profile/researcher-profile.service.ts | 5 ++--- src/app/item-page/simple/item-page.component.ts | 4 ++-- .../profile-page-researcher-form.component.ts | 6 +++--- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/app/core/profile/model/researcher-profile.model.ts b/src/app/core/profile/model/researcher-profile.model.ts index e5098496d3..a07467476e 100644 --- a/src/app/core/profile/model/researcher-profile.model.ts +++ b/src/app/core/profile/model/researcher-profile.model.ts @@ -4,7 +4,7 @@ import { HALLink } from '../../shared/hal-link.model'; import { ResourceType } from '../../shared/resource-type'; import { excludeFromEquals } from '../../utilities/equals.decorators'; import { RESEARCHER_PROFILE } from './researcher-profile.resource-type'; -import {CacheableObject} from "../../cache/cacheable-object.model"; +import {CacheableObject} from '../../cache/cacheable-object.model'; /** * Class the represents a Researcher Profile. diff --git a/src/app/core/profile/researcher-profile.service.ts b/src/app/core/profile/researcher-profile.service.ts index 3b4144b77c..0220afb964 100644 --- a/src/app/core/profile/researcher-profile.service.ts +++ b/src/app/core/profile/researcher-profile.service.ts @@ -1,3 +1,4 @@ +/* eslint-disable max-classes-per-file */ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; @@ -30,9 +31,7 @@ import { RESEARCHER_PROFILE } from './model/researcher-profile.resource-type'; import { HttpOptions } from '../dspace-rest/dspace-rest.service'; import { PostRequest } from '../data/request.models'; import { hasValue } from '../../shared/empty.util'; -import {CoreState} from "../core-state.model"; - -/* tslint:disable:max-classes-per-file */ +import {CoreState} from '../core-state.model'; /** * A private DataService implementation to delegate specific methods to. diff --git a/src/app/item-page/simple/item-page.component.ts b/src/app/item-page/simple/item-page.component.ts index 32a0d9f4c1..34a059246d 100644 --- a/src/app/item-page/simple/item-page.component.ts +++ b/src/app/item-page/simple/item-page.component.ts @@ -80,7 +80,7 @@ export class ItemPageComponent implements OnInit { this.route.data.pipe( map((data) => data.dso as RemoteData) ).subscribe((data: RemoteData) => { - this.itemUrl = data?.payload?.self + this.itemUrl = data?.payload?.self; }); } @@ -102,7 +102,7 @@ export class ItemPageComponent implements OnInit { this.authorizationService.isAuthorized(FeatureID.ShowClaimItem, this.itemUrl).pipe( take(1) ).subscribe((isAuthorized: boolean) => { - this.claimable$.next(isAuthorized) + this.claimable$.next(isAuthorized); }); } diff --git a/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.ts b/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.ts index 6a0b687afa..e9d9cb6d05 100644 --- a/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.ts +++ b/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.ts @@ -128,10 +128,10 @@ export class ProfilePageResearcherFormComponent implements OnInit { * @param researcherProfile the profile to update */ toggleProfileVisibility(researcherProfile: ResearcherProfile): void { - /* tslint:disable:no-empty */ this.researcherProfileService.setVisibility(researcherProfile, !researcherProfile.visible) - .subscribe((updatedProfile) => {}); // this.researcherProfile$.next(updatedProfile); - /* tslint:enable:no-empty */ + .subscribe((updatedProfile) => { + this.researcherProfile$.next(updatedProfile); + }); } /** From 788a326592ee5e4462eb1ab27f69b090d1d8dcdd Mon Sep 17 00:00:00 2001 From: Luca Giamminonni Date: Fri, 29 Apr 2022 15:51:35 +0200 Subject: [PATCH 2/3] [CST-5307] Fixed test --- ...ile-page-researcher-form.component.spec.ts | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.spec.ts b/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.spec.ts index bacb3469ad..d12c445ce4 100644 --- a/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.spec.ts +++ b/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.spec.ts @@ -16,11 +16,6 @@ import { ProfilePageResearcherFormComponent } from './profile-page-researcher-fo import { ProfileClaimService } from '../profile-claim/profile-claim.service'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { AuthService } from 'src/app/core/auth/auth.service'; -import { EditItemDataService } from '../../core/submission/edititem-data.service'; -import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; -import { EditItemMode } from '../../core/submission/models/edititem-mode.model'; -import { EditItem } from '../../core/submission/models/edititem.model'; -import { createPaginatedList } from '../../shared/testing/utils.test'; describe('ProfilePageResearcherFormComponent', () => { @@ -39,17 +34,6 @@ describe('ProfilePageResearcherFormComponent', () => { let authService: AuthService; - let editItemDataService: any; - - const editItemMode: EditItemMode = Object.assign(new EditItemMode(), { - name: 'test', - label: 'test' - }); - - const editItem: EditItem = Object.assign(new EditItem(), { - modes: createSuccessfulRemoteDataObject$(createPaginatedList([editItemMode])) - }); - function init() { user = Object.assign(new EPerson(), { @@ -80,10 +64,6 @@ describe('ProfilePageResearcherFormComponent', () => { canClaimProfiles: observableOf(false), }); - editItemDataService = jasmine.createSpyObj('EditItemDataService', { - findById: createSuccessfulRemoteDataObject$(editItem) - }); - } beforeEach(waitForAsync(() => { @@ -96,8 +76,7 @@ describe('ProfilePageResearcherFormComponent', () => { { provide: ResearcherProfileService, useValue: researcherProfileService }, { provide: NotificationsService, useValue: notificationsServiceStub }, { provide: ProfileClaimService, useValue: profileClaimService }, - { provide: AuthService, useValue: authService }, - { provide: EditItemDataService, useValue: editItemDataService } + { provide: AuthService, useValue: authService } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); From 804930fbe2b5cca46343d24bf7486034cf5cc4f8 Mon Sep 17 00:00:00 2001 From: Luca Giamminonni Date: Tue, 3 May 2022 15:35:51 +0200 Subject: [PATCH 3/3] [CST-5307] Improved researcher profile component --- ...on-search-result-list-element.component.ts | 15 ++- .../item-pages/person/person.component.html | 3 +- .../person/person.component.spec.ts | 7 +- .../item-pages/person/person.component.ts | 93 ++++++++++++++++++- .../full/full-item-page.component.html | 3 +- .../full/full-item-page.component.ts | 9 +- .../item-page/simple/item-page.component.ts | 63 +------------ .../item-types/shared/item.component.spec.ts | 13 ++- ...rofile-page-researcher-form.component.html | 4 +- .../profile-page/profile-page.component.html | 17 ++-- .../profile-page.component.spec.ts | 10 ++ .../profile-page/profile-page.component.ts | 19 +++- 12 files changed, 162 insertions(+), 94 deletions(-) diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.ts b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.ts index a6f64bff1b..32785d7b8a 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.ts @@ -2,6 +2,9 @@ import { Component } from '@angular/core'; import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; import { ViewMode } from '../../../../../core/shared/view-mode.model'; import { ItemSearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component'; +import {TruncatableService} from '../../../../../shared/truncatable/truncatable.service'; +import {DSONameService} from '../../../../../core/breadcrumbs/dso-name.service'; +import {isNotEmpty} from '../../../../../shared/empty.util'; @listableObjectComponent('PersonSearchResult', ViewMode.ListElement) @Component({ @@ -14,9 +17,15 @@ import { ItemSearchResultListElementComponent } from '../../../../../shared/obje */ export class PersonSearchResultListElementComponent extends ItemSearchResultListElementComponent { + public constructor(protected truncatableService: TruncatableService, protected dsoNameService: DSONameService) { + super(truncatableService, dsoNameService); + } + get name() { - return this.value ? - this.value : - this.firstMetadataValue('person.familyName') + ', ' + this.firstMetadataValue('person.givenName'); + let personName = this.dsoNameService.getName(this.dso); + if (isNotEmpty(this.firstMetadataValue('person.familyName')) && isNotEmpty(this.firstMetadataValue('person.givenName'))) { + personName = this.firstMetadataValue('person.familyName') + ', ' + this.firstMetadataValue('person.givenName'); + } + return personName; } } diff --git a/src/app/entity-groups/research-entities/item-pages/person/person.component.html b/src/app/entity-groups/research-entities/item-pages/person/person.component.html index 8cf6117121..7505a31327 100644 --- a/src/app/entity-groups/research-entities/item-pages/person/person.component.html +++ b/src/app/entity-groups/research-entities/item-pages/person/person.component.html @@ -1,9 +1,10 @@

- {{'person.page.titleprefix' | translate}} + {{'person.page.titleprefix' | translate}}

+
diff --git a/src/app/entity-groups/research-entities/item-pages/person/person.component.spec.ts b/src/app/entity-groups/research-entities/item-pages/person/person.component.spec.ts index 546621700a..93b3cf208d 100644 --- a/src/app/entity-groups/research-entities/item-pages/person/person.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-pages/person/person.component.spec.ts @@ -54,7 +54,12 @@ const mockItem: Item = Object.assign(new Item(), { } ] }, - relationships: createRelationshipsObservable() + relationships: createRelationshipsObservable(), + _links: { + self : { + href: 'item-href' + } + } }); describe('PersonComponent', getItemPageFieldsTest(mockItem, PersonComponent)); diff --git a/src/app/entity-groups/research-entities/item-pages/person/person.component.ts b/src/app/entity-groups/research-entities/item-pages/person/person.component.ts index 8b104cc9b1..42eb4ec7e6 100644 --- a/src/app/entity-groups/research-entities/item-pages/person/person.component.ts +++ b/src/app/entity-groups/research-entities/item-pages/person/person.component.ts @@ -1,7 +1,20 @@ -import { Component } from '@angular/core'; +import {Component, OnInit} from '@angular/core'; import { ItemComponent } from '../../../../item-page/simple/item-types/shared/item.component'; import { ViewMode } from '../../../../core/shared/view-mode.model'; import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import {MetadataValue} from '../../../../core/shared/metadata.models'; +import {FeatureID} from '../../../../core/data/feature-authorization/feature-id'; +import {mergeMap, take} from 'rxjs/operators'; +import {getFirstSucceededRemoteData} from '../../../../core/shared/operators'; +import {RemoteData} from '../../../../core/data/remote-data'; +import {ResearcherProfile} from '../../../../core/profile/model/researcher-profile.model'; +import {isNotUndefined} from '../../../../shared/empty.util'; +import {BehaviorSubject, Observable} from 'rxjs'; +import {RouteService} from '../../../../core/services/route.service'; +import {AuthorizationDataService} from '../../../../core/data/feature-authorization/authorization-data.service'; +import {ResearcherProfileService} from '../../../../core/profile/researcher-profile.service'; +import {NotificationsService} from '../../../../shared/notifications/notifications.service'; +import {TranslateService} from '@ngx-translate/core'; @listableObjectComponent('Person', ViewMode.StandalonePage) @Component({ @@ -12,5 +25,81 @@ import { listableObjectComponent } from '../../../../shared/object-collection/sh /** * The component for displaying metadata and relations of an item of the type Person */ -export class PersonComponent extends ItemComponent { +export class PersonComponent extends ItemComponent implements OnInit { + + claimable$: BehaviorSubject = new BehaviorSubject(false); + + constructor(protected routeService: RouteService, + protected authorizationService: AuthorizationDataService, + protected notificationsService: NotificationsService, + protected translate: TranslateService, + protected researcherProfileService: ResearcherProfileService) { + super(routeService); + } + + ngOnInit(): void { + super.ngOnInit(); + + this.authorizationService.isAuthorized(FeatureID.ShowClaimItem, this.object._links.self.href).pipe( + take(1) + ).subscribe((isAuthorized: boolean) => { + this.claimable$.next(isAuthorized); + }); + + } + + claim() { + + this.authorizationService.isAuthorized(FeatureID.CanClaimItem, this.object._links.self.href).pipe( + take(1) + ).subscribe((isAuthorized: boolean) => { + if (!isAuthorized) { + this.notificationsService.warning(this.translate.get('researcherprofile.claim.not-authorized')); + } else { + this.createFromExternalSource(); + } + }); + + } + + createFromExternalSource() { + this.researcherProfileService.createFromExternalSource(this.object._links.self.href).pipe( + getFirstSucceededRemoteData(), + mergeMap((rd: RemoteData) => { + return this.researcherProfileService.findRelatedItemId(rd.payload); + })) + .subscribe((id: string) => { + if (isNotUndefined(id)) { + this.notificationsService.success(this.translate.get('researcherprofile.success.claim.title'), + this.translate.get('researcherprofile.success.claim.body')); + this.claimable$.next(false); + } else { + this.notificationsService.error( + this.translate.get('researcherprofile.error.claim.title'), + this.translate.get('researcherprofile.error.claim.body')); + } + }); + } + + isClaimable(): Observable { + return this.claimable$; + } + + getTitleMetadataValues(): MetadataValue[]{ + const metadataValues = []; + const familyName = this.object?.firstMetadata('person.familyName'); + const givenName = this.object?.firstMetadata('person.givenName'); + const title = this.object?.firstMetadata('dc.title'); + if (familyName){ + metadataValues.push(familyName); + } + if (givenName){ + metadataValues.push(givenName); + } + if (metadataValues.length === 0 && title){ + metadataValues.push(title); + } + return metadataValues; + } + } diff --git a/src/app/item-page/full/full-item-page.component.html b/src/app/item-page/full/full-item-page.component.html index bfa25ec009..7cc8ff92c4 100644 --- a/src/app/item-page/full/full-item-page.component.html +++ b/src/app/item-page/full/full-item-page.component.html @@ -10,7 +10,6 @@
-
- \ No newline at end of file + diff --git a/src/app/item-page/full/full-item-page.component.ts b/src/app/item-page/full/full-item-page.component.ts index 99cf083bc5..369769c77d 100644 --- a/src/app/item-page/full/full-item-page.component.ts +++ b/src/app/item-page/full/full-item-page.component.ts @@ -16,10 +16,6 @@ import { hasValue } from '../../shared/empty.util'; import { AuthService } from '../../core/auth/auth.service'; import { Location } from '@angular/common'; import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; -import { TranslateService } from '@ngx-translate/core'; -import { NotificationsService } from '../../shared/notifications/notifications.service'; -import { ResearcherProfileService } from '../../core/profile/researcher-profile.service'; -import { CollectionDataService } from '../../core/data/collection-data.service'; /** @@ -52,11 +48,8 @@ export class FullItemPageComponent extends ItemPageComponent implements OnInit, items: ItemDataService, authService: AuthService, authorizationService: AuthorizationDataService, - translate: TranslateService, - notificationsService: NotificationsService, - researcherProfileService: ResearcherProfileService, private _location: Location) { - super(route, router, items, authService, authorizationService, translate, notificationsService, researcherProfileService); + super(route, router, items, authService, authorizationService); } /*** AoT inheritance fix, will hopefully be resolved in the near future **/ diff --git a/src/app/item-page/simple/item-page.component.ts b/src/app/item-page/simple/item-page.component.ts index 34a059246d..b3660eb9d7 100644 --- a/src/app/item-page/simple/item-page.component.ts +++ b/src/app/item-page/simple/item-page.component.ts @@ -64,24 +64,13 @@ export class ItemPageComponent implements OnInit { itemUrl: string; - public claimable$: BehaviorSubject = new BehaviorSubject(false); - public isProcessing$: BehaviorSubject = new BehaviorSubject(false); - constructor( protected route: ActivatedRoute, private router: Router, private items: ItemDataService, private authService: AuthService, - private authorizationService: AuthorizationDataService, - private translate: TranslateService, - private notificationsService: NotificationsService, - private researcherProfileService: ResearcherProfileService + private authorizationService: AuthorizationDataService ) { - this.route.data.pipe( - map((data) => data.dso as RemoteData) - ).subscribe((data: RemoteData) => { - this.itemUrl = data?.payload?.self; - }); } /** @@ -99,55 +88,5 @@ export class ItemPageComponent implements OnInit { this.isAdmin$ = this.authorizationService.isAuthorized(FeatureID.AdministratorOf); - this.authorizationService.isAuthorized(FeatureID.ShowClaimItem, this.itemUrl).pipe( - take(1) - ).subscribe((isAuthorized: boolean) => { - this.claimable$.next(isAuthorized); - }); - } - - claim() { - this.isProcessing$.next(true); - - this.authorizationService.isAuthorized(FeatureID.CanClaimItem, this.itemUrl).pipe( - take(1) - ).subscribe((isAuthorized: boolean) => { - if (!isAuthorized) { - this.notificationsService.warning(this.translate.get('researcherprofile.claim.not-authorized')); - this.isProcessing$.next(false); - } else { - this.createFromExternalSource(); - } - }); - - } - - createFromExternalSource() { - this.researcherProfileService.createFromExternalSource(this.itemUrl).pipe( - tap((rd: any) => { - if (!rd.hasSucceeded) { - this.isProcessing$.next(false); - } - }), - getFirstSucceededRemoteData(), - mergeMap((rd: RemoteData) => { - return this.researcherProfileService.findRelatedItemId(rd.payload); - })) - .subscribe((id: string) => { - if (isNotUndefined(id)) { - this.notificationsService.success(this.translate.get('researcherprofile.success.claim.title'), - this.translate.get('researcherprofile.success.claim.body')); - this.claimable$.next(false); - this.isProcessing$.next(false); - } else { - this.notificationsService.error( - this.translate.get('researcherprofile.error.claim.title'), - this.translate.get('researcherprofile.error.claim.body')); - } - }); - } - - isClaimable(): Observable { - return this.claimable$; } } diff --git a/src/app/item-page/simple/item-types/shared/item.component.spec.ts b/src/app/item-page/simple/item-types/shared/item.component.spec.ts index fc07f60b28..6f7684b896 100644 --- a/src/app/item-page/simple/item-types/shared/item.component.spec.ts +++ b/src/app/item-page/simple/item-types/shared/item.component.spec.ts @@ -4,7 +4,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { Store } from '@ngrx/store'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; +import {Observable, of as observableOf} from 'rxjs'; import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; import { BitstreamDataService } from '../../../../core/data/bitstream-data.service'; @@ -32,6 +32,8 @@ import { ItemComponent } from './item.component'; import { createPaginatedList } from '../../../../shared/testing/utils.test'; import { RouteService } from '../../../../core/services/route.service'; import { MetadataValue } from '../../../../core/shared/metadata.models'; +import {AuthorizationDataService} from '../../../../core/data/feature-authorization/authorization-data.service'; +import {ResearcherProfileService} from '../../../../core/profile/researcher-profile.service'; export const iiifEnabled = Object.assign(new MetadataValue(),{ 'value': 'true', @@ -69,6 +71,11 @@ export function getItemPageFieldsTest(mockItem: Item, component) { return createSuccessfulRemoteDataObject$(new Bitstream()); } }; + + const authorizationService = jasmine.createSpyObj('authorizationService', { + isAuthorized: observableOf(true) + }); + TestBed.configureTestingModule({ imports: [TranslateModule.forRoot({ loader: { @@ -92,7 +99,9 @@ export function getItemPageFieldsTest(mockItem: Item, component) { { provide: NotificationsService, useValue: {} }, { provide: DefaultChangeAnalyzer, useValue: {} }, { provide: BitstreamDataService, useValue: mockBitstreamDataService }, - { provide: RouteService, useValue: {} } + { provide: RouteService, useValue: {} }, + { provide: AuthorizationDataService, useValue: authorizationService }, + { provide: ResearcherProfileService, useValue: {} } ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.html b/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.html index b2d53ea0e3..bb55418744 100644 --- a/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.html +++ b/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.html @@ -9,7 +9,7 @@

{{'researcher.profile.not.associated' | translate}}

- -