Skip to content

Commit

Permalink
UIQM-226 MARC holdings: Can add multiple 852s tags (#296)
Browse files Browse the repository at this point in the history
* UIQM-226 MARC holdings: Can add multiple 852s tags

* UIQM-226 remove unused import of getLocationValue

* UIQM-226 override moduleNameMapper to remove 'ky' mapping

* Revert "UIQM-226 override moduleNameMapper to remove 'ky' mapping"

This reverts commit 38ad378.
  • Loading branch information
BogdanDenis committed Apr 8, 2022
1 parent 2167990 commit 6b159cf
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 96 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Change history for ui-quick-marc

## [5.0.2] (IN PROGRESS)

* [UIQM-226](https://issues.folio.org/browse/UIQM-226) MARC holdings: Can add multiple 852s tags.

## [5.0.1](https://github.com/folio-org/ui-quick-marc/tree/v5.0.1) (2022-03-29)

* [UIQM-219](https://issues.folio.org/browse/UIQM-219) Cannot assign MARC authority permissions only.
Expand Down
12 changes: 0 additions & 12 deletions src/QuickMarcEditor/QuickMarcEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import {
restoreRecordAtIndex,
getCorrespondingMarcTag,
getContentSubfieldValue,
getLocationValue,
} from './utils';

const spySubscription = { values: true };
Expand All @@ -56,7 +55,6 @@ const QuickMarcEditor = ({
const [records, setRecords] = useState([]);
const [isDeleteModalOpened, setIsDeleteModalOpened] = useState(false);
const [deletedRecords, setDeletedRecords] = useState([]);
const [permanentLocation, setPermanentLocation] = useState('');
const [isLocationLookupUsed, setIsLocationLookupUsed] = useState(false);

const isLocationLookupNeeded = marcType === MARC_TYPES.HOLDINGS
Expand Down Expand Up @@ -189,14 +187,6 @@ const QuickMarcEditor = ({
const changeRecords = useCallback(({ values }) => {
if (values?.records) {
setRecords(values.records);

if (isLocationLookupNeeded) {
const locationField = values.records.find(field => field.tag === '852');

const matchedLocation = getLocationValue(locationField?.content);

setPermanentLocation(matchedLocation);
}
}
}, []);

Expand Down Expand Up @@ -249,8 +239,6 @@ const QuickMarcEditor = ({
subtype={initialValues?.leader[7]}
setDeletedRecords={setDeletedRecords}
isLocationLookupNeeded={isLocationLookupNeeded}
permanentLocation={permanentLocation}
setPermanentLocation={setPermanentLocation}
isLocationLookupUsed={isLocationLookupUsed}
setIsLocationLookupUsed={setIsLocationLookupUsed}
marcType={marcType}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,64 @@
import React from 'react';
import React, {
useState,
useCallback,
} from 'react';
import PropTypes from 'prop-types';
import { useIntl } from 'react-intl';

import { omit } from 'lodash';
import { FormSpy } from 'react-final-form';

import { LocationLookup } from '@folio/stripes/smart-components';

import { QUICK_MARC_ACTIONS } from '../../constants';
import { getLocationValue } from '../../utils';
import { ContentField } from '../ContentField';

export const LocationField = ({
const spySubscription = { values: true };

const propTypes = {
action: PropTypes.oneOf(Object.values(QUICK_MARC_ACTIONS)).isRequired,
input: PropTypes.shape({
value: PropTypes.string,
}),
fields: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.string.isRequired,
tag: PropTypes.string.isRequired,
indicators: PropTypes.arrayOf(PropTypes.string),
content: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
})),
permanentLocation: PropTypes.string.isRequired,
setPermanentLocation: PropTypes.func.isRequired,
isLocationLookupUsed: PropTypes.bool.isRequired,
setIsLocationLookupUsed: PropTypes.func.isRequired,
};

const LocationField = ({
id,
action,
input,
fields,
isLocationLookupUsed,
setIsLocationLookupUsed,
permanentLocation,
setPermanentLocation,
...props
}) => {
const intl = useIntl();
const [permanentLocation, setPermanentLocation] = useState(getLocationValue(input.value));

const getContentFieldValue = useCallback(() => {
const locationField = fields.find(field => field.id === id);

if (!locationField) {
return input;
}

const getContentFieldValue = () => {
const locationField = fields.find(field => field.tag === '852');
const newInput = omit(input, ['value']);
const locationValue = getLocationValue(input.value);
const locationValue = getLocationValue(locationField.content);

let newInputValue;

if (action === QUICK_MARC_ACTIONS.EDIT) {
newInputValue = locationValue
? input.value.replace(locationValue, permanentLocation)
? locationField.content.replace(locationValue, permanentLocation)
: `${permanentLocation} ${input.value.trim()}`;
} else {
newInputValue = permanentLocation;
Expand All @@ -41,7 +68,17 @@ export const LocationField = ({
newInput.value = newInputValue;

return newInput;
};
}, [permanentLocation, input]);

const changeRecords = useCallback(({ values }) => {
if (values?.records) {
const locationField = values.records.find(field => field.id === id);

const matchedLocation = getLocationValue(locationField?.content);

setPermanentLocation(matchedLocation);
}
}, []);

const isReplacingLocationNeeded = permanentLocation !== getLocationValue(input.value);

Expand All @@ -57,32 +94,23 @@ export const LocationField = ({
/>
<LocationLookup
label={intl.formatMessage({ id: 'ui-quick-marc.permanentLocationLookup' })}
marginBottom0
onLocationSelected={location => {
if (!isLocationLookupUsed) {
setIsLocationLookupUsed(true);
}

setPermanentLocation(`$b ${location.code}`);
}}
marginBottom0
/>
<FormSpy
subscription={spySubscription}
onChange={changeRecords}
/>
</>
);
};

LocationField.propTypes = {
action: PropTypes.oneOf(Object.values(QUICK_MARC_ACTIONS)).isRequired,
input: PropTypes.shape({
value: PropTypes.string,
}),
fields: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.string.isRequired,
tag: PropTypes.string.isRequired,
indicators: PropTypes.arrayOf(PropTypes.string),
content: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
})),
permanentLocation: PropTypes.string.isRequired,
setPermanentLocation: PropTypes.func.isRequired,
isLocationLookupUsed: PropTypes.bool.isRequired,
setIsLocationLookupUsed: PropTypes.func.isRequired,
};
LocationField.propTypes = propTypes;

export { LocationField };
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { render } from '@testing-library/react';
import {
render,
fireEvent,
} from '@testing-library/react';
import { Form } from 'react-final-form';
import arrayMutators from 'final-form-arrays';

import { QUICK_MARC_ACTIONS } from '../../constants';

Expand All @@ -11,30 +16,52 @@ const fields = [
content: '00000nu\\\\\\2200000un\\4500',
},
{
id: '1',
id: 'id-1',
tag: '852',
content: '$b KU/CC/DI/A $t 3 $h M3',
indicators: ['0', '1'],
},
];

const renderLocationField = (props) => (render(
<LocationField
action={QUICK_MARC_ACTIONS.EDIT}
input={{
value: '$b KU/CC/DI/A $t 3 $h M3',
}}
fields={fields}
permanentLocation="$b KU/CC/DI/A"
setPermanentLocation={jest.fn()}
isLocationLookupUsed={false}
setIsLocationLookupUsed={jest.fn()}
meta={{
dirty: false,
}}
{...props}
/>,
));
const newLocation = { code: 'NEWLOCATION' };

jest.mock('@folio/stripes/smart-components', () => ({
LocationLookup: ({ onLocationSelected }) => (
<div>
<span>LocationLookup</span>
<button
onClick={() => onLocationSelected(newLocation)}
>
Select location
</button>
</div>
)
}))

const getLocationField = (props = {}) => (
<Form
onSubmit={jest.fn()}
mutators={{ ...arrayMutators }}
render={() => (
<LocationField
id="id-1"
action={QUICK_MARC_ACTIONS.EDIT}
input={{
value: '$b KU/CC/DI/A $t 3 $h M3',
}}
fields={fields}
isLocationLookupUsed={false}
setIsLocationLookupUsed={jest.fn()}
meta={{
dirty: false,
}}
{...props}
/>
)}
/>
);

const renderLocationField = (props = {}) => render(getLocationField(props));

describe('Given LocationField', () => {
it('should render content field and location lookup', () => {
Expand All @@ -47,48 +74,29 @@ describe('Given LocationField', () => {
expect(getByText('LocationLookup')).toBeDefined();
});

describe('when permanentLocation is equal to input value', () => {
it('should display permanentLocation for subfield $b in location field', () => {
const { getByText } = renderLocationField();

expect(getByText('$b KU/CC/DI/A $t 3 $h M3')).toBeDefined();
});
});

describe('when permanentLocation is not equal to input value', () => {
describe('when selecting a new location', () => {
describe('when action is edit', () => {
describe('when input value contains location subfield', () => {
it('should display permanentLocation for subfield $b in location field', () => {
const { getByText } = renderLocationField({
permanentLocation: '$b E',
});

expect(getByText('$b E $t 3 $h M3')).toBeDefined();
});
});
it('should replace subfield $b with new location value in location field', () => {
const { getByText } = renderLocationField();

describe('when input value does not contain location subfield', () => {
it('should display permanentLocation for subfield $b in location field', () => {
const { getByText } = renderLocationField({
input: {
value: '$t 3 $h M3',
},
permanentLocation: '$b E',
});
fireEvent.click(getByText('Select location'));

expect(getByText('$b E $t 3 $h M3')).toBeDefined();
});
expect(getByText('$b NEWLOCATION $t 3 $h M3')).toBeDefined();
});
});

describe('when action is create', () => {
it('should display just subfield $b with permanentLocation value in location field', () => {
it('should set subfield $b with new location value in location field', () => {
const { getByText } = renderLocationField({
action: QUICK_MARC_ACTIONS.CREATE,
permanentLocation: '$b E',
input: {
value: '$a ',
},
});

expect(getByText('$b E')).toBeDefined();
fireEvent.click(getByText('Select location'));

expect(getByText('$b NEWLOCATION')).toBeDefined();
});
});
});
Expand Down
10 changes: 4 additions & 6 deletions src/QuickMarcEditor/QuickMarcEditorRows/QuickMarcEditorRows.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Field } from 'react-final-form';
import {
useIntl,
} from 'react-intl';
import { omit } from 'lodash';

import {
TextField,
Expand Down Expand Up @@ -44,8 +45,6 @@ const QuickMarcEditorRows = ({
subtype,
setDeletedRecords,
isLocationLookupNeeded,
permanentLocation,
setPermanentLocation,
isLocationLookupUsed,
setIsLocationLookupUsed,
mutators: {
Expand Down Expand Up @@ -103,7 +102,7 @@ const QuickMarcEditorRows = ({

return (
<div
key={idx}
key={recordRow.id}
className={styles.quickMarcEditorRow}
data-testid="quick-marc-editorid"
>
Expand Down Expand Up @@ -225,13 +224,12 @@ const QuickMarcEditorRows = ({
{(props) => {
return isLocationField ? (
<LocationField
id={recordRow.id}
action={action}
fields={fields}
isLocationLookupUsed={isLocationLookupUsed}
setIsLocationLookupUsed={setIsLocationLookupUsed}
permanentLocation={permanentLocation}
setPermanentLocation={setPermanentLocation}
{...props}
{...omit(props, ['id'])}
/>
) : (
<ContentField {...props} />
Expand Down
1 change: 0 additions & 1 deletion src/QuickMarcEditor/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,6 @@ export const validateLeader = (prevLeader = '', leader = '', marcType = MARC_TYP

export const getLocationValue = (value) => {
const matches = value?.match(/\$b\s([^$\s]+\/?)+/) || [];

return matches[0] || '';
};

Expand Down

0 comments on commit 6b159cf

Please sign in to comment.