diff --git a/src/app/shared/collection-dropdown/collection-dropdown.component.html b/src/app/shared/collection-dropdown/collection-dropdown.component.html
index 36269294c1..ce5fe0deb8 100644
--- a/src/app/shared/collection-dropdown/collection-dropdown.component.html
+++ b/src/app/shared/collection-dropdown/collection-dropdown.component.html
@@ -11,14 +11,13 @@
\ No newline at end of file
+
+
diff --git a/src/app/shared/collection-dropdown/collection-dropdown.component.spec.ts b/src/app/shared/collection-dropdown/collection-dropdown.component.spec.ts
index f08df65ca4..612f5a1733 100644
--- a/src/app/shared/collection-dropdown/collection-dropdown.component.spec.ts
+++ b/src/app/shared/collection-dropdown/collection-dropdown.component.spec.ts
@@ -5,21 +5,16 @@ import { By } from '@angular/platform-browser';
import { getTestScheduler } from 'jasmine-marbles';
import { TestScheduler } from 'rxjs/testing';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
-import { of as observableOf } from 'rxjs';
import { CollectionDropdownComponent } from './collection-dropdown.component';
-import { RemoteData } from '../../core/data/remote-data';
-import { buildPaginatedList, PaginatedList } from '../../core/data/paginated-list.model';
-import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
+import { buildPaginatedList } from '../../core/data/paginated-list.model';
+import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
import { PageInfo } from '../../core/shared/page-info.model';
import { Collection } from '../../core/shared/collection.model';
import { CollectionDataService } from '../../core/data/collection-data.service';
import { TranslateLoaderMock } from '../mocks/translate-loader.mock';
import { Community } from '../../core/shared/community.model';
import { MockElementRef } from '../testing/element-ref.mock';
-import { FollowLinkConfig } from '../utils/follow-link-config.model';
-import { FindListOptions } from '../../core/data/request.models';
-import { Observable } from 'rxjs/internal/Observable';
const community: Community = Object.assign(new Community(), {
id: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88',
@@ -99,17 +94,6 @@ const listElementMock = {
}
};
-// tslint:disable-next-line: max-classes-per-file
-class CollectionDataServiceMock {
- getAuthorizedCollection(query: string, options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable>> {
- return observableOf(
- createSuccessfulRemoteDataObject(
- buildPaginatedList(new PageInfo(), collections)
- )
- );
- }
-}
-
describe('CollectionDropdownComponent', () => {
let component: CollectionDropdownComponent;
let componentAsAny: any;
@@ -117,12 +101,19 @@ describe('CollectionDropdownComponent', () => {
let scheduler: TestScheduler;
const collectionDataServiceMock: any = jasmine.createSpyObj('CollectionDataService', {
- getAuthorizedCollection: jasmine.createSpy('getAuthorizedCollection')
+ getAuthorizedCollection: jasmine.createSpy('getAuthorizedCollection'),
+ getAuthorizedCollectionByEntityType: jasmine.createSpy('getAuthorizedCollectionByEntityType')
});
const paginatedCollection = buildPaginatedList(new PageInfo(), collections);
const paginatedCollectionRD$ = createSuccessfulRemoteDataObject$(paginatedCollection);
+ const paginatedEmptyCollection = buildPaginatedList(new PageInfo(), []);
+ const paginatedEmptyCollectionRD$ = createSuccessfulRemoteDataObject$(paginatedEmptyCollection);
+
+ const paginatedOneElementCollection = buildPaginatedList(new PageInfo(), [collections[0]]);
+ const paginatedOneElementCollectionRD$ = createSuccessfulRemoteDataObject$(paginatedOneElementCollection);
+
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
@@ -150,6 +141,7 @@ describe('CollectionDropdownComponent', () => {
component = fixture.componentInstance;
componentAsAny = component;
componentAsAny.collectionDataService.getAuthorizedCollection.and.returnValue(paginatedCollectionRD$);
+ componentAsAny.collectionDataService.getAuthorizedCollectionByEntityType.and.returnValue(paginatedCollectionRD$);
});
it('should init component with collection list', () => {
@@ -225,4 +217,48 @@ describe('CollectionDropdownComponent', () => {
expect(component.hasNextPage).toEqual(true);
expect(component.searchListCollection).toEqual([]);
});
+
+ it('should invoke the method getAuthorizedCollectionByEntityType of CollectionDataService when entityType is set',() => {
+ component.entityType = 'rel';
+ scheduler.schedule(() => fixture.detectChanges());
+ scheduler.flush();
+ expect((component as any).collectionDataService.getAuthorizedCollectionByEntityType).toHaveBeenCalled();
+ });
+
+ it('should emit hasChoice true when totalElements is greater then one', () => {
+ spyOn(component.hasChoice, '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);
+ });
+
+ it('should emit theOnlySelectable when totalElements is equal to one', () => {
+
+ componentAsAny.collectionDataService.getAuthorizedCollection.and.returnValue(paginatedOneElementCollectionRD$);
+ componentAsAny.collectionDataService.getAuthorizedCollectionByEntityType.and.returnValue(paginatedOneElementCollectionRD$);
+
+ spyOn(component.theOnlySelectable, 'emit').and.callThrough();
+ component.ngOnInit();
+ fixture.detectChanges();
+
+ const expectedTheOnlySelectable = {
+ communities: [ { id: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88', name: 'Community 1', uuid: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88' } ],
+ collection: { id: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88', uuid: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88', name: 'Collection 1' }
+ };
+
+ expect(component.theOnlySelectable.emit).toHaveBeenCalledWith(expectedTheOnlySelectable);
+ });
});
diff --git a/src/app/shared/collection-dropdown/collection-dropdown.component.ts b/src/app/shared/collection-dropdown/collection-dropdown.component.ts
index c91ddbdb0a..6c11613512 100644
--- a/src/app/shared/collection-dropdown/collection-dropdown.component.ts
+++ b/src/app/shared/collection-dropdown/collection-dropdown.component.ts
@@ -4,6 +4,7 @@ import {
ElementRef,
EventEmitter,
HostListener,
+ Input,
OnDestroy,
OnInit,
Output
@@ -11,7 +12,7 @@ import {
import { FormControl } from '@angular/forms';
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
-import { debounceTime, distinctUntilChanged, map, mergeMap, reduce, startWith, switchMap } from 'rxjs/operators';
+import { debounceTime, distinctUntilChanged, map, mergeMap, reduce, startWith, switchMap, take } from 'rxjs/operators';
import { hasValue } from '../empty.util';
import { RemoteData } from '../../core/data/remote-data';
@@ -106,6 +107,21 @@ export class CollectionDropdownComponent implements OnInit, OnDestroy {
*/
currentQuery: string;
+ /**
+ * If present this value is used to filter collection list by entity type
+ */
+ @Input() entityType: string;
+
+ /**
+ * Emit to notify whether collections to choice from are more than one
+ */
+ @Output() hasChoice = new EventEmitter();
+
+ /**
+ * Emit to notify the only selectable collection.
+ */
+ @Output() theOnlySelectable = new EventEmitter();
+
constructor(
private changeDetectorRef: ChangeDetectorRef,
private collectionDataService: CollectionDataService,
@@ -190,14 +206,26 @@ export class CollectionDropdownComponent implements OnInit, OnDestroy {
elementsPerPage: 10,
currentPage: page
};
- this.searchListCollection$ = this.collectionDataService
- .getAuthorizedCollection(query, findOptions, true, false, followLink('parentCommunity'))
- .pipe(
+ let searchListService$: Observable>> = null;
+ if (this.entityType) {
+ searchListService$ = this.collectionDataService
+ .getAuthorizedCollectionByEntityType(
+ query,
+ this.entityType,
+ findOptions,
+ false,
+ followLink('parentCommunity'));
+ } else {
+ searchListService$ = this.collectionDataService
+ .getAuthorizedCollection(query, findOptions, true, false, followLink('parentCommunity'));
+ }
+ this.searchListCollection$ = searchListService$.pipe(
getFirstSucceededRemoteWithNotEmptyData(),
switchMap((collections: RemoteData>) => {
if ( (this.searchListCollection.length + findOptions.elementsPerPage) >= collections.payload.totalElements ) {
this.hasNextPage = false;
}
+ this.emitSelectionEvents(collections);
return collections.payload.page;
}),
mergeMap((collection: Collection) => collection.parentCommunity.pipe(
@@ -247,4 +275,28 @@ export class CollectionDropdownComponent implements OnInit, OnDestroy {
hideShowLoader(hideShow: boolean) {
this.isLoadingList.next(hideShow);
}
+
+ /**
+ * Emit events related to the number of selectable collections.
+ * hasChoice containing whether there are more then one selectable collections.
+ * theOnlySelectable containing the only collection available.
+ * @param collections
+ * @private
+ */
+ private emitSelectionEvents(collections: RemoteData>) {
+ this.hasChoice.emit(collections.payload.totalElements > 1);
+ if (collections.payload.totalElements === 1) {
+ const collection = collections.payload.page[0];
+ collections.payload.page[0].parentCommunity.pipe(
+ getFirstSucceededRemoteDataPayload(),
+ take(1)
+ ).subscribe((community: Community) => {
+ this.theOnlySelectable.emit({
+ communities: [{ id: community.id, name: community.name, uuid: community.id }],
+ collection: { id: collection.id, uuid: collection.id, name: collection.name }
+ });
+ });
+ }
+ }
+
}
diff --git a/src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.spec.ts b/src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.spec.ts
index 55634dbf7f..b46df8ff36 100644
--- a/src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.spec.ts
+++ b/src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.spec.ts
@@ -26,7 +26,8 @@ describe('AuthorizedCollectionSelectorComponent', () => {
id: 'authorized-collection'
});
collectionService = jasmine.createSpyObj('collectionService', {
- getAuthorizedCollection: createSuccessfulRemoteDataObject$(createPaginatedList([collection]))
+ getAuthorizedCollection: createSuccessfulRemoteDataObject$(createPaginatedList([collection])),
+ getAuthorizedCollectionByEntityType: createSuccessfulRemoteDataObject$(createPaginatedList([collection]))
});
notificationsService = jasmine.createSpyObj('notificationsService', ['error']);
TestBed.configureTestingModule({
@@ -49,12 +50,27 @@ describe('AuthorizedCollectionSelectorComponent', () => {
});
describe('search', () => {
- it('should call getAuthorizedCollection and return the authorized collection in a SearchResult', (done) => {
+ describe('when has no entity type', () => {
+ it('should call getAuthorizedCollection and return the authorized collection in a SearchResult', (done) => {
component.search('', 1).subscribe((resultRD) => {
- expect(collectionService.getAuthorizedCollection).toHaveBeenCalled();
+ expect(collectionService.getAuthorizedCollection).toHaveBeenCalled();
expect(resultRD.payload.page.length).toEqual(1);
expect(resultRD.payload.page[0].indexableObject).toEqual(collection);
- done();
+ done();
+ });
+ });
+ });
+
+ describe('when has entity type', () => {
+ it('should call getAuthorizedCollectionByEntityType and return the authorized collection in a SearchResult', (done) => {
+ component.entityType = 'test';
+ fixture.detectChanges();
+ component.search('', 1).subscribe((resultRD) => {
+ expect(collectionService.getAuthorizedCollectionByEntityType).toHaveBeenCalled();
+ expect(resultRD.payload.page.length).toEqual(1);
+ expect(resultRD.payload.page[0].indexableObject).toEqual(collection);
+ done();
+ });
});
});
});
diff --git a/src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.ts b/src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.ts
index bca1727542..b6aa0b3413 100644
--- a/src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.ts
+++ b/src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.ts
@@ -1,8 +1,8 @@
-import { Component } from '@angular/core';
+import { Component, Input } from '@angular/core';
import { DSOSelectorComponent } from '../dso-selector.component';
import { SearchService } from '../../../../core/shared/search/search.service';
import { CollectionDataService } from '../../../../core/data/collection-data.service';
-import { Observable } from 'rxjs/internal/Observable';
+import { Observable } from 'rxjs';
import { getFirstCompletedRemoteData } from '../../../../core/shared/operators';
import { map } from 'rxjs/operators';
import { CollectionSearchResult } from '../../../object-collection/shared/collection-search-result.model';
@@ -14,6 +14,8 @@ import { RemoteData } from '../../../../core/data/remote-data';
import { hasValue } from '../../../empty.util';
import { NotificationsService } from '../../../notifications/notifications.service';
import { TranslateService } from '@ngx-translate/core';
+import { Collection } from '../../../../core/shared/collection.model';
+import { FindListOptions } from '../../../../core/data/request.models';
@Component({
selector: 'ds-authorized-collection-selector',
@@ -24,6 +26,11 @@ import { TranslateService } from '@ngx-translate/core';
* Component rendering a list of collections to select from
*/
export class AuthorizedCollectionSelectorComponent extends DSOSelectorComponent {
+ /**
+ * If present this value is used to filter collection list by entity type
+ */
+ @Input() entityType: string;
+
constructor(protected searchService: SearchService,
protected collectionDataService: CollectionDataService,
protected notifcationsService: NotificationsService,
@@ -44,10 +51,23 @@ export class AuthorizedCollectionSelectorComponent extends DSOSelectorComponent
* @param page Page to retrieve
*/
search(query: string, page: number): Observable>>> {
- return this.collectionDataService.getAuthorizedCollection(query, Object.assign({
+ let searchListService$: Observable>> = null;
+ const findOptions: FindListOptions = {
currentPage: page,
elementsPerPage: this.defaultPagination.pageSize
- }),true, false, followLink('parentCommunity')).pipe(
+ };
+
+ if (this.entityType) {
+ searchListService$ = this.collectionDataService
+ .getAuthorizedCollectionByEntityType(
+ query,
+ this.entityType,
+ findOptions);
+ } else {
+ searchListService$ = this.collectionDataService
+ .getAuthorizedCollection(query, findOptions, true, false, followLink('parentCommunity'));
+ }
+ return searchListService$.pipe(
getFirstCompletedRemoteData(),
map((rd) => Object.assign(new RemoteData(null, null, null, null), rd, {
payload: hasValue(rd.payload) ? buildPaginatedList(rd.payload.pageInfo, rd.payload.page.map((col) => Object.assign(new CollectionSearchResult(), { indexableObject: col }))) : null,
diff --git a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.html
index 8761e4eb9e..5fccd58f48 100644
--- a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.html
+++ b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.html
@@ -6,6 +6,9 @@
{{header | translate}}
-
+
diff --git a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.spec.ts b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.spec.ts
index 3afb3c5e9a..90bd07c52b 100644
--- a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.spec.ts
+++ b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.spec.ts
@@ -69,4 +69,10 @@ describe('CreateItemParentSelectorComponent', () => {
expect(router.navigate).toHaveBeenCalledWith(['/submit'], { queryParams: { collection: collection.uuid } });
});
+ it('should call navigate on the router with entityType parameter', () => {
+ const entityType = 'Person';
+ component.entityType = entityType;
+ component.navigate(collection);
+ expect(router.navigate).toHaveBeenCalledWith(['/submit'], { queryParams: { collection: collection.uuid, entityType: entityType } });
+ });
});
diff --git a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts
index 03d7732fb0..b109be0af2 100644
--- a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts
+++ b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
import { DSpaceObjectType } from '../../../../core/shared/dspace-object-type.model';
import { DSpaceObject } from '../../../../core/shared/dspace-object.model';
@@ -22,6 +22,11 @@ export class CreateItemParentSelectorComponent extends DSOSelectorModalWrapperCo
action = SelectorActionType.CREATE;
header = 'dso-selector.create.item.sub-level';
+ /**
+ * If present this value is used to filter collection list by entity type
+ */
+ @Input() entityType: string;
+
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) {
super(activeModal, route);
}
@@ -35,6 +40,9 @@ export class CreateItemParentSelectorComponent extends DSOSelectorModalWrapperCo
['collection']: dso.uuid,
}
};
+ if (this.entityType) {
+ navigationExtras.queryParams.entityType = this.entityType;
+ }
this.router.navigate(['/submit'], navigationExtras);
}
}