-
diff --git a/src/app/submission/form/collection/submission-form-collection.component.spec.ts b/src/app/submission/form/collection/submission-form-collection.component.spec.ts
index 105d94b966..0132289266 100644
--- a/src/app/submission/form/collection/submission-form-collection.component.spec.ts
+++ b/src/app/submission/form/collection/submission-form-collection.component.spec.ts
@@ -1,14 +1,11 @@
-import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, DebugElement, SimpleChange } from '@angular/core';
+import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '@angular/core';
import { async, ComponentFixture, fakeAsync, inject, TestBed, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
-import { of as observableOf } from 'rxjs';
-import { filter } from 'rxjs/operators';
import { TranslateModule } from '@ngx-translate/core';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { Store } from '@ngrx/store';
-import { cold } from 'jasmine-marbles';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub';
import { mockSubmissionId, mockSubmissionRestResponse } from '../../../shared/mocks/submission.mock';
@@ -19,172 +16,13 @@ import { SubmissionJsonPatchOperationsService } from '../../../core/submission/s
import { SubmissionJsonPatchOperationsServiceStub } from '../../../shared/testing/submission-json-patch-operations-service.stub';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
-import { RemoteData } from '../../../core/data/remote-data';
-import { Community } from '../../../core/shared/community.model';
-import { PaginatedList } from '../../../core/data/paginated-list';
-import { PageInfo } from '../../../core/shared/page-info.model';
-import { Collection } from '../../../core/shared/collection.model';
import { createTestComponent } from '../../../shared/testing/utils.test';
import { CollectionDataService } from '../../../core/data/collection-data.service';
-
-const subcommunities = [Object.assign(new Community(), {
- name: 'SubCommunity 1',
- id: '123456789-1',
- metadata: [
- {
- key: 'dc.title',
- language: 'en_US',
- value: 'SubCommunity 1'
- }]
-}),
- Object.assign(new Community(), {
- name: 'SubCommunity 1',
- id: '123456789s-1',
- metadata: [
- {
- key: 'dc.title',
- language: 'en_US',
- value: 'SubCommunity 1'
- }]
- })
-];
-
-const mockCommunity1Collection1 = Object.assign(new Collection(), {
- name: 'Community 1-Collection 1',
- id: '1234567890-1',
- metadata: [
- {
- key: 'dc.title',
- language: 'en_US',
- value: 'Community 1-Collection 1'
- }]
-});
-
-const mockCommunity1Collection2 = Object.assign(new Collection(), {
- name: 'Community 1-Collection 2',
- id: '1234567890-2',
- metadata: [
- {
- key: 'dc.title',
- language: 'en_US',
- value: 'Community 1-Collection 2'
- }]
-});
-
-const mockCommunity2Collection1 = Object.assign(new Collection(), {
- name: 'Community 2-Collection 1',
- id: '1234567890-3',
- metadata: [
- {
- key: 'dc.title',
- language: 'en_US',
- value: 'Community 2-Collection 1'
- }]
-});
-
-const mockCommunity2Collection2 = Object.assign(new Collection(), {
- name: 'Community 2-Collection 2',
- id: '1234567890-4',
- metadata: [
- {
- key: 'dc.title',
- language: 'en_US',
- value: 'Community 2-Collection 2'
- }]
-});
-
-const mockCommunity = Object.assign(new Community(), {
- name: 'Community 1',
- id: '123456789-1',
- metadata: [
- {
- key: 'dc.title',
- language: 'en_US',
- value: 'Community 1'
- }],
- collections: observableOf(new RemoteData(true, true, true,
- undefined, new PaginatedList(new PageInfo(), [mockCommunity1Collection1, mockCommunity1Collection2]))),
- subcommunities: observableOf(new RemoteData(true, true, true,
- undefined, new PaginatedList(new PageInfo(), subcommunities))),
-});
-
-const mockCommunity2 = Object.assign(new Community(), {
- name: 'Community 2',
- id: '123456789-2',
- metadata: [
- {
- key: 'dc.title',
- language: 'en_US',
- value: 'Community 2'
- }],
- collections: observableOf(new RemoteData(true, true, true,
- undefined, new PaginatedList(new PageInfo(), [mockCommunity2Collection1, mockCommunity2Collection2]))),
- subcommunities: observableOf(new RemoteData(true, true, true,
- undefined, new PaginatedList(new PageInfo(), []))),
-});
-
-const mockCommunity1Collection1Rd = observableOf(new RemoteData(true, true, true,
- undefined, mockCommunity1Collection1));
-
-const mockCommunityList = observableOf(new RemoteData(true, true, true,
- undefined, new PaginatedList(new PageInfo(), [mockCommunity, mockCommunity2])));
-
-const mockCommunityCollectionList = observableOf(new RemoteData(true, true, true,
- undefined, new PaginatedList(new PageInfo(), [mockCommunity1Collection1, mockCommunity1Collection2])));
-
-const mockCommunity2CollectionList = observableOf(new RemoteData(true, true, true,
- undefined, new PaginatedList(new PageInfo(), [mockCommunity2Collection1, mockCommunity2Collection2])));
-
-const mockCollectionList = [
- {
- communities: [
- {
- id: '123456789-1',
- name: 'Community 1'
- }
- ],
- collection: {
- id: '1234567890-1',
- name: 'Community 1-Collection 1'
- }
- },
- {
- communities: [
- {
- id: '123456789-1',
- name: 'Community 1'
- }
- ],
- collection: {
- id: '1234567890-2',
- name: 'Community 1-Collection 2'
- }
- },
- {
- communities: [
- {
- id: '123456789-2',
- name: 'Community 2'
- }
- ],
- collection: {
- id: '1234567890-3',
- name: 'Community 2-Collection 1'
- }
- },
- {
- communities: [
- {
- id: '123456789-2',
- name: 'Community 2'
- }
- ],
- collection: {
- id: '1234567890-4',
- name: 'Community 2-Collection 2'
- }
- }
-];
+import { hot, cold } from 'jasmine-marbles';
+import { of } from 'rxjs';
+import { SectionsService } from '../../sections/sections.service';
+import { componentFactoryName } from '@angular/compiler';
+import { Collection } from 'src/app/core/shared/collection.model';
describe('SubmissionFormCollectionComponent Component', () => {
@@ -198,7 +36,57 @@ describe('SubmissionFormCollectionComponent Component', () => {
const collectionId = '1234567890-1';
const definition = 'traditional';
const submissionRestResponse = mockSubmissionRestResponse;
- const searchedCollection = 'Community 2-Collection 2';
+
+ const mockCollectionList = [
+ {
+ communities: [
+ {
+ id: '123456789-1',
+ name: 'Community 1'
+ }
+ ],
+ collection: {
+ id: '1234567890-1',
+ name: 'Community 1-Collection 1'
+ }
+ },
+ {
+ communities: [
+ {
+ id: '123456789-1',
+ name: 'Community 1'
+ }
+ ],
+ collection: {
+ id: '1234567890-2',
+ name: 'Community 1-Collection 2'
+ }
+ },
+ {
+ communities: [
+ {
+ id: '123456789-2',
+ name: 'Community 2'
+ }
+ ],
+ collection: {
+ id: '1234567890-3',
+ name: 'Community 2-Collection 1'
+ }
+ },
+ {
+ communities: [
+ {
+ id: '123456789-2',
+ name: 'Community 2'
+ }
+ ],
+ collection: {
+ id: '1234567890-4',
+ name: 'Community 2-Collection 2'
+ }
+ }
+ ];
const communityDataService: any = jasmine.createSpyObj('communityDataService', {
findAll: jasmine.createSpy('findAll')
@@ -217,6 +105,10 @@ describe('SubmissionFormCollectionComponent Component', () => {
replace: jasmine.createSpy('replace')
});
+ const sectionsService: any = jasmine.createSpyObj('sectionsService', {
+ isSectionAvailable: of(true)
+ });
+
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
@@ -236,6 +128,7 @@ describe('SubmissionFormCollectionComponent Component', () => {
{ provide: CommunityDataService, useValue: communityDataService },
{ provide: JsonPatchOperationsBuilder, useValue: jsonPatchOpBuilder },
{ provide: Store, useValue: store },
+ { provide: SectionsService, useValue: sectionsService },
ChangeDetectorRef,
SubmissionFormCollectionComponent
],
@@ -299,72 +192,11 @@ describe('SubmissionFormCollectionComponent Component', () => {
expect(compAsAny.pathCombiner).toEqual(expected);
});
- it('should init collection list properly', () => {
- communityDataService.findAll.and.returnValue(mockCommunityList);
- collectionDataService.findById.and.returnValue(mockCommunity1Collection1Rd);
- collectionDataService.getAuthorizedCollectionByCommunity.and.returnValues(mockCommunityCollectionList, mockCommunity2CollectionList);
-
- comp.ngOnChanges({
- currentCollectionId: new SimpleChange(null, collectionId, true)
- });
-
- expect(comp.searchListCollection$).toBeObservable(cold('(ab)', {
- a: [],
- b: mockCollectionList
- }));
-
- expect(comp.selectedCollectionName$).toBeObservable(cold('(a|)', {
- a: 'Community 1-Collection 1'
- }));
- });
-
- it('should show only the searched collection', () => {
- comp.searchListCollection$ = observableOf(mockCollectionList);
- fixture.detectChanges();
-
- comp.searchField.setValue(searchedCollection);
- fixture.detectChanges();
-
- comp.searchListCollection$.pipe(
- filter(() => !comp.disabled$.getValue())
- ).subscribe((list) => {
- expect(list).toEqual([mockCollectionList[3]]);
- });
-
- });
-
- it('should emit collectionChange event when selecting a new collection', () => {
- spyOn(comp.searchField, 'reset').and.callThrough();
- spyOn(comp.collectionChange, 'emit').and.callThrough();
- jsonPatchOpServiceStub.jsonPatchByResourceID.and.returnValue(observableOf(submissionRestResponse));
- comp.ngOnInit();
- comp.onSelect(mockCollectionList[1]);
- fixture.detectChanges();
-
- expect(comp.searchField.reset).toHaveBeenCalled();
- expect(comp.collectionChange.emit).toHaveBeenCalledWith(submissionRestResponse[0] as any);
- expect(submissionServiceStub.changeSubmissionCollection).toHaveBeenCalled();
- expect(comp.selectedCollectionId).toBe(mockCollectionList[1].collection.id);
- expect(comp.selectedCollectionName$).toBeObservable(cold('(a|)', {
- a: mockCollectionList[1].collection.name
- }));
-
- });
-
- it('should reset searchField when dropdown menu has been closed', () => {
- spyOn(comp.searchField, 'reset').and.callThrough();
- comp.toggled(false);
-
- expect(comp.searchField.reset).toHaveBeenCalled();
- });
-
describe('', () => {
let dropdowBtn: DebugElement;
let dropdownMenu: DebugElement;
beforeEach(() => {
-
- comp.searchListCollection$ = observableOf(mockCollectionList);
fixture.detectChanges();
dropdowBtn = fixture.debugElement.query(By.css('#collectionControlsMenuButton'));
dropdownMenu = fixture.debugElement.query(By.css('#collectionControlsDropdownMenu'));
@@ -387,49 +219,46 @@ describe('SubmissionFormCollectionComponent Component', () => {
fixture.whenStable().then(() => {
expect(comp.onClose).toHaveBeenCalled();
expect(dropdownMenu.nativeElement.classList).toContain('show');
- expect(dropdownMenu.queryAll(By.css('.collection-item')).length).toBe(4);
});
}));
- it('should trigger onSelect method when select a new collection from dropdown menu', fakeAsync(() => {
+ it('the dropdown menu should be enable', () => {
+ const dropDown = fixture.debugElement.query(By.css('#collectionControlsDropdownMenu'));
+ expect(dropDown).toBeTruthy();
+ });
- spyOn(comp, 'onSelect');
- dropdowBtn.triggerEventHandler('click', null);
- tick();
+ it('the dropdown menu should be disabled', () => {
+ comp.available$ = of(false);
+ fixture.detectChanges();
+ const dropDown = fixture.debugElement.query(By.css('#collectionControlsDropdownMenu'));
+ expect(dropDown).toBeFalsy();
+ });
+
+ it('should be simulated when the drop-down menu is closed', () => {
+ spyOn(comp, 'onClose');
+ comp.onClose();
+ expect(comp.onClose).toHaveBeenCalled();
+ });
+
+ it('should be simulated when the drop-down menu is toggled', () => {
+ spyOn(comp, 'toggled');
+ comp.toggled(false);
+ expect(comp.toggled).toHaveBeenCalled();
+ });
+
+ it('should ', () => {
+ spyOn(comp.collectionChange, 'emit').and.callThrough();
+ jsonPatchOpServiceStub.jsonPatchByResourceID.and.returnValue(of(submissionRestResponse));
+ comp.ngOnInit();
+ comp.onSelect(mockCollectionList[1]);
fixture.detectChanges();
- const secondLink: DebugElement = dropdownMenu.query(By.css('.collection-item:nth-child(2)'));
- secondLink.triggerEventHandler('click', null);
- tick();
- fixture.detectChanges();
-
- fixture.whenStable().then(() => {
-
- expect(comp.onSelect).toHaveBeenCalled();
- });
- }));
-
- it('should update searchField on input type', fakeAsync(() => {
-
- dropdowBtn.triggerEventHandler('click', null);
- tick();
- fixture.detectChanges();
-
- fixture.whenStable().then(() => {
- const input = fixture.debugElement.query(By.css('input.form-control'));
- const el = input.nativeElement;
-
- expect(el.value).toBe('');
-
- el.value = searchedCollection;
- el.dispatchEvent(new Event('input'));
-
- fixture.detectChanges();
-
- expect(fixture.componentInstance.searchField.value).toEqual(searchedCollection);
- });
- }));
-
+ expect(submissionServiceStub.changeSubmissionCollection).toHaveBeenCalled();
+ expect(comp.selectedCollectionId).toBe(mockCollectionList[1].collection.id);
+ expect(comp.selectedCollectionName$).toBeObservable(cold('(a|)', {
+ a: mockCollectionList[1].collection.name
+ }));
+ });
});
});
diff --git a/src/app/submission/form/collection/submission-form-collection.component.ts b/src/app/submission/form/collection/submission-form-collection.component.ts
index f84764d6a4..6517be7101 100644
--- a/src/app/submission/form/collection/submission-form-collection.component.ts
+++ b/src/app/submission/form/collection/submission-form-collection.component.ts
@@ -7,52 +7,28 @@ import {
OnChanges,
OnInit,
Output,
- SimpleChanges
+ SimpleChanges,
+ ViewChild
} from '@angular/core';
-import { FormControl } from '@angular/forms';
-import { BehaviorSubject, combineLatest, Observable, of as observableOf, Subscription } from 'rxjs';
+import { BehaviorSubject, Observable, of as observableOf, Subscription } from 'rxjs';
import {
- debounceTime,
- distinctUntilChanged,
- filter,
find,
- flatMap,
- map,
- mergeMap,
- reduce,
- startWith
+ map
} from 'rxjs/operators';
import { Collection } from '../../../core/shared/collection.model';
import { CommunityDataService } from '../../../core/data/community-data.service';
-import { Community } from '../../../core/shared/community.model';
-import { hasValue, isEmpty, isNotEmpty } from '../../../shared/empty.util';
+import { hasValue, isNotEmpty } from '../../../shared/empty.util';
import { RemoteData } from '../../../core/data/remote-data';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
-import { PaginatedList } from '../../../core/data/paginated-list';
import { SubmissionService } from '../../submission.service';
import { SubmissionObject } from '../../../core/submission/models/submission-object.model';
import { SubmissionJsonPatchOperationsService } from '../../../core/submission/submission-json-patch-operations.service';
import { CollectionDataService } from '../../../core/data/collection-data.service';
-import { FindListOptions } from '../../../core/data/request.models';
-
-/**
- * An interface to represent a collection entry
- */
-interface CollectionListEntryItem {
- id: string;
- name: string;
-}
-
-/**
- * An interface to represent an entry in the collection list
- */
-interface CollectionListEntry {
- communities: CollectionListEntryItem[],
- collection: CollectionListEntryItem
-}
+import { CollectionDropdownComponent } from 'src/app/shared/collection-dropdown/collection-dropdown.component';
+import { SectionsService } from '../../sections/sections.service';
/**
* This component allows to show the current collection the submission belonging to and to change it.
@@ -88,30 +64,12 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
*/
@Output() collectionChange: EventEmitter
= new EventEmitter();
- /**
- * A boolean representing if this dropdown button is disabled
- * @type {BehaviorSubject}
- */
- public disabled$ = new BehaviorSubject(true);
-
/**
* A boolean representing if a collection change operation is processing
* @type {BehaviorSubject}
*/
public processingChange$ = new BehaviorSubject(false);
- /**
- * The search form control
- * @type {FormControl}
- */
- public searchField: FormControl = new FormControl();
-
- /**
- * The collection list obtained from a search
- * @type {Observable}
- */
- public searchListCollection$: Observable;
-
/**
* The selected collection id
* @type {string}
@@ -130,24 +88,23 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
*/
protected pathCombiner: JsonPatchOperationPathCombiner;
- /**
- * A boolean representing if dropdown list is scrollable to the bottom
- * @type {boolean}
- */
- private scrollableBottom = false;
-
- /**
- * A boolean representing if dropdown list is scrollable to the top
- * @type {boolean}
- */
- private scrollableTop = false;
-
/**
* Array to track all subscriptions and unsubscribe them onDestroy
* @type {Array}
*/
private subs: Subscription[] = [];
+ /**
+ * The html child that contains the collections list
+ */
+ @ViewChild(CollectionDropdownComponent, {static: false}) collectionDropdown: CollectionDropdownComponent;
+
+ /**
+ * A boolean representing if the collection section is available
+ * @type {BehaviorSubject}
+ */
+ available$: Observable;
+
/**
* Initialize instance variables
*
@@ -159,37 +116,11 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
* @param {SubmissionService} submissionService
*/
constructor(protected cdr: ChangeDetectorRef,
- private communityDataService: CommunityDataService,
private collectionDataService: CollectionDataService,
private operationsBuilder: JsonPatchOperationsBuilder,
private operationsService: SubmissionJsonPatchOperationsService,
- private submissionService: SubmissionService) {
- }
-
- /**
- * Method called on mousewheel event, it prevent the page scroll
- * when arriving at the top/bottom of dropdown menu
- *
- * @param event
- * mousewheel event
- */
- @HostListener('mousewheel', ['$event']) onMousewheel(event) {
- if (event.wheelDelta > 0 && this.scrollableTop) {
- event.preventDefault();
- }
- if (event.wheelDelta < 0 && this.scrollableBottom) {
- event.preventDefault();
- }
- }
-
- /**
- * Check if dropdown scrollbar is at the top or bottom of the dropdown list
- *
- * @param event
- */
- onScroll(event) {
- this.scrollableBottom = (event.target.scrollTop + event.target.clientHeight === event.target.scrollHeight);
- this.scrollableTop = (event.target.scrollTop === 0);
+ private submissionService: SubmissionService,
+ private sectionsService: SectionsService) {
}
/**
@@ -204,51 +135,6 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
find((collectionRD: RemoteData) => isNotEmpty(collectionRD.payload)),
map((collectionRD: RemoteData) => collectionRD.payload.name)
);
-
- const findOptions: FindListOptions = {
- elementsPerPage: 1000
- };
-
- // Retrieve collection list only when is the first change
- if (changes.currentCollectionId.isFirstChange()) {
- // @TODO replace with search/top browse endpoint
- // @TODO implement community/subcommunity hierarchy
- const communities$ = this.communityDataService.findAll(findOptions).pipe(
- find((communities: RemoteData>) => isNotEmpty(communities.payload)),
- mergeMap((communities: RemoteData>) => communities.payload.page));
-
- const listCollection$ = communities$.pipe(
- flatMap((communityData: Community) => {
- return this.collectionDataService.getAuthorizedCollectionByCommunity(communityData.uuid, findOptions).pipe(
- find((collections: RemoteData>) => !collections.isResponsePending && collections.hasSucceeded),
- mergeMap((collections: RemoteData>) => collections.payload.page),
- filter((collectionData: Collection) => isNotEmpty(collectionData)),
- map((collectionData: Collection) => ({
- communities: [{ id: communityData.id, name: communityData.name }],
- collection: { id: collectionData.id, name: collectionData.name }
- }))
- );
- }),
- reduce((acc: any, value: any) => [...acc, ...value], []),
- startWith([])
- );
-
- const searchTerm$ = this.searchField.valueChanges.pipe(
- debounceTime(200),
- distinctUntilChanged(),
- startWith('')
- );
-
- this.searchListCollection$ = combineLatest(searchTerm$, listCollection$).pipe(
- map(([searchTerm, listCollection]) => {
- this.disabled$.next(isEmpty(listCollection));
- if (isEmpty(searchTerm)) {
- return listCollection;
- } else {
- return listCollection.filter((v) => v.collection.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1).slice(0, 5);
- }
- }));
- }
}
}
@@ -257,6 +143,7 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
*/
ngOnInit() {
this.pathCombiner = new JsonPatchOperationPathCombiner('sections', 'collection');
+ this.available$ = this.sectionsService.isSectionAvailable(this.submissionId, 'collection');
}
/**
@@ -273,7 +160,6 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
* the selected [CollectionListEntryItem]
*/
onSelect(event) {
- this.searchField.reset();
this.processingChange$.next(true);
this.operationsBuilder.replace(this.pathCombiner.getPath(), event.collection.id, true);
this.subs.push(this.operationsService.jsonPatchByResourceID(
@@ -296,7 +182,7 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
* Reset search form control on dropdown menu close
*/
onClose() {
- this.searchField.reset();
+ this.collectionDropdown.reset();
}
/**
@@ -307,7 +193,7 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
*/
toggled(isOpen: boolean) {
if (!isOpen) {
- this.searchField.reset();
+ this.collectionDropdown.reset();
}
}
}