From a4eb419cfec030aa9d6cf82996361679866080b7 Mon Sep 17 00:00:00 2001 From: Dmytro-Melnyshyn Date: Wed, 13 Nov 2024 15:01:06 +0200 Subject: [PATCH] UIQM-716-test --- src/MarcRoute/MarcRoute.js | 2 + src/QuickMarc.js | 25 +- .../QuickMarcEditorContainer.js | 15 +- src/QuickMarcEditor/useMarcCreate/index.js | 1 + .../useMarcCreate/useMarcCreate.js | 231 +++++++++++++++ src/QuickMarcEditor/useMarcDerive/index.js | 1 + .../useMarcDerive/useMarcDerive.js | 235 +++++++++++++++ src/QuickMarcEditor/useMarcEdit/index.js | 1 + .../useMarcEdit/useMarcEdit.js | 275 ++++++++++++++++++ src/QuickMarcEditor/utils.js | 34 +++ 10 files changed, 815 insertions(+), 5 deletions(-) create mode 100644 src/QuickMarcEditor/useMarcCreate/index.js create mode 100644 src/QuickMarcEditor/useMarcCreate/useMarcCreate.js create mode 100644 src/QuickMarcEditor/useMarcDerive/index.js create mode 100644 src/QuickMarcEditor/useMarcDerive/useMarcDerive.js create mode 100644 src/QuickMarcEditor/useMarcEdit/index.js create mode 100644 src/QuickMarcEditor/useMarcEdit/useMarcEdit.js diff --git a/src/MarcRoute/MarcRoute.js b/src/MarcRoute/MarcRoute.js index d3beec1e..d62163f0 100644 --- a/src/MarcRoute/MarcRoute.js +++ b/src/MarcRoute/MarcRoute.js @@ -31,6 +31,7 @@ const MarcRoute = ({ const { marcType, action, + useMarcActionHandler, } = routeProps; const centralTenantId = stripes.user.user?.consortium?.centralTenantId; const isRequestToCentralTenantFromMember = applyCentralTenantInHeaders(location, stripes, marcType) @@ -75,6 +76,7 @@ const MarcRoute = ({ onClose={onClose} onSave={onSave} externalRecordPath={externalRecordPath} + useMarcActionHandler={useMarcActionHandler} onCheckCentralTenantPerm={checkCentralTenantPerm} /> diff --git a/src/QuickMarc.js b/src/QuickMarc.js index a4e002de..237333fa 100644 --- a/src/QuickMarc.js +++ b/src/QuickMarc.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import PropTypes from 'prop-types'; import { Switch, @@ -13,6 +13,19 @@ import { MARC_TYPES, keyboardCommands, } from './common/constants'; +import { useMarcCreate } from './QuickMarcEditor/useMarcCreate'; +import { useMarcEdit } from './QuickMarcEditor/useMarcEdit'; +import { useMarcDerive } from './QuickMarcEditor/useMarcDerive'; + +const createUseMarcActionHandler = (action) => { + const marcActionHooks = { + [QUICK_MARC_ACTIONS.CREATE]: useMarcCreate, + [QUICK_MARC_ACTIONS.EDIT]: useMarcEdit, + [QUICK_MARC_ACTIONS.DERIVE]: useMarcDerive, + }; + + return marcActionHooks[action]; +}; const QuickMarc = ({ basePath, @@ -33,6 +46,8 @@ const QuickMarc = ({ // .../some-path/create-bibliographic => [, create-bibliographic, create, bibliographic] const [, page, action] = location.pathname.match(/\/((edit|create|derive)-(bibliographic|authority|holdings))/) || []; + const useMarcActionHandler = useMemo(() => createUseMarcActionHandler(action), [action]); + const editorRoutesConfig = [ { path: `${basePath}/:action-bibliographic/:externalId?`, @@ -40,6 +55,7 @@ const QuickMarc = ({ props: { action, marcType: MARC_TYPES.BIB, + useMarcActionHandler, }, }, { @@ -48,22 +64,25 @@ const QuickMarc = ({ props: { action, marcType: MARC_TYPES.AUTHORITY, + useMarcActionHandler, }, }, { path: `${basePath}/create-holdings/:externalId`, permission: 'ui-quick-marc.quick-marc-holdings-editor.create', props: { - action: QUICK_MARC_ACTIONS.CREATE, + action, marcType: MARC_TYPES.HOLDINGS, + useMarcActionHandler, }, }, { path: `${basePath}/edit-holdings/:instanceId/:externalId`, permission: 'ui-quick-marc.quick-marc-holdings-editor.all', props: { - action: QUICK_MARC_ACTIONS.EDIT, + action, marcType: MARC_TYPES.HOLDINGS, + useMarcActionHandler, }, }, ]; diff --git a/src/QuickMarcEditor/QuickMarcEditorContainer.js b/src/QuickMarcEditor/QuickMarcEditorContainer.js index 552da16c..118d280d 100644 --- a/src/QuickMarcEditor/QuickMarcEditorContainer.js +++ b/src/QuickMarcEditor/QuickMarcEditorContainer.js @@ -69,6 +69,7 @@ const QuickMarcEditorContainer = ({ location, externalRecordPath, stripes, + useMarcActionHandler, onCheckCentralTenantPerm, }) => { const { @@ -216,7 +217,17 @@ const QuickMarcEditorContainer = ({ setRelatedRecordVersion, ]); - const { onSubmit, httpError, runValidation } = useSaveRecord({ + // const { onSubmit, httpError, runValidation } = useSaveRecord({ + // linksCount, + // locations, + // fixedFieldSpec, + // mutator, + // refreshPageData: loadData, + // onClose: handleClose, + // onSave: handleSave, + // }); + + const { onSubmit, httpError, runValidation } = useMarcActionHandler({ linksCount, locations, fixedFieldSpec, @@ -224,7 +235,7 @@ const QuickMarcEditorContainer = ({ refreshPageData: loadData, onClose: handleClose, onSave: handleSave, - }); + }) useEffect(() => { loadData(); diff --git a/src/QuickMarcEditor/useMarcCreate/index.js b/src/QuickMarcEditor/useMarcCreate/index.js new file mode 100644 index 00000000..04d2e5cf --- /dev/null +++ b/src/QuickMarcEditor/useMarcCreate/index.js @@ -0,0 +1 @@ +export * from './useMarcCreate'; diff --git a/src/QuickMarcEditor/useMarcCreate/useMarcCreate.js b/src/QuickMarcEditor/useMarcCreate/useMarcCreate.js new file mode 100644 index 00000000..63484234 --- /dev/null +++ b/src/QuickMarcEditor/useMarcCreate/useMarcCreate.js @@ -0,0 +1,231 @@ +import { + useCallback, + useContext, + useMemo, + useState, +} from 'react'; +import { + useHistory, + useLocation, useParams, +} from 'react-router-dom'; +import flow from 'lodash/flow'; +import isEmpty from 'lodash/isEmpty'; +import noop from 'lodash/noop'; + +import { useStripes } from '@folio/stripes/core'; +import { useShowCallout } from '@folio/stripes-acq-components'; + +import { QuickMarcContext } from '../../contexts'; +import { + useAuthorityLinking, + useValidation, +} from '../../hooks'; +import { + applyCentralTenantInHeaders, + autopopulateFixedField, + autopopulateIndicators, + autopopulateMaterialCharsField, + autopopulatePhysDescriptionField, + autopopulateSubfieldSection, + cleanBytesFields, + combineSplitFields, + formatLeaderForSubmit, + hydrateMarcRecord, + parseHttpError, + processEditingAfterCreation, + recordHasLinks, + redirectToRecord, + removeDeletedRecords, + removeRowsWithoutContent, + saveLinksToNewRecord, +} from '../utils'; +import { MARC_TYPES } from '../../common'; +import getQuickMarcRecordStatus from '../getQuickMarcRecordStatus'; + +const useMarcCreate = ({ + linksCount, + locations, + fixedFieldSpec, + mutator, + refreshPageData, + onSave, +}) => { + const history = useHistory(); + const location = useLocation(); + const stripes = useStripes(); + const showCallout = useShowCallout(); + + const { + action, + marcType, + initialValues, + instance, + validationErrorsRef, + continueAfterSave, + basePath, + } = useContext(QuickMarcContext); + + const [httpError, setHttpError] = useState(null); + + const isRequestToCentralTenantFromMember = applyCentralTenantInHeaders(location, stripes, marcType); + const centralTenantId = stripes.user.user.consortium?.centralTenantId; + const tenantId = isRequestToCentralTenantFromMember ? centralTenantId : ''; + + const { + linkableBibFields, + linkingRules, + sourceFiles, + actualizeLinks, + } = useAuthorityLinking({ marcType, action }); + + const validationContext = useMemo(() => ({ + initialValues, + marcType, + action, + linkableBibFields, + linkingRules, + fixedFieldSpec, + instanceId: instance?.id, + sourceFiles, + linksCount, + naturalId: instance?.naturalId, + locations, + }), [ + action, + instance?.naturalId, + linksCount, + initialValues, + marcType, + locations, + linkableBibFields, + linkingRules, + sourceFiles, + fixedFieldSpec, + instance?.id, + ]); + + const { validate } = useValidation(validationContext, tenantId); + + const prepareForSubmit = useCallback((formValues) => { + const formValuesForCreate = flow( + removeDeletedRecords, + removeRowsWithoutContent, + autopopulateIndicators, + marcRecord => autopopulateFixedField(marcRecord, marcType, fixedFieldSpec), + autopopulatePhysDescriptionField, + autopopulateMaterialCharsField, + marcRecord => autopopulateSubfieldSection(marcRecord, marcType), + marcRecord => cleanBytesFields(marcRecord, fixedFieldSpec, marcType), + marcRecord => formatLeaderForSubmit(marcType, marcRecord), + combineSplitFields, + )(formValues); + + return formValuesForCreate; + }, [marcType, fixedFieldSpec]); + + const runValidation = useCallback(async (formValues) => { + const formValuesForValidation = prepareForSubmit(formValues); + + return validate(formValuesForValidation.records); + }, [validate, prepareForSubmit]); + + const onSubmit = useCallback(async (formValues, _api, complete) => { + // if validation has any issues - cancel submit + if (!isEmpty(validationErrorsRef.current)) { + return complete(); + } + + const formValuesToProcess = prepareForSubmit(formValues); + + let formValuesToHydrate; + + try { + if (marcType === MARC_TYPES.BIB) { + formValuesToHydrate = await actualizeLinks(formValuesToProcess); + } else { + formValuesToHydrate = formValuesToProcess; + } + } catch (errorResponse) { + const parsedError = await parseHttpError(errorResponse); + + setHttpError(parsedError); + + return null; + } + + formValuesToHydrate._actionType = 'create'; + + const formValuesForCreate = hydrateMarcRecord(formValuesToHydrate); + + return mutator.quickMarcEditMarcRecord.POST(formValuesForCreate) + .then(async ({ qmRecordId }) => { + const instanceId = formValues.externalId; + + showCallout({ messageId: 'ui-quick-marc.record.save.success.processing' }); + + try { + const { externalId } = await getQuickMarcRecordStatus({ + quickMarcRecordStatusGETRequest: mutator.quickMarcRecordStatus.GET, + qmRecordId, + showCallout, + }); + + showCallout({ messageId: 'ui-quick-marc.record.saveNew.success' }); + + if (marcType === MARC_TYPES.BIB && recordHasLinks(formValuesForCreate.fields)) { + await saveLinksToNewRecord(mutator, externalId, formValuesForCreate) + .catch(noop); + } + + if (continueAfterSave.current) { + await processEditingAfterCreation( + formValues, + externalId, + basePath, + location, + history, + refreshPageData, + marcType, + ); + + return; + } + + await redirectToRecord(externalId, instanceId, marcType, onSave); + } catch (err) { + // eslint-disable-next-line no-console + console.error(err); + showCallout({ + messageId: 'ui-quick-marc.record.saveNew.error', + type: 'error', + }); + } + }) + .catch(async (errorResponse) => { + const parsedError = await parseHttpError(errorResponse); + + setHttpError(parsedError); + }); + }, [ + showCallout, + prepareForSubmit, + actualizeLinks, + validationErrorsRef, + marcType, + continueAfterSave, + mutator, + basePath, + location, + history, + refreshPageData, + onSave, + ]); + + return { + onSubmit, + httpError, + runValidation, + }; +}; + +export { useMarcCreate }; diff --git a/src/QuickMarcEditor/useMarcDerive/index.js b/src/QuickMarcEditor/useMarcDerive/index.js new file mode 100644 index 00000000..044d1a72 --- /dev/null +++ b/src/QuickMarcEditor/useMarcDerive/index.js @@ -0,0 +1 @@ +export * from './useMarcDerive'; diff --git a/src/QuickMarcEditor/useMarcDerive/useMarcDerive.js b/src/QuickMarcEditor/useMarcDerive/useMarcDerive.js new file mode 100644 index 00000000..9e92b83a --- /dev/null +++ b/src/QuickMarcEditor/useMarcDerive/useMarcDerive.js @@ -0,0 +1,235 @@ +import { + useCallback, + useContext, + useMemo, + useState, +} from 'react'; +import { + useHistory, + useLocation, +} from 'react-router-dom'; +import flow from 'lodash/flow'; +import isEmpty from 'lodash/isEmpty'; +import noop from 'lodash/noop'; + +import { useStripes } from '@folio/stripes/core'; +import { useShowCallout } from '@folio/stripes-acq-components'; + +import { QuickMarcContext } from '../../contexts'; +import { + useAuthorityLinking, + useValidation, +} from '../../hooks'; +import { + applyCentralTenantInHeaders, + autopopulateFixedField, + autopopulateIndicators, + autopopulateMaterialCharsField, + autopopulatePhysDescriptionField, + autopopulateSubfieldSection, + cleanBytesFields, + combineSplitFields, + formatLeaderForSubmit, + hydrateMarcRecord, + parseHttpError, + processEditingAfterCreation, + recordHasLinks, + removeDeletedRecords, + removeEnteredDate, + removeFieldsForDerive, + saveLinksToNewRecord, +} from '../utils'; +import getQuickMarcRecordStatus from '../getQuickMarcRecordStatus'; + +const useMarcDerive = ({ + linksCount, + locations, + fixedFieldSpec, + mutator, + refreshPageData, + onClose, +}) => { + const history = useHistory(); + const location = useLocation(); + const stripes = useStripes(); + const showCallout = useShowCallout(); + + const [httpError, setHttpError] = useState(null); + + const { + action, + marcType, + initialValues, + instance, + validationErrorsRef, + continueAfterSave, + basePath, + } = useContext(QuickMarcContext); + + const { + linkableBibFields, + linkingRules, + sourceFiles, + actualizeLinks, + } = useAuthorityLinking({ marcType, action }); + + const isRequestToCentralTenantFromMember = applyCentralTenantInHeaders(location, stripes, marcType); + const centralTenantId = stripes.user.user.consortium?.centralTenantId; + const tenantId = isRequestToCentralTenantFromMember ? centralTenantId : ''; + + const validationContext = useMemo(() => ({ + initialValues, + marcType, + action, + linkableBibFields, + linkingRules, + fixedFieldSpec, + instanceId: instance?.id, + sourceFiles, + linksCount, + naturalId: instance?.naturalId, + locations, + }), [ + action, + instance?.naturalId, + linksCount, + initialValues, + marcType, + locations, + linkableBibFields, + linkingRules, + sourceFiles, + fixedFieldSpec, + instance?.id, + ]); + + const { validate } = useValidation(validationContext, tenantId); + + const prepareForSubmit = useCallback((formValues) => { + const formValuesForCreate = flow( + removeDeletedRecords, + removeFieldsForDerive, + removeEnteredDate, + autopopulateIndicators, + marcRecord => autopopulateFixedField(marcRecord, marcType, fixedFieldSpec), + autopopulatePhysDescriptionField, + autopopulateMaterialCharsField, + marcRecord => autopopulateSubfieldSection(marcRecord, marcType), + marcRecord => cleanBytesFields(marcRecord, fixedFieldSpec, marcType), + marcRecord => formatLeaderForSubmit(marcType, marcRecord), + combineSplitFields, + )(formValues); + + return formValuesForCreate; + }, [marcType, fixedFieldSpec]); + + const runValidation = useCallback(async (formValues) => { + const formValuesForValidation = prepareForSubmit(formValues); + + return validate(formValuesForValidation.records); + }, [validate, prepareForSubmit]); + + const onSubmit = useCallback(async (formValues, _api, complete) => { + // if validation has any issues - cancel submit + if (!isEmpty(validationErrorsRef.current)) { + return complete(); + } + + const formValuesToProcess = prepareForSubmit(formValues); + + showCallout({ messageId: 'ui-quick-marc.record.saveNew.onSave' }); + + let formValuesToHydrate; + + try { + formValuesToHydrate = await actualizeLinks(formValuesToProcess); + } catch (errorResponse) { + const parsedError = await parseHttpError(errorResponse); + + setHttpError(parsedError); + + return null; + } + + formValuesToHydrate.relatedRecordVersion = 1; + formValuesToHydrate._actionType = 'create'; + + const formValuesForDerive = hydrateMarcRecord(formValuesToHydrate); + + return mutator.quickMarcEditMarcRecord.POST(formValuesForDerive) + .then(async ({ qmRecordId }) => { + if (!continueAfterSave.current) { + onClose('id'); // https://issues.folio.org/browse/UIQM-82 + } + + try { + const { externalId } = await getQuickMarcRecordStatus({ + quickMarcRecordStatusGETRequest: mutator.quickMarcRecordStatus.GET, + qmRecordId, + showCallout, + }); + + showCallout({ messageId: 'ui-quick-marc.record.saveNew.success' }); + + if (continueAfterSave.current) { + if (recordHasLinks(formValuesForDerive.fields)) { + await saveLinksToNewRecord(mutator, externalId, formValuesForDerive) + .catch(noop); + } + + await processEditingAfterCreation( + formValues, + externalId, + basePath, + location, + history, + refreshPageData, + marcType, + ); + + return; + } + + if (recordHasLinks(formValuesForDerive.fields)) { + saveLinksToNewRecord(mutator, externalId, formValuesForDerive) + .finally(() => onClose(externalId)); + } else { + onClose(externalId); + } + } catch (err) { + // eslint-disable-next-line no-console + console.error(err); + showCallout({ + messageId: 'ui-quick-marc.record.saveNew.error', + type: 'error', + }); + } + }) + .catch(async (errorResponse) => { + const parsedError = await parseHttpError(errorResponse); + + setHttpError(parsedError); + }); + }, [ + onClose, + showCallout, + prepareForSubmit, + actualizeLinks, + validationErrorsRef, + continueAfterSave, + mutator, + basePath, + history, + location, + refreshPageData, + marcType, + ]); + + return { + onSubmit, + httpError, + runValidation, + }; +}; + +export { useMarcDerive }; diff --git a/src/QuickMarcEditor/useMarcEdit/index.js b/src/QuickMarcEditor/useMarcEdit/index.js new file mode 100644 index 00000000..b0e73a87 --- /dev/null +++ b/src/QuickMarcEditor/useMarcEdit/index.js @@ -0,0 +1 @@ +export * from './useMarcEdit'; diff --git a/src/QuickMarcEditor/useMarcEdit/useMarcEdit.js b/src/QuickMarcEditor/useMarcEdit/useMarcEdit.js new file mode 100644 index 00000000..175d0ed2 --- /dev/null +++ b/src/QuickMarcEditor/useMarcEdit/useMarcEdit.js @@ -0,0 +1,275 @@ +import { + useCallback, + useContext, + useMemo, + useState, +} from 'react'; +import { + useLocation, + useParams, +} from 'react-router-dom'; +import flow from 'lodash/flow'; +import isEmpty from 'lodash/isEmpty'; +import isNil from 'lodash/isNil'; + +import { useStripes } from '@folio/stripes/core'; +import { useShowCallout } from '@folio/stripes-acq-components'; +import { getHeaders } from '@folio/stripes-marc-components'; + +import { QuickMarcContext } from '../../contexts'; +import { + useAuthorityLinking, + useValidation, +} from '../../hooks'; +import { + applyCentralTenantInHeaders, + are010Or1xxUpdated, + autopopulateFixedField, + autopopulateIndicators, + autopopulateMaterialCharsField, + autopopulatePhysDescriptionField, + autopopulateSubfieldSection, + cleanBytesFields, + combineSplitFields, + formatLeaderForSubmit, + getFieldIds, + hydrateMarcRecord, + parseHttpError, + redirectToRecord, + removeDeletedRecords, + removeDuplicateSystemGeneratedFields, +} from '../utils'; +import { + ERROR_TYPES, + EXTERNAL_INSTANCE_APIS, + MARC_TYPES, +} from '../../common'; +import { useMarcRecordMutation } from '../../queries'; + +const useMarcEdit = ({ + linksCount, + locations, + fixedFieldSpec, + mutator, + refreshPageData, + onSave, +}) => { + const { + externalId: _externalId, + instanceId: _instanceId, + } = useParams(); + const location = useLocation(); + const stripes = useStripes(); + const showCallout = useShowCallout(); + + const { + action, + marcType, + initialValues, + instance, + validationErrorsRef, + relatedRecordVersion, + continueAfterSave, + } = useContext(QuickMarcContext); + + const [httpError, setHttpError] = useState(null); + + const { token, locale } = stripes.okapi; + const isRequestToCentralTenantFromMember = applyCentralTenantInHeaders(location, stripes, marcType); + const centralTenantId = stripes.user.user.consortium?.centralTenantId; + const tenantId = isRequestToCentralTenantFromMember ? centralTenantId : ''; + + const { + linkableBibFields, + linkingRules, + sourceFiles, + actualizeLinks, + } = useAuthorityLinking({ marcType, action }); + + const { updateMarcRecord } = useMarcRecordMutation({ tenantId }); + + const validationContext = useMemo(() => ({ + initialValues, + marcType, + action, + linkableBibFields, + linkingRules, + fixedFieldSpec, + instanceId: instance?.id, + sourceFiles, + linksCount, + naturalId: instance?.naturalId, + locations, + }), [ + action, + instance?.naturalId, + linksCount, + initialValues, + marcType, + locations, + linkableBibFields, + linkingRules, + sourceFiles, + fixedFieldSpec, + instance?.id, + ]); + + const { validate } = useValidation(validationContext, tenantId); + + const prepareForSubmit = useCallback((formValues) => { + const formValuesForCreate = flow( + removeDeletedRecords, + removeDuplicateSystemGeneratedFields, + marcRecord => formatLeaderForSubmit(marcType, marcRecord), + autopopulateIndicators, + marcRecord => autopopulateFixedField(marcRecord, marcType, fixedFieldSpec), + autopopulatePhysDescriptionField, + autopopulateMaterialCharsField, + marcRecord => autopopulateSubfieldSection(marcRecord, marcType), + marcRecord => cleanBytesFields(marcRecord, fixedFieldSpec, marcType), + combineSplitFields, + )(formValues); + + return formValuesForCreate; + }, [marcType, fixedFieldSpec]); + + const runValidation = useCallback(async (formValues) => { + const formValuesForValidation = prepareForSubmit(formValues); + + return validate(formValuesForValidation.records); + }, [validate, prepareForSubmit]); + + const onSubmit = useCallback(async (formValues, _api, complete) => { + let is1xxOr010Updated = false; + + // if validation has any issues - cancel submit + if (!isEmpty(validationErrorsRef.current)) { + return complete(); + } + + if (marcType === MARC_TYPES.AUTHORITY && linksCount > 0) { + is1xxOr010Updated = are010Or1xxUpdated(initialValues.records, formValues.records); + } + + const formValuesToProcess = prepareForSubmit(formValues); + + const path = EXTERNAL_INSTANCE_APIS[marcType]; + + const fetchInstance = async () => { + const fetchedInstance = await mutator.quickMarcEditInstance.GET({ + path: `${path}/${formValuesToProcess.externalId}`, + ...(isRequestToCentralTenantFromMember && { headers: getHeaders(centralTenantId, token, locale) }), + }); + + return fetchedInstance; + }; + + let formValuesToHydrate; + let instanceResponse; + + try { + const actualizeLinksPromise = marcType === MARC_TYPES.BIB + ? actualizeLinks(formValuesToProcess) + : Promise.resolve(formValuesToProcess); + + const [ + formValuesWithActualizedLinkedFields, + instanceData, + ] = await Promise.all([ + actualizeLinksPromise, + fetchInstance(), + ]); + + formValuesToHydrate = formValuesWithActualizedLinkedFields; + instanceResponse = instanceData; + } catch (errorResponse) { + const parsedError = await parseHttpError(errorResponse); + + setHttpError(parsedError); + + return undefined; + } + + const prevVersion = instance._version; + const lastVersion = instanceResponse._version; + + if (!isNil(prevVersion) && !isNil(lastVersion) && prevVersion !== lastVersion) { + setHttpError({ + errorType: ERROR_TYPES.OPTIMISTIC_LOCKING, + message: 'ui-quick-marc.record.save.error.derive', + }); + + return null; + } + + formValuesToHydrate._actionType = 'edit'; + formValuesToHydrate.relatedRecordVersion = marcType === MARC_TYPES.AUTHORITY + ? instance._version + : relatedRecordVersion; + + const formValuesToSave = hydrateMarcRecord(formValuesToHydrate); + const fn = () => Promise.resolve() + + return updateMarcRecord(formValuesToSave) + .then(async () => { + if (is1xxOr010Updated) { + const values = { + count: linksCount, + }; + + showCallout({ + messageId: 'ui-quick-marc.record.save.updatingLinkedBibRecords', + values, + }); + } else { + showCallout({ + messageId: 'ui-quick-marc.record.save.success.processing', + }); + } + + if (continueAfterSave.current) { + const fieldIds = getFieldIds(formValuesToHydrate); + + await refreshPageData(fieldIds); + + return; + } + + await redirectToRecord(_externalId, _instanceId, marcType, onSave); + }) + .catch(async (errorResponse) => { + const parsedError = await parseHttpError(errorResponse); + + setHttpError(parsedError); + }); + }, [ + showCallout, + refreshPageData, + initialValues, + instance, + marcType, + mutator, + linksCount, + prepareForSubmit, + actualizeLinks, + centralTenantId, + token, + locale, + updateMarcRecord, + isRequestToCentralTenantFromMember, + validationErrorsRef, + relatedRecordVersion, + _externalId, + _instanceId, + continueAfterSave, + onSave, + ]); + + return { + onSubmit, + httpError, + runValidation, + }; +}; + +export { useMarcEdit }; diff --git a/src/QuickMarcEditor/utils.js b/src/QuickMarcEditor/utils.js index ac4bd044..47dc3651 100644 --- a/src/QuickMarcEditor/utils.js +++ b/src/QuickMarcEditor/utils.js @@ -1266,3 +1266,37 @@ export const getFieldIds = (formValues) => { .filter(field => !field._isDeleted) .map(field => field.id); }; + +export const redirectToRecord = async (externalId, instanceId, marcType, onSave) => { + if (marcType === MARC_TYPES.HOLDINGS) { + await onSave(`${instanceId}/${externalId}`); + } else { + await onSave(externalId); + } +}; + +export const processEditingAfterCreation = async ( + formValues, + externalId, + basePath, + location, + history, + refreshPageData, + marcType, +) => { + const fieldIds = getFieldIds(formValues); + const searchParams = new URLSearchParams(location.search); + + const routes = { + [MARC_TYPES.BIB]: `${basePath}/edit-bibliographic/${externalId}`, + [MARC_TYPES.AUTHORITY]: `${basePath}/edit-authority/${externalId}`, + [MARC_TYPES.HOLDINGS]: `${basePath}/edit-holdings/${externalId}`, + }; + + await refreshPageData(fieldIds, QUICK_MARC_ACTIONS.EDIT, externalId); + + history.push({ + pathname: routes[marcType], + search: searchParams.toString(), + }); +};