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 7a0f07adda..7dc93e8adf 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 @@ -18,21 +18,36 @@ {{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.scss b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.scss new file mode 100644 index 0000000000..98f634e66b --- /dev/null +++ b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.scss @@ -0,0 +1,3 @@ +.spinner-button { + margin-bottom: calc((var(--bs-line-height-base) * 1rem - var(--bs-font-size-base)) / 2); +} \ No newline at end of file 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 ca6e1e9cd8..abc5fe3083 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 @@ -22,12 +22,14 @@ 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'; +import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; /** * Component that contains the controls to run, reset and test the harvest */ @Component({ selector: 'ds-collection-source-controls', + styleUrls: ['./collection-source-controls.component.scss'], templateUrl: './collection-source-controls.component.html', }) export class CollectionSourceControlsComponent implements OnDestroy { @@ -50,6 +52,10 @@ export class CollectionSourceControlsComponent implements OnDestroy { contentSource$: Observable; private subs: Subscription[] = []; + testConfigRunning$ = new BehaviorSubject(false); + importRunning$ = new BehaviorSubject(false); + reImportRunning$ = new BehaviorSubject(false); + constructor(private scriptDataService: ScriptDataService, private processDataService: ProcessDataService, private requestService: RequestService, @@ -75,6 +81,7 @@ export class CollectionSourceControlsComponent implements OnDestroy { * @param contentSource - The content source to be tested */ testConfiguration(contentSource) { + this.testConfigRunning$.next(true); this.subs.push(this.scriptDataService.invoke('harvest', [ {name: '-g', value: null}, {name: '-a', value: contentSource.oaiSource}, @@ -85,6 +92,7 @@ export class CollectionSourceControlsComponent implements OnDestroy { if (rd.hasFailed) { // show a notification when the script invocation fails this.notificationsService.error(this.translateService.get('collection.source.controls.test.submit.error')); + this.testConfigRunning$.next(false); } }), // filter out responses that aren't successful since the pinging of the process only needs to happen when the invocation was successful. @@ -104,6 +112,7 @@ export class CollectionSourceControlsComponent implements OnDestroy { } if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { this.notificationsService.error(this.translateService.get('collection.source.controls.test.failed')); + this.testConfigRunning$.next(false); } if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) { this.bitstreamService.findByHref(process._links.output.href).pipe(getFirstSucceededRemoteDataPayload()).subscribe((bitstream) => { @@ -114,6 +123,7 @@ export class CollectionSourceControlsComponent implements OnDestroy { this.notificationsService.info(this.translateService.get('collection.source.controls.test.completed'), output); }); }); + this.testConfigRunning$.next(false); } } )); @@ -123,6 +133,7 @@ export class CollectionSourceControlsComponent implements OnDestroy { * Start the harvest for the current collection */ importNow() { + this.importRunning$.next(true); this.subs.push(this.scriptDataService.invoke('harvest', [ {name: '-r', value: null}, {name: '-c', value: this.collection.uuid}, @@ -132,6 +143,7 @@ export class CollectionSourceControlsComponent implements OnDestroy { tap((rd) => { if (rd.hasFailed) { this.notificationsService.error(this.translateService.get('collection.source.controls.import.submit.error')); + this.importRunning$.next(false); } else { this.notificationsService.success(this.translateService.get('collection.source.controls.import.submit.success')); } @@ -153,10 +165,12 @@ export class CollectionSourceControlsComponent implements OnDestroy { } if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { this.notificationsService.error(this.translateService.get('collection.source.controls.import.failed')); + this.importRunning$.next(false); } if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) { this.notificationsService.success(this.translateService.get('collection.source.controls.import.completed')); - this.requestService.setStaleByHrefSubstring(this.collection._links.self.href); + this.requestService.setStaleByHrefSubstring(this.collection._links.self.href); + this.importRunning$.next(false); } } )); @@ -166,6 +180,7 @@ export class CollectionSourceControlsComponent implements OnDestroy { * Reset and reimport the current collection */ resetAndReimport() { + this.reImportRunning$.next(true); this.subs.push(this.scriptDataService.invoke('harvest', [ {name: '-o', value: null}, {name: '-c', value: this.collection.uuid}, @@ -175,6 +190,7 @@ export class CollectionSourceControlsComponent implements OnDestroy { tap((rd) => { if (rd.hasFailed) { this.notificationsService.error(this.translateService.get('collection.source.controls.reset.submit.error')); + this.reImportRunning$.next(false); } else { this.notificationsService.success(this.translateService.get('collection.source.controls.reset.submit.success')); } @@ -196,10 +212,12 @@ export class CollectionSourceControlsComponent implements OnDestroy { } if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) { this.notificationsService.error(this.translateService.get('collection.source.controls.reset.failed')); + this.reImportRunning$.next(false); } 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); + this.reImportRunning$.next(false); } } )); diff --git a/src/app/core/shared/content-source.model.ts b/src/app/core/shared/content-source.model.ts index cb78c85a7c..40cf43ad0c 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, serializeAs } from 'cerialize'; +import { autoserializeAs, deserialize, deserializeAs, serializeAs } from 'cerialize'; import { HALLink } from './hal-link.model'; import { MetadataConfig } from './metadata-config.model'; import { CacheableObject } from '../cache/object-cache.reducer'; @@ -6,7 +6,6 @@ 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'; /** diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 052f0ecc2b..ebf849f1a7 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -886,9 +886,11 @@ "collection.source.controls.test.failed": "The script to test the settings has failed", "collection.source.controls.test.completed": "The script to test the settings has successfully finished", "collection.source.controls.test.submit": "Test configuration", + "collection.source.controls.test.running": "Testing configuration...", "collection.source.controls.import.submit.success": "The import has been successfully initiated", "collection.source.controls.import.submit.error": "Something went wrong with initiating the import", "collection.source.controls.import.submit": "Import now", + "collection.source.controls.import.running": "Importing...", "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", @@ -896,6 +898,7 @@ "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.reset.running": "Resetting and reimporting...", "collection.source.controls.harvest.status": "Harvest status:", "collection.source.controls.harvest.start": "Harvest start time:", "collection.source.controls.harvest.last": "Last time harvested:",