mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
[CST-7216] Angular: Import saf via URL
This commit is contained in:

committed by
Francesco Pio Scognamiglio

parent
1ea7c61315
commit
e47b42bc89
@@ -20,12 +20,24 @@
|
|||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<ui-switch [checkedLabel]="'admin.metadata-import.page.toggle.upload' | translate"
|
||||||
|
[uncheckedLabel]="'admin.metadata-import.page.toggle.url' | translate"
|
||||||
|
[checked]="isUpload"
|
||||||
|
(change)="toggleUpload()" ></ui-switch>
|
||||||
|
|
||||||
<ds-file-dropzone-no-uploader
|
<ds-file-dropzone-no-uploader
|
||||||
|
*ngIf="isUpload"
|
||||||
|
data-test="file-dropzone"
|
||||||
(onFileAdded)="setFile($event)"
|
(onFileAdded)="setFile($event)"
|
||||||
[dropMessageLabel]="'admin.batch-import.page.dropMsg'"
|
[dropMessageLabel]="'admin.batch-import.page.dropMsg'"
|
||||||
[dropMessageLabelReplacement]="'admin.batch-import.page.dropMsgReplace'">
|
[dropMessageLabelReplacement]="'admin.batch-import.page.dropMsgReplace'">
|
||||||
</ds-file-dropzone-no-uploader>
|
</ds-file-dropzone-no-uploader>
|
||||||
|
|
||||||
|
<div class="form-group mt-2" *ngIf="!isUpload">
|
||||||
|
<input class="form-control" type="text" placeholder="{{'admin.metadata-import.page.urlMsg' | translate}}"
|
||||||
|
data-test="file-url-input" [(ngModel)]="fileURL">
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="space-children-mr">
|
<div class="space-children-mr">
|
||||||
<button class="btn btn-secondary" id="backButton"
|
<button class="btn btn-secondary" id="backButton"
|
||||||
(click)="this.onReturn();">{{'admin.metadata-import.page.button.return' | translate}}</button>
|
(click)="this.onReturn();">{{'admin.metadata-import.page.button.return' | translate}}</button>
|
||||||
|
@@ -86,10 +86,18 @@ describe('BatchImportPageComponent', () => {
|
|||||||
let fileMock: File;
|
let fileMock: File;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
component.isUpload = true;
|
||||||
fileMock = new File([''], 'filename.zip', { type: 'application/zip' });
|
fileMock = new File([''], 'filename.zip', { type: 'application/zip' });
|
||||||
component.setFile(fileMock);
|
component.setFile(fileMock);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should show the file dropzone', () => {
|
||||||
|
const fileDropzone = fixture.debugElement.query(By.css('[data-test="file-dropzone"]'));
|
||||||
|
const fileUrlInput = fixture.debugElement.query(By.css('[data-test="file-url-input"]'));
|
||||||
|
expect(fileDropzone).toBeTruthy();
|
||||||
|
expect(fileUrlInput).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
describe('if proceed button is pressed without validate only', () => {
|
describe('if proceed button is pressed without validate only', () => {
|
||||||
beforeEach(fakeAsync(() => {
|
beforeEach(fakeAsync(() => {
|
||||||
component.validateOnly = false;
|
component.validateOnly = false;
|
||||||
@@ -99,9 +107,9 @@ describe('BatchImportPageComponent', () => {
|
|||||||
}));
|
}));
|
||||||
it('metadata-import script is invoked with --zip fileName and the mockFile', () => {
|
it('metadata-import script is invoked with --zip fileName and the mockFile', () => {
|
||||||
const parameterValues: ProcessParameter[] = [
|
const parameterValues: ProcessParameter[] = [
|
||||||
Object.assign(new ProcessParameter(), { name: '--zip', value: 'filename.zip' }),
|
Object.assign(new ProcessParameter(), { name: '--add' }),
|
||||||
|
Object.assign(new ProcessParameter(), { name: '--zip', value: 'filename.zip' })
|
||||||
];
|
];
|
||||||
parameterValues.push(Object.assign(new ProcessParameter(), { name: '--add' }));
|
|
||||||
expect(scriptService.invoke).toHaveBeenCalledWith(BATCH_IMPORT_SCRIPT_NAME, parameterValues, [fileMock]);
|
expect(scriptService.invoke).toHaveBeenCalledWith(BATCH_IMPORT_SCRIPT_NAME, parameterValues, [fileMock]);
|
||||||
});
|
});
|
||||||
it('success notification is shown', () => {
|
it('success notification is shown', () => {
|
||||||
@@ -121,8 +129,8 @@ describe('BatchImportPageComponent', () => {
|
|||||||
}));
|
}));
|
||||||
it('metadata-import script is invoked with --zip fileName and the mockFile and -v validate-only', () => {
|
it('metadata-import script is invoked with --zip fileName and the mockFile and -v validate-only', () => {
|
||||||
const parameterValues: ProcessParameter[] = [
|
const parameterValues: ProcessParameter[] = [
|
||||||
Object.assign(new ProcessParameter(), { name: '--zip', value: 'filename.zip' }),
|
|
||||||
Object.assign(new ProcessParameter(), { name: '--add' }),
|
Object.assign(new ProcessParameter(), { name: '--add' }),
|
||||||
|
Object.assign(new ProcessParameter(), { name: '--zip', value: 'filename.zip' }),
|
||||||
Object.assign(new ProcessParameter(), { name: '-v', value: true }),
|
Object.assign(new ProcessParameter(), { name: '-v', value: true }),
|
||||||
];
|
];
|
||||||
expect(scriptService.invoke).toHaveBeenCalledWith(BATCH_IMPORT_SCRIPT_NAME, parameterValues, [fileMock]);
|
expect(scriptService.invoke).toHaveBeenCalledWith(BATCH_IMPORT_SCRIPT_NAME, parameterValues, [fileMock]);
|
||||||
@@ -148,4 +156,77 @@ describe('BatchImportPageComponent', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('if url is set', () => {
|
||||||
|
beforeEach(fakeAsync(() => {
|
||||||
|
component.isUpload = false;
|
||||||
|
component.fileURL = 'example.fileURL.com';
|
||||||
|
fixture.detectChanges();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should show the file url input', () => {
|
||||||
|
const fileDropzone = fixture.debugElement.query(By.css('[data-test="file-dropzone"]'));
|
||||||
|
const fileUrlInput = fixture.debugElement.query(By.css('[data-test="file-url-input"]'));
|
||||||
|
expect(fileDropzone).toBeFalsy();
|
||||||
|
expect(fileUrlInput).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if proceed button is pressed without validate only', () => {
|
||||||
|
beforeEach(fakeAsync(() => {
|
||||||
|
component.validateOnly = false;
|
||||||
|
const proceed = fixture.debugElement.query(By.css('#proceedButton')).nativeElement;
|
||||||
|
proceed.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
}));
|
||||||
|
it('metadata-import script is invoked with --u and the file url', () => {
|
||||||
|
const parameterValues: ProcessParameter[] = [
|
||||||
|
Object.assign(new ProcessParameter(), { name: '--add' }),
|
||||||
|
Object.assign(new ProcessParameter(), { name: '--u', value: 'example.fileURL.com' })
|
||||||
|
];
|
||||||
|
expect(scriptService.invoke).toHaveBeenCalledWith(BATCH_IMPORT_SCRIPT_NAME, parameterValues, [null]);
|
||||||
|
});
|
||||||
|
it('success notification is shown', () => {
|
||||||
|
expect(notificationService.success).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
it('redirected to process page', () => {
|
||||||
|
expect(router.navigateByUrl).toHaveBeenCalledWith('/processes/46');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if proceed button is pressed with validate only', () => {
|
||||||
|
beforeEach(fakeAsync(() => {
|
||||||
|
component.validateOnly = true;
|
||||||
|
const proceed = fixture.debugElement.query(By.css('#proceedButton')).nativeElement;
|
||||||
|
proceed.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
}));
|
||||||
|
it('metadata-import script is invoked with --u and the file url and -v validate-only', () => {
|
||||||
|
const parameterValues: ProcessParameter[] = [
|
||||||
|
Object.assign(new ProcessParameter(), { name: '--add' }),
|
||||||
|
Object.assign(new ProcessParameter(), { name: '--u', value: 'example.fileURL.com' }),
|
||||||
|
Object.assign(new ProcessParameter(), { name: '-v', value: true }),
|
||||||
|
];
|
||||||
|
expect(scriptService.invoke).toHaveBeenCalledWith(BATCH_IMPORT_SCRIPT_NAME, parameterValues, [null]);
|
||||||
|
});
|
||||||
|
it('success notification is shown', () => {
|
||||||
|
expect(notificationService.success).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
it('redirected to process page', () => {
|
||||||
|
expect(router.navigateByUrl).toHaveBeenCalledWith('/processes/46');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if proceed is pressed; but script invoke fails', () => {
|
||||||
|
beforeEach(fakeAsync(() => {
|
||||||
|
jasmine.getEnv().allowRespy(true);
|
||||||
|
spyOn(scriptService, 'invoke').and.returnValue(createFailedRemoteDataObject$('Error', 500));
|
||||||
|
const proceed = fixture.debugElement.query(By.css('#proceedButton')).nativeElement;
|
||||||
|
proceed.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
}));
|
||||||
|
it('error notification is shown', () => {
|
||||||
|
expect(notificationService.error).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -8,7 +8,7 @@ import { ProcessParameter } from '../../process-page/processes/process-parameter
|
|||||||
import { getFirstCompletedRemoteData } from '../../core/shared/operators';
|
import { getFirstCompletedRemoteData } from '../../core/shared/operators';
|
||||||
import { RemoteData } from '../../core/data/remote-data';
|
import { RemoteData } from '../../core/data/remote-data';
|
||||||
import { Process } from '../../process-page/processes/process.model';
|
import { Process } from '../../process-page/processes/process.model';
|
||||||
import { isNotEmpty } from '../../shared/empty.util';
|
import { isEmpty, isNotEmpty } from '../../shared/empty.util';
|
||||||
import { getProcessDetailRoute } from '../../process-page/process-page-routing.paths';
|
import { getProcessDetailRoute } from '../../process-page/process-page-routing.paths';
|
||||||
import {
|
import {
|
||||||
ImportBatchSelectorComponent
|
ImportBatchSelectorComponent
|
||||||
@@ -32,11 +32,22 @@ export class BatchImportPageComponent {
|
|||||||
* The validate only flag
|
* The validate only flag
|
||||||
*/
|
*/
|
||||||
validateOnly = true;
|
validateOnly = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dso object for community or collection
|
* dso object for community or collection
|
||||||
*/
|
*/
|
||||||
dso: DSpaceObject = null;
|
dso: DSpaceObject = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The flag between upload and url
|
||||||
|
*/
|
||||||
|
isUpload = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File URL when flag is for url
|
||||||
|
*/
|
||||||
|
fileURL: string;
|
||||||
|
|
||||||
public constructor(private location: Location,
|
public constructor(private location: Location,
|
||||||
protected translate: TranslateService,
|
protected translate: TranslateService,
|
||||||
protected notificationsService: NotificationsService,
|
protected notificationsService: NotificationsService,
|
||||||
@@ -72,13 +83,18 @@ export class BatchImportPageComponent {
|
|||||||
* Starts import-metadata script with --zip fileName (and the selected file)
|
* Starts import-metadata script with --zip fileName (and the selected file)
|
||||||
*/
|
*/
|
||||||
public importMetadata() {
|
public importMetadata() {
|
||||||
if (this.fileObject == null) {
|
if (this.fileObject == null && isEmpty(this.fileURL)) {
|
||||||
this.notificationsService.error(this.translate.get('admin.metadata-import.page.error.addFile'));
|
this.notificationsService.error(this.translate.get('admin.metadata-import.page.error.addFile'));
|
||||||
} else {
|
} else {
|
||||||
const parameterValues: ProcessParameter[] = [
|
const parameterValues: ProcessParameter[] = [
|
||||||
Object.assign(new ProcessParameter(), { name: '--zip', value: this.fileObject.name }),
|
|
||||||
Object.assign(new ProcessParameter(), { name: '--add' })
|
Object.assign(new ProcessParameter(), { name: '--add' })
|
||||||
];
|
];
|
||||||
|
if (this.isUpload) {
|
||||||
|
parameterValues.push(Object.assign(new ProcessParameter(), { name: '--zip', value: this.fileObject.name }));
|
||||||
|
} else {
|
||||||
|
this.fileObject = null;
|
||||||
|
parameterValues.push(Object.assign(new ProcessParameter(), { name: '--u', value: this.fileURL }));
|
||||||
|
}
|
||||||
if (this.dso) {
|
if (this.dso) {
|
||||||
parameterValues.push(Object.assign(new ProcessParameter(), { name: '--collection', value: this.dso.uuid }));
|
parameterValues.push(Object.assign(new ProcessParameter(), { name: '--collection', value: this.dso.uuid }));
|
||||||
}
|
}
|
||||||
@@ -121,4 +137,11 @@ export class BatchImportPageComponent {
|
|||||||
removeDspaceObject(): void {
|
removeDspaceObject(): void {
|
||||||
this.dso = null;
|
this.dso = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* toggle the flag between upload and url
|
||||||
|
*/
|
||||||
|
toggleUpload() {
|
||||||
|
this.isUpload = !this.isUpload;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,7 +10,7 @@ import { AdminSearchModule } from './admin-search-page/admin-search.module';
|
|||||||
import { AdminSidebarSectionComponent } from './admin-sidebar/admin-sidebar-section/admin-sidebar-section.component';
|
import { AdminSidebarSectionComponent } from './admin-sidebar/admin-sidebar-section/admin-sidebar-section.component';
|
||||||
import { ExpandableAdminSidebarSectionComponent } from './admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component';
|
import { ExpandableAdminSidebarSectionComponent } from './admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component';
|
||||||
import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component';
|
import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component';
|
||||||
import { UploadModule } from '../shared/upload/upload.module';
|
import { UiSwitchModule } from 'ngx-ui-switch';
|
||||||
|
|
||||||
const ENTRY_COMPONENTS = [
|
const ENTRY_COMPONENTS = [
|
||||||
// put only entry components that use custom decorator
|
// put only entry components that use custom decorator
|
||||||
@@ -27,7 +27,7 @@ const ENTRY_COMPONENTS = [
|
|||||||
AdminSearchModule.withEntryComponents(),
|
AdminSearchModule.withEntryComponents(),
|
||||||
AdminWorkflowModuleModule.withEntryComponents(),
|
AdminWorkflowModuleModule.withEntryComponents(),
|
||||||
SharedModule,
|
SharedModule,
|
||||||
UploadModule,
|
UiSwitchModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
AdminCurationTasksComponent,
|
AdminCurationTasksComponent,
|
||||||
|
@@ -586,6 +586,12 @@
|
|||||||
|
|
||||||
"admin.batch-import.page.error.addFile": "Select Zip file first!",
|
"admin.batch-import.page.error.addFile": "Select Zip file first!",
|
||||||
|
|
||||||
|
"admin.metadata-import.page.toggle.upload": "Upload",
|
||||||
|
|
||||||
|
"admin.metadata-import.page.toggle.url": "URL",
|
||||||
|
|
||||||
|
"admin.metadata-import.page.urlMsg": "Insert the batch ZIP url to import",
|
||||||
|
|
||||||
"admin.metadata-import.page.validateOnly": "Validate Only",
|
"admin.metadata-import.page.validateOnly": "Validate Only",
|
||||||
|
|
||||||
"admin.metadata-import.page.validateOnly.hint": "When selected, the uploaded CSV will be validated. You will receive a report of detected changes, but no changes will be saved.",
|
"admin.metadata-import.page.validateOnly.hint": "When selected, the uploaded CSV will be validated. You will receive a report of detected changes, but no changes will be saved.",
|
||||||
|
Reference in New Issue
Block a user