Skip to content

Commit 0ff731c

Browse files
atarix83Andrea Barbasso
authored andcommitted
Merged in task/dspace-cris-2023_02_x/DSC-1852 (pull request DSpace#2028)
[DSC-1852] Fix issue with process notification which were frozen without updating the status of the process Approved-by: Andrea Barbasso
2 parents f402dcd + 33e94d2 commit 0ff731c

4 files changed

Lines changed: 59 additions & 57 deletions

File tree

src/app/core/data/processes/process-data.service.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,7 @@ export class ProcessDataService extends IdentifiableDataService<Process> impleme
123123
* @param processId The ID of the process
124124
*/
125125
getProcess(processId: string): Observable<RemoteData<Process>> {
126-
const href$ = this.getProcessEndpoint(processId);
127-
return this.findByHref(href$,false);
126+
return this.findById(processId, false);
128127
}
129128

130129
/**

src/app/shared/notifications/process-notification/process-notification.component.html

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="notification alert {{notificationType}} alert-dismissible m-3 shadow" role="alert"
1+
<div class="notification alert {{(notificationType$ | async)}} alert-dismissible m-3 shadow" role="alert"
22
[@enterLeave]="animate">
33

44
<button *ngIf="notification.options.clickToClose"
@@ -25,8 +25,8 @@
2525
</strong>
2626
</div>
2727

28-
<span *ngIf="(finished | async)" class="notification-content pl-1">
29-
{{process.processStatus.toString() | titlecase}}
28+
<span *ngIf="(finished | async)" class="notification-content pl-1">
29+
{{(processStatus$ | async) | translate}}
3030
</span>
3131
<span *ngIf="!(finished | async)" class="notification-content pl-1">
3232
{{'process.new.notification.process.processing' | translate}}
@@ -37,17 +37,13 @@
3737
</div>
3838
</div>
3939

40-
<div *ngIf="(finished | async) && files && files?.length > 0">
40+
<div *ngIf="(finished | async) && (files$ | async)?.length > 0">
4141
<div class="notification-content pl-1">{{ 'process.new.notification.process.files' | translate}}</div>
42+
<ds-file-download-link class="pl-1" *ngFor="let file of (files$ | async); let last=last;" [bitstream]="file">
43+
<span>{{getFileName(file)}}</span>
44+
<span>({{(file?.sizeBytes) | dsFileSize }})</span>
45+
</ds-file-download-link>
4246
</div>
43-
44-
<div class="pl-2" *ngIf="(finished | async) && files && files?.length > 0">
45-
<ds-file-download-link *ngFor="let file of files; let last=last;" [bitstream]="file">
46-
<span>{{getFileName(file)}}</span>
47-
<span>({{(file?.sizeBytes) | dsFileSize }})</span>
48-
</ds-file-download-link>
49-
</div>
50-
5147
</div>
5248

5349

src/app/shared/notifications/process-notification/process-notification.component.ts

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
import { BehaviorSubject, Observable, of as observableOf, Subscription, timer } from 'rxjs';
21
import {
32
ChangeDetectionStrategy,
43
ChangeDetectorRef,
54
Component,
65
Input,
7-
NgZone,
86
OnDestroy,
97
OnInit,
108
TemplateRef,
119
ViewEncapsulation
1210
} from '@angular/core';
1311
import { trigger } from '@angular/animations';
1412
import { DomSanitizer } from '@angular/platform-browser';
13+
14+
import { BehaviorSubject, Observable, of as observableOf, Subscription, timer } from 'rxjs';
15+
import { filter, map, switchMap, take, tap } from 'rxjs/operators';
16+
1517
import { NotificationsService } from '../notifications.service';
1618
import { scaleEnter, scaleInState, scaleLeave, scaleOutState } from '../../animations/scale';
1719
import { rotateEnter, rotateInState, rotateLeave, rotateOutState } from '../../animations/rotate';
@@ -26,9 +28,10 @@ import { IProcessNotification } from '../models/process-notification.model';
2628
import { ProcessDataService } from '../../../core/data/processes/process-data.service';
2729
import { Process } from '../../../process-page/processes/process.model';
2830
import { Bitstream } from '../../../core/shared/bitstream.model';
29-
import { getFirstCompletedRemoteData, getFirstSucceededRemoteListPayload } from '../../../core/shared/operators';
31+
import { getAllCompletedRemoteData, getFirstCompletedRemoteData } from '../../../core/shared/operators';
3032
import { DSONameService } from '../../../core/breadcrumbs/dso-name.service';
3133
import { DSpaceObject } from '../../../core/shared/dspace-object.model';
34+
import { RemoteData } from '../../../core/data/remote-data';
3235

3336
@Component({
3437
selector: 'ds-process-notification',
@@ -84,7 +87,7 @@ export class ProcessNotificationComponent implements OnInit, OnDestroy {
8487
/**
8588
* The process that is being checked.
8689
*/
87-
public process: Process;
90+
public processStatus$: BehaviorSubject<string> = new BehaviorSubject('');
8891

8992
/**
9093
* If process checking is finished.
@@ -94,76 +97,76 @@ export class ProcessNotificationComponent implements OnInit, OnDestroy {
9497
/**
9598
* Files generated from process end.
9699
*/
97-
public files: Bitstream[];
100+
public files$: BehaviorSubject<Bitstream[]> = new BehaviorSubject<Bitstream[]>([]);
98101

99102
/**
100103
* Type of the notification visualisation.
101104
*/
102-
public notificationType = 'alert-info';
105+
public notificationType$: BehaviorSubject<string> = new BehaviorSubject('alert-info');
103106

104107
constructor(private notificationService: NotificationsService,
105108
private domSanitizer: DomSanitizer,
106109
protected processService: ProcessDataService,
107110
protected nameService: DSONameService,
108111
private cdr: ChangeDetectorRef,
109-
private zone: NgZone) {
112+
) {
110113
}
111114

112115
/**
113116
* On init, start check process, and insert notifications information.
114117
*/
115118
ngOnInit(): void {
116119
this.animate = this.notification.options.animate + NotificationAnimationsStatus.In;
117-
this.initCheckProcess();
120+
this.pollUntilProcessFinished();
118121
this.html = this.notification.html;
119122
this.contentType(this.notification.title, 'title');
120123
}
121124

122125
/**
123-
* Initialization of timer.
124-
*/
125-
initCheckProcess() {
126-
const source = timer(0, this.notification.checkTime);
127-
this.sub = source.subscribe(val => {
128-
this.checkProcess();
126+
* Poll process endpoint until it's finished.
127+
*/
128+
pollUntilProcessFinished() {
129+
timer(0, this.notification.checkTime).pipe(
130+
switchMap(() => this.processService.getProcess(this.notification.processId)),
131+
getAllCompletedRemoteData(),
132+
filter((res: RemoteData<Process>) => res.hasFailed || res?.payload?.processStatus.toString() === 'COMPLETED' || res?.payload?.processStatus.toString() === 'FAILED'),
133+
take(1),
134+
tap((res: RemoteData<Process>) => this.pollingFinishedFor(res)),
135+
switchMap((res: RemoteData<Process>) => this.getFiles(res)),
136+
).subscribe((files: Bitstream[]) => {
137+
const logFiles = files.filter( (file) => !this.getFileName(file).includes('.log'));
138+
this.files$.next(logFiles);
139+
this.finished.next(true);
129140
});
130141
}
131142

132143
/**
133-
* Send request to get the updated process information.
134-
*/
135-
checkProcess() {
136-
this.processService.getProcess(this.notification.processId)
137-
.pipe(getFirstCompletedRemoteData())
138-
.subscribe( (res) => {
139-
this.process = res.payload;
140-
this.zone.run(() => this.cdr.detectChanges());
141-
if (this.process.processStatus.toString() === 'COMPLETED' || this.process.processStatus.toString() === 'FAILED') {
142-
this.sub.unsubscribe();
143-
if (this.process.processStatus.toString() === 'COMPLETED') {
144-
this.notificationType = 'alert-success';
145-
this.getFiles();
146-
} else {
147-
this.notificationType = 'alert-danger';
148-
this.zone.run(() => this.cdr.detectChanges());
149-
}
150-
this.finished.next(true);
151-
}
152-
});
144+
* Handle process results
145+
*
146+
* @param processRD The RemoteData object for finished process
147+
*/
148+
pollingFinishedFor(processRD: RemoteData<Process>) {
149+
if (processRD.hasSucceeded && processRD.payload.processStatus.toString() === 'COMPLETED') {
150+
this.notificationType$.next('alert-success');
151+
this.processStatus$.next('process.new.notification.process.status.completed');
152+
} else {
153+
this.processStatus$.next('process.new.notification.process.status.failed');
154+
this.notificationType$.next('alert-danger');
155+
}
153156
}
154157

155158
/**
156159
* When the process is completed get the files output.
157160
*/
158-
getFiles() {
159-
this.processService.getFiles(this.notification.processId)
160-
.pipe(
161-
getFirstSucceededRemoteListPayload(),
162-
)
163-
.subscribe( (files: Bitstream[]) => {
164-
this.files = files.filter( (file) => !this.getFileName(file).includes('.log'));
165-
this.zone.run(() => this.cdr.detectChanges());
166-
});
161+
getFiles(processRD: RemoteData<Process>): Observable<Bitstream[]> {
162+
if (processRD.hasSucceeded && processRD.payload.processStatus.toString() === 'COMPLETED') {
163+
return this.processService.getFiles(processRD.payload.processId).pipe(
164+
getFirstCompletedRemoteData(),
165+
map((response) => response.hasSucceeded ? response.payload.page : [])
166+
);
167+
} else {
168+
return observableOf([]);
169+
}
167170
}
168171

169172
/**

src/assets/i18n/en.json5

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4459,6 +4459,10 @@
44594459

44604460
"process.new.notification.process.files": "Output Files: ",
44614461

4462+
"process.new.notification.process.status.completed": "Completed",
4463+
4464+
"process.new.notification.process.status.failed": "Failed",
4465+
44624466
"process.new.header": "Create a new process",
44634467

44644468
"process.new.title": "Create a new process",

0 commit comments

Comments
 (0)