mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 18:14:17 +00:00
[CST-4591] Change import from external source page in order to work with entity type
This commit is contained in:
@@ -53,6 +53,7 @@ export const externalSourceMyStaffDb: ExternalSource = {
|
|||||||
export function getMockExternalSourceService(): ExternalSourceService {
|
export function getMockExternalSourceService(): ExternalSourceService {
|
||||||
return jasmine.createSpyObj('ExternalSourceService', {
|
return jasmine.createSpyObj('ExternalSourceService', {
|
||||||
findAll: jasmine.createSpy('findAll'),
|
findAll: jasmine.createSpy('findAll'),
|
||||||
|
searchBy: jasmine.createSpy('searchBy'),
|
||||||
getExternalSourceEntries: jasmine.createSpy('getExternalSourceEntries'),
|
getExternalSourceEntries: jasmine.createSpy('getExternalSourceEntries'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,12 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<ds-collection-dropdown (selectionChange)="selectObject($event)">
|
<ds-loading *ngIf="isLoading()"></ds-loading>
|
||||||
|
<ds-collection-dropdown [ngClass]="{'d-none': isLoading()}"
|
||||||
|
(selectionChange)="selectObject($event)"
|
||||||
|
(hasChoice)="onHasChoice($event)"
|
||||||
|
(theOnlySelectable)="theOnlySelectable($event)"
|
||||||
|
[entityType]="entityType">
|
||||||
</ds-collection-dropdown>
|
</ds-collection-dropdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
import { Component, NO_ERRORS_SCHEMA, EventEmitter } from '@angular/core';
|
import { Component, EventEmitter, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { waitForAsync, TestBed, ComponentFixture, inject } from '@angular/core/testing';
|
import { ComponentFixture, fakeAsync, inject, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { createTestComponent } from '../../../shared/testing/utils.test';
|
import { createTestComponent } from '../../../shared/testing/utils.test';
|
||||||
import { SubmissionImportExternalCollectionComponent } from './submission-import-external-collection.component';
|
import { SubmissionImportExternalCollectionComponent } from './submission-import-external-collection.component';
|
||||||
import { CollectionListEntry } from '../../../shared/collection-dropdown/collection-dropdown.component';
|
import { CollectionListEntry } from '../../../shared/collection-dropdown/collection-dropdown.component';
|
||||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
|
||||||
describe('SubmissionImportExternalCollectionComponent test suite', () => {
|
describe('SubmissionImportExternalCollectionComponent test suite', () => {
|
||||||
let comp: SubmissionImportExternalCollectionComponent;
|
let comp: SubmissionImportExternalCollectionComponent;
|
||||||
@@ -76,6 +77,48 @@ describe('SubmissionImportExternalCollectionComponent test suite', () => {
|
|||||||
|
|
||||||
expect(compAsAny.activeModal.dismiss).toHaveBeenCalled();
|
expect(compAsAny.activeModal.dismiss).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be in loading state when hasChoice variable is different to true', () => {
|
||||||
|
comp.hasChoice = null;
|
||||||
|
expect(comp.isLoading()).toBeTrue();
|
||||||
|
|
||||||
|
comp.hasChoice = false;
|
||||||
|
expect(comp.isLoading()).toBeTrue();
|
||||||
|
|
||||||
|
comp.hasChoice = true;
|
||||||
|
expect(comp.isLoading()).toBeFalse();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set hasChoice variable on hasChoice event', () => {
|
||||||
|
comp.hasChoice = null;
|
||||||
|
|
||||||
|
comp.onHasChoice(true);
|
||||||
|
expect(comp.hasChoice).toBe(true);
|
||||||
|
|
||||||
|
comp.onHasChoice(false);
|
||||||
|
expect(comp.hasChoice).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit theOnlySelectable', () => {
|
||||||
|
spyOn(comp.selectedEvent, 'emit').and.callThrough();
|
||||||
|
|
||||||
|
const selected: any = {};
|
||||||
|
comp.theOnlySelectable(selected);
|
||||||
|
|
||||||
|
expect(comp.selectedEvent.emit).toHaveBeenCalledWith(selected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('dropdown should be invisible when the component is loading', fakeAsync(() => {
|
||||||
|
|
||||||
|
spyOn(comp, 'isLoading').and.returnValue(true);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const dropdownMenu = fixture.debugElement.query(By.css('ds-collection-dropdown')).nativeElement;
|
||||||
|
expect(dropdownMenu.classList).toContain('d-none');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Component, Output, EventEmitter } from '@angular/core';
|
import { Component, EventEmitter, Output } from '@angular/core';
|
||||||
import { CollectionListEntry } from '../../../shared/collection-dropdown/collection-dropdown.component';
|
import { CollectionListEntry } from '../../../shared/collection-dropdown/collection-dropdown.component';
|
||||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
|
|
||||||
@@ -16,6 +16,16 @@ export class SubmissionImportExternalCollectionComponent {
|
|||||||
*/
|
*/
|
||||||
@Output() public selectedEvent = new EventEmitter<CollectionListEntry>();
|
@Output() public selectedEvent = new EventEmitter<CollectionListEntry>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If present this value is used to filter collection list by entity type
|
||||||
|
*/
|
||||||
|
public entityType: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a collection choice is available
|
||||||
|
*/
|
||||||
|
public hasChoice: boolean = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the component variables.
|
* Initialize the component variables.
|
||||||
* @param {NgbActiveModal} activeModal
|
* @param {NgbActiveModal} activeModal
|
||||||
@@ -37,4 +47,27 @@ export class SubmissionImportExternalCollectionComponent {
|
|||||||
public closeCollectionModal(): void {
|
public closeCollectionModal(): void {
|
||||||
this.activeModal.dismiss(false);
|
this.activeModal.dismiss(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Propagate the onlySelectable collection
|
||||||
|
* @param theOnlySelectable
|
||||||
|
*/
|
||||||
|
public theOnlySelectable(theOnlySelectable: CollectionListEntry) {
|
||||||
|
this.selectedEvent.emit(theOnlySelectable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the hasChoice state
|
||||||
|
* @param hasChoice
|
||||||
|
*/
|
||||||
|
public onHasChoice(hasChoice: boolean) {
|
||||||
|
this.hasChoice = hasChoice;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the component is in loading state.
|
||||||
|
*/
|
||||||
|
public isLoading(): boolean {
|
||||||
|
return this.hasChoice !== true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h2>{{'submission.import-external.preview.title' | translate}}</h2>
|
<h2>{{'submission.import-external.preview.title.' + labelPrefix | translate}}</h2>
|
||||||
<button type="button" class="close"
|
<button type="button" class="close"
|
||||||
(click)="closeMetadataModal()" aria-label="Close">
|
(click)="closeMetadataModal()" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { NgbActiveModal, NgbModalRef, NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbActiveModal, NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { ExternalSourceEntry } from '../../../core/shared/external-source-entry.model';
|
import { ExternalSourceEntry } from '../../../core/shared/external-source-entry.model';
|
||||||
import { MetadataValue } from '../../../core/shared/metadata.models';
|
import { MetadataValue } from '../../../core/shared/metadata.models';
|
||||||
import { Metadata } from '../../../core/shared/metadata.utils';
|
import { Metadata } from '../../../core/shared/metadata.utils';
|
||||||
@@ -28,6 +28,10 @@ export class SubmissionImportExternalPreviewComponent implements OnInit {
|
|||||||
* The entry metadata list
|
* The entry metadata list
|
||||||
*/
|
*/
|
||||||
public metadataList: { key: string, value: MetadataValue }[];
|
public metadataList: { key: string, value: MetadataValue }[];
|
||||||
|
/**
|
||||||
|
* The label prefix to use to generate the translation label
|
||||||
|
*/
|
||||||
|
public labelPrefix: string;
|
||||||
/**
|
/**
|
||||||
* The modal for the entry preview
|
* The modal for the entry preview
|
||||||
*/
|
*/
|
||||||
@@ -77,6 +81,7 @@ export class SubmissionImportExternalPreviewComponent implements OnInit {
|
|||||||
this.modalRef = this.modalService.open(SubmissionImportExternalCollectionComponent, {
|
this.modalRef = this.modalService.open(SubmissionImportExternalCollectionComponent, {
|
||||||
size: 'lg',
|
size: 'lg',
|
||||||
});
|
});
|
||||||
|
this.modalRef.componentInstance.entityType = this.labelPrefix;
|
||||||
this.closeMetadataModal();
|
this.closeMetadataModal();
|
||||||
|
|
||||||
this.modalRef.componentInstance.selectedEvent.pipe(
|
this.modalRef.componentInstance.selectedEvent.pipe(
|
||||||
|
@@ -15,7 +15,7 @@ import {
|
|||||||
getMockExternalSourceService
|
getMockExternalSourceService
|
||||||
} from '../../../shared/mocks/external-source.service.mock';
|
} from '../../../shared/mocks/external-source.service.mock';
|
||||||
import { PageInfo } from '../../../core/shared/page-info.model';
|
import { PageInfo } from '../../../core/shared/page-info.model';
|
||||||
import { PaginatedList, buildPaginatedList } from '../../../core/data/paginated-list.model';
|
import { buildPaginatedList, PaginatedList } from '../../../core/data/paginated-list.model';
|
||||||
import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils';
|
||||||
import { ExternalSource } from '../../../core/shared/external-source.model';
|
import { ExternalSource } from '../../../core/shared/external-source.model';
|
||||||
import { FindListOptions } from '../../../core/data/request.models';
|
import { FindListOptions } from '../../../core/data/request.models';
|
||||||
@@ -23,6 +23,7 @@ import { HostWindowService } from '../../../shared/host-window.service';
|
|||||||
import { HostWindowServiceStub } from '../../../shared/testing/host-window-service.stub';
|
import { HostWindowServiceStub } from '../../../shared/testing/host-window-service.stub';
|
||||||
import { getTestScheduler } from 'jasmine-marbles';
|
import { getTestScheduler } from 'jasmine-marbles';
|
||||||
import { TestScheduler } from 'rxjs/testing';
|
import { TestScheduler } from 'rxjs/testing';
|
||||||
|
import { RequestParam } from '../../../core/cache/models/request-param.model';
|
||||||
|
|
||||||
describe('SubmissionImportExternalSearchbarComponent test suite', () => {
|
describe('SubmissionImportExternalSearchbarComponent test suite', () => {
|
||||||
let comp: SubmissionImportExternalSearchbarComponent;
|
let comp: SubmissionImportExternalSearchbarComponent;
|
||||||
@@ -63,9 +64,9 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => {
|
|||||||
|
|
||||||
// synchronous beforeEach
|
// synchronous beforeEach
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockExternalSourceService.findAll.and.returnValue(observableOf(paginatedListRD));
|
mockExternalSourceService.searchBy.and.returnValue(observableOf(paginatedListRD));
|
||||||
const html = `
|
const html = `
|
||||||
<ds-submission-import-external-searchbar></ds-submission-import-external-searchbar>`;
|
<ds-submission-import-external-searchbar [initExternalSourceData]="initExternalSourceData"></ds-submission-import-external-searchbar>`;
|
||||||
testFixture = createTestComponent(html, TestComponent) as ComponentFixture<TestComponent>;
|
testFixture = createTestComponent(html, TestComponent) as ComponentFixture<TestComponent>;
|
||||||
testComp = testFixture.componentInstance;
|
testComp = testFixture.componentInstance;
|
||||||
});
|
});
|
||||||
@@ -88,7 +89,7 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => {
|
|||||||
const pageInfo = new PageInfo();
|
const pageInfo = new PageInfo();
|
||||||
paginatedList = buildPaginatedList(pageInfo, [externalSourceOrcid, externalSourceCiencia, externalSourceMyStaffDb]);
|
paginatedList = buildPaginatedList(pageInfo, [externalSourceOrcid, externalSourceCiencia, externalSourceMyStaffDb]);
|
||||||
paginatedListRD = createSuccessfulRemoteDataObject(paginatedList);
|
paginatedListRD = createSuccessfulRemoteDataObject(paginatedList);
|
||||||
compAsAny.externalService.findAll.and.returnValue(observableOf(paginatedListRD));
|
compAsAny.externalService.searchBy.and.returnValue(observableOf(paginatedListRD));
|
||||||
sourceList = [
|
sourceList = [
|
||||||
{id: 'orcid', name: 'orcid'},
|
{id: 'orcid', name: 'orcid'},
|
||||||
{id: 'ciencia', name: 'ciencia'},
|
{id: 'ciencia', name: 'ciencia'},
|
||||||
@@ -103,7 +104,7 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should init component properly (without initExternalSourceData)', () => {
|
it('Should init component properly (without initExternalSourceData)', () => {
|
||||||
comp.initExternalSourceData = { sourceId: '', query: '' };
|
comp.initExternalSourceData = { entity: 'Publication', sourceId: '', query: '' };
|
||||||
scheduler.schedule(() => fixture.detectChanges());
|
scheduler.schedule(() => fixture.detectChanges());
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
@@ -113,7 +114,7 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should init component properly (with initExternalSourceData populated)', () => {
|
it('Should init component properly (with initExternalSourceData populated)', () => {
|
||||||
comp.initExternalSourceData = { query: 'dummy', sourceId: 'ciencia' };
|
comp.initExternalSourceData = { entity: 'Publication', query: 'dummy', sourceId: 'ciencia' };
|
||||||
scheduler.schedule(() => fixture.detectChanges());
|
scheduler.schedule(() => fixture.detectChanges());
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
@@ -129,6 +130,7 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should load additional external sources', () => {
|
it('Should load additional external sources', () => {
|
||||||
|
comp.initExternalSourceData = { entity: 'Publication', query: 'dummy', sourceId: 'ciencia' };
|
||||||
comp.sourceListLoading = false;
|
comp.sourceListLoading = false;
|
||||||
compAsAny.pageInfo = new PageInfo({
|
compAsAny.pageInfo = new PageInfo({
|
||||||
elementsPerPage: 3,
|
elementsPerPage: 3,
|
||||||
@@ -139,6 +141,9 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => {
|
|||||||
compAsAny.findListOptions = Object.assign({}, new FindListOptions(), {
|
compAsAny.findListOptions = Object.assign({}, new FindListOptions(), {
|
||||||
elementsPerPage: 3,
|
elementsPerPage: 3,
|
||||||
currentPage: 0,
|
currentPage: 0,
|
||||||
|
searchParams: [
|
||||||
|
new RequestParam('entityType', 'Publication')
|
||||||
|
]
|
||||||
});
|
});
|
||||||
comp.sourceList = sourceList;
|
comp.sourceList = sourceList;
|
||||||
const expected = sourceList.concat(sourceList);
|
const expected = sourceList.concat(sourceList);
|
||||||
@@ -150,9 +155,10 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('The \'search\' method should call \'emit\'', () => {
|
it('The \'search\' method should call \'emit\'', () => {
|
||||||
|
comp.initExternalSourceData = { entity: 'Publication', query: 'dummy', sourceId: 'ciencia' };
|
||||||
comp.selectedElement = { id: 'orcidV2', name: 'orcidV2' };
|
comp.selectedElement = { id: 'orcidV2', name: 'orcidV2' };
|
||||||
comp.searchString = 'dummy';
|
comp.searchString = 'dummy';
|
||||||
const expected = { sourceId: comp.selectedElement.id, query: comp.searchString };
|
const expected = { entity: 'Publication', sourceId: comp.selectedElement.id, query: comp.searchString };
|
||||||
spyOn(comp.externalSourceData, 'emit');
|
spyOn(comp.externalSourceData, 'emit');
|
||||||
comp.search();
|
comp.search();
|
||||||
|
|
||||||
@@ -167,5 +173,5 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => {
|
|||||||
template: ``
|
template: ``
|
||||||
})
|
})
|
||||||
class TestComponent {
|
class TestComponent {
|
||||||
|
initExternalSourceData = { entity: 'Publication', query: 'dummy', sourceId: 'ciencia' };
|
||||||
}
|
}
|
||||||
|
@@ -1,19 +1,12 @@
|
|||||||
import {
|
import { ChangeDetectorRef, Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
|
||||||
ChangeDetectorRef,
|
|
||||||
Component,
|
|
||||||
EventEmitter,
|
|
||||||
Input,
|
|
||||||
OnDestroy,
|
|
||||||
OnInit,
|
|
||||||
Output
|
|
||||||
} from '@angular/core';
|
|
||||||
|
|
||||||
import { Observable, of as observableOf, Subscription } from 'rxjs';
|
import { Observable, of as observableOf, Subscription } from 'rxjs';
|
||||||
import { catchError, tap } from 'rxjs/operators';
|
import { catchError, tap } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { RequestParam } from '../../../core/cache/models/request-param.model';
|
||||||
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 { ExternalSource } from '../../../core/shared/external-source.model';
|
||||||
import { PaginatedList, buildPaginatedList } from '../../../core/data/paginated-list.model';
|
import { buildPaginatedList, PaginatedList } from '../../../core/data/paginated-list.model';
|
||||||
import { RemoteData } from '../../../core/data/remote-data';
|
import { RemoteData } from '../../../core/data/remote-data';
|
||||||
import { PageInfo } from '../../../core/shared/page-info.model';
|
import { PageInfo } from '../../../core/shared/page-info.model';
|
||||||
import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils';
|
||||||
@@ -34,6 +27,7 @@ export interface SourceElement {
|
|||||||
* Interface for the external source data to export.
|
* Interface for the external source data to export.
|
||||||
*/
|
*/
|
||||||
export interface ExternalSourceData {
|
export interface ExternalSourceData {
|
||||||
|
entity: string;
|
||||||
query: string;
|
query: string;
|
||||||
sourceId: string;
|
sourceId: string;
|
||||||
}
|
}
|
||||||
@@ -116,8 +110,11 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit, OnDes
|
|||||||
this.findListOptions = Object.assign({}, new FindListOptions(), {
|
this.findListOptions = Object.assign({}, new FindListOptions(), {
|
||||||
elementsPerPage: 5,
|
elementsPerPage: 5,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
|
searchParams: [
|
||||||
|
new RequestParam('entityType', this.initExternalSourceData.entity)
|
||||||
|
]
|
||||||
});
|
});
|
||||||
this.externalService.findAll(this.findListOptions).pipe(
|
this.externalService.searchBy('findByEntityType', this.findListOptions).pipe(
|
||||||
catchError(() => {
|
catchError(() => {
|
||||||
const pageInfo = new PageInfo();
|
const pageInfo = new PageInfo();
|
||||||
const paginatedList = buildPaginatedList(pageInfo, []);
|
const paginatedList = buildPaginatedList(pageInfo, []);
|
||||||
@@ -158,8 +155,11 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit, OnDes
|
|||||||
this.findListOptions = Object.assign({}, new FindListOptions(), {
|
this.findListOptions = Object.assign({}, new FindListOptions(), {
|
||||||
elementsPerPage: 5,
|
elementsPerPage: 5,
|
||||||
currentPage: this.findListOptions.currentPage + 1,
|
currentPage: this.findListOptions.currentPage + 1,
|
||||||
|
searchParams: [
|
||||||
|
new RequestParam('entityType', this.initExternalSourceData.entity)
|
||||||
|
]
|
||||||
});
|
});
|
||||||
this.sub = this.externalService.findAll(this.findListOptions).pipe(
|
this.externalService.searchBy('findByEntityType', this.findListOptions).pipe(
|
||||||
catchError(() => {
|
catchError(() => {
|
||||||
const pageInfo = new PageInfo();
|
const pageInfo = new PageInfo();
|
||||||
const paginatedList = buildPaginatedList(pageInfo, []);
|
const paginatedList = buildPaginatedList(pageInfo, []);
|
||||||
@@ -182,7 +182,13 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit, OnDes
|
|||||||
* Passes the search parameters to the parent component.
|
* Passes the search parameters to the parent component.
|
||||||
*/
|
*/
|
||||||
public search(): void {
|
public search(): void {
|
||||||
this.externalSourceData.emit({ sourceId: this.selectedElement.id, query: this.searchString });
|
this.externalSourceData.emit(
|
||||||
|
{
|
||||||
|
entity: this.initExternalSourceData.entity,
|
||||||
|
sourceId: this.selectedElement.id,
|
||||||
|
query: this.searchString
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -193,4 +199,5 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit, OnDes
|
|||||||
this.sub.unsubscribe();
|
this.sub.unsubscribe();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,17 +1,18 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<h2 id="header" class="pb-2">{{'submission.import-external.title' | translate}}</h2>
|
<h2 id="header" class="pb-2">{{'submission.import-external.title' + ((label) ? '.' + label : '') | translate}}</h2>
|
||||||
<ds-submission-import-external-searchbar
|
<ds-submission-import-external-searchbar
|
||||||
[initExternalSourceData]="routeData"
|
*ngIf="reload$.value.entity"
|
||||||
|
[initExternalSourceData]="reload$.value"
|
||||||
(externalSourceData) = "getExternalSourceData($event)">
|
(externalSourceData) = "getExternalSourceData($event)">
|
||||||
</ds-submission-import-external-searchbar>
|
</ds-submission-import-external-searchbar>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row" *ngIf="reload$.value.entity">
|
||||||
<div *ngIf="routeData.sourceId !== ''" class="col-md-12">
|
<div *ngIf="reload$.value.sourceId !== ''" class="col-md-12">
|
||||||
<ng-container *ngVar="(entriesRD$ | async) as entriesRD">
|
<ng-container *ngVar="(entriesRD$ | async) as entriesRD">
|
||||||
<h3 *ngIf="entriesRD && entriesRD?.payload?.page?.length !== 0">{{ 'submission.sections.describe.relationship-lookup.selection-tab.title.' + routeData.sourceId | translate}}</h3>
|
<h3 *ngIf="entriesRD && entriesRD?.payload?.page?.length !== 0">{{ 'submission.sections.describe.relationship-lookup.selection-tab.title' | translate}}</h3>
|
||||||
<ds-viewable-collection *ngIf="entriesRD?.hasSucceeded && !(isLoading$ | async) && entriesRD?.payload?.page?.length > 0" @fadeIn
|
<ds-viewable-collection *ngIf="entriesRD?.hasSucceeded && !(isLoading$ | async) && entriesRD?.payload?.page?.length > 0" @fadeIn
|
||||||
[objects]="entriesRD"
|
[objects]="entriesRD"
|
||||||
[selectionConfig]="{ repeatable: repeatable, listId: listId }"
|
[selectionConfig]="{ repeatable: repeatable, listId: listId }"
|
||||||
@@ -29,12 +30,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="routeData.sourceId === ''" class="col-md-12">
|
<div *ngIf="reload$.value.sourceId === ''" class="col-md-12">
|
||||||
<ds-alert [type]="'alert-info'">
|
<ds-alert [type]="'alert-info'">
|
||||||
<p class="lead mb-0">{{'submission.import-external.page.hint' | translate}}</p>
|
<p class="lead mb-0">{{'submission.import-external.page.hint' | translate}}</p>
|
||||||
</ds-alert>
|
</ds-alert>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row" *ngIf="!reload$.value.entity">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<ds-alert [type]="'alert-warning'">
|
||||||
|
<p class="lead mb-0">{{'submission.import-external.page.noentity' | translate}}</p>
|
||||||
|
</ds-alert>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<hr>
|
<hr>
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { Component, NO_ERRORS_SCHEMA } from '@angular/core';
|
import { Component, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { waitForAsync, ComponentFixture, inject, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
|
|
||||||
import { getTestScheduler } from 'jasmine-marbles';
|
import { getTestScheduler } from 'jasmine-marbles';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
@@ -102,17 +102,19 @@ describe('SubmissionImportExternalComponent test suite', () => {
|
|||||||
|
|
||||||
it('Should init component properly (without route data)', () => {
|
it('Should init component properly (without route data)', () => {
|
||||||
const expectedEntries = createSuccessfulRemoteDataObject(createPaginatedList([]));
|
const expectedEntries = createSuccessfulRemoteDataObject(createPaginatedList([]));
|
||||||
|
comp.routeData = {entity: '', sourceId: '', query: '' };
|
||||||
spyOn(compAsAny.routeService, 'getQueryParameterValue').and.returnValue(observableOf(''));
|
spyOn(compAsAny.routeService, 'getQueryParameterValue').and.returnValue(observableOf(''));
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(comp.routeData).toEqual({ sourceId: '', query: '' });
|
expect(comp.routeData).toEqual({entity: '', sourceId: '', query: '' });
|
||||||
expect(comp.isLoading$.value).toBe(false);
|
expect(comp.isLoading$.value).toBe(false);
|
||||||
expect(comp.entriesRD$.value).toEqual(expectedEntries);
|
expect(comp.entriesRD$.value).toEqual(expectedEntries);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should init component properly (with route data)', () => {
|
it('Should init component properly (with route data)', () => {
|
||||||
|
comp.routeData = {entity: '', sourceId: '', query: '' };
|
||||||
spyOn(compAsAny, 'retrieveExternalSources');
|
spyOn(compAsAny, 'retrieveExternalSources');
|
||||||
spyOn(compAsAny.routeService, 'getQueryParameterValue').and.returnValues(observableOf('source'), observableOf('dummy'));
|
spyOn(compAsAny.routeService, 'getQueryParameterValue').and.returnValues(observableOf('entity'), observableOf('source'), observableOf('dummy'));
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(compAsAny.retrieveExternalSources).toHaveBeenCalled();
|
expect(compAsAny.retrieveExternalSources).toHaveBeenCalled();
|
||||||
@@ -120,7 +122,7 @@ describe('SubmissionImportExternalComponent test suite', () => {
|
|||||||
|
|
||||||
it('Should call \'getExternalSourceEntries\' properly', () => {
|
it('Should call \'getExternalSourceEntries\' properly', () => {
|
||||||
spyOn(routeServiceStub, 'getQueryParameterValue').and.callFake((param) => {
|
spyOn(routeServiceStub, 'getQueryParameterValue').and.callFake((param) => {
|
||||||
if (param === 'source') {
|
if (param === 'sourceId') {
|
||||||
return observableOf('orcidV2');
|
return observableOf('orcidV2');
|
||||||
} else if (param === 'query') {
|
} else if (param === 'query') {
|
||||||
return observableOf('test');
|
return observableOf('test');
|
||||||
@@ -136,15 +138,15 @@ describe('SubmissionImportExternalComponent test suite', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should call \'router.navigate\'', () => {
|
it('Should call \'router.navigate\'', () => {
|
||||||
comp.routeData = { sourceId: '', query: '' };
|
comp.routeData = {entity: 'Person', sourceId: '', query: '' };
|
||||||
spyOn(compAsAny, 'retrieveExternalSources').and.callFake(() => null);
|
spyOn(compAsAny, 'retrieveExternalSources').and.callFake(() => null);
|
||||||
compAsAny.router.navigate.and.returnValue( new Promise(() => {return;}));
|
compAsAny.router.navigate.and.returnValue( new Promise(() => {return;}));
|
||||||
const event = { sourceId: 'orcidV2', query: 'dummy' };
|
const event = {entity: 'Person', sourceId: 'orcidV2', query: 'dummy' };
|
||||||
|
|
||||||
scheduler.schedule(() => comp.getExternalSourceData(event));
|
scheduler.schedule(() => comp.getExternalSourceData(event));
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect(compAsAny.router.navigate).toHaveBeenCalledWith([], { queryParams: { source: event.sourceId, query: event.query }, replaceUrl: true });
|
expect(compAsAny.router.navigate).toHaveBeenCalledWith([], { queryParams: { entity: event.entity, sourceId: event.sourceId, query: event.query }, replaceUrl: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Entry should be passed to the component loaded inside the modal', () => {
|
it('Entry should be passed to the component loaded inside the modal', () => {
|
||||||
@@ -166,6 +168,13 @@ describe('SubmissionImportExternalComponent test suite', () => {
|
|||||||
expect(compAsAny.modalService.open).toHaveBeenCalledWith(SubmissionImportExternalPreviewComponent, { size: 'lg' });
|
expect(compAsAny.modalService.open).toHaveBeenCalledWith(SubmissionImportExternalPreviewComponent, { size: 'lg' });
|
||||||
expect(comp.modalRef.componentInstance.externalSourceEntry).toEqual(entry);
|
expect(comp.modalRef.componentInstance.externalSourceEntry).toEqual(entry);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should set the correct label', () => {
|
||||||
|
const label = 'Person';
|
||||||
|
compAsAny.selectLabel(label);
|
||||||
|
|
||||||
|
expect(comp.label).toEqual(label);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@@ -45,9 +45,10 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
public isLoading$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
public isLoading$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||||
|
|
||||||
public reload$: BehaviorSubject<{ query: string, source: string }> = new BehaviorSubject<{ query: string; source: string }>({
|
public reload$: BehaviorSubject<ExternalSourceData> = new BehaviorSubject<ExternalSourceData>({
|
||||||
|
entity: '',
|
||||||
query: '',
|
query: '',
|
||||||
source: ''
|
sourceId: ''
|
||||||
});
|
});
|
||||||
/**
|
/**
|
||||||
* Configuration to use for the import buttons
|
* Configuration to use for the import buttons
|
||||||
@@ -109,11 +110,10 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy {
|
|||||||
* Get the entries for the selected external source and set initial configuration.
|
* Get the entries for the selected external source and set initial configuration.
|
||||||
*/
|
*/
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.label = 'Journal';
|
|
||||||
this.listId = 'list-submission-external-sources';
|
this.listId = 'list-submission-external-sources';
|
||||||
this.context = Context.EntitySearchModalWithNameVariants;
|
this.context = Context.EntitySearchModalWithNameVariants;
|
||||||
this.repeatable = false;
|
this.repeatable = false;
|
||||||
this.routeData = {sourceId: '', query: ''};
|
this.routeData = {entity: '', sourceId: '', query: ''};
|
||||||
this.importConfig = {
|
this.importConfig = {
|
||||||
buttonLabel: 'submission.sections.describe.relationship-lookup.external-source.import-button-title.' + this.label
|
buttonLabel: 'submission.sections.describe.relationship-lookup.external-source.import-button-title.' + this.label
|
||||||
};
|
};
|
||||||
@@ -121,12 +121,14 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy {
|
|||||||
this.isLoading$ = new BehaviorSubject(false);
|
this.isLoading$ = new BehaviorSubject(false);
|
||||||
this.subs.push(combineLatest(
|
this.subs.push(combineLatest(
|
||||||
[
|
[
|
||||||
this.routeService.getQueryParameterValue('source'),
|
this.routeService.getQueryParameterValue('entity'),
|
||||||
|
this.routeService.getQueryParameterValue('sourceId'),
|
||||||
this.routeService.getQueryParameterValue('query')
|
this.routeService.getQueryParameterValue('query')
|
||||||
]).pipe(
|
]).pipe(
|
||||||
take(1)
|
take(1)
|
||||||
).subscribe(([source, query]: [string, string]) => {
|
).subscribe(([entity, sourceId, query]: [string, string, string]) => {
|
||||||
this.reload$.next({query: query, source: source});
|
this.reload$.next({entity: entity, query: query, sourceId: sourceId});
|
||||||
|
this.selectLabel(entity);
|
||||||
this.retrieveExternalSources();
|
this.retrieveExternalSources();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -138,11 +140,11 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy {
|
|||||||
this.router.navigate(
|
this.router.navigate(
|
||||||
[],
|
[],
|
||||||
{
|
{
|
||||||
queryParams: {source: event.sourceId, query: event.query},
|
queryParams: event,
|
||||||
replaceUrl: true
|
replaceUrl: true
|
||||||
}
|
}
|
||||||
).then(() => {
|
).then(() => {
|
||||||
this.reload$.next({source: event.sourceId, query: event.query});
|
this.reload$.next(event);
|
||||||
this.retrieveExternalSources();
|
this.retrieveExternalSources();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -157,6 +159,7 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
const modalComp = this.modalRef.componentInstance;
|
const modalComp = this.modalRef.componentInstance;
|
||||||
modalComp.externalSourceEntry = entry;
|
modalComp.externalSourceEntry = entry;
|
||||||
|
modalComp.labelPrefix = this.label;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -173,22 +176,17 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve external source entries
|
* Retrieve external source entries.
|
||||||
*
|
|
||||||
* @param source The source tupe
|
|
||||||
* @param query The query string to search
|
|
||||||
*/
|
*/
|
||||||
private retrieveExternalSources(): void {
|
private retrieveExternalSources(): void {
|
||||||
if (hasValue(this.retrieveExternalSourcesSub)) {
|
/* if (hasValue(this.retrieveExternalSourcesSub)) {
|
||||||
this.retrieveExternalSourcesSub.unsubscribe();
|
this.retrieveExternalSourcesSub.unsubscribe();
|
||||||
}
|
}*/
|
||||||
this.retrieveExternalSourcesSub = this.reload$.pipe(
|
this.retrieveExternalSourcesSub = this.reload$.pipe(
|
||||||
filter((sourceQueryObject: { source: string, query: string }) => isNotEmpty(sourceQueryObject.source) && isNotEmpty(sourceQueryObject.query)),
|
filter((sourceQueryObject: ExternalSourceData) => isNotEmpty(sourceQueryObject.sourceId) && isNotEmpty(sourceQueryObject.query)),
|
||||||
switchMap((sourceQueryObject: { source: string, query: string }) => {
|
switchMap((sourceQueryObject: ExternalSourceData) => {
|
||||||
const source = sourceQueryObject.source;
|
|
||||||
const query = sourceQueryObject.query;
|
const query = sourceQueryObject.query;
|
||||||
this.routeData.sourceId = source;
|
this.routeData = sourceQueryObject;
|
||||||
this.routeData.query = query;
|
|
||||||
return this.searchConfigService.paginatedSearchOptions.pipe(
|
return this.searchConfigService.paginatedSearchOptions.pipe(
|
||||||
tap((v) => this.isLoading$.next(true)),
|
tap((v) => this.isLoading$.next(true)),
|
||||||
filter((searchOptions) => searchOptions.query === query),
|
filter((searchOptions) => searchOptions.query === query),
|
||||||
@@ -204,4 +202,16 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the correct button label, depending on the entity.
|
||||||
|
*
|
||||||
|
* @param entity The entity name
|
||||||
|
*/
|
||||||
|
private selectLabel(entity: string): void {
|
||||||
|
this.label = entity;
|
||||||
|
this.importConfig = {
|
||||||
|
buttonLabel: 'submission.sections.describe.relationship-lookup.external-source.import-button-title.' + this.label
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -3211,8 +3211,24 @@
|
|||||||
|
|
||||||
"submission.import-external.title": "Import metadata from an external source",
|
"submission.import-external.title": "Import metadata from an external source",
|
||||||
|
|
||||||
|
"submission.import-external.title.Journal": "Import a journal from an external source",
|
||||||
|
|
||||||
|
"submission.import-external.title.JournalIssue": "Import a journal issue from an external source",
|
||||||
|
|
||||||
|
"submission.import-external.title.JournalVolume": "Import a journal volume from an external source",
|
||||||
|
|
||||||
|
"submission.import-external.title.OrgUnit": "Import a publisher from an external source",
|
||||||
|
|
||||||
|
"submission.import-external.title.Person": "Import a person from an external source",
|
||||||
|
|
||||||
|
"submission.import-external.title.Project": "Import a project from an external source",
|
||||||
|
|
||||||
|
"submission.import-external.title.Publication": "Import a publication from an external source",
|
||||||
|
|
||||||
"submission.import-external.page.hint": "Enter a query above to find items from the web to import in to DSpace.",
|
"submission.import-external.page.hint": "Enter a query above to find items from the web to import in to DSpace.",
|
||||||
|
|
||||||
|
"submission.import-external.page.noentity": "An entity type must be selected in order to use this page. Select it using the 'Import metadata from an external source' button in 'MyDspace' page.",
|
||||||
|
|
||||||
"submission.import-external.back-to-my-dspace": "Back to MyDSpace",
|
"submission.import-external.back-to-my-dspace": "Back to MyDSpace",
|
||||||
|
|
||||||
"submission.import-external.search.placeholder": "Search the external source",
|
"submission.import-external.search.placeholder": "Search the external source",
|
||||||
|
Reference in New Issue
Block a user