From a4193deb0c55320daa9289f00f91f145e435605e Mon Sep 17 00:00:00 2001 From: Alisher Musurmonov Date: Tue, 7 Nov 2023 14:52:51 +0500 Subject: [PATCH] UISACQCOMP-166: configure the plugin via props --- lib/DonorsList/AddDonorButton.js | 26 +++++++-- lib/DonorsList/DonorsContainer.js | 82 +++++++++++++++------------- lib/DonorsList/DonorsForm.js | 56 +++++++++++++++++++ lib/DonorsList/DonorsForm.test.js | 89 +++++++++++++++++++++++++++++++ lib/DonorsList/DonorsList.js | 59 +++++++++++--------- lib/DonorsList/constants.js | 6 +-- lib/DonorsList/index.js | 2 +- 7 files changed, 251 insertions(+), 69 deletions(-) create mode 100644 lib/DonorsList/DonorsForm.js create mode 100644 lib/DonorsList/DonorsForm.test.js diff --git a/lib/DonorsList/AddDonorButton.js b/lib/DonorsList/AddDonorButton.js index f470de74..2a0d6b4d 100644 --- a/lib/DonorsList/AddDonorButton.js +++ b/lib/DonorsList/AddDonorButton.js @@ -13,7 +13,15 @@ import { visibleFilters, } from './constants'; -const AddDonorButton = ({ onAddDonors, fields, stripes, name }) => { +const AddDonorButton = ({ + fields, + name, + onAddDonors, + searchLabel, + showTriggerButton, + stripes, + visibleColumns, +}) => { const addDonors = (donors = []) => { const addedDonorIds = new Set(fields.value); const newDonorsIds = map(donors.filter(({ id }) => !addedDonorIds.has(id)), 'id'); @@ -24,20 +32,24 @@ const AddDonorButton = ({ onAddDonors, fields, stripes, name }) => { } }; + if (!showTriggerButton) { + return null; + } + return ( } + searchLabel={searchLabel} searchButtonStyle="default" disableRecordCreation stripes={stripes} selectVendor={addDonors} modalLabel={modalLabel} resultsPaneTitle={resultsPaneTitle} - visibleColumns={pluginVisibleColumns} + visibleColumns={visibleColumns} initialFilters={initialFilters} searchableIndexes={searchableIndexes} visibleFilters={visibleFilters} @@ -55,6 +67,14 @@ AddDonorButton.propTypes = { fields: PropTypes.object, stripes: PropTypes.object, name: PropTypes.string.isRequired, + showTriggerButton: PropTypes.bool, + searchLabel: PropTypes.node, + visibleColumns: PropTypes.arrayOf(PropTypes.string), }; +AddDonorButton.defaultProps = { + showTriggerButton: true, + searchLabel: , + visibleColumns: pluginVisibleColumns, +}; export default AddDonorButton; diff --git a/lib/DonorsList/DonorsContainer.js b/lib/DonorsList/DonorsContainer.js index 3c914f5e..7812670d 100644 --- a/lib/DonorsList/DonorsContainer.js +++ b/lib/DonorsList/DonorsContainer.js @@ -1,52 +1,62 @@ -import React, { useState } from 'react'; import PropTypes from 'prop-types'; -import { FieldArray } from 'react-final-form-arrays'; -import { - Col, - Loading, - Row, -} from '@folio/stripes/components'; +import { useStripes } from '@folio/stripes/core'; +import AddDonorButton from './AddDonorButton'; import DonorsList from './DonorsList'; -import { useFetchDonors } from './hooks'; - -function DonorsContainer({ name, donorOrganizationIds }) { - const [donorIds, setDonorIds] = useState(donorOrganizationIds); - const { donors, isLoading } = useFetchDonors(donorIds); - - const donorsMap = donors.reduce((acc, contact) => { - acc[contact.id] = contact; - - return acc; - }, {}); - - if (isLoading) { - return ; - } +import { defaultVisibleColumns } from './constants'; + +function DonorsContainer({ + donorsMap, + fields, + id, + setDonorIds, + showTriggerButton, + visibleColumns, + ...rest +}) { + const stripes = useStripes(); return ( - - - - - + <> + +
+ { + showTriggerButton && ( + + ) + } + ); } DonorsContainer.propTypes = { - name: PropTypes.string.isRequired, - donorOrganizationIds: PropTypes.arrayOf(PropTypes.string), + columnWidths: PropTypes.object, + donorsMap: PropTypes.object, + fields: PropTypes.object, + formatter: PropTypes.object, + id: PropTypes.string.isRequired, + searchLabel: PropTypes.node, + setDonorIds: PropTypes.func.isRequired, + showTriggerButton: PropTypes.bool, + visibleColumns: PropTypes.arrayOf(PropTypes.string), }; DonorsContainer.defaultProps = { - donorOrganizationIds: [], + showTriggerButton: true, + visibleColumns: defaultVisibleColumns, }; export default DonorsContainer; diff --git a/lib/DonorsList/DonorsForm.js b/lib/DonorsList/DonorsForm.js new file mode 100644 index 00000000..5164ba0e --- /dev/null +++ b/lib/DonorsList/DonorsForm.js @@ -0,0 +1,56 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import { FieldArray } from 'react-final-form-arrays'; + +import { + Col, + Loading, + Row, +} from '@folio/stripes/components'; + +import DonorsContainer from './DonorsContainer'; +import { useFetchDonors } from './hooks'; + +function DonorsForm({ name, donorOrganizationIds, ...rest }) { + const [donorIds, setDonorIds] = useState(donorOrganizationIds); + const { donors, isLoading } = useFetchDonors(donorIds); + + const donorsMap = donors.reduce((acc, contact) => { + acc[contact.id] = contact; + + return acc; + }, {}); + + if (isLoading) { + return ; + } + + return ( + + + + + + ); +} + +DonorsForm.propTypes = { + donorOrganizationIds: PropTypes.arrayOf(PropTypes.string), + name: PropTypes.string.isRequired, + searchLabel: PropTypes.node, + showTriggerButton: PropTypes.bool, + visibleColumns: PropTypes.arrayOf(PropTypes.string), +}; + +DonorsForm.defaultProps = { + donorOrganizationIds: [], +}; + +export default DonorsForm; diff --git a/lib/DonorsList/DonorsForm.test.js b/lib/DonorsList/DonorsForm.test.js new file mode 100644 index 00000000..ac196e29 --- /dev/null +++ b/lib/DonorsList/DonorsForm.test.js @@ -0,0 +1,89 @@ +import { MemoryRouter } from 'react-router-dom'; +import { render, screen } from '@testing-library/react'; + +import stripesFinalForm from '@folio/stripes/final-form'; + +import DonorsForm from './DonorsForm'; +import { useFetchDonors } from './hooks'; + +jest.mock('@folio/stripes/components', () => ({ + ...jest.requireActual('@folio/stripes/components'), + Loading: jest.fn(() => 'Loading'), +})); + +jest.mock('./DonorsList', () => jest.fn(({ donorsMap }) => { + if (!Object.values(donorsMap).length) { + return 'stripes-components.tableEmpty'; + } + + return Object.values(donorsMap).map(({ name }) =>
{name}
); +})); + +jest.mock('./hooks', () => ({ + useFetchDonors: jest.fn().mockReturnValue({ + donors: [], + isLoading: false, + }), +})); + +const defaultProps = { + name: 'donors', + donorOrganizationIds: [], +}; + +const renderForm = (props = {}) => ( +
+ + + +); + +const FormCmpt = stripesFinalForm({})(renderForm); + +const renderComponent = (props = {}) => (render( + + { }} {...props} /> + , +)); + +describe('DonorsForm', () => { + beforeEach(() => { + useFetchDonors.mockClear().mockReturnValue({ + donors: [], + isLoading: false, + }); + }); + + it('should render component', () => { + renderComponent(); + + expect(screen.getByText('stripes-components.tableEmpty')).toBeDefined(); + }); + + it('should render Loading component', () => { + useFetchDonors.mockClear().mockReturnValue({ + donors: [], + isLoading: true, + }); + + renderComponent(); + + expect(screen.getByText('Loading')).toBeDefined(); + }); + + it('should call `useFetchDonors` with `donorOrganizationIds`', () => { + const mockData = [{ name: 'Amazon', code: 'AMAZ', id: '1' }]; + + useFetchDonors.mockClear().mockReturnValue({ + donors: mockData, + isLoading: false, + }); + + renderComponent({ donorOrganizationIds: ['1'] }); + + expect(screen.getByText(mockData[0].name)).toBeDefined(); + }); +}); diff --git a/lib/DonorsList/DonorsList.js b/lib/DonorsList/DonorsList.js index c17e54a1..b11a82ef 100644 --- a/lib/DonorsList/DonorsList.js +++ b/lib/DonorsList/DonorsList.js @@ -9,14 +9,12 @@ import { MultiColumnList, TextLink, } from '@folio/stripes/components'; -import { useStripes } from '@folio/stripes/core'; -import AddDonorButton from './AddDonorButton'; import { alignRowProps, - columnMapping, - columnWidths, - visibleColumns, + defaultColumnMapping, + defaultColumnWidths, + defaultVisibleColumns, } from './constants'; const getDonorUrl = (orgId) => { @@ -50,9 +48,17 @@ const getResultsFormatter = ({ ), }); -const DonorsList = ({ setDonorIds, fields, donorsMap, id }) => { +const DonorsList = ({ + columnMapping, + columnWidths, + donorsMap, + fields, + formatter, + id, + stripes, + visibleColumns, +}) => { const intl = useIntl(); - const stripes = useStripes(); const canViewOrganizations = stripes.hasPerm('ui-organizations.view'); const donors = useMemo(() => (fields.value || []) @@ -72,32 +78,33 @@ const DonorsList = ({ setDonorIds, fields, donorsMap, id }) => { }, [canViewOrganizations, fields, intl]); return ( - <> - -
- - + ); }; DonorsList.propTypes = { - setDonorIds: PropTypes.func.isRequired, fields: PropTypes.object, donorsMap: PropTypes.object, id: PropTypes.string.isRequired, + stripes: PropTypes.object, + visibleColumns: PropTypes.arrayOf(PropTypes.string), + formatter: PropTypes.object, + columnWidths: PropTypes.object, + columnMapping: PropTypes.object, +}; + +DonorsList.defaultProps = { + columnMapping: defaultColumnMapping, + columnWidths: defaultColumnWidths, + visibleColumns: defaultVisibleColumns, }; export default DonorsList; diff --git a/lib/DonorsList/constants.js b/lib/DonorsList/constants.js index 2fb6138c..c93a14bc 100644 --- a/lib/DonorsList/constants.js +++ b/lib/DonorsList/constants.js @@ -1,12 +1,12 @@ import { FormattedMessage } from 'react-intl'; -export const columnMapping = { +export const defaultColumnMapping = { name: , code: , unassignDonor: null, }; -export const visibleColumns = [ +export const defaultVisibleColumns = [ 'name', 'code', 'unassignDonor', @@ -14,7 +14,7 @@ export const visibleColumns = [ export const alignRowProps = { alignLastColToEnd: true }; -export const columnWidths = { +export const defaultColumnWidths = { name: '45%', code: '45%', unassignDonor: '10%', diff --git a/lib/DonorsList/index.js b/lib/DonorsList/index.js index 66ae435f..6b255540 100644 --- a/lib/DonorsList/index.js +++ b/lib/DonorsList/index.js @@ -1 +1 @@ -export { default as DonorsList } from './DonorsContainer'; +export { default as DonorsList } from './DonorsForm';