diff --git a/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts index cb16cedb422..ef021123d42 100644 --- a/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts @@ -7,7 +7,7 @@ import { import { Observable } from 'rxjs'; import { BreadcrumbConfig } from '../../breadcrumbs/breadcrumb/breadcrumb-config.model'; -import { ITEM_PAGE_LINKS_TO_FOLLOW } from '../../item-page/item.resolver'; +import { getItemPageLinksToFollow } from '../../item-page/item.resolver'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { ItemDataService } from '../data/item-data.service'; import { DSpaceObject } from '../shared/dspace-object.model'; @@ -24,7 +24,7 @@ export const itemBreadcrumbResolver: ResolveFn<BreadcrumbConfig<Item>> = ( breadcrumbService: DSOBreadcrumbsService = inject(DSOBreadcrumbsService), dataService: ItemDataService = inject(ItemDataService), ): Observable<BreadcrumbConfig<Item>> => { - const linksToFollow: FollowLinkConfig<DSpaceObject>[] = ITEM_PAGE_LINKS_TO_FOLLOW as FollowLinkConfig<DSpaceObject>[]; + const linksToFollow: FollowLinkConfig<DSpaceObject>[] = getItemPageLinksToFollow() as FollowLinkConfig<DSpaceObject>[]; return DSOBreadcrumbResolver( route, state, diff --git a/src/app/core/browse/browse.service.spec.ts b/src/app/core/browse/browse.service.spec.ts index f9999439e1e..f3328c2bedd 100644 --- a/src/app/core/browse/browse.service.spec.ts +++ b/src/app/core/browse/browse.service.spec.ts @@ -7,7 +7,6 @@ import { of as observableOf } from 'rxjs'; import { TestScheduler } from 'rxjs/testing'; import { getMockHrefOnlyDataService } from '../../shared/mocks/href-only-data.service.mock'; -import { getMockRemoteDataBuildService } from '../../shared/mocks/remote-data-build.service.mock'; import { getMockRequestService } from '../../shared/mocks/request.service.mock'; import { createSuccessfulRemoteDataObject, @@ -18,7 +17,6 @@ import { createPaginatedList, getFirstUsedArgumentOfSpyMethod, } from '../../shared/testing/utils.test'; -import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { RequestService } from '../data/request.service'; import { RequestEntry } from '../data/request-entry.model'; import { FlatBrowseDefinition } from '../shared/flat-browse-definition.model'; @@ -31,7 +29,6 @@ describe('BrowseService', () => { let scheduler: TestScheduler; let service: BrowseService; let requestService: RequestService; - let rdbService: RemoteDataBuildService; const browsesEndpointURL = 'https://rest.api/browses'; const halService: any = new HALEndpointServiceStub(browsesEndpointURL); @@ -129,7 +126,6 @@ describe('BrowseService', () => { halService, browseDefinitionDataService, hrefOnlyDataService, - rdbService, ); } @@ -141,11 +137,9 @@ describe('BrowseService', () => { beforeEach(() => { requestService = getMockRequestService(getRequestEntry$(true)); - rdbService = getMockRemoteDataBuildService(); service = initTestService(); spyOn(halService, 'getEndpoint').and .returnValue(hot('--a-', { a: browsesEndpointURL })); - spyOn(rdbService, 'buildList').and.callThrough(); }); it('should call BrowseDefinitionDataService to create the RemoteData Observable', () => { @@ -162,9 +156,7 @@ describe('BrowseService', () => { beforeEach(() => { requestService = getMockRequestService(getRequestEntry$(true)); - rdbService = getMockRemoteDataBuildService(); service = initTestService(); - spyOn(rdbService, 'buildList').and.callThrough(); }); describe('when getBrowseEntriesFor is called with a valid browse definition id', () => { @@ -215,7 +207,6 @@ describe('BrowseService', () => { describe('if getBrowseDefinitions fires', () => { beforeEach(() => { requestService = getMockRequestService(getRequestEntry$(true)); - rdbService = getMockRemoteDataBuildService(); service = initTestService(); spyOn(service, 'getBrowseDefinitions').and .returnValue(hot('--a-', { @@ -270,7 +261,6 @@ describe('BrowseService', () => { describe('if getBrowseDefinitions doesn\'t fire', () => { it('should return undefined', () => { requestService = getMockRequestService(getRequestEntry$(true)); - rdbService = getMockRemoteDataBuildService(); service = initTestService(); spyOn(service, 'getBrowseDefinitions').and .returnValue(hot('----')); @@ -288,9 +278,7 @@ describe('BrowseService', () => { describe('getFirstItemFor', () => { beforeEach(() => { requestService = getMockRequestService(); - rdbService = getMockRemoteDataBuildService(); service = initTestService(); - spyOn(rdbService, 'buildList').and.callThrough(); }); describe('when getFirstItemFor is called with a valid browse definition id', () => { diff --git a/src/app/core/browse/browse.service.ts b/src/app/core/browse/browse.service.ts index 43f33f26e49..5fe06a700e5 100644 --- a/src/app/core/browse/browse.service.ts +++ b/src/app/core/browse/browse.service.ts @@ -6,6 +6,7 @@ import { startWith, } from 'rxjs/operators'; +import { environment } from '../../../environments/environment'; import { hasValue, hasValueOperator, @@ -16,7 +17,6 @@ import { followLink, FollowLinkConfig, } from '../../shared/utils/follow-link-config.model'; -import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { SortDirection } from '../cache/models/sort-options.model'; import { HrefOnlyDataService } from '../data/href-only-data.service'; import { PaginatedList } from '../data/paginated-list.model'; @@ -38,9 +38,15 @@ import { URLCombiner } from '../url-combiner/url-combiner'; import { BrowseDefinitionDataService } from './browse-definition-data.service'; import { BrowseEntrySearchOptions } from './browse-entry-search-options.model'; -export const BROWSE_LINKS_TO_FOLLOW: FollowLinkConfig<BrowseEntry | Item>[] = [ - followLink('thumbnail'), -]; +export function getBrowseLinksToFollow(): FollowLinkConfig<BrowseEntry | Item>[] { + const followLinks = [ + followLink('thumbnail'), + ]; + if (environment.item.showAccessStatuses) { + followLinks.push(followLink('accessStatus')); + } + return followLinks; +} /** * The service handling all browse requests @@ -67,7 +73,6 @@ export class BrowseService { protected halService: HALEndpointService, private browseDefinitionDataService: BrowseDefinitionDataService, private hrefOnlyDataService: HrefOnlyDataService, - private rdb: RemoteDataBuildService, ) { } @@ -117,7 +122,7 @@ export class BrowseService { }), ); if (options.fetchThumbnail ) { - return this.hrefOnlyDataService.findListByHref<BrowseEntry>(href$, {}, undefined, undefined, ...BROWSE_LINKS_TO_FOLLOW); + return this.hrefOnlyDataService.findListByHref<BrowseEntry>(href$, {}, undefined, undefined, ...getBrowseLinksToFollow()); } return this.hrefOnlyDataService.findListByHref<BrowseEntry>(href$); } @@ -165,7 +170,7 @@ export class BrowseService { }), ); if (options.fetchThumbnail) { - return this.hrefOnlyDataService.findListByHref<Item>(href$, {}, undefined, undefined, ...BROWSE_LINKS_TO_FOLLOW); + return this.hrefOnlyDataService.findListByHref<Item>(href$, {}, undefined, undefined, ...getBrowseLinksToFollow()); } return this.hrefOnlyDataService.findListByHref<Item>(href$); } diff --git a/src/app/core/data/relationship-data.service.spec.ts b/src/app/core/data/relationship-data.service.spec.ts index 1fa30ae7e4d..d4a6658f477 100644 --- a/src/app/core/data/relationship-data.service.spec.ts +++ b/src/app/core/data/relationship-data.service.spec.ts @@ -3,6 +3,8 @@ import { Store } from '@ngrx/store'; import { provideMockStore } from '@ngrx/store/testing'; import { of as observableOf } from 'rxjs'; +import { APP_CONFIG } from '../../../config/app-config.interface'; +import { environment } from '../../../environments/environment.test'; import { PAGINATED_RELATIONS_TO_ITEMS_OPERATOR } from '../../item-page/simple/item-types/shared/item-relationships-utils'; import { getMockRemoteDataBuildServiceHrefMap } from '../../shared/mocks/remote-data-build.service.mock'; import { getMockRequestService } from '../../shared/mocks/request.service.mock'; @@ -150,6 +152,7 @@ describe('RelationshipDataService', () => { { provide: RequestService, useValue: requestService }, { provide: PAGINATED_RELATIONS_TO_ITEMS_OPERATOR, useValue: jasmine.createSpy('paginatedRelationsToItems').and.returnValue((v) => v) }, { provide: Store, useValue: provideMockStore() }, + { provide: APP_CONFIG, useValue: environment }, RelationshipDataService, ], }); @@ -157,7 +160,7 @@ describe('RelationshipDataService', () => { }); describe('composition', () => { - const initService = () => new RelationshipDataService(null, null, null, null, null, null, null, null); + const initService = () => new RelationshipDataService(null, null, null, null, null, null, null, null, environment); testSearchDataImplementation(initService); }); diff --git a/src/app/core/data/relationship-data.service.ts b/src/app/core/data/relationship-data.service.ts index 0ab9a0a3a2e..d52c14f0a76 100644 --- a/src/app/core/data/relationship-data.service.ts +++ b/src/app/core/data/relationship-data.service.ts @@ -24,6 +24,10 @@ import { tap, } from 'rxjs/operators'; +import { + APP_CONFIG, + AppConfig, +} from '../../../config/app-config.interface'; import { AppState, keySelector, @@ -133,6 +137,7 @@ export class RelationshipDataService extends IdentifiableDataService<Relationshi protected itemService: ItemDataService, protected appStore: Store<AppState>, @Inject(PAGINATED_RELATIONS_TO_ITEMS_OPERATOR) private paginatedRelationsToItems: (thisId: string) => (source: Observable<RemoteData<PaginatedList<Relationship>>>) => Observable<RemoteData<PaginatedList<Item>>>, + @Inject(APP_CONFIG) private appConfig: AppConfig, ) { super('relationships', requestService, rdbService, objectCache, halService, 15 * 60 * 1000); @@ -319,7 +324,7 @@ export class RelationshipDataService extends IdentifiableDataService<Relationshi * @param options */ getRelatedItemsByLabel(item: Item, label: string, options?: FindListOptions): Observable<RemoteData<PaginatedList<Item>>> { - const linksToFollow: FollowLinkConfig<Relationship>[] = itemLinksToFollow(options.fetchThumbnail); + const linksToFollow: FollowLinkConfig<Relationship>[] = itemLinksToFollow(options.fetchThumbnail, this.appConfig.item.showAccessStatuses); linksToFollow.push(followLink('relationshipType')); return this.getItemRelationshipsByLabel(item, label, options, true, true, ...linksToFollow).pipe(this.paginatedRelationsToItems(item.uuid)); diff --git a/src/app/home-page/recent-item-list/recent-item-list.component.ts b/src/app/home-page/recent-item-list/recent-item-list.component.ts index 65c1998b7a0..c7383dd883d 100644 --- a/src/app/home-page/recent-item-list/recent-item-list.component.ts +++ b/src/app/home-page/recent-item-list/recent-item-list.component.ts @@ -98,6 +98,9 @@ export class RecentItemListComponent implements OnInit, OnDestroy { if (this.appConfig.browseBy.showThumbnails) { linksToFollow.push(followLink('thumbnail')); } + if (this.appConfig.item.showAccessStatuses) { + linksToFollow.push(followLink('accessStatus')); + } this.itemRD$ = this.searchService.search( new PaginatedSearchOptions({ diff --git a/src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts b/src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts index 3829b3286c0..1e963a5cca2 100644 --- a/src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts +++ b/src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts @@ -33,7 +33,7 @@ import { getAllSucceededRemoteData } from '../../../core/shared/operators'; import { hasValue } from '../../../shared/empty.util'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { AbstractTrackableComponent } from '../../../shared/trackable/abstract-trackable.component'; -import { ITEM_PAGE_LINKS_TO_FOLLOW } from '../../item.resolver'; +import { getItemPageLinksToFollow } from '../../item.resolver'; import { getItemPageRoute } from '../../item-page-routing-paths'; @Component({ @@ -92,7 +92,7 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl this.item = rd.payload; }), switchMap((rd: RemoteData<Item>) => { - return this.itemService.findByHref(rd.payload._links.self.href, true, true, ...ITEM_PAGE_LINKS_TO_FOLLOW); + return this.itemService.findByHref(rd.payload._links.self.href, true, true, ...getItemPageLinksToFollow()); }), getAllSucceededRemoteData(), ).subscribe((rd: RemoteData<Item>) => { diff --git a/src/app/item-page/edit-item-page/item-delete/item-delete.component.ts b/src/app/item-page/edit-item-page/item-delete/item-delete.component.ts index 1655856a3ed..ae791ccd8e7 100644 --- a/src/app/item-page/edit-item-page/item-delete/item-delete.component.ts +++ b/src/app/item-page/edit-item-page/item-delete/item-delete.component.ts @@ -320,8 +320,8 @@ export class ItemDeleteComponent this.linkService.resolveLinks( relationship, followLink('relationshipType'), - followLink('leftItem'), - followLink('rightItem'), + followLink('leftItem', undefined, followLink<Item>('accessStatus')), + followLink('rightItem', undefined, followLink<Item>('accessStatus')), ); return relationship.relationshipType.pipe( getFirstSucceededRemoteData(), diff --git a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts index 656d6089353..2b3e35c2292 100644 --- a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts +++ b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts @@ -478,7 +478,7 @@ export class EditRelationshipListComponent implements OnInit, OnDestroy { ); // this adds thumbnail images when required by configuration - const linksToFollow: FollowLinkConfig<Relationship>[] = itemLinksToFollow(this.fetchThumbnail); + const linksToFollow: FollowLinkConfig<Relationship>[] = itemLinksToFollow(this.fetchThumbnail, this.appConfig.item.showAccessStatuses); this.subs.push( observableCombineLatest([ diff --git a/src/app/item-page/item-page.resolver.ts b/src/app/item-page/item-page.resolver.ts index 431d8522e74..22267f3ce6f 100644 --- a/src/app/item-page/item-page.resolver.ts +++ b/src/app/item-page/item-page.resolver.ts @@ -18,7 +18,7 @@ import { redirectOn4xx } from '../core/shared/authorized.operators'; import { Item } from '../core/shared/item.model'; import { getFirstCompletedRemoteData } from '../core/shared/operators'; import { hasValue } from '../shared/empty.util'; -import { ITEM_PAGE_LINKS_TO_FOLLOW } from './item.resolver'; +import { getItemPageLinksToFollow } from './item.resolver'; import { getItemPageRoute } from './item-page-routing-paths'; /** @@ -44,7 +44,7 @@ export const itemPageResolver: ResolveFn<RemoteData<Item>> = ( route.params.id, true, false, - ...ITEM_PAGE_LINKS_TO_FOLLOW, + ...getItemPageLinksToFollow(), ).pipe( getFirstCompletedRemoteData(), redirectOn4xx(router, authService), diff --git a/src/app/item-page/item.resolver.ts b/src/app/item-page/item.resolver.ts index 343e0d19834..1fb00d91659 100644 --- a/src/app/item-page/item.resolver.ts +++ b/src/app/item-page/item.resolver.ts @@ -7,6 +7,7 @@ import { import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; +import { environment } from '../../environments/environment'; import { AppState } from '../app.reducer'; import { ItemDataService } from '../core/data/item-data.service'; import { RemoteData } from '../core/data/remote-data'; @@ -22,15 +23,21 @@ import { * The self links defined in this list are expected to be requested somewhere in the near future * Requesting them as embeds will limit the number of requests */ -export const ITEM_PAGE_LINKS_TO_FOLLOW: FollowLinkConfig<Item>[] = [ - followLink('owningCollection', {}, - followLink('parentCommunity', {}, - followLink('parentCommunity')), - ), - followLink('relationships'), - followLink('version', {}, followLink('versionhistory')), - followLink('thumbnail'), -]; +export function getItemPageLinksToFollow(): FollowLinkConfig<Item>[] { + const followLinks: FollowLinkConfig<Item>[] = [ + followLink('owningCollection', {}, + followLink('parentCommunity', {}, + followLink('parentCommunity')), + ), + followLink('relationships'), + followLink('version', {}, followLink('versionhistory')), + followLink('thumbnail'), + ]; + if (environment.item.showAccessStatuses) { + followLinks.push(followLink('accessStatus')); + } + return followLinks; +} export const itemResolver: ResolveFn<RemoteData<Item>> = ( route: ActivatedRouteSnapshot, @@ -42,7 +49,7 @@ export const itemResolver: ResolveFn<RemoteData<Item>> = ( route.params.id, true, false, - ...ITEM_PAGE_LINKS_TO_FOLLOW, + ...getItemPageLinksToFollow(), ).pipe( getFirstCompletedRemoteData(), ); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index a373c539846..7d89f64e5c2 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -280,7 +280,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo const relationship$ = this.relationshipService.findById(this.metadataService.virtualValue(this.value), true, true, - ... itemLinksToFollow(this.fetchThumbnail)).pipe( + ... itemLinksToFollow(this.fetchThumbnail, this.appConfig.item.showAccessStatuses)).pipe( getAllSucceededRemoteData(), getRemoteDataPayload()); this.relationshipValue$ = observableCombineLatest([this.item$.pipe(take(1)), relationship$]).pipe( diff --git a/src/app/shared/utils/relation-query.utils.ts b/src/app/shared/utils/relation-query.utils.ts index e2f3a0eb6c5..158744e78c3 100644 --- a/src/app/shared/utils/relation-query.utils.ts +++ b/src/app/shared/utils/relation-query.utils.ts @@ -1,3 +1,4 @@ +import { Item } from '../../core/shared/item.model'; import { Relationship } from '../../core/shared/item-relationships/relationship.model'; import { followLink, @@ -24,19 +25,22 @@ export function getFilterByRelation(relationType: string, itemUUID: string): str } /** - * Creates links to follow for the leftItem and rightItem. Links will include - * @param showThumbnail thumbnail image configuration - * @returns followLink array + * Creates links to follow for the leftItem and rightItem. Optionally additional links for `thumbnail` & `accessStatus` + * can be embedded as well. + * + * @param showThumbnail Whether the `thumbnail` needs to be embedded on the {@link Item} + * @param showAccessStatus Whether the `accessStatus` needs to be embedded on the {@link Item} */ -export function itemLinksToFollow(showThumbnail: boolean): FollowLinkConfig<Relationship>[] { - let linksToFollow: FollowLinkConfig<Relationship>[]; +export function itemLinksToFollow(showThumbnail: boolean, showAccessStatus: boolean): FollowLinkConfig<Relationship>[] { + const conditionalLinksToFollow: FollowLinkConfig<Item>[] = []; if (showThumbnail) { - linksToFollow = [ - followLink('leftItem',{}, followLink('thumbnail')), - followLink('rightItem',{}, followLink('thumbnail')), - ]; - } else { - linksToFollow = [followLink('leftItem'), followLink('rightItem')]; + conditionalLinksToFollow.push(followLink<Item>('thumbnail')); } - return linksToFollow; + if (showAccessStatus) { + conditionalLinksToFollow.push(followLink<Item>('accessStatus')); + } + return [ + followLink('leftItem', undefined, ...conditionalLinksToFollow), + followLink('rightItem', undefined, ...conditionalLinksToFollow), + ]; }