diff --git a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.html b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.html
index 425d773e2d..7a0f07adda 100644
--- a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.html
+++ b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.html
@@ -11,6 +11,10 @@
{{'collection.source.controls.harvest.last' | translate}}
+ {{contentSource?.message ? contentSource?.message : 'collection.source.controls.harvest.no-information'|translate }}
+
+
+ {{'collection.source.controls.harvest.message' | translate}}
{{contentSource?.lastHarvested ? contentSource?.lastHarvested : 'collection.source.controls.harvest.no-information'|translate }}
diff --git a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts
index 3307b8fc79..3eb83ebe8a 100644
--- a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts
+++ b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts
@@ -21,6 +21,7 @@ import { getTestScheduler } from 'jasmine-marbles';
import { TestScheduler } from 'rxjs/testing';
import { By } from '@angular/platform-browser';
import { VarDirective } from '../../../../shared/utils/var.directive';
+import { ContentSourceSetSerializer } from '../../../../core/shared/content-source-set-serializer';
describe('CollectionSourceControlsComponent', () => {
let comp: CollectionSourceControlsComponent;
@@ -133,7 +134,7 @@ describe('CollectionSourceControlsComponent', () => {
expect(scriptDataService.invoke).toHaveBeenCalledWith('harvest', [
{name: '-g', value: null},
{name: '-a', value: contentSource.oaiSource},
- {name: '-i', value: contentSource.oaiSetId},
+ {name: '-i', value: new ContentSourceSetSerializer().Serialize(contentSource.oaiSetId)},
], []);
expect(processDataService.findById).toHaveBeenCalledWith(process.processId, false);
@@ -148,7 +149,19 @@ describe('CollectionSourceControlsComponent', () => {
expect(scriptDataService.invoke).toHaveBeenCalledWith('harvest', [
{name: '-r', value: null},
- {name: '-e', value: 'dspacedemo+admin@gmail.com'},
+ {name: '-c', value: collection.uuid},
+ ], []);
+ expect(processDataService.findById).toHaveBeenCalledWith(process.processId, false);
+ expect(notificationsService.success).toHaveBeenCalled();
+ });
+ });
+ describe('resetAndReimport', () => {
+ it('should invoke a script that will start the harvest', () => {
+ comp.resetAndReimport();
+ scheduler.flush();
+
+ expect(scriptDataService.invoke).toHaveBeenCalledWith('harvest', [
+ {name: '-o', value: null},
{name: '-c', value: collection.uuid},
], []);
expect(processDataService.findById).toHaveBeenCalledWith(process.processId, false);
diff --git a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts
index 4562772391..ca6e1e9cd8 100644
--- a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts
+++ b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts
@@ -21,6 +21,7 @@ import { Process } from '../../../../process-page/processes/process.model';
import { TranslateService } from '@ngx-translate/core';
import { HttpClient } from '@angular/common/http';
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
+import { ContentSourceSetSerializer } from '../../../../core/shared/content-source-set-serializer';
/**
* Component that contains the controls to run, reset and test the harvest
@@ -77,7 +78,7 @@ export class CollectionSourceControlsComponent implements OnDestroy {
this.subs.push(this.scriptDataService.invoke('harvest', [
{name: '-g', value: null},
{name: '-a', value: contentSource.oaiSource},
- {name: '-i', value: contentSource.oaiSetId},
+ {name: '-i', value: new ContentSourceSetSerializer().Serialize(contentSource.oaiSetId)},
], []).pipe(
getFirstCompletedRemoteData(),
tap((rd) => {
@@ -124,14 +125,15 @@ export class CollectionSourceControlsComponent implements OnDestroy {
importNow() {
this.subs.push(this.scriptDataService.invoke('harvest', [
{name: '-r', value: null},
- {name: '-e', value: 'dspacedemo+admin@gmail.com'},
{name: '-c', value: this.collection.uuid},
], [])
.pipe(
getFirstCompletedRemoteData(),
tap((rd) => {
if (rd.hasFailed) {
- this.notificationsService.error(this.translateService.get('collection.source.controls.test.submit.error'));
+ this.notificationsService.error(this.translateService.get('collection.source.controls.import.submit.error'));
+ } else {
+ this.notificationsService.success(this.translateService.get('collection.source.controls.import.submit.success'));
}
}),
filter((rd) => rd.hasSucceeded && hasValue(rd.payload)),
@@ -164,7 +166,43 @@ export class CollectionSourceControlsComponent implements OnDestroy {
* Reset and reimport the current collection
*/
resetAndReimport() {
- // TODO implement when a single option is present
+ this.subs.push(this.scriptDataService.invoke('harvest', [
+ {name: '-o', value: null},
+ {name: '-c', value: this.collection.uuid},
+ ], [])
+ .pipe(
+ getFirstCompletedRemoteData(),
+ tap((rd) => {
+ if (rd.hasFailed) {
+ this.notificationsService.error(this.translateService.get('collection.source.controls.reset.submit.error'));
+ } else {
+ this.notificationsService.success(this.translateService.get('collection.source.controls.reset.submit.success'));
+ }
+ }),
+ filter((rd) => rd.hasSucceeded && hasValue(rd.payload)),
+ switchMap((rd) => this.processDataService.findById(rd.payload.processId, false)),
+ getAllCompletedRemoteData(),
+ filter((rd) => !rd.isStale && (rd.hasSucceeded || rd.hasFailed)),
+ map((rd) => rd.payload),
+ hasValueOperator(),
+ ).subscribe((process) => {
+ if (process.processStatus.toString() !== ProcessStatus[ProcessStatus.COMPLETED].toString() &&
+ process.processStatus.toString() !== ProcessStatus[ProcessStatus.FAILED].toString()) {
+ // Ping the current process state every 5s
+ setTimeout(() => {
+ this.requestService.setStaleByHrefSubstring(process._links.self.href);
+ this.requestService.setStaleByHrefSubstring(this.collection._links.self.href);
+ }, 5000);
+ }
+ if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) {
+ this.notificationsService.error(this.translateService.get('collection.source.controls.reset.failed'));
+ }
+ if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) {
+ this.notificationsService.success(this.translateService.get('collection.source.controls.reset.completed'));
+ this.requestService.setStaleByHrefSubstring(this.collection._links.self.href);
+ }
+ }
+ ));
}
ngOnDestroy(): void {
diff --git a/src/app/core/shared/content-source-set-serializer.spec.ts b/src/app/core/shared/content-source-set-serializer.spec.ts
new file mode 100644
index 0000000000..2203481250
--- /dev/null
+++ b/src/app/core/shared/content-source-set-serializer.spec.ts
@@ -0,0 +1,26 @@
+import { ContentSourceSetSerializer } from './content-source-set-serializer';
+
+describe('ContentSourceSetSerializer', () => {
+ let serializer: ContentSourceSetSerializer;
+
+ beforeEach(() => {
+ serializer = new ContentSourceSetSerializer();
+ });
+
+ describe('Serialize', () => {
+ it('should return all when the value is empty', () => {
+ expect(serializer.Serialize('')).toEqual('all');
+ });
+ it('should return the value when it is not empty', () => {
+ expect(serializer.Serialize('test-value')).toEqual('test-value');
+ });
+ });
+ describe('Deserialize', () => {
+ it('should return an empty value when the value is \'all\'', () => {
+ expect(serializer.Deserialize('all')).toEqual('');
+ });
+ it('should return the value when it is not \'all\'', () => {
+ expect(serializer.Deserialize('test-value')).toEqual('test-value');
+ });
+ });
+});
diff --git a/src/app/core/shared/content-source-set-serializer.ts b/src/app/core/shared/content-source-set-serializer.ts
new file mode 100644
index 0000000000..ec0baec5a6
--- /dev/null
+++ b/src/app/core/shared/content-source-set-serializer.ts
@@ -0,0 +1,31 @@
+import { isEmpty } from '../../shared/empty.util';
+
+/**
+ * Serializer to create convert the 'all' value supported by the server to an empty string and vice versa.
+ */
+export class ContentSourceSetSerializer {
+
+ /**
+ * Method to serialize a setId
+ * @param {string} setId
+ * @returns {string} the provided set ID, unless when an empty set ID is provided. In that case, 'all' will be returned.
+ */
+ Serialize(setId: string): any {
+ if (isEmpty(setId)) {
+ return 'all';
+ }
+ return setId;
+ }
+
+ /**
+ * Method to deserialize a setId
+ * @param {string} setId
+ * @returns {string} the provided set ID. When 'all' is provided, an empty set ID will be returned.
+ */
+ Deserialize(setId: string): string {
+ if (setId === 'all') {
+ return '';
+ }
+ return setId;
+ }
+}
diff --git a/src/app/core/shared/content-source.model.ts b/src/app/core/shared/content-source.model.ts
index c98901219d..cb78c85a7c 100644
--- a/src/app/core/shared/content-source.model.ts
+++ b/src/app/core/shared/content-source.model.ts
@@ -1,4 +1,4 @@
-import { autoserializeAs, deserializeAs, deserialize } from 'cerialize';
+import { autoserializeAs, deserializeAs, deserialize, serializeAs } from 'cerialize';
import { HALLink } from './hal-link.model';
import { MetadataConfig } from './metadata-config.model';
import { CacheableObject } from '../cache/object-cache.reducer';
@@ -6,6 +6,8 @@ import { typedObject } from '../cache/builders/build-decorators';
import { CONTENT_SOURCE } from './content-source.resource-type';
import { excludeFromEquals } from '../utilities/equals.decorators';
import { ResourceType } from './resource-type';
+import { IDToUUIDSerializer } from '../cache/id-to-uuid-serializer';
+import { ContentSourceSetSerializer } from './content-source-set-serializer';
/**
* The type of content harvesting used
@@ -49,7 +51,8 @@ export class ContentSource extends CacheableObject {
/**
* OAI Specific set ID
*/
- @autoserializeAs('oai_set_id')
+ @deserializeAs(new ContentSourceSetSerializer(), 'oai_set_id')
+ @serializeAs(new ContentSourceSetSerializer(), 'oai_set_id')
oaiSetId: string;
/**
@@ -70,15 +73,30 @@ export class ContentSource extends CacheableObject {
*/
metadataConfigs: MetadataConfig[];
+ /**
+ * The current harvest status
+ */
@autoserializeAs('harvest_status')
harvestStatus: string;
+ /**
+ * The last's harvest start time
+ */
@autoserializeAs('harvest_start_time')
harvestStartTime: string;
+ /**
+ * When the collection was last harvested
+ */
@autoserializeAs('last_harvested')
lastHarvested: string;
+ /**
+ * The current harvest message
+ */
+ @autoserializeAs('harvest_message')
+ message: string;
+
/**
* The {@link HALLink}s for this ContentSource
*/
diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5
index 8d89561d68..052f0ecc2b 100644
--- a/src/assets/i18n/en.json5
+++ b/src/assets/i18n/en.json5
@@ -891,10 +891,15 @@
"collection.source.controls.import.submit": "Import now",
"collection.source.controls.import.failed": "An error occurred during the import",
"collection.source.controls.import.completed": "The import completed",
+ "collection.source.controls.reset.submit.success": "The reset and reimport has been successfully initiated",
+ "collection.source.controls.reset.submit.error": "Something went wrong with initiating the reset and reimport",
+ "collection.source.controls.reset.failed": "An error occurred during the reset and reimport",
+ "collection.source.controls.reset.completed": "The reset and reimport completed",
"collection.source.controls.reset.submit": "Reset and reimport",
"collection.source.controls.harvest.status": "Harvest status:",
"collection.source.controls.harvest.start": "Harvest start time:",
"collection.source.controls.harvest.last": "Last time harvested:",
+ "collection.source.controls.harvest.message": "Harvest info:",
"collection.source.controls.harvest.no-information": "N/A",