From 59564eb44d1b8bc56bbfedc601693a556181eb80 Mon Sep 17 00:00:00 2001 From: Danilo Di Nuzzo Date: Fri, 26 Jun 2020 09:25:22 +0200 Subject: [PATCH 1/6] [CST-3091] add comp collection-selector, fix issue --- .../collection-selector.component.html | 11 +++++ .../collection-selector.component.scss | 0 .../collection-selector.component.spec.ts | 25 +++++++++++ .../collection-selector.component.ts | 35 ++++++++++++++++ .../my-dspace-new-submission.component.html | 3 +- .../my-dspace-new-submission.component.ts | 41 +++++++++++++++++-- .../+my-dspace-page/my-dspace-page.module.ts | 7 +++- .../shared/uploader/uploader-error.model.ts | 9 ++++ .../shared/uploader/uploader-options.model.ts | 5 +++ src/app/shared/uploader/uploader.component.ts | 13 +++++- src/assets/i18n/en.json5 | 4 ++ 11 files changed, 145 insertions(+), 8 deletions(-) create mode 100644 src/app/+my-dspace-page/collection-selector/collection-selector.component.html create mode 100644 src/app/+my-dspace-page/collection-selector/collection-selector.component.scss create mode 100644 src/app/+my-dspace-page/collection-selector/collection-selector.component.spec.ts create mode 100644 src/app/+my-dspace-page/collection-selector/collection-selector.component.ts create mode 100644 src/app/shared/uploader/uploader-error.model.ts diff --git a/src/app/+my-dspace-page/collection-selector/collection-selector.component.html b/src/app/+my-dspace-page/collection-selector/collection-selector.component.html new file mode 100644 index 00000000000..ef8865ad876 --- /dev/null +++ b/src/app/+my-dspace-page/collection-selector/collection-selector.component.html @@ -0,0 +1,11 @@ +
+ + +
diff --git a/src/app/+my-dspace-page/collection-selector/collection-selector.component.scss b/src/app/+my-dspace-page/collection-selector/collection-selector.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/+my-dspace-page/collection-selector/collection-selector.component.spec.ts b/src/app/+my-dspace-page/collection-selector/collection-selector.component.spec.ts new file mode 100644 index 00000000000..8cfc6e63611 --- /dev/null +++ b/src/app/+my-dspace-page/collection-selector/collection-selector.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CollectionSelectorComponent } from './collection-selector.component'; + +describe('CollectionSelectorComponent', () => { + let component: CollectionSelectorComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CollectionSelectorComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CollectionSelectorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/+my-dspace-page/collection-selector/collection-selector.component.ts b/src/app/+my-dspace-page/collection-selector/collection-selector.component.ts new file mode 100644 index 00000000000..e1a5a887d37 --- /dev/null +++ b/src/app/+my-dspace-page/collection-selector/collection-selector.component.ts @@ -0,0 +1,35 @@ +import { Component, OnInit } from '@angular/core'; +import { DSOSelectorModalWrapperComponent, SelectorActionType } from 'src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component'; +import { DSpaceObject } from '../../core/shared/dspace-object.model'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { ActivatedRoute, Router } from '@angular/router'; +import { DSpaceObjectType } from 'src/app/core/shared/dspace-object-type.model'; + +@Component({ + selector: 'ds-collection-selector', + templateUrl: './collection-selector.component.html', + styleUrls: ['./collection-selector.component.scss'] +}) +export class CollectionSelectorComponent extends DSOSelectorModalWrapperComponent { + objectType = DSpaceObjectType.ITEM; + selectorType = DSpaceObjectType.COLLECTION; + action = SelectorActionType.CREATE; + + navigate(dso: DSpaceObject) { + throw new Error('Method not implemented.'); + } + + constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) { + super(activeModal, route); + } + + /** + * Method called when an element has been selected from collection list. + * Its close the active modal and send selected value to the component container + * @param dso The selected DSpaceObject + */ + selectObject(dso: DSpaceObject) { + this.activeModal.close(dso); + } + +} 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 4809f206aea..a3181f3dfe0 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 @@ -3,7 +3,8 @@ + (onUploadError)="onUploadError($event)" + (onFileSelected)="uploadDialogForFileUpload($event)">
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 8d20a5736a3..d68502a476c 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,4 +1,4 @@ -import { ChangeDetectorRef, Component, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core'; +import { ChangeDetectorRef, Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; import { Subscription } from 'rxjs'; import { first } from 'rxjs/operators'; @@ -18,6 +18,9 @@ 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 { CollectionSelectorComponent } from '../collection-selector/collection-selector.component'; +import { UploaderComponent } from 'src/app/shared/uploader/uploader.component'; +import { UploaderError } from 'src/app/shared/uploader/uploader-error.model'; /** * This component represents the whole mydspace page header @@ -43,6 +46,11 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { */ private sub: Subscription; + /** + * Reference to uploaderComponent + */ + @ViewChild(UploaderComponent, { static: false }) uploaderComponent: UploaderComponent; + /** * Initialize instance variables * @@ -67,6 +75,7 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { * Initialize url and Bearer token */ ngOnInit() { + this.uploadFilesOptions.autoUpload = false; this.sub = this.halService.getEndpoint('workspaceitems').pipe(first()).subscribe((url) => { this.uploadFilesOptions.url = url; this.uploadFilesOptions.authToken = this.authService.buildAuthHeader(); @@ -106,8 +115,12 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { /** * Method called on file upload error */ - public onUploadError() { - this.notificationsService.error(null, this.translate.get('mydspace.upload.upload-failed')); + public onUploadError(error: UploaderError) { + let errorMessageKey = 'mydspace.upload.upload-failed'; + if (hasValue(error.status) && error.status === 422) { + errorMessageKey = 'mydspace.upload.upload-failed-manyentries'; + } + this.notificationsService.error(null, this.translate.get(errorMessageKey)); } /** @@ -118,6 +131,28 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { this.modalService.open(CreateItemParentSelectorComponent); } + /** + * Method for open dialog after submission file selection + */ + uploadDialogForFileUpload(items) { + const uploader = this.uploaderComponent.uploader; + if (hasValue(items) && items.length > 1) { + this.notificationsService.error(null, this.translate.get('mydspace.upload.upload-failed-moreonefile')); + uploader.clearQueue(); + this.changeDetectorRef.detectChanges(); + } else { + const modalRef = this.modalService.open(CollectionSelectorComponent); + // When the dialog are closes its takes the collection selected and + // uploads choosed file after adds owningCollection parameter + modalRef.result.then( (result) => { + uploader.onBuildItemForm = (fileItem: any, form: any) => { + form.append('owningCollection', result.uuid); + }; + uploader.uploadAll(); + }); + } + } + /** * Unsubscribe from the subscription */ diff --git a/src/app/+my-dspace-page/my-dspace-page.module.ts b/src/app/+my-dspace-page/my-dspace-page.module.ts index 1cf30c4ec95..49570fec6d7 100644 --- a/src/app/+my-dspace-page/my-dspace-page.module.ts +++ b/src/app/+my-dspace-page/my-dspace-page.module.ts @@ -20,6 +20,7 @@ import { SearchResultListElementComponent } from '../shared/object-list/search-r import { ItemSearchResultListElementSubmissionComponent } from '../shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component'; import { WorkflowItemSearchResultListElementComponent } from '../shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component'; import { PoolSearchResultDetailElementComponent } from '../shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component'; +import { CollectionSelectorComponent } from './collection-selector/collection-selector.component'; @NgModule({ imports: [ @@ -40,7 +41,8 @@ import { PoolSearchResultDetailElementComponent } from '../shared/object-detail/ ClaimedTaskSearchResultDetailElementComponent, PoolSearchResultDetailElementComponent, MyDSpaceNewSubmissionComponent, - ItemSearchResultListElementSubmissionComponent + ItemSearchResultListElementSubmissionComponent, + CollectionSelectorComponent ], providers: [ MyDSpaceGuard, @@ -57,7 +59,8 @@ import { PoolSearchResultDetailElementComponent } from '../shared/object-detail/ WorkflowItemSearchResultDetailElementComponent, ClaimedTaskSearchResultDetailElementComponent, PoolSearchResultDetailElementComponent, - ItemSearchResultListElementSubmissionComponent + ItemSearchResultListElementSubmissionComponent, + CollectionSelectorComponent ] }) diff --git a/src/app/shared/uploader/uploader-error.model.ts b/src/app/shared/uploader/uploader-error.model.ts new file mode 100644 index 00000000000..9238a0df367 --- /dev/null +++ b/src/app/shared/uploader/uploader-error.model.ts @@ -0,0 +1,9 @@ +/** + * An interface that represents the upload error values + */ +export interface UploaderError { + item?: any; + response?: any; + status?: any; + headers?: any; +} diff --git a/src/app/shared/uploader/uploader-options.model.ts b/src/app/shared/uploader/uploader-options.model.ts index f195b0930e5..959e5c32959 100644 --- a/src/app/shared/uploader/uploader-options.model.ts +++ b/src/app/shared/uploader/uploader-options.model.ts @@ -17,6 +17,11 @@ export class UploaderOptions { */ autoUpload = true; + /** + * Set the max number of files that can be loaded + */ + maxFileNumber: number; + /** * The request method to use for the file upload request */ diff --git a/src/app/shared/uploader/uploader.component.ts b/src/app/shared/uploader/uploader.component.ts index 72a38d1eb15..07f4245954b 100644 --- a/src/app/shared/uploader/uploader.component.ts +++ b/src/app/shared/uploader/uploader.component.ts @@ -69,6 +69,11 @@ export class UploaderComponent { */ @Output() onUploadError: EventEmitter = new EventEmitter(); + /** + * The function to call when a file is selected + */ + @Output() onFileSelected: EventEmitter = new EventEmitter(); + public uploader: FileUploader; public uploaderId: string; public isOverBaseDropZone = observableOf(false); @@ -102,7 +107,8 @@ export class UploaderComponent { itemAlias: this.uploadFilesOptions.itemAlias, removeAfterUpload: true, autoUpload: this.uploadFilesOptions.autoUpload, - method: this.uploadFilesOptions.method + method: this.uploadFilesOptions.method, + queueLimit: this.uploadFilesOptions.maxFileNumber }); if (isUndefined(this.enableDragOverDocument)) { @@ -121,6 +127,9 @@ export class UploaderComponent { this.uploader.onAfterAddingFile = ((item) => { item.withCredentials = false; }); + this.uploader.onAfterAddingAll = ((items) => { + this.onFileSelected.emit(items); + }); if (isUndefined(this.onBeforeUpload)) { this.onBeforeUpload = () => {return}; } @@ -149,7 +158,7 @@ export class UploaderComponent { } }; this.uploader.onErrorItem = (item: any, response: any, status: any, headers: any) => { - this.onUploadError.emit(null); + this.onUploadError.emit({ item: item, response: response, status: status, headers: headers }); this.uploader.cancelAll(); }; this.uploader.onProgressAll = () => this.onProgress(); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 4173fa1cf24..e7cfdb9e4dd 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1803,6 +1803,10 @@ "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", + "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", + + "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", + "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", "mydspace.upload.upload-successful": "New workspace item created. Click {{here}} for edit it.", From 0ca1798537d976338fedbb47890216c648c0e9d4 Mon Sep 17 00:00:00 2001 From: Danilo Di Nuzzo Date: Fri, 26 Jun 2020 15:25:58 +0200 Subject: [PATCH 2/6] [CST-3091] fix tests and add new labels --- .../collection-selector.component.html | 2 +- .../collection-selector.component.spec.ts | 138 +- .../collection-selector.component.ts | 18 +- .../my-dspace-new-submission.component.html | 2 +- ...my-dspace-new-submission.component.spec.ts | 38 +- .../my-dspace-new-submission.component.ts | 10 +- src/assets/i18n/ar.json5 | 556 ++- src/assets/i18n/cs.json5 | 556 ++- src/assets/i18n/de.json5 | 552 ++- src/assets/i18n/en.json5 | 2 + src/assets/i18n/es.json5 | 3224 ++++++++++------- src/assets/i18n/fi.json5 | 554 ++- src/assets/i18n/fr.json5 | 552 ++- src/assets/i18n/ja.json5 | 556 ++- src/assets/i18n/lv.json5 | 524 ++- src/assets/i18n/nl.json5 | 553 ++- src/assets/i18n/pl.json5 | 556 ++- src/assets/i18n/pt.json5 | 552 ++- src/assets/i18n/sw.json5 | 556 ++- src/assets/i18n/tr.json5 | 556 ++- 20 files changed, 8607 insertions(+), 1450 deletions(-) diff --git a/src/app/+my-dspace-page/collection-selector/collection-selector.component.html b/src/app/+my-dspace-page/collection-selector/collection-selector.component.html index ef8865ad876..83cc4151a36 100644 --- a/src/app/+my-dspace-page/collection-selector/collection-selector.component.html +++ b/src/app/+my-dspace-page/collection-selector/collection-selector.component.html @@ -1,5 +1,5 @@
-