diff --git a/src/app/core/submission/vocabularies/vocabulary.service.ts b/src/app/core/submission/vocabularies/vocabulary.service.ts index db038cc903c..27e78bc3f4c 100644 --- a/src/app/core/submission/vocabularies/vocabulary.service.ts +++ b/src/app/core/submission/vocabularies/vocabulary.service.ts @@ -148,17 +148,19 @@ export class VocabularyService { pagination: paginationOptions }); - // Use ORCID external source (try both orcid and orcidV2) - return this.externalSourceDataService.getExternalSourceEntries('orcid', searchOptions).pipe( - switchMap((orcidResponse: RemoteData>) => { - if (orcidResponse.hasSucceeded && orcidResponse.payload && orcidResponse.payload.page.length > 0) { + // Use ORCID external source with proper completion handling + return this.externalSourceDataService.getExternalSourceEntries('orcid', searchOptions, false, false).pipe( + // Use the existing DSpace operator to ensure completion + getFirstSucceededRemoteDataPayload(), + switchMap((paginatedList: PaginatedList) => { + if (paginatedList && paginatedList.page.length > 0) { // Convert ExternalSourceEntry to VocabularyEntry - const vocabularyEntries: VocabularyEntry[] = orcidResponse.payload.page.map(entry => { + const vocabularyEntries: VocabularyEntry[] = paginatedList.page.map(entry => { const vocabEntry = new VocabularyEntry(); // Display shows author name + ORCID for selection vocabEntry.display = `${entry.display} (ORCID: ${entry.id})`; - // Value should be just the author name (what goes in the main field) - vocabEntry.value = entry.display; + // Value should be just the author name (what goes in the main field) + vocabEntry.value = entry.display; // Authority is the ORCID ID (what goes in the authority field) vocabEntry.authority = entry.id; vocabEntry.otherInformation = { orcid: entry.id }; @@ -173,8 +175,9 @@ export class VocabularyService { return createSuccessfulRemoteDataObject$(emptyList); } }), - catchError(() => { - // On error, return empty list + catchError((error) => { + console.warn('ORCID lookup failed:', error); + // Return empty list on error rather than falling back const emptyList = buildPaginatedList(new PageInfo(), []); return createSuccessfulRemoteDataObject$(emptyList); }) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts index 63545f45d2f..d15964f89bb 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts @@ -2,7 +2,7 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnDestroy, OnInit, O import { UntypedFormGroup } from '@angular/forms'; import { of as observableOf, Subscription } from 'rxjs'; -import { catchError, distinctUntilChanged } from 'rxjs/operators'; +import { catchError, distinctUntilChanged, finalize } from 'rxjs/operators'; import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'; import { DynamicFormLayoutService, DynamicFormValidationService } from '@ng-dynamic-forms/core'; @@ -230,8 +230,13 @@ export class DsDynamicLookupComponent extends DsDynamicVocabularyComponent imple [] )) ), - distinctUntilChanged()) - .subscribe((list: PaginatedList) => { + distinctUntilChanged(), + finalize(() => { + // Always reset loading state regardless of success or error + this.loading = false; + this.cdr.detectChanges(); + }) + ).subscribe((list: PaginatedList) => { this.optionsList = list.page; this.updatePageInfo( list.pageInfo.elementsPerPage, @@ -239,8 +244,6 @@ export class DsDynamicLookupComponent extends DsDynamicVocabularyComponent imple list.pageInfo.totalElements, list.pageInfo.totalPages ); - this.loading = false; - this.cdr.detectChanges(); })); }