From 3ecdfe422df3b31b20d257f9197d0b2e7d250920 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Thu, 9 Jan 2025 18:46:10 +0100 Subject: [PATCH 1/2] 122357: Ensure the request href$ observable aren't triggered multiple times --- src/app/core/data/base/base-data.service.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/core/data/base/base-data.service.ts b/src/app/core/data/base/base-data.service.ts index 85603580a43..2b69e5791b0 100644 --- a/src/app/core/data/base/base-data.service.ts +++ b/src/app/core/data/base/base-data.service.ts @@ -6,7 +6,7 @@ * http://www.dspace.org/license/ */ -import { AsyncSubject, from as observableFrom, Observable, of as observableOf } from 'rxjs'; +import { AsyncSubject, from as observableFrom, Observable, of as observableOf, shareReplay } from 'rxjs'; import { map, mergeMap, skipWhile, switchMap, take, tap, toArray } from 'rxjs/operators'; import { hasValue, isNotEmpty, isNotEmptyOperator } from '../../../shared/empty.util'; import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; @@ -264,6 +264,7 @@ export class BaseDataService implements HALDataServic isNotEmptyOperator(), take(1), map((href: string) => this.buildHrefFromFindOptions(href, {}, [], ...linksToFollow)), + shareReplay(1), ); this.createAndSendGetRequest(requestHref$, useCachedVersionIfAvailable); @@ -298,6 +299,7 @@ export class BaseDataService implements HALDataServic isNotEmptyOperator(), take(1), map((href: string) => this.buildHrefFromFindOptions(href, options, [], ...linksToFollow)), + shareReplay(1), ); this.createAndSendGetRequest(requestHref$, useCachedVersionIfAvailable); From 0570542b1eb2874617deac27f38c4ecec7bbc1c3 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Thu, 9 Jan 2025 15:18:24 +0100 Subject: [PATCH 2/2] 122357: Reduced the amount of times the browse observables are fired again --- .../browse-by-date.component.ts | 24 +++++++++------ .../browse-by-metadata.component.ts | 29 ++++++++++++------- src/app/browse-by/browse-by-routing.module.ts | 2 -- .../browse-by-title.component.ts | 26 ++++++++++------- 4 files changed, 50 insertions(+), 31 deletions(-) diff --git a/src/app/browse-by/browse-by-date/browse-by-date.component.ts b/src/app/browse-by/browse-by-date/browse-by-date.component.ts index e655d88cc97..ed904df8e83 100644 --- a/src/app/browse-by/browse-by-date/browse-by-date.component.ts +++ b/src/app/browse-by/browse-by-date/browse-by-date.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectorRef, Component, Inject, OnInit } from '@angular/core'; -import { BrowseByMetadataComponent, browseParamsToOptions, getBrowseSearchOptions } from '../browse-by-metadata/browse-by-metadata.component'; +import { BrowseByMetadataComponent, browseParamsToOptions } from '../browse-by-metadata/browse-by-metadata.component'; import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { ActivatedRoute, Params, Router } from '@angular/router'; @@ -7,7 +7,7 @@ import { BrowseService } from '../../core/browse/browse.service'; import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; import { StartsWithType } from '../../shared/starts-with/starts-with-decorator'; import { PaginationService } from '../../core/pagination/pagination.service'; -import { map } from 'rxjs/operators'; +import { map, distinctUntilChanged } from 'rxjs/operators'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { isValidDate } from '../../shared/date.util'; @@ -53,16 +53,22 @@ export class BrowseByDateComponent extends BrowseByMetadataComponent implements const sortConfig = new SortOptions('default', SortDirection.ASC); this.startsWithType = StartsWithType.date; // include the thumbnail configuration in browse search options - this.updatePage(getBrowseSearchOptions(this.defaultBrowseId, this.paginationConfig, sortConfig, this.fetchThumbnails)); this.currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig); this.currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, sortConfig); + const routeParams$: Observable = observableCombineLatest([ + this.route.params, + this.route.queryParams, + ]).pipe( + map(([params, queryParams]: [Params, Params]) => Object.assign({}, params, queryParams)), + distinctUntilChanged((prev: Params, curr: Params) => prev.id === curr.id && prev.startsWith === curr.startsWith), + ); this.subs.push( - observableCombineLatest([this.route.params, this.route.queryParams, this.scope$, this.route.data, - this.currentPagination$, this.currentSort$]).pipe( - map(([routeParams, queryParams, scope, data, currentPage, currentSort]) => { - return [Object.assign({}, routeParams, queryParams, data), scope, currentPage, currentSort]; - }) - ).subscribe(([params, scope, currentPage, currentSort]: [Params, string, PaginationComponentOptions, SortOptions]) => { + observableCombineLatest([ + routeParams$, + this.scope$, + this.currentPagination$, + this.currentSort$, + ]).subscribe(([params, scope, currentPage, currentSort]: [Params, string, PaginationComponentOptions, SortOptions]) => { const metadataKeys = params.browseDefinition ? params.browseDefinition.metadataKeys : this.defaultMetadataKeys; this.browseId = params.id || this.defaultBrowseId; this.startsWith = +params.startsWith || params.startsWith; diff --git a/src/app/browse-by/browse-by-metadata/browse-by-metadata.component.ts b/src/app/browse-by/browse-by-metadata/browse-by-metadata.component.ts index af1645daa30..b4ef750e667 100644 --- a/src/app/browse-by/browse-by-metadata/browse-by-metadata.component.ts +++ b/src/app/browse-by/browse-by-metadata/browse-by-metadata.component.ts @@ -1,5 +1,5 @@ import { BehaviorSubject, combineLatest as observableCombineLatest, Observable, Subscription, of as observableOf } from 'rxjs'; -import { Component, Inject, OnInit, OnDestroy, Input, OnChanges } from '@angular/core'; +import { Component, Inject, OnInit, OnDestroy, Input, OnChanges, SimpleChanges } from '@angular/core'; import { RemoteData } from '../../core/data/remote-data'; import { PaginatedList } from '../../core/data/paginated-list.model'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; @@ -14,7 +14,7 @@ import { getFirstSucceededRemoteData } from '../../core/shared/operators'; import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; import { StartsWithType } from '../../shared/starts-with/starts-with-decorator'; import { PaginationService } from '../../core/pagination/pagination.service'; -import { map } from 'rxjs/operators'; +import { map, distinctUntilChanged } from 'rxjs/operators'; import { APP_CONFIG, AppConfig } from '../../../config/app-config.interface'; import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; import { rendersBrowseBy } from '../browse-by-switcher/browse-by-decorator'; @@ -158,15 +158,22 @@ export class BrowseByMetadataComponent implements OnInit, OnChanges, OnDestroy { ngOnInit(): void { const sortConfig = new SortOptions('default', SortDirection.ASC); - this.updatePage(getBrowseSearchOptions(this.defaultBrowseId, this.paginationConfig, sortConfig)); this.currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig); this.currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, sortConfig); + const routeParams$: Observable = observableCombineLatest([ + this.route.params, + this.route.queryParams, + ]).pipe( + map(([params, queryParams]: [Params, Params]) => Object.assign({}, params, queryParams)), + distinctUntilChanged((prev: Params, curr: Params) => prev.id === curr.id && prev.authority === curr.authority && prev.value === curr.value && prev.startsWith === curr.startsWith), + ); this.subs.push( - observableCombineLatest([this.route.params, this.route.queryParams, this.scope$, this.currentPagination$, this.currentSort$]).pipe( - map(([routeParams, queryParams, scope, currentPage, currentSort]) => { - return [Object.assign({}, routeParams, queryParams), scope, currentPage, currentSort]; - }) - ).subscribe(([params, scope, currentPage, currentSort]: [Params, string, PaginationComponentOptions, SortOptions]) => { + observableCombineLatest([ + routeParams$, + this.scope$, + this.currentPagination$, + this.currentSort$, + ]).subscribe(([params, scope, currentPage, currentSort]: [Params, string, PaginationComponentOptions, SortOptions]) => { this.browseId = params.id || this.defaultBrowseId; this.authority = params.authority; @@ -190,8 +197,10 @@ export class BrowseByMetadataComponent implements OnInit, OnChanges, OnDestroy { } - ngOnChanges(): void { - this.scope$.next(this.scope); + ngOnChanges(changes: SimpleChanges): void { + if (hasValue(changes.scope)) { + this.scope$.next(this.scope); + } } /** diff --git a/src/app/browse-by/browse-by-routing.module.ts b/src/app/browse-by/browse-by-routing.module.ts index f07df26b32b..d5143351e0d 100644 --- a/src/app/browse-by/browse-by-routing.module.ts +++ b/src/app/browse-by/browse-by-routing.module.ts @@ -4,7 +4,6 @@ import { BrowseByGuard } from './browse-by-guard'; import { BrowseByDSOBreadcrumbResolver } from './browse-by-dso-breadcrumb.resolver'; import { BrowseByI18nBreadcrumbResolver } from './browse-by-i18n-breadcrumb.resolver'; import { BrowseByPageComponent } from './browse-by-page/browse-by-page.component'; -import { DSOEditMenuResolver } from '../shared/dso-page/dso-edit-menu.resolver'; @NgModule({ imports: [ @@ -13,7 +12,6 @@ import { DSOEditMenuResolver } from '../shared/dso-page/dso-edit-menu.resolver'; path: '', resolve: { breadcrumb: BrowseByDSOBreadcrumbResolver, - menu: DSOEditMenuResolver }, children: [ { diff --git a/src/app/browse-by/browse-by-title/browse-by-title.component.ts b/src/app/browse-by/browse-by-title/browse-by-title.component.ts index 7b603af48bc..22b4bf47806 100644 --- a/src/app/browse-by/browse-by-title/browse-by-title.component.ts +++ b/src/app/browse-by/browse-by-title/browse-by-title.component.ts @@ -1,12 +1,12 @@ -import { combineLatest as observableCombineLatest } from 'rxjs'; +import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { Component, OnInit } from '@angular/core'; import { Params } from '@angular/router'; import { BrowseByMetadataComponent, - browseParamsToOptions, getBrowseSearchOptions + browseParamsToOptions, } from '../browse-by-metadata/browse-by-metadata.component'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; -import { map } from 'rxjs/operators'; +import { map, distinctUntilChanged } from 'rxjs/operators'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { rendersBrowseBy } from '../browse-by-switcher/browse-by-decorator'; import { BrowseByDataType } from '../browse-by-switcher/browse-by-data-type'; @@ -24,16 +24,22 @@ export class BrowseByTitleComponent extends BrowseByMetadataComponent implements ngOnInit(): void { const sortConfig = new SortOptions('dc.title', SortDirection.ASC); - // include the thumbnail configuration in browse search options - this.updatePage(getBrowseSearchOptions(this.defaultBrowseId, this.paginationConfig, sortConfig, this.fetchThumbnails)); this.currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig); this.currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, sortConfig); + const routeParams$: Observable = observableCombineLatest([ + this.route.params, + this.route.queryParams, + ]).pipe( + map(([params, queryParams]: [Params, Params]) => Object.assign({}, params, queryParams)), + distinctUntilChanged((prev: Params, curr: Params) => prev.id === curr.id && prev.startsWith === curr.startsWith), + ); this.subs.push( - observableCombineLatest([this.route.params, this.route.queryParams, this.scope$, this.currentPagination$, this.currentSort$]).pipe( - map(([routeParams, queryParams, scope, currentPage, currentSort]) => { - return [Object.assign({}, routeParams, queryParams), scope, currentPage, currentSort]; - }) - ).subscribe(([params, scope, currentPage, currentSort]: [Params, string, PaginationComponentOptions, SortOptions]) => { + observableCombineLatest([ + routeParams$, + this.scope$, + this.currentPagination$, + this.currentSort$, + ]).subscribe(([params, scope, currentPage, currentSort]: [Params, string, PaginationComponentOptions, SortOptions]) => { this.startsWith = +params.startsWith || params.startsWith; this.browseId = params.id || this.defaultBrowseId; this.updatePageWithItems(browseParamsToOptions(params, scope, currentPage, currentSort, this.browseId, this.fetchThumbnails), undefined, undefined);