[CST-4591] Fix issue with showing empty collection results

This commit is contained in:
Giuseppe Digilio
2021-09-24 13:18:50 +02:00
parent a170f1f8a9
commit c6a73f2dcb
6 changed files with 87 additions and 97 deletions

View File

@@ -1,6 +1,5 @@
<div class="form-group w-100 pr-2 pl-2">
<input *ngIf="searchField"
type="search"
<div *ngIf="searchField" class="form-group w-100 pr-2 pl-2">
<input type="search"
class="form-control w-100"
(click)="$event.stopPropagation();"
placeholder="{{ 'submission.sections.general.search-collection' | translate }}"
@@ -8,8 +7,7 @@
#searchFieldEl>
</div>
<div class="dropdown-divider"></div>
<div
class="scrollable-menu"
<div class="scrollable-menu"
aria-labelledby="dropdownMenuButton"
(scroll)="onScroll($event)"
infiniteScroll
@@ -19,11 +17,11 @@
[fromRoot]="true"
[scrollWindow]="false"
(scrolled)="onScrollDown()">
<button class="dropdown-item disabled" *ngIf="searchListCollection?.length == 0 && !(isLoadingList | async)">
{{'submission.sections.general.no-collection' | translate}}
</button>
<button
*ngFor="let listItem of searchListCollection"
<button *ngFor="let listItem of searchListCollection"
class="dropdown-item collection-item"
title="{{ listItem.collection.name }}"
(click)="onSelect(listItem)">
@@ -34,7 +32,7 @@
<li class="list-item text-truncate text-primary font-weight-bold">{{ listItem.collection.name}}</li>
</ul>
</button>
<button class="dropdown-item disabled" *ngIf="(isLoadingList | async)" >
<button class="dropdown-item disabled" *ngIf="(isLoadingList | async)">
<ds-loading message="{{'loading.default' | translate}}">
</ds-loading>
</button>

View File

@@ -226,23 +226,11 @@ describe('CollectionDropdownComponent', () => {
});
it('should emit hasChoice true when totalElements is greater then one', () => {
spyOn(component.hasChoice, 'emit').and.callThrough();
spyOn(component.searchComplete, 'emit').and.callThrough();
component.ngOnInit();
fixture.detectChanges();
expect(component.hasChoice.emit).toHaveBeenCalledWith(true);
});
it('should emit hasChoice false when totalElements is not greater then one', () => {
componentAsAny.collectionDataService.getAuthorizedCollection.and.returnValue(paginatedEmptyCollectionRD$);
componentAsAny.collectionDataService.getAuthorizedCollectionByEntityType.and.returnValue(paginatedEmptyCollectionRD$);
spyOn(component.hasChoice, 'emit').and.callThrough();
component.ngOnInit();
fixture.detectChanges();
expect(component.hasChoice.emit).toHaveBeenCalledWith(false);
expect(component.searchComplete.emit).toHaveBeenCalledWith();
});
it('should emit theOnlySelectable when totalElements is equal to one', () => {

View File

@@ -11,7 +11,7 @@ import {
} from '@angular/core';
import { FormControl } from '@angular/forms';
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import { BehaviorSubject, from as observableFrom, Observable, of as observableOf, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, mergeMap, reduce, startWith, switchMap, take } from 'rxjs/operators';
import { hasValue } from '../empty.util';
@@ -22,10 +22,7 @@ import { Community } from '../../core/shared/community.model';
import { CollectionDataService } from '../../core/data/collection-data.service';
import { Collection } from '../../core/shared/collection.model';
import { followLink } from '../utils/follow-link-config.model';
import {
getFirstSucceededRemoteDataPayload,
getFirstSucceededRemoteWithNotEmptyData
} from '../../core/shared/operators';
import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../../core/shared/operators';
/**
* An interface to represent a collection entry
@@ -113,9 +110,9 @@ export class CollectionDropdownComponent implements OnInit, OnDestroy {
@Input() entityType: string;
/**
* Emit to notify whether collections to choice from are more than one
* Emit to notify whether search is complete
*/
@Output() hasChoice = new EventEmitter<boolean>();
@Output() searchComplete = new EventEmitter<any>();
/**
* Emit to notify the only selectable collection.
@@ -213,21 +210,21 @@ export class CollectionDropdownComponent implements OnInit, OnDestroy {
query,
this.entityType,
findOptions,
false,
true,
followLink('parentCommunity'));
} else {
searchListService$ = this.collectionDataService
.getAuthorizedCollection(query, findOptions, true, false, followLink('parentCommunity'));
.getAuthorizedCollection(query, findOptions, true, true, followLink('parentCommunity'));
}
this.searchListCollection$ = searchListService$.pipe(
getFirstSucceededRemoteWithNotEmptyData(),
switchMap((collections: RemoteData<PaginatedList<Collection>>) => {
if ( (this.searchListCollection.length + findOptions.elementsPerPage) >= collections.payload.totalElements ) {
getFirstCompletedRemoteData(),
switchMap((collectionsRD: RemoteData<PaginatedList<Collection>>) => {
this.searchComplete.emit();
if (collectionsRD.hasSucceeded && collectionsRD.payload.totalElements > 0) {
if ( (this.searchListCollection.length + findOptions.elementsPerPage) >= collectionsRD.payload.totalElements ) {
this.hasNextPage = false;
}
this.emitSelectionEvents(collections);
return collections.payload.page;
}),
this.emitSelectionEvents(collectionsRD);
return observableFrom(collectionsRD.payload.page).pipe(
mergeMap((collection: Collection) => collection.parentCommunity.pipe(
getFirstSucceededRemoteDataPayload(),
map((community: Community) => ({
@@ -236,12 +233,21 @@ export class CollectionDropdownComponent implements OnInit, OnDestroy {
})
))),
reduce((acc: any, value: any) => [...acc, value], []),
startWith([])
);
this.subs.push(this.searchListCollection$.subscribe(
(next) => { this.searchListCollection.push(...next); }, undefined,
() => { this.hideShowLoader(false); this.changeDetectorRef.detectChanges(); }
));
}
} else {
this.hasNextPage = false;
return observableOf([]);
}
})
);
this.subs.push(
this.searchListCollection$.subscribe((list: CollectionListEntry[]) => {
this.searchListCollection.push(...list);
this.hideShowLoader(false);
this.changeDetectorRef.detectChanges();
})
);
}
/**
@@ -284,7 +290,6 @@ export class CollectionDropdownComponent implements OnInit, OnDestroy {
* @private
*/
private emitSelectionEvents(collections: RemoteData<PaginatedList<Collection>>) {
this.hasChoice.emit(collections.payload.totalElements > 1);
if (collections.payload.totalElements === 1) {
const collection = collections.payload.page[0];
collections.payload.page[0].parentCommunity.pipe(

View File

@@ -1,5 +1,5 @@
<div>
<div class="modal-header">{{'dso-selector.create.collection.head' | translate}}
<div class="modal-header">{{'dso-selector.select.collection.head' | translate}}
<button type="button" class="close" (click)="closeCollectionModal()" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
@@ -8,7 +8,7 @@
<ds-loading *ngIf="isLoading()"></ds-loading>
<ds-collection-dropdown [ngClass]="{'d-none': isLoading()}"
(selectionChange)="selectObject($event)"
(hasChoice)="onHasChoice($event)"
(searchComplete)="searchComplete()"
(theOnlySelectable)="theOnlySelectable($event)"
[entityType]="entityType">
</ds-collection-dropdown>

View File

@@ -78,25 +78,23 @@ describe('SubmissionImportExternalCollectionComponent test suite', () => {
expect(compAsAny.activeModal.dismiss).toHaveBeenCalled();
});
it('should be in loading state when hasChoice variable is different to true', () => {
comp.hasChoice = null;
it('should be in loading state when search is not completed', () => {
comp.loading = null;
expect(comp.isLoading()).toBeFalse();
comp.loading = true;
expect(comp.isLoading()).toBeTrue();
comp.hasChoice = false;
expect(comp.isLoading()).toBeTrue();
comp.hasChoice = true;
comp.loading = false;
expect(comp.isLoading()).toBeFalse();
});
it('should set hasChoice variable on hasChoice event', () => {
comp.hasChoice = null;
it('should set loading variable to false on searchComplete event', () => {
comp.loading = null;
comp.onHasChoice(true);
expect(comp.hasChoice).toBe(true);
comp.searchComplete();
expect(comp.loading).toBe(false);
comp.onHasChoice(false);
expect(comp.hasChoice).toBe(false);
});
it('should emit theOnlySelectable', () => {

View File

@@ -22,9 +22,9 @@ export class SubmissionImportExternalCollectionComponent {
public entityType: string;
/**
* If a collection choice is available
* If collection searching is pending or not
*/
public hasChoice: boolean = null;
public loading = true;
/**
* Initialize the component variables.
@@ -60,14 +60,15 @@ export class SubmissionImportExternalCollectionComponent {
* Set the hasChoice state
* @param hasChoice
*/
public onHasChoice(hasChoice: boolean) {
this.hasChoice = hasChoice;
public searchComplete() {
this.loading = false;
}
/**
* If the component is in loading state.
*/
public isLoading(): boolean {
return this.hasChoice !== true;
return !!this.loading;
}
}