mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Merge pull request #3014 from atmire/w2p-113904_AddSupportForNullUsers
Handle Null Users Gracefully in Process Overview Page
This commit is contained in:
@@ -177,5 +177,27 @@ export class ProcessFormComponent implements OnInit {
|
|||||||
};
|
};
|
||||||
void this.router.navigate([getProcessListRoute()], extras);
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -10,7 +10,10 @@ import {
|
|||||||
NgbCollapse,
|
NgbCollapse,
|
||||||
NgbModal,
|
NgbModal,
|
||||||
} from '@ng-bootstrap/ng-bootstrap';
|
} from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import {
|
||||||
|
TranslateModule,
|
||||||
|
TranslateService,
|
||||||
|
} from '@ngx-translate/core';
|
||||||
import { BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
import { take } from 'rxjs/operators';
|
import { take } from 'rxjs/operators';
|
||||||
|
|
||||||
@@ -50,6 +53,8 @@ describe('ProcessOverviewTableComponent', () => {
|
|||||||
let processes: Process[];
|
let processes: Process[];
|
||||||
let ePerson: EPerson;
|
let ePerson: EPerson;
|
||||||
|
|
||||||
|
let translateServiceSpy: jasmine.SpyObj<TranslateService>;
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
processes = [
|
processes = [
|
||||||
Object.assign(new Process(), {
|
Object.assign(new Process(), {
|
||||||
@@ -58,6 +63,7 @@ describe('ProcessOverviewTableComponent', () => {
|
|||||||
startTime: '2020-03-19 00:30:00',
|
startTime: '2020-03-19 00:30:00',
|
||||||
endTime: '2020-03-19 23:30:00',
|
endTime: '2020-03-19 23:30:00',
|
||||||
processStatus: ProcessStatus.COMPLETED,
|
processStatus: ProcessStatus.COMPLETED,
|
||||||
|
userId: 'testid',
|
||||||
}),
|
}),
|
||||||
Object.assign(new Process(), {
|
Object.assign(new Process(), {
|
||||||
processId: 2,
|
processId: 2,
|
||||||
@@ -65,6 +71,7 @@ describe('ProcessOverviewTableComponent', () => {
|
|||||||
startTime: '2020-03-20 00:30:00',
|
startTime: '2020-03-20 00:30:00',
|
||||||
endTime: '2020-03-20 23:30:00',
|
endTime: '2020-03-20 23:30:00',
|
||||||
processStatus: ProcessStatus.FAILED,
|
processStatus: ProcessStatus.FAILED,
|
||||||
|
userId: 'testid',
|
||||||
}),
|
}),
|
||||||
Object.assign(new Process(), {
|
Object.assign(new Process(), {
|
||||||
processId: 3,
|
processId: 3,
|
||||||
@@ -72,9 +79,12 @@ describe('ProcessOverviewTableComponent', () => {
|
|||||||
startTime: '2020-03-21 00:30:00',
|
startTime: '2020-03-21 00:30:00',
|
||||||
endTime: '2020-03-21 23:30:00',
|
endTime: '2020-03-21 23:30:00',
|
||||||
processStatus: ProcessStatus.RUNNING,
|
processStatus: ProcessStatus.RUNNING,
|
||||||
|
userId: 'testid',
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
ePerson = Object.assign(new EPerson(), {
|
ePerson = Object.assign(new EPerson(), {
|
||||||
|
id: 'testid',
|
||||||
|
uuid: 'testid',
|
||||||
metadata: {
|
metadata: {
|
||||||
'eperson.firstname': [
|
'eperson.firstname': [
|
||||||
{
|
{
|
||||||
@@ -133,6 +143,8 @@ describe('ProcessOverviewTableComponent', () => {
|
|||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
init();
|
init();
|
||||||
|
|
||||||
|
translateServiceSpy = jasmine.createSpyObj('TranslateService', ['get']);
|
||||||
|
|
||||||
void TestBed.configureTestingModule({
|
void TestBed.configureTestingModule({
|
||||||
declarations: [NgbCollapse],
|
declarations: [NgbCollapse],
|
||||||
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), VarDirective, ProcessOverviewTableComponent],
|
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();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -18,7 +18,10 @@ import {
|
|||||||
RouterLink,
|
RouterLink,
|
||||||
} from '@angular/router';
|
} from '@angular/router';
|
||||||
import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import {
|
||||||
|
TranslateModule,
|
||||||
|
TranslateService,
|
||||||
|
} from '@ngx-translate/core';
|
||||||
import {
|
import {
|
||||||
BehaviorSubject,
|
BehaviorSubject,
|
||||||
from as observableFrom,
|
from as observableFrom,
|
||||||
@@ -46,9 +49,12 @@ import { RouteService } from '../../../core/services/route.service';
|
|||||||
import { redirectOn4xx } from '../../../core/shared/authorized.operators';
|
import { redirectOn4xx } from '../../../core/shared/authorized.operators';
|
||||||
import {
|
import {
|
||||||
getAllCompletedRemoteData,
|
getAllCompletedRemoteData,
|
||||||
getFirstSucceededRemoteDataPayload,
|
getFirstCompletedRemoteData,
|
||||||
} from '../../../core/shared/operators';
|
} 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 { ThemedLoadingComponent } from '../../../shared/loading/themed-loading.component';
|
||||||
import { PaginationComponent } from '../../../shared/pagination/pagination.component';
|
import { PaginationComponent } from '../../../shared/pagination/pagination.component';
|
||||||
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
||||||
@@ -153,12 +159,13 @@ export class ProcessOverviewTableComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
constructor(protected processOverviewService: ProcessOverviewService,
|
constructor(protected processOverviewService: ProcessOverviewService,
|
||||||
protected processBulkDeleteService: ProcessBulkDeleteService,
|
protected processBulkDeleteService: ProcessBulkDeleteService,
|
||||||
protected ePersonDataService: EPersonDataService,
|
public ePersonDataService: EPersonDataService,
|
||||||
protected dsoNameService: DSONameService,
|
public dsoNameService: DSONameService,
|
||||||
protected paginationService: PaginationService,
|
protected paginationService: PaginationService,
|
||||||
protected routeService: RouteService,
|
protected routeService: RouteService,
|
||||||
protected router: Router,
|
protected router: Router,
|
||||||
protected auth: AuthService,
|
protected auth: AuthService,
|
||||||
|
private translateService: TranslateService,
|
||||||
@Inject(PLATFORM_ID) protected platformId: object,
|
@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.
|
// Creates an ID from the first 2 characters of the process status.
|
||||||
// Should two process status values ever start with the same substring,
|
// Should two process status values ever start with the same substring,
|
||||||
// increase the number of characters until the ids are distinct.
|
// 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(), {
|
const defaultPaginationOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: this.paginationId,
|
id: this.paginationId,
|
||||||
@@ -218,7 +225,7 @@ export class ProcessOverviewTableComponent implements OnInit, OnDestroy {
|
|||||||
// Map RemoteData<PaginatedList<Process>> to RemoteData<PaginatedList<ProcessOverviewTableEntry>>
|
// Map RemoteData<PaginatedList<Process>> to RemoteData<PaginatedList<ProcessOverviewTableEntry>>
|
||||||
switchMap((processesRD: RemoteData<PaginatedList<Process>>) => {
|
switchMap((processesRD: RemoteData<PaginatedList<Process>>) => {
|
||||||
// Create observable emitting all processes one by one
|
// 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
|
// Map every Process to ProcessOverviewTableEntry
|
||||||
mergeMap((process: Process) => {
|
mergeMap((process: Process) => {
|
||||||
return this.getEPersonName(process.userId).pipe(
|
return this.getEPersonName(process.userId).pipe(
|
||||||
@@ -243,7 +250,6 @@ export class ProcessOverviewTableComponent implements OnInit, OnDestroy {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
).subscribe((next: RemoteData<PaginatedList<ProcessOverviewTableEntry>>) => {
|
).subscribe((next: RemoteData<PaginatedList<ProcessOverviewTableEntry>>) => {
|
||||||
this.processesRD$.next(next);
|
this.processesRD$.next(next);
|
||||||
}));
|
}));
|
||||||
@@ -267,10 +273,20 @@ export class ProcessOverviewTableComponent implements OnInit, OnDestroy {
|
|||||||
* @param id ID of the EPerson
|
* @param id ID of the EPerson
|
||||||
*/
|
*/
|
||||||
getEPersonName(id: string): Observable<string> {
|
getEPersonName(id: string): Observable<string> {
|
||||||
return this.ePersonDataService.findById(id).pipe(
|
if (isNotEmpty(id)) {
|
||||||
getFirstSucceededRemoteDataPayload(),
|
return this.ePersonDataService.findById(id).pipe(
|
||||||
map((eperson: EPerson) => this.dsoNameService.getName(eperson)),
|
getFirstCompletedRemoteData(),
|
||||||
);
|
switchMap((rd: RemoteData<EPerson>) => {
|
||||||
|
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');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -3846,6 +3846,8 @@
|
|||||||
|
|
||||||
"process.overview.delete.header": "Delete processes",
|
"process.overview.delete.header": "Delete processes",
|
||||||
|
|
||||||
|
"process.overview.unknown.user": "Unknown",
|
||||||
|
|
||||||
"process.bulk.delete.error.head": "Error on deleteing process",
|
"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. ",
|
"process.bulk.delete.error.body": "The process with ID {{processId}} could not be deleted. The remaining processes will continue being deleted. ",
|
||||||
|
Reference in New Issue
Block a user