diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 310ad704ec..1c14366057 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -8,11 +8,11 @@ import { find, map, mergeMap, + skipWhile, + switchMap, take, takeWhile, - switchMap, tap, - skipWhile, } from 'rxjs/operators'; import { hasValue, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util'; import { NotificationOptions } from '../../shared/notifications/models/notification-options.model'; @@ -25,18 +25,12 @@ import { ObjectCacheService } from '../cache/object-cache.service'; import { DSpaceSerializer } from '../dspace-rest/dspace.serializer'; import { DSpaceObject } from '../shared/dspace-object.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { getRemoteDataPayload, getFirstSucceededRemoteData, } from '../shared/operators'; +import { getFirstSucceededRemoteData, getRemoteDataPayload, } from '../shared/operators'; import { URLCombiner } from '../url-combiner/url-combiner'; import { ChangeAnalyzer } from './change-analyzer'; import { PaginatedList } from './paginated-list.model'; import { RemoteData } from './remote-data'; -import { - CreateRequest, - GetRequest, - PatchRequest, - PutRequest, - DeleteRequest -} from './request.models'; +import { CreateRequest, DeleteRequest, GetRequest, PatchRequest, PutRequest } from './request.models'; import { RequestService } from './request.service'; import { RestRequestMethod } from './rest-request-method'; import { UpdateDataService } from './update-data.service'; @@ -168,7 +162,7 @@ export abstract class DataService implements UpdateDa * @return {Observable} * Return an observable that emits created HREF */ - protected buildHrefWithParams(href: string, params: RequestParam[], ...linksToFollow: FollowLinkConfig[]): string { + buildHrefWithParams(href: string, params: RequestParam[], ...linksToFollow: FollowLinkConfig[]): string { let args = []; if (hasValue(params)) { diff --git a/src/app/core/profile/model/researcher-profile.model.ts b/src/app/core/profile/model/researcher-profile.model.ts index a07467476e..6c8b19db40 100644 --- a/src/app/core/profile/model/researcher-profile.model.ts +++ b/src/app/core/profile/model/researcher-profile.model.ts @@ -1,10 +1,15 @@ +import { Observable } from 'rxjs'; import { autoserialize, deserialize, deserializeAs } from 'cerialize'; -import { typedObject } from '../../cache/builders/build-decorators'; + +import { link, typedObject } from '../../cache/builders/build-decorators'; 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'; +import { RemoteData } from '../../data/remote-data'; +import { ITEM } from '../../shared/item.resource-type'; +import { Item } from '../../shared/item.model'; /** * Class the represents a Researcher Profile. @@ -46,4 +51,11 @@ export class ResearcherProfile extends CacheableObject { eperson: HALLink }; + /** + * The related person Item + * Will be undefined unless the item {@link HALLink} has been resolved. + */ + @link(ITEM) + item?: Observable>; + } diff --git a/src/app/core/profile/researcher-profile.service.spec.ts b/src/app/core/profile/researcher-profile.service.spec.ts index 3a8d7b6017..eb5ff776fe 100644 --- a/src/app/core/profile/researcher-profile.service.spec.ts +++ b/src/app/core/profile/researcher-profile.service.spec.ts @@ -25,6 +25,7 @@ import { Item } from '../shared/item.model'; import { ReplaceOperation } from 'fast-json-patch'; import { HttpOptions } from '../dspace-rest/dspace-rest.service'; import { PostRequest } from '../data/request.models'; +import { followLink } from '../../shared/utils/follow-link-config.model'; describe('ResearcherProfileService', () => { let scheduler: TestScheduler; @@ -86,6 +87,7 @@ describe('ResearcherProfileService', () => { } }); const endpointURL = `https://rest.api/rest/api/profiles`; + const endpointURLWithEmbed = 'https://rest.api/rest/api/profiles?embed=item'; const sourceUri = `https://rest.api/rest/api/external-source/profile`; const requestURL = `https://rest.api/rest/api/profiles/${researcherProfileId}`; const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a'; @@ -280,13 +282,13 @@ describe('ResearcherProfileService', () => { let headers = new HttpHeaders(); headers = headers.append('Content-Type', 'text/uri-list'); options.headers = headers; - const request = new PostRequest(requestUUID, endpointURL, sourceUri, options); + const request = new PostRequest(requestUUID, endpointURLWithEmbed, sourceUri, options); scheduler.schedule(() => service.createFromExternalSource(sourceUri)); scheduler.flush(); expect((service as any).requestService.send).toHaveBeenCalledWith(request); - expect((service as any).rdbService.buildFromRequestUUID).toHaveBeenCalledWith(requestUUID); + expect((service as any).rdbService.buildFromRequestUUID).toHaveBeenCalledWith(requestUUID, followLink('item')); }); }); diff --git a/src/app/core/profile/researcher-profile.service.ts b/src/app/core/profile/researcher-profile.service.ts index 23656f3f71..705b3ebc65 100644 --- a/src/app/core/profile/researcher-profile.service.ts +++ b/src/app/core/profile/researcher-profile.service.ts @@ -26,7 +26,7 @@ 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'; -import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; +import { followLink, FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { Item } from '../shared/item.model'; /** @@ -123,7 +123,8 @@ export class ResearcherProfileService { * @param researcherProfile the profile to find for */ public findRelatedItemId(researcherProfile: ResearcherProfile): Observable { - return this.itemService.findByHref(researcherProfile._links.item.href, false).pipe( + const relatedItem$ = researcherProfile.item ? researcherProfile.item : this.itemService.findByHref(researcherProfile._links.item.href, false); + return relatedItem$.pipe( getFirstCompletedRemoteData(), map((itemRD: RemoteData) => (itemRD.hasSucceeded && itemRD.payload) ? itemRD.payload.id : null) ); @@ -159,12 +160,13 @@ export class ResearcherProfileService { const href$ = this.halService.getEndpoint(this.dataService.getLinkPath()); href$.pipe( - find((href: string) => hasValue(href)) + find((href: string) => hasValue(href)), + map((href: string) => this.dataService.buildHrefWithParams(href, [], followLink('item'))) ).subscribe((endpoint: string) => { const request = new PostRequest(requestId, endpoint, sourceUri, options); this.requestService.send(request); }); - return this.rdbService.buildFromRequestUUID(requestId); + return this.rdbService.buildFromRequestUUID(requestId, followLink('item')); } } 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 0b096b99b7..00a3f4bc94 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 @@ -17,6 +17,7 @@ import { ProfilePageResearcherFormComponent } from './profile-page-researcher-fo import { ProfileClaimService } from '../profile-claim/profile-claim.service'; import { AuthService } from '../../core/auth/auth.service'; import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { followLink } from '../../shared/utils/follow-link-config.model'; describe('ProfilePageResearcherFormComponent', () => { @@ -92,7 +93,7 @@ describe('ProfilePageResearcherFormComponent', () => { }); it('should search the researcher profile for the current user', () => { - expect(researcherProfileService.findById).toHaveBeenCalledWith(user.id, false); + expect(researcherProfileService.findById).toHaveBeenCalledWith(user.id, false, true, followLink('item')); }); describe('createProfile', () => { 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 bffec746d3..f0235c6423 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 @@ -16,6 +16,7 @@ import { ResearcherProfileService } from '../../core/profile/researcher-profile. import { ProfileClaimService } from '../profile-claim/profile-claim.service'; import { RemoteData } from '../../core/data/remote-data'; import { isNotEmpty } from '../../shared/empty.util'; +import { followLink } from '../../shared/utils/follow-link-config.model'; @Component({ selector: 'ds-profile-page-researcher-form', @@ -180,7 +181,7 @@ export class ProfilePageResearcherFormComponent implements OnInit { * Initializes the researcherProfile and researcherProfileItemId attributes using the profile of the current user. */ private initResearchProfile(): void { - this.researcherProfileService.findById(this.user.id, false).pipe( + this.researcherProfileService.findById(this.user.id, false, true, followLink('item')).pipe( getFirstSucceededRemoteDataPayload(), tap((researcherProfile) => this.researcherProfile$.next(researcherProfile)), mergeMap((researcherProfile) => this.researcherProfileService.findRelatedItemId(researcherProfile)),