Skip to content

Commit

Permalink
feat: add custom error validation to series (#595)
Browse files Browse the repository at this point in the history
  • Loading branch information
EmmanuelDemey authored Feb 13, 2024
1 parent 47e29b8 commit 651cb08
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 95 deletions.
125 changes: 85 additions & 40 deletions app/src/js/applications/operations/series/edition/edition.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ import { CL_SOURCE_CATEGORY, CL_FREQ } from 'js/actions/constants/codeList';
import {
EditorMarkdown,
ItemToSelectModel,
PageTitleBlock, withTitle, SelectRmes, ErrorBloc, GlobalClientSideErrorBloc, ClientSideError
PageTitleBlock,
withTitle,
SelectRmes,
ErrorBloc,
GlobalClientSideErrorBloc,
ClientSideError,
} from 'bauhaus-utilities';
import { PublishersInput, CreatorsInput } from 'bauhaus-operations';

Expand Down Expand Up @@ -87,12 +92,12 @@ class OperationsSerieEdition extends Component {
},
};
}
this.setState(state => ({
this.setState((state) => ({
serverSideError: '',
submitting: true,
clientSideErrors: {
...state.clientSideErrors,
errorMessage: []
errorMessage: [],
},
serie: {
...this.state.serie,
Expand All @@ -102,39 +107,36 @@ class OperationsSerieEdition extends Component {
};
onSubmit = () => {
const clientSideErrors = validate(this.state.serie);
if(clientSideErrors.errorMessage?.length > 0){
if (clientSideErrors.errorMessage?.length > 0) {
this.setState({
submitting: true,
clientSideErrors
})
clientSideErrors,
});
} else {
this.setState({ saving: true })
this.setState({ saving: true });
const isCreation = !this.state.serie.id;

const method = isCreation ? 'postSeries' : 'putSeries';
return api[method](this.state.serie).then(
(id = this.state.serie.id) => {
goBackOrReplace(this.props, `/operations/series/${id}`, isCreation);
},
err => {
this.setState({
serverSideError: err,
});
}
).finally(() => this.setState({ saving: false }));
return api[method](this.state.serie)
.then(
(id = this.state.serie.id) => {
goBackOrReplace(this.props, `/operations/series/${id}`, isCreation);
},
(err) => {
this.setState({
serverSideError: err,
});
}
)
.finally(() => this.setState({ saving: false }));
}
};

render() {
if (this.state.saving) return <Loading textType="saving" />;

const {
frequencies,
categories,
organisations,
indicators,
series,
} = this.props;
const { frequencies, categories, organisations, indicators, series } =
this.props;

const serie = {
...this.state.serie,
Expand Down Expand Up @@ -168,10 +170,11 @@ class OperationsSerieEdition extends Component {
indicators,
'indicator'
);
const seriesAndIndicatorsOptions = ItemToSelectModel.mergedItemsToSelectModels(
indicatorsOptions,
seriesOptions
);
const seriesAndIndicatorsOptions =
ItemToSelectModel.mergedItemsToSelectModels(
indicatorsOptions,
seriesOptions
);

const serverSideError = this.state.serverSideError;

Expand All @@ -187,10 +190,18 @@ class OperationsSerieEdition extends Component {

<ActionToolbar>
<CancelButton action={goBack(this.props, '/operations/series')} />
<SaveButton action={this.onSubmit} disabled={this.state.clientSideErrors.errorMessage?.length > 0} />
<SaveButton
action={this.onSubmit}
disabled={this.state.clientSideErrors.errorMessage?.length > 0}
/>
</ActionToolbar>
{ this.state.submitting && this.state.clientSideErrors && <GlobalClientSideErrorBloc clientSideErrors={this.state.clientSideErrors.errorMessage} D={D}/> }
{ serverSideError && <ErrorBloc error={[serverSideError]} D={D}/> }
{this.state.submitting && this.state.clientSideErrors && (
<GlobalClientSideErrorBloc
clientSideErrors={this.state.clientSideErrors.errorMessage}
D={D}
/>
)}
{serverSideError && <ErrorBloc error={[serverSideError]} D={D} />}
<form>
{!isEditing && (
<div className="row">
Expand All @@ -206,7 +217,10 @@ class OperationsSerieEdition extends Component {
})
}
/>
<ClientSideError id="family-error" error={this.state.clientSideErrors?.fields?.family}></ClientSideError>
<ClientSideError
id="family-error"
error={this.state.clientSideErrors?.fields?.family}
></ClientSideError>
</div>
</div>
)}
Expand All @@ -219,10 +233,19 @@ class OperationsSerieEdition extends Component {
id="prefLabelLg1"
value={serie.prefLabelLg1}
onChange={this.onChange}
aria-invalid={!!this.state.clientSideErrors.fields?.prefLabelLg1}
aria-describedby={!!this.state.clientSideErrors.fields?.prefLabelLg1 ? 'prefLabelLg1-error' : null}
aria-invalid={
!!this.state.clientSideErrors.fields?.prefLabelLg1
}
aria-describedby={
!!this.state.clientSideErrors.fields?.prefLabelLg1
? 'prefLabelLg1-error'
: null
}
/>
<ClientSideError id="prefLabelLg1-error" error={this.state.clientSideErrors?.fields?.prefLabelLg1}></ClientSideError>
<ClientSideError
id="prefLabelLg1-error"
error={this.state.clientSideErrors?.fields?.prefLabelLg1}
></ClientSideError>
</div>
<div className="form-group col-md-6">
<LabelRequired htmlFor="prefLabelLg2">{D2.title}</LabelRequired>
Expand All @@ -232,10 +255,19 @@ class OperationsSerieEdition extends Component {
id="prefLabelLg2"
value={serie.prefLabelLg2}
onChange={this.onChange}
aria-invalid={!!this.state.clientSideErrors.fields?.prefLabelLg2}
aria-describedby={!!this.state.clientSideErrors.fields?.prefLabelLg2 ? 'prefLabelLg2-error' : null}
aria-invalid={
!!this.state.clientSideErrors.fields?.prefLabelLg2
}
aria-describedby={
!!this.state.clientSideErrors.fields?.prefLabelLg2
? 'prefLabelLg2-error'
: null
}
/>
<ClientSideError id="prefLabelLg2-error" error={this.state.clientSideErrors?.fields?.prefLabelLg2}></ClientSideError>
<ClientSideError
id="prefLabelLg2-error"
error={this.state.clientSideErrors?.fields?.prefLabelLg2}
></ClientSideError>
</div>
</div>
<div className="row">
Expand Down Expand Up @@ -318,6 +350,10 @@ class OperationsSerieEdition extends Component {
}
/>
</label>
<ClientSideError
id="typecode-error"
error={this.state.clientSideErrors?.fields?.typeCode}
></ClientSideError>
</div>
</div>
<div className="row">
Expand All @@ -338,6 +374,12 @@ class OperationsSerieEdition extends Component {
}
/>
</label>
<ClientSideError
id="accrualPeriodicityCode-error"
error={
this.state.clientSideErrors?.fields?.accrualPeriodicityCode
}
></ClientSideError>
</div>
</div>

Expand Down Expand Up @@ -417,7 +459,10 @@ class OperationsSerieEdition extends Component {
})
}
/>
<ClientSideError id="creators-error" error={this.state.clientSideErrors?.fields?.creators}></ClientSideError>
<ClientSideError
id="creators-error"
error={this.state.clientSideErrors?.fields?.creators}
></ClientSideError>
</div>
</div>
<div className="row">
Expand Down Expand Up @@ -514,6 +559,6 @@ class OperationsSerieEdition extends Component {
}
}

export default withTitle(OperationsSerieEdition, D.operationsTitle, props => {
export default withTitle(OperationsSerieEdition, D.operationsTitle, (props) => {
return props.serie?.prefLabelLg1 || D.seriesCreateTitle;
});
64 changes: 48 additions & 16 deletions app/src/js/applications/operations/series/edition/validation.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,62 @@
import D, { D1, D2 } from 'js/i18n';

export function validate({ creators, prefLabelLg1, prefLabelLg2, family }) {
const errorMessages = [];
export const listOfExtraMandatoryFields = (
process.env.REACT_APP_VALIDATION_OPERATION_SERIES_EXTRA_MANDATORY_FIELDS ?? ''
).split(',');

if(!creators || creators.length === 0){
errorMessages.push(D.mandatoryProperty(D1.creatorTitle))
const fieldToTitleMapping = {
creators: D1.creatorTitle,
prefLabelLg1: D1.title,
prefLabelLg2: D2.title,
family: D1.familyTitle,
typeCode: D1.operationType,
accrualPeriodicityCode: D1.dataCollectFrequency,
};

export const isMandatoryField = (fieldName) =>
listOfExtraMandatoryFields.indexOf(fieldName) >= 0;

export function validate({
creators,
prefLabelLg1,
prefLabelLg2,
family,
...otherFields
}) {
const fields = {};
const errorMessage = [];

if (!creators || creators.length === 0) {
errorMessage.push(D.mandatoryProperty(fieldToTitleMapping.creators));
fields.creators = D.mandatoryProperty(fieldToTitleMapping.creators);
}

if(!prefLabelLg1){
errorMessages.push(D.mandatoryProperty(D1.title))
if (!prefLabelLg1) {
errorMessage.push(D.mandatoryProperty(fieldToTitleMapping.prefLabelLg1));
fields.prefLabelLg1 = D.mandatoryProperty(fieldToTitleMapping.prefLabelLg1);
}
if(!prefLabelLg2){
errorMessages.push(D.mandatoryProperty(D2.title))
if (!prefLabelLg2) {
errorMessage.push(D.mandatoryProperty(fieldToTitleMapping.prefLabelLg2));
fields.prefLabelLg2 = D.mandatoryProperty(fieldToTitleMapping.prefLabelLg2);
}

if (!family) {
errorMessages.push(D.mandatoryProperty(D1.familyTitle))
errorMessage.push(D.mandatoryProperty(fieldToTitleMapping.family));
fields.family = D.mandatoryProperty(fieldToTitleMapping.family);
}

listOfExtraMandatoryFields.forEach((extraMandatoryField) => {
if (!otherFields[extraMandatoryField]) {
errorMessage.push(
D.mandatoryProperty(fieldToTitleMapping[extraMandatoryField] ?? '')
);
fields[extraMandatoryField] = D.mandatoryProperty(
fieldToTitleMapping[extraMandatoryField] ?? ''
);
}
});
return {
fields: {
creators: (!creators || creators.length === 0) ? D.mandatoryProperty(D1.creatorTitle) : '',
prefLabelLg1: !prefLabelLg1 ? D.mandatoryProperty(D1.title) : '',
prefLabelLg2: !prefLabelLg2 ? D.mandatoryProperty(D2.title) : '',
family: !family ? D.mandatoryProperty(D1.familyTitle) : '',
},
errorMessage: errorMessages,
fields,
errorMessage,
};
}
Loading

0 comments on commit 651cb08

Please sign in to comment.