diff --git a/src/app/process-page/form/process-form.component.ts b/src/app/process-page/form/process-form.component.ts index d361926bc7..b85c1cd0bf 100644 --- a/src/app/process-page/form/process-form.component.ts +++ b/src/app/process-page/form/process-form.component.ts @@ -177,5 +177,27 @@ export class ProcessFormComponent implements OnInit { }; void this.router.navigate([getProcessListRoute()], extras); } -} + updateScript($event: Script) { + this.selectedScript = $event; + this.parameters = undefined; + } + + get generatedProcessName() { + const paramsString = this.parameters?.map((p: ProcessParameter) => { + const value = this.parseValue(p.value); + return isEmpty(value) ? p.name : `${p.name} ${value}`; + }).join(' ') || ''; + return isEmpty(paramsString) ? this.selectedScript.name : `${this.selectedScript.name} ${paramsString}`; + } + + private parseValue(value: any) { + if (typeof value === 'boolean') { + return undefined; + } + if (value instanceof File) { + return value.name; + } + return value?.toString(); + } +} diff --git a/src/app/process-page/overview/table/process-overview-table.component.spec.ts b/src/app/process-page/overview/table/process-overview-table.component.spec.ts index 9684e22ce2..c704b2b3ea 100644 --- a/src/app/process-page/overview/table/process-overview-table.component.spec.ts +++ b/src/app/process-page/overview/table/process-overview-table.component.spec.ts @@ -10,7 +10,10 @@ import { NgbCollapse, NgbModal, } from '@ng-bootstrap/ng-bootstrap'; -import { TranslateModule } from '@ngx-translate/core'; +import { + TranslateModule, + TranslateService, +} from '@ngx-translate/core'; import { BehaviorSubject } from 'rxjs'; import { take } from 'rxjs/operators'; @@ -50,6 +53,8 @@ describe('ProcessOverviewTableComponent', () => { let processes: Process[]; let ePerson: EPerson; + let translateServiceSpy: jasmine.SpyObj; + function init() { processes = [ Object.assign(new Process(), { @@ -58,6 +63,7 @@ describe('ProcessOverviewTableComponent', () => { startTime: '2020-03-19 00:30:00', endTime: '2020-03-19 23:30:00', processStatus: ProcessStatus.COMPLETED, + userId: 'testid', }), Object.assign(new Process(), { processId: 2, @@ -65,6 +71,7 @@ describe('ProcessOverviewTableComponent', () => { startTime: '2020-03-20 00:30:00', endTime: '2020-03-20 23:30:00', processStatus: ProcessStatus.FAILED, + userId: 'testid', }), Object.assign(new Process(), { processId: 3, @@ -72,9 +79,12 @@ describe('ProcessOverviewTableComponent', () => { startTime: '2020-03-21 00:30:00', endTime: '2020-03-21 23:30:00', processStatus: ProcessStatus.RUNNING, + userId: 'testid', }), ]; ePerson = Object.assign(new EPerson(), { + id: 'testid', + uuid: 'testid', metadata: { 'eperson.firstname': [ { @@ -133,6 +143,8 @@ describe('ProcessOverviewTableComponent', () => { beforeEach(waitForAsync(() => { init(); + translateServiceSpy = jasmine.createSpyObj('TranslateService', ['get']); + void TestBed.configureTestingModule({ declarations: [NgbCollapse], imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), VarDirective, ProcessOverviewTableComponent], @@ -217,4 +229,43 @@ describe('ProcessOverviewTableComponent', () => { }); }); + + describe('getEPersonName function', () => { + it('should return unknown user when id is null', (done: DoneFn) => { + const id = null; + const expectedTranslation = 'process.overview.unknown.user'; + + translateServiceSpy.get(expectedTranslation); + + component.getEPersonName(id).subscribe((result: string) => { + expect(result).toBe(expectedTranslation); + done(); + }); + expect(translateServiceSpy.get).toHaveBeenCalledWith('process.overview.unknown.user'); + }); + + it('should return unknown user when id is invalid', (done: DoneFn) => { + const id = ''; + const expectedTranslation = 'process.overview.unknown.user'; + + translateServiceSpy.get(expectedTranslation); + + component.getEPersonName(id).subscribe((result: string) => { + expect(result).toBe(expectedTranslation); + done(); + }); + expect(translateServiceSpy.get).toHaveBeenCalledWith('process.overview.unknown.user'); + }); + + it('should return EPerson name when id is correct', (done: DoneFn) => { + const id = 'testid'; + const expectedName = 'John Doe'; + + component.getEPersonName(id).subscribe((result: string) => { + expect(result).toEqual(expectedName); + done(); + }); + expect(translateServiceSpy.get).not.toHaveBeenCalled(); + }); + }); }); diff --git a/src/app/process-page/overview/table/process-overview-table.component.ts b/src/app/process-page/overview/table/process-overview-table.component.ts index 4df95e8780..492b44af1f 100644 --- a/src/app/process-page/overview/table/process-overview-table.component.ts +++ b/src/app/process-page/overview/table/process-overview-table.component.ts @@ -18,7 +18,10 @@ import { RouterLink, } from '@angular/router'; import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap'; -import { TranslateModule } from '@ngx-translate/core'; +import { + TranslateModule, + TranslateService, +} from '@ngx-translate/core'; import { BehaviorSubject, from as observableFrom, @@ -46,9 +49,12 @@ import { RouteService } from '../../../core/services/route.service'; import { redirectOn4xx } from '../../../core/shared/authorized.operators'; import { getAllCompletedRemoteData, - getFirstSucceededRemoteDataPayload, + getFirstCompletedRemoteData, } from '../../../core/shared/operators'; -import { hasValue } from '../../../shared/empty.util'; +import { + hasValue, + isNotEmpty, +} from '../../../shared/empty.util'; import { ThemedLoadingComponent } from '../../../shared/loading/themed-loading.component'; import { PaginationComponent } from '../../../shared/pagination/pagination.component'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; @@ -153,12 +159,13 @@ export class ProcessOverviewTableComponent implements OnInit, OnDestroy { constructor(protected processOverviewService: ProcessOverviewService, protected processBulkDeleteService: ProcessBulkDeleteService, - protected ePersonDataService: EPersonDataService, - protected dsoNameService: DSONameService, + public ePersonDataService: EPersonDataService, + public dsoNameService: DSONameService, protected paginationService: PaginationService, protected routeService: RouteService, protected router: Router, protected auth: AuthService, + private translateService: TranslateService, @Inject(PLATFORM_ID) protected platformId: object, ) { } @@ -176,7 +183,7 @@ export class ProcessOverviewTableComponent implements OnInit, OnDestroy { // Creates an ID from the first 2 characters of the process status. // Should two process status values ever start with the same substring, // increase the number of characters until the ids are distinct. - this.paginationId = this.processStatus.toLowerCase().substring(0,2); + this.paginationId = this.processStatus.toLowerCase().substring(0, 2); const defaultPaginationOptions = Object.assign(new PaginationComponentOptions(), { id: this.paginationId, @@ -218,7 +225,7 @@ export class ProcessOverviewTableComponent implements OnInit, OnDestroy { // Map RemoteData> to RemoteData> switchMap((processesRD: RemoteData>) => { // Create observable emitting all processes one by one - return observableFrom(processesRD.payload.page).pipe( + return observableFrom(processesRD.payload.page).pipe( // Map every Process to ProcessOverviewTableEntry mergeMap((process: Process) => { return this.getEPersonName(process.userId).pipe( @@ -243,7 +250,6 @@ export class ProcessOverviewTableComponent implements OnInit, OnDestroy { }), ); }), - ).subscribe((next: RemoteData>) => { this.processesRD$.next(next); })); @@ -267,10 +273,20 @@ export class ProcessOverviewTableComponent implements OnInit, OnDestroy { * @param id ID of the EPerson */ getEPersonName(id: string): Observable { - return this.ePersonDataService.findById(id).pipe( - getFirstSucceededRemoteDataPayload(), - map((eperson: EPerson) => this.dsoNameService.getName(eperson)), - ); + if (isNotEmpty(id)) { + return this.ePersonDataService.findById(id).pipe( + getFirstCompletedRemoteData(), + switchMap((rd: RemoteData) => { + if (rd.hasSucceeded) { + return [this.dsoNameService.getName(rd.payload)]; + } else { + return this.translateService.get('process.overview.unknown.user'); + } + }), + ); + } else { + return this.translateService.get('process.overview.unknown.user'); + } } /** diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index f1175ad61a..a9bff0ce76 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3846,6 +3846,8 @@ "process.overview.delete.header": "Delete processes", + "process.overview.unknown.user": "Unknown", + "process.bulk.delete.error.head": "Error on deleteing process", "process.bulk.delete.error.body": "The process with ID {{processId}} could not be deleted. The remaining processes will continue being deleted. ",