diff --git a/src/app/process-page/detail/process-detail.component.html b/src/app/process-page/detail/process-detail.component.html
index e76d24d17a..e13770a0a3 100644
--- a/src/app/process-page/detail/process-detail.component.html
+++ b/src/app/process-page/detail/process-detail.component.html
@@ -34,13 +34,19 @@
{{ process.processStatus }}
-
- 0">{{ (outputLogs$ | async)?.join('\n') }}
-
- {{ 'process.detail.logs.none' | translate }}
-
-
+
+
+
+ 0">{{ (outputLogs$ | async)?.join('\n') }}
+
+ {{ 'process.detail.logs.none' | translate }}
+
+
- {{'process.detail.back' | translate}}
+
diff --git a/src/app/process-page/detail/process-detail.component.spec.ts b/src/app/process-page/detail/process-detail.component.spec.ts
index c1efd233e8..8d4a3f0e62 100644
--- a/src/app/process-page/detail/process-detail.component.spec.ts
+++ b/src/app/process-page/detail/process-detail.component.spec.ts
@@ -1,7 +1,7 @@
import { ProcessOutputDataService } from '../../core/data/process-output-data.service';
import { ProcessOutput } from '../processes/process-output.model';
import { ProcessDetailComponent } from './process-detail.component';
-import { async, ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
+import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { VarDirective } from '../../shared/utils/var.directive';
import { TranslateModule } from '@ngx-translate/core';
import { RouterTestingModule } from '@angular/router/testing';
@@ -93,7 +93,10 @@ describe('ProcessDetailComponent', () => {
declarations: [ProcessDetailComponent, ProcessDetailFieldComponent, VarDirective, FileSizePipe],
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])],
providers: [
- { provide: ActivatedRoute, useValue: { data: observableOf({ process: createSuccessfulRemoteDataObject(process) }) } },
+ {
+ provide: ActivatedRoute,
+ useValue: { data: observableOf({ process: createSuccessfulRemoteDataObject(process) }) }
+ },
{ provide: ProcessDataService, useValue: processService },
{ provide: ProcessOutputDataService, useValue: processOutputService },
{ provide: DSONameService, useValue: nameService }
@@ -105,15 +108,16 @@ describe('ProcessDetailComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(ProcessDetailComponent);
component = fixture.componentInstance;
- fixture.detectChanges();
});
it('should display the script\'s name', () => {
+ fixture.detectChanges();
const name = fixture.debugElement.query(By.css('#process-name')).nativeElement;
expect(name.textContent).toContain(process.scriptName);
});
it('should display the process\'s parameters', () => {
+ fixture.detectChanges();
const args = fixture.debugElement.query(By.css('#process-arguments')).nativeElement;
process.parameters.forEach((param) => {
expect(args.textContent).toContain(`${param.name} ${param.value}`)
@@ -121,27 +125,52 @@ describe('ProcessDetailComponent', () => {
});
it('should display the process\'s output files', () => {
+ fixture.detectChanges();
const processFiles = fixture.debugElement.query(By.css('#process-files')).nativeElement;
expect(processFiles.textContent).toContain(fileName);
});
- it('should display the process\'s output logs', () => {
- const outputProcess = fixture.debugElement.query(By.css('#process-output pre')).nativeElement;
- expect(outputProcess.textContent).toContain('Process started');
+ describe('if press show output logs', () => {
+ beforeEach(fakeAsync(() => {
+ spyOn(component, 'showProcessOutputLogs').and.callThrough();
+ fixture.detectChanges();
+ const showOutputButton = fixture.debugElement.query(By.css('#showOutputButton'));
+ showOutputButton.triggerEventHandler('click', {
+ preventDefault: () => {/**/
+ }
+ });
+ tick();
+ }));
+ it('should trigger showProcessOutputLogs', () => {
+ expect(component.showProcessOutputLogs).toHaveBeenCalled();
+ });
+ it('should display the process\'s output logs', () => {
+ fixture.detectChanges();
+ const outputProcess = fixture.debugElement.query(By.css('#process-output pre'));
+ expect(outputProcess.nativeElement.textContent).toContain('Process started');
+ });
});
- describe('if process has no output logs (yet)', () => {
+ describe('if press show output logs and process has no output logs (yet)', () => {
beforeEach(fakeAsync(() => {
- jasmine.getEnv().allowRespy(true);
- const emptyProcessOutput = Object.assign(new ProcessOutput(), {
- logs: []
- });
- spyOn(processOutputService, 'findByHref').and.returnValue(createSuccessfulRemoteDataObject$(emptyProcessOutput));
- fixture = TestBed.createComponent(ProcessDetailComponent);
- component = fixture.componentInstance;
- fixture.detectChanges();
- })
- );
+ jasmine.getEnv().allowRespy(true);
+ const emptyProcessOutput = Object.assign(new ProcessOutput(), {
+ logs: []
+ });
+ spyOn(processOutputService, 'findByHref').and.returnValue(createSuccessfulRemoteDataObject$(emptyProcessOutput));
+ fixture = TestBed.createComponent(ProcessDetailComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ spyOn(component, 'showProcessOutputLogs').and.callThrough();
+ fixture.detectChanges();
+ const showOutputButton = fixture.debugElement.query(By.css('#showOutputButton'));
+ showOutputButton.triggerEventHandler('click', {
+ preventDefault: () => {/**/
+ }
+ });
+ tick();
+ fixture.detectChanges();
+ }));
it('should not display the process\'s output logs', () => {
const outputProcess = fixture.debugElement.query(By.css('#process-output pre'));
expect(outputProcess).toBeNull();
@@ -150,7 +179,6 @@ describe('ProcessDetailComponent', () => {
const noOutputProcess = fixture.debugElement.query(By.css('#no-output-logs-message')).nativeElement;
expect(noOutputProcess).toBeDefined();
});
- }
- )
+ });
});
diff --git a/src/app/process-page/detail/process-detail.component.ts b/src/app/process-page/detail/process-detail.component.ts
index af6e3238a6..f6b628f0f8 100644
--- a/src/app/process-page/detail/process-detail.component.ts
+++ b/src/app/process-page/detail/process-detail.component.ts
@@ -1,12 +1,13 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, NgZone, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
+import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
import { Observable } from 'rxjs/internal/Observable';
import { ProcessOutputDataService } from '../../core/data/process-output-data.service';
import { RemoteData } from '../../core/data/remote-data';
import { DSpaceObject } from '../../core/shared/dspace-object.model';
import { ProcessOutput } from '../processes/process-output.model';
import { Process } from '../processes/process.model';
-import { map, switchMap } from 'rxjs/operators';
+import { finalize, map, switchMap, take } from 'rxjs/operators';
import { getFirstSucceededRemoteDataPayload, redirectToPageNotFoundOn404 } from '../../core/shared/operators';
import { AlertType } from '../../shared/alert/aletr-type';
import { ProcessDataService } from '../../core/data/processes/process-data.service';
@@ -44,11 +45,21 @@ export class ProcessDetailComponent implements OnInit {
*/
outputLogs$: Observable;
+ /**
+ * Boolean on whether or not to show the output logs
+ */
+ showOutputLogs = false;
+ /**
+ * When it's retrieving the output logs from backend, to show loading component
+ */
+ retrievingOutputLogs$ = new BehaviorSubject(false);
+
constructor(protected route: ActivatedRoute,
protected router: Router,
protected processService: ProcessDataService,
protected processOutputService: ProcessOutputDataService,
- protected nameService: DSONameService) {
+ protected nameService: DSONameService,
+ private zone: NgZone) {
}
/**
@@ -65,17 +76,6 @@ export class ProcessDetailComponent implements OnInit {
getFirstSucceededRemoteDataPayload(),
switchMap((process: Process) => this.processService.getFiles(process.processId))
);
-
- const processOutputRD$: Observable> = this.processRD$.pipe(
- getFirstSucceededRemoteDataPayload(),
- switchMap((process: Process) => this.processOutputService.findByHref(process._links.output.href))
- );
- this.outputLogs$ = processOutputRD$.pipe(
- getFirstSucceededRemoteDataPayload(),
- map((processOutput: ProcessOutput) => {
- return processOutput.logs;
- })
- )
}
/**
@@ -86,4 +86,27 @@ export class ProcessDetailComponent implements OnInit {
return bitstream instanceof DSpaceObject ? this.nameService.getName(bitstream) : 'unknown';
}
+ /**
+ * Retrieves the process logs, while setting the loading subject to true.
+ * Sets the outputLogs when retrieved and sets the showOutputLogs boolean to show them and hide the button.
+ */
+ showProcessOutputLogs() {
+ this.retrievingOutputLogs$.next(true);
+ this.zone.runOutsideAngular(() => {
+ const processOutputRD$: Observable> = this.processRD$.pipe(
+ getFirstSucceededRemoteDataPayload(),
+ switchMap((process: Process) => this.processOutputService.findByHref(process._links.output.href))
+ );
+ this.outputLogs$ = processOutputRD$.pipe(
+ getFirstSucceededRemoteDataPayload(),
+ map((processOutput: ProcessOutput) => {
+ this.showOutputLogs = true;
+ return processOutput.logs;
+ }),
+ finalize(() => this.zone.run(() => this.retrievingOutputLogs$.next(false))),
+ )
+ });
+ this.outputLogs$.pipe(take(1)).subscribe();
+ }
+
}
diff --git a/src/app/process-page/process-page.resolver.ts b/src/app/process-page/process-page.resolver.ts
index 57c749e1cb..84821a2574 100644
--- a/src/app/process-page/process-page.resolver.ts
+++ b/src/app/process-page/process-page.resolver.ts
@@ -24,7 +24,7 @@ export class ProcessPageResolver implements Resolve> {
* or an error if something went wrong
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable> {
- return this.processService.findById(route.params.id, followLink('script'), followLink('output') ).pipe(
+ return this.processService.findById(route.params.id, followLink('script')).pipe(
find((RD) => hasValue(RD.error) || RD.hasSucceeded),
);
}
diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5
index 75db3eceb1..036fd87ec8 100644
--- a/src/assets/i18n/en.json5
+++ b/src/assets/i18n/en.json5
@@ -2085,6 +2085,10 @@
"process.detail.output" : "Process Output",
+ "process.detail.logs.button": "Retrieve process output",
+
+ "process.detail.logs.loading": "Retrieving",
+
"process.detail.logs.none": "This process has no output yet",
"process.detail.output-files" : "Output Files",