From fb40b8f0315641e5e3d0fb858842688175ae0ea9 Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Thu, 18 Jun 2020 16:16:31 +0200 Subject: [PATCH 01/29] Submission from an external source initial commit --- .../import-external-page.component.html | 1 + .../import-external-page.component.scss | 0 .../import-external-page.component.spec.ts | 26 ++++ .../import-external-page.component.ts | 13 ++ .../import-external-page.module.ts | 28 ++++ .../import-external-routing.module.ts | 24 +++ .../my-dspace-new-submission.component.html | 3 + src/app/app-routing.module.ts | 1 + src/app/core/data/external-source.service.ts | 17 ++- ...n-import-external-searchbar.component.html | 24 +++ ...n-import-external-searchbar.component.scss | 12 ++ ...ion-import-external-searchbar.component.ts | 143 ++++++++++++++++++ .../submission-import-external.component.html | 24 +++ .../submission-import-external.component.scss | 0 .../submission-import-external.component.ts | 35 +++++ src/app/submission/submission.module.ts | 7 +- src/assets/i18n/en.json5 | 28 ++++ 17 files changed, 383 insertions(+), 3 deletions(-) create mode 100644 src/app/+import-external-page/import-external-page.component.html create mode 100644 src/app/+import-external-page/import-external-page.component.scss create mode 100644 src/app/+import-external-page/import-external-page.component.spec.ts create mode 100644 src/app/+import-external-page/import-external-page.component.ts create mode 100644 src/app/+import-external-page/import-external-page.module.ts create mode 100644 src/app/+import-external-page/import-external-routing.module.ts create mode 100644 src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html create mode 100644 src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss create mode 100644 src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts create mode 100644 src/app/submission/import-external/submission-import-external.component.html create mode 100644 src/app/submission/import-external/submission-import-external.component.scss create mode 100644 src/app/submission/import-external/submission-import-external.component.ts diff --git a/src/app/+import-external-page/import-external-page.component.html b/src/app/+import-external-page/import-external-page.component.html new file mode 100644 index 0000000000..5edccd55cb --- /dev/null +++ b/src/app/+import-external-page/import-external-page.component.html @@ -0,0 +1 @@ + diff --git a/src/app/+import-external-page/import-external-page.component.scss b/src/app/+import-external-page/import-external-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+import-external-page/import-external-page.component.spec.ts b/src/app/+import-external-page/import-external-page.component.spec.ts new file mode 100644 index 0000000000..e673959a32 --- /dev/null +++ b/src/app/+import-external-page/import-external-page.component.spec.ts @@ -0,0 +1,26 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ImportExternalPageComponent } from './import-external-page.component'; + +fdescribe('ImportExternalPageComponent', () => { + let component: ImportExternalPageComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ImportExternalPageComponent ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ImportExternalPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create ImportExternalPageComponent', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/+import-external-page/import-external-page.component.ts b/src/app/+import-external-page/import-external-page.component.ts new file mode 100644 index 0000000000..c205482cb3 --- /dev/null +++ b/src/app/+import-external-page/import-external-page.component.ts @@ -0,0 +1,13 @@ +import { Component, Injector, OnInit } from '@angular/core'; + +/** + * Component representing the external import page of the submission. + */ +@Component({ + selector: 'ds-import-external-page', + templateUrl: './import-external-page.component.html', + styleUrls: ['./import-external-page.component.scss'] +}) +export class ImportExternalPageComponent { + +} diff --git a/src/app/+import-external-page/import-external-page.module.ts b/src/app/+import-external-page/import-external-page.module.ts new file mode 100644 index 0000000000..c81e80615f --- /dev/null +++ b/src/app/+import-external-page/import-external-page.module.ts @@ -0,0 +1,28 @@ +import { CommonModule } from '@angular/common'; +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({ + imports: [ + CommonModule, + SharedModule, + CoreModule.forRoot(), + ImportExternalRoutingModule, + SubmissionModule, + ], + declarations: [ ], + entryComponents: [ ] +}) + +/** + * This module handles all components that are necessary for the submission external import page + */ +export class ImportExternalPageModule { + +} diff --git a/src/app/+import-external-page/import-external-routing.module.ts b/src/app/+import-external-page/import-external-routing.module.ts new file mode 100644 index 0000000000..91cdbf9877 --- /dev/null +++ b/src/app/+import-external-page/import-external-routing.module.ts @@ -0,0 +1,24 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; +import { SubmissionImportExternalComponent } from '../submission/import-external/submission-import-external.component'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + { + canActivate: [ AuthenticatedGuard ], + path: '', + component: SubmissionImportExternalComponent, + pathMatch: 'full', + data: { + title: 'submission.import-external.page.title' + } + } + ]) + ], + providers: [ ] +}) +export class ImportExternalRoutingModule { + +} diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html index 911ba26b31..3adaea7128 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html @@ -10,6 +10,9 @@ {{'mydspace.new-submission' | translate}} + + {{'mydspace.new-submission-external' | translate}} + diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 0ba0851e4e..655f0f94fc 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -86,6 +86,7 @@ export function getDSOPath(dso: DSpaceObject): string { { path: 'login', loadChildren: './+login-page/login-page.module#LoginPageModule' }, { path: 'logout', loadChildren: './+logout-page/logout-page.module#LogoutPageModule' }, { path: 'submit', loadChildren: './+submit-page/submit-page.module#SubmitPageModule' }, + { path: 'import-external', loadChildren: './+import-external-page/import-external-page.module#ImportExternalPageModule' }, { path: 'workspaceitems', loadChildren: './+workspaceitems-edit-page/workspaceitems-edit-page.module#WorkspaceitemsEditPageModule' diff --git a/src/app/core/data/external-source.service.ts b/src/app/core/data/external-source.service.ts index 0c1a8d255c..8ad0494f3d 100644 --- a/src/app/core/data/external-source.service.ts +++ b/src/app/core/data/external-source.service.ts @@ -11,7 +11,7 @@ import { NotificationsService } from '../../shared/notifications/notifications.s import { HttpClient } from '@angular/common/http'; import { FindListOptions, GetRequest } from './request.models'; import { Observable } from 'rxjs/internal/Observable'; -import { distinctUntilChanged, map, switchMap } from 'rxjs/operators'; +import { distinctUntilChanged, map, switchMap, take, flatMap } from 'rxjs/operators'; import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; import { hasValue, isNotEmptyOperator } from '../../shared/empty.util'; import { configureRequest } from '../shared/operators'; @@ -19,6 +19,7 @@ import { RemoteData } from './remote-data'; import { PaginatedList } from './paginated-list'; import { ExternalSourceEntry } from '../shared/external-source-entry.model'; import { DefaultChangeAnalyzer } from './default-change-analyzer.service'; +import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; /** * A service handling all external source requests @@ -59,6 +60,20 @@ export class ExternalSourceService extends DataService { ); } + /** + * Return the list of external sources. + * + * @param options + * Find list options object. + * @param linksToFollow + * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. + * @return Observable>> + * The list of the external sources. + */ + getAllExternalSources(options: FindListOptions = {}, ...linksToFollow: Array>): Observable>> { + return this.findAll(options, ...linksToFollow); + } + /** * Get the entries for an external source * @param externalSourceId The id of the external source to fetch entries for diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html new file mode 100644 index 0000000000..f7a971a381 --- /dev/null +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html @@ -0,0 +1,24 @@ +
+ +
+
+ + + +
+
+
diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss new file mode 100644 index 0000000000..076ceae9b8 --- /dev/null +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss @@ -0,0 +1,12 @@ +.input-group-append .btn.btn { + margin-left: -1px; +} + +.input-group-append .dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.w-fx { + min-width: 200px; +} 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 new file mode 100644 index 0000000000..e13c8dad3b --- /dev/null +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts @@ -0,0 +1,143 @@ +import { Component, OnInit, ChangeDetectorRef, Output, EventEmitter } from '@angular/core'; +import { of as observableOf } from 'rxjs'; +import { ExternalSourceService } from '../../../core/data/external-source.service'; +import { catchError, first, tap } from 'rxjs/operators'; +import { ExternalSource } from '../../../core/shared/external-source.model'; +import { PaginatedList } from '../../../core/data/paginated-list'; +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'; + +/** + * Interface for the selected external source element. + */ +interface SourceElement { + id: string; + name: string; +} + +/** + * Interface for the external source data to export. + */ +export interface ExternalSourceData { + query: string; + sourceId: string; +} + +/** + * This component builds the searchbar for the submission external import. + */ +@Component({ + selector: 'ds-submission-import-external-searchbar', + styleUrls: ['./submission-import-external-searchbar.component.scss'], + templateUrl: './submission-import-external-searchbar.component.html' +}) +export class SubmissionImportExternalSearchbarComponent implements OnInit { + /** + * The selected external sources. + */ + public selectedElement: SourceElement; + /** + * The list of external sources. + */ + public sourceList: SourceElement[] = []; + /** + * The string used to search items in the external sources. + */ + public searchString: string; + /** + * The external sources loading status. + */ + public sourceListloading = false; + /** + * The external source data to use to perform the search. + */ + @Output() public externalSourceData: EventEmitter = new EventEmitter(); + + /** + * The external sources pagination data. + */ + protected pageInfo: PageInfo; + /** + * The options for REST data retireval. + */ + protected findListOptions: FindListOptions; + + /** + * Initialize the component variables. + * @param {ExternalSourceService} externalService + * @param {ChangeDetectorRef} cdr + */ + constructor( + private externalService: ExternalSourceService, + private cdr: ChangeDetectorRef, + ) { } + + /** + * Component intitialization and retireve first page of external sources. + */ + ngOnInit() { + this.searchString = ''; + this.selectedElement = {id: '', name: 'loading'}; + this.findListOptions = { + elementsPerPage: 5, + currentPage: 0, + }; + this.externalService.getAllExternalSources(this.findListOptions).pipe( + catchError(() => { + const pageInfo = new PageInfo(); + const paginatedList = new PaginatedList(pageInfo, []); + const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + return observableOf(paginatedListRD); + }), + first() + ).subscribe((externalSource: RemoteData>) => { + externalSource.payload.page.forEach((element) => { + this.sourceList.push({id: element.id, name: element.name}); + this.selectedElement = this.sourceList[0]; + }); + this.pageInfo = externalSource.payload.pageInfo; + this.cdr.detectChanges(); + }); + } + + /** + * Set the selected external source. + */ + makeSourceSelection(source) { + this.selectedElement = source; + } + + /** + * Load the next pages of external sources. + */ + onScroll() { + if (!this.sourceListloading && this.pageInfo.currentPage <= this.pageInfo.totalPages) { + this.sourceListloading = true; + this.findListOptions.currentPage++; + this.externalService.getAllExternalSources(this.findListOptions).pipe( + catchError(() => { + const pageInfo = new PageInfo(); + const paginatedList = new PaginatedList(pageInfo, []); + 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(); + }) + } + } + + /** + * Passes the search parameters to the parent component. + */ + public search() { + this.externalSourceData.emit({sourceId: this.selectedElement.id, query: this.searchString}); + } +} diff --git a/src/app/submission/import-external/submission-import-external.component.html b/src/app/submission/import-external/submission-import-external.component.html new file mode 100644 index 0000000000..1d2c7cb7c7 --- /dev/null +++ b/src/app/submission/import-external/submission-import-external.component.html @@ -0,0 +1,24 @@ +
+
+
+ + + +
+
+
+
+ DATA
+ {{(externalSourceData)?externalSourceData.sourceId:''}} : {{(externalSourceData)?externalSourceData.query:''}} +
+
+ +
diff --git a/src/app/submission/import-external/submission-import-external.component.scss b/src/app/submission/import-external/submission-import-external.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/submission/import-external/submission-import-external.component.ts b/src/app/submission/import-external/submission-import-external.component.ts new file mode 100644 index 0000000000..2b53961540 --- /dev/null +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -0,0 +1,35 @@ +import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; +import { Observable, of as observableOf } from 'rxjs'; +import { ExternalSourceService } from '../../core/data/external-source.service'; +import { ExternalSourceData } from './import-external-searchbar/submission-import-external-searchbar.component'; + +/** + * This component allows to submit a new workspaceitem importing the data from an external source. + */ +@Component({ + selector: 'ds-submission-import-external', + styleUrls: ['./submission-import-external.component.scss'], + templateUrl: './submission-import-external.component.html' +}) +export class SubmissionImportExternalComponent { + /** + * The external source search data. + */ + public externalSourceData: ExternalSourceData; + + /** + * Initialize the component variables. + * @param {ExternalSourceService} externalService + */ + constructor( + private externalService: ExternalSourceService, + private cdr: ChangeDetectorRef, + ) { } + + /** + * Get the data to submit a search. + */ + public getExternalsourceData(event: ExternalSourceData) { + this.externalSourceData = event; + } +} diff --git a/src/app/submission/submission.module.ts b/src/app/submission/submission.module.ts index 806258baa8..f7accaf0ca 100644 --- a/src/app/submission/submission.module.ts +++ b/src/app/submission/submission.module.ts @@ -28,7 +28,8 @@ import { SubmissionSectionUploadFileViewComponent } from './sections/upload/file import { SubmissionSectionUploadAccessConditionsComponent } from './sections/upload/accessConditions/submission-section-upload-access-conditions.component'; import { SubmissionSubmitComponent } from './submit/submission-submit.component'; import { storeModuleConfig } from '../app.reducer'; -import { CoreState } from '../core/core.reducers'; +import { SubmissionImportExternalComponent } from './import-external/submission-import-external.component'; +import { SubmissionImportExternalSearchbarComponent } from './import-external/import-external-searchbar/submission-import-external-searchbar.component'; @NgModule({ imports: [ @@ -55,7 +56,9 @@ import { CoreState } from '../core/core.reducers'; SubmissionUploadFilesComponent, SubmissionSectionUploadFileComponent, SubmissionSectionUploadFileEditComponent, - SubmissionSectionUploadFileViewComponent + SubmissionSectionUploadFileViewComponent, + SubmissionImportExternalComponent, + SubmissionImportExternalSearchbarComponent, ], entryComponents: [ SubmissionSectionUploadComponent, diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 4173fa1cf2..bd0f23d24e 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1767,6 +1767,8 @@ "mydspace.new-submission": "New submission", + "mydspace.new-submission-external": "Import from external source", + "mydspace.results.head": "Your submissions", "mydspace.results.no-abstract": "No Abstract", @@ -2396,6 +2398,32 @@ "submission.general.save-later": "Save for later", + "submission.import-external.page.title": "Import metadata from an external source", + + "submission.import-external.title": "Import metadata from an external source", + + "submission.import-external.back-to-my-dspace": "Back to MyDSpace", + + "submission.import-external.search.placeholder": "Search the external source", + + "submission.import-external.search.button": "Search", + + "submission.import-external.search.button.hint": "Write some words to search", + + "submission.import-external.search.source.hint": "Pick an external source", + + "submission.import-external.source.loading": "Loading ...", + + "submission.import-external.source.sherpaJournal": "SHERPA Journals", + + "submission.import-external.source.sherpaPublisher": "SHERPA Publishers", + + "submission.import-external.source.orcidV2": "ORCID", + + "submission.import-external.source.pubmed": "Pubmed", + + "submission.import-external.source.lcname": "Library of Congress Names", + "submission.sections.describe.relationship-lookup.close": "Close", From 63cff331d2445718b39941a4548b87654d81c81b Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 18 Jun 2020 19:01:34 +0200 Subject: [PATCH 02/29] Fixed scrollable dropdown --- ...n-import-external-searchbar.component.html | 34 ++++++----- ...n-import-external-searchbar.component.scss | 22 +++++++- ...ion-import-external-searchbar.component.ts | 56 ++++++++++++------- .../submission-import-external.component.html | 1 + 4 files changed, 72 insertions(+), 41 deletions(-) diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html index f7a971a381..a63828568d 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html @@ -1,24 +1,22 @@
-
-
- - diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss index 076ceae9b8..562b5b5613 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss @@ -1,12 +1,28 @@ -.input-group-append .btn.btn { +.input-group-append .btn { margin-left: -1px; + border-top-left-radius: 0; + border-bottom-left-radius: 0; } .input-group-append .dropdown-toggle { - border-top-right-radius: 0; - border-bottom-right-radius: 0; + border-radius: 0; } .w-fx { min-width: 200px; } + +.scrollable-menu { + height: auto; + max-height: $dropdown-menu-max-height; + overflow-x: hidden; +} + +.scrollable-dropdown-loading { + background-color: map-get($theme-colors, primary); + color: white; + height: $spacer * 2 !important; + line-height: $spacer * 2; + position: sticky; + bottom: 0; +} 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 e13c8dad3b..039d11de30 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 @@ -1,13 +1,17 @@ -import { Component, OnInit, ChangeDetectorRef, Output, EventEmitter } from '@angular/core'; +import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; + import { of as observableOf } from 'rxjs'; +import { catchError, tap } from 'rxjs/operators'; + import { ExternalSourceService } from '../../../core/data/external-source.service'; -import { catchError, first, tap } from 'rxjs/operators'; import { ExternalSource } from '../../../core/shared/external-source.model'; import { PaginatedList } from '../../../core/data/paginated-list'; 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. @@ -34,6 +38,10 @@ export interface ExternalSourceData { templateUrl: './submission-import-external-searchbar.component.html' }) export class SubmissionImportExternalSearchbarComponent implements OnInit { + /** + * The init external source value. + */ + @Input() public initExternalSourceValue: string; /** * The selected external sources. */ @@ -49,7 +57,7 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { /** * The external sources loading status. */ - public sourceListloading = false; + public sourceListLoading = false; /** * The external source data to use to perform the search. */ @@ -72,18 +80,19 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { constructor( private externalService: ExternalSourceService, private cdr: ChangeDetectorRef, - ) { } + ) { + } /** - * Component intitialization and retireve first page of external sources. + * Component initialization and retrieve first page of external sources. */ ngOnInit() { this.searchString = ''; - this.selectedElement = {id: '', name: 'loading'}; - this.findListOptions = { + this.selectedElement = { id: '', name: 'loading' }; + this.findListOptions = Object.assign({}, new FindListOptions(), { elementsPerPage: 5, currentPage: 0, - }; + }); this.externalService.getAllExternalSources(this.findListOptions).pipe( catchError(() => { const pageInfo = new PageInfo(); @@ -91,13 +100,17 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); return observableOf(paginatedListRD); }), - first() - ).subscribe((externalSource: RemoteData>) => { - externalSource.payload.page.forEach((element) => { - this.sourceList.push({id: element.id, name: element.name}); - this.selectedElement = this.sourceList[0]; + getFirstSucceededRemoteDataPayload() + ).subscribe((externalSource: PaginatedList) => { + let initEntry; + externalSource.page.forEach((element) => { + this.sourceList.push({ id: element.id, name: element.name }); + if (isEmpty(initEntry) || this.initExternalSourceValue === element.id) { + initEntry = { id: element.id, name: element.name } + } }); - this.pageInfo = externalSource.payload.pageInfo; + this.selectedElement = initEntry; + this.pageInfo = externalSource.pageInfo; this.cdr.detectChanges(); }); } @@ -113,9 +126,12 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { * Load the next pages of external sources. */ onScroll() { - if (!this.sourceListloading && this.pageInfo.currentPage <= this.pageInfo.totalPages) { - this.sourceListloading = true; - this.findListOptions.currentPage++; + if (!this.sourceListLoading && this.pageInfo.currentPage <= this.pageInfo.totalPages) { + this.sourceListLoading = true; + this.findListOptions = Object.assign({}, new FindListOptions(), { + elementsPerPage: 5, + currentPage: this.findListOptions.currentPage + 1, + }); this.externalService.getAllExternalSources(this.findListOptions).pipe( catchError(() => { const pageInfo = new PageInfo(); @@ -123,10 +139,10 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); return observableOf(paginatedListRD); }), - tap(() => this.sourceListloading = false)) + tap(() => this.sourceListLoading = false)) .subscribe((externalSource: RemoteData>) => { externalSource.payload.page.forEach((element) => { - this.sourceList.push({id: element.id, name: element.name}); + this.sourceList.push({ id: element.id, name: element.name }); }) this.pageInfo = externalSource.payload.pageInfo; this.cdr.detectChanges(); @@ -138,6 +154,6 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { * Passes the search parameters to the parent component. */ public search() { - this.externalSourceData.emit({sourceId: this.selectedElement.id, query: this.searchString}); + this.externalSourceData.emit({ sourceId: this.selectedElement.id, query: this.searchString }); } } diff --git a/src/app/submission/import-external/submission-import-external.component.html b/src/app/submission/import-external/submission-import-external.component.html index 1d2c7cb7c7..43e1c8ba71 100644 --- a/src/app/submission/import-external/submission-import-external.component.html +++ b/src/app/submission/import-external/submission-import-external.component.html @@ -3,6 +3,7 @@
From e7ef9dab20b7265555123df69ca0f1a27ab6cb20 Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Mon, 22 Jun 2020 19:59:10 +0200 Subject: [PATCH 03/29] External source items import code completed --- .../import-external-page.component.spec.ts | 2 +- .../core/data/external-source.service.spec.ts | 17 +++ src/app/core/data/external-source.service.ts | 16 +- ...ion-import-external-searchbar.component.ts | 20 ++- .../submission-import-external.component.html | 29 +++- .../submission-import-external.component.ts | 137 ++++++++++++++++-- src/app/submission/submission.module.ts | 6 +- src/assets/i18n/en.json5 | 10 ++ 8 files changed, 213 insertions(+), 24 deletions(-) diff --git a/src/app/+import-external-page/import-external-page.component.spec.ts b/src/app/+import-external-page/import-external-page.component.spec.ts index e673959a32..5a2b7c5f8e 100644 --- a/src/app/+import-external-page/import-external-page.component.spec.ts +++ b/src/app/+import-external-page/import-external-page.component.spec.ts @@ -2,7 +2,7 @@ import { NO_ERRORS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ImportExternalPageComponent } from './import-external-page.component'; -fdescribe('ImportExternalPageComponent', () => { +describe('ImportExternalPageComponent', () => { let component: ImportExternalPageComponent; let fixture: ComponentFixture; diff --git a/src/app/core/data/external-source.service.spec.ts b/src/app/core/data/external-source.service.spec.ts index 7c7d676bc7..2fc4589bed 100644 --- a/src/app/core/data/external-source.service.spec.ts +++ b/src/app/core/data/external-source.service.spec.ts @@ -74,4 +74,21 @@ describe('ExternalSourceService', () => { }); }); }); + + describe('getAllExternalSources', () => { + it('should call findAll', () => { + spyOn(service, 'findAll'); + service.getAllExternalSources(); + expect(service.findAll).toHaveBeenCalled(); + }); + }); + + describe('getExternalSource', () => { + it('should call findById', () => { + const externalSourceId = 'orcidV2'; + spyOn(service, 'findById'); + service.getExternalSource(externalSourceId); + expect(service.findById).toHaveBeenCalledWith(externalSourceId); + }); + }); }); diff --git a/src/app/core/data/external-source.service.ts b/src/app/core/data/external-source.service.ts index 8ad0494f3d..eda0440b4a 100644 --- a/src/app/core/data/external-source.service.ts +++ b/src/app/core/data/external-source.service.ts @@ -11,7 +11,7 @@ import { NotificationsService } from '../../shared/notifications/notifications.s import { HttpClient } from '@angular/common/http'; import { FindListOptions, GetRequest } from './request.models'; import { Observable } from 'rxjs/internal/Observable'; -import { distinctUntilChanged, map, switchMap, take, flatMap } from 'rxjs/operators'; +import { distinctUntilChanged, map, switchMap, take, flatMap, catchError } from 'rxjs/operators'; import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; import { hasValue, isNotEmptyOperator } from '../../shared/empty.util'; import { configureRequest } from '../shared/operators'; @@ -60,6 +60,20 @@ export class ExternalSourceService extends DataService { ); } + /** + * Return a single external source. + * + * @param id + * The external source id. + * @param linksToFollow + * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. + * @return Observable> + * The list of the external sources. + */ + getExternalSource(id: string, ...linksToFollow: Array>): Observable> { + return this.findById(id, ...linksToFollow); + } + /** * Return the list of external sources. * 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 039d11de30..cd2f24eb2c 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 @@ -41,7 +41,7 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { /** * The init external source value. */ - @Input() public initExternalSourceValue: string; + @Input() public initExternalSourceData: ExternalSourceData; /** * The selected external sources. */ @@ -49,7 +49,7 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { /** * The list of external sources. */ - public sourceList: SourceElement[] = []; + public sourceList: SourceElement[]; /** * The string used to search items in the external sources. */ @@ -87,8 +87,12 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { * Component initialization and retrieve first page of external sources. */ ngOnInit() { + this.selectedElement = { + id: '', + name: 'loading' + }; this.searchString = ''; - this.selectedElement = { id: '', name: 'loading' }; + this.sourceList = []; this.findListOptions = Object.assign({}, new FindListOptions(), { elementsPerPage: 5, currentPage: 0, @@ -102,14 +106,16 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { }), getFirstSucceededRemoteDataPayload() ).subscribe((externalSource: PaginatedList) => { - let initEntry; externalSource.page.forEach((element) => { this.sourceList.push({ id: element.id, name: element.name }); - if (isEmpty(initEntry) || this.initExternalSourceValue === element.id) { - initEntry = { id: element.id, name: element.name } + if (this.initExternalSourceData.sourceId === element.id) { + this.selectedElement = { id: element.id, name: element.name }; + this.searchString = this.initExternalSourceData.query; } }); - this.selectedElement = initEntry; + if (this.selectedElement.id === '') { + this.selectedElement = this.sourceList[0]; + } this.pageInfo = externalSource.pageInfo; this.cdr.detectChanges(); }); diff --git a/src/app/submission/import-external/submission-import-external.component.html b/src/app/submission/import-external/submission-import-external.component.html index 43e1c8ba71..2aac8557aa 100644 --- a/src/app/submission/import-external/submission-import-external.component.html +++ b/src/app/submission/import-external/submission-import-external.component.html @@ -3,15 +3,36 @@
-
- DATA
- {{(externalSourceData)?externalSourceData.sourceId:''}} : {{(externalSourceData)?externalSourceData.query:''}} +
+ +

{{ 'submission.sections.describe.relationship-lookup.selection-tab.title.' + routeData.sourceId | translate}}

+ + + +
+ {{ 'search.results.empty' | translate }} +
+
+
+
+
+

{{'submission.import-external.page.hint' | translate}}

+
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 2b53961540..47ae781baa 100644 --- a/src/app/submission/import-external/submission-import-external.component.ts +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -1,7 +1,22 @@ -import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; -import { Observable, of as observableOf } from 'rxjs'; +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { combineLatest, BehaviorSubject } from 'rxjs'; import { ExternalSourceService } from '../../core/data/external-source.service'; import { ExternalSourceData } from './import-external-searchbar/submission-import-external-searchbar.component'; +import { RemoteData } from '../../core/data/remote-data'; +import { PaginatedList } from '../../core/data/paginated-list'; +import { ExternalSourceEntry } from '../../core/shared/external-source-entry.model'; +import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; +import { switchMap, filter } from 'rxjs/operators'; +import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; +import { Context } from '../../core/shared/context.model'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { RouteService } from '../../core/services/route.service'; +import { createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils'; +import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { SubmissionImportExternalPreviewComponent } from './import-external-preview/submission-import-external-preview.component'; +import { fadeIn } from '../../shared/animations/fade'; +import { createPaginatedList } from '../../shared/testing/utils.test'; /** * This component allows to submit a new workspaceitem importing the data from an external source. @@ -9,27 +24,129 @@ import { ExternalSourceData } from './import-external-searchbar/submission-impor @Component({ selector: 'ds-submission-import-external', styleUrls: ['./submission-import-external.component.scss'], - templateUrl: './submission-import-external.component.html' + templateUrl: './submission-import-external.component.html', + animations: [ fadeIn ] }) -export class SubmissionImportExternalComponent { +export class SubmissionImportExternalComponent implements OnInit { /** - * The external source search data. + * The external source search data from the routing service. */ - public externalSourceData: ExternalSourceData; + public routeData: ExternalSourceData; + /** + * The displayed list of entries + */ + public entriesRD$: BehaviorSubject>>; + /** + * TRUE if the REST service is called to retrieve the external source items + */ + public isLoading$: BehaviorSubject; + /** + * Configuration to use for the import buttons + */ + public importConfig: { buttonLabel: string }; + /** + * Suffix for button label + */ + public label: string; + /** + * The ID of the list to add/remove selected items to/from + */ + public listId: string; + /** + * TRUE if the selection is repeatable + */ + public repeatable: boolean; + /** + * The initial pagination options + */ + public initialPagination = Object.assign(new PaginationComponentOptions(), { + id: 'submission-external-source-relation-list', + pageSize: 5 + }); + /** + * The context to displaying lists for + */ + public context: Context; + /** + * The modal for the entry preview + */ + modalRef: NgbModalRef; /** * Initialize the component variables. + * @param {SearchConfigurationService} searchConfigService * @param {ExternalSourceService} externalService + * @param {RouteService} routeService + * @param {Router} router + * @param {NgbModal} modalService */ constructor( + public searchConfigService: SearchConfigurationService, private externalService: ExternalSourceService, - private cdr: ChangeDetectorRef, + private routeService: RouteService, + private router: Router, + private modalService: NgbModal, ) { } /** - * Get the data to submit a search. + * Get the entries for the selected external source and set initial configuration. */ - public getExternalsourceData(event: ExternalSourceData) { - this.externalSourceData = event; + ngOnInit(): void { + this.label = 'Journal'; + this.listId = 'list-submission-external-sources'; + this.context = Context.SubmissionModal; + this.repeatable = false; + this.routeData = { sourceId: '', query: '' }; + this.importConfig = { + buttonLabel: 'submission.sections.describe.relationship-lookup.external-source.import-button-title.' + this.label + }; + this.entriesRD$ = new BehaviorSubject(createSuccessfulRemoteDataObject(createPaginatedList([]))); + this.isLoading$ = new BehaviorSubject(false); + combineLatest( + [ + this.routeService.getQueryParameterValue('source'), + this.routeService.getQueryParameterValue('query') + ]).pipe( + filter(([source, query]) => source && query && source !== '' && query !== ''), + filter(([source, query]) => source !== this.routeData.sourceId || query !== this.routeData.query), + switchMap(([source, query]) => { + this.routeData.sourceId = source; + this.routeData.query = query; + this.isLoading$.next(true); + return this.searchConfigService.paginatedSearchOptions.pipe( + switchMap((searchOptions: PaginatedSearchOptions) => { + return this.externalService.getExternalSourceEntries(this.routeData.sourceId, searchOptions); + }) + ) + }), + ).subscribe((rdData) => { + this.entriesRD$.next(rdData); + this.isLoading$.next(false); + }); + } + + /** + * Get the data from the searchbar and changes the router data. + */ + public getExternalsourceData(event: ExternalSourceData): void { + this.router.navigate( + [], + { + queryParams: { source: event.sourceId, query: event.query }, + replaceUrl: true + } + ); + } + + /** + * Display an item preview by opening up an import modal window. + * @param entry The entry to import + */ + public import(entry): void { + this.modalRef = this.modalService.open(SubmissionImportExternalPreviewComponent, { + size: 'lg', + }); + const modalComp = this.modalRef.componentInstance; + modalComp.externalSourceEntry = entry; } } diff --git a/src/app/submission/submission.module.ts b/src/app/submission/submission.module.ts index f7accaf0ca..7ff8b98d9e 100644 --- a/src/app/submission/submission.module.ts +++ b/src/app/submission/submission.module.ts @@ -30,6 +30,7 @@ import { SubmissionSubmitComponent } from './submit/submission-submit.component' 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'; @NgModule({ imports: [ @@ -59,12 +60,15 @@ import { SubmissionImportExternalSearchbarComponent } from './import-external/im SubmissionSectionUploadFileViewComponent, SubmissionImportExternalComponent, SubmissionImportExternalSearchbarComponent, + SubmissionImportExternalPreviewComponent ], entryComponents: [ SubmissionSectionUploadComponent, SubmissionSectionformComponent, SubmissionSectionLicenseComponent, - SubmissionSectionContainerComponent], + SubmissionSectionContainerComponent, + SubmissionImportExternalPreviewComponent + ], exports: [ SubmissionEditComponent, SubmissionFormComponent, diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index bd0f23d24e..3e2994142d 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2402,6 +2402,8 @@ "submission.import-external.title": "Import metadata from an external source", + "submission.import-external.page.hint": "Search items using external sources.", + "submission.import-external.back-to-my-dspace": "Back to MyDSpace", "submission.import-external.search.placeholder": "Search the external source", @@ -2424,6 +2426,12 @@ "submission.import-external.source.lcname": "Library of Congress Names", + "submission.import-external.preview.title": "Item Preview", + + "submission.import-external.preview.subtitle": "The metadata below was imported from an external source. It will be pre-filled when you start the submission.", + + "submission.import-external.preview.button.import": "Start submission", + "submission.sections.describe.relationship-lookup.close": "Close", @@ -2555,6 +2563,8 @@ "submission.sections.describe.relationship-lookup.selection-tab.title.orcidV2": "Search Results", + "submission.sections.describe.relationship-lookup.selection-tab.title.orcidv2": "Search Results", + "submission.sections.describe.relationship-lookup.selection-tab.title.lcname": "Search Results", "submission.sections.describe.relationship-lookup.name-variant.notification.content": "Would you like to save \"{{ value }}\" as a name variant for this person so you and others can reuse it for future submissions? If you don\'t you can still use it for this submission.", From 2f04b6ae831c72cb129edb4b0ad7e46b9dee8692 Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Mon, 22 Jun 2020 19:59:29 +0200 Subject: [PATCH 04/29] External source items import new files --- .../mocks/external-source.service.mock.ts | 12 +++ ...ion-import-external-preview.component.html | 39 ++++++++ ...ion-import-external-preview.component.scss | 3 + ...ssion-import-external-preview.component.ts | 70 ++++++++++++++ ...mport-external-searchbar.component.spec.ts | 91 +++++++++++++++++++ ...bmission-import-external.component.spec.ts | 0 6 files changed, 215 insertions(+) create mode 100644 src/app/shared/mocks/external-source.service.mock.ts create mode 100644 src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html create mode 100644 src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.scss create mode 100644 src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.ts create mode 100644 src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts create mode 100644 src/app/submission/import-external/submission-import-external.component.spec.ts diff --git a/src/app/shared/mocks/external-source.service.mock.ts b/src/app/shared/mocks/external-source.service.mock.ts new file mode 100644 index 0000000000..80e40512c5 --- /dev/null +++ b/src/app/shared/mocks/external-source.service.mock.ts @@ -0,0 +1,12 @@ +// import { ExternalSourceService } from '../../core/data/external-source.service'; + +/** + * Mock for [[ExternalSourceService]] + */ +/*export function getMockExternalSourceService(): +ExternalSourceService { + return jasmine.createSpyObj('ExternalSourceService', { + getAllExternalSources: jasmine.createSpy('getAllExternalSources'), + getExternalSourceEntries: jasmine.createSpy('getExternalSourceEntries'), + }); +}*/ 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 new file mode 100644 index 0000000000..29f1804f1f --- /dev/null +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html @@ -0,0 +1,39 @@ + + diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.scss b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.scss new file mode 100644 index 0000000000..1a70081367 --- /dev/null +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.scss @@ -0,0 +1,3 @@ +.close:focus { + outline: none !important; +} 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 new file mode 100644 index 0000000000..de86bba3b1 --- /dev/null +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.ts @@ -0,0 +1,70 @@ +import { Component, OnInit } from '@angular/core'; +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'; + +/** + * This component display a preview of an external source item. + */ +@Component({ + selector: 'ds-submission-import-external-preview', + styleUrls: ['./submission-import-external-preview.component.scss'], + templateUrl: './submission-import-external-preview.component.html' +}) +export class SubmissionImportExternalPreviewComponent implements OnInit { + /** + * The external source entry + */ + public externalSourceEntry: ExternalSourceEntry; + /** + * The entry metadata list + */ + public metadataList: Array<{ key: string, value: MetadataValue }>; + /** + * The modal for the entry preview + */ + modalRef: NgbModalRef; + + /** + * Initialize the component variables. + * @param {NgbActiveModal} activeModal + */ + constructor( + private activeModal: NgbActiveModal, + private modalService: NgbModal + ) { } + + /** + * Metadata initialization for HTML display. + */ + ngOnInit(): void { + this.metadataList = []; + const metadataKeys = Object.keys(this.externalSourceEntry.metadata); + metadataKeys.forEach((key) => { + this.metadataList.push({ + key: key, + value: Metadata.first(this.externalSourceEntry.metadata, key) + }); + }) + } + + /** + * Closes the modal. + */ + public closeMetadataModal(): void { + this.activeModal.dismiss(false); + } + + /** + * Start the import of an entry by opening up an import modal window. + * @param entry The entry to import + */ + public import(entry): void { + this.modalRef = this.modalService.open(SubmissionImportExternalPreviewComponent, { + size: 'lg', + }); + const modalComp = this.modalRef.componentInstance; + modalComp.externalSourceEntry = entry; + } +} 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 new file mode 100644 index 0000000000..66ce798ed9 --- /dev/null +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts @@ -0,0 +1,91 @@ +// 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'; + +/*describe('SubmissionImportExternalSearchbarComponent test suite', () => { + let comp: SubmissionImportExternalSearchbarComponent; + let compAsAny: any; + let fixture: ComponentFixture; + + beforeEach(async (() => { + TestBed.configureTestingModule({ + imports: [ + SubmissionModule, + TranslateModule.forRoot(), + ], + declarations: [ + SubmissionImportExternalSearchbarComponent, + TestComponent, + ], + providers: [ + { provide: ExternalSourceService, useClass: getMockExternalSourceService }, + ChangeDetectorRef, + SubmissionImportExternalSearchbarComponent + ], + 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 SubmissionImportExternalSearchbarComponent', inject([SubmissionImportExternalSearchbarComponent], (app: SubmissionImportExternalSearchbarComponent) => { + expect(app).toBeDefined(); + })); + });*/ + + /*describe('', () => { + beforeEach(() => { + fixture = TestBed.createComponent(SubmissionImportExternalSearchbarComponent); + comp = fixture.componentInstance; + compAsAny = comp; + // compAsAny.externalService.getAllExternalSources.and.returnValue(observableOf([ + + // ])); + }); + + afterEach(() => { + fixture.destroy(); + comp = null; + compAsAny = null; + }); + + it('Should init component properly', () => { + comp.ngOnInit(); + fixture.detectChanges(); + + expect(comp.selectedElement) + expect(compAsAny.pageInfo) + expect(comp.sourceList) + }); + });*/ +/* +}); + +// declare a test component +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { + +}*/ 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 new file mode 100644 index 0000000000..e69de29bb2 From b4ec056d036ce8a39150e289365bc3e7b4e353cd Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Mon, 22 Jun 2020 20:23:54 +0200 Subject: [PATCH 05/29] Removing file for conflicts --- .../my-dspace-new-submission.component.html | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html deleted file mode 100644 index 3adaea7128..0000000000 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html +++ /dev/null @@ -1,18 +0,0 @@ - From c2c650fa1a17c1e879b7f1ccf3c68d6c27809e28 Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Mon, 22 Jun 2020 20:26:04 +0200 Subject: [PATCH 06/29] External import button added --- .../my-dspace-new-submission.component.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html index 4809f206ae..da5519eb07 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html @@ -10,6 +10,9 @@ + + {{'mydspace.new-submission-external' | translate}} +
From 43f5e08530c7a8838eb028131df65c69c3069d24 Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Wed, 24 Jun 2020 10:16:30 +0200 Subject: [PATCH 07/29] External source import completed with tests --- .../import-external-page.component.ts | 2 +- .../import-external-page.module.ts | 2 - .../collection-dropdown.component.ts | 2 +- .../mocks/external-source.service.mock.ts | 53 +++++- src/app/shared/shared.module.ts | 3 +- .../shared/testing/submission-service.stub.ts | 1 + ...-import-external-collection.component.html | 11 ++ ...-import-external-collection.component.scss | 3 + ...port-external-collection.component.spec.ts | 89 ++++++++++ ...on-import-external-collection.component.ts | 40 +++++ ...ion-import-external-preview.component.html | 4 +- ...-import-external-preview.component.spec.ts | 153 +++++++++++++++++ ...ssion-import-external-preview.component.ts | 44 ++++- ...mport-external-searchbar.component.spec.ts | 102 ++++++++--- ...ion-import-external-searchbar.component.ts | 23 ++- ...bmission-import-external.component.spec.ts | 159 ++++++++++++++++++ .../submission-import-external.component.ts | 2 +- src/app/submission/submission.module.ts | 7 +- src/app/submission/submission.service.spec.ts | 13 ++ src/app/submission/submission.service.ts | 18 ++ src/assets/i18n/en.json5 | 4 + 21 files changed, 681 insertions(+), 54 deletions(-) create mode 100644 src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.html create mode 100644 src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.scss create mode 100644 src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.spec.ts create mode 100644 src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.ts create mode 100644 src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts 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", From 1f54094d5a7554cf577bf243fdd8571314fc1691 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 24 Jun 2020 10:31:54 +0200 Subject: [PATCH 08/29] Fixed components import --- src/app/+import-external-page/import-external-page.module.ts | 5 ++++- src/app/submission/submission.module.ts | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) 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 8dae7c2f88..017c723ad9 100644 --- a/src/app/+import-external-page/import-external-page.module.ts +++ b/src/app/+import-external-page/import-external-page.module.ts @@ -5,6 +5,7 @@ import { SharedModule } from '../shared/shared.module'; import { CoreModule } from '../core/core.module'; import { ImportExternalRoutingModule } from './import-external-routing.module'; import { SubmissionModule } from '../submission/submission.module'; +import { ImportExternalPageComponent } from './import-external-page.component'; @NgModule({ imports: [ @@ -14,7 +15,9 @@ import { SubmissionModule } from '../submission/submission.module'; ImportExternalRoutingModule, SubmissionModule, ], - declarations: [ ], + declarations: [ + ImportExternalPageComponent + ], entryComponents: [ ] }) diff --git a/src/app/submission/submission.module.ts b/src/app/submission/submission.module.ts index 4e5e5bc6da..9446286c52 100644 --- a/src/app/submission/submission.module.ts +++ b/src/app/submission/submission.module.ts @@ -75,7 +75,8 @@ import { SubmissionImportExternalCollectionComponent } from './import-external/i exports: [ SubmissionEditComponent, SubmissionFormComponent, - SubmissionSubmitComponent + SubmissionSubmitComponent, + SubmissionImportExternalComponent ], providers: [ SectionUploadService, From 74d1e0bccb53c8d4995c8f034eadbcecde415b54 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 24 Jun 2020 10:48:29 +0200 Subject: [PATCH 09/29] Fixed issue with spyOn --- .../import-external/submission-import-external.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 70fdd5f477..9988f098c9 100644 --- a/src/app/submission/import-external/submission-import-external.component.ts +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -16,7 +16,7 @@ import { createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { SubmissionImportExternalPreviewComponent } from './import-external-preview/submission-import-external-preview.component'; import { fadeIn } from '../../shared/animations/fade'; -import { createPaginatedList } from '../../shared/testing/utils.test'; +import { PageInfo } from '../../core/shared/page-info.model'; /** * This component allows to submit a new workspaceitem importing the data from an external source. @@ -100,7 +100,7 @@ export class SubmissionImportExternalComponent implements OnInit { this.importConfig = { buttonLabel: 'submission.sections.describe.relationship-lookup.external-source.import-button-title.' + this.label }; - this.entriesRD$ = new BehaviorSubject(createSuccessfulRemoteDataObject(createPaginatedList([]))); + this.entriesRD$ = new BehaviorSubject(createSuccessfulRemoteDataObject(new PaginatedList(new PageInfo(), []))); this.isLoading$ = new BehaviorSubject(false); combineLatest( [ From c25085b299258bec0d66bac11873188b0ab304da Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Wed, 24 Jun 2020 11:52:34 +0200 Subject: [PATCH 10/29] Lint errors fixed --- src/app/shared/mocks/external-source.service.mock.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app/shared/mocks/external-source.service.mock.ts b/src/app/shared/mocks/external-source.service.mock.ts index 4edf9efb14..3e96eb508e 100644 --- a/src/app/shared/mocks/external-source.service.mock.ts +++ b/src/app/shared/mocks/external-source.service.mock.ts @@ -9,10 +9,10 @@ export const externalSourceOrcid: ExternalSource = { hierarchical: false, _links: { entries: { - href: "https://dspace7.4science.cloud/server/api/integration/externalsources/orcid/entries" + href: 'https://dspace7.4science.cloud/server/api/integration/externalsources/orcid/entries' }, self: { - href: "https://dspace7.4science.cloud/server/api/integration/externalsources/orcid" + href: 'https://dspace7.4science.cloud/server/api/integration/externalsources/orcid' } } }; @@ -24,10 +24,10 @@ export const externalSourceCiencia: ExternalSource = { hierarchical: false, _links: { entries: { - href: "https://dspace7.4science.cloud/server/api/integration/externalsources/ciencia/entries" + href: 'https://dspace7.4science.cloud/server/api/integration/externalsources/ciencia/entries' }, self: { - href: "https://dspace7.4science.cloud/server/api/integration/externalsources/ciencia" + href: 'https://dspace7.4science.cloud/server/api/integration/externalsources/ciencia' } } }; @@ -39,10 +39,10 @@ export const externalSourceMyStaffDb: ExternalSource = { hierarchical: false, _links: { entries: { - href: "https://dspace7.4science.cloud/server/api/integration/externalsources/my_staff_db/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" + href: 'https://dspace7.4science.cloud/server/api/integration/externalsources/my_staff_db' } } }; From ba46f243c8dd68b3ab41b8b23bf964d2a2d114ab Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Wed, 24 Jun 2020 15:38:45 +0200 Subject: [PATCH 11/29] Test fix for CI --- ...ion-import-external-preview.component.html | 2 +- ...-import-external-preview.component.spec.ts | 5 ++-- src/assets/i18n/en.json5 | 25 ++++++++++++++++++- 3 files changed, 27 insertions(+), 5 deletions(-) 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 0f155286ce..83c1ed82b6 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 @@ -19,7 +19,7 @@
- {{metadata.key}} + {{'item.preview.' + metadata.key | translate}}

{{metadata.value.value}}

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 index 66dfc72e6b..71360b9cc3 100644 --- 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 @@ -48,8 +48,8 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { { provide: Router, useValue: new RouterStub() }, { provide: SubmissionService, useValue: new SubmissionServiceStub() }, { provide: NotificationsService, useValue: new NotificationsServiceStub() }, - NgbModal, - NgbActiveModal, + { provide: NgbModal, useValue: { open: () => {/*comment*/} } }, + { provide: NgbActiveModal, useValue: { dismiss: () => {/*comment*/} } }, SubmissionImportExternalPreviewComponent ], schemas: [NO_ERRORS_SCHEMA] @@ -97,7 +97,6 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { const expected = [ { key: 'dc.identifier.uri', value: Metadata.first(comp.externalSourceEntry.metadata, 'dc.identifier.uri') } ]; - comp.ngOnInit(); fixture.detectChanges(); expect(comp.metadataList).toEqual(expected); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index d5c761dae1..cb5a5b956a 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1425,6 +1425,28 @@ "item.page.uri": "URI", + "item.preview.dc.identifier.uri": "Identifier:", + + "item.preview.dc.contributor.author": "Authors:", + + "item.preview.dc.date.issued": "Published date:", + + "item.preview.dc.description.abstract": "Abstract:", + + "item.preview.dc.identifier.other": "Other identifier:", + + "item.preview.dc.language.iso": "Language:", + + "item.preview.dc.subject": "Subjects:", + + "item.preview.dc.title": "Title:", + + "item.preview.person.familyName": "Surname:", + + "item.preview.person.givenName": "Name:", + + "item.preview.person.identifier.orcid": "ORCID:", + "item.select.confirm": "Confirm selected", @@ -2440,7 +2462,6 @@ "submission.import-external.preview.error.import.body": "An error occurs during the external source entry import process.", - "submission.sections.describe.relationship-lookup.close": "Close", "submission.sections.describe.relationship-lookup.external-source.added": "Successfully added local entry to the selection", @@ -2575,6 +2596,8 @@ "submission.sections.describe.relationship-lookup.selection-tab.title.lcname": "Search Results", + "submission.sections.describe.relationship-lookup.selection-tab.title.pubmed": "Search Results", + "submission.sections.describe.relationship-lookup.name-variant.notification.content": "Would you like to save \"{{ value }}\" as a name variant for this person so you and others can reuse it for future submissions? If you don\'t you can still use it for this submission.", "submission.sections.describe.relationship-lookup.name-variant.notification.confirm": "Save a new name variant", From 9ada61db2874730bc94fa7da7305e7b055975b6b Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Thu, 25 Jun 2020 16:58:43 +0200 Subject: [PATCH 12/29] Multiple call to external source service fix --- .../import-external/submission-import-external.component.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 9988f098c9..e23dce9719 100644 --- a/src/app/submission/import-external/submission-import-external.component.ts +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -7,7 +7,7 @@ import { RemoteData } from '../../core/data/remote-data'; import { PaginatedList } from '../../core/data/paginated-list'; import { ExternalSourceEntry } from '../../core/shared/external-source-entry.model'; import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; -import { switchMap, filter } from 'rxjs/operators'; +import { switchMap, filter, take } from 'rxjs/operators'; import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; import { Context } from '../../core/shared/context.model'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; @@ -116,7 +116,8 @@ export class SubmissionImportExternalComponent implements OnInit { return this.searchConfigService.paginatedSearchOptions.pipe( switchMap((searchOptions: PaginatedSearchOptions) => { return this.externalService.getExternalSourceEntries(this.routeData.sourceId, searchOptions); - }) + }), + take(1) ) }), ).subscribe((rdData) => { From 97b4b905857c885f65d1171c090c7954784add4c Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Fri, 26 Jun 2020 09:29:11 +0200 Subject: [PATCH 13/29] Additional fix for CI tests --- src/app/core/data/external-source.service.ts | 2 +- .../submission-import-external-preview.component.spec.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/core/data/external-source.service.ts b/src/app/core/data/external-source.service.ts index eda0440b4a..0d84639a40 100644 --- a/src/app/core/data/external-source.service.ts +++ b/src/app/core/data/external-source.service.ts @@ -11,7 +11,7 @@ import { NotificationsService } from '../../shared/notifications/notifications.s import { HttpClient } from '@angular/common/http'; import { FindListOptions, GetRequest } from './request.models'; import { Observable } from 'rxjs/internal/Observable'; -import { distinctUntilChanged, map, switchMap, take, flatMap, catchError } from 'rxjs/operators'; +import { distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; import { hasValue, isNotEmptyOperator } from '../../shared/empty.util'; import { configureRequest } from '../shared/operators'; 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 index 71360b9cc3..2060594de4 100644 --- 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 @@ -21,6 +21,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { let compAsAny: any; let fixture: ComponentFixture; let submissionServiceStub: SubmissionServiceStub; + const modal = jasmine.createSpyObj('modal', ['close', 'dismiss']); const externalEntry = Object.assign(new ExternalSourceEntry(), { id: '0001-0001-0001-0001', display: 'John Doe', @@ -49,7 +50,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { { provide: SubmissionService, useValue: new SubmissionServiceStub() }, { provide: NotificationsService, useValue: new NotificationsServiceStub() }, { provide: NgbModal, useValue: { open: () => {/*comment*/} } }, - { provide: NgbActiveModal, useValue: { dismiss: () => {/*comment*/} } }, + { provide: NgbActiveModal, useValue: modal }, SubmissionImportExternalPreviewComponent ], schemas: [NO_ERRORS_SCHEMA] @@ -103,7 +104,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { }); it('Should close the modal calling \'activeModal.dismiss\'', () => { - spyOn(compAsAny.activeModal, 'dismiss'); + comp.modalRef = jasmine.createSpyObj('modal', ['close', 'dismiss']); comp.closeMetadataModal(); expect(compAsAny.activeModal.dismiss).toHaveBeenCalled(); From e094663a774e973e1334ef78e9f5faf72f0d490c Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Fri, 26 Jun 2020 11:19:44 +0200 Subject: [PATCH 14/29] Additional fix for CI tests --- .../submission-import-external-preview.component.spec.ts | 9 +++++---- .../submission-import-external.component.spec.ts | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) 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 index 2060594de4..3bb6a19645 100644 --- 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 @@ -21,7 +21,8 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { let compAsAny: any; let fixture: ComponentFixture; let submissionServiceStub: SubmissionServiceStub; - const modal = jasmine.createSpyObj('modal', ['close', 'dismiss']); + const ngbActiveModal = jasmine.createSpyObj('modal', ['close', 'dismiss']); + const ngbModal = jasmine.createSpyObj('modal', ['open']); const externalEntry = Object.assign(new ExternalSourceEntry(), { id: '0001-0001-0001-0001', display: 'John Doe', @@ -49,8 +50,8 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { { provide: Router, useValue: new RouterStub() }, { provide: SubmissionService, useValue: new SubmissionServiceStub() }, { provide: NotificationsService, useValue: new NotificationsServiceStub() }, - { provide: NgbModal, useValue: { open: () => {/*comment*/} } }, - { provide: NgbActiveModal, useValue: modal }, + { provide: NgbModal, useValue: ngbModal }, + { provide: NgbActiveModal, useValue: ngbActiveModal }, SubmissionImportExternalPreviewComponent ], schemas: [NO_ERRORS_SCHEMA] @@ -129,7 +130,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { { id: 'jk11k13o-9v4z-632i-sr88-wq071n0h1d47' } ]; comp.externalSourceEntry = externalEntry; - spyOn(compAsAny.modalService, 'open').and.returnValue({componentInstance: { selectedEvent: observableOf(emittedEvent)}}); + ngbModal.open.and.returnValue({componentInstance: { selectedEvent: observableOf(emittedEvent)}}); spyOn(comp, 'closeMetadataModal'); submissionServiceStub.createSubmissionFromExternalSource.and.returnValue(observableOf(submissionObjects)); spyOn(compAsAny.router, 'navigateByUrl'); 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 6b5ec05171..923d431923 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 @@ -23,6 +23,7 @@ describe('SubmissionImportExternalComponent test suite', () => { let comp: SubmissionImportExternalComponent; let compAsAny: any; let fixture: ComponentFixture; + const ngbModal = jasmine.createSpyObj('modal', ['open']); const mockSearchOptions = of(new PaginatedSearchOptions({ pagination: Object.assign(new PaginationComponentOptions(), { pageSize: 10, @@ -48,7 +49,7 @@ describe('SubmissionImportExternalComponent test suite', () => { { provide: SearchConfigurationService, useValue: searchConfigServiceStub }, { provide: RouteService, useValue: routeServiceStub }, { provide: Router, useValue: new RouterStub() }, - NgbModal, + { provide: NgbModal, useValue: ngbModal }, SubmissionImportExternalComponent ], schemas: [NO_ERRORS_SCHEMA] @@ -93,7 +94,6 @@ describe('SubmissionImportExternalComponent test suite', () => { 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: '' }); @@ -139,7 +139,7 @@ describe('SubmissionImportExternalComponent test suite', () => { ] } }); - spyOn(compAsAny.modalService, 'open').and.returnValue({componentInstance: { externalSourceEntry: null}}); + ngbModal.open.and.returnValue({componentInstance: { externalSourceEntry: null}}); comp.import(entry); expect(compAsAny.modalService.open).toHaveBeenCalledWith(SubmissionImportExternalPreviewComponent, { size: 'lg' }); From e36cb83622ec106dc64c4f597f8f388580f8a605 Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Thu, 2 Jul 2020 11:50:39 +0200 Subject: [PATCH 15/29] Additional fix for CI tests --- .../submission-import-external-searchbar.component.spec.ts | 2 -- .../submission-import-external.component.spec.ts | 1 - 2 files changed, 3 deletions(-) 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 1f77374932..285581560b 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 @@ -84,7 +84,6 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => { it('Should init component properly (without initExternalSourceData)', () => { comp.initExternalSourceData = { sourceId: '', query: '' }; - comp.ngOnInit(); fixture.detectChanges(); expect(comp.selectedElement).toEqual(sourceList[0]); @@ -94,7 +93,6 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => { it('Should init component properly (with initExternalSourceData populated)', () => { comp.initExternalSourceData = { query: 'dummy', sourceId: 'ciencia' }; - comp.ngOnInit(); fixture.detectChanges(); expect(comp.selectedElement).toEqual(sourceList[1]); 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 923d431923..4cbe204a91 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 @@ -110,7 +110,6 @@ describe('SubmissionImportExternalComponent test suite', () => { }) }); spyOn(compAsAny.routeService, 'getQueryParameterValue').and.returnValue(observableOf('dummy')); - comp.ngOnInit(); fixture.detectChanges(); expect(comp.routeData).toEqual({ sourceId: 'dummy', query: 'dummy' }); From d6a5d9d1ddf96bb792a5fd3db23534acd9a7dad2 Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Mon, 6 Jul 2020 09:12:18 +0200 Subject: [PATCH 16/29] CI test fix, buttons and searchbar style fix and service methods removed --- .../my-dspace-new-submission.component.html | 10 ++++--- ...my-dspace-new-submission.component.spec.ts | 5 +++- .../my-dspace-new-submission.component.ts | 15 ++++++++-- .../core/data/external-source.service.spec.ts | 17 ----------- src/app/core/data/external-source.service.ts | 28 ------------------- .../mocks/external-source.service.mock.ts | 2 +- ...-import-external-preview.component.spec.ts | 7 ++++- ...n-import-external-searchbar.component.html | 9 ++++-- ...mport-external-searchbar.component.spec.ts | 5 +++- ...ion-import-external-searchbar.component.ts | 14 ++++++++-- src/assets/i18n/en.json5 | 6 ++-- 11 files changed, 55 insertions(+), 63 deletions(-) diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html index da5519eb07..248909b215 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html @@ -7,11 +7,13 @@
- - - {{'mydspace.new-submission-external' | translate}} +
+ diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.spec.ts b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.spec.ts index 16b50d18f0..f2687e452c 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.spec.ts +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.spec.ts @@ -23,6 +23,8 @@ import { getMockScrollToService } from '../../shared/mocks/scroll-to-service.moc import { UploaderService } from '../../shared/uploader/uploader.service'; import { By } from '@angular/platform-browser'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { HostWindowService } from '../../shared/host-window.service'; +import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub'; describe('MyDSpaceNewSubmissionComponent test', () => { @@ -63,7 +65,8 @@ describe('MyDSpaceNewSubmissionComponent test', () => { }, ChangeDetectorRef, MyDSpaceNewSubmissionComponent, - UploaderService + UploaderService, + { provide: HostWindowService, useValue: new HostWindowServiceStub(800) }, ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts index 8d20a5736a..e3cf19bf8a 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectorRef, Component, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core'; -import { Subscription } from 'rxjs'; +import { Subscription, Observable } from 'rxjs'; import { first } from 'rxjs/operators'; import { Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; @@ -18,6 +18,7 @@ import { SearchResult } from '../../shared/search/search-result.model'; import { Router } from '@angular/router'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { CreateItemParentSelectorComponent } from 'src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; +import { HostWindowService } from '../../shared/host-window.service'; /** * This component represents the whole mydspace page header @@ -38,6 +39,11 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { */ public uploadFilesOptions: UploaderOptions = new UploaderOptions(); + /** + * Emits true if were on a small screen + */ + public isXsOrSm$: Observable; + /** * Subscription to unsubscribe from */ @@ -52,6 +58,9 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { * @param {NotificationsService} notificationsService * @param {Store} store * @param {TranslateService} translate + * @param {Router} router + * @param {NgbModal} modalService + * @param {HostWindowService} windowService */ constructor(private authService: AuthService, private changeDetectorRef: ChangeDetectorRef, @@ -60,7 +69,8 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { private store: Store, private translate: TranslateService, private router: Router, - private modalService: NgbModal) { + private modalService: NgbModal, + protected windowService: HostWindowService) { } /** @@ -73,6 +83,7 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { this.changeDetectorRef.detectChanges(); } ); + this.isXsOrSm$ = this.windowService.isXsOrSm(); } /** diff --git a/src/app/core/data/external-source.service.spec.ts b/src/app/core/data/external-source.service.spec.ts index 2fc4589bed..7c7d676bc7 100644 --- a/src/app/core/data/external-source.service.spec.ts +++ b/src/app/core/data/external-source.service.spec.ts @@ -74,21 +74,4 @@ describe('ExternalSourceService', () => { }); }); }); - - describe('getAllExternalSources', () => { - it('should call findAll', () => { - spyOn(service, 'findAll'); - service.getAllExternalSources(); - expect(service.findAll).toHaveBeenCalled(); - }); - }); - - describe('getExternalSource', () => { - it('should call findById', () => { - const externalSourceId = 'orcidV2'; - spyOn(service, 'findById'); - service.getExternalSource(externalSourceId); - expect(service.findById).toHaveBeenCalledWith(externalSourceId); - }); - }); }); diff --git a/src/app/core/data/external-source.service.ts b/src/app/core/data/external-source.service.ts index 0d84639a40..edc538a39b 100644 --- a/src/app/core/data/external-source.service.ts +++ b/src/app/core/data/external-source.service.ts @@ -60,34 +60,6 @@ export class ExternalSourceService extends DataService { ); } - /** - * Return a single external source. - * - * @param id - * The external source id. - * @param linksToFollow - * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. - * @return Observable> - * The list of the external sources. - */ - getExternalSource(id: string, ...linksToFollow: Array>): Observable> { - return this.findById(id, ...linksToFollow); - } - - /** - * Return the list of external sources. - * - * @param options - * Find list options object. - * @param linksToFollow - * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. - * @return Observable>> - * The list of the external sources. - */ - getAllExternalSources(options: FindListOptions = {}, ...linksToFollow: Array>): Observable>> { - return this.findAll(options, ...linksToFollow); - } - /** * Get the entries for an external source * @param externalSourceId The id of the external source to fetch entries for diff --git a/src/app/shared/mocks/external-source.service.mock.ts b/src/app/shared/mocks/external-source.service.mock.ts index 3e96eb508e..85d63189e5 100644 --- a/src/app/shared/mocks/external-source.service.mock.ts +++ b/src/app/shared/mocks/external-source.service.mock.ts @@ -53,7 +53,7 @@ export const externalSourceMyStaffDb: ExternalSource = { export function getMockExternalSourceService(): ExternalSourceService { return jasmine.createSpyObj('ExternalSourceService', { - getAllExternalSources: jasmine.createSpy('getAllExternalSources'), + findAll: jasmine.createSpy('findAll'), getExternalSourceEntries: jasmine.createSpy('getExternalSourceEntries'), }); } 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 index 3bb6a19645..29b0094b69 100644 --- 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 @@ -3,7 +3,9 @@ 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 { TestScheduler } from 'rxjs/testing'; import { of as observableOf, of } from 'rxjs/internal/observable/of'; +import { getTestScheduler } from 'jasmine-marbles'; import { SubmissionImportExternalPreviewComponent } from './submission-import-external-preview.component'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { RouterStub } from '../../../shared/testing/router.stub'; @@ -21,6 +23,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { let compAsAny: any; let fixture: ComponentFixture; let submissionServiceStub: SubmissionServiceStub; + let scheduler: TestScheduler; const ngbActiveModal = jasmine.createSpyObj('modal', ['close', 'dismiss']); const ngbModal = jasmine.createSpyObj('modal', ['open']); const externalEntry = Object.assign(new ExternalSourceEntry(), { @@ -38,6 +41,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { }); beforeEach(async (() => { + scheduler = getTestScheduler(); TestBed.configureTestingModule({ imports: [ TranslateModule.forRoot() @@ -134,7 +138,8 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { spyOn(comp, 'closeMetadataModal'); submissionServiceStub.createSubmissionFromExternalSource.and.returnValue(observableOf(submissionObjects)); spyOn(compAsAny.router, 'navigateByUrl'); - comp.import(); + scheduler.schedule(() => comp.import()); + scheduler.flush(); expect(compAsAny.modalService.open).toHaveBeenCalledWith(SubmissionImportExternalCollectionComponent, { size: 'lg' }); expect(comp.closeMetadataModal).toHaveBeenCalled(); diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html index a63828568d..fe70299e4e 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html @@ -1,6 +1,9 @@ -
+
-
+
+
+ +
- +
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 285581560b..25f12c6e38 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 @@ -11,6 +11,8 @@ 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'; +import { HostWindowService } from '../../../shared/host-window.service'; +import { HostWindowServiceStub } from '../../../shared/testing/host-window-service.stub'; describe('SubmissionImportExternalSearchbarComponent test suite', () => { let comp: SubmissionImportExternalSearchbarComponent; @@ -29,6 +31,7 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => { providers: [ { provide: ExternalSourceService, useClass: getMockExternalSourceService }, ChangeDetectorRef, + { provide: HostWindowService, useValue: new HostWindowServiceStub(800) }, SubmissionImportExternalSearchbarComponent ], schemas: [NO_ERRORS_SCHEMA] @@ -68,7 +71,7 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => { const pageInfo = new PageInfo(); paginatedList = new PaginatedList(pageInfo, [externalSourceOrcid, externalSourceCiencia, externalSourceMyStaffDb]); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); - compAsAny.externalService.getAllExternalSources.and.returnValue(observableOf(paginatedListRD)); + compAsAny.externalService.findAll.and.returnValue(observableOf(paginatedListRD)); sourceList = [ {id: 'orcid', name: 'orcid'}, {id: 'ciencia', name: 'ciencia'}, 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 efbcbad60c..bb156e1878 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 @@ -1,6 +1,6 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, Observable } from 'rxjs'; import { catchError, tap } from 'rxjs/operators'; import { ExternalSourceService } from '../../../core/data/external-source.service'; @@ -11,6 +11,7 @@ import { PageInfo } from '../../../core/shared/page-info.model'; import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; import { FindListOptions } from '../../../core/data/request.models'; import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; +import { HostWindowService } from '../../../shared/host-window.service'; /** * Interface for the selected external source element. @@ -57,6 +58,10 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { * The external sources loading status. */ public sourceListLoading = false; + /** + * Emits true if were on a small screen + */ + public isXsOrSm$: Observable; /** * The external source data to use to perform the search. */ @@ -75,10 +80,12 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { * Initialize the component variables. * @param {ExternalSourceService} externalService * @param {ChangeDetectorRef} cdr + * @param {HostWindowService} windowService */ constructor( private externalService: ExternalSourceService, private cdr: ChangeDetectorRef, + protected windowService: HostWindowService ) { } @@ -96,7 +103,7 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { elementsPerPage: 5, currentPage: 0, }); - this.externalService.getAllExternalSources(this.findListOptions).pipe( + this.externalService.findAll(this.findListOptions).pipe( catchError(() => { const pageInfo = new PageInfo(); const paginatedList = new PaginatedList(pageInfo, []); @@ -118,6 +125,7 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { this.pageInfo = externalSource.pageInfo; this.cdr.detectChanges(); }); + this.isXsOrSm$ = this.windowService.isXsOrSm(); } /** @@ -137,7 +145,7 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { elementsPerPage: 5, currentPage: this.findListOptions.currentPage + 1, }); - this.externalService.getAllExternalSources(this.findListOptions).pipe( + this.externalService.findAll(this.findListOptions).pipe( catchError(() => { const pageInfo = new PageInfo(); const paginatedList = new PaginatedList(pageInfo, []); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index cc21874672..75cf73339d 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1859,7 +1859,9 @@ "mydspace.new-submission": "New submission", - "mydspace.new-submission-external": "Import from external source", + "mydspace.new-submission-external": "Import metadata from external source", + + "mydspace.new-submission-external-short": "Import metadata", "mydspace.results.head": "Your submissions", @@ -2562,7 +2564,7 @@ "submission.import-external.title": "Import metadata from an external source", - "submission.import-external.page.hint": "Search items using external sources.", + "submission.import-external.page.hint": "No search performed yet. Search items using external sources.", "submission.import-external.back-to-my-dspace": "Back to MyDSpace", From 9ec57094100a5e88d67865c0e63b1b5a7ec60957 Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Mon, 6 Jul 2020 10:28:17 +0200 Subject: [PATCH 17/29] CI test fix using TestScheduler --- .../submission-import-external-preview.component.spec.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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 index 29b0094b69..58488dd5ab 100644 --- 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 @@ -79,7 +79,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { testFixture.destroy(); }); - it('should create SubmissionImportExternalComponent', inject([SubmissionImportExternalPreviewComponent], (app: SubmissionImportExternalPreviewComponent) => { + it('should create SubmissionImportExternalPreviewComponent', inject([SubmissionImportExternalPreviewComponent], (app: SubmissionImportExternalPreviewComponent) => { expect(app).toBeDefined(); })); }); @@ -103,14 +103,16 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { const expected = [ { key: 'dc.identifier.uri', value: Metadata.first(comp.externalSourceEntry.metadata, 'dc.identifier.uri') } ]; - fixture.detectChanges(); + scheduler.schedule(() => comp.ngOnInit()); + scheduler.flush(); expect(comp.metadataList).toEqual(expected); }); it('Should close the modal calling \'activeModal.dismiss\'', () => { comp.modalRef = jasmine.createSpyObj('modal', ['close', 'dismiss']); - comp.closeMetadataModal(); + scheduler.schedule(() => comp.closeMetadataModal()); + scheduler.flush(); expect(compAsAny.activeModal.dismiss).toHaveBeenCalled(); }); From 7c36051fccd12383e5959ca4e5c9cc276c1aac10 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 6 Jul 2020 11:24:21 +0200 Subject: [PATCH 18/29] fixed travis failure --- ...ission-import-external-preview.component.spec.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) 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 index 58488dd5ab..aa4413637c 100644 --- 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 @@ -4,7 +4,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { Router } from '@angular/router'; import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { TestScheduler } from 'rxjs/testing'; -import { of as observableOf, of } from 'rxjs/internal/observable/of'; +import { of as observableOf } from 'rxjs/internal/observable/of'; import { getTestScheduler } from 'jasmine-marbles'; import { SubmissionImportExternalPreviewComponent } from './submission-import-external-preview.component'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; @@ -103,16 +103,14 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { const expected = [ { key: 'dc.identifier.uri', value: Metadata.first(comp.externalSourceEntry.metadata, 'dc.identifier.uri') } ]; - scheduler.schedule(() => comp.ngOnInit()); - scheduler.flush(); + fixture.detectChanges(); expect(comp.metadataList).toEqual(expected); }); it('Should close the modal calling \'activeModal.dismiss\'', () => { comp.modalRef = jasmine.createSpyObj('modal', ['close', 'dismiss']); - scheduler.schedule(() => comp.closeMetadataModal()); - scheduler.flush(); + comp.closeMetadataModal(); expect(compAsAny.activeModal.dismiss).toHaveBeenCalled(); }); @@ -136,7 +134,10 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { { id: 'jk11k13o-9v4z-632i-sr88-wq071n0h1d47' } ]; comp.externalSourceEntry = externalEntry; - ngbModal.open.and.returnValue({componentInstance: { selectedEvent: observableOf(emittedEvent)}}); + ngbModal.open.and.returnValue({ + componentInstance: { selectedEvent: observableOf(emittedEvent)}, + close: (): void => { /* empty */ } + }); spyOn(comp, 'closeMetadataModal'); submissionServiceStub.createSubmissionFromExternalSource.and.returnValue(observableOf(submissionObjects)); spyOn(compAsAny.router, 'navigateByUrl'); From a38e5cf632f75a98b8bbfdc02dec673df4511ca9 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 6 Jul 2020 12:30:53 +0200 Subject: [PATCH 19/29] fixed travis failure --- ...mport-external-searchbar.component.spec.ts | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) 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 25f12c6e38..10cc122624 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,5 +1,5 @@ import { Component, NO_ERRORS_SCHEMA, ChangeDetectorRef } from '@angular/core'; -import { async, TestBed, ComponentFixture, inject } from '@angular/core/testing'; +import { async, TestBed, ComponentFixture, inject, fakeAsync, tick } 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'; @@ -13,13 +13,17 @@ import { ExternalSource } from '../../../core/shared/external-source.model'; import { FindListOptions } from '../../../core/data/request.models'; import { HostWindowService } from '../../../shared/host-window.service'; import { HostWindowServiceStub } from '../../../shared/testing/host-window-service.stub'; +import { getTestScheduler } from 'jasmine-marbles'; +import { TestScheduler } from 'rxjs/testing'; describe('SubmissionImportExternalSearchbarComponent test suite', () => { let comp: SubmissionImportExternalSearchbarComponent; let compAsAny: any; let fixture: ComponentFixture; + let scheduler: TestScheduler; beforeEach(async (() => { + scheduler = getTestScheduler(); TestBed.configureTestingModule({ imports: [ TranslateModule.forRoot(), @@ -85,23 +89,25 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => { compAsAny = null; }); - it('Should init component properly (without initExternalSourceData)', () => { + it('Should init component properly (without initExternalSourceData)', fakeAsync(() => { comp.initExternalSourceData = { sourceId: '', query: '' }; fixture.detectChanges(); + tick(); 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)', () => { + it('Should init component properly (with initExternalSourceData populated)', fakeAsync(() => { comp.initExternalSourceData = { query: 'dummy', sourceId: 'ciencia' }; fixture.detectChanges(); + tick(); 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'}; @@ -123,7 +129,9 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => { }); comp.sourceList = sourceList; const expected = sourceList.concat(sourceList); - comp.onScroll(); + + scheduler.schedule(() => comp.onScroll()); + scheduler.flush(); expect(comp.sourceList).toEqual(expected); }); From b8abedb5d6eaa6f78b9c68ab36513177fe263aa1 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 16 Jul 2020 14:49:03 +0200 Subject: [PATCH 20/29] Fixed test --- ...-import-external-preview.component.spec.ts | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) 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 index 58488dd5ab..5467d9e7b7 100644 --- 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 @@ -1,10 +1,10 @@ import { Component, NO_ERRORS_SCHEMA } from '@angular/core'; -import { async, TestBed, ComponentFixture, inject } from '@angular/core/testing'; +import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing'; import { TranslateModule } from '@ngx-translate/core'; import { Router } from '@angular/router'; -import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { TestScheduler } from 'rxjs/testing'; -import { of as observableOf, of } from 'rxjs/internal/observable/of'; +import { of as observableOf } from 'rxjs/internal/observable/of'; import { getTestScheduler } from 'jasmine-marbles'; import { SubmissionImportExternalPreviewComponent } from './submission-import-external-preview.component'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; @@ -40,7 +40,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { _links: { self: { href: 'http://test-rest.com/server/api/integration/externalSources/orcidV2/entryValues/0000-0003-4851-8004' } } }); - beforeEach(async (() => { + beforeEach(async(() => { scheduler = getTestScheduler(); TestBed.configureTestingModule({ imports: [ @@ -117,7 +117,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { expect(compAsAny.activeModal.dismiss).toHaveBeenCalled(); }); - it('Should start the import process opening a modal', () => { + it('Should start the import process opening a modal', (done) => { const emittedEvent: CollectionListEntry = { communities: [ { @@ -133,10 +133,15 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { } }; const submissionObjects = [ - { id: 'jk11k13o-9v4z-632i-sr88-wq071n0h1d47' } + { id: 'jk11k13o-9v4z-632i-sr88-wq071n0h1d47' } ]; comp.externalSourceEntry = externalEntry; - ngbModal.open.and.returnValue({componentInstance: { selectedEvent: observableOf(emittedEvent)}}); + ngbModal.open.and.returnValue({ + componentInstance: { selectedEvent: observableOf(emittedEvent) }, + close: () => { + return; + } + }); spyOn(comp, 'closeMetadataModal'); submissionServiceStub.createSubmissionFromExternalSource.and.returnValue(observableOf(submissionObjects)); spyOn(compAsAny.router, 'navigateByUrl'); @@ -147,6 +152,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { 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'); + done(); }); }); }); From 92258190467e2e4fc023fdd48b5caeb18e9b1a28 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 16 Jul 2020 17:00:14 +0200 Subject: [PATCH 21/29] [CST-3092] Removed label from New submission and Import buttons --- .../my-dspace-new-submission.component.html | 4 ++-- .../my-dspace-new-submission.component.ts | 19 +++++-------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html index 248909b215..4cb58012bc 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html @@ -8,12 +8,12 @@
diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts index e3cf19bf8a..5659c442ad 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts @@ -1,9 +1,11 @@ import { ChangeDetectorRef, Component, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core'; +import { Router } from '@angular/router'; -import { Subscription, Observable } from 'rxjs'; +import { Subscription } from 'rxjs'; import { first } from 'rxjs/operators'; import { Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { SubmissionState } from '../../submission/submission.reducers'; import { AuthService } from '../../core/auth/auth.service'; @@ -15,10 +17,7 @@ import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; import { NotificationType } from '../../shared/notifications/models/notification-type'; import { hasValue } from '../../shared/empty.util'; import { SearchResult } from '../../shared/search/search-result.model'; -import { Router } from '@angular/router'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { CreateItemParentSelectorComponent } from 'src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; -import { HostWindowService } from '../../shared/host-window.service'; +import { CreateItemParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; /** * This component represents the whole mydspace page header @@ -39,11 +38,6 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { */ public uploadFilesOptions: UploaderOptions = new UploaderOptions(); - /** - * Emits true if were on a small screen - */ - public isXsOrSm$: Observable; - /** * Subscription to unsubscribe from */ @@ -60,7 +54,6 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { * @param {TranslateService} translate * @param {Router} router * @param {NgbModal} modalService - * @param {HostWindowService} windowService */ constructor(private authService: AuthService, private changeDetectorRef: ChangeDetectorRef, @@ -69,8 +62,7 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { private store: Store, private translate: TranslateService, private router: Router, - private modalService: NgbModal, - protected windowService: HostWindowService) { + private modalService: NgbModal) { } /** @@ -83,7 +75,6 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { this.changeDetectorRef.detectChanges(); } ); - this.isXsOrSm$ = this.windowService.isXsOrSm(); } /** From 1c31deb3dfde1ae866f7b5b87786863f8f42cad5 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 16 Jul 2020 17:01:06 +0200 Subject: [PATCH 22/29] [CST-3092] fixed style issue with external source search bar --- .../submission-import-external-searchbar.component.scss | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss index 562b5b5613..0d2a79b056 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss @@ -1,7 +1,6 @@ -.input-group-append .btn { +.input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle) { margin-left: -1px; - border-top-left-radius: 0; - border-bottom-left-radius: 0; + border-radius: 0 0.25rem 0.25rem 0; } .input-group-append .dropdown-toggle { From c48b817c2da6de75c54f6c9962214b4e72dd4a0b Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 16 Jul 2020 17:02:12 +0200 Subject: [PATCH 23/29] [CST-3092] Changed start message from external source page --- .../import-external/submission-import-external.component.html | 4 ++-- src/assets/i18n/en.json5 | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/submission/import-external/submission-import-external.component.html b/src/app/submission/import-external/submission-import-external.component.html index 2aac8557aa..9f52969635 100644 --- a/src/app/submission/import-external/submission-import-external.component.html +++ b/src/app/submission/import-external/submission-import-external.component.html @@ -30,9 +30,9 @@
-
+

{{'submission.import-external.page.hint' | translate}}

-
+
diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 6aee58458f..23f72646c6 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2683,7 +2683,7 @@ "submission.import-external.title": "Import metadata from an external source", - "submission.import-external.page.hint": "No search performed yet. Search items using external sources.", + "submission.import-external.page.hint": "Enter a query above to find items from the web to import in to DSpace.", "submission.import-external.back-to-my-dspace": "Back to MyDSpace", From 3f77ffa1e689f1538bc4800f481d8c1d9cd3e01b Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 27 Jul 2020 11:14:56 +0200 Subject: [PATCH 24/29] [CST-3092] remove margin bottom --- .../import-external/submission-import-external.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/submission/import-external/submission-import-external.component.html b/src/app/submission/import-external/submission-import-external.component.html index 9f52969635..c4de97b934 100644 --- a/src/app/submission/import-external/submission-import-external.component.html +++ b/src/app/submission/import-external/submission-import-external.component.html @@ -31,7 +31,7 @@
-

{{'submission.import-external.page.hint' | translate}}

+

{{'submission.import-external.page.hint' | translate}}

From 4779dd209ec4c0ab2a6504ca4b21aaa1455e504b Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 27 Jul 2020 11:15:15 +0200 Subject: [PATCH 25/29] [CST-3092] fix context --- .../import-external/submission-import-external.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e23dce9719..a369863a74 100644 --- a/src/app/submission/import-external/submission-import-external.component.ts +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -94,7 +94,7 @@ export class SubmissionImportExternalComponent implements OnInit { ngOnInit(): void { this.label = 'Journal'; this.listId = 'list-submission-external-sources'; - this.context = Context.SubmissionModal; + this.context = Context.EntitySearchModalWithNameVariants; this.repeatable = false; this.routeData = { sourceId: '', query: '' }; this.importConfig = { From 94b4115ecd3d2c80b4d69c30fc00fc17f97a8de3 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 26 Aug 2020 12:53:50 +0200 Subject: [PATCH 26/29] Removed unintentional fdescribe --- .../my-dspace-new-submission.component.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.spec.ts b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.spec.ts index bbcb7f65bf..c395408cf5 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.spec.ts +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.spec.ts @@ -26,7 +26,7 @@ import { HostWindowService } from '../../shared/host-window.service'; import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub'; import { UploaderComponent } from 'src/app/shared/uploader/uploader.component'; -fdescribe('MyDSpaceNewSubmissionComponent test', () => { +describe('MyDSpaceNewSubmissionComponent test', () => { const translateService: TranslateService = jasmine.createSpyObj('translateService', { get: (key: string): any => { observableOf(key) }, From ab190e381d4e624a58e5e17be91bf6c086e946cb Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 26 Aug 2020 14:35:23 +0200 Subject: [PATCH 27/29] Fixed test --- ...n-import-external-searchbar.component.spec.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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 10cc122624..09a1781d1d 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 @@ -89,25 +89,25 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => { compAsAny = null; }); - it('Should init component properly (without initExternalSourceData)', fakeAsync(() => { + it('Should init component properly (without initExternalSourceData)', () => { comp.initExternalSourceData = { sourceId: '', query: '' }; - fixture.detectChanges(); - tick(); + scheduler.schedule(() => fixture.detectChanges()); + scheduler.flush(); 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)', fakeAsync(() => { + it('Should init component properly (with initExternalSourceData populated)', () => { comp.initExternalSourceData = { query: 'dummy', sourceId: 'ciencia' }; - fixture.detectChanges(); - tick(); + scheduler.schedule(() => fixture.detectChanges()); + scheduler.flush(); 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'}; From 67bd19a340cc639d20e1702ff2dc241a9e4a4fed Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 26 Aug 2020 14:42:47 +0200 Subject: [PATCH 28/29] Fixed template --- .../submission-import-external-searchbar.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html index fe70299e4e..0e51ebb38e 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html @@ -16,7 +16,7 @@ [infiniteScrollThrottle]="50" (scrolled)="onScroll()" [scrollWindow]="false"> - +

{{'submission.import-external.source.loading' | translate}}

From ee2f11f6027767816017f28a356b53d674a5f9e7 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 26 Aug 2020 15:33:52 +0200 Subject: [PATCH 29/29] Fixed template --- .../submission-import-external-searchbar.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html index 0e51ebb38e..535395e534 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html @@ -4,7 +4,7 @@
- +