Skip to content

Commit 9e5f2c0

Browse files
[UXP-147] add section errors visualization, minor refactor, add labels
1 parent bc5c681 commit 9e5f2c0

35 files changed

Lines changed: 77831 additions & 27315 deletions

src/app/submission/objects/submission-objects.actions.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
WorkspaceitemSectionDataType,
1010
WorkspaceitemSectionsObject
1111
} from '../../core/submission/models/workspaceitem-sections.model';
12-
import { SubmissionObject } from '../../core/submission/models/submission-object.model';
12+
import { SubmissionObject, SubmissionObjectError } from '../../core/submission/models/submission-object.model';
1313
import { SubmissionDefinitionsModel } from '../../core/config/models/config-submission-definitions.model';
1414
import { SectionsType } from '../sections/sections-type';
1515
import { Item } from '../../core/shared/item.model';
@@ -1088,18 +1088,19 @@ export class ExecuteExternalUploadErrorAction implements Action {
10881088
type = SubmissionObjectActionTypes.EXECUTE_EXTERNAL_UPLOAD_ERROR;
10891089
payload: {
10901090
submissionId: string;
1091+
errors: SubmissionObjectError[]
10911092
};
10921093

10931094
/**
10941095
* Create a new ExecuteExternalUploadActionError
10951096
*
10961097
* @param submissionId
10971098
* the submission's ID
1098-
* @param sectionId
1099+
* @param errors
10991100
* the section's ID
11001101
*/
1101-
constructor(submissionId: string) {
1102-
this.payload = { submissionId };
1102+
constructor(submissionId: string, errors: SubmissionObjectError[]) {
1103+
this.payload = { submissionId, errors };
11031104
}
11041105
}
11051106

src/app/submission/objects/submission-objects.effects.ts

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ import { NotificationOptions } from '../../shared/notifications/models/notificat
6868
import {
6969
WorkspaceitemSectionDetectDuplicateObject
7070
} from '../../core/submission/models/workspaceitem-section-deduplication.model';
71+
import { Simulate } from 'react-dom/test-utils';
72+
import error = Simulate.error;
7173

7274
@Injectable()
7375
export class SubmissionObjectEffects {
@@ -308,7 +310,7 @@ export class SubmissionObjectEffects {
308310
switchMap(([action, state]: [DepositSubmissionAction, any]) => {
309311
return this.submissionService.depositSubmission(state.submission.objects[action.payload.submissionId].selfUrl).pipe(
310312
map(() => new DepositSubmissionSuccessAction(action.payload.submissionId)),
311-
catchError((error) => observableOf(new DepositSubmissionErrorAction(action.payload.submissionId))));
313+
catchError(() => observableOf(new DepositSubmissionErrorAction(action.payload.submissionId))));
312314
})));
313315

314316
/**
@@ -397,12 +399,25 @@ export class SubmissionObjectEffects {
397399
action.payload.submissionId,
398400
'sections',
399401
action.payload.sectionId).pipe(
400-
map((response: SubmissionObject[]) => new ExecuteExternalUploadSuccessAction(
401-
action.payload.submissionId,
402-
action.payload.sectionId,
403-
response
404-
)),
405-
catchError(() => observableOf(new ExecuteExternalUploadErrorAction(action.payload.submissionId))));
402+
map((response: SubmissionObject[]) => {
403+
const errors = [].concat.apply([], response.map(sub => sub.errors));
404+
const sectionErrors = errors.filter((errorObject: SubmissionObjectError) => errorObject.paths.length > 0)
405+
.filter(err => err.paths.includes('/sections/' + action.payload.sectionId));
406+
407+
if (sectionErrors.length > 0) {
408+
return new ExecuteExternalUploadErrorAction(action.payload.submissionId, sectionErrors);
409+
} else {
410+
return new ExecuteExternalUploadSuccessAction(
411+
action.payload.submissionId,
412+
action.payload.sectionId,
413+
response
414+
);
415+
}
416+
}),
417+
catchError((rd: RemoteData<any>) => observableFrom(
418+
this.parseErrorResponse(false, rd.errors, action.payload.submissionId, rd.statusCode, rd.errorMessage)
419+
))
420+
);
406421
}))
407422
);
408423

@@ -415,6 +430,15 @@ export class SubmissionObjectEffects {
415430
{ dispatch: false }
416431
);
417432

433+
/**
434+
* Show external update errors
435+
*/
436+
executeExternalUploadError$ = createEffect(() => this.actions$.pipe(
437+
ofType(SubmissionObjectActionTypes.EXECUTE_EXTERNAL_UPLOAD_ERROR),
438+
tap(() => this.notificationsService.error(null, this.translate.get('submission.sections.external-upload.upload-error-notice')))),
439+
{ dispatch: false }
440+
);
441+
418442
/**
419443
* Show a notification on success and redirect to MyDSpace page
420444
*/
@@ -635,11 +659,11 @@ function filterErrors(sectionForm: FormState, sectionErrors: SubmissionSectionEr
635659
return [];
636660
}
637661
const filteredErrors = [];
638-
sectionErrors.forEach((error: SubmissionSectionError) => {
662+
sectionErrors.forEach((err: SubmissionSectionError) => {
639663
const errorPaths: SectionErrorPath[] = parseSectionErrorPaths(error.path);
640664
errorPaths.forEach((path: SectionErrorPath) => {
641665
if (path.fieldId && sectionForm.touched[path.fieldId]) {
642-
filteredErrors.push(error);
666+
filteredErrors.push(err);
643667
}
644668
});
645669
});

src/app/submission/objects/submission-objects.reducer.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ describe('submissionReducer test suite', () => {
8888
savePending: false,
8989
saveDecisionPending: false,
9090
externalUploadPending: false,
91+
externalUploadErrors: [],
9192
depositPending: false,
9293
metadataSecurityConfiguration: metadataSecurityConfiguration as any,
9394
}

src/app/submission/objects/submission-objects.reducer.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ import {
5555
} from '../../core/submission/models/workspaceitem-section-deduplication.model';
5656
import { SubmissionSectionObject } from './submission-section-object.model';
5757
import { MetadataSecurityConfiguration } from '../../core/submission/models/metadata-security-configuration';
58+
import { SubmissionObjectError } from '../../core/submission/models/submission-object.model';
5859

5960
/**
6061
* An interface to represent SubmissionSectionObject entry
@@ -112,6 +113,10 @@ export interface SubmissionObjectEntry {
112113
*/
113114
externalUploadPending?: boolean;
114115

116+
/**
117+
* Errors from external upload
118+
*/
119+
externalUploadErrors?: SubmissionObjectError[];
115120
/**
116121
* A boolean representing if a submission deposit operation is pending
117122
*/
@@ -411,6 +416,7 @@ function initSubmission(state: SubmissionObjectState, action: InitSubmissionForm
411416
savePending: false,
412417
saveDecisionPending: false,
413418
externalUploadPending: false,
419+
externalUploadErrors: [],
414420
depositPending: false,
415421
metadataSecurityConfiguration: action.payload.metadataSecurityConfiguration,
416422
isDiscarding: false
@@ -1110,6 +1116,7 @@ function startExternalUploadExecution(state: SubmissionObjectState, action: Exec
11101116
return Object.assign({}, state, {
11111117
[ action.payload.submissionId ]: Object.assign({}, state[ action.payload.submissionId ], {
11121118
externalUploadPending: true,
1119+
externalUploadErrors: [],
11131120
})
11141121
});
11151122
} else {
@@ -1132,6 +1139,7 @@ function endExternalUploadExecution(state: SubmissionObjectState, action: Execut
11321139
return Object.assign({}, state, {
11331140
[ action.payload.submissionId ]: Object.assign({}, state[ action.payload.submissionId ], {
11341141
externalUploadPending: false,
1142+
externalUploadErrors: action.payload.errors
11351143
})
11361144
});
11371145
} else {

src/app/submission/sections/external-upload/section-external-upload.component.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
<label for="externalUploadSource">{{'submission.sections.external-upload.source' | translate}}</label>
1212
<input [(ngModel)]="source" class="form-control w-100" id="externalUploadSource" [placeholder]="'submission.sections.external-upload.placeholder' | translate" />
1313
</div>
14+
<div class="d-flex flex-column" *ngIf="(errors$ | async).length > 0">
15+
<div class="text-danger mt-1" *ngFor="let error of (errors$ | async)">
16+
{{error.message | translate}}
17+
</div>
18+
</div>
1419
<div class="w-100 d-flex justify-content-center">
1520
<button [disabled]="!source" (click)="submitUpload()" class="btn btn-success mt-4">{{'submission.sections.external-upload.import' | translate}}</button>
1621
</div>

src/app/submission/sections/external-upload/section-external-upload.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ export class SectionExternalUploadComponent extends SectionModelComponent implem
2727

2828
public loading$ = this.submissionService.getExternalUplodaProcessingStatus(this.injectedSubmissionId);
2929

30+
public errors$ = this.submissionService.getExternalUplodaErorrs(this.injectedSubmissionId);
31+
3032
public AlertType = AlertType;
3133

3234
/**
@@ -90,7 +92,6 @@ export class SectionExternalUploadComponent extends SectionModelComponent implem
9092
.subscribe(() => {
9193
this.operationsBuilder.add(this.pathCombiner.getPath(this.patchOperationPath), this.source, false, true);
9294
this.externalUploadService.executeExternalUpload(this.submissionId, this.injectedSectionData.id);
93-
this.source = '';
9495
});
9596
}
9697
}

src/app/submission/submission.service.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import { HttpOptions } from '../core/dspace-rest/dspace-rest.service';
3030
import { SubmissionRestService } from '../core/submission/submission-rest.service';
3131
import { SectionDataObject } from './sections/models/section-data.model';
3232
import { SubmissionScopeType } from '../core/submission/submission-scope-type';
33-
import { SubmissionObject } from '../core/submission/models/submission-object.model';
33+
import { SubmissionObject, SubmissionObjectError } from '../core/submission/models/submission-object.model';
3434
import { RouteService } from '../core/services/route.service';
3535
import { SectionsType } from './sections/sections-type';
3636
import { NotificationsService } from '../shared/notifications/notifications.service';
@@ -554,6 +554,21 @@ export class SubmissionService {
554554
startWith(false));
555555
}
556556

557+
/**
558+
* Return the external upload status of the submission
559+
*
560+
* @param submissionId
561+
* The submission id
562+
* @return Observable<boolean>
563+
* observable with submission save-decision status
564+
*/
565+
getExternalUplodaErorrs(submissionId: string): Observable<SubmissionObjectError[]> {
566+
return this.getSubmissionObject(submissionId).pipe(
567+
map((state: SubmissionObjectEntry) => state.externalUploadErrors),
568+
distinctUntilChanged(),
569+
startWith([]));
570+
}
571+
557572
/**
558573
* Return whether submission unsaved modification are present
559574
*

0 commit comments

Comments
 (0)