Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ERM-3298, Block save on invalid date in license edit #749

Merged
merged 4 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"start": "stripes serve",
"build": "stripes build --output ./output",
"test": "yarn run test:jest",
"test:jest": "jest --ci --coverage",
"test:jest": "jest --ci --coverage --maxWorkers=50%",
"build-mod-descriptor": "stripes mod descriptor --full --strict | jq '.[]' > module-descriptor.json ",
"formatjs-compile": "formatjs compile-folder --ast --format simple ./translations/ui-licenses ./translations/ui-licenses/compiled",
"lint": "eslint src test"
Expand Down
249 changes: 129 additions & 120 deletions src/components/formSections/LicenseFormInfo/LicenseFormInfo.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { FormattedMessage, useIntl } from 'react-intl';
import { Field } from 'react-final-form';
import { FieldArray } from 'react-final-form-arrays';
import { AlternativeNamesFieldArray, requiredValidator } from '@folio/stripes-erm-components';

import {
Checkbox,
Expand All @@ -13,21 +12,22 @@ import {
Select,
TextArea,
TextField,
getLocaleDateFormat
} from '@folio/stripes/components';

export default class LicenseFormInfo extends React.Component {
static propTypes = {
data: PropTypes.shape({
statusValues: PropTypes.arrayOf(PropTypes.object),
typeValues: PropTypes.arrayOf(PropTypes.object),
}),
id: PropTypes.string,
mutators: PropTypes.object,
values: PropTypes.object
};
import {
AlternativeNamesFieldArray,
requiredValidator,
datePlausibilityCheck,
} from '@folio/stripes-erm-components';


const LicenseFormInfo = ({ data: { statusValues, typeValues }, id, mutators, values }) => {
const intl = useIntl();
const dateFormat = getLocaleDateFormat({ intl });
const backendDateStandard = 'YYYY-MM-DD';
/* istanbul ignore next */
validateEndDate = (value, allValues) => {
const validateEndDate = (value, allValues) => {
if (value && allValues.startDate && (allValues.openEnded !== true)) {
const startDate = new Date(allValues.startDate);
const endDate = new Date(allValues.endDate);
Expand All @@ -41,121 +41,130 @@ export default class LicenseFormInfo extends React.Component {
}
}
return undefined;
}

render() {
const { data, id, mutators, values } = this.props;
};

return (
<div data-test-license-info id={id}>
<Row>
<Col xs={12}>
<Field
autoFocus
component={TextField}
id="edit-license-name"
label={<FormattedMessage id="ui-licenses.prop.name" />}
maxLength={255}
name="name"
required
validate={requiredValidator}
/>
</Col>
</Row>
<Row>
<Col md={6} xs={12}>
<Field
component={Select}
dataOptions={data.typeValues}
id="edit-license-type"
label={<FormattedMessage id="ui-licenses.prop.type" />}
name="type"
placeholder=" "
required
validate={requiredValidator}
/>
</Col>
<Col md={6} xs={12}>
<Field
component={Select}
dataOptions={data.statusValues}
id="edit-license-status"
label={<FormattedMessage id="ui-licenses.prop.status" />}
name="status"
placeholder=" "
required
validate={requiredValidator}
/>
</Col>
</Row>
<Row>
<Col md={5} xs={12}>
<Field
backendDateStandard="YYYY-MM-DD"
component={Datepicker}
id="edit-license-start-date"
label={<FormattedMessage id="ui-licenses.prop.startDate" />}
name="startDate"
parse={v => v} // Lets us pass an empty string instead of `undefined`
timeZone="UTC"
/>
</Col>
<Col md={5} xs={10}>
<Field
backendDateStandard="YYYY-MM-DD"
component={Datepicker}
disabled={values.openEnded}
id="edit-license-end-date"
label={<FormattedMessage id="ui-licenses.prop.endDate" />}
name="endDate"
parse={v => v} // Lets us pass an empty string instead of `undefined`
timeZone="UTC"
validate={this.validateEndDate}
/>
</Col>
<Col style={{ paddingTop: 20 }} xs={2}>
<Field
name="openEnded"
type="checkbox"
>
{props => {
/* istanbul ignore next */
return (<Checkbox
checked={props.input.checked}
return (
<div data-test-license-info id={id}>
<Row>
<Col xs={12}>
<Field
autoFocus
component={TextField}
id="edit-license-name"
label={<FormattedMessage id="ui-licenses.prop.name" />}
maxLength={255}
name="name"
required
validate={requiredValidator}
/>
</Col>
</Row>
<Row>
<Col md={6} xs={12}>
<Field
component={Select}
dataOptions={typeValues}
id="edit-license-type"
label={<FormattedMessage id="ui-licenses.prop.type" />}
name="type"
placeholder=" "
required
validate={requiredValidator}
/>
</Col>
<Col md={6} xs={12}>
<Field
component={Select}
dataOptions={statusValues}
id="edit-license-status"
label={<FormattedMessage id="ui-licenses.prop.status" />}
name="status"
placeholder=" "
required
validate={requiredValidator}
/>
</Col>
</Row>
<Row>
<Col md={5} xs={12}>
<Field
component={Datepicker}
id="edit-license-start-date"
label={<FormattedMessage id="ui-licenses.prop.startDate" />}
name="startDate"
parse={(v) => v} // Lets us pass an empty string instead of `undefined`
timeZone="UTC"
validate={(value) => datePlausibilityCheck(value, dateFormat, backendDateStandard)}
/>
</Col>
<Col md={5} xs={10}>
<Field
component={Datepicker}
disabled={values.openEnded}
id="edit-license-end-date"
label={<FormattedMessage id="ui-licenses.prop.endDate" />}
name="endDate"
parse={(v) => v} // Lets us pass an empty string instead of `undefined`
timeZone="UTC"
validate={
((value) => datePlausibilityCheck(value, dateFormat, backendDateStandard),
validateEndDate)
}
/>
</Col>
<Col style={{ paddingTop: 20 }} xs={2}>
<Field name="openEnded" type="checkbox">
{(input) => {
/* istanbul ignore next */
return (
<Checkbox
checked={input.checked}
id="edit-license-open-ended"
label={<FormattedMessage id="ui-licenses.prop.openEnded" />}
onChange={e => {
props.input.onChange(e);
onChange={(e) => {
input.onChange(e);
mutators.setFieldData('endDate', {
warning: e.target.checked ? (
<div data-test-warn-clear-end-date>
<FormattedMessage id="ui-licenses.warn.clearEndDate" />
</div>
) : undefined
) : undefined,
});
}}
type="checkbox"
/>);
}}
</Field>
</Col>
</Row>
<Row>
<Col xs={12}>
<Field
component={TextArea}
id="edit-license-description"
label={<FormattedMessage id="ui-licenses.prop.description" />}
name="description"
parse={v => v} // Lets us pass an empty string instead of `undefined`
/>
</Col>
</Row>
<FieldArray
component={AlternativeNamesFieldArray}
name="alternateNames"
/>
</div>
);
}
}
/>
);
}}
</Field>
</Col>
</Row>
<Row>
<Col xs={12}>
<Field
component={TextArea}
id="edit-license-description"
label={<FormattedMessage id="ui-licenses.prop.description" />}
name="description"
parse={(v) => v} // Lets us pass an empty string instead of `undefined`
/>
</Col>
</Row>
<FieldArray
component={AlternativeNamesFieldArray}
name="alternateNames"
/>
</div>
);
};

LicenseFormInfo.propTypes = {
data: PropTypes.shape({
statusValues: PropTypes.arrayOf(PropTypes.object),
typeValues: PropTypes.arrayOf(PropTypes.object),
}),
id: PropTypes.string,
mutators: PropTypes.object,
values: PropTypes.object
};

export default LicenseFormInfo;