Skip to content

Commit dd5a167

Browse files
authored
Merge pull request DSpace#3013 from atmire/process-ui-null-eperson-fix-7.6
[Port dspace-7_x] Handle Null Users Gracefully in Process Overview Page
2 parents 3ae9c8e + b7b1c3e commit dd5a167

3 files changed

Lines changed: 74 additions & 11 deletions

File tree

src/app/process-page/overview/process-overview.component.spec.ts

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ProcessOverviewComponent } from './process-overview.component';
22
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
33
import { VarDirective } from '../../shared/utils/var.directive';
4-
import { TranslateModule } from '@ngx-translate/core';
4+
import { TranslateModule, TranslateService } from '@ngx-translate/core';
55
import { RouterTestingModule } from '@angular/router/testing';
66
import { NO_ERRORS_SCHEMA } from '@angular/core';
77
import { ProcessDataService } from '../../core/data/processes/process-data.service';
@@ -33,6 +33,8 @@ describe('ProcessOverviewComponent', () => {
3333
let processBulkDeleteService;
3434
let modalService;
3535

36+
let translateServiceSpy: jasmine.SpyObj<TranslateService>;
37+
3638
const pipe = new DatePipe('en-US');
3739

3840
function init() {
@@ -42,24 +44,29 @@ describe('ProcessOverviewComponent', () => {
4244
scriptName: 'script-name',
4345
startTime: '2020-03-19 00:30:00',
4446
endTime: '2020-03-19 23:30:00',
45-
processStatus: ProcessStatus.COMPLETED
47+
processStatus: ProcessStatus.COMPLETED,
48+
userId: 'testid'
4649
}),
4750
Object.assign(new Process(), {
4851
processId: 2,
4952
scriptName: 'script-name',
5053
startTime: '2020-03-20 00:30:00',
5154
endTime: '2020-03-20 23:30:00',
52-
processStatus: ProcessStatus.FAILED
55+
processStatus: ProcessStatus.FAILED,
56+
userId: 'testid'
5357
}),
5458
Object.assign(new Process(), {
5559
processId: 3,
5660
scriptName: 'another-script-name',
5761
startTime: '2020-03-21 00:30:00',
5862
endTime: '2020-03-21 23:30:00',
59-
processStatus: ProcessStatus.RUNNING
63+
processStatus: ProcessStatus.RUNNING,
64+
userId: 'testid'
6065
})
6166
];
6267
ePerson = Object.assign(new EPerson(), {
68+
id: 'testid',
69+
uuid: 'testid',
6370
metadata: {
6471
'eperson.firstname': [
6572
{
@@ -110,6 +117,9 @@ describe('ProcessOverviewComponent', () => {
110117

111118
beforeEach(waitForAsync(() => {
112119
init();
120+
121+
translateServiceSpy = jasmine.createSpyObj('TranslateService', ['get']);
122+
113123
TestBed.configureTestingModule({
114124
declarations: [ProcessOverviewComponent, VarDirective],
115125
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])],
@@ -249,4 +259,43 @@ describe('ProcessOverviewComponent', () => {
249259
expect(component.setProcesses).toHaveBeenCalled();
250260
});
251261
});
262+
263+
describe('getEPersonName function', () => {
264+
it('should return unknown user when id is null', (done: DoneFn) => {
265+
const id = null;
266+
const expectedTranslation = 'process.overview.unknown.user';
267+
268+
translateServiceSpy.get(expectedTranslation);
269+
270+
component.getEpersonName(id).subscribe((result: string) => {
271+
expect(result).toBe(expectedTranslation);
272+
done();
273+
});
274+
expect(translateServiceSpy.get).toHaveBeenCalledWith('process.overview.unknown.user');
275+
});
276+
277+
it('should return unknown user when id is invalid', (done: DoneFn) => {
278+
const id = '';
279+
const expectedTranslation = 'process.overview.unknown.user';
280+
281+
translateServiceSpy.get(expectedTranslation);
282+
283+
component.getEpersonName(id).subscribe((result: string) => {
284+
expect(result).toBe(expectedTranslation);
285+
done();
286+
});
287+
expect(translateServiceSpy.get).toHaveBeenCalledWith('process.overview.unknown.user');
288+
});
289+
290+
it('should return EPerson name when id is correct', (done: DoneFn) => {
291+
const id = 'testid';
292+
const expectedName = 'John Doe';
293+
294+
component.getEpersonName(id).subscribe((result: string) => {
295+
expect(result).toEqual(expectedName);
296+
done();
297+
});
298+
expect(translateServiceSpy.get).not.toHaveBeenCalled();
299+
});
300+
});
252301
});

src/app/process-page/overview/process-overview.component.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@ import { PaginatedList } from '../../core/data/paginated-list.model';
55
import { Process } from '../processes/process.model';
66
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
77
import { EPersonDataService } from '../../core/eperson/eperson-data.service';
8-
import { getFirstSucceededRemoteDataPayload } from '../../core/shared/operators';
8+
import { getFirstCompletedRemoteData } from '../../core/shared/operators';
99
import { EPerson } from '../../core/eperson/models/eperson.model';
10-
import { map, switchMap } from 'rxjs/operators';
10+
import { switchMap } from 'rxjs/operators';
1111
import { ProcessDataService } from '../../core/data/processes/process-data.service';
1212
import { PaginationService } from '../../core/pagination/pagination.service';
1313
import { FindListOptions } from '../../core/data/find-list-options.model';
1414
import { ProcessBulkDeleteService } from './process-bulk-delete.service';
1515
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
16-
import { hasValue } from '../../shared/empty.util';
16+
import { hasValue, isNotEmpty } from '../../shared/empty.util';
1717
import { DSONameService } from '../../core/breadcrumbs/dso-name.service';
18+
import { TranslateService } from '@ngx-translate/core';
1819

1920
@Component({
2021
selector: 'ds-process-overview',
@@ -61,6 +62,7 @@ export class ProcessOverviewComponent implements OnInit, OnDestroy {
6162
protected modalService: NgbModal,
6263
public processBulkDeleteService: ProcessBulkDeleteService,
6364
protected dsoNameService: DSONameService,
65+
private translateService: TranslateService,
6466
) {
6567
}
6668

@@ -83,10 +85,20 @@ export class ProcessOverviewComponent implements OnInit, OnDestroy {
8385
* @param id ID of the EPerson
8486
*/
8587
getEpersonName(id: string): Observable<string> {
86-
return this.ePersonService.findById(id).pipe(
87-
getFirstSucceededRemoteDataPayload(),
88-
map((eperson: EPerson) => this.dsoNameService.getName(eperson)),
89-
);
88+
if (isNotEmpty(id)) {
89+
return this.ePersonService.findById(id).pipe(
90+
getFirstCompletedRemoteData(),
91+
switchMap((rd: RemoteData<EPerson>) => {
92+
if (rd.hasSucceeded) {
93+
return [this.dsoNameService.getName(rd.payload)];
94+
} else {
95+
return this.translateService.get('process.overview.unknown.user');
96+
}
97+
})
98+
);
99+
} else {
100+
return this.translateService.get('process.overview.unknown.user');
101+
}
90102
}
91103

92104
ngOnDestroy(): void {

src/assets/i18n/en.json5

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5360,4 +5360,6 @@
53605360

53615361
"vocabulary-treeview.search.form.add": "Add",
53625362

5363+
"process.overview.unknown.user": "Unknown",
5364+
53635365
}

0 commit comments

Comments
 (0)