mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Merge pull request #1254 from 4Science/#1206
Improve error handling during submission
This commit is contained in:
@@ -8,7 +8,7 @@
|
|||||||
[size]="4"
|
[size]="4"
|
||||||
[(ngModel)]="initialYear"
|
[(ngModel)]="initialYear"
|
||||||
[value]="year"
|
[value]="year"
|
||||||
[class.is-invalid]="showErrorMessages"
|
[invalid]="showErrorMessages"
|
||||||
[placeholder]='yearPlaceholder'
|
[placeholder]='yearPlaceholder'
|
||||||
(blur)="onBlur($event)"
|
(blur)="onBlur($event)"
|
||||||
(change)="onChange($event)"
|
(change)="onChange($event)"
|
||||||
|
@@ -254,6 +254,13 @@ export class FormComponent implements OnDestroy, OnInit {
|
|||||||
|
|
||||||
onBlur(event: DynamicFormControlEvent): void {
|
onBlur(event: DynamicFormControlEvent): void {
|
||||||
this.blur.emit(event);
|
this.blur.emit(event);
|
||||||
|
const control: FormControl = event.control;
|
||||||
|
const fieldIndex: number = (event.context && event.context.index) ? event.context.index : 0;
|
||||||
|
if (control.valid) {
|
||||||
|
this.formService.removeError(this.formId, event.model.name, fieldIndex);
|
||||||
|
} else {
|
||||||
|
this.formService.addControlErrors(control, this.formId, event.model.name, fieldIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onCustomEvent(event: any) {
|
onCustomEvent(event: any) {
|
||||||
|
@@ -2,10 +2,13 @@ import {
|
|||||||
FormAction,
|
FormAction,
|
||||||
FormActionTypes,
|
FormActionTypes,
|
||||||
FormAddError,
|
FormAddError,
|
||||||
FormChangeAction, FormClearErrorsAction,
|
FormAddTouchedAction,
|
||||||
|
FormChangeAction,
|
||||||
|
FormClearErrorsAction,
|
||||||
FormInitAction,
|
FormInitAction,
|
||||||
FormRemoveAction, FormRemoveErrorAction,
|
FormRemoveAction,
|
||||||
FormStatusChangeAction, FormAddTouchedAction
|
FormRemoveErrorAction,
|
||||||
|
FormStatusChangeAction
|
||||||
} from './form.actions';
|
} from './form.actions';
|
||||||
import { hasValue } from '../empty.util';
|
import { hasValue } from '../empty.util';
|
||||||
import { isEqual, uniqWith } from 'lodash';
|
import { isEqual, uniqWith } from 'lodash';
|
||||||
@@ -82,12 +85,16 @@ function addFormErrors(state: FormState, action: FormAddError) {
|
|||||||
fieldIndex: action.payload.fieldIndex,
|
fieldIndex: action.payload.fieldIndex,
|
||||||
message: action.payload.errorMessage
|
message: action.payload.errorMessage
|
||||||
};
|
};
|
||||||
|
const metadata = action.payload.fieldId.replace(/\_/g, '.');
|
||||||
|
const touched = Object.assign({}, state[formId].touched, {
|
||||||
|
[metadata]: true
|
||||||
|
});
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
[formId]: {
|
[formId]: {
|
||||||
data: state[formId].data,
|
data: state[formId].data,
|
||||||
valid: state[formId].valid,
|
valid: state[formId].valid,
|
||||||
errors: state[formId].errors ? uniqWith(state[formId].errors.concat(error), isEqual) : [].concat(error),
|
errors: state[formId].errors ? uniqWith(state[formId].errors.concat(error), isEqual) : [].concat(error),
|
||||||
|
touched
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { map, distinctUntilChanged, filter } from 'rxjs/operators';
|
import { distinctUntilChanged, filter, map } from 'rxjs/operators';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms';
|
import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
@@ -11,12 +11,15 @@ import { DynamicFormControlEvent, DynamicFormControlModel } from '@ng-dynamic-fo
|
|||||||
import { isEmpty, isNotUndefined } from '../empty.util';
|
import { isEmpty, isNotUndefined } from '../empty.util';
|
||||||
import { uniqueId } from 'lodash';
|
import { uniqueId } from 'lodash';
|
||||||
import {
|
import {
|
||||||
|
FormAddError,
|
||||||
|
FormAddTouchedAction,
|
||||||
FormChangeAction,
|
FormChangeAction,
|
||||||
FormInitAction,
|
FormInitAction,
|
||||||
FormRemoveAction, FormRemoveErrorAction, FormAddTouchedAction,
|
FormRemoveAction,
|
||||||
|
FormRemoveErrorAction,
|
||||||
FormStatusChangeAction
|
FormStatusChangeAction
|
||||||
} from './form.actions';
|
} from './form.actions';
|
||||||
import { FormEntry, FormTouchedState } from './form.reducer';
|
import { FormEntry, FormError, FormTouchedState } from './form.reducer';
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../environments/environment';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@@ -66,7 +69,7 @@ export class FormService {
|
|||||||
/**
|
/**
|
||||||
* Method to retrieve form's errors from state
|
* Method to retrieve form's errors from state
|
||||||
*/
|
*/
|
||||||
public getFormErrors(formId: string): Observable<any> {
|
public getFormErrors(formId: string): Observable<FormError[]> {
|
||||||
return this.store.pipe(
|
return this.store.pipe(
|
||||||
select(formObjectFromIdSelector(formId)),
|
select(formObjectFromIdSelector(formId)),
|
||||||
filter((state) => isNotUndefined(state)),
|
filter((state) => isNotUndefined(state)),
|
||||||
@@ -105,6 +108,34 @@ export class FormService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if form group has an invalid form control
|
||||||
|
* @param formGroup The form group to check
|
||||||
|
*/
|
||||||
|
public hasValidationErrors(formGroup: FormGroup | FormArray): boolean {
|
||||||
|
let hasErrors = false;
|
||||||
|
const fields: string[] = Object.keys(formGroup.controls);
|
||||||
|
for (const field of fields) {
|
||||||
|
const control = formGroup.get(field);
|
||||||
|
if (control instanceof FormControl) {
|
||||||
|
hasErrors = !control.valid && control.touched;
|
||||||
|
} else if (control instanceof FormGroup || control instanceof FormArray) {
|
||||||
|
hasErrors = this.hasValidationErrors(control);
|
||||||
|
}
|
||||||
|
if (hasErrors) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasErrors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public addControlErrors(field: AbstractControl, formId: string, fieldId: string, fieldIndex: number) {
|
||||||
|
const errors: string[] = Object.keys(field.errors)
|
||||||
|
.filter((errorKey) => field.errors[errorKey] === true)
|
||||||
|
.map((errorKey) => `error.validation.${errorKey}`);
|
||||||
|
errors.forEach((error) => this.addError(formId, fieldId, fieldIndex, error));
|
||||||
|
}
|
||||||
|
|
||||||
public addErrorToField(field: AbstractControl, model: DynamicFormControlModel, message: string) {
|
public addErrorToField(field: AbstractControl, model: DynamicFormControlModel, message: string) {
|
||||||
const error = {}; // create the error object
|
const error = {}; // create the error object
|
||||||
const errorKey = this.getValidatorNameFromMap(message);
|
const errorKey = this.getValidatorNameFromMap(message);
|
||||||
@@ -186,7 +217,12 @@ export class FormService {
|
|||||||
this.store.dispatch(new FormAddTouchedAction(formId, ids));
|
this.store.dispatch(new FormAddTouchedAction(formId, ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeError(formId: string, eventModelId: string, fieldIndex: number) {
|
public addError(formId: string, fieldId: string, fieldIndex: number, message: string) {
|
||||||
this.store.dispatch(new FormRemoveErrorAction(formId, eventModelId, fieldIndex));
|
const normalizedFieldId = fieldId.replace(/\./g, '_');
|
||||||
|
this.store.dispatch(new FormAddError(formId, normalizedFieldId, fieldIndex, message));
|
||||||
|
}
|
||||||
|
public removeError(formId: string, fieldId: string, fieldIndex: number) {
|
||||||
|
const normalizedFieldId = fieldId.replace(/\./g, '_');
|
||||||
|
this.store.dispatch(new FormRemoveErrorAction(formId, normalizedFieldId, fieldIndex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,9 @@ export function getMockFormService(
|
|||||||
resetForm: {},
|
resetForm: {},
|
||||||
validateAllFormFields: jasmine.createSpy('validateAllFormFields'),
|
validateAllFormFields: jasmine.createSpy('validateAllFormFields'),
|
||||||
isValid: jasmine.createSpy('isValid'),
|
isValid: jasmine.createSpy('isValid'),
|
||||||
isFormInitialized: observableOf(true)
|
isFormInitialized: observableOf(true),
|
||||||
|
addError: jasmine.createSpy('addError'),
|
||||||
|
removeError: jasmine.createSpy('removeError'),
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -60,7 +60,7 @@ export const mockSectionsErrors = [
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
export const mockSectionsErrorsTwo = [
|
export const mockSectionsErrorsTouchedField = [
|
||||||
{
|
{
|
||||||
message: 'error.validation.required',
|
message: 'error.validation.required',
|
||||||
paths: [
|
paths: [
|
||||||
@@ -1020,7 +1020,127 @@ export const mockSubmissionState: SubmissionObjectState = Object.assign({}, {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
isLoading: false,
|
||||||
|
isValid: false,
|
||||||
|
removePending: false
|
||||||
|
} as any,
|
||||||
|
'collection': {
|
||||||
|
config: '',
|
||||||
|
mandatory: true,
|
||||||
|
sectionType: 'collection',
|
||||||
|
visibility: {
|
||||||
|
main: 'HIDDEN',
|
||||||
|
other: 'HIDDEN'
|
||||||
|
},
|
||||||
|
collapsed: false,
|
||||||
|
enabled: true,
|
||||||
|
data: {},
|
||||||
|
errorsToShow: [],
|
||||||
|
isLoading: false,
|
||||||
|
isValid: false,
|
||||||
|
removePending: false
|
||||||
|
} as any,
|
||||||
|
'traditionalpageone': {
|
||||||
|
header: 'submit.progressbar.describe.stepone',
|
||||||
|
config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone',
|
||||||
|
mandatory: true,
|
||||||
|
sectionType: 'submission-form',
|
||||||
|
collapsed: false,
|
||||||
|
enabled: true,
|
||||||
|
data: {},
|
||||||
|
errorsToShow: [],
|
||||||
|
formId: '2_traditionalpageone',
|
||||||
|
isLoading: false,
|
||||||
|
isValid: false,
|
||||||
|
removePending: false
|
||||||
|
} as any,
|
||||||
|
'traditionalpagetwo': {
|
||||||
|
header: 'submit.progressbar.describe.steptwo',
|
||||||
|
config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpagetwo',
|
||||||
|
mandatory: false,
|
||||||
|
sectionType: 'submission-form',
|
||||||
|
collapsed: false,
|
||||||
|
enabled: false,
|
||||||
|
data: {},
|
||||||
|
errorsToShow: [],
|
||||||
|
isLoading: false,
|
||||||
|
isValid: false,
|
||||||
|
removePending: false
|
||||||
|
} as any,
|
||||||
|
'detect-duplicate': {
|
||||||
|
header: 'submit.progressbar.detect-duplicate',
|
||||||
|
config: '',
|
||||||
|
mandatory: true,
|
||||||
|
sectionType: 'detect-duplicate',
|
||||||
|
collapsed: false,
|
||||||
|
enabled: true,
|
||||||
|
data: {
|
||||||
|
matches: {}
|
||||||
|
},
|
||||||
|
errorsToShow: [],
|
||||||
|
isLoading: false,
|
||||||
|
isValid: false,
|
||||||
|
removePending: false
|
||||||
|
} as any,
|
||||||
|
'upload': {
|
||||||
|
header: 'submit.progressbar.upload',
|
||||||
|
config: 'https://rest.api/dspace-spring-rest/api/config/submissionuploads/upload',
|
||||||
|
mandatory: true,
|
||||||
|
sectionType: 'upload',
|
||||||
|
collapsed: false,
|
||||||
|
enabled: true,
|
||||||
|
data: {
|
||||||
|
files: []
|
||||||
|
},
|
||||||
|
errorsToShow: [],
|
||||||
|
isLoading: false,
|
||||||
|
isValid: false,
|
||||||
|
removePending: false
|
||||||
|
} as any,
|
||||||
|
'license': {
|
||||||
|
header: 'submit.progressbar.license',
|
||||||
|
config: '',
|
||||||
|
mandatory: true,
|
||||||
|
sectionType: 'license',
|
||||||
|
visibility: {
|
||||||
|
main: null,
|
||||||
|
other: 'READONLY'
|
||||||
|
},
|
||||||
|
collapsed: false,
|
||||||
|
enabled: true,
|
||||||
|
data: {},
|
||||||
|
errorsToShow: [],
|
||||||
|
isLoading: false,
|
||||||
|
isValid: false,
|
||||||
|
removePending: false
|
||||||
|
} as any
|
||||||
|
},
|
||||||
|
isLoading: false,
|
||||||
|
savePending: false,
|
||||||
|
depositPending: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const mockSubmissionStateWithDuplicate: SubmissionObjectState = Object.assign({}, {
|
||||||
|
826: {
|
||||||
|
collection: mockSubmissionCollectionId,
|
||||||
|
definition: 'traditional',
|
||||||
|
selfUrl: mockSubmissionSelfUrl,
|
||||||
|
activeSection: null,
|
||||||
|
sections: {
|
||||||
|
'extraction': {
|
||||||
|
config: '',
|
||||||
|
mandatory: true,
|
||||||
|
sectionType: 'utils',
|
||||||
|
visibility: {
|
||||||
|
main: 'HIDDEN',
|
||||||
|
other: 'HIDDEN'
|
||||||
|
},
|
||||||
|
collapsed: false,
|
||||||
|
enabled: true,
|
||||||
|
data: {},
|
||||||
|
errorsToShow: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
} as any,
|
} as any,
|
||||||
@@ -1035,7 +1155,7 @@ export const mockSubmissionState: SubmissionObjectState = Object.assign({}, {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
} as any,
|
} as any,
|
||||||
@@ -1047,7 +1167,7 @@ export const mockSubmissionState: SubmissionObjectState = Object.assign({}, {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
formId: '2_traditionalpageone',
|
formId: '2_traditionalpageone',
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
@@ -1060,7 +1180,7 @@ export const mockSubmissionState: SubmissionObjectState = Object.assign({}, {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
} as any,
|
} as any,
|
||||||
@@ -1074,7 +1194,7 @@ export const mockSubmissionState: SubmissionObjectState = Object.assign({}, {
|
|||||||
data: {
|
data: {
|
||||||
files: []
|
files: []
|
||||||
},
|
},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
} as any,
|
} as any,
|
||||||
@@ -1090,7 +1210,7 @@ export const mockSubmissionState: SubmissionObjectState = Object.assign({}, {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
} as any
|
} as any
|
||||||
@@ -1119,7 +1239,7 @@ export const mockSubmissionStateWithoutUpload: SubmissionObjectState = Object.as
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
} as any,
|
} as any,
|
||||||
@@ -1134,7 +1254,7 @@ export const mockSubmissionStateWithoutUpload: SubmissionObjectState = Object.as
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
} as any,
|
} as any,
|
||||||
@@ -1146,7 +1266,7 @@ export const mockSubmissionStateWithoutUpload: SubmissionObjectState = Object.as
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
formId: '2_traditionalpageone',
|
formId: '2_traditionalpageone',
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
@@ -1159,7 +1279,7 @@ export const mockSubmissionStateWithoutUpload: SubmissionObjectState = Object.as
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
} as any,
|
} as any,
|
||||||
@@ -1175,7 +1295,7 @@ export const mockSubmissionStateWithoutUpload: SubmissionObjectState = Object.as
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
} as any
|
} as any
|
||||||
@@ -1198,7 +1318,7 @@ export const mockSectionsState = Object.assign({}, {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
} as any,
|
} as any,
|
||||||
@@ -1213,7 +1333,7 @@ export const mockSectionsState = Object.assign({}, {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
} as any,
|
} as any,
|
||||||
@@ -1225,7 +1345,7 @@ export const mockSectionsState = Object.assign({}, {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
} as any,
|
} as any,
|
||||||
@@ -1237,7 +1357,7 @@ export const mockSectionsState = Object.assign({}, {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
} as any,
|
} as any,
|
||||||
@@ -1249,7 +1369,7 @@ export const mockSectionsState = Object.assign({}, {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
} as any,
|
} as any,
|
||||||
@@ -1265,7 +1385,7 @@ export const mockSectionsState = Object.assign({}, {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
} as any
|
} as any
|
||||||
|
@@ -18,4 +18,6 @@ export class SectionsServiceStub {
|
|||||||
setSectionError = jasmine.createSpy('setSectionError');
|
setSectionError = jasmine.createSpy('setSectionError');
|
||||||
setSectionStatus = jasmine.createSpy('setSectionStatus');
|
setSectionStatus = jasmine.createSpy('setSectionStatus');
|
||||||
computeSectionConfiguredMetadata = jasmine.createSpy('computeSectionConfiguredMetadata');
|
computeSectionConfiguredMetadata = jasmine.createSpy('computeSectionConfiguredMetadata');
|
||||||
|
getShownSectionErrors = jasmine.createSpy('getShownSectionErrors');
|
||||||
|
getSectionServerErrors = jasmine.createSpy('getSectionServerErrors');
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
[sections]="sections"
|
[sections]="sections"
|
||||||
[selfUrl]="selfUrl"
|
[selfUrl]="selfUrl"
|
||||||
[submissionDefinition]="submissionDefinition"
|
[submissionDefinition]="submissionDefinition"
|
||||||
|
[submissionErrors]="submissionErrors"
|
||||||
[item]="item"
|
[item]="item"
|
||||||
[submissionId]="submissionId"></ds-submission-form>
|
[submissionId]="submissionId"></ds-submission-form>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -2,11 +2,11 @@ import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
|
|||||||
import { ActivatedRoute, ParamMap, Router } from '@angular/router';
|
import { ActivatedRoute, ParamMap, Router } from '@angular/router';
|
||||||
|
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { filter, switchMap, debounceTime } from 'rxjs/operators';
|
import { debounceTime, filter, switchMap } from 'rxjs/operators';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { WorkspaceitemSectionsObject } from '../../core/submission/models/workspaceitem-sections.model';
|
import { WorkspaceitemSectionsObject } from '../../core/submission/models/workspaceitem-sections.model';
|
||||||
import { hasValue, isEmpty, isNotNull, isNotEmptyOperator } from '../../shared/empty.util';
|
import { hasValue, isEmpty, isNotEmptyOperator, isNotNull } from '../../shared/empty.util';
|
||||||
import { SubmissionDefinitionsModel } from '../../core/config/models/config-submission-definitions.model';
|
import { SubmissionDefinitionsModel } from '../../core/config/models/config-submission-definitions.model';
|
||||||
import { SubmissionService } from '../submission.service';
|
import { SubmissionService } from '../submission.service';
|
||||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||||
@@ -18,6 +18,8 @@ import { getAllSucceededRemoteData } from '../../core/shared/operators';
|
|||||||
import { ItemDataService } from '../../core/data/item-data.service';
|
import { ItemDataService } from '../../core/data/item-data.service';
|
||||||
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
|
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
|
||||||
import { SubmissionJsonPatchOperationsService } from '../../core/submission/submission-json-patch-operations.service';
|
import { SubmissionJsonPatchOperationsService } from '../../core/submission/submission-json-patch-operations.service';
|
||||||
|
import { SubmissionError } from '../objects/submission-objects.reducer';
|
||||||
|
import parseSectionErrors from '../utils/parseSectionErrors';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component allows to edit an existing workspaceitem/workflowitem.
|
* This component allows to edit an existing workspaceitem/workflowitem.
|
||||||
@@ -53,6 +55,12 @@ export class SubmissionEditComponent implements OnDestroy, OnInit {
|
|||||||
*/
|
*/
|
||||||
public submissionDefinition: SubmissionDefinitionsModel;
|
public submissionDefinition: SubmissionDefinitionsModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The submission errors present in the submission object
|
||||||
|
* @type {SubmissionError}
|
||||||
|
*/
|
||||||
|
public submissionErrors: SubmissionError;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The submission id
|
* The submission id
|
||||||
* @type {string}
|
* @type {string}
|
||||||
@@ -86,6 +94,7 @@ export class SubmissionEditComponent implements OnDestroy, OnInit {
|
|||||||
* @param {ItemDataService} itemDataService
|
* @param {ItemDataService} itemDataService
|
||||||
* @param {SubmissionService} submissionService
|
* @param {SubmissionService} submissionService
|
||||||
* @param {TranslateService} translate
|
* @param {TranslateService} translate
|
||||||
|
* @param {SubmissionJsonPatchOperationsService} submissionJsonPatchOperationsService
|
||||||
*/
|
*/
|
||||||
constructor(private changeDetectorRef: ChangeDetectorRef,
|
constructor(private changeDetectorRef: ChangeDetectorRef,
|
||||||
private notificationsService: NotificationsService,
|
private notificationsService: NotificationsService,
|
||||||
@@ -112,6 +121,8 @@ export class SubmissionEditComponent implements OnDestroy, OnInit {
|
|||||||
this.notificationsService.info(null, this.translate.get('submission.general.cannot_submit'));
|
this.notificationsService.info(null, this.translate.get('submission.general.cannot_submit'));
|
||||||
this.router.navigate(['/mydspace']);
|
this.router.navigate(['/mydspace']);
|
||||||
} else {
|
} else {
|
||||||
|
const { errors } = submissionObjectRD.payload;
|
||||||
|
this.submissionErrors = parseSectionErrors(errors);
|
||||||
this.submissionId = submissionObjectRD.payload.id.toString();
|
this.submissionId = submissionObjectRD.payload.id.toString();
|
||||||
this.collectionId = (submissionObjectRD.payload.collection as Collection).id;
|
this.collectionId = (submissionObjectRD.payload.collection as Collection).id;
|
||||||
this.selfUrl = submissionObjectRD.payload._links.self.href;
|
this.selfUrl = submissionObjectRD.payload._links.self.href;
|
||||||
|
@@ -126,6 +126,7 @@ describe('SubmissionFormComponent Component', () => {
|
|||||||
comp.submissionDefinition = submissionDefinition;
|
comp.submissionDefinition = submissionDefinition;
|
||||||
comp.selfUrl = selfUrl;
|
comp.selfUrl = selfUrl;
|
||||||
comp.sections = sectionsData;
|
comp.sections = sectionsData;
|
||||||
|
comp.submissionErrors = null;
|
||||||
comp.item = new Item();
|
comp.item = new Item();
|
||||||
|
|
||||||
submissionServiceStub.getSubmissionObject.and.returnValue(observableOf(submissionState));
|
submissionServiceStub.getSubmissionObject.and.returnValue(observableOf(submissionState));
|
||||||
|
@@ -11,7 +11,7 @@ import { WorkspaceitemSectionsObject } from '../../core/submission/models/worksp
|
|||||||
|
|
||||||
import { hasValue, isNotEmpty } from '../../shared/empty.util';
|
import { hasValue, isNotEmpty } from '../../shared/empty.util';
|
||||||
import { UploaderOptions } from '../../shared/uploader/uploader-options.model';
|
import { UploaderOptions } from '../../shared/uploader/uploader-options.model';
|
||||||
import { SubmissionObjectEntry } from '../objects/submission-objects.reducer';
|
import { SubmissionError, SubmissionObjectEntry } from '../objects/submission-objects.reducer';
|
||||||
import { SectionDataObject } from '../sections/models/section-data.model';
|
import { SectionDataObject } from '../sections/models/section-data.model';
|
||||||
import { SubmissionService } from '../submission.service';
|
import { SubmissionService } from '../submission.service';
|
||||||
import { Item } from '../../core/shared/item.model';
|
import { Item } from '../../core/shared/item.model';
|
||||||
@@ -41,6 +41,12 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
@Input() sections: WorkspaceitemSectionsObject;
|
@Input() sections: WorkspaceitemSectionsObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The submission errors present in the submission object
|
||||||
|
* @type {SubmissionError}
|
||||||
|
*/
|
||||||
|
@Input() submissionErrors: SubmissionError;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The submission self url
|
* The submission self url
|
||||||
* @type {string}
|
* @type {string}
|
||||||
@@ -163,7 +169,7 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy {
|
|||||||
this.submissionDefinition,
|
this.submissionDefinition,
|
||||||
this.sections,
|
this.sections,
|
||||||
this.item,
|
this.item,
|
||||||
null);
|
this.submissionErrors);
|
||||||
this.changeDetectorRef.detectChanges();
|
this.changeDetectorRef.detectChanges();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||||
import { waitForAsync, ComponentFixture, inject, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
|
|
||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||||
@@ -165,6 +165,7 @@ describe('SubmissionUploadFilesComponent Component', () => {
|
|||||||
submissionId,
|
submissionId,
|
||||||
sectionId,
|
sectionId,
|
||||||
mockSectionsData[sectionId],
|
mockSectionsData[sectionId],
|
||||||
|
expectedErrors[sectionId],
|
||||||
expectedErrors[sectionId]
|
expectedErrors[sectionId]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -188,6 +189,7 @@ describe('SubmissionUploadFilesComponent Component', () => {
|
|||||||
submissionId,
|
submissionId,
|
||||||
sectionId,
|
sectionId,
|
||||||
mockSectionsData[sectionId],
|
mockSectionsData[sectionId],
|
||||||
|
expectedErrors[sectionId],
|
||||||
expectedErrors[sectionId]
|
expectedErrors[sectionId]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@@ -143,7 +143,7 @@ export class SubmissionUploadFilesComponent implements OnChanges {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.sectionService.updateSectionData(this.submissionId, sectionId, sectionData, sectionErrors);
|
this.sectionService.updateSectionData(this.submissionId, sectionId, sectionData, sectionErrors, sectionErrors);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { Action } from '@ngrx/store';
|
import { Action } from '@ngrx/store';
|
||||||
|
|
||||||
import { type } from '../../shared/ngrx/type';
|
import { type } from '../../shared/ngrx/type';
|
||||||
import { SectionVisibility, SubmissionSectionError } from './submission-objects.reducer';
|
import { SectionVisibility, SubmissionError, SubmissionSectionError } from './submission-objects.reducer';
|
||||||
import { WorkspaceitemSectionUploadFileObject } from '../../core/submission/models/workspaceitem-section-upload-file.model';
|
import { WorkspaceitemSectionUploadFileObject } from '../../core/submission/models/workspaceitem-section-upload-file.model';
|
||||||
import {
|
import {
|
||||||
WorkspaceitemSectionDataType,
|
WorkspaceitemSectionDataType,
|
||||||
@@ -206,7 +206,8 @@ export class UpdateSectionDataAction implements Action {
|
|||||||
submissionId: string;
|
submissionId: string;
|
||||||
sectionId: string;
|
sectionId: string;
|
||||||
data: WorkspaceitemSectionDataType;
|
data: WorkspaceitemSectionDataType;
|
||||||
errors: SubmissionSectionError[];
|
errorsToShow: SubmissionSectionError[];
|
||||||
|
serverValidationErrors: SubmissionSectionError[];
|
||||||
metadata: string[];
|
metadata: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -219,17 +220,20 @@ export class UpdateSectionDataAction implements Action {
|
|||||||
* the section's ID to add
|
* the section's ID to add
|
||||||
* @param data
|
* @param data
|
||||||
* the section's data
|
* the section's data
|
||||||
* @param errors
|
* @param errorsToShow
|
||||||
* the section's errors
|
* the list of the section's errors to show
|
||||||
|
* @param serverValidationErrors
|
||||||
|
* the list of the section errors detected by the server
|
||||||
* @param metadata
|
* @param metadata
|
||||||
* the section's metadata
|
* the section's metadata
|
||||||
*/
|
*/
|
||||||
constructor(submissionId: string,
|
constructor(submissionId: string,
|
||||||
sectionId: string,
|
sectionId: string,
|
||||||
data: WorkspaceitemSectionDataType,
|
data: WorkspaceitemSectionDataType,
|
||||||
errors: SubmissionSectionError[],
|
errorsToShow: SubmissionSectionError[],
|
||||||
|
serverValidationErrors: SubmissionSectionError[],
|
||||||
metadata?: string[]) {
|
metadata?: string[]) {
|
||||||
this.payload = { submissionId, sectionId, data, errors, metadata };
|
this.payload = { submissionId, sectionId, data, errorsToShow, serverValidationErrors, metadata };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +312,7 @@ export class InitSubmissionFormAction implements Action {
|
|||||||
submissionDefinition: SubmissionDefinitionsModel;
|
submissionDefinition: SubmissionDefinitionsModel;
|
||||||
sections: WorkspaceitemSectionsObject;
|
sections: WorkspaceitemSectionsObject;
|
||||||
item: Item;
|
item: Item;
|
||||||
errors: SubmissionSectionError[];
|
errors: SubmissionError;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -333,7 +337,7 @@ export class InitSubmissionFormAction implements Action {
|
|||||||
submissionDefinition: SubmissionDefinitionsModel,
|
submissionDefinition: SubmissionDefinitionsModel,
|
||||||
sections: WorkspaceitemSectionsObject,
|
sections: WorkspaceitemSectionsObject,
|
||||||
item: Item,
|
item: Item,
|
||||||
errors: SubmissionSectionError[]) {
|
errors: SubmissionError) {
|
||||||
this.payload = { collectionId, submissionId, selfUrl, submissionDefinition, sections, item, errors };
|
this.payload = { collectionId, submissionId, selfUrl, submissionDefinition, sections, item, errors };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,7 +28,7 @@ import {
|
|||||||
mockSectionsData,
|
mockSectionsData,
|
||||||
mockSectionsDataTwo,
|
mockSectionsDataTwo,
|
||||||
mockSectionsErrors,
|
mockSectionsErrors,
|
||||||
mockSectionsErrorsTwo,
|
mockSectionsErrorsTouchedField,
|
||||||
mockSubmissionCollectionId,
|
mockSubmissionCollectionId,
|
||||||
mockSubmissionDefinition,
|
mockSubmissionDefinition,
|
||||||
mockSubmissionDefinitionResponse,
|
mockSubmissionDefinitionResponse,
|
||||||
@@ -358,18 +358,21 @@ describe('SubmissionObjectEffects test suite', () => {
|
|||||||
submissionId,
|
submissionId,
|
||||||
'traditionalpageone',
|
'traditionalpageone',
|
||||||
mockSectionsData.traditionalpageone as any,
|
mockSectionsData.traditionalpageone as any,
|
||||||
|
errorsList.traditionalpageone || [],
|
||||||
errorsList.traditionalpageone || []
|
errorsList.traditionalpageone || []
|
||||||
),
|
),
|
||||||
c: new UpdateSectionDataAction(
|
c: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'license',
|
'license',
|
||||||
mockSectionsData.license as any,
|
mockSectionsData.license as any,
|
||||||
|
errorsList.license || [],
|
||||||
errorsList.license || []
|
errorsList.license || []
|
||||||
),
|
),
|
||||||
d: new UpdateSectionDataAction(
|
d: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'upload',
|
'upload',
|
||||||
mockSectionsData.upload as any,
|
mockSectionsData.upload as any,
|
||||||
|
errorsList.upload || [],
|
||||||
errorsList.upload || []
|
errorsList.upload || []
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
@@ -408,25 +411,29 @@ describe('SubmissionObjectEffects test suite', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const errorsList = parseSectionErrors(mockSectionsErrorsTwo);
|
const errorsToShowList = parseSectionErrors(mockSectionsErrorsTouchedField);
|
||||||
|
const serverValidationErrorsList = parseSectionErrors(mockSectionsErrors);
|
||||||
const expected = cold('--(bcd)-', {
|
const expected = cold('--(bcd)-', {
|
||||||
b: new UpdateSectionDataAction(
|
b: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'traditionalpageone',
|
'traditionalpageone',
|
||||||
mockSectionsData.traditionalpageone as any,
|
mockSectionsData.traditionalpageone as any,
|
||||||
errorsList.traditionalpageone
|
errorsToShowList.traditionalpageone,
|
||||||
|
serverValidationErrorsList.traditionalpageone
|
||||||
),
|
),
|
||||||
c: new UpdateSectionDataAction(
|
c: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'license',
|
'license',
|
||||||
mockSectionsData.license as any,
|
mockSectionsData.license as any,
|
||||||
errorsList.license || []
|
errorsToShowList.license || [],
|
||||||
|
serverValidationErrorsList.license || []
|
||||||
),
|
),
|
||||||
d: new UpdateSectionDataAction(
|
d: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'upload',
|
'upload',
|
||||||
mockSectionsData.upload as any,
|
mockSectionsData.upload as any,
|
||||||
errorsList.upload || []
|
errorsToShowList.upload || [],
|
||||||
|
serverValidationErrorsList.upload || []
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -459,18 +466,21 @@ describe('SubmissionObjectEffects test suite', () => {
|
|||||||
submissionId,
|
submissionId,
|
||||||
'traditionalpageone',
|
'traditionalpageone',
|
||||||
mockSectionsData.traditionalpageone as any,
|
mockSectionsData.traditionalpageone as any,
|
||||||
|
[],
|
||||||
[]
|
[]
|
||||||
),
|
),
|
||||||
c: new UpdateSectionDataAction(
|
c: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'license',
|
'license',
|
||||||
mockSectionsData.license as any,
|
mockSectionsData.license as any,
|
||||||
|
[],
|
||||||
[]
|
[]
|
||||||
),
|
),
|
||||||
d: new UpdateSectionDataAction(
|
d: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'upload',
|
'upload',
|
||||||
mockSectionsData.upload as any,
|
mockSectionsData.upload as any,
|
||||||
|
[],
|
||||||
[]
|
[]
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
@@ -506,18 +516,21 @@ describe('SubmissionObjectEffects test suite', () => {
|
|||||||
submissionId,
|
submissionId,
|
||||||
'traditionalpageone',
|
'traditionalpageone',
|
||||||
mockSectionsData.traditionalpageone as any,
|
mockSectionsData.traditionalpageone as any,
|
||||||
|
errorsList.traditionalpageone || [],
|
||||||
errorsList.traditionalpageone || []
|
errorsList.traditionalpageone || []
|
||||||
),
|
),
|
||||||
c: new UpdateSectionDataAction(
|
c: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'license',
|
'license',
|
||||||
mockSectionsData.license as any,
|
mockSectionsData.license as any,
|
||||||
|
errorsList.license || [],
|
||||||
errorsList.license || []
|
errorsList.license || []
|
||||||
),
|
),
|
||||||
d: new UpdateSectionDataAction(
|
d: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'upload',
|
'upload',
|
||||||
mockSectionsData.upload as any,
|
mockSectionsData.upload as any,
|
||||||
|
errorsList.upload || [],
|
||||||
errorsList.upload || []
|
errorsList.upload || []
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
@@ -553,24 +566,28 @@ describe('SubmissionObjectEffects test suite', () => {
|
|||||||
submissionId,
|
submissionId,
|
||||||
'traditionalpageone',
|
'traditionalpageone',
|
||||||
mockSectionsDataTwo.traditionalpageone as any,
|
mockSectionsDataTwo.traditionalpageone as any,
|
||||||
|
errorsList.traditionalpageone || [],
|
||||||
errorsList.traditionalpageone || []
|
errorsList.traditionalpageone || []
|
||||||
),
|
),
|
||||||
c: new UpdateSectionDataAction(
|
c: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'traditionalpagetwo',
|
'traditionalpagetwo',
|
||||||
mockSectionsDataTwo.traditionalpagetwo as any,
|
mockSectionsDataTwo.traditionalpagetwo as any,
|
||||||
|
errorsList.traditionalpagetwo || [],
|
||||||
errorsList.traditionalpagetwo || []
|
errorsList.traditionalpagetwo || []
|
||||||
),
|
),
|
||||||
d: new UpdateSectionDataAction(
|
d: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'license',
|
'license',
|
||||||
mockSectionsDataTwo.license as any,
|
mockSectionsDataTwo.license as any,
|
||||||
|
errorsList.license || [],
|
||||||
errorsList.license || []
|
errorsList.license || []
|
||||||
),
|
),
|
||||||
e: new UpdateSectionDataAction(
|
e: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'upload',
|
'upload',
|
||||||
mockSectionsDataTwo.upload as any,
|
mockSectionsDataTwo.upload as any,
|
||||||
|
errorsList.upload || [],
|
||||||
errorsList.upload || []
|
errorsList.upload || []
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
@@ -610,18 +627,21 @@ describe('SubmissionObjectEffects test suite', () => {
|
|||||||
submissionId,
|
submissionId,
|
||||||
'traditionalpageone',
|
'traditionalpageone',
|
||||||
mockSectionsData.traditionalpageone as any,
|
mockSectionsData.traditionalpageone as any,
|
||||||
[]
|
[],
|
||||||
|
errorsList.traditionalpageone
|
||||||
),
|
),
|
||||||
c: new UpdateSectionDataAction(
|
c: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'license',
|
'license',
|
||||||
mockSectionsData.license as any,
|
mockSectionsData.license as any,
|
||||||
|
errorsList.license || [],
|
||||||
errorsList.license || []
|
errorsList.license || []
|
||||||
),
|
),
|
||||||
d: new UpdateSectionDataAction(
|
d: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'upload',
|
'upload',
|
||||||
mockSectionsData.upload as any,
|
mockSectionsData.upload as any,
|
||||||
|
errorsList.upload || [],
|
||||||
errorsList.upload || []
|
errorsList.upload || []
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
@@ -655,18 +675,21 @@ describe('SubmissionObjectEffects test suite', () => {
|
|||||||
submissionId,
|
submissionId,
|
||||||
'traditionalpageone',
|
'traditionalpageone',
|
||||||
mockSectionsData.traditionalpageone as any,
|
mockSectionsData.traditionalpageone as any,
|
||||||
|
[],
|
||||||
[]
|
[]
|
||||||
),
|
),
|
||||||
c: new UpdateSectionDataAction(
|
c: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'license',
|
'license',
|
||||||
mockSectionsData.license as any,
|
mockSectionsData.license as any,
|
||||||
|
[],
|
||||||
[]
|
[]
|
||||||
),
|
),
|
||||||
d: new UpdateSectionDataAction(
|
d: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'upload',
|
'upload',
|
||||||
mockSectionsData.upload as any,
|
mockSectionsData.upload as any,
|
||||||
|
[],
|
||||||
[]
|
[]
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
@@ -696,26 +719,28 @@ describe('SubmissionObjectEffects test suite', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const errorsList = parseSectionErrors(mockSectionsErrors);
|
const serverValidationErrorsList = parseSectionErrors(mockSectionsErrors);
|
||||||
console.log(errorsList);
|
|
||||||
const expected = cold('--(bcd)-', {
|
const expected = cold('--(bcd)-', {
|
||||||
b: new UpdateSectionDataAction(
|
b: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'traditionalpageone',
|
'traditionalpageone',
|
||||||
mockSectionsData.traditionalpageone as any,
|
mockSectionsData.traditionalpageone as any,
|
||||||
[]
|
[],
|
||||||
|
serverValidationErrorsList.traditionalpageone
|
||||||
),
|
),
|
||||||
c: new UpdateSectionDataAction(
|
c: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'license',
|
'license',
|
||||||
mockSectionsData.license as any,
|
mockSectionsData.license as any,
|
||||||
errorsList.license || []
|
serverValidationErrorsList.license || [],
|
||||||
|
serverValidationErrorsList.license || []
|
||||||
),
|
),
|
||||||
d: new UpdateSectionDataAction(
|
d: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'upload',
|
'upload',
|
||||||
mockSectionsData.upload as any,
|
mockSectionsData.upload as any,
|
||||||
errorsList.upload || []
|
serverValidationErrorsList.upload || [],
|
||||||
|
serverValidationErrorsList.upload || []
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -750,24 +775,28 @@ describe('SubmissionObjectEffects test suite', () => {
|
|||||||
submissionId,
|
submissionId,
|
||||||
'traditionalpageone',
|
'traditionalpageone',
|
||||||
mockSectionsDataTwo.traditionalpageone as any,
|
mockSectionsDataTwo.traditionalpageone as any,
|
||||||
[]
|
[],
|
||||||
|
errorsList.traditionalpageone
|
||||||
),
|
),
|
||||||
c: new UpdateSectionDataAction(
|
c: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'traditionalpagetwo',
|
'traditionalpagetwo',
|
||||||
mockSectionsDataTwo.traditionalpagetwo as any,
|
mockSectionsDataTwo.traditionalpagetwo as any,
|
||||||
|
errorsList.traditionalpagetwo || [],
|
||||||
errorsList.traditionalpagetwo || []
|
errorsList.traditionalpagetwo || []
|
||||||
),
|
),
|
||||||
d: new UpdateSectionDataAction(
|
d: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'license',
|
'license',
|
||||||
mockSectionsDataTwo.license as any,
|
mockSectionsDataTwo.license as any,
|
||||||
|
errorsList.license || [],
|
||||||
errorsList.license || []
|
errorsList.license || []
|
||||||
),
|
),
|
||||||
e: new UpdateSectionDataAction(
|
e: new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'upload',
|
'upload',
|
||||||
mockSectionsDataTwo.upload as any,
|
mockSectionsDataTwo.upload as any,
|
||||||
|
errorsList.upload || [],
|
||||||
errorsList.upload || []
|
errorsList.upload || []
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
@@ -880,18 +909,21 @@ describe('SubmissionObjectEffects test suite', () => {
|
|||||||
submissionId,
|
submissionId,
|
||||||
'traditionalpageone',
|
'traditionalpageone',
|
||||||
mockSectionsData.traditionalpageone as any,
|
mockSectionsData.traditionalpageone as any,
|
||||||
|
errorsList.traditionalpageone || [],
|
||||||
errorsList.traditionalpageone || []
|
errorsList.traditionalpageone || []
|
||||||
),
|
),
|
||||||
new UpdateSectionDataAction(
|
new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'license',
|
'license',
|
||||||
mockSectionsData.license as any,
|
mockSectionsData.license as any,
|
||||||
|
errorsList.license || [],
|
||||||
errorsList.license || []
|
errorsList.license || []
|
||||||
),
|
),
|
||||||
new UpdateSectionDataAction(
|
new UpdateSectionDataAction(
|
||||||
submissionId,
|
submissionId,
|
||||||
'upload',
|
'upload',
|
||||||
mockSectionsData.upload as any,
|
mockSectionsData.upload as any,
|
||||||
|
errorsList.upload || [],
|
||||||
errorsList.upload || []
|
errorsList.upload || []
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
@@ -5,16 +5,7 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
import { isEqual, union } from 'lodash';
|
import { isEqual, union } from 'lodash';
|
||||||
|
|
||||||
import { from as observableFrom, Observable, of as observableOf } from 'rxjs';
|
import { from as observableFrom, Observable, of as observableOf } from 'rxjs';
|
||||||
import {
|
import { catchError, filter, map, mergeMap, switchMap, take, tap, withLatestFrom } from 'rxjs/operators';
|
||||||
catchError,
|
|
||||||
filter,
|
|
||||||
map,
|
|
||||||
mergeMap,
|
|
||||||
switchMap,
|
|
||||||
take,
|
|
||||||
tap,
|
|
||||||
withLatestFrom
|
|
||||||
} from 'rxjs/operators';
|
|
||||||
import { SubmissionObject } from '../../core/submission/models/submission-object.model';
|
import { SubmissionObject } from '../../core/submission/models/submission-object.model';
|
||||||
import { WorkflowItem } from '../../core/submission/models/workflowitem.model';
|
import { WorkflowItem } from '../../core/submission/models/workflowitem.model';
|
||||||
import { WorkspaceitemSectionUploadObject } from '../../core/submission/models/workspaceitem-section-upload.model';
|
import { WorkspaceitemSectionUploadObject } from '../../core/submission/models/workspaceitem-section-upload.model';
|
||||||
@@ -83,7 +74,7 @@ export class SubmissionObjectEffects {
|
|||||||
} else {
|
} else {
|
||||||
sectionData = action.payload.item.metadata;
|
sectionData = action.payload.item.metadata;
|
||||||
}
|
}
|
||||||
const sectionErrors = null;
|
const sectionErrors = isNotEmpty(action.payload.errors) ? (action.payload.errors[sectionId] || null) : null;
|
||||||
mappedActions.push(
|
mappedActions.push(
|
||||||
new InitSectionAction(
|
new InitSectionAction(
|
||||||
action.payload.submissionId,
|
action.payload.submissionId,
|
||||||
@@ -232,10 +223,7 @@ export class SubmissionObjectEffects {
|
|||||||
switchMap(([action, state]: [DepositSubmissionAction, any]) => {
|
switchMap(([action, state]: [DepositSubmissionAction, any]) => {
|
||||||
return this.submissionService.depositSubmission(state.submission.objects[action.payload.submissionId].selfUrl).pipe(
|
return this.submissionService.depositSubmission(state.submission.objects[action.payload.submissionId].selfUrl).pipe(
|
||||||
map(() => new DepositSubmissionSuccessAction(action.payload.submissionId)),
|
map(() => new DepositSubmissionSuccessAction(action.payload.submissionId)),
|
||||||
catchError((error) => {
|
catchError((error) => observableOf(new DepositSubmissionErrorAction(action.payload.submissionId))));
|
||||||
console.log('submission error', error);
|
|
||||||
return observableOf(new DepositSubmissionErrorAction(action.payload.submissionId));
|
|
||||||
}));
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -297,7 +285,7 @@ export class SubmissionObjectEffects {
|
|||||||
return item$.pipe(
|
return item$.pipe(
|
||||||
map((item: Item) => item.metadata),
|
map((item: Item) => item.metadata),
|
||||||
filter((metadata) => !isEqual(action.payload.data, metadata)),
|
filter((metadata) => !isEqual(action.payload.data, metadata)),
|
||||||
map((metadata: any) => new UpdateSectionDataAction(action.payload.submissionId, action.payload.sectionId, metadata, action.payload.errors, action.payload.metadata))
|
map((metadata: any) => new UpdateSectionDataAction(action.payload.submissionId, action.payload.sectionId, metadata, action.payload.errorsToShow, action.payload.serverValidationErrors, action.payload.metadata))
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return observableOf(new UpdateSectionDataSuccessAction());
|
return observableOf(new UpdateSectionDataSuccessAction());
|
||||||
@@ -413,7 +401,7 @@ export class SubmissionObjectEffects {
|
|||||||
|
|
||||||
const sectionForm = getForm(forms, currentState, sectionId);
|
const sectionForm = getForm(forms, currentState, sectionId);
|
||||||
const filteredErrors = filterErrors(sectionForm, sectionErrors, currentState.sections[sectionId].sectionType, notify);
|
const filteredErrors = filterErrors(sectionForm, sectionErrors, currentState.sections[sectionId].sectionType, notify);
|
||||||
mappedActions.push(new UpdateSectionDataAction(submissionId, sectionId, sectionData, filteredErrors));
|
mappedActions.push(new UpdateSectionDataAction(submissionId, sectionId, sectionData, filteredErrors, sectionErrors));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -28,7 +28,8 @@ import {
|
|||||||
SaveSubmissionSectionFormAction,
|
SaveSubmissionSectionFormAction,
|
||||||
SaveSubmissionSectionFormErrorAction,
|
SaveSubmissionSectionFormErrorAction,
|
||||||
SaveSubmissionSectionFormSuccessAction,
|
SaveSubmissionSectionFormSuccessAction,
|
||||||
SectionStatusChangeAction, SubmissionObjectAction,
|
SectionStatusChangeAction,
|
||||||
|
SubmissionObjectAction,
|
||||||
UpdateSectionDataAction
|
UpdateSectionDataAction
|
||||||
} from './submission-objects.actions';
|
} from './submission-objects.actions';
|
||||||
import { SectionsType } from '../sections/sections-type';
|
import { SectionsType } from '../sections/sections-type';
|
||||||
@@ -68,7 +69,7 @@ describe('submissionReducer test suite', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const action = new InitSubmissionFormAction(collectionId, submissionId, selfUrl, submissionDefinition, {}, new Item(), []);
|
const action = new InitSubmissionFormAction(collectionId, submissionId, selfUrl, submissionDefinition, {}, new Item(), null);
|
||||||
const newState = submissionObjectReducer({}, action);
|
const newState = submissionObjectReducer({}, action);
|
||||||
|
|
||||||
expect(newState).toEqual(expectedState);
|
expect(newState).toEqual(expectedState);
|
||||||
@@ -237,12 +238,13 @@ describe('submissionReducer test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: true
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
let action: any = new InitSubmissionFormAction(collectionId, submissionId, selfUrl, submissionDefinition, {}, new Item(), []);
|
let action: any = new InitSubmissionFormAction(collectionId, submissionId, selfUrl, submissionDefinition, {}, new Item(), null);
|
||||||
let newState = submissionObjectReducer({}, action);
|
let newState = submissionObjectReducer({}, action);
|
||||||
|
|
||||||
action = new InitSectionAction(
|
action = new InitSectionAction(
|
||||||
@@ -329,7 +331,7 @@ describe('submissionReducer test suite', () => {
|
|||||||
]
|
]
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
const action = new UpdateSectionDataAction(submissionId, 'traditionalpageone', data, []);
|
const action = new UpdateSectionDataAction(submissionId, 'traditionalpageone', data, [], []);
|
||||||
const newState = submissionObjectReducer(initState, action);
|
const newState = submissionObjectReducer(initState, action);
|
||||||
|
|
||||||
expect(newState[826].sections.traditionalpageone.data).toEqual(data);
|
expect(newState[826].sections.traditionalpageone.data).toEqual(data);
|
||||||
@@ -340,7 +342,7 @@ describe('submissionReducer test suite', () => {
|
|||||||
} as any;
|
} as any;
|
||||||
const metadata = ['dc.title', 'dc.contributor.author'];
|
const metadata = ['dc.title', 'dc.contributor.author'];
|
||||||
|
|
||||||
const action = new UpdateSectionDataAction(submissionId, 'traditionalpageone', data, [], metadata);
|
const action = new UpdateSectionDataAction(submissionId, 'traditionalpageone', data, [], [], metadata);
|
||||||
const newState = submissionObjectReducer(initState, action);
|
const newState = submissionObjectReducer(initState, action);
|
||||||
|
|
||||||
expect(newState[826].sections.traditionalpageone.metadata).toEqual(metadata);
|
expect(newState[826].sections.traditionalpageone.metadata).toEqual(metadata);
|
||||||
@@ -354,10 +356,10 @@ describe('submissionReducer test suite', () => {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const action = new UpdateSectionDataAction(submissionId, 'traditionalpageone', {}, errors);
|
const action = new UpdateSectionDataAction(submissionId, 'traditionalpageone', {}, errors, errors);
|
||||||
const newState = submissionObjectReducer(initState, action);
|
const newState = submissionObjectReducer(initState, action);
|
||||||
|
|
||||||
expect(newState[826].sections.traditionalpageone.errors).toEqual(errors);
|
expect(newState[826].sections.traditionalpageone.errorsToShow).toEqual(errors);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove all submission section errors properly', () => {
|
it('should remove all submission section errors properly', () => {
|
||||||
@@ -366,7 +368,7 @@ describe('submissionReducer test suite', () => {
|
|||||||
|
|
||||||
newState = submissionObjectReducer(initState, action);
|
newState = submissionObjectReducer(initState, action);
|
||||||
|
|
||||||
expect(newState[826].sections.traditionalpageone.errors).toEqual([]);
|
expect(newState[826].sections.traditionalpageone.errorsToShow).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add submission section error properly', () => {
|
it('should add submission section error properly', () => {
|
||||||
@@ -378,7 +380,7 @@ describe('submissionReducer test suite', () => {
|
|||||||
const action = new InertSectionErrorsAction(submissionId, 'traditionalpageone', error);
|
const action = new InertSectionErrorsAction(submissionId, 'traditionalpageone', error);
|
||||||
const newState = submissionObjectReducer(initState, action);
|
const newState = submissionObjectReducer(initState, action);
|
||||||
|
|
||||||
expect(newState[826].sections.traditionalpageone.errors).toEqual([error]);
|
expect(newState[826].sections.traditionalpageone.errorsToShow).toEqual([error]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove specified submission section error/s properly', () => {
|
it('should remove specified submission section error/s properly', () => {
|
||||||
@@ -402,21 +404,21 @@ describe('submissionReducer test suite', () => {
|
|||||||
message: 'error.validation.required'
|
message: 'error.validation.required'
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let action: any = new UpdateSectionDataAction(submissionId, 'traditionalpageone', {}, errors);
|
let action: any = new UpdateSectionDataAction(submissionId, 'traditionalpageone', {}, errors, errors);
|
||||||
let newState = submissionObjectReducer(initState, action);
|
let newState = submissionObjectReducer(initState, action);
|
||||||
|
|
||||||
action = new DeleteSectionErrorsAction(submissionId, 'traditionalpageone', error);
|
action = new DeleteSectionErrorsAction(submissionId, 'traditionalpageone', error);
|
||||||
newState = submissionObjectReducer(newState, action);
|
newState = submissionObjectReducer(newState, action);
|
||||||
|
|
||||||
expect(newState[826].sections.traditionalpageone.errors).toEqual(expectedErrors);
|
expect(newState[826].sections.traditionalpageone.errorsToShow).toEqual(expectedErrors);
|
||||||
|
|
||||||
action = new UpdateSectionDataAction(submissionId, 'traditionalpageone', {}, errors);
|
action = new UpdateSectionDataAction(submissionId, 'traditionalpageone', {}, errors, errors);
|
||||||
newState = submissionObjectReducer(initState, action);
|
newState = submissionObjectReducer(initState, action);
|
||||||
|
|
||||||
action = new DeleteSectionErrorsAction(submissionId, 'traditionalpageone', errors);
|
action = new DeleteSectionErrorsAction(submissionId, 'traditionalpageone', errors);
|
||||||
newState = submissionObjectReducer(newState, action);
|
newState = submissionObjectReducer(newState, action);
|
||||||
|
|
||||||
expect(newState[826].sections.traditionalpageone.errors).toEqual([]);
|
expect(newState[826].sections.traditionalpageone.errorsToShow).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add a new file', () => {
|
it('should add a new file', () => {
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { hasValue, isNotEmpty, isNotNull, isUndefined } from '../../shared/empty.util';
|
import { hasValue, isEmpty, isNotEmpty, isNotNull, isUndefined } from '../../shared/empty.util';
|
||||||
import { differenceWith, findKey, isEqual, uniqWith } from 'lodash';
|
import { differenceWith, findKey, isEqual, uniqWith } from 'lodash';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -97,9 +97,14 @@ export interface SubmissionSectionObject {
|
|||||||
data: WorkspaceitemSectionDataType;
|
data: WorkspaceitemSectionDataType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of the section errors
|
* The list of the section's errors to show. It contains the error list to display when section is not pristine
|
||||||
*/
|
*/
|
||||||
errors: SubmissionSectionError[];
|
errorsToShow: SubmissionSectionError[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of the section's errors detected by the server. They may not be shown yet if section is pristine
|
||||||
|
*/
|
||||||
|
serverValidationErrors: SubmissionSectionError[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A boolean representing if this section is loading
|
* A boolean representing if this section is loading
|
||||||
@@ -117,6 +122,13 @@ export interface SubmissionSectionObject {
|
|||||||
formId: string;
|
formId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface to represent section error
|
||||||
|
*/
|
||||||
|
export interface SubmissionError {
|
||||||
|
[submissionId: string]: SubmissionSectionError[];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface to represent section error
|
* An interface to represent section error
|
||||||
*/
|
*/
|
||||||
@@ -332,7 +344,7 @@ const removeError = (state: SubmissionObjectState, action: DeleteSectionErrorsAc
|
|||||||
if (Array.isArray(errors)) {
|
if (Array.isArray(errors)) {
|
||||||
filteredErrors = differenceWith(errors, errors, isEqual);
|
filteredErrors = differenceWith(errors, errors, isEqual);
|
||||||
} else {
|
} else {
|
||||||
filteredErrors = state[ submissionId ].sections[ sectionId ].errors
|
filteredErrors = state[ submissionId ].sections[ sectionId ].errorsToShow
|
||||||
.filter((currentError) => currentError.path !== errors.path || !isEqual(currentError, errors));
|
.filter((currentError) => currentError.path !== errors.path || !isEqual(currentError, errors));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,7 +352,7 @@ const removeError = (state: SubmissionObjectState, action: DeleteSectionErrorsAc
|
|||||||
[ submissionId ]: Object.assign({}, state[ submissionId ], {
|
[ submissionId ]: Object.assign({}, state[ submissionId ], {
|
||||||
sections: Object.assign({}, state[ submissionId ].sections, {
|
sections: Object.assign({}, state[ submissionId ].sections, {
|
||||||
[ sectionId ]: Object.assign({}, state[ submissionId ].sections [ sectionId ], {
|
[ sectionId ]: Object.assign({}, state[ submissionId ].sections [ sectionId ], {
|
||||||
errors: filteredErrors
|
errorsToShow: filteredErrors
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -354,13 +366,13 @@ const addError = (state: SubmissionObjectState, action: InertSectionErrorsAction
|
|||||||
const { submissionId, sectionId, error } = action.payload;
|
const { submissionId, sectionId, error } = action.payload;
|
||||||
|
|
||||||
if (hasValue(state[ submissionId ].sections[ sectionId ])) {
|
if (hasValue(state[ submissionId ].sections[ sectionId ])) {
|
||||||
const errors = uniqWith(state[ submissionId ].sections[ sectionId ].errors.concat(error), isEqual);
|
const errorsToShow = uniqWith(state[ submissionId ].sections[ sectionId ].errorsToShow.concat(error), isEqual);
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
[ submissionId ]: Object.assign({}, state[ submissionId ], {
|
[ submissionId ]: Object.assign({}, state[ submissionId ], {
|
||||||
activeSection: state[ action.payload.submissionId ].activeSection, sections: Object.assign({}, state[ submissionId ].sections, {
|
activeSection: state[ action.payload.submissionId ].activeSection, sections: Object.assign({}, state[ submissionId ].sections, {
|
||||||
[ sectionId ]: Object.assign({}, state[ action.payload.submissionId ].sections [ action.payload.sectionId ], {
|
[ sectionId ]: Object.assign({}, state[ action.payload.submissionId ].sections [ action.payload.sectionId ], {
|
||||||
errors
|
errorsToShow
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
@@ -378,7 +390,7 @@ const addError = (state: SubmissionObjectState, action: InertSectionErrorsAction
|
|||||||
* @param action
|
* @param action
|
||||||
* a RemoveSectionErrorsAction
|
* a RemoveSectionErrorsAction
|
||||||
* @return SubmissionObjectState
|
* @return SubmissionObjectState
|
||||||
* the new state, with the section's errors updated.
|
* the new state, with the section's errorsToShow updated.
|
||||||
*/
|
*/
|
||||||
function removeSectionErrors(state: SubmissionObjectState, action: RemoveSectionErrorsAction): SubmissionObjectState {
|
function removeSectionErrors(state: SubmissionObjectState, action: RemoveSectionErrorsAction): SubmissionObjectState {
|
||||||
if (isNotEmpty(state[ action.payload.submissionId ])
|
if (isNotEmpty(state[ action.payload.submissionId ])
|
||||||
@@ -387,7 +399,7 @@ function removeSectionErrors(state: SubmissionObjectState, action: RemoveSection
|
|||||||
[ action.payload.submissionId ]: Object.assign({}, state[ action.payload.submissionId ], {
|
[ action.payload.submissionId ]: Object.assign({}, state[ action.payload.submissionId ], {
|
||||||
sections: Object.assign({}, state[ action.payload.submissionId ].sections, {
|
sections: Object.assign({}, state[ action.payload.submissionId ].sections, {
|
||||||
[ action.payload.sectionId ]: Object.assign({}, state[ action.payload.submissionId ].sections [ action.payload.sectionId ], {
|
[ action.payload.sectionId ]: Object.assign({}, state[ action.payload.submissionId ].sections [ action.payload.sectionId ], {
|
||||||
errors: []
|
errorsToShow: []
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -644,9 +656,10 @@ function initSection(state: SubmissionObjectState, action: InitSectionAction): S
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: action.payload.enabled,
|
enabled: action.payload.enabled,
|
||||||
data: action.payload.data,
|
data: action.payload.data,
|
||||||
errors: action.payload.errors || [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: action.payload.errors || [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: isEmpty(action.payload.errors)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -702,7 +715,8 @@ function updateSectionData(state: SubmissionObjectState, action: UpdateSectionDa
|
|||||||
[ action.payload.sectionId ]: Object.assign({}, state[ action.payload.submissionId ].sections [ action.payload.sectionId ], {
|
[ action.payload.sectionId ]: Object.assign({}, state[ action.payload.submissionId ].sections [ action.payload.sectionId ], {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: action.payload.data,
|
data: action.payload.data,
|
||||||
errors: action.payload.errors,
|
errorsToShow: action.payload.errorsToShow,
|
||||||
|
serverValidationErrors: action.payload.serverValidationErrors,
|
||||||
metadata: reduceSectionMetadata(action.payload.metadata, state[ action.payload.submissionId ].sections [ action.payload.sectionId ].metadata)
|
metadata: reduceSectionMetadata(action.payload.metadata, state[ action.payload.submissionId ].sections [ action.payload.sectionId ].metadata)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@@ -27,7 +27,8 @@ describe('SubmissionSectionCcLicensesComponent', () => {
|
|||||||
config: 'test config',
|
config: 'test config',
|
||||||
mandatory: true,
|
mandatory: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
header: 'test header',
|
header: 'test header',
|
||||||
id: 'test section id',
|
id: 'test section id',
|
||||||
sectionType: SectionsType.SubmissionForm
|
sectionType: SectionsType.SubmissionForm
|
||||||
|
@@ -1,11 +1,7 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
import { Observable, of as observableOf, Subscription } from 'rxjs';
|
import { Observable, of as observableOf, Subscription } from 'rxjs';
|
||||||
import {
|
import { Field, Option, SubmissionCcLicence } from '../../../core/submission/models/submission-cc-license.model';
|
||||||
Field,
|
import { getFirstSucceededRemoteData, getRemoteDataPayload } from '../../../core/shared/operators';
|
||||||
Option,
|
|
||||||
SubmissionCcLicence
|
|
||||||
} from '../../../core/submission/models/submission-cc-license.model';
|
|
||||||
import { getRemoteDataPayload, getFirstSucceededRemoteData } from '../../../core/shared/operators';
|
|
||||||
import { distinctUntilChanged, filter, map, take } from 'rxjs/operators';
|
import { distinctUntilChanged, filter, map, take } from 'rxjs/operators';
|
||||||
import { SubmissionCcLicenseDataService } from '../../../core/submission/submission-cc-license-data.service';
|
import { SubmissionCcLicenseDataService } from '../../../core/submission/submission-cc-license-data.service';
|
||||||
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
|
||||||
@@ -234,7 +230,7 @@ export class SubmissionSectionCcLicensesComponent extends SectionModelComponent
|
|||||||
this.subscriptions.push(
|
this.subscriptions.push(
|
||||||
this.sectionService.getSectionState(this.submissionId, this.sectionData.id, SectionsType.CcLicense).pipe(
|
this.sectionService.getSectionState(this.submissionId, this.sectionData.id, SectionsType.CcLicense).pipe(
|
||||||
filter((sectionState) => {
|
filter((sectionState) => {
|
||||||
return isNotEmpty(sectionState) && (isNotEmpty(sectionState.data) || isNotEmpty(sectionState.errors));
|
return isNotEmpty(sectionState) && (isNotEmpty(sectionState.data) || isNotEmpty(sectionState.errorsToShow));
|
||||||
}),
|
}),
|
||||||
distinctUntilChanged(),
|
distinctUntilChanged(),
|
||||||
map((sectionState) => sectionState.data as WorkspaceitemSectionCcLicenseObject),
|
map((sectionState) => sectionState.data as WorkspaceitemSectionCcLicenseObject),
|
||||||
|
@@ -22,11 +22,12 @@ const sectionState = {
|
|||||||
header: 'submit.progressbar.describe.stepone',
|
header: 'submit.progressbar.describe.stepone',
|
||||||
config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone',
|
config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone',
|
||||||
mandatory: true,
|
mandatory: true,
|
||||||
sectionType: 'submission-form',
|
sectionType: SectionsType.SubmissionForm,
|
||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
} as any;
|
} as any;
|
||||||
@@ -35,7 +36,8 @@ const sectionObject: SectionDataObject = {
|
|||||||
config: 'https://dspace7.4science.it/or2018/api/config/submissionforms/traditionalpageone',
|
config: 'https://dspace7.4science.it/or2018/api/config/submissionforms/traditionalpageone',
|
||||||
mandatory: true,
|
mandatory: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
header: 'submit.progressbar.describe.stepone',
|
header: 'submit.progressbar.describe.stepone',
|
||||||
id: 'traditionalpageone',
|
id: 'traditionalpageone',
|
||||||
sectionType: SectionsType.SubmissionForm
|
sectionType: SectionsType.SubmissionForm
|
||||||
@@ -56,6 +58,7 @@ describe('SubmissionSectionContainerComponent test suite', () => {
|
|||||||
function init() {
|
function init() {
|
||||||
sectionsServiceStub.isSectionValid.and.returnValue(observableOf(true));
|
sectionsServiceStub.isSectionValid.and.returnValue(observableOf(true));
|
||||||
sectionsServiceStub.getSectionState.and.returnValue(observableOf(sectionState));
|
sectionsServiceStub.getSectionState.and.returnValue(observableOf(sectionState));
|
||||||
|
sectionsServiceStub.getShownSectionErrors.and.returnValue(observableOf([]));
|
||||||
submissionServiceStub.getActiveSectionId.and.returnValue(observableOf('traditionalpageone'));
|
submissionServiceStub.getActiveSectionId.and.returnValue(observableOf('traditionalpageone'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -300,7 +300,6 @@ export class SectionFormOperationsService {
|
|||||||
|
|
||||||
const path = this.getFieldPathFromEvent(event);
|
const path = this.getFieldPathFromEvent(event);
|
||||||
const value = this.getFieldValueFromChangeEvent(event);
|
const value = this.getFieldValueFromChangeEvent(event);
|
||||||
console.log(value);
|
|
||||||
if (this.formBuilder.isQualdropGroup(event.model as DynamicFormControlModel)) {
|
if (this.formBuilder.isQualdropGroup(event.model as DynamicFormControlModel)) {
|
||||||
this.dispatchOperationsFromMap(this.getQualdropValueMap(event), pathCombiner, event, previousValue);
|
this.dispatchOperationsFromMap(this.getQualdropValueMap(event), pathCombiner, event, previousValue);
|
||||||
} else if (event.context && event.context instanceof DynamicFormArrayGroupModel) {
|
} else if (event.context && event.context instanceof DynamicFormArrayGroupModel) {
|
||||||
|
@@ -44,6 +44,7 @@ import { SubmissionObjectDataService } from '../../../core/submission/submission
|
|||||||
import { ObjectCacheService } from '../../../core/cache/object-cache.service';
|
import { ObjectCacheService } from '../../../core/cache/object-cache.service';
|
||||||
import { RequestService } from '../../../core/data/request.service';
|
import { RequestService } from '../../../core/data/request.service';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
||||||
|
import { cold } from 'jasmine-marbles';
|
||||||
|
|
||||||
function getMockSubmissionFormsConfigService(): SubmissionFormsConfigService {
|
function getMockSubmissionFormsConfigService(): SubmissionFormsConfigService {
|
||||||
return jasmine.createSpyObj('FormOperationsService', {
|
return jasmine.createSpyObj('FormOperationsService', {
|
||||||
@@ -59,7 +60,8 @@ const sectionObject: SectionDataObject = {
|
|||||||
config: 'https://dspace7.4science.it/or2018/api/config/submissionforms/traditionalpageone',
|
config: 'https://dspace7.4science.it/or2018/api/config/submissionforms/traditionalpageone',
|
||||||
mandatory: true,
|
mandatory: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
header: 'submit.progressbar.describe.stepone',
|
header: 'submit.progressbar.describe.stepone',
|
||||||
id: 'traditionalpageone',
|
id: 'traditionalpageone',
|
||||||
sectionType: SectionsType.SubmissionForm
|
sectionType: SectionsType.SubmissionForm
|
||||||
@@ -200,6 +202,7 @@ describe('SubmissionSectionformComponent test suite', () => {
|
|||||||
formService.isValid.and.returnValue(observableOf(true));
|
formService.isValid.and.returnValue(observableOf(true));
|
||||||
formConfigService.findByHref.and.returnValue(observableOf(testFormConfiguration));
|
formConfigService.findByHref.and.returnValue(observableOf(testFormConfiguration));
|
||||||
sectionsServiceStub.getSectionData.and.returnValue(observableOf(sectionData));
|
sectionsServiceStub.getSectionData.and.returnValue(observableOf(sectionData));
|
||||||
|
sectionsServiceStub.getSectionServerErrors.and.returnValue(observableOf([]));
|
||||||
|
|
||||||
const html = `
|
const html = `
|
||||||
<ds-submission-section-form></ds-submission-section-form>`;
|
<ds-submission-section-form></ds-submission-section-form>`;
|
||||||
@@ -246,6 +249,7 @@ describe('SubmissionSectionformComponent test suite', () => {
|
|||||||
formService.isValid.and.returnValue(observableOf(true));
|
formService.isValid.and.returnValue(observableOf(true));
|
||||||
formConfigService.findByHref.and.returnValue(createSuccessfulRemoteDataObject$(testFormConfiguration));
|
formConfigService.findByHref.and.returnValue(createSuccessfulRemoteDataObject$(testFormConfiguration));
|
||||||
sectionsServiceStub.getSectionData.and.returnValue(observableOf(sectionData));
|
sectionsServiceStub.getSectionData.and.returnValue(observableOf(sectionData));
|
||||||
|
sectionsServiceStub.getSectionServerErrors.and.returnValue(observableOf([]));
|
||||||
spyOn(comp, 'initForm');
|
spyOn(comp, 'initForm');
|
||||||
spyOn(comp, 'subscriptions');
|
spyOn(comp, 'subscriptions');
|
||||||
|
|
||||||
@@ -253,7 +257,7 @@ describe('SubmissionSectionformComponent test suite', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(compAsAny.formConfig).toEqual(testFormConfiguration);
|
expect(compAsAny.formConfig).toEqual(testFormConfiguration);
|
||||||
expect(comp.sectionData.errors).toEqual([]);
|
expect(comp.sectionData.errorsToShow).toEqual([]);
|
||||||
expect(comp.sectionData.data).toEqual(sectionData);
|
expect(comp.sectionData.data).toEqual(sectionData);
|
||||||
expect(comp.isLoading).toBeFalsy();
|
expect(comp.isLoading).toBeFalsy();
|
||||||
expect(comp.initForm).toHaveBeenCalledWith(sectionData);
|
expect(comp.initForm).toHaveBeenCalledWith(sectionData);
|
||||||
@@ -322,7 +326,7 @@ describe('SubmissionSectionformComponent test suite', () => {
|
|||||||
};
|
};
|
||||||
const sectionError = [];
|
const sectionError = [];
|
||||||
comp.sectionData.data = {};
|
comp.sectionData.data = {};
|
||||||
comp.sectionData.errors = [];
|
comp.sectionData.errorsToShow = [];
|
||||||
compAsAny.formData = {};
|
compAsAny.formData = {};
|
||||||
compAsAny.sectionMetadata = ['dc.title'];
|
compAsAny.sectionMetadata = ['dc.title'];
|
||||||
|
|
||||||
@@ -342,7 +346,7 @@ describe('SubmissionSectionformComponent test suite', () => {
|
|||||||
'dc.title': [new FormFieldMetadataValueObject('test')]
|
'dc.title': [new FormFieldMetadataValueObject('test')]
|
||||||
};
|
};
|
||||||
comp.sectionData.data = {};
|
comp.sectionData.data = {};
|
||||||
comp.sectionData.errors = [];
|
comp.sectionData.errorsToShow = [];
|
||||||
compAsAny.formData = sectionData;
|
compAsAny.formData = sectionData;
|
||||||
compAsAny.sectionMetadata = ['dc.title'];
|
compAsAny.sectionMetadata = ['dc.title'];
|
||||||
|
|
||||||
@@ -368,7 +372,8 @@ describe('SubmissionSectionformComponent test suite', () => {
|
|||||||
it('should check for error', () => {
|
it('should check for error', () => {
|
||||||
comp.isUpdating = false;
|
comp.isUpdating = false;
|
||||||
comp.formId = 'test';
|
comp.formId = 'test';
|
||||||
comp.sectionData.errors = [];
|
comp.sectionData.errorsToShow = [];
|
||||||
|
comp.sectionData.serverValidationErrors = [];
|
||||||
|
|
||||||
comp.checksForErrors(parsedSectionErrors);
|
comp.checksForErrors(parsedSectionErrors);
|
||||||
|
|
||||||
@@ -379,7 +384,37 @@ describe('SubmissionSectionformComponent test suite', () => {
|
|||||||
parsedSectionErrors,
|
parsedSectionErrors,
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
expect(comp.sectionData.errors).toEqual(parsedSectionErrors);
|
expect(comp.sectionData.errorsToShow).toEqual(parsedSectionErrors);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a valid status when form is valid and there are no server validation errors', () => {
|
||||||
|
formService.isValid.and.returnValue(observableOf(true));
|
||||||
|
sectionsServiceStub.getSectionServerErrors.and.returnValue(observableOf([]));
|
||||||
|
const expected = cold('(b|)', {
|
||||||
|
b: true
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(compAsAny.getSectionStatus()).toBeObservable(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an invalid status when form is valid and there are server validation errors', () => {
|
||||||
|
formService.isValid.and.returnValue(observableOf(true));
|
||||||
|
sectionsServiceStub.getSectionServerErrors.and.returnValue(observableOf(parsedSectionErrors));
|
||||||
|
const expected = cold('(b|)', {
|
||||||
|
b: false
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(compAsAny.getSectionStatus()).toBeObservable(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an invalid status when form is not valid and there are no server validation errors', () => {
|
||||||
|
formService.isValid.and.returnValue(observableOf(false));
|
||||||
|
sectionsServiceStub.getSectionServerErrors.and.returnValue(observableOf([]));
|
||||||
|
const expected = cold('(b|)', {
|
||||||
|
b: false
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(compAsAny.getSectionStatus()).toBeObservable(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should subscribe to state properly', () => {
|
it('should subscribe to state properly', () => {
|
||||||
@@ -392,7 +427,7 @@ describe('SubmissionSectionformComponent test suite', () => {
|
|||||||
};
|
};
|
||||||
const sectionState = {
|
const sectionState = {
|
||||||
data: sectionData,
|
data: sectionData,
|
||||||
errors: parsedSectionErrors
|
errorsToShow: parsedSectionErrors
|
||||||
};
|
};
|
||||||
|
|
||||||
formService.getFormData.and.returnValue(observableOf(formData));
|
formService.getFormData.and.returnValue(observableOf(formData));
|
||||||
@@ -402,7 +437,7 @@ describe('SubmissionSectionformComponent test suite', () => {
|
|||||||
|
|
||||||
expect(compAsAny.subs.length).toBe(2);
|
expect(compAsAny.subs.length).toBe(2);
|
||||||
expect(compAsAny.formData).toEqual(formData);
|
expect(compAsAny.formData).toEqual(formData);
|
||||||
expect(comp.updateForm).toHaveBeenCalledWith(sectionState.data, sectionState.errors);
|
expect(comp.updateForm).toHaveBeenCalledWith(sectionState.data, sectionState.errorsToShow);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -2,15 +2,7 @@ import { ChangeDetectorRef, Component, Inject, ViewChild } from '@angular/core';
|
|||||||
import { DynamicFormControlEvent, DynamicFormControlModel } from '@ng-dynamic-forms/core';
|
import { DynamicFormControlEvent, DynamicFormControlModel } from '@ng-dynamic-forms/core';
|
||||||
|
|
||||||
import { combineLatest as observableCombineLatest, Observable, Subscription } from 'rxjs';
|
import { combineLatest as observableCombineLatest, Observable, Subscription } from 'rxjs';
|
||||||
import {
|
import { distinctUntilChanged, filter, find, map, mergeMap, take, tap } from 'rxjs/operators';
|
||||||
distinctUntilChanged,
|
|
||||||
filter,
|
|
||||||
find,
|
|
||||||
map,
|
|
||||||
take,
|
|
||||||
tap,
|
|
||||||
mergeMap
|
|
||||||
} from 'rxjs/operators';
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { findIndex, isEqual } from 'lodash';
|
import { findIndex, isEqual } from 'lodash';
|
||||||
|
|
||||||
@@ -19,7 +11,7 @@ import { FormComponent } from '../../../shared/form/form.component';
|
|||||||
import { FormService } from '../../../shared/form/form.service';
|
import { FormService } from '../../../shared/form/form.service';
|
||||||
import { SectionModelComponent } from '../models/section.model';
|
import { SectionModelComponent } from '../models/section.model';
|
||||||
import { SubmissionFormsConfigService } from '../../../core/config/submission-forms-config.service';
|
import { SubmissionFormsConfigService } from '../../../core/config/submission-forms-config.service';
|
||||||
import { hasValue, isNotEmpty, isUndefined } from '../../../shared/empty.util';
|
import { hasValue, isEmpty, isNotEmpty, isUndefined } from '../../../shared/empty.util';
|
||||||
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
|
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
|
||||||
import { SubmissionFormsModel } from '../../../core/config/models/config-submission-forms.model';
|
import { SubmissionFormsModel } from '../../../core/config/models/config-submission-forms.model';
|
||||||
import { SubmissionSectionError, SubmissionSectionObject } from '../../objects/submission-objects.reducer';
|
import { SubmissionSectionError, SubmissionSectionObject } from '../../objects/submission-objects.reducer';
|
||||||
@@ -183,7 +175,7 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
|||||||
take(1))
|
take(1))
|
||||||
.subscribe(([sectionData, workspaceItem]: [WorkspaceitemSectionFormObject, WorkspaceItem]) => {
|
.subscribe(([sectionData, workspaceItem]: [WorkspaceitemSectionFormObject, WorkspaceItem]) => {
|
||||||
if (isUndefined(this.formModel)) {
|
if (isUndefined(this.formModel)) {
|
||||||
this.sectionData.errors = [];
|
// this.sectionData.errorsToShow = [];
|
||||||
this.workspaceItem = workspaceItem;
|
this.workspaceItem = workspaceItem;
|
||||||
// Is the first loading so init form
|
// Is the first loading so init form
|
||||||
this.initForm(sectionData);
|
this.initForm(sectionData);
|
||||||
@@ -211,7 +203,14 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
|||||||
* the section status
|
* the section status
|
||||||
*/
|
*/
|
||||||
protected getSectionStatus(): Observable<boolean> {
|
protected getSectionStatus(): Observable<boolean> {
|
||||||
return this.formService.isValid(this.formId);
|
const formStatus$ = this.formService.isValid(this.formId);
|
||||||
|
const serverValidationStatus$ = this.sectionService.getSectionServerErrors(this.submissionId, this.sectionData.id).pipe(
|
||||||
|
map((validationErrors) => isEmpty(validationErrors))
|
||||||
|
);
|
||||||
|
|
||||||
|
return observableCombineLatest([formStatus$, serverValidationStatus$]).pipe(
|
||||||
|
map(([formValidation, serverSideValidation]: [boolean, boolean]) => formValidation && serverSideValidation)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -263,7 +262,7 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
|||||||
this.submissionService.getSubmissionScope()
|
this.submissionService.getSubmissionScope()
|
||||||
);
|
);
|
||||||
const sectionMetadata = this.sectionService.computeSectionConfiguredMetadata(this.formConfig);
|
const sectionMetadata = this.sectionService.computeSectionConfiguredMetadata(this.formConfig);
|
||||||
this.sectionService.updateSectionData(this.submissionId, this.sectionData.id, sectionData, [], sectionMetadata);
|
this.sectionService.updateSectionData(this.submissionId, this.sectionData.id, sectionData, this.sectionData.errorsToShow, this.sectionData.serverValidationErrors, sectionMetadata);
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const msg: string = this.translate.instant('error.submission.sections.init-form-error') + e.toString();
|
const msg: string = this.translate.instant('error.submission.sections.init-form-error') + e.toString();
|
||||||
@@ -296,10 +295,10 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
|||||||
this.checksForErrors(errors);
|
this.checksForErrors(errors);
|
||||||
this.isUpdating = false;
|
this.isUpdating = false;
|
||||||
this.cdr.detectChanges();
|
this.cdr.detectChanges();
|
||||||
} else if (isNotEmpty(errors) || isNotEmpty(this.sectionData.errors)) {
|
} else if (isNotEmpty(errors) || isNotEmpty(this.sectionData.errorsToShow)) {
|
||||||
this.checksForErrors(errors);
|
this.checksForErrors(errors);
|
||||||
}
|
}
|
||||||
} else if (isNotEmpty(errors) || isNotEmpty(this.sectionData.errors)) {
|
} else if (isNotEmpty(errors) || isNotEmpty(this.sectionData.errorsToShow)) {
|
||||||
this.checksForErrors(errors);
|
this.checksForErrors(errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,8 +314,8 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
|||||||
this.formService.isFormInitialized(this.formId).pipe(
|
this.formService.isFormInitialized(this.formId).pipe(
|
||||||
find((status: boolean) => status === true && !this.isUpdating))
|
find((status: boolean) => status === true && !this.isUpdating))
|
||||||
.subscribe(() => {
|
.subscribe(() => {
|
||||||
this.sectionService.checkSectionErrors(this.submissionId, this.sectionData.id, this.formId, errors, this.sectionData.errors);
|
this.sectionService.checkSectionErrors(this.submissionId, this.sectionData.id, this.formId, errors, this.sectionData.errorsToShow);
|
||||||
this.sectionData.errors = errors;
|
this.sectionData.errorsToShow = errors;
|
||||||
this.cdr.detectChanges();
|
this.cdr.detectChanges();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -340,13 +339,13 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
|||||||
*/
|
*/
|
||||||
this.sectionService.getSectionState(this.submissionId, this.sectionData.id, this.sectionData.sectionType).pipe(
|
this.sectionService.getSectionState(this.submissionId, this.sectionData.id, this.sectionData.sectionType).pipe(
|
||||||
filter((sectionState: SubmissionSectionObject) => {
|
filter((sectionState: SubmissionSectionObject) => {
|
||||||
return isNotEmpty(sectionState) && (isNotEmpty(sectionState.data) || isNotEmpty(sectionState.errors));
|
return isNotEmpty(sectionState) && (isNotEmpty(sectionState.data) || isNotEmpty(sectionState.errorsToShow));
|
||||||
}),
|
}),
|
||||||
distinctUntilChanged())
|
distinctUntilChanged())
|
||||||
.subscribe((sectionState: SubmissionSectionObject) => {
|
.subscribe((sectionState: SubmissionSectionObject) => {
|
||||||
this.fieldsOnTheirWayToBeRemoved = new Map();
|
this.fieldsOnTheirWayToBeRemoved = new Map();
|
||||||
this.sectionMetadata = sectionState.metadata;
|
this.sectionMetadata = sectionState.metadata;
|
||||||
this.updateForm(sectionState.data as WorkspaceitemSectionFormObject, sectionState.errors);
|
this.updateForm(sectionState.data as WorkspaceitemSectionFormObject, sectionState.errorsToShow);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -367,11 +366,22 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
|||||||
const metadata = this.formOperationsService.getFieldPathSegmentedFromChangeEvent(event);
|
const metadata = this.formOperationsService.getFieldPathSegmentedFromChangeEvent(event);
|
||||||
const value = this.formOperationsService.getFieldValueFromChangeEvent(event);
|
const value = this.formOperationsService.getFieldValueFromChangeEvent(event);
|
||||||
|
|
||||||
if (environment.submission.autosave.metadata.indexOf(metadata) !== -1 && isNotEmpty(value)) {
|
if ((environment.submission.autosave.metadata.indexOf(metadata) !== -1 && isNotEmpty(value)) || this.hasRelatedCustomError(metadata)) {
|
||||||
this.submissionService.dispatchSave(this.submissionId);
|
this.submissionService.dispatchSave(this.submissionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private hasRelatedCustomError(medatata): boolean {
|
||||||
|
const index = findIndex(this.sectionData.errorsToShow, {path: this.pathCombiner.getPath(medatata).path});
|
||||||
|
if (index !== -1) {
|
||||||
|
const error = this.sectionData.errorsToShow[index];
|
||||||
|
const validator = error.message.replace('error.validation.', '');
|
||||||
|
return !environment.form.validatorMap.hasOwnProperty(validator);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called when a form dfFocus event is fired.
|
* Method called when a form dfFocus event is fired.
|
||||||
* Initialize [FormFieldPreviousValueObject] instance.
|
* Initialize [FormFieldPreviousValueObject] instance.
|
||||||
|
@@ -70,7 +70,8 @@ const sectionObject: SectionDataObject = {
|
|||||||
acceptanceDate: null,
|
acceptanceDate: null,
|
||||||
granted: false
|
granted: false
|
||||||
},
|
},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
header: 'submit.progressbar.describe.license',
|
header: 'submit.progressbar.describe.license',
|
||||||
id: 'license',
|
id: 'license',
|
||||||
sectionType: SectionsType.License
|
sectionType: SectionsType.License
|
||||||
|
@@ -18,9 +18,14 @@ export interface SectionDataObject {
|
|||||||
data: WorkspaceitemSectionDataType;
|
data: WorkspaceitemSectionDataType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of the section errors
|
* The list of the section's errors to show
|
||||||
*/
|
*/
|
||||||
errors: SubmissionSectionError[];
|
errorsToShow: SubmissionSectionError[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of the section's errors detected by the server
|
||||||
|
*/
|
||||||
|
serverValidationErrors: SubmissionSectionError[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The section header
|
* The section header
|
||||||
|
@@ -6,7 +6,7 @@ import { uniq } from 'lodash';
|
|||||||
|
|
||||||
import { SectionsService } from './sections.service';
|
import { SectionsService } from './sections.service';
|
||||||
import { hasValue, isNotEmpty, isNotNull } from '../../shared/empty.util';
|
import { hasValue, isNotEmpty, isNotNull } from '../../shared/empty.util';
|
||||||
import { SubmissionSectionError, SubmissionSectionObject } from '../objects/submission-objects.reducer';
|
import { SubmissionSectionError } from '../objects/submission-objects.reducer';
|
||||||
import parseSectionErrorPaths, { SectionErrorPath } from '../utils/parseSectionErrorPaths';
|
import parseSectionErrorPaths, { SectionErrorPath } from '../utils/parseSectionErrorPaths';
|
||||||
import { SubmissionService } from '../submission.service';
|
import { SubmissionService } from '../submission.service';
|
||||||
import { SectionsType } from './sections-type';
|
import { SectionsType } from './sections-type';
|
||||||
@@ -111,8 +111,7 @@ export class SectionsDirective implements OnDestroy, OnInit {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
this.subs.push(
|
this.subs.push(
|
||||||
this.sectionService.getSectionState(this.submissionId, this.sectionId, this.sectionType).pipe(
|
this.sectionService.getShownSectionErrors(this.submissionId, this.sectionId, this.sectionType)
|
||||||
map((state: SubmissionSectionObject) => state.errors))
|
|
||||||
.subscribe((errors: SubmissionSectionError[]) => {
|
.subscribe((errors: SubmissionSectionError[]) => {
|
||||||
if (isNotEmpty(errors)) {
|
if (isNotEmpty(errors)) {
|
||||||
errors.forEach((errorItem: SubmissionSectionError) => {
|
errors.forEach((errorItem: SubmissionSectionError) => {
|
||||||
|
@@ -28,13 +28,15 @@ import {
|
|||||||
SectionStatusChangeAction,
|
SectionStatusChangeAction,
|
||||||
UpdateSectionDataAction
|
UpdateSectionDataAction
|
||||||
} from '../objects/submission-objects.actions';
|
} from '../objects/submission-objects.actions';
|
||||||
import { FormAddError, FormClearErrorsAction, FormRemoveErrorAction } from '../../shared/form/form.actions';
|
import { FormClearErrorsAction } from '../../shared/form/form.actions';
|
||||||
import parseSectionErrors from '../utils/parseSectionErrors';
|
import parseSectionErrors from '../utils/parseSectionErrors';
|
||||||
import { SubmissionScopeType } from '../../core/submission/submission-scope-type';
|
import { SubmissionScopeType } from '../../core/submission/submission-scope-type';
|
||||||
import { SubmissionSectionError } from '../objects/submission-objects.reducer';
|
import { SubmissionSectionError } from '../objects/submission-objects.reducer';
|
||||||
import { getMockScrollToService } from '../../shared/mocks/scroll-to-service.mock';
|
import { getMockScrollToService } from '../../shared/mocks/scroll-to-service.mock';
|
||||||
import { storeModuleConfig } from '../../app.reducer';
|
import { storeModuleConfig } from '../../app.reducer';
|
||||||
import { SectionsType } from './sections-type';
|
import { SectionsType } from './sections-type';
|
||||||
|
import { FormService } from '../../shared/form/form.service';
|
||||||
|
import { getMockFormService } from '../../shared/mocks/form-service.mock';
|
||||||
|
|
||||||
describe('SectionsService test suite', () => {
|
describe('SectionsService test suite', () => {
|
||||||
let notificationsServiceStub: NotificationsServiceStub;
|
let notificationsServiceStub: NotificationsServiceStub;
|
||||||
@@ -57,6 +59,8 @@ describe('SectionsService test suite', () => {
|
|||||||
select: jasmine.createSpy('select')
|
select: jasmine.createSpy('select')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const formService: any = getMockFormService();
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -74,6 +78,7 @@ describe('SectionsService test suite', () => {
|
|||||||
{ provide: SubmissionService, useClass: SubmissionServiceStub },
|
{ provide: SubmissionService, useClass: SubmissionServiceStub },
|
||||||
{ provide: TranslateService, useValue: getMockTranslateService() },
|
{ provide: TranslateService, useValue: getMockTranslateService() },
|
||||||
{ provide: Store, useValue: store },
|
{ provide: Store, useValue: store },
|
||||||
|
{ provide: FormService, useValue: formService },
|
||||||
SectionsService
|
SectionsService
|
||||||
]
|
]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
@@ -98,22 +103,23 @@ describe('SectionsService test suite', () => {
|
|||||||
it('should dispatch a new FormAddError for each section\'s error', () => {
|
it('should dispatch a new FormAddError for each section\'s error', () => {
|
||||||
service.checkSectionErrors(submissionId, sectionId, formId, sectionErrors[sectionId]);
|
service.checkSectionErrors(submissionId, sectionId, formId, sectionErrors[sectionId]);
|
||||||
|
|
||||||
expect(store.dispatch).toHaveBeenCalledWith(new FormAddError(
|
expect(formService.addError).toHaveBeenCalledWith(
|
||||||
formId,
|
formId,
|
||||||
'dc_contributor_author',
|
'dc.contributor.author',
|
||||||
0,
|
0,
|
||||||
'error.validation.required'));
|
'error.validation.required');
|
||||||
|
|
||||||
expect(store.dispatch).toHaveBeenCalledWith(new FormAddError(
|
expect(formService.addError).toHaveBeenCalledWith(
|
||||||
formId,
|
formId,
|
||||||
'dc_title',
|
'dc.title',
|
||||||
0,
|
0,
|
||||||
'error.validation.required'));
|
'error.validation.required');
|
||||||
|
|
||||||
expect(store.dispatch).toHaveBeenCalledWith(new FormAddError(formId,
|
expect(formService.addError).toHaveBeenCalledWith(
|
||||||
'dc_date_issued',
|
formId,
|
||||||
|
'dc.date.issued',
|
||||||
0,
|
0,
|
||||||
'error.validation.required'));
|
'error.validation.required');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should dispatch a new FormRemoveErrorAction for each section\'s error that no longer exists', () => {
|
it('should dispatch a new FormRemoveErrorAction for each section\'s error that no longer exists', () => {
|
||||||
@@ -123,21 +129,21 @@ describe('SectionsService test suite', () => {
|
|||||||
|
|
||||||
service.checkSectionErrors(submissionId, sectionId, formId, currentErrors, prevErrors);
|
service.checkSectionErrors(submissionId, sectionId, formId, currentErrors, prevErrors);
|
||||||
|
|
||||||
expect(store.dispatch).toHaveBeenCalledWith(new FormAddError(
|
expect(formService.addError).toHaveBeenCalledWith(
|
||||||
formId,
|
formId,
|
||||||
'dc_contributor_author',
|
'dc.contributor.author',
|
||||||
0,
|
0,
|
||||||
'error.validation.required'));
|
'error.validation.required');
|
||||||
|
|
||||||
expect(store.dispatch).toHaveBeenCalledWith(new FormAddError(
|
expect(formService.addError).toHaveBeenCalledWith(
|
||||||
formId,
|
formId,
|
||||||
'dc_title',
|
'dc.title',
|
||||||
0,
|
0,
|
||||||
'error.validation.required'));
|
'error.validation.required');
|
||||||
expect(store.dispatch).toHaveBeenCalledWith(new FormRemoveErrorAction(
|
expect(formService.removeError).toHaveBeenCalledWith(
|
||||||
formId,
|
formId,
|
||||||
'dc_date_issued',
|
'dc.date.issued',
|
||||||
0));
|
0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -417,7 +423,7 @@ describe('SectionsService test suite', () => {
|
|||||||
scheduler.schedule(() => service.updateSectionData(submissionId, sectionId, data, []));
|
scheduler.schedule(() => service.updateSectionData(submissionId, sectionId, data, []));
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect(store.dispatch).toHaveBeenCalledWith(new UpdateSectionDataAction(submissionId, sectionId, data, []));
|
expect(store.dispatch).toHaveBeenCalledWith(new UpdateSectionDataAction(submissionId, sectionId, data, [], []));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should dispatch a new UpdateSectionDataAction and display a new notification when section is not enabled', () => {
|
it('should dispatch a new UpdateSectionDataAction and display a new notification when section is not enabled', () => {
|
||||||
@@ -429,7 +435,7 @@ describe('SectionsService test suite', () => {
|
|||||||
scheduler.schedule(() => service.updateSectionData(submissionId, sectionId, data, []));
|
scheduler.schedule(() => service.updateSectionData(submissionId, sectionId, data, []));
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect(store.dispatch).toHaveBeenCalledWith(new UpdateSectionDataAction(submissionId, sectionId, data, []));
|
expect(store.dispatch).toHaveBeenCalledWith(new UpdateSectionDataAction(submissionId, sectionId, data, [], []));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { combineLatest, Observable } from 'rxjs';
|
import { combineLatest, Observable } from 'rxjs';
|
||||||
import { distinctUntilChanged, filter, map, take } from 'rxjs/operators';
|
import { distinctUntilChanged, filter, map, mergeMap, take } from 'rxjs/operators';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { ScrollToConfigOptions, ScrollToService } from '@nicky-lenaers/ngx-scroll-to';
|
import { ScrollToConfigOptions, ScrollToService } from '@nicky-lenaers/ngx-scroll-to';
|
||||||
import { findKey, isEqual } from 'lodash';
|
import { findIndex, findKey, isEqual } from 'lodash';
|
||||||
|
|
||||||
import { SubmissionState } from '../submission.reducers';
|
import { SubmissionState } from '../submission.reducers';
|
||||||
import { hasValue, isEmpty, isNotEmpty, isNotUndefined } from '../../shared/empty.util';
|
import { hasValue, isEmpty, isNotEmpty, isNotUndefined } from '../../shared/empty.util';
|
||||||
@@ -27,11 +27,12 @@ import {
|
|||||||
submissionObjectFromIdSelector,
|
submissionObjectFromIdSelector,
|
||||||
submissionSectionDataFromIdSelector,
|
submissionSectionDataFromIdSelector,
|
||||||
submissionSectionErrorsFromIdSelector,
|
submissionSectionErrorsFromIdSelector,
|
||||||
submissionSectionFromIdSelector
|
submissionSectionFromIdSelector,
|
||||||
|
submissionSectionServerErrorsFromIdSelector
|
||||||
} from '../selectors';
|
} from '../selectors';
|
||||||
import { SubmissionScopeType } from '../../core/submission/submission-scope-type';
|
import { SubmissionScopeType } from '../../core/submission/submission-scope-type';
|
||||||
import parseSectionErrorPaths, { SectionErrorPath } from '../utils/parseSectionErrorPaths';
|
import parseSectionErrorPaths, { SectionErrorPath } from '../utils/parseSectionErrorPaths';
|
||||||
import { FormAddError, FormClearErrorsAction, FormRemoveErrorAction } from '../../shared/form/form.actions';
|
import { FormClearErrorsAction } from '../../shared/form/form.actions';
|
||||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||||
import { SubmissionService } from '../submission.service';
|
import { SubmissionService } from '../submission.service';
|
||||||
import { WorkspaceitemSectionDataType } from '../../core/submission/models/workspaceitem-sections.model';
|
import { WorkspaceitemSectionDataType } from '../../core/submission/models/workspaceitem-sections.model';
|
||||||
@@ -39,6 +40,9 @@ import { SectionsType } from './sections-type';
|
|||||||
import { normalizeSectionData } from '../../core/submission/submission-response-parsing.service';
|
import { normalizeSectionData } from '../../core/submission/submission-response-parsing.service';
|
||||||
import { SubmissionFormsModel } from '../../core/config/models/config-submission-forms.model';
|
import { SubmissionFormsModel } from '../../core/config/models/config-submission-forms.model';
|
||||||
import { parseReviver } from '@ng-dynamic-forms/core';
|
import { parseReviver } from '@ng-dynamic-forms/core';
|
||||||
|
import { FormService } from '../../shared/form/form.service';
|
||||||
|
import { JsonPatchOperationPathCombiner } from '../../core/json-patch/builder/json-patch-operation-path-combiner';
|
||||||
|
import { FormError } from '../../shared/form/form.reducer';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A service that provides methods used in submission process.
|
* A service that provides methods used in submission process.
|
||||||
@@ -48,13 +52,15 @@ export class SectionsService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize service variables
|
* Initialize service variables
|
||||||
|
* @param {FormService} formService
|
||||||
* @param {NotificationsService} notificationsService
|
* @param {NotificationsService} notificationsService
|
||||||
* @param {ScrollToService} scrollToService
|
* @param {ScrollToService} scrollToService
|
||||||
* @param {SubmissionService} submissionService
|
* @param {SubmissionService} submissionService
|
||||||
* @param {Store<SubmissionState>} store
|
* @param {Store<SubmissionState>} store
|
||||||
* @param {TranslateService} translate
|
* @param {TranslateService} translate
|
||||||
*/
|
*/
|
||||||
constructor(private notificationsService: NotificationsService,
|
constructor(private formService: FormService,
|
||||||
|
private notificationsService: NotificationsService,
|
||||||
private scrollToService: ScrollToService,
|
private scrollToService: ScrollToService,
|
||||||
private submissionService: SubmissionService,
|
private submissionService: SubmissionService,
|
||||||
private store: Store<SubmissionState>,
|
private store: Store<SubmissionState>,
|
||||||
@@ -95,12 +101,9 @@ export class SectionsService {
|
|||||||
|
|
||||||
errorPaths.forEach((path: SectionErrorPath) => {
|
errorPaths.forEach((path: SectionErrorPath) => {
|
||||||
if (path.fieldId) {
|
if (path.fieldId) {
|
||||||
const fieldId = path.fieldId.replace(/\./g, '_');
|
|
||||||
|
|
||||||
// Dispatch action to add form error to the state;
|
// Dispatch action to add form error to the state;
|
||||||
const formAddErrorAction = new FormAddError(formId, fieldId, path.fieldIndex, error.message);
|
this.formService.addError(formId, path.fieldId, path.fieldIndex, error.message);
|
||||||
this.store.dispatch(formAddErrorAction);
|
dispatchedErrors.push(path.fieldId);
|
||||||
dispatchedErrors.push(fieldId);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -111,12 +114,9 @@ export class SectionsService {
|
|||||||
|
|
||||||
errorPaths.forEach((path: SectionErrorPath) => {
|
errorPaths.forEach((path: SectionErrorPath) => {
|
||||||
if (path.fieldId) {
|
if (path.fieldId) {
|
||||||
const fieldId = path.fieldId.replace(/\./g, '_');
|
if (!dispatchedErrors.includes(path.fieldId)) {
|
||||||
|
|
||||||
if (!dispatchedErrors.includes(fieldId)) {
|
|
||||||
// Dispatch action to remove form error from the state;
|
// Dispatch action to remove form error from the state;
|
||||||
const formRemoveErrorAction = new FormRemoveErrorAction(formId, fieldId, path.fieldIndex);
|
this.formService.removeError(formId, path.fieldId, path.fieldIndex);
|
||||||
this.store.dispatch(formRemoveErrorAction);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -174,7 +174,40 @@ export class SectionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the error list object data for the specified section
|
* Get the list of validation errors present in the given section
|
||||||
|
*
|
||||||
|
* @param submissionId
|
||||||
|
* The submission id
|
||||||
|
* @param sectionId
|
||||||
|
* The section id
|
||||||
|
* @param sectionType
|
||||||
|
* The type of section for which retrieve errors
|
||||||
|
*/
|
||||||
|
getShownSectionErrors(submissionId: string, sectionId: string, sectionType: SectionsType): Observable<SubmissionSectionError[]> {
|
||||||
|
let errorsState$: Observable<SubmissionSectionError[]>;
|
||||||
|
if (sectionType !== SectionsType.SubmissionForm) {
|
||||||
|
errorsState$ = this.getSectionErrors(submissionId, sectionId);
|
||||||
|
} else {
|
||||||
|
errorsState$ = this.getSectionState(submissionId, sectionId, sectionType).pipe(
|
||||||
|
mergeMap((state: SubmissionSectionObject) => this.formService.getFormErrors(state.formId).pipe(
|
||||||
|
map((formErrors: FormError[]) => {
|
||||||
|
const pathCombiner = new JsonPatchOperationPathCombiner('sections', sectionId);
|
||||||
|
const sectionErrors = formErrors
|
||||||
|
.map((error) => ({
|
||||||
|
path: pathCombiner.getPath(error.fieldId.replace(/\_/g, '.')).path,
|
||||||
|
message: error.message
|
||||||
|
} as SubmissionSectionError))
|
||||||
|
.filter((sectionError: SubmissionSectionError) => findIndex(state.errorsToShow, {path: sectionError.path}) === -1);
|
||||||
|
return [...state.errorsToShow, ...sectionErrors];
|
||||||
|
})
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return errorsState$;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Return the error list to show for the specified section
|
||||||
*
|
*
|
||||||
* @param submissionId
|
* @param submissionId
|
||||||
* The submission id
|
* The submission id
|
||||||
@@ -188,6 +221,21 @@ export class SectionsService {
|
|||||||
distinctUntilChanged());
|
distinctUntilChanged());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the error list detected by the server for the specified section
|
||||||
|
*
|
||||||
|
* @param submissionId
|
||||||
|
* The submission id
|
||||||
|
* @param sectionId
|
||||||
|
* The section id
|
||||||
|
* @return Observable<SubmissionSectionError>
|
||||||
|
* observable of array of [SubmissionSectionError]
|
||||||
|
*/
|
||||||
|
public getSectionServerErrors(submissionId: string, sectionId: string): Observable<SubmissionSectionError[]> {
|
||||||
|
return this.store.select(submissionSectionServerErrorsFromIdSelector(submissionId, sectionId)).pipe(
|
||||||
|
distinctUntilChanged());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the state object for the specified section
|
* Return the state object for the specified section
|
||||||
*
|
*
|
||||||
@@ -383,12 +431,23 @@ export class SectionsService {
|
|||||||
* The section id
|
* The section id
|
||||||
* @param data
|
* @param data
|
||||||
* The section data
|
* The section data
|
||||||
* @param errors
|
* @param errorsToShow
|
||||||
* The list of section errors
|
* The list of the section's errors to show. It contains the error list
|
||||||
|
* to display when section is not pristine
|
||||||
|
* @param serverValidationErrors
|
||||||
|
* The list of the section's errors detected by the server.
|
||||||
|
* They may not be shown yet if section is pristine
|
||||||
* @param metadata
|
* @param metadata
|
||||||
* The section metadata
|
* The section metadata
|
||||||
*/
|
*/
|
||||||
public updateSectionData(submissionId: string, sectionId: string, data: WorkspaceitemSectionDataType, errors: SubmissionSectionError[] = [], metadata?: string[]) {
|
public updateSectionData(
|
||||||
|
submissionId: string,
|
||||||
|
sectionId: string,
|
||||||
|
data: WorkspaceitemSectionDataType,
|
||||||
|
errorsToShow: SubmissionSectionError[] = [],
|
||||||
|
serverValidationErrors: SubmissionSectionError[] = [],
|
||||||
|
metadata?: string[]
|
||||||
|
) {
|
||||||
if (isNotEmpty(data)) {
|
if (isNotEmpty(data)) {
|
||||||
const isAvailable$ = this.isSectionAvailable(submissionId, sectionId);
|
const isAvailable$ = this.isSectionAvailable(submissionId, sectionId);
|
||||||
const isEnabled$ = this.isSectionEnabled(submissionId, sectionId);
|
const isEnabled$ = this.isSectionEnabled(submissionId, sectionId);
|
||||||
@@ -397,7 +456,7 @@ export class SectionsService {
|
|||||||
take(1),
|
take(1),
|
||||||
filter(([available, enabled]: [boolean, boolean]) => available))
|
filter(([available, enabled]: [boolean, boolean]) => available))
|
||||||
.subscribe(([available, enabled]: [boolean, boolean]) => {
|
.subscribe(([available, enabled]: [boolean, boolean]) => {
|
||||||
this.store.dispatch(new UpdateSectionDataAction(submissionId, sectionId, data, errors, metadata));
|
this.store.dispatch(new UpdateSectionDataAction(submissionId, sectionId, data, errorsToShow, serverValidationErrors, metadata));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -98,7 +98,8 @@ describe('SubmissionSectionUploadComponent test suite', () => {
|
|||||||
data: {
|
data: {
|
||||||
files: []
|
files: []
|
||||||
},
|
},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
header: 'submit.progressbar.describe.upload',
|
header: 'submit.progressbar.describe.upload',
|
||||||
id: 'upload-id',
|
id: 'upload-id',
|
||||||
sectionType: SectionsType.Upload
|
sectionType: SectionsType.Upload
|
||||||
|
@@ -61,5 +61,11 @@ export function submissionSectionDataFromIdSelector(submissionId: string, sectio
|
|||||||
|
|
||||||
export function submissionSectionErrorsFromIdSelector(submissionId: string, sectionId: string): MemoizedSelector<SubmissionState, any> {
|
export function submissionSectionErrorsFromIdSelector(submissionId: string, sectionId: string): MemoizedSelector<SubmissionState, any> {
|
||||||
const submissionIdSelector = submissionSectionFromIdSelector(submissionId, sectionId);
|
const submissionIdSelector = submissionSectionFromIdSelector(submissionId, sectionId);
|
||||||
return subStateSelector<SubmissionState, SubmissionSectionObject>(submissionIdSelector, 'errors');
|
return subStateSelector<SubmissionState, SubmissionSectionObject>(submissionIdSelector, 'errorsToShow');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function submissionSectionServerErrorsFromIdSelector(submissionId: string, sectionId: string): MemoizedSelector<SubmissionState, any> {
|
||||||
|
const submissionIdSelector = submissionSectionFromIdSelector(submissionId, sectionId);
|
||||||
|
return subStateSelector<SubmissionState, SubmissionSectionObject>(submissionIdSelector, 'serverValidationErrors');
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { StoreModule } from '@ngrx/store';
|
import { StoreModule } from '@ngrx/store';
|
||||||
import { waitForAsync, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
|
import { fakeAsync, flush, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { HttpHeaders } from '@angular/common/http';
|
import { HttpHeaders } from '@angular/common/http';
|
||||||
|
|
||||||
@@ -32,9 +32,7 @@ import {
|
|||||||
SaveSubmissionSectionFormAction,
|
SaveSubmissionSectionFormAction,
|
||||||
SetActiveSectionAction
|
SetActiveSectionAction
|
||||||
} from './objects/submission-objects.actions';
|
} from './objects/submission-objects.actions';
|
||||||
import {
|
import { createFailedRemoteDataObject, } from '../shared/remote-data.utils';
|
||||||
createFailedRemoteDataObject,
|
|
||||||
} from '../shared/remote-data.utils';
|
|
||||||
import { getMockSearchService } from '../shared/mocks/search-service.mock';
|
import { getMockSearchService } from '../shared/mocks/search-service.mock';
|
||||||
import { getMockRequestService } from '../shared/mocks/request.service.mock';
|
import { getMockRequestService } from '../shared/mocks/request.service.mock';
|
||||||
import { RequestService } from '../core/data/request.service';
|
import { RequestService } from '../core/data/request.service';
|
||||||
@@ -68,7 +66,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
},
|
},
|
||||||
@@ -83,7 +82,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
},
|
},
|
||||||
@@ -95,7 +95,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
},
|
},
|
||||||
@@ -107,7 +108,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
},
|
},
|
||||||
@@ -119,7 +121,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: true
|
isValid: true
|
||||||
},
|
},
|
||||||
@@ -131,7 +134,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
},
|
},
|
||||||
@@ -143,7 +147,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
},
|
},
|
||||||
@@ -155,7 +160,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
},
|
},
|
||||||
@@ -167,7 +173,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
},
|
},
|
||||||
@@ -183,7 +190,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
}
|
}
|
||||||
@@ -213,7 +221,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
},
|
},
|
||||||
@@ -228,7 +237,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
},
|
},
|
||||||
@@ -240,7 +250,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: true
|
isValid: true
|
||||||
},
|
},
|
||||||
@@ -252,7 +263,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
},
|
},
|
||||||
@@ -264,7 +276,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: true
|
isValid: true
|
||||||
},
|
},
|
||||||
@@ -276,7 +289,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
},
|
},
|
||||||
@@ -288,7 +302,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
},
|
},
|
||||||
@@ -300,7 +315,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
},
|
},
|
||||||
@@ -312,7 +328,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: true
|
isValid: true
|
||||||
},
|
},
|
||||||
@@ -328,7 +345,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: true
|
isValid: true
|
||||||
}
|
}
|
||||||
@@ -452,7 +470,7 @@ describe('SubmissionService test suite', () => {
|
|||||||
submissionDefinition,
|
submissionDefinition,
|
||||||
{},
|
{},
|
||||||
new Item(),
|
new Item(),
|
||||||
[]
|
null
|
||||||
);
|
);
|
||||||
const expected = new InitSubmissionFormAction(
|
const expected = new InitSubmissionFormAction(
|
||||||
collectionId,
|
collectionId,
|
||||||
@@ -461,7 +479,7 @@ describe('SubmissionService test suite', () => {
|
|||||||
submissionDefinition,
|
submissionDefinition,
|
||||||
{},
|
{},
|
||||||
new Item(),
|
new Item(),
|
||||||
[]);
|
null);
|
||||||
|
|
||||||
expect((service as any).store.dispatch).toHaveBeenCalledWith(expected);
|
expect((service as any).store.dispatch).toHaveBeenCalledWith(expected);
|
||||||
});
|
});
|
||||||
@@ -564,7 +582,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
mandatory: true,
|
mandatory: true,
|
||||||
sectionType: 'submission-form',
|
sectionType: 'submission-form',
|
||||||
data: {},
|
data: {},
|
||||||
errors: []
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'submit.progressbar.describe.indexing',
|
header: 'submit.progressbar.describe.indexing',
|
||||||
@@ -573,7 +592,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
mandatory: false,
|
mandatory: false,
|
||||||
sectionType: 'submission-form',
|
sectionType: 'submission-form',
|
||||||
data: {},
|
data: {},
|
||||||
errors: []
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'submit.progressbar.describe.publicationchannel',
|
header: 'submit.progressbar.describe.publicationchannel',
|
||||||
@@ -582,7 +602,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
mandatory: true,
|
mandatory: true,
|
||||||
sectionType: 'submission-form',
|
sectionType: 'submission-form',
|
||||||
data: {},
|
data: {},
|
||||||
errors: []
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'submit.progressbar.describe.acknowledgement',
|
header: 'submit.progressbar.describe.acknowledgement',
|
||||||
@@ -591,7 +612,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
mandatory: false,
|
mandatory: false,
|
||||||
sectionType: 'submission-form',
|
sectionType: 'submission-form',
|
||||||
data: {},
|
data: {},
|
||||||
errors: []
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'submit.progressbar.describe.identifiers',
|
header: 'submit.progressbar.describe.identifiers',
|
||||||
@@ -600,7 +622,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
mandatory: false,
|
mandatory: false,
|
||||||
sectionType: 'submission-form',
|
sectionType: 'submission-form',
|
||||||
data: {},
|
data: {},
|
||||||
errors: []
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'submit.progressbar.describe.references',
|
header: 'submit.progressbar.describe.references',
|
||||||
@@ -609,7 +632,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
mandatory: false,
|
mandatory: false,
|
||||||
sectionType: 'submission-form',
|
sectionType: 'submission-form',
|
||||||
data: {},
|
data: {},
|
||||||
errors: []
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'submit.progressbar.upload',
|
header: 'submit.progressbar.upload',
|
||||||
@@ -618,7 +642,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
mandatory: true,
|
mandatory: true,
|
||||||
sectionType: 'upload',
|
sectionType: 'upload',
|
||||||
data: {},
|
data: {},
|
||||||
errors: []
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'submit.progressbar.license',
|
header: 'submit.progressbar.license',
|
||||||
@@ -627,7 +652,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
mandatory: true,
|
mandatory: true,
|
||||||
sectionType: 'license',
|
sectionType: 'license',
|
||||||
data: {},
|
data: {},
|
||||||
errors: []
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
@@ -781,7 +807,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
};
|
};
|
||||||
@@ -795,7 +822,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
data: {},
|
data: {},
|
||||||
errors: [],
|
errorsToShow: [],
|
||||||
|
serverValidationErrors: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isValid: false
|
isValid: false
|
||||||
};
|
};
|
||||||
|
@@ -22,9 +22,9 @@ import {
|
|||||||
SetActiveSectionAction
|
SetActiveSectionAction
|
||||||
} from './objects/submission-objects.actions';
|
} from './objects/submission-objects.actions';
|
||||||
import {
|
import {
|
||||||
|
SubmissionError,
|
||||||
SubmissionObjectEntry,
|
SubmissionObjectEntry,
|
||||||
SubmissionSectionEntry,
|
SubmissionSectionEntry,
|
||||||
SubmissionSectionError,
|
|
||||||
SubmissionSectionObject
|
SubmissionSectionObject
|
||||||
} from './objects/submission-objects.reducer';
|
} from './objects/submission-objects.reducer';
|
||||||
import { submissionObjectFromIdSelector } from './selectors';
|
import { submissionObjectFromIdSelector } from './selectors';
|
||||||
@@ -183,7 +183,7 @@ export class SubmissionService {
|
|||||||
submissionDefinition: SubmissionDefinitionsModel,
|
submissionDefinition: SubmissionDefinitionsModel,
|
||||||
sections: WorkspaceitemSectionsObject,
|
sections: WorkspaceitemSectionsObject,
|
||||||
item: Item,
|
item: Item,
|
||||||
errors: SubmissionSectionError[]) {
|
errors: SubmissionError) {
|
||||||
this.store.dispatch(new InitSubmissionFormAction(collectionId, submissionId, selfUrl, submissionDefinition, sections, item, errors));
|
this.store.dispatch(new InitSubmissionFormAction(collectionId, submissionId, selfUrl, submissionDefinition, sections, item, errors));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,7 +292,8 @@ export class SubmissionService {
|
|||||||
sectionObject.config = sections[sectionId].config;
|
sectionObject.config = sections[sectionId].config;
|
||||||
sectionObject.mandatory = sections[sectionId].mandatory;
|
sectionObject.mandatory = sections[sectionId].mandatory;
|
||||||
sectionObject.data = sections[sectionId].data;
|
sectionObject.data = sections[sectionId].data;
|
||||||
sectionObject.errors = sections[sectionId].errors;
|
sectionObject.errorsToShow = sections[sectionId].errorsToShow;
|
||||||
|
sectionObject.serverValidationErrors = sections[sectionId].serverValidationErrors;
|
||||||
sectionObject.header = sections[sectionId].header;
|
sectionObject.header = sections[sectionId].header;
|
||||||
sectionObject.id = sectionId;
|
sectionObject.id = sectionId;
|
||||||
sectionObject.sectionType = sections[sectionId].sectionType;
|
sectionObject.sectionType = sections[sectionId].sectionType;
|
||||||
|
@@ -1,19 +1,17 @@
|
|||||||
import { ChangeDetectorRef, Component, OnDestroy, OnInit, ViewContainerRef } from '@angular/core';
|
import { ChangeDetectorRef, Component, OnDestroy, OnInit, ViewContainerRef } from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
|
||||||
import { Subscription } from 'rxjs';
|
import { BehaviorSubject, Subscription } from 'rxjs';
|
||||||
|
import { debounceTime, switchMap } from 'rxjs/operators';
|
||||||
import { hasValue, isEmpty, isNotNull, isNotEmptyOperator } from '../../shared/empty.util';
|
|
||||||
import { SubmissionDefinitionsModel } from '../../core/config/models/config-submission-definitions.model';
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
import { hasValue, isEmpty, isNotEmptyOperator, isNotNull } from '../../shared/empty.util';
|
||||||
|
import { SubmissionDefinitionsModel } from '../../core/config/models/config-submission-definitions.model';
|
||||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||||
import { SubmissionService } from '../submission.service';
|
import { SubmissionService } from '../submission.service';
|
||||||
import { SubmissionObject } from '../../core/submission/models/submission-object.model';
|
import { SubmissionObject } from '../../core/submission/models/submission-object.model';
|
||||||
import { Collection } from '../../core/shared/collection.model';
|
|
||||||
import { Item } from '../../core/shared/item.model';
|
import { Item } from '../../core/shared/item.model';
|
||||||
import { WorkspaceitemSectionsObject } from '../../core/submission/models/workspaceitem-sections.model';
|
import { WorkspaceitemSectionsObject } from '../../core/submission/models/workspaceitem-sections.model';
|
||||||
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
|
|
||||||
import { switchMap, debounceTime } from 'rxjs/operators';
|
|
||||||
import { getAllSucceededRemoteData } from '../../core/shared/operators';
|
import { getAllSucceededRemoteData } from '../../core/shared/operators';
|
||||||
import { RemoteData } from '../../core/data/remote-data';
|
import { RemoteData } from '../../core/data/remote-data';
|
||||||
import { ItemDataService } from '../../core/data/item-data.service';
|
import { ItemDataService } from '../../core/data/item-data.service';
|
||||||
|
Reference in New Issue
Block a user