diff --git a/CHANGELOG.md b/CHANGELOG.md index 551e9bb..64be73b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change history for ui-plugin-find-authority +## [3.1.0] (IN PROGRESS) + +* [UIPFAUTH-83](https://issues.folio.org/browse/UIPFAUTH-83) Resolve circular dependency with ui-quick-marc. Clone QuickMarcView component from `ui-quick-marc`. + ## [3.0.0] (https://github.com/folio-org/ui-plugin-find-authority/tree/v3.0.0) (2023-10-13) * [UIPFAUTH-44](https://issues.folio.org/browse/UIPFAUTH-44) Show an error message in modal after linking. diff --git a/package.json b/package.json index 54321a1..1c306ce 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,6 @@ "regenerator-runtime": "^0.13.3" }, "dependencies": { - "@folio/quick-marc": "^7.0.0", "query-string": "^7.0.1" }, "peerDependencies": { diff --git a/src/components/MarcAuthorityView/MarcAuthorityView.js b/src/components/MarcAuthorityView/MarcAuthorityView.js index 13da116..8f7662d 100644 --- a/src/components/MarcAuthorityView/MarcAuthorityView.js +++ b/src/components/MarcAuthorityView/MarcAuthorityView.js @@ -26,8 +26,8 @@ import { useNamespace, useStripes, } from '@folio/stripes/core'; -import MarcView from '@folio/quick-marc/src/QuickMarcView/QuickMarcView'; +import MarcView from '../../temp/QuickMarcView/QuickMarcView'; import { headFieldValue, isConsortiaEnv, diff --git a/src/temp/QuickMarcView/MarcContent/MarcContent.css b/src/temp/QuickMarcView/MarcContent/MarcContent.css new file mode 100644 index 0000000..a6f1401 --- /dev/null +++ b/src/temp/QuickMarcView/MarcContent/MarcContent.css @@ -0,0 +1,14 @@ +.marcWrapper { + margin-left: 20px; +} + +.marc { + table-layout: fixed; + border: 0; + font-family: courier; + white-space: pre-wrap; + + & tr td { + vertical-align: top; + } +} diff --git a/src/temp/QuickMarcView/MarcContent/MarcContent.js b/src/temp/QuickMarcView/MarcContent/MarcContent.js new file mode 100644 index 0000000..6aceaa6 --- /dev/null +++ b/src/temp/QuickMarcView/MarcContent/MarcContent.js @@ -0,0 +1,71 @@ +import PropTypes from 'prop-types'; + +import { Headline } from '@folio/stripes/components'; + +import MarcField from '../MarcField'; +import { isControlField } from '../utils'; +import styles from './MarcContent.css'; + +const propTypes = { + isPrint: PropTypes.bool, + marc: PropTypes.object.isRequired, + marcTitle: PropTypes.node.isRequired, + tenantId: PropTypes.string, +}; + +const defaultProps = { + isPrint: false, + tenantId: '', +}; + +const MarcContent = ({ + marcTitle, + marc, + isPrint, + tenantId, +}) => { + const showLinkIcon = marc.recordType === 'MARC_BIB'; + const parsedContent = marc.parsedRecord.content; + const parsedMarc = { + leader: parsedContent.leader, + fields: [ + ...parsedContent.fields.filter(isControlField), + ...parsedContent.fields.filter(field => !isControlField(field)), + ], + }; + + return ( +
+ + {marcTitle} + + + + + + + {parsedMarc.fields.map(field => ( + + ))} + +
+ {`LEADER ${parsedMarc.leader}`} +
+
+ ); +}; + +MarcContent.propTypes = propTypes; +MarcContent.defaultProps = defaultProps; + +export default MarcContent; diff --git a/src/temp/QuickMarcView/MarcContent/MarcContent.test.js b/src/temp/QuickMarcView/MarcContent/MarcContent.test.js new file mode 100644 index 0000000..7a51ea5 --- /dev/null +++ b/src/temp/QuickMarcView/MarcContent/MarcContent.test.js @@ -0,0 +1,66 @@ +import { render } from '@folio/jest-config-stripes/testing-library/react'; + +import { runAxeTest } from '@folio/stripes-testing'; + +import Harness from '../../../../test/jest/helpers/harness'; + +import MarcContent from './MarcContent'; + +jest.mock('../MarcField', () => jest.fn(() => MarcField)); + +const marc = { + parsedRecord: { + id: 'a178daf3-b10a-4ff9-a4bf-703a0091f043', + content: { + fields: [{ + '001': 'in00000000140', + }, { + '008': '120126r20122010nyu b 001 0 eng ', + }], + leader: '00331cam a2200085 a 4500', + }, + }, + recordType: 'MARC_BIB', +}; + +const renderMarcContent = (props = {}) => render( + + fakeMarkTitle} + marc={marc} + {...props} + /> + , +); + +describe('Given MarcContent', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should render with no axe errors', async () => { + const { container } = renderMarcContent(); + + await runAxeTest({ + rootNode: container, + }); + }); + + it('should show the marc title', () => { + const { getByText } = renderMarcContent(); + + expect(getByText('fakeMarkTitle')).toBeVisible(); + }); + + it('should display the content of the marc record', () => { + const { getByText } = renderMarcContent(); + + expect(getByText('LEADER 00331cam a2200085 a 4500')).toBeVisible(); + }); + + it('should render list of marc fields', () => { + const { getAllByText } = renderMarcContent(); + + expect(getAllByText('MarcField').length).toBe(2); + }); +}); diff --git a/src/temp/QuickMarcView/MarcContent/index.js b/src/temp/QuickMarcView/MarcContent/index.js new file mode 100644 index 0000000..3f46392 --- /dev/null +++ b/src/temp/QuickMarcView/MarcContent/index.js @@ -0,0 +1 @@ +export { default } from './MarcContent'; diff --git a/src/temp/QuickMarcView/MarcField.css b/src/temp/QuickMarcView/MarcField.css new file mode 100644 index 0000000..479c4b7 --- /dev/null +++ b/src/temp/QuickMarcView/MarcField.css @@ -0,0 +1,3 @@ +.indicators { + width: 30px; +} diff --git a/src/temp/QuickMarcView/MarcField.js b/src/temp/QuickMarcView/MarcField.js new file mode 100644 index 0000000..e7b604a --- /dev/null +++ b/src/temp/QuickMarcView/MarcField.js @@ -0,0 +1,60 @@ +import { Fragment } from 'react'; +import PropTypes from 'prop-types'; + +import { normalizeIndicator } from './utils'; + +import styles from './MarcField.css'; + +const propTypes = { + field: PropTypes.object.isRequired, +}; + +const MarcField = ({ + field, +}) => { + const fieldTag = Object.keys(field)[0]; + const hasIndicators = typeof field[fieldTag] !== 'string'; + const subFields = hasIndicators + ? field[fieldTag].subfields.map(subFieldTag => { + const subKey = Object.keys(subFieldTag)[0]; + + const subfieldValue = field[fieldTag].isHighlighted + ? {subFieldTag[subKey]} + : subFieldTag[subKey]; + + return ( + + + {subKey} + {' '} + {subfieldValue} + {' '} + + ); + }) + : field[fieldTag].replace(/\\/g, ' '); + + return ( + + + {fieldTag} + + + { + hasIndicators && ( + + {`${normalizeIndicator(field[fieldTag].ind1)} ${normalizeIndicator(field[fieldTag].ind2)}`} + + ) + } + + + {subFields} + + + ); +}; + +MarcField.propTypes = propTypes; + +export default MarcField; diff --git a/src/temp/QuickMarcView/QuickMarcView.js b/src/temp/QuickMarcView/QuickMarcView.js new file mode 100644 index 0000000..5c4dd3f --- /dev/null +++ b/src/temp/QuickMarcView/QuickMarcView.js @@ -0,0 +1,90 @@ +import PropTypes from 'prop-types'; + +import { + Pane, + Paneset, +} from '@folio/stripes/components'; + +import MarcContent from './MarcContent'; + +const propTypes = { + isPaneset: PropTypes.bool, + lastMenu: PropTypes.node, + marc: PropTypes.object.isRequired, + marcTitle: PropTypes.node.isRequired, + onClose: PropTypes.func.isRequired, + paneHeight: PropTypes.string, + paneSub: PropTypes.oneOfType([ + PropTypes.node, + PropTypes.string, + ]), + paneTitle: PropTypes.oneOfType([ + PropTypes.node, + PropTypes.string, + ]).isRequired, + paneWidth: PropTypes.string, + tenantId: PropTypes.string, +}; + +const defaultProps = { + isPaneset: true, + paneHeight: null, + lastMenu: null, + paneSub: null, + paneWidth: '', + tenantId: '', +}; + +/* + This is a temporarily copied component from ui-quick-marc to resolve a ciecular dependency. + TODO: Remove it from here after https://issues.folio.org/browse/UIQM-570 is done. +*/ +const QuickMarcView = ({ + paneTitle, + paneSub, + paneHeight, + marcTitle, + marc, + onClose, + paneWidth, + lastMenu, + isPaneset, + tenantId, +}) => { + const renderContent = () => ( + + + + ); + + return isPaneset + ? ( + + {renderContent()} + + ) + : renderContent(); +}; + +QuickMarcView.propTypes = propTypes; +QuickMarcView.defaultProps = defaultProps; + +export default QuickMarcView; diff --git a/src/temp/QuickMarcView/QuickMarcView.test.js b/src/temp/QuickMarcView/QuickMarcView.test.js new file mode 100644 index 0000000..412cdc6 --- /dev/null +++ b/src/temp/QuickMarcView/QuickMarcView.test.js @@ -0,0 +1,142 @@ +import { render } from '@folio/jest-config-stripes/testing-library/react'; + +import { runAxeTest } from '@folio/stripes-testing'; + +import QuickMarcView from './QuickMarcView'; + +import Harness from '../../../test/jest/helpers/harness'; + +const marc = { + parsedRecord: { + id: 'a178daf3-b10a-4ff9-a4bf-703a0091f043', + content: { + fields: [{ + '001': 'in00000000140', + }, { + '008': '120126r20122010nyu b 001 0 eng ', + }, { + '005': '20211207090250.8', + }, { + '100': { + 'ind1': '/', + 'ind2': '/', + subfields: [{ + a: 'Some controlled value', + }, { + 9: 'authority-id', + }], + }, + }, { + '245': { + 'ind1': '1', + 'ind2': '0', + subfields: [{ + a: 'Across the line of control :', + }, { + b: 'inside Pakistan-administered Jammu and Kashmir /', + }, { + b: 'Luv Puri.', + }], + isHighlighted: true, + }, + }, { + '999': { + ind1: 'f', + ind2: 'f', + subfields: [{ + s: '225f733f-8231-4d48-b104-a9c56d675eec', + }, { + i: '225f733f-8231-4d48-b104-a9c56d675eec', + }], + }, + }], + leader: '00331cam a2200085 a 4500', + }, + }, + recordType: 'MARC_BIB', +}; + +const mockOnClose = jest.fn(); + +const renderQuickMarcView = (props = {}) => render( + + + , +); + +describe('Given QuickMarcView', () => { + it('should render with no axe errors', async () => { + const { container } = renderQuickMarcView(); + + await runAxeTest({ + rootNode: container, + }); + }); + + it('should show pane title', () => { + const { getByText } = renderQuickMarcView(); + + expect(getByText('Pane title')).toBeDefined(); + }); + + it('should show pane sub', () => { + const { getByText } = renderQuickMarcView(); + + expect(getByText('Pane sub')).toBeDefined(); + }); + + it('should show MARC title', () => { + const { getByText } = renderQuickMarcView(); + + expect(getByText('MARC title')).toBeDefined(); + }); + + it('should show MARC leader', () => { + const { getByText } = renderQuickMarcView(); + + expect(getByText(`LEADER ${marc.parsedRecord.content.leader}`)).toBeDefined(); + }); + + it('should render paneset wrapper', () => { + const { getByTestId } = renderQuickMarcView(); + + expect(getByTestId('qm-view-paneset')).toBeDefined(); + }); + + describe('when a field has isHighlighted flag', () => { + it('should highlight the field content', () => { + const { container } = renderQuickMarcView(); + + const highlightedContent = [...container.querySelectorAll('mark')].map(mark => mark.textContent).join(' '); + + expect(highlightedContent).toEqual('Across the line of control : inside Pakistan-administered Jammu and Kashmir / Luv Puri.'); + }); + }); + + describe('when "isPaneset" prop is false', () => { + it('should not render paneset wrapper', () => { + const { queryByTestId } = renderQuickMarcView({ + isPaneset: false, + }); + + expect(queryByTestId('qm-view-paneset')).toBeNull(); + }); + }); + + describe('when present "lastMenu" prop', () => { + it('should render "lastMenu" prop', () => { + const { getByText } = renderQuickMarcView({ + lastMenu:
Last Menu Node
, + }); + + expect(getByText('Last Menu Node')).toBeDefined(); + }); + }); +}); diff --git a/src/temp/QuickMarcView/utils.js b/src/temp/QuickMarcView/utils.js new file mode 100644 index 0000000..ca7a4a5 --- /dev/null +++ b/src/temp/QuickMarcView/utils.js @@ -0,0 +1,3 @@ +export const isControlField = field => (Object.keys(field)[0]).startsWith('00'); + +export const normalizeIndicator = indictor => indictor.replace(/\\/g, ' ');