diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f86733d..006de6a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * [UIQM-430](https://issues.folio.org/browse/UIQM-430) If the user manually enters the $9 field on a non-linkable, then hide the authorized icon on the view source. * [UIQM-426](https://issues.folio.org/browse/UIQM-426) Show error if $9 is added during deriving. * [UIQM-422](https://issues.folio.org/browse/UIQM-422) Edit/Derive MARC bib | Show Type label on 006 and 007 MARC fields. +* [UIQM-426](https://issues.folio.org/browse/UIQM-426) Allow a user to manual enter/edit $9 for non-linkable/non-controllable bib field ## [6.0.1](https://github.com/folio-org/ui-quick-marc/tree/v6.0.1) (2023-03-14) diff --git a/src/QuickMarcEditor/QuickMarcEditWrapper.js b/src/QuickMarcEditor/QuickMarcEditWrapper.js index c1e5224a..d2e1a81e 100644 --- a/src/QuickMarcEditor/QuickMarcEditWrapper.js +++ b/src/QuickMarcEditor/QuickMarcEditWrapper.js @@ -8,7 +8,7 @@ import PropTypes from 'prop-types'; import { useShowCallout } from '@folio/stripes-acq-components'; import QuickMarcEditor from './QuickMarcEditor'; - +import { useAuthorityLinking } from '../hooks'; import { QUICK_MARC_ACTIONS } from './constants'; import { EXTERNAL_INSTANCE_APIS, @@ -56,6 +56,7 @@ const QuickMarcEditWrapper = ({ const showCallout = useShowCallout(); const location = useLocation(); const [httpError, setHttpError] = useState(null); + const { linkableBibFields } = useAuthorityLinking(); const prepareForSubmit = useCallback((formValues) => { const formValuesToSave = removeDeletedRecords(formValues); @@ -78,6 +79,7 @@ const QuickMarcEditWrapper = ({ locations, linksCount, naturalId: instance.naturalId, + linkableBibFields, }); if (validationErrorMessage) { @@ -85,7 +87,7 @@ const QuickMarcEditWrapper = ({ } return undefined; - }, [initialValues, linksCount, locations, marcType, prepareForSubmit, instance.naturalId]); + }, [initialValues, linksCount, locations, marcType, prepareForSubmit, instance.naturalId, linkableBibFields]); const onSubmit = useCallback(async (formValues) => { let is1xxOr010Updated = false; diff --git a/src/QuickMarcEditor/QuickMarcEditorRows/QuickMarcEditorRows.js b/src/QuickMarcEditor/QuickMarcEditorRows/QuickMarcEditorRows.js index 5c59fef6..10ce9aad 100644 --- a/src/QuickMarcEditor/QuickMarcEditorRows/QuickMarcEditorRows.js +++ b/src/QuickMarcEditor/QuickMarcEditorRows/QuickMarcEditorRows.js @@ -239,7 +239,7 @@ const QuickMarcEditorRows = ({ const isContentField = !(isLocationField || isFixedField || isMaterialCharsField || isPhysDescriptionField); const isMARCFieldProtections = marcType !== MARC_TYPES.HOLDINGS && action === QUICK_MARC_ACTIONS.EDIT; const isProtectedField = recordRow.isProtected; - const isLinkVisible = checkCanBeLinked(stripes, marcType, action, linkableBibFields, recordRow.tag); + const isLinkVisible = checkCanBeLinked(stripes, marcType, linkableBibFields, recordRow.tag); const canViewAuthorityRecord = stripes.hasPerm('ui-marc-authorities.authority-record.view') && recordRow._isLinked; diff --git a/src/QuickMarcEditor/utils.js b/src/QuickMarcEditor/utils.js index c39d7a17..9bc6ab92 100644 --- a/src/QuickMarcEditor/utils.js +++ b/src/QuickMarcEditor/utils.js @@ -427,7 +427,7 @@ export const checkDuplicate010Field = (marcRecords) => { return undefined; }; -export const checkCanBeLinked = (stripes, marcType, action, linkableBibFields, tag) => ( +export const checkCanBeLinked = (stripes, marcType, linkableBibFields, tag) => ( stripes.hasPerm('ui-quick-marc.quick-marc-authority-records.linkUnlink') && marcType === MARC_TYPES.BIB && linkableBibFields.includes(tag) @@ -446,19 +446,17 @@ export const validateSubfield = (marcRecords, initialMarcRecords) => { return undefined; }; -const validate$9 = (marcRecords, uncontrolledSubfields) => { - const hasEntered$9 = marcRecords.some(field => { - if (typeof field.content !== 'string') { - return false; - } +const validate$9InLinkable = (marcRecords, linkableBibFields, uncontrolledSubfields) => { + const fieldsToCheck = marcRecords.filter(field => linkableBibFields.includes(field.tag)); - if (field.subfieldGroups) { - return uncontrolledSubfields.some(subfield => { - return field.subfieldGroups[subfield] && '$9' in getContentSubfieldValue(field.subfieldGroups[subfield]); - }); + const hasEntered$9 = fieldsToCheck.some(field => { + if (!field.subfieldGroups) { + return '$9' in getContentSubfieldValue(field.content); } - return '$9' in getContentSubfieldValue(field.content); + return uncontrolledSubfields.some(subfield => { + return field.subfieldGroups[subfield] && '$9' in getContentSubfieldValue(field.subfieldGroups[subfield]); + }); }); if (hasEntered$9) { @@ -516,7 +514,7 @@ const validateSubfieldsThatCanBeControlled = (marcRecords, uncontrolledSubfields return null; }; -const validateMarcBibRecord = (marcRecords) => { +const validateMarcBibRecord = (marcRecords, linkableBibFields) => { const titleRecords = marcRecords.filter(({ tag }) => tag === '245'); if (titleRecords.length === 0) { @@ -529,7 +527,7 @@ const validateMarcBibRecord = (marcRecords) => { const uncontrolledSubfields = ['uncontrolledAlpha', 'uncontrolledNumber']; - const $9Error = validate$9(marcRecords, uncontrolledSubfields); + const $9Error = validate$9InLinkable(marcRecords, linkableBibFields, uncontrolledSubfields); if ($9Error) { return $9Error; @@ -685,6 +683,7 @@ export const validateMarcRecord = ({ locations = [], linksCount, naturalId, + linkableBibFields = [], }) => { const marcRecords = marcRecord.records || []; const initialMarcRecords = initialValues.records; @@ -699,7 +698,7 @@ export const validateMarcRecord = ({ let validationResult; if (marcType === MARC_TYPES.BIB) { - validationResult = validateMarcBibRecord(marcRecords); + validationResult = validateMarcBibRecord(marcRecords, linkableBibFields); } else if (marcType === MARC_TYPES.HOLDINGS) { validationResult = validateMarcHoldingsRecord(marcRecords, locations); } else if (marcType === MARC_TYPES.AUTHORITY) { diff --git a/src/QuickMarcEditor/utils.test.js b/src/QuickMarcEditor/utils.test.js index 747cc5a4..1f17bb01 100644 --- a/src/QuickMarcEditor/utils.test.js +++ b/src/QuickMarcEditor/utils.test.js @@ -419,6 +419,15 @@ describe('QuickMarcEditor utils', () => { '_isDeleted': false, '_isLinked': false, }, + { + 'tag': '500', + 'content': '$a Black Panther $c (Fictitious character) $v Comic books, strips, etc.', + 'indicators': ['0', '0'], + 'isProtected': false, + 'id': '402c0aec-5e1b-49a3-83a2-da788f48b27a', + '_isDeleted': false, + '_isLinked': false, + }, ], }; @@ -430,19 +439,33 @@ describe('QuickMarcEditor utils', () => { expect(utils.validateMarcRecord({ marcRecord: record, initialValues, + linkableBibFields: ['100', '600'], }).props.id).toBe('ui-quick-marc.record.error.$9'); }); - it('should return an error for a not linked field', () => { + it('should return an error for linkable field', () => { const record = cloneDeep(initialValues); - record.records[4].content += ' $9 fakeValue'; + record.records[4].content = '$9 fakeValue'; expect(utils.validateMarcRecord({ marcRecord: record, initialValues, + linkableBibFields: ['100', '600'], }).props.id).toBe('ui-quick-marc.record.error.$9'); }); + + it('should not return an error for a not linkable field', () => { + const record = cloneDeep(initialValues); + + record.records[5].content += ' $9 fakeValue'; + + expect(utils.validateMarcRecord({ + marcRecord: record, + initialValues, + linkableBibFields: ['100', '600'], + })).toBeUndefined(); + }); }); describe('when a user enters into the linked field subfield(s) that can be controlled', () => { diff --git a/translations/ui-quick-marc/en.json b/translations/ui-quick-marc/en.json index c506349b..1c7637bc 100644 --- a/translations/ui-quick-marc/en.json +++ b/translations/ui-quick-marc/en.json @@ -186,7 +186,7 @@ "record.error.tag.nonDigits": "Invalid MARC tag. Please try again.", "record.error.subfield": "Missing a subfield value for a MARC tag", "record.error.location.invalid": "852 $b contains an invalid Location code. Please try again.", - "record.error.$9": "$9 is not a valid subfield.", + "record.error.$9": "$9 is an invalid subfield for linkable bibliographic fields.", "record.error.1xx.change": "Cannot change the saved MARC authority field {tag} because it controls a bibliographic field(s). To change this 1XX, you must unlink all controlled bibliographic fields.", "record.error.1xx.add$t": "Cannot add a $t to the ${tag} field because it controls a bibliographic field(s) that cannot control this subfield. To change this 1XX value, you must unlink all controlled bibliographic fields that cannot control $t.", "record.error.1xx.remove$t": "Cannot remove $t from the ${tag} field because it controls a bibliographic field(s) that requires this subfield. To change this 1XX value, you must unlink all controlled bibliographic fields that requires $t to be controlled.",