From 12eb4558a9cfbac2a5178b38308b9e586f8c1758 Mon Sep 17 00:00:00 2001 From: Zahraa Chreim Date: Tue, 24 Jun 2025 07:57:34 +0300 Subject: [PATCH 1/3] =?UTF-8?q?132284:=20Add=20paginated=20vocabulary=20se?= =?UTF-8?q?arch=20with=20=E2=80=98Show=20previous/next=20results=E2=80=99?= =?UTF-8?q?=20controls=20in=20hierarchical=20browse?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit a201d2f3b3b7395a1e4c5643fb0a86b72a5b150e) --- .../vocabulary-treeview.component.html | 17 +++++++ .../vocabulary-treeview.component.ts | 33 +++++++++++++ .../vocabulary-treeview.service.ts | 46 +++++++++++++++++-- src/assets/i18n/en.json5 | 4 ++ 4 files changed, 97 insertions(+), 3 deletions(-) diff --git a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html index 6da6a33cd4b..93f44d6abec 100644 --- a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html +++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html @@ -123,3 +123,20 @@

+ @if (showPreviousPage$ | async) { + + } + @if (showNextPage$ | async) { + + } + +} diff --git a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts index b62dff59b05..a31b7ba24ba 100644 --- a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts +++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts @@ -23,6 +23,7 @@ import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateModule } from '@ngx-translate/core'; import { Observable, + of, Subscription, } from 'rxjs'; import { @@ -172,6 +173,14 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit, OnChanges readonly AlertType = AlertType; + public showNextPage$ = this.vocabularyTreeviewService.showNextPageSubject + ? this.vocabularyTreeviewService.showNextPageSubject.asObservable() + : of(false); + + public showPreviousPage$ = this.vocabularyTreeviewService.showPreviousPageSubject + ? this.vocabularyTreeviewService.showPreviousPageSubject.asObservable() + : of(false); + /** * Initialize instance variables * @@ -353,6 +362,30 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit, OnChanges } } + /** + * Loads the next page of vocabulary search results. + * Increments the current page in the service and re-triggers the query with the same search term and selection. + */ + loadNextPage(): void { + const svc = this.vocabularyTreeviewService; + + if (svc.currentPage < svc.totalPages) { + svc.searchByQueryAndPage(svc.queryInProgress, [], svc.currentPage + 1); + } + } + + /** + * Loads the previous page of vocabulary search results. + * Decrements the current page in the service and re-triggers the query with the same search term and selection. + */ + loadPreviousPage(): void { + const svc = this.vocabularyTreeviewService; + + if (svc.currentPage > 1) { + svc.searchByQueryAndPage(svc.queryInProgress, [], svc.currentPage - 1); + } + } + /** * Check if search box contains any text */ diff --git a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.service.ts b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.service.ts index 83266b1b5f6..722015da951 100644 --- a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.service.ts +++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.service.ts @@ -10,10 +10,13 @@ import { merge, mergeMap, scan, + tap, } from 'rxjs/operators'; import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { RemoteData } from '../../../core/data/remote-data'; import { + getFirstSucceededRemoteData, getFirstSucceededRemoteDataPayload, getFirstSucceededRemoteListPayload, } from '../../../core/shared/operators'; @@ -90,6 +93,12 @@ export class VocabularyTreeviewService { */ private hideSearchingWhenUnsubscribed$ = new Observable(() => () => this.loading.next(false)); + public currentPage = 1; + public totalPages = 1; + public queryInProgress = ''; + public showNextPageSubject = new BehaviorSubject(false); + public showPreviousPageSubject = new BehaviorSubject(false); + /** * Initialize instance variables * @@ -197,10 +206,28 @@ export class VocabularyTreeviewService { } /** - * Perform a search operation by query + * Initiates a vocabulary search using the provided query term and selection, starting from the first page. + * + * @param query - The text input to search for within the vocabulary. + * @param selectedItems - Currently selected vocabulary item IDs to retain in the result. */ searchByQuery(query: string, selectedItems: string[]) { + this.searchByQueryAndPage(query, selectedItems, 1); + } + + /** + * Executes a paginated vocabulary search with the given query, selection, and page number. + * Updates pagination state, loading indicators, and triggers the vocabulary tree rebuild. + * + * @param query - The search term to filter vocabulary entries. + * @param selectedItems - IDs of items currently selected in the tree. + * @param page - The page number to fetch (1-based index). + */ + searchByQueryAndPage(query: string, selectedItems: string[], page: number = 1) { this.loading.next(true); + this.queryInProgress = query; + this.currentPage = page; + if (isEmpty(this.storedNodes)) { this.storedNodes = this.dataChange.value; this.storedNodeMap = this.nodeMap; @@ -208,9 +235,22 @@ export class VocabularyTreeviewService { this.nodeMap = new Map(); this.dataChange.next([]); - this.vocabularyService.getVocabularyEntriesByValue(query, false, this.vocabularyOptions, new PageInfo()).pipe( + const pageInfo = new PageInfo({ + elementsPerPage: 20, + currentPage: page, + totalElements: 0, + totalPages: 0, + }); + + this.vocabularyService.getVocabularyEntriesByValue(query, false, this.vocabularyOptions, pageInfo).pipe( + getFirstSucceededRemoteData(), + tap((rd: RemoteData>) => { + this.totalPages = rd.payload.pageInfo.totalPages; + this.showPreviousPageSubject.next(rd.payload.pageInfo.currentPage > 1); + this.showNextPageSubject.next(rd.payload.pageInfo.currentPage < this.totalPages); + }), getFirstSucceededRemoteListPayload(), - mergeMap((result: VocabularyEntry[]) => (result.length > 0) ? result : observableOf(null)), + mergeMap((result: VocabularyEntry[]) => result.length > 0 ? result : observableOf(null)), mergeMap((entry: VocabularyEntry) => this.vocabularyService.findEntryDetailById(entry.otherInformation.id, this.vocabularyName).pipe( getFirstSucceededRemoteDataPayload(), diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index b34909fa6a1..4086f2f2bd4 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1101,6 +1101,10 @@ "browse.title": "Browsing by {{ field }}{{ startsWith }} {{ value }}", + "browse.taxonomy.show_next_results": "Show next results", + + "browse.taxonomy.show_previous_results": "Show previous results", + "browse.title.page": "Browsing by {{ field }} {{ value }}", "search.browse.item-back": "Back to Results", From 6f13ce190320dab7d1f342b7f33462519b6fa42b Mon Sep 17 00:00:00 2001 From: Zahraa Chreim Date: Thu, 30 Oct 2025 10:30:31 +0200 Subject: [PATCH 2/3] 132284: Reset pagination button state when navigating away from the subject category page (cherry picked from commit 231da9c2c50f9043a1f5090833aa8429b7d71db2) (cherry picked from commit f007a25dedb02d2e893a090a8057b6d812a4daae) --- .../vocabulary-treeview.component.ts | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts index a31b7ba24ba..7d0abea87f5 100644 --- a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts +++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts @@ -173,13 +173,9 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit, OnChanges readonly AlertType = AlertType; - public showNextPage$ = this.vocabularyTreeviewService.showNextPageSubject - ? this.vocabularyTreeviewService.showNextPageSubject.asObservable() - : of(false); + public showNextPage$: Observable; - public showPreviousPage$ = this.vocabularyTreeviewService.showPreviousPageSubject - ? this.vocabularyTreeviewService.showPreviousPageSubject.asObservable() - : of(false); + public showPreviousPage$: Observable; /** * Initialize instance variables @@ -284,6 +280,12 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit, OnChanges * Initialize the component, setting up the data to build the tree */ ngOnInit(): void { + + // Initialize observables to false when component loads + // Ensures pagination buttons are hidden on first load or after navigation + this.showNextPage$ = of(false); + this.showPreviousPage$ = of(false); + this.subs.push( this.vocabularyService.findVocabularyById(this.vocabularyOptions.name).pipe( // Retrieve the configured preloadLevel from REST @@ -353,6 +355,17 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit, OnChanges * Search for a vocabulary entry by query */ search() { + + // Reassign observables after performing each new search + // Updates pagination button visibility based on available pages + this.showNextPage$ = this.vocabularyTreeviewService.showNextPageSubject + ? this.vocabularyTreeviewService.showNextPageSubject.asObservable() + : of(false); + + this.showPreviousPage$ = this.vocabularyTreeviewService.showPreviousPageSubject + ? this.vocabularyTreeviewService.showPreviousPageSubject.asObservable() + : of(false); + if (isNotEmpty(this.searchText)) { if (isEmpty(this.storedNodeMap)) { this.storedNodeMap = this.nodeMap; From b48cbd77aa3ce825e2e052f5343135f773a12156 Mon Sep 17 00:00:00 2001 From: Zahraa Chreim Date: Fri, 7 Nov 2025 14:50:34 +0200 Subject: [PATCH 3/3] 132284: Reset pagination on reset (cherry picked from commit 9aacba60b4c296b9b0e9561d4d15b83d006193d1) (cherry picked from commit 8fb9d83842ffe056df5560cdbdc8abe2c7f874f1) --- .../form/vocabulary-treeview/vocabulary-treeview.component.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts index 7d0abea87f5..7ddf51866f7 100644 --- a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts +++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts @@ -425,6 +425,9 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit, OnChanges if (this.searchInput) { this.searchInput.nativeElement.focus(); } + + this.showNextPage$ = of(false); + this.showPreviousPage$ = of(false); } add() {