diff --git a/src/app/+import-external-page/import-external-page.component.ts b/src/app/+import-external-page/import-external-page.component.ts
index c205482cb3..00709dad16 100644
--- a/src/app/+import-external-page/import-external-page.component.ts
+++ b/src/app/+import-external-page/import-external-page.component.ts
@@ -1,4 +1,4 @@
-import { Component, Injector, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
/**
* Component representing the external import page of the submission.
diff --git a/src/app/+import-external-page/import-external-page.module.ts b/src/app/+import-external-page/import-external-page.module.ts
index c81e80615f..8dae7c2f88 100644
--- a/src/app/+import-external-page/import-external-page.module.ts
+++ b/src/app/+import-external-page/import-external-page.module.ts
@@ -4,8 +4,6 @@ import { NgModule } from '@angular/core';
import { SharedModule } from '../shared/shared.module';
import { CoreModule } from '../core/core.module';
import { ImportExternalRoutingModule } from './import-external-routing.module';
-import { SubmissionImportExternalComponent } from '../submission/import-external/submission-import-external.component';
-import { SubmissionImportExternalSearchbarComponent } from '../submission/import-external/import-external-searchbar/submission-import-external-searchbar.component';
import { SubmissionModule } from '../submission/submission.module';
@NgModule({
diff --git a/src/app/shared/collection-dropdown/collection-dropdown.component.ts b/src/app/shared/collection-dropdown/collection-dropdown.component.ts
index 0e9a4ab629..49af24ad3d 100644
--- a/src/app/shared/collection-dropdown/collection-dropdown.component.ts
+++ b/src/app/shared/collection-dropdown/collection-dropdown.component.ts
@@ -24,7 +24,7 @@ interface CollectionListEntryItem {
/**
* An interface to represent an entry in the collection list
*/
-interface CollectionListEntry {
+export interface CollectionListEntry {
communities: CollectionListEntryItem[],
collection: CollectionListEntryItem
}
diff --git a/src/app/shared/mocks/external-source.service.mock.ts b/src/app/shared/mocks/external-source.service.mock.ts
index 80e40512c5..4edf9efb14 100644
--- a/src/app/shared/mocks/external-source.service.mock.ts
+++ b/src/app/shared/mocks/external-source.service.mock.ts
@@ -1,12 +1,59 @@
-// import { ExternalSourceService } from '../../core/data/external-source.service';
+import { ExternalSourceService } from '../../core/data/external-source.service';
+import { ExternalSource } from '../../core/shared/external-source.model';
+import { ResourceType } from '../../core/shared/resource-type';
+
+export const externalSourceOrcid: ExternalSource = {
+ type: new ResourceType('externalsource'),
+ id: 'orcid',
+ name: 'orcid',
+ hierarchical: false,
+ _links: {
+ entries: {
+ href: "https://dspace7.4science.cloud/server/api/integration/externalsources/orcid/entries"
+ },
+ self: {
+ href: "https://dspace7.4science.cloud/server/api/integration/externalsources/orcid"
+ }
+ }
+};
+
+export const externalSourceCiencia: ExternalSource = {
+ type: new ResourceType('externalsource'),
+ id: 'ciencia',
+ name: 'ciencia',
+ hierarchical: false,
+ _links: {
+ entries: {
+ href: "https://dspace7.4science.cloud/server/api/integration/externalsources/ciencia/entries"
+ },
+ self: {
+ href: "https://dspace7.4science.cloud/server/api/integration/externalsources/ciencia"
+ }
+ }
+};
+
+export const externalSourceMyStaffDb: ExternalSource = {
+ type: new ResourceType('externalsource'),
+ id: 'my_staff_db',
+ name: 'my_staff_db',
+ hierarchical: false,
+ _links: {
+ entries: {
+ href: "https://dspace7.4science.cloud/server/api/integration/externalsources/my_staff_db/entries"
+ },
+ self: {
+ href: "https://dspace7.4science.cloud/server/api/integration/externalsources/my_staff_db"
+ }
+ }
+};
/**
* Mock for [[ExternalSourceService]]
*/
-/*export function getMockExternalSourceService():
+export function getMockExternalSourceService():
ExternalSourceService {
return jasmine.createSpyObj('ExternalSourceService', {
getAllExternalSources: jasmine.createSpy('getAllExternalSources'),
getExternalSourceEntries: jasmine.createSpy('getExternalSourceEntries'),
});
-}*/
+}
diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts
index 8ef3f91257..e83e1179f6 100644
--- a/src/app/shared/shared.module.ts
+++ b/src/app/shared/shared.module.ts
@@ -461,7 +461,8 @@ const ENTRY_COMPONENTS = [
ClaimedTaskActionsApproveComponent,
ClaimedTaskActionsRejectComponent,
ClaimedTaskActionsReturnToPoolComponent,
- ClaimedTaskActionsEditMetadataComponent
+ ClaimedTaskActionsEditMetadataComponent,
+ CollectionDropdownComponent
];
const SHARED_ITEM_PAGE_COMPONENTS = [
diff --git a/src/app/shared/testing/submission-service.stub.ts b/src/app/shared/testing/submission-service.stub.ts
index a330fa3eee..35c3ddfee0 100644
--- a/src/app/shared/testing/submission-service.stub.ts
+++ b/src/app/shared/testing/submission-service.stub.ts
@@ -2,6 +2,7 @@ export class SubmissionServiceStub {
changeSubmissionCollection = jasmine.createSpy('changeSubmissionCollection');
createSubmission = jasmine.createSpy('createSubmission');
+ createSubmissionFromExternalSource = jasmine.createSpy('createSubmissionFromExternalSource');
depositSubmission = jasmine.createSpy('depositSubmission');
discardSubmission = jasmine.createSpy('discardSubmission');
dispatchInit = jasmine.createSpy('dispatchInit');
diff --git a/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.html b/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.html
new file mode 100644
index 0000000000..73b41378c8
--- /dev/null
+++ b/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.html
@@ -0,0 +1,11 @@
+
diff --git a/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.scss b/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.scss
new file mode 100644
index 0000000000..1a70081367
--- /dev/null
+++ b/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.scss
@@ -0,0 +1,3 @@
+.close:focus {
+ outline: none !important;
+}
diff --git a/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.spec.ts b/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.spec.ts
new file mode 100644
index 0000000000..5002c4f94a
--- /dev/null
+++ b/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.spec.ts
@@ -0,0 +1,89 @@
+import { Component, NO_ERRORS_SCHEMA, EventEmitter } from '@angular/core';
+import { async, TestBed, ComponentFixture, inject } from '@angular/core/testing';
+import { TranslateModule } from '@ngx-translate/core';
+import { createTestComponent } from '../../../shared/testing/utils.test';
+import { SubmissionImportExternalCollectionComponent } from './submission-import-external-collection.component';
+import { CollectionListEntry } from '../../../shared/collection-dropdown/collection-dropdown.component';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+
+describe('SubmissionImportExternalCollectionComponent test suite', () => {
+ let comp: SubmissionImportExternalCollectionComponent;
+ let compAsAny: any;
+ let fixture: ComponentFixture;
+
+ beforeEach(async (() => {
+ TestBed.configureTestingModule({
+ imports: [
+ TranslateModule.forRoot(),
+ ],
+ declarations: [
+ SubmissionImportExternalCollectionComponent,
+ TestComponent,
+ ],
+ providers: [
+ NgbActiveModal,
+ SubmissionImportExternalCollectionComponent
+ ],
+ schemas: [NO_ERRORS_SCHEMA]
+ }).compileComponents().then();
+ }));
+
+ // First test to check the correct component creation
+ describe('', () => {
+ let testComp: TestComponent;
+ let testFixture: ComponentFixture;
+
+ // synchronous beforeEach
+ beforeEach(() => {
+ const html = `
+ `;
+ testFixture = createTestComponent(html, TestComponent) as ComponentFixture;
+ testComp = testFixture.componentInstance;
+ });
+
+ afterEach(() => {
+ testFixture.destroy();
+ });
+
+ it('should create SubmissionImportExternalCollectionComponent', inject([SubmissionImportExternalCollectionComponent], (app: SubmissionImportExternalCollectionComponent) => {
+ expect(app).toBeDefined();
+ }));
+ });
+
+ describe('', () => {
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SubmissionImportExternalCollectionComponent);
+ comp = fixture.componentInstance;
+ compAsAny = comp;
+ });
+
+ afterEach(() => {
+ fixture.destroy();
+ comp = null;
+ compAsAny = null;
+ });
+
+ it('The variable \'selectedEvent\' should be assigned', () => {
+ const event = new EventEmitter();
+ comp.selectObject(event);
+
+ expect(comp.selectedEvent).toEqual(event);
+ });
+
+ it('The variable \'selectedEvent\' should be assigned', () => {
+ spyOn(compAsAny.activeModal, 'dismiss');
+ comp.closeCollectionModal();
+
+ expect(compAsAny.activeModal.dismiss).toHaveBeenCalled();
+ });
+ });
+});
+
+// declare a test component
+@Component({
+ selector: 'ds-test-cmp',
+ template: ``
+})
+class TestComponent {
+
+}
diff --git a/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.ts b/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.ts
new file mode 100644
index 0000000000..cbac0cb710
--- /dev/null
+++ b/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.ts
@@ -0,0 +1,40 @@
+import { Component, Output, EventEmitter } from '@angular/core';
+import { CollectionListEntry } from '../../../shared/collection-dropdown/collection-dropdown.component';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+
+/**
+ * Wrap component for 'ds-collection-dropdown'.
+ */
+@Component({
+ selector: 'ds-submission-import-external-collection',
+ styleUrls: ['./submission-import-external-collection.component.scss'],
+ templateUrl: './submission-import-external-collection.component.html'
+})
+export class SubmissionImportExternalCollectionComponent {
+ /**
+ * The event passed by 'ds-collection-dropdown'.
+ */
+ @Output() public selectedEvent = new EventEmitter();
+
+ /**
+ * Initialize the component variables.
+ * @param {NgbActiveModal} activeModal
+ */
+ constructor(
+ private activeModal: NgbActiveModal
+ ) { }
+
+ /**
+ * This method populates the 'selectedEvent' variable.
+ */
+ public selectObject(event): void {
+ this.selectedEvent.emit(event);
+ }
+
+ /**
+ * This method closes the modal.
+ */
+ public closeCollectionModal(): void {
+ this.activeModal.dismiss(false);
+ }
+}
diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html
index 29f1804f1f..0f155286ce 100644
--- a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html
+++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html
@@ -30,9 +30,9 @@
diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts
new file mode 100644
index 0000000000..66dfc72e6b
--- /dev/null
+++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts
@@ -0,0 +1,153 @@
+import { Component, NO_ERRORS_SCHEMA } from '@angular/core';
+import { async, TestBed, ComponentFixture, inject } from '@angular/core/testing';
+import { TranslateModule } from '@ngx-translate/core';
+import { Router } from '@angular/router';
+import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { of as observableOf, of } from 'rxjs/internal/observable/of';
+import { SubmissionImportExternalPreviewComponent } from './submission-import-external-preview.component';
+import { NotificationsService } from '../../../shared/notifications/notifications.service';
+import { RouterStub } from '../../../shared/testing/router.stub';
+import { SubmissionService } from '../../submission.service';
+import { createTestComponent } from '../../../shared/testing/utils.test';
+import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub';
+import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
+import { ExternalSourceEntry } from '../../../core/shared/external-source-entry.model';
+import { Metadata } from '../../../core/shared/metadata.utils';
+import { SubmissionImportExternalCollectionComponent } from '../import-external-collection/submission-import-external-collection.component';
+import { CollectionListEntry } from '../../../shared/collection-dropdown/collection-dropdown.component';
+
+describe('SubmissionImportExternalPreviewComponent test suite', () => {
+ let comp: SubmissionImportExternalPreviewComponent;
+ let compAsAny: any;
+ let fixture: ComponentFixture;
+ let submissionServiceStub: SubmissionServiceStub;
+ const externalEntry = Object.assign(new ExternalSourceEntry(), {
+ id: '0001-0001-0001-0001',
+ display: 'John Doe',
+ value: 'John, Doe',
+ metadata: {
+ 'dc.identifier.uri': [
+ {
+ value: 'https://orcid.org/0001-0001-0001-0001'
+ }
+ ]
+ },
+ _links: { self: { href: 'http://test-rest.com/server/api/integration/externalSources/orcidV2/entryValues/0000-0003-4851-8004' } }
+ });
+
+ beforeEach(async (() => {
+ TestBed.configureTestingModule({
+ imports: [
+ TranslateModule.forRoot()
+ ],
+ declarations: [
+ SubmissionImportExternalPreviewComponent,
+ TestComponent
+ ],
+ providers: [
+ { provide: Router, useValue: new RouterStub() },
+ { provide: SubmissionService, useValue: new SubmissionServiceStub() },
+ { provide: NotificationsService, useValue: new NotificationsServiceStub() },
+ NgbModal,
+ NgbActiveModal,
+ SubmissionImportExternalPreviewComponent
+ ],
+ schemas: [NO_ERRORS_SCHEMA]
+ }).compileComponents().then();
+ }));
+
+ // First test to check the correct component creation
+ describe('', () => {
+ let testComp: TestComponent;
+ let testFixture: ComponentFixture;
+
+ // synchronous beforeEach
+ beforeEach(() => {
+ const html = `
+ `;
+ testFixture = createTestComponent(html, TestComponent) as ComponentFixture;
+ testComp = testFixture.componentInstance;
+ });
+
+ afterEach(() => {
+ testFixture.destroy();
+ });
+
+ it('should create SubmissionImportExternalComponent', inject([SubmissionImportExternalPreviewComponent], (app: SubmissionImportExternalPreviewComponent) => {
+ expect(app).toBeDefined();
+ }));
+ });
+
+ describe('', () => {
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SubmissionImportExternalPreviewComponent);
+ comp = fixture.componentInstance;
+ compAsAny = comp;
+ submissionServiceStub = TestBed.get(SubmissionService);
+ });
+
+ afterEach(() => {
+ fixture.destroy();
+ comp = null;
+ compAsAny = null;
+ });
+
+ it('Should init component properly', () => {
+ comp.externalSourceEntry = externalEntry;
+ const expected = [
+ { key: 'dc.identifier.uri', value: Metadata.first(comp.externalSourceEntry.metadata, 'dc.identifier.uri') }
+ ];
+ comp.ngOnInit();
+ fixture.detectChanges();
+
+ expect(comp.metadataList).toEqual(expected);
+ });
+
+ it('Should close the modal calling \'activeModal.dismiss\'', () => {
+ spyOn(compAsAny.activeModal, 'dismiss');
+ comp.closeMetadataModal();
+
+ expect(compAsAny.activeModal.dismiss).toHaveBeenCalled();
+ });
+
+ it('Should start the import process opening a modal', () => {
+ const emittedEvent: CollectionListEntry = {
+ communities: [
+ {
+ id: 'dummy',
+ uuid: 'dummy',
+ name: 'dummy',
+ }
+ ],
+ collection: {
+ id: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88',
+ uuid: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88',
+ name: 'Collection 1',
+ }
+ };
+ const submissionObjects = [
+ { id: 'jk11k13o-9v4z-632i-sr88-wq071n0h1d47' }
+ ];
+ comp.externalSourceEntry = externalEntry;
+ spyOn(compAsAny.modalService, 'open').and.returnValue({componentInstance: { selectedEvent: observableOf(emittedEvent)}});
+ spyOn(comp, 'closeMetadataModal');
+ submissionServiceStub.createSubmissionFromExternalSource.and.returnValue(observableOf(submissionObjects));
+ spyOn(compAsAny.router, 'navigateByUrl');
+ comp.import();
+
+ expect(compAsAny.modalService.open).toHaveBeenCalledWith(SubmissionImportExternalCollectionComponent, { size: 'lg' });
+ expect(comp.closeMetadataModal).toHaveBeenCalled();
+ expect(compAsAny.submissionService.createSubmissionFromExternalSource).toHaveBeenCalledWith(externalEntry._links.self.href, emittedEvent.collection.id);
+ expect(compAsAny.router.navigateByUrl).toHaveBeenCalledWith('/workspaceitems/' + submissionObjects[0].id + '/edit');
+ });
+ });
+});
+
+// declare a test component
+@Component({
+ selector: 'ds-test-cmp',
+ template: ``
+})
+class TestComponent {
+
+}
diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.ts b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.ts
index de86bba3b1..8294ec66ba 100644
--- a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.ts
+++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.ts
@@ -1,8 +1,15 @@
import { Component, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
import { NgbActiveModal, NgbModalRef, NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { ExternalSourceEntry } from '../../../core/shared/external-source-entry.model';
import { MetadataValue } from '../../../core/shared/metadata.models';
import { Metadata } from '../../../core/shared/metadata.utils';
+import { CollectionListEntry } from '../../../shared/collection-dropdown/collection-dropdown.component';
+import { mergeMap } from 'rxjs/operators';
+import { SubmissionService } from '../../submission.service';
+import { SubmissionObject } from '../../../core/submission/models/submission-object.model';
+import { NotificationsService } from '../../../shared/notifications/notifications.service';
+import { SubmissionImportExternalCollectionComponent } from '../import-external-collection/submission-import-external-collection.component';
/**
* This component display a preview of an external source item.
@@ -29,10 +36,17 @@ export class SubmissionImportExternalPreviewComponent implements OnInit {
/**
* Initialize the component variables.
* @param {NgbActiveModal} activeModal
+ * @param {SubmissionService} submissionService
+ * @param {NgbModal} modalService
+ * @param {Router} router
+ * @param {NotificationsService} notificationService
*/
constructor(
private activeModal: NgbActiveModal,
- private modalService: NgbModal
+ private submissionService: SubmissionService,
+ private modalService: NgbModal,
+ private router: Router,
+ private notificationService: NotificationsService
) { }
/**
@@ -57,14 +71,30 @@ export class SubmissionImportExternalPreviewComponent implements OnInit {
}
/**
- * Start the import of an entry by opening up an import modal window.
- * @param entry The entry to import
+ * Start the import of an entry by opening up a collection choice modal window.
*/
- public import(entry): void {
- this.modalRef = this.modalService.open(SubmissionImportExternalPreviewComponent, {
+ public import(): void {
+ this.modalRef = this.modalService.open(SubmissionImportExternalCollectionComponent, {
size: 'lg',
});
- const modalComp = this.modalRef.componentInstance;
- modalComp.externalSourceEntry = entry;
+ this.closeMetadataModal();
+
+ this.modalRef.componentInstance.selectedEvent.pipe(
+ mergeMap((collectionListEntry: CollectionListEntry) => {
+ return this.submissionService.createSubmissionFromExternalSource(this.externalSourceEntry._links.self.href, collectionListEntry.collection.id);
+ })
+ ).subscribe((submissionObjects: SubmissionObject[]) => {
+ let isValid = false
+ if (submissionObjects.length === 1) {
+ if (submissionObjects[0] !== null) {
+ isValid = true;
+ this.router.navigateByUrl('/workspaceitems/' + submissionObjects[0].id + '/edit');
+ }
+ }
+ if (!isValid) {
+ this.notificationService.error('submission.import-external.preview.error.import.title', 'submission.import-external.preview.error.import.body');
+ }
+ this.modalRef.close();
+ });
}
}
diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts
index 66ce798ed9..1f77374932 100644
--- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts
+++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts
@@ -1,13 +1,18 @@
-// import { Component, NO_ERRORS_SCHEMA, ChangeDetectorRef } from '@angular/core';
-// import { async, TestBed, ComponentFixture, inject } from '@angular/core/testing';
-// import { TranslateModule } from '@ngx-translate/core';
-// import { SubmissionImportExternalSearchbarComponent } from './submission-import-external-searchbar.component';
-// import { ExternalSourceService } from '../../../core/data/external-source.service';
-// import { createTestComponent } from '../../../shared/testing/utils.test';
-// import { getMockExternalSourceService } from '../../../shared/mocks/external-source.service.mock';
-// import { SubmissionModule } from '../../submission.module';
+import { Component, NO_ERRORS_SCHEMA, ChangeDetectorRef } from '@angular/core';
+import { async, TestBed, ComponentFixture, inject } from '@angular/core/testing';
+import { TranslateModule } from '@ngx-translate/core';
+import { of as observableOf } from 'rxjs';
+import { SubmissionImportExternalSearchbarComponent, SourceElement } from './submission-import-external-searchbar.component';
+import { ExternalSourceService } from '../../../core/data/external-source.service';
+import { createTestComponent } from '../../../shared/testing/utils.test';
+import { getMockExternalSourceService, externalSourceOrcid, externalSourceCiencia, externalSourceMyStaffDb } from '../../../shared/mocks/external-source.service.mock';
+import { PageInfo } from '../../../core/shared/page-info.model';
+import { PaginatedList } from '../../../core/data/paginated-list';
+import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils';
+import { ExternalSource } from '../../../core/shared/external-source.model';
+import { FindListOptions } from '../../../core/data/request.models';
-/*describe('SubmissionImportExternalSearchbarComponent test suite', () => {
+describe('SubmissionImportExternalSearchbarComponent test suite', () => {
let comp: SubmissionImportExternalSearchbarComponent;
let compAsAny: any;
let fixture: ComponentFixture;
@@ -15,7 +20,6 @@
beforeEach(async (() => {
TestBed.configureTestingModule({
imports: [
- SubmissionModule,
TranslateModule.forRoot(),
],
declarations: [
@@ -51,16 +55,25 @@
it('should create SubmissionImportExternalSearchbarComponent', inject([SubmissionImportExternalSearchbarComponent], (app: SubmissionImportExternalSearchbarComponent) => {
expect(app).toBeDefined();
}));
- });*/
+ });
+
+ describe('', () => {
+ let sourceList: SourceElement[];
+ let paginatedList: PaginatedList;
- /*describe('', () => {
beforeEach(() => {
fixture = TestBed.createComponent(SubmissionImportExternalSearchbarComponent);
comp = fixture.componentInstance;
compAsAny = comp;
- // compAsAny.externalService.getAllExternalSources.and.returnValue(observableOf([
-
- // ]));
+ const pageInfo = new PageInfo();
+ paginatedList = new PaginatedList(pageInfo, [externalSourceOrcid, externalSourceCiencia, externalSourceMyStaffDb]);
+ const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList);
+ compAsAny.externalService.getAllExternalSources.and.returnValue(observableOf(paginatedListRD));
+ sourceList = [
+ {id: 'orcid', name: 'orcid'},
+ {id: 'ciencia', name: 'ciencia'},
+ {id: 'my_staff_db', name: 'my_staff_db'},
+ ];
});
afterEach(() => {
@@ -69,16 +82,61 @@
compAsAny = null;
});
- it('Should init component properly', () => {
+ it('Should init component properly (without initExternalSourceData)', () => {
+ comp.initExternalSourceData = { sourceId: '', query: '' };
comp.ngOnInit();
fixture.detectChanges();
- expect(comp.selectedElement)
- expect(compAsAny.pageInfo)
- expect(comp.sourceList)
+ expect(comp.selectedElement).toEqual(sourceList[0]);
+ expect(compAsAny.pageInfo).toEqual(paginatedList.pageInfo);
+ expect(comp.sourceList).toEqual(sourceList);
});
- });*/
-/*
+
+ it('Should init component properly (with initExternalSourceData populated)', () => {
+ comp.initExternalSourceData = { query: 'dummy', sourceId: 'ciencia' };
+ comp.ngOnInit();
+ fixture.detectChanges();
+
+ expect(comp.selectedElement).toEqual(sourceList[1]);
+ expect(compAsAny.pageInfo).toEqual(paginatedList.pageInfo);
+ expect(comp.sourceList).toEqual(sourceList);
+ });
+
+ it('Variable \'selectedElement\' should be assigned', () => {
+ const selectedElement = {id: 'orcid', name: 'orcid'};
+ comp.makeSourceSelection(selectedElement);
+ expect(comp.selectedElement).toEqual(selectedElement);
+ });
+
+ it('Should load additional external sources', () => {
+ comp.sourceListLoading = false;
+ compAsAny.pageInfo = new PageInfo({
+ elementsPerPage: 3,
+ totalElements: 6,
+ totalPages: 2,
+ currentPage: 0
+ });
+ compAsAny.findListOptions = Object.assign({}, new FindListOptions(), {
+ elementsPerPage: 3,
+ currentPage: 0,
+ });
+ comp.sourceList = sourceList;
+ const expected = sourceList.concat(sourceList);
+ comp.onScroll();
+
+ expect(comp.sourceList).toEqual(expected);
+ });
+
+ it('The \'search\' method should call \'emit\'', () => {
+ comp.selectedElement = { id: 'orcidV2', name: 'orcidV2' };
+ comp.searchString = 'dummy';
+ const expected = { sourceId: comp.selectedElement.id, query: comp.searchString };
+ spyOn(comp.externalSourceData, 'emit');
+ comp.search();
+
+ expect(comp.externalSourceData.emit).toHaveBeenCalledWith(expected);
+ });
+ });
});
// declare a test component
@@ -88,4 +146,4 @@
})
class TestComponent {
-}*/
+}
diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts
index cd2f24eb2c..efbcbad60c 100644
--- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts
+++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts
@@ -10,13 +10,12 @@ import { RemoteData } from '../../../core/data/remote-data';
import { PageInfo } from '../../../core/shared/page-info.model';
import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils';
import { FindListOptions } from '../../../core/data/request.models';
-import { isEmpty } from '../../../shared/empty.util';
import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators';
/**
* Interface for the selected external source element.
*/
-interface SourceElement {
+export interface SourceElement {
id: string;
name: string;
}
@@ -124,14 +123,14 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit {
/**
* Set the selected external source.
*/
- makeSourceSelection(source) {
+ public makeSourceSelection(source): void {
this.selectedElement = source;
}
/**
* Load the next pages of external sources.
*/
- onScroll() {
+ public onScroll(): void {
if (!this.sourceListLoading && this.pageInfo.currentPage <= this.pageInfo.totalPages) {
this.sourceListLoading = true;
this.findListOptions = Object.assign({}, new FindListOptions(), {
@@ -145,21 +144,21 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit {
const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList);
return observableOf(paginatedListRD);
}),
- tap(() => this.sourceListLoading = false))
- .subscribe((externalSource: RemoteData>) => {
- externalSource.payload.page.forEach((element) => {
- this.sourceList.push({ id: element.id, name: element.name });
- })
- this.pageInfo = externalSource.payload.pageInfo;
- this.cdr.detectChanges();
+ tap(() => this.sourceListLoading = false)
+ ).subscribe((externalSource: RemoteData>) => {
+ externalSource.payload.page.forEach((element) => {
+ this.sourceList.push({ id: element.id, name: element.name });
})
+ this.pageInfo = externalSource.payload.pageInfo;
+ this.cdr.detectChanges();
+ })
}
}
/**
* Passes the search parameters to the parent component.
*/
- public search() {
+ public search(): void {
this.externalSourceData.emit({ sourceId: this.selectedElement.id, query: this.searchString });
}
}
diff --git a/src/app/submission/import-external/submission-import-external.component.spec.ts b/src/app/submission/import-external/submission-import-external.component.spec.ts
index e69de29bb2..6b5ec05171 100644
--- a/src/app/submission/import-external/submission-import-external.component.spec.ts
+++ b/src/app/submission/import-external/submission-import-external.component.spec.ts
@@ -0,0 +1,159 @@
+import { Component, NO_ERRORS_SCHEMA } from '@angular/core';
+import { async, TestBed, ComponentFixture, inject } from '@angular/core/testing';
+import { TranslateModule } from '@ngx-translate/core';
+import { Router } from '@angular/router';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { of as observableOf, of } from 'rxjs/internal/observable/of';
+import { SubmissionImportExternalComponent } from './submission-import-external.component';
+import { ExternalSourceService } from '../../core/data/external-source.service';
+import { getMockExternalSourceService } from '../../shared/mocks/external-source.service.mock';
+import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
+import { RouteService } from '../../core/services/route.service';
+import { createTestComponent, createPaginatedList } from '../../shared/testing/utils.test';
+import { RouterStub } from '../../shared/testing/router.stub';
+import { VarDirective } from '../../shared/utils/var.directive';
+import { routeServiceStub } from '../../shared/testing/route-service.stub';
+import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model';
+import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
+import { createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils';
+import { ExternalSourceEntry } from '../../core/shared/external-source-entry.model';
+import { SubmissionImportExternalPreviewComponent } from './import-external-preview/submission-import-external-preview.component';
+
+describe('SubmissionImportExternalComponent test suite', () => {
+ let comp: SubmissionImportExternalComponent;
+ let compAsAny: any;
+ let fixture: ComponentFixture;
+ const mockSearchOptions = of(new PaginatedSearchOptions({
+ pagination: Object.assign(new PaginationComponentOptions(), {
+ pageSize: 10,
+ currentPage: 0
+ })
+ }));
+ const searchConfigServiceStub = {
+ paginatedSearchOptions: mockSearchOptions
+ };
+
+ beforeEach(async (() => {
+ TestBed.configureTestingModule({
+ imports: [
+ TranslateModule.forRoot()
+ ],
+ declarations: [
+ SubmissionImportExternalComponent,
+ TestComponent,
+ VarDirective
+ ],
+ providers: [
+ { provide: ExternalSourceService, useClass: getMockExternalSourceService },
+ { provide: SearchConfigurationService, useValue: searchConfigServiceStub },
+ { provide: RouteService, useValue: routeServiceStub },
+ { provide: Router, useValue: new RouterStub() },
+ NgbModal,
+ SubmissionImportExternalComponent
+ ],
+ schemas: [NO_ERRORS_SCHEMA]
+ }).compileComponents().then();
+ }));
+
+ // First test to check the correct component creation
+ describe('', () => {
+ let testComp: TestComponent;
+ let testFixture: ComponentFixture;
+
+ // synchronous beforeEach
+ beforeEach(() => {
+ const html = `
+ `;
+ testFixture = createTestComponent(html, TestComponent) as ComponentFixture;
+ testComp = testFixture.componentInstance;
+ });
+
+ afterEach(() => {
+ testFixture.destroy();
+ });
+
+ it('should create SubmissionImportExternalComponent', inject([SubmissionImportExternalComponent], (app: SubmissionImportExternalComponent) => {
+ expect(app).toBeDefined();
+ }));
+ });
+
+ describe('', () => {
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SubmissionImportExternalComponent);
+ comp = fixture.componentInstance;
+ compAsAny = comp;
+ });
+
+ afterEach(() => {
+ fixture.destroy();
+ comp = null;
+ compAsAny = null;
+ });
+
+ it('Should init component properly (without route data)', () => {
+ const expectedEntries = createSuccessfulRemoteDataObject(createPaginatedList([]));
+ spyOn(compAsAny.routeService, 'getQueryParameterValue').and.returnValue(observableOf(''));
+ comp.ngOnInit();
+ fixture.detectChanges();
+
+ expect(comp.routeData).toEqual({ sourceId: '', query: '' });
+ expect(comp.isLoading$.value).toBe(false);
+ expect(comp.entriesRD$.value).toEqual(expectedEntries);
+ });
+
+ it('Should init component properly (with route data)', () => {
+ const expectedEntries = createSuccessfulRemoteDataObject(createPaginatedList([]));
+ const searchOptions = new PaginatedSearchOptions({
+ pagination: Object.assign(new PaginationComponentOptions(), {
+ pageSize: 10,
+ currentPage: 0
+ })
+ });
+ spyOn(compAsAny.routeService, 'getQueryParameterValue').and.returnValue(observableOf('dummy'));
+ comp.ngOnInit();
+ fixture.detectChanges();
+
+ expect(comp.routeData).toEqual({ sourceId: 'dummy', query: 'dummy' });
+ expect(comp.isLoading$.value).toBe(true);
+ expect(comp.entriesRD$.value).toEqual(expectedEntries);
+ expect(compAsAny.externalService.getExternalSourceEntries).toHaveBeenCalledWith('dummy', searchOptions);
+ });
+
+ it('Should call \'router.navigate\'', () => {
+ const event = { sourceId: 'orcidV2', query: 'dummy' };
+ comp.getExternalsourceData(event);
+
+ expect(compAsAny.router.navigate).toHaveBeenCalledWith([], { queryParams: { source: event.sourceId, query: event.query }, replaceUrl: true });
+ });
+
+ it('Entry should be passed to the component loaded inside the modal', () => {
+ const entry = Object.assign(new ExternalSourceEntry(), {
+ id: '0001-0001-0001-0001',
+ display: 'John Doe',
+ value: 'John, Doe',
+ metadata: {
+ 'dc.identifier.uri': [
+ {
+ value: 'https://orcid.org/0001-0001-0001-0001'
+ }
+ ]
+ }
+ });
+ spyOn(compAsAny.modalService, 'open').and.returnValue({componentInstance: { externalSourceEntry: null}});
+ comp.import(entry);
+
+ expect(compAsAny.modalService.open).toHaveBeenCalledWith(SubmissionImportExternalPreviewComponent, { size: 'lg' });
+ expect(comp.modalRef.componentInstance.externalSourceEntry).toEqual(entry);
+ });
+ });
+
+});
+
+// declare a test component
+@Component({
+ selector: 'ds-test-cmp',
+ template: ``
+})
+class TestComponent {
+
+}
diff --git a/src/app/submission/import-external/submission-import-external.component.ts b/src/app/submission/import-external/submission-import-external.component.ts
index 47ae781baa..70fdd5f477 100644
--- a/src/app/submission/import-external/submission-import-external.component.ts
+++ b/src/app/submission/import-external/submission-import-external.component.ts
@@ -70,7 +70,7 @@ export class SubmissionImportExternalComponent implements OnInit {
/**
* The modal for the entry preview
*/
- modalRef: NgbModalRef;
+ public modalRef: NgbModalRef;
/**
* Initialize the component variables.
diff --git a/src/app/submission/submission.module.ts b/src/app/submission/submission.module.ts
index 7ff8b98d9e..4e5e5bc6da 100644
--- a/src/app/submission/submission.module.ts
+++ b/src/app/submission/submission.module.ts
@@ -31,6 +31,7 @@ import { storeModuleConfig } from '../app.reducer';
import { SubmissionImportExternalComponent } from './import-external/submission-import-external.component';
import { SubmissionImportExternalSearchbarComponent } from './import-external/import-external-searchbar/submission-import-external-searchbar.component';
import { SubmissionImportExternalPreviewComponent } from './import-external/import-external-preview/submission-import-external-preview.component';
+import { SubmissionImportExternalCollectionComponent } from './import-external/import-external-collection/submission-import-external-collection.component';
@NgModule({
imports: [
@@ -60,14 +61,16 @@ import { SubmissionImportExternalPreviewComponent } from './import-external/impo
SubmissionSectionUploadFileViewComponent,
SubmissionImportExternalComponent,
SubmissionImportExternalSearchbarComponent,
- SubmissionImportExternalPreviewComponent
+ SubmissionImportExternalPreviewComponent,
+ SubmissionImportExternalCollectionComponent
],
entryComponents: [
SubmissionSectionUploadComponent,
SubmissionSectionformComponent,
SubmissionSectionLicenseComponent,
SubmissionSectionContainerComponent,
- SubmissionImportExternalPreviewComponent
+ SubmissionImportExternalPreviewComponent,
+ SubmissionImportExternalCollectionComponent
],
exports: [
SubmissionEditComponent,
diff --git a/src/app/submission/submission.service.spec.ts b/src/app/submission/submission.service.spec.ts
index eb7538ec69..9cb678dbb3 100644
--- a/src/app/submission/submission.service.spec.ts
+++ b/src/app/submission/submission.service.spec.ts
@@ -410,6 +410,19 @@ describe('SubmissionService test suite', () => {
});
});
+ describe('createSubmissionFromExternalSource', () => {
+ it('should deposit submission', () => {
+ const options: HttpOptions = Object.create({});
+ let headers = new HttpHeaders();
+ headers = headers.append('Content-Type', 'text/uri-list');
+ options.headers = headers;
+
+ service.createSubmissionFromExternalSource(selfUrl, collectionId);
+
+ expect((service as any).restService.postToEndpoint).toHaveBeenCalledWith('workspaceitems', selfUrl, null, options, collectionId);
+ });
+ });
+
describe('depositSubmission', () => {
it('should deposit submission', () => {
const options: HttpOptions = Object.create({});
diff --git a/src/app/submission/submission.service.ts b/src/app/submission/submission.service.ts
index f06f6ea069..7aa02c6c07 100644
--- a/src/app/submission/submission.service.ts
+++ b/src/app/submission/submission.service.ts
@@ -113,6 +113,24 @@ export class SubmissionService {
catchError(() => observableOf({} as SubmissionObject)))
}
+ /**
+ * Perform a REST call to deposit a workspaceitem and return response
+ *
+ * @param selfUrl
+ * The workspaceitem self url
+ * @param collectionId
+ * Optional collection id
+ * @return Observable
+ * observable of SubmissionObject
+ */
+ createSubmissionFromExternalSource(selfUrl: string, collectionId?: string): Observable {
+ const options: HttpOptions = Object.create({});
+ let headers = new HttpHeaders();
+ headers = headers.append('Content-Type', 'text/uri-list');
+ options.headers = headers;
+ return this.restService.postToEndpoint(this.workspaceLinkPath, selfUrl, null, options, collectionId) as Observable;
+ }
+
/**
* Perform a REST call to deposit a workspaceitem and return response
*
diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5
index 3e2994142d..fdacf7cd44 100644
--- a/src/assets/i18n/en.json5
+++ b/src/assets/i18n/en.json5
@@ -2432,6 +2432,10 @@
"submission.import-external.preview.button.import": "Start submission",
+ "submission.import-external.preview.error.import.title": "Submission error",
+
+ "submission.import-external.preview.error.import.body": "An error occurs during the external source entry import process.",
+
"submission.sections.describe.relationship-lookup.close": "Close",