From fead3bc3fe6450d02aab4b75a429ecb78bace23f Mon Sep 17 00:00:00 2001 From: Marie Verdonck Date: Fri, 5 Mar 2021 13:27:42 +0100 Subject: [PATCH] 77178: Support embed sizes and use them in the ComCol tree --- .../community-list-service.ts | 40 ++++++++++++------- src/app/core/data/comcol-data.service.ts | 5 ++- src/app/core/data/community-data.service.ts | 5 ++- src/app/core/data/data.service.spec.ts | 32 +++++++++++++++ src/app/core/data/data.service.ts | 36 ++++++++++++----- 5 files changed, 90 insertions(+), 28 deletions(-) diff --git a/src/app/community-list-page/community-list-service.ts b/src/app/community-list-page/community-list-service.ts index f7c02c4262..18413b5762 100644 --- a/src/app/community-list-page/community-list-service.ts +++ b/src/app/community-list-page/community-list-service.ts @@ -19,6 +19,7 @@ import { CommunityListState } from './community-list.reducer'; import { getCommunityPageRoute } from '../+community-page/community-page-routing-paths'; import { getCollectionPageRoute } from '../+collection-page/collection-page-routing-paths'; import { getFirstSucceededRemoteData, getFirstCompletedRemoteData } from '../core/shared/operators'; +import { followLink } from '../shared/utils/follow-link-config.model'; /** * Each node in the tree is represented by a flatNode which contains info about the node itself and its position and @@ -115,6 +116,10 @@ export class CommunityListService { private store: Store) { } + private configOnePage: FindListOptions = Object.assign(new FindListOptions(), { + elementsPerPage: 1 + }); + saveCommunityListStateToStore(expandedNodes: FlatNode[], loadingNode: FlatNode): void { this.store.dispatch(new CommunityListSaveAction(expandedNodes, loadingNode)); } @@ -162,16 +167,19 @@ export class CommunityListService { */ private getTopCommunities(options: FindListOptions): Observable> { return this.communityDataService.findTop({ - currentPage: options.currentPage, - elementsPerPage: MAX_COMCOLS_PER_PAGE, - sort: { - field: options.sort.field, - direction: options.sort.direction - } - }).pipe( - getFirstSucceededRemoteData(), - map((results) => results.payload), - ); + currentPage: options.currentPage, + elementsPerPage: MAX_COMCOLS_PER_PAGE, + sort: { + field: options.sort.field, + direction: options.sort.direction + } + }, + followLink('subcommunities', this.configOnePage, true, true), + followLink('collections', this.configOnePage, true, true)) + .pipe( + getFirstSucceededRemoteData(), + map((results) => results.payload), + ); } /** @@ -231,9 +239,11 @@ export class CommunityListService { let subcoms = []; for (let i = 1; i <= currentCommunityPage; i++) { const nextSetOfSubcommunitiesPage = this.communityDataService.findByParent(community.uuid, { - elementsPerPage: MAX_COMCOLS_PER_PAGE, - currentPage: i - }) + elementsPerPage: MAX_COMCOLS_PER_PAGE, + currentPage: i + }, + followLink('subcommunities', this.configOnePage, true, true), + followLink('collections', this.configOnePage, true, true)) .pipe( getFirstCompletedRemoteData(), switchMap((rd: RemoteData>) => { @@ -289,7 +299,7 @@ export class CommunityListService { public getIsExpandable(community: Community): Observable { let hasSubcoms$: Observable; let hasColls$: Observable; - hasSubcoms$ = this.communityDataService.findByParent(community.uuid, { elementsPerPage: 1 }) + hasSubcoms$ = this.communityDataService.findByParent(community.uuid, this.configOnePage) .pipe( map((rd: RemoteData>) => { if (hasValue(rd) && hasValue(rd.payload)) { @@ -300,7 +310,7 @@ export class CommunityListService { }), ); - hasColls$ = this.collectionDataService.findByParent(community.uuid, { elementsPerPage: 1 }) + hasColls$ = this.collectionDataService.findByParent(community.uuid, this.configOnePage) .pipe( map((rd: RemoteData>) => { if (hasValue(rd) && hasValue(rd.payload)) { diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index 2dcffeb961..12aedf8009 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -18,6 +18,7 @@ import { BitstreamDataService } from './bitstream-data.service'; import { NoContent } from '../shared/NoContent.model'; import { createFailedRemoteDataObject$ } from '../../shared/remote-data.utils'; import { URLCombiner } from '../url-combiner/url-combiner'; +import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; export abstract class ComColDataService extends DataService { protected abstract cds: CommunityDataService; @@ -66,11 +67,11 @@ export abstract class ComColDataService extend protected abstract getFindByParentHref(parentUUID: string): Observable; - public findByParent(parentUUID: string, options: FindListOptions = {}): Observable>> { + public findByParent(parentUUID: string, options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { const href$ = this.getFindByParentHref(parentUUID).pipe( map((href: string) => this.buildHrefFromFindOptions(href, options)) ); - return this.findAllByHref(href$); + return this.findAllByHref(href$, options, true, true, ...linksToFollow); } /** diff --git a/src/app/core/data/community-data.service.ts b/src/app/core/data/community-data.service.ts index 6fbc2f9778..8dee72e391 100644 --- a/src/app/core/data/community-data.service.ts +++ b/src/app/core/data/community-data.service.ts @@ -19,6 +19,7 @@ import { RemoteData } from './remote-data'; import { FindListOptions } from './request.models'; import { RequestService } from './request.service'; import { BitstreamDataService } from './bitstream-data.service'; +import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; @Injectable() @dataService(COMMUNITY) @@ -45,9 +46,9 @@ export class CommunityDataService extends ComColDataService { return this.halService.getEndpoint(this.linkPath); } - findTop(options: FindListOptions = {}): Observable>> { + findTop(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> { const hrefObs = this.getFindAllHref(options, this.topLinkPath); - return this.findAllByHref(hrefObs, undefined); + return this.findAllByHref(hrefObs, undefined, true, true, ...linksToFollow); } protected getFindByParentHref(parentUUID: string): Observable { diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts index 82d2271c10..a8bbfa79a0 100644 --- a/src/app/core/data/data.service.spec.ts +++ b/src/app/core/data/data.service.spec.ts @@ -193,6 +193,16 @@ describe('DataService', () => { }); }); + it('should include single linksToFollow as embed and its size', () => { + const expected = `${endpoint}?embed.size=bundles=5&embed=bundles`; + const config: FindListOptions = Object.assign(new FindListOptions(), { + elementsPerPage: 5 + }); + (service as any).getFindAllHref({}, null, followLink('bundles', config, true, true, true)).subscribe((value) => { + expect(value).toBe(expected); + }); + }); + it('should include multiple linksToFollow as embed', () => { const expected = `${endpoint}?embed=bundles&embed=owningCollection&embed=templateItemOf`; @@ -201,6 +211,18 @@ describe('DataService', () => { }); }); + it('should include multiple linksToFollow as embed and its sizes if given', () => { + const expected = `${endpoint}?embed=bundles&embed.size=owningCollection=2&embed=owningCollection&embed=templateItemOf`; + + const config: FindListOptions = Object.assign(new FindListOptions(), { + elementsPerPage: 2 + }); + + (service as any).getFindAllHref({}, null, followLink('bundles'), followLink('owningCollection', config, true, true, true), followLink('templateItemOf')).subscribe((value) => { + expect(value).toBe(expected); + }); + }); + it('should not include linksToFollow with shouldEmbed = false', () => { const expected = `${endpoint}?embed=templateItemOf`; @@ -216,6 +238,16 @@ describe('DataService', () => { expect(value).toBe(expected); }); }); + + it('should include nested linksToFollow 2lvl and nested embed\'s size', () => { + const expected = `${endpoint}?embed.size=owningCollection/itemtemplate=4&embed=owningCollection/itemtemplate`; + const config: FindListOptions = Object.assign(new FindListOptions(), { + elementsPerPage: 4 + }); + (service as any).getFindAllHref({}, null, followLink('owningCollection', undefined, true, true, true, followLink('itemtemplate', config, true, true, true))).subscribe((value) => { + expect(value).toBe(expected); + }); + }); }); describe('getIDHref', () => { diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index e98de0f77d..814c281a37 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -215,10 +215,19 @@ export abstract class DataService implements UpdateDa */ protected addEmbedParams(href: string, args: string[], ...linksToFollow: FollowLinkConfig[]) { linksToFollow.forEach((linkToFollow: FollowLinkConfig) => { - if (linkToFollow !== undefined && linkToFollow.shouldEmbed) { + if (hasValue(linkToFollow) && linkToFollow.shouldEmbed) { const embedString = 'embed=' + String(linkToFollow.name); - const embedWithNestedString = this.addNestedEmbeds(embedString, ...linkToFollow.linksToFollow); - args = this.addHrefArg(href, args, embedWithNestedString); + // Add the embeds size if given in the FollowLinkConfig.FindListOptions + if (hasValue(linkToFollow.findListOptions) && hasValue(linkToFollow.findListOptions.elementsPerPage)) { + args = this.addHrefArg(href, args, + 'embed.size=' + String(linkToFollow.name) + '=' + linkToFollow.findListOptions.elementsPerPage); + } + // Adds the nested embeds and their size if given + if (isNotEmpty(linkToFollow.linksToFollow)) { + args = this.addNestedEmbeds(embedString, href, args, ...linkToFollow.linksToFollow); + } else { + args = this.addHrefArg(href, args, embedString); + } } }); return args; @@ -243,21 +252,30 @@ export abstract class DataService implements UpdateDa } /** - * Add the nested followLinks to the embed param, recursively, separated by a / + * Add the nested followLinks to the embed param, separated by a /, and their sizes, recursively * @param embedString embedString so far (recursive) + * @param href The href the params are to be added to + * @param args params for the query string * @param linksToFollow links we want to embed in query string if shouldEmbed is true */ - protected addNestedEmbeds(embedString: string, ...linksToFollow: FollowLinkConfig[]): string { + protected addNestedEmbeds(embedString: string, href: string, args: string[], ...linksToFollow: FollowLinkConfig[]): string[] { let nestEmbed = embedString; linksToFollow.forEach((linkToFollow: FollowLinkConfig) => { - if (linkToFollow !== undefined && linkToFollow.shouldEmbed) { + if (hasValue(linkToFollow) && linkToFollow.shouldEmbed) { nestEmbed = nestEmbed + '/' + String(linkToFollow.name); - if (linkToFollow.linksToFollow !== undefined) { - nestEmbed = this.addNestedEmbeds(nestEmbed, ...linkToFollow.linksToFollow); + // Add the nested embeds size if given in the FollowLinkConfig.FindListOptions + if (hasValue(linkToFollow.findListOptions) && hasValue(linkToFollow.findListOptions.elementsPerPage)) { + const nestedEmbedSize = 'embed.size=' + nestEmbed.split('=')[1] + '=' + linkToFollow.findListOptions.elementsPerPage; + args = this.addHrefArg(href, args, nestedEmbedSize); + } + if (hasValue(linkToFollow.linksToFollow) && isNotEmpty(linkToFollow.linksToFollow)) { + args = this.addNestedEmbeds(nestEmbed, href, args, ...linkToFollow.linksToFollow); + } else { + args = this.addHrefArg(href, args, nestEmbed); } } }); - return nestEmbed; + return args; } /**