Skip to content

Commit

Permalink
UIIN-2896 Inventory app: Define and implement shortcut key for editin…
Browse files Browse the repository at this point in the history
…g a quickMARC bib record (#2479)

* UIIN-2896 Inventory app: Define and implement shortcut key for editing a quickMARC bib record

* UIIN-2896 added tests for new edit marc record shortcuts

* UIIN-2896 disable edit MARC record for source FOLIO

* UIIN-2896 Added a util to redirect to edit MARC page
  • Loading branch information
BogdanDenis authored May 20, 2024
1 parent 23c2402 commit 92818ca
Show file tree
Hide file tree
Showing 11 changed files with 213 additions and 56 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* Add callout noting user's active affiliation when it changes after selecting holding or item. Refs UIIN-2831, UIIN-2872.
* Jest/RTL: Cover LocationSelectionWithCheck components with unit tests. Refs UIIN-2670.
* Populate Acquisitions accordion on instance when central ordering is active. Refs UIIN-2793.
* Inventory app: Define and implement shortcut key for editing a quickMARC bib record. Refs UIIN-2896.

## [11.0.4](https://github.com/folio-org/ui-inventory/tree/v11.0.4) (2024-04-30)
[Full Changelog](https://github.com/folio-org/ui-inventory/compare/v11.0.3...v11.0.4)
Expand Down
10 changes: 10 additions & 0 deletions src/ViewHoldingsRecord.js
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,16 @@ class ViewHoldingsRecord extends React.Component {
if (stripes.hasPerm('ui-inventory.holdings.edit')) this.onEditHolding();
}),
},
{
name: 'editMARC',
handler: handleKeyCommand(() => {
if (!stripes.hasPerm('ui-quick-marc.quick-marc-editor.all') || !this.isMARCSource()) {
return;
}

this.handleEditInQuickMarc();
}),
},
{
name: 'expandAllSections',
handler: (e) => expandAllSections(e, this.accordionStatusRef),
Expand Down
20 changes: 18 additions & 2 deletions src/ViewHoldingsRecord.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@ const spyOncollapseAllSections = jest.spyOn(require('@folio/stripes/components')
const spyOnexpandAllSections = jest.spyOn(require('@folio/stripes/components'), 'expandAllSections');

const mockData = jest.fn().mockResolvedValue({ id: 'testId' });
const mockGoTo = jest.fn();

const defaultProps = {
id: 'id',
goTo: jest.fn(),
goTo: mockGoTo,
holdingsrecordid: 'holdingId',
referenceTables: {
holdingsSources: [{ id: 'sourceId', name: 'MARC' }],
Expand All @@ -57,7 +58,12 @@ const defaultProps = {
resources: {
holdingsRecords: {
records: [
{ sourceId: 'sourceId', temporaryLocationId: 'inactiveLocation' }
{
sourceId: 'sourceId',
temporaryLocationId: 'inactiveLocation',
id: 'holdingId',
_version: 1,
}
],
},
instances1: { records: [{ id: 'instanceId' }], hasLoaded: true },
Expand Down Expand Up @@ -270,4 +276,14 @@ describe('ViewHoldingsRecord actions', () => {
expect(spyOnexpandAllSections).toHaveBeenCalled();
});
});

describe('when using an editMARC shortcut', () => {
it('should redirect to marc edit page', async () => {
await act(async () => { renderViewHoldingsRecord(); });

fireEvent.click(screen.getByRole('button', { name: 'editMARC' }));

expect(mockGoTo).toHaveBeenLastCalledWith(`/inventory/quick-marc/edit-holdings/instanceId/${defaultProps.holdingsrecordid}?%2F=&relatedRecordVersion=1`);
});
});
});
23 changes: 13 additions & 10 deletions src/ViewInstance.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
isMARCSource,
getLinkedAuthorityIds,
setRecordForDeletion,
redirectToMarcEditPage,
} from './utils';
import {
CONSORTIUM_PREFIX,
Expand Down Expand Up @@ -339,21 +340,12 @@ class ViewInstance extends React.Component {
history,
location,
stripes,
isShared,
} = this.props;

const ci = makeConnectedInstance(this.props, stripes.logger);
const instance = ci.instance();

const searchParams = new URLSearchParams(location.search);

searchParams.delete('relatedRecordVersion');
searchParams.append('shared', isShared.toString());

history.push({
pathname: `/inventory/quick-marc/${page}/${instance.id}`,
search: searchParams.toString(),
});
redirectToMarcEditPage(`/inventory/quick-marc/${page}/${instance.id}`, instance, location, history);
};

editInstanceMarc = () => {
Expand Down Expand Up @@ -1042,6 +1034,7 @@ class ViewInstance extends React.Component {
onCopy,
updateLocation,
canUseSingleRecordImport,
selectedInstance,
} = this.props;
const {
linkedAuthoritiesLength,
Expand All @@ -1066,6 +1059,16 @@ class ViewInstance extends React.Component {
if (stripes.hasPerm('ui-inventory.instance.edit')) this.onClickEditInstance();
}),
},
{
name: 'editMARC',
handler: handleKeyCommand(() => {
if (!stripes.hasPerm('ui-quick-marc.quick-marc-editor.all') || !isMARCSource(selectedInstance.source)) {
return;
}

this.editInstanceMarc();
}),
},
{
name: 'duplicateRecord',
handler: handleKeyCommand(() => {
Expand Down
24 changes: 22 additions & 2 deletions src/ViewInstance.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,7 @@ describe('ViewInstance', () => {
renderViewInstance();
const expectedValue = {
pathname: `/inventory/quick-marc/edit-bib/${defaultProp.selectedInstance.id}`,
search: 'filters=test1&query=test2&sort=test3&qindex=test&shared=false',
search: 'filters=test1&query=test2&sort=test3&qindex=test',
};
fireEvent.click(screen.getByRole('button', { name: 'Actions' }));
const button = screen.getByRole('button', { name: 'Edit MARC bibliographic record' });
Expand Down Expand Up @@ -929,7 +929,7 @@ describe('ViewInstance', () => {
renderViewInstance({ isShared: false });
const expectedValue = {
pathname: `/inventory/quick-marc/duplicate-bib/${defaultProp.selectedInstance.id}`,
search: 'filters=test1&query=test2&sort=test3&qindex=test&shared=false',
search: 'filters=test1&query=test2&sort=test3&qindex=test',
};
fireEvent.click(screen.getByRole('button', { name: 'Actions' }));
const button = screen.getByRole('button', { name: 'Derive new MARC bibliographic record' });
Expand Down Expand Up @@ -1162,4 +1162,24 @@ describe('ViewInstance', () => {
expect(spyOnexpandAllSections).toBeCalled();
});
});

describe('when using an editMARC shortcut', () => {
it('should redirect to marc edit page', () => {
const selectedInstance = {
...instances[0],
shared: true,
};

StripesConnectedInstance.prototype.instance.mockImplementation(() => selectedInstance);

renderViewInstance({ selectedInstance });

fireEvent.click(screen.getByRole('button', { name: 'editMARC' }));

expect(mockPush).toHaveBeenLastCalledWith({
pathname: `/inventory/quick-marc/edit-bib/${instance.id}`,
search: 'filters=test1&query=test2&sort=test3&qindex=test&shared=true',
});
});
});
});
86 changes: 61 additions & 25 deletions src/components/ViewSource/ViewSource.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import React, {
useState,
useEffect,
useMemo,
useCallback,
} from 'react';
import {
useLocation,
useHistory,
} from 'react-router-dom';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';

import {
Button,
LoadingView,
HasCommand,
checkScope,
} from '@folio/stripes/components';
import { useStripes } from '@folio/stripes/core';
import {
Expand All @@ -18,7 +26,11 @@ import {

import { useGoBack } from '../../common/hooks';

import { isUserInConsortiumMode } from '../../utils';
import {
isUserInConsortiumMode,
handleKeyCommand,
redirectToMarcEditPage,
} from '../../utils';
import MARC_TYPES from './marcTypes';

import styles from './ViewSource.css';
Expand All @@ -33,6 +45,8 @@ const ViewSource = ({
marcType,
}) => {
const stripes = useStripes();
const location = useLocation();
const history = useHistory();
const [isShownPrintPopup, setIsShownPrintPopup] = useState(false);
const openPrintPopup = () => setIsShownPrintPopup(true);
const closePrintPopup = () => setIsShownPrintPopup(false);
Expand All @@ -51,6 +65,22 @@ const ViewSource = ({
const [marc, setMarc] = useState();
const [isMarcLoading, setIsMarcLoading] = useState(true);

const redirectToMARCEdit = useCallback(() => {
const urlId = isHoldingsRecord ? `${instanceId}/${holdingsRecordId}` : instanceId;
const pathname = `/inventory/quick-marc/edit-${isHoldingsRecord ? 'holdings' : 'bib'}/${urlId}`;

redirectToMarcEditPage(pathname, instance, location, history);
}, [isHoldingsRecord]);

const shortcuts = useMemo(() => [
{
name: 'editMARC',
handler: handleKeyCommand(() => {
if (stripes.hasPerm('ui-quick-marc.quick-marc-editor.all')) redirectToMARCEdit();
}),
},
], [stripes, redirectToMARCEdit]);

useEffect(() => {
setIsMarcLoading(true);

Expand Down Expand Up @@ -94,32 +124,38 @@ const ViewSource = ({
);

return (
<div className={styles.viewSource}>
<MarcView
paneTitle={paneTitle}
marcTitle={marcTitle}
marc={marc}
onClose={goBack}
lastMenu={
isPrintAvailable &&
<Button
marginBottom0
buttonStyle="primary"
onClick={openPrintPopup}
>
<FormattedMessage id="ui-quick-marc.print" />
</Button>
}
/>
{isPrintAvailable && isShownPrintPopup && (
<PrintPopup
marc={marc}
paneTitle={instance.title}
<HasCommand
commands={shortcuts}
isWithinScope={checkScope}
scope={document.body}
>
<div className={styles.viewSource}>
<MarcView
paneTitle={paneTitle}
marcTitle={marcTitle}
onAfterPrint={closePrintPopup}
marc={marc}
onClose={goBack}
lastMenu={
isPrintAvailable &&
<Button
marginBottom0
buttonStyle="primary"
onClick={openPrintPopup}
>
<FormattedMessage id="ui-quick-marc.print" />
</Button>
}
/>
)}
</div>
{isPrintAvailable && isShownPrintPopup && (
<PrintPopup
marc={marc}
paneTitle={instance.title}
marcTitle={marcTitle}
onAfterPrint={closePrintPopup}
/>
)}
</div>
</HasCommand>
);
};

Expand Down
32 changes: 31 additions & 1 deletion src/components/ViewSource/ViewSource.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import {
BrowserRouter as Router,
useHistory,
} from 'react-router-dom';
import { act } from 'react-dom/test-utils';

import {
Expand All @@ -18,6 +21,12 @@ import { CONSORTIUM_PREFIX } from '../../constants';
import MARC_TYPES from './marcTypes';

jest.mock('../../common/hooks/useGoBack', () => jest.fn());
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useHistory: jest.fn().mockReturnValue({
push: jest.fn(),
}),
}));

const mutator = {
marcRecord: {
Expand All @@ -26,6 +35,7 @@ const mutator = {
};

const mockGoBack = jest.fn();
const mockPush = jest.fn();
const mockInstance = {
id: 'instance-id',
title: 'Instance title',
Expand All @@ -49,6 +59,9 @@ const getViewSource = (props = {}) => (

describe('ViewSource', () => {
beforeEach(() => {
useHistory.mockClear().mockReturnValue({
push: mockPush,
});
useGoBack.mockReturnValue(mockGoBack);
});

Expand Down Expand Up @@ -153,4 +166,21 @@ describe('ViewSource', () => {
expect(screen.getByText('Local MARC bibliographic record')).toBeInTheDocument();
});
});

describe('when using an editMARC shortcut', () => {
beforeEach(async () => {
await act(async () => {
await renderWithIntl(getViewSource(), translations);
});
});

it('should redirect to marc edit page', () => {
fireEvent.click(screen.getByRole('button', { name: 'editMARC' }));

expect(mockPush).toHaveBeenLastCalledWith({
pathname: `/inventory/quick-marc/edit-bib/${mockInstance.id}`,
search: '',
});
});
});
});
Loading

0 comments on commit 92818ca

Please sign in to comment.