Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,16 @@ <h2 *ngIf="!(loading | async) && dataSource.data.length === 0" class="h4 text-ce
</cdk-tree-node>
</cdk-tree>
</div>
<!-- Show previous/next results pagination -->
<div class="mb-3 d-flex gap-2" *ngIf="(showPreviousPage$ | async) || (showNextPage$ | async)">
<button class="btn btn-outline-secondary"
*ngIf="showPreviousPage$ | async"
(click)="loadPreviousPage(selectedItems)">
{{ 'browse.taxonomy.show_previous_results' | translate }}
</button>
<button class="btn btn-outline-secondary"
*ngIf="showNextPage$ | async"
(click)="loadNextPage(selectedItems)">
{{ 'browse.taxonomy.show_next_results' | translate }}
</button>
</div>
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { FlatTreeControl } from '@angular/cdk/tree';
import { Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output, OnChanges, SimpleChanges, ViewChild } from '@angular/core';

import { Observable, Subscription, of } from 'rxjs';
import { map, tap, switchMap } from 'rxjs/operators';
import { Observable, Subscription } from 'rxjs';
import { Store } from '@ngrx/store';
import { TranslateService } from '@ngx-translate/core';

Expand Down Expand Up @@ -116,6 +116,10 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit, OnChanges

readonly AlertType = AlertType;

public showNextPage$: Observable<boolean>;

public showPreviousPage$: Observable<boolean>;

/**
* Initialize instance variables
*
Expand Down Expand Up @@ -222,6 +226,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
Expand Down Expand Up @@ -289,6 +299,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;
Expand All @@ -298,6 +319,28 @@ 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(selectedItems: string[]) {
const svc = this.vocabularyTreeviewService;
if (svc.currentPage < svc.totalPages) {
svc.searchByQueryAndPage(svc.queryInProgress, selectedItems, 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(selectedItems: string[]) {
const svc = this.vocabularyTreeviewService;
if (svc.currentPage > 1) {
svc.searchByQueryAndPage(svc.queryInProgress, selectedItems, svc.currentPage - 1);
}
}

/**
* Check if search box contains any text
*/
Expand Down Expand Up @@ -328,6 +371,9 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit, OnChanges
if (this.searchInput) {
this.searchInput.nativeElement.focus();
}

this.showNextPage$ = of(false);
this.showPreviousPage$ = of(false);
}

add() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';

import { BehaviorSubject, Observable, of as observableOf } from 'rxjs';
import { map, merge, mergeMap, scan } from 'rxjs/operators';
import { map, merge, mergeMap, scan, tap } from 'rxjs/operators';
import findIndex from 'lodash/findIndex';

import {
Expand All @@ -17,10 +17,11 @@ import { isEmpty, isNotEmpty } from '../../empty.util';
import { VocabularyOptions } from '../../../core/submission/vocabularies/models/vocabulary-options.model';
import {
getFirstSucceededRemoteDataPayload,
getFirstSucceededRemoteListPayload
getFirstSucceededRemoteListPayload, getFirstSucceededRemoteData
} from '../../../core/shared/operators';
import { PaginatedList } from '../../../core/data/paginated-list.model';
import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
import { RemoteData } from '../../../core/data/remote-data';

/**
* A service that provides methods to deal with vocabulary tree
Expand Down Expand Up @@ -79,6 +80,12 @@ export class VocabularyTreeviewService {
*/
private hideSearchingWhenUnsubscribed$ = new Observable(() => () => this.loading.next(false));

public currentPage = 1;
public totalPages = 1;
public queryInProgress = '';
public showNextPageSubject = new BehaviorSubject<boolean>(false);
public showPreviousPageSubject = new BehaviorSubject<boolean>(false);

/**
* Initialize instance variables
*
Expand Down Expand Up @@ -186,20 +193,51 @@ 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;
}
this.nodeMap = new Map<string, TreeviewNode>();
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<PaginatedList<VocabularyEntry>>) => {
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()
Expand Down
4 changes: 4 additions & 0 deletions src/assets/i18n/en.json5
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,10 @@

"browse.taxonomy.button": "Browse",

"browse.taxonomy.show_next_results": "Show next results",

"browse.taxonomy.show_previous_results": "Show previous results",

"browse.title": "Browsing {{ collection }} by {{ field }}{{ startsWith }} {{ value }}",

"browse.title.page": "Browsing {{ collection }} by {{ field }} {{ value }}",
Expand Down
Loading