From 375c86d737d4063b0f45d8e1e06fdf2104ff4c7d Mon Sep 17 00:00:00 2001 From: Uladzislau_Kutarkin Date: Mon, 12 Feb 2024 15:14:49 +0400 Subject: [PATCH 1/7] UIBULKED-404: Render preview after query executed --- CHANGELOG.md | 1 + .../BulkEditListFilters.js | 10 +++++++++ .../BulkEditListResult/Preview/Preview.js | 14 ++++++++++-- .../Preview/Preview.test.js | 20 ++++++++++++++--- .../PreviewContainer/PreviewContainer.js | 22 +++++++++++++------ src/hooks/api/useQueryPlugin.js | 9 ++++++++ test/jest/__mock__/fakeData.js | 1 + 7 files changed, 65 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41e162d5..f87dbac3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -92,6 +92,7 @@ * [UIBULKED-351](https://issues.folio.org/browse/UIBULKED-351) Hide Query tab * [UIBULKED-276](https://issues.folio.org/browse/UIBULKED-276) Rename "Instance" column for holdings records preview * [UIBULKED-352](https://issues.folio.org/browse/UIBULKED-352) Localize numbers displayed in bulk edit +* [UIBULKED-404](https://issues.folio.org/browse/UIBULKED-404)Render preview after query executed. ## [3.0.5](https://github.com/folio-org/ui-bulk-edit/tree/v3.0.5) (2023-03-22) diff --git a/src/components/BulkEditList/BulkEditListFilters/BulkEditListFilters.js b/src/components/BulkEditList/BulkEditListFilters/BulkEditListFilters.js index 737a6a3e..09903593 100644 --- a/src/components/BulkEditList/BulkEditListFilters/BulkEditListFilters.js +++ b/src/components/BulkEditList/BulkEditListFilters/BulkEditListFilters.js @@ -117,6 +117,7 @@ export const BulkEditListFilters = ({ testQueryDataSource, getParamsSource, cancelQueryDataSource, + runQueryDataSource } = useQueryPlugin(recordTypeId); const handleChange = (value, field) => setFilters(prev => ({ @@ -250,6 +251,13 @@ export const BulkEditListFilters = ({ } }, [location.search]); + const onQueryRunSuccess = ({ id }) => { + history.replace({ + pathname: `/bulk-edit/${id}/progress`, + search: buildSearch({}, location.search), + }); + }; + const renderCapabilities = () => ( {}} + onQueryRunSuccess={onQueryRunSuccess} + runQueryDataSource={runQueryDataSource} cancelQueryDataSource={cancelQueryDataSource} /> diff --git a/src/components/BulkEditList/BulkEditListResult/Preview/Preview.js b/src/components/BulkEditList/BulkEditListResult/Preview/Preview.js index 9b4ec17c..24bd59b0 100644 --- a/src/components/BulkEditList/BulkEditListResult/Preview/Preview.js +++ b/src/components/BulkEditList/BulkEditListResult/Preview/Preview.js @@ -6,6 +6,7 @@ import { } from '@folio/stripes/components'; import PropTypes from 'prop-types'; import { useLocation } from 'react-router-dom'; +import React from 'react'; import css from './Preview.css'; import { PreviewAccordion } from './PreviewAccordion'; import { ErrorsAccordion } from './ErrorsAccordion'; @@ -15,15 +16,21 @@ import { useRecordsPreview } from '../../../../hooks/api'; -import { EDITING_STEPS, PAGINATION_CONFIG } from '../../../../constants'; +import { + CRITERIA, + EDITING_STEPS, + PAGINATION_CONFIG +} from '../../../../constants'; import { usePagination } from '../../../../hooks/usePagination'; import { useBulkOperationStats } from '../../../../hooks/useBulkOperationStats'; +import { NoResultsMessage } from '../NoResultsMessage/NoResultsMessage'; export const Preview = ({ id, title, isInitial, bulkDetails }) => { const location = useLocation(); const search = new URLSearchParams(location.search); const step = search.get('step'); const capabilities = search.get('capabilities'); + const criteria = search.get('criteria'); const totalRecords = step === EDITING_STEPS.COMMIT ? bulkDetails?.processedNumOfRecords : bulkDetails?.matchedNumOfRecords; @@ -51,6 +58,9 @@ export const Preview = ({ id, title, isInitial, bulkDetails }) => { const errors = data?.errors || []; + if (!((bulkDetails.fqlQuery && criteria === CRITERIA.QUERY) || (criteria !== CRITERIA.QUERY && !bulkDetails.fqlQuery))) { + return ; + } return (
@@ -95,7 +105,6 @@ export const Preview = ({ id, title, isInitial, bulkDetails }) => { /> )}
-
); @@ -112,5 +121,6 @@ Preview.propTypes = { processedNumOfRecords: PropTypes.number, matchedNumOfErrors: PropTypes.number, committedNumOfErrors: PropTypes.number, + fqlQuery: PropTypes.string }), }; diff --git a/src/components/BulkEditList/BulkEditListResult/Preview/Preview.test.js b/src/components/BulkEditList/BulkEditListResult/Preview/Preview.test.js index 10748007..d5c2dcd5 100644 --- a/src/components/BulkEditList/BulkEditListResult/Preview/Preview.test.js +++ b/src/components/BulkEditList/BulkEditListResult/Preview/Preview.test.js @@ -1,7 +1,7 @@ import { MemoryRouter } from 'react-router'; import { QueryClientProvider } from 'react-query'; -import { render, screen } from '@testing-library/react'; +import { logDOM, render, screen } from '@testing-library/react'; import { useOkapiKy } from '@folio/stripes/core'; import { runAxeTest } from '@folio/stripes-testing'; @@ -12,6 +12,7 @@ import { queryClient } from '../../../../../test/jest/utils/queryClient'; import { RootContext } from '../../../../context/RootContext'; import { Preview } from './Preview'; +import { CRITERIA } from '../../../../constants'; jest.mock('./PreviewAccordion', () => ({ PreviewAccordion: () => 'PreviewAccordion', @@ -27,9 +28,9 @@ const defaultProps = { id: bulkOperation.id, }; -const renderPreview = (props = defaultProps) => { +const renderPreview = (props = defaultProps, criteria = 'query') => { render( - + @@ -87,4 +88,17 @@ describe('Preview Query', () => { rootNode: document.body, }); }); + it('should render with no axe errors', async () => { + renderPreview(); + + await runAxeTest({ + rootNode: document.body, + }); + }); + + it('should render no message', async () => { + renderPreview(defaultProps, CRITERIA.IDENTIFIER); + + logDOM(); + }); }); diff --git a/src/components/BulkEditList/BulkEditListResult/PreviewContainer/PreviewContainer.js b/src/components/BulkEditList/BulkEditListResult/PreviewContainer/PreviewContainer.js index fa5eef26..839933c2 100644 --- a/src/components/BulkEditList/BulkEditListResult/PreviewContainer/PreviewContainer.js +++ b/src/components/BulkEditList/BulkEditListResult/PreviewContainer/PreviewContainer.js @@ -1,11 +1,20 @@ import React, { useMemo } from 'react'; import { useIntl } from 'react-intl'; -import { useLocation, useParams } from 'react-router'; +import { + useLocation, + useParams +} from 'react-router'; -import { Layout, Loading } from '@folio/stripes/components'; +import { + Layout, + Loading +} from '@folio/stripes/components'; import { useBulkOperationDetails } from '../../../../hooks/api'; -import { CRITERIA, EDITING_STEPS } from '../../../../constants'; +import { + CRITERIA, + EDITING_STEPS +} from '../../../../constants'; import { Preview } from '../Preview/Preview'; import { NoResultsMessage } from '../NoResultsMessage/NoResultsMessage'; @@ -18,21 +27,20 @@ const PreviewContainer = () => { const step = search.get('step'); const fileUploadedName = search.get('fileName'); const capabilities = search.get('capabilities')?.toLocaleLowerCase(); - const queryText = search.get('queryText'); const criteria = search.get('criteria'); const { id } = useParams(); const { bulkDetails, isLoading } = useBulkOperationDetails({ id, additionalQueryKeys: [step] }); const title = useMemo(() => { - if (queryText) return intl.formatMessage({ id: 'ui-bulk-edit.preview.query.title' }, { queryText }); + if (bulkDetails?.fqlQuery) return intl.formatMessage({ id: 'ui-bulk-edit.preview.query.title' }, { queryText: bulkDetails.fqlQuery }); return intl.formatMessage({ id: 'ui-bulk-edit.preview.file.title' }, { fileUploadedName }); - }, [queryText, fileUploadedName]); + }, [bulkDetails?.fqlQuery, fileUploadedName]); const isInitial = step === EDITING_STEPS.UPLOAD; - if (criteria !== CRITERIA.IDENTIFIER) { + if (criteria === CRITERIA.LOGS) { return ; } else if (isLoading) { return ( diff --git a/src/hooks/api/useQueryPlugin.js b/src/hooks/api/useQueryPlugin.js index f22ef749..eba6b283 100644 --- a/src/hooks/api/useQueryPlugin.js +++ b/src/hooks/api/useQueryPlugin.js @@ -38,11 +38,20 @@ export const useQueryPlugin = (recordType) => { return ky.delete(`query/${queryId}`); }; + const runQueryDataSource = async ({ fqlQuery }) => { + const response = ky.post('bulk-operations/query', { json: { + entityTypeId:recordType, + fqlQuery: JSON.stringify(fqlQuery) + } }); + return response.json(); + }; + return { entityTypeDataSource, queryDetailsDataSource, testQueryDataSource, getParamsSource, cancelQueryDataSource, + runQueryDataSource, }; }; diff --git a/test/jest/__mock__/fakeData.js b/test/jest/__mock__/fakeData.js index 6d25e2ba..7582ea5a 100644 --- a/test/jest/__mock__/fakeData.js +++ b/test/jest/__mock__/fakeData.js @@ -11,6 +11,7 @@ export const bulkEditLogsData = Array(50).fill(null).map((_, index) => [ processedNumOfRecords: 55, committedNumOfRecords: 20, editing: 'In app', + fqlQuery: 'test' }, { id: (index + 1).toString(), From 7ee84d1c24ea675b72c16a98b2ad4ef91b1e1e1d Mon Sep 17 00:00:00 2001 From: Uladzislau_Kutarkin Date: Mon, 12 Feb 2024 18:17:04 +0400 Subject: [PATCH 2/7] UIBULKED-404: update permissions --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index a482f117..14b2b011 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,8 @@ "bulk-operations.download.item.get", "bulk-operations.collection.get", "bulk-operations.item.get", - "usergroups.collection.get" + "usergroups.collection.get", + "bulk-operations.item.query.post" ] }, { From 1117e0ad5be89376b2c48bfee5ec771cc7bf03c4 Mon Sep 17 00:00:00 2001 From: Uladzislau_Kutarkin Date: Mon, 12 Feb 2024 18:43:26 +0400 Subject: [PATCH 3/7] UIBULKED-404: update permissions --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 14b2b011..854145a2 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,6 @@ "bulk-operations.collection.get", "bulk-operations.item.get", "usergroups.collection.get", - "bulk-operations.item.query.post" ] }, { @@ -144,7 +143,8 @@ "fqm.entityTypes.item.columnValues.get", "fqm.query.async.results.get", "fqm.query.async.post", - "fqm.query.async.delete" + "fqm.query.async.delete", + "bulk-operations.item.query.post" ], "visible": true } From 20ffd3d258b62e3e6241b38765ef1049ea508c36 Mon Sep 17 00:00:00 2001 From: Uladzislau_Kutarkin Date: Mon, 12 Feb 2024 18:45:40 +0400 Subject: [PATCH 4/7] UIBULKED-404: fix issue in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 854145a2..ba2717f2 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "bulk-operations.download.item.get", "bulk-operations.collection.get", "bulk-operations.item.get", - "usergroups.collection.get", + "usergroups.collection.get" ] }, { From 50e9337220a31d605515499e141bad00916d0b64 Mon Sep 17 00:00:00 2001 From: Uladzislau_Kutarkin Date: Wed, 14 Feb 2024 10:29:05 +0400 Subject: [PATCH 5/7] UIBULKED-404: merge master --- .../BulkEditListSidebar/QueryTab/QueryTab.js | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/components/BulkEditList/BulkEditListSidebar/QueryTab/QueryTab.js b/src/components/BulkEditList/BulkEditListSidebar/QueryTab/QueryTab.js index 52bdc8df..ba108a46 100644 --- a/src/components/BulkEditList/BulkEditListSidebar/QueryTab/QueryTab.js +++ b/src/components/BulkEditList/BulkEditListSidebar/QueryTab/QueryTab.js @@ -1,5 +1,8 @@ import React, { useContext } from 'react'; -import { useHistory } from 'react-router-dom'; +import { + useHistory, + useLocation +} from 'react-router-dom'; import { Pluggable } from '@folio/stripes/core'; import { buildSearch } from '@folio/stripes-acq-components'; @@ -8,13 +11,17 @@ import { useRecordTypes } from '../../../../hooks/api/useRecordTypes'; import { getRecordType } from '../../../../utils/getRecordType'; import { useQueryPlugin } from '../../../../hooks/api'; import { useSearchParams } from '../../../../hooks/useSearchParams'; -import { useBulkPermissions, useLocationFilters } from '../../../../hooks'; +import { + useBulkPermissions, + useLocationFilters +} from '../../../../hooks'; import { getCapabilityOptions } from '../../../../utils/helpers'; import { CRITERIA, QUERY_FILTERS } from '../../../../constants'; import { RootContext } from '../../../../context/RootContext'; export const QueryTab = () => { const history = useHistory(); + const location = useLocation(); const { queryRecordType, criteria, @@ -56,6 +63,7 @@ export const QueryTab = () => { testQueryDataSource, getParamsSource, cancelQueryDataSource, + runQueryDataSource } = useQueryPlugin(recordTypeId); const handleCapabilityChange = (e) => { @@ -71,6 +79,13 @@ export const QueryTab = () => { setVisibleColumns(null); }; + const onQueryRunSuccess = ({ id }) => { + history.replace({ + pathname: `/bulk-edit/${id}/progress`, + search: buildSearch({}, location.search), + }); + }; + return ( <> @@ -91,6 +106,8 @@ export const QueryTab = () => { queryDetailsDataSource={queryDetailsDataSource} onQueryRunFail={() => {}} cancelQueryDataSource={cancelQueryDataSource} + onQueryRunSuccess={onQueryRunSuccess} + runQueryDataSource={runQueryDataSource} /> ); From 73f9b696338eabff09df0d0c2007e92c411e1be0 Mon Sep 17 00:00:00 2001 From: Uladzislau_Kutarkin Date: Wed, 14 Feb 2024 13:40:55 +0400 Subject: [PATCH 6/7] UIBULKED-404: fix merge from master --- .../BulkEditActionMenu/BulkEditActionMenu.js | 15 ++++++++++----- .../BulkEditInApp/BulkEditInApp.js | 6 +++++- .../BulkEditListResult/Preview/Preview.js | 12 ++++++++---- src/hooks/api/useRecordsPreview.js | 4 ++++ src/utils/mappers/mappers.js | 9 ++++++--- 5 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/components/BulkEditActionMenu/BulkEditActionMenu.js b/src/components/BulkEditActionMenu/BulkEditActionMenu.js index 5560dee7..c813c73e 100644 --- a/src/components/BulkEditActionMenu/BulkEditActionMenu.js +++ b/src/components/BulkEditActionMenu/BulkEditActionMenu.js @@ -21,6 +21,7 @@ import { BULK_VISIBLE_COLUMNS, FILE_SEARCH_PARAMS, FILE_TO_LINK, + CRITERIA, } from '../../constants'; import { useBulkPermissions, @@ -43,8 +44,12 @@ const BulkEditActionMenu = ({ const perms = useBulkPermissions(); const search = new URLSearchParams(location.search); const capability = search.get('capabilities'); + const criteria = search.get('criteria'); + const queryRecordType = search.get('queryRecordType'); const step = search.get('step'); + const key = criteria === CRITERIA.QUERY ? queryRecordType : capability; + const [columnSearch, setColumnSearch] = useState(''); const { @@ -60,10 +65,10 @@ const BulkEditActionMenu = ({ const [fileInfo, setFileInfo] = useState(null); - const hasEditPerm = (hasHoldingsInventoryEdit && capability === CAPABILITIES.HOLDING) - || (hasItemInventoryEdit && capability === CAPABILITIES.ITEM) - || (hasUserEditInAppPerm && capability === CAPABILITIES.USER) - || (hasInstanceInventoryEdit && capability === CAPABILITIES.INSTANCE); + const hasEditPerm = (hasHoldingsInventoryEdit && key === CAPABILITIES.HOLDING) + || (hasItemInventoryEdit && key === CAPABILITIES.ITEM) + || (hasUserEditInAppPerm && key === CAPABILITIES.USER) + || (hasInstanceInventoryEdit && key === CAPABILITIES.INSTANCE); useFileDownload({ @@ -96,7 +101,7 @@ const BulkEditActionMenu = ({ const columnsOptions = columns.map(item => ({ ...item, - label: item.ignoreTranslation ? item.label : intl.formatMessage({ id: `ui-bulk-edit.columns.${capability}.${item.label}` }), + label: item.ignoreTranslation ? item.label : intl.formatMessage({ id: `ui-bulk-edit.columns.${key}.${item.label}` }), disabled: isLastUnselectedColumn(item.value) || !countOfRecords, })); diff --git a/src/components/BulkEditList/BulkEditListResult/BulkEditInApp/BulkEditInApp.js b/src/components/BulkEditList/BulkEditListResult/BulkEditInApp/BulkEditInApp.js index 3527a1b6..0f25737c 100644 --- a/src/components/BulkEditList/BulkEditListResult/BulkEditInApp/BulkEditInApp.js +++ b/src/components/BulkEditList/BulkEditListResult/BulkEditInApp/BulkEditInApp.js @@ -13,6 +13,7 @@ import { BulkEditInAppTitle } from './BulkEditInAppTitle/BulkEditInAppTitle'; import { ContentUpdatesForm } from './ContentUpdatesForm/ContentUpdatesForm'; import { CAPABILITIES, + CRITERIA, getHoldingsOptions, getInstanceOptions, getItemsOptions, @@ -29,6 +30,9 @@ export const BulkEditInApp = ({ const intl = useIntl(); const location = useLocation(); const search = new URLSearchParams(location.search); + const criteria = search.get('criteria'); + const queryRecordType = search.get('queryRecordType'); + const key = criteria === CRITERIA.QUERY ? queryRecordType : capabilities; const fileUploadedName = search.get('fileName'); const isItemCapability = capabilities === CAPABILITIES.ITEM; @@ -44,7 +48,7 @@ export const BulkEditInApp = ({ [CAPABILITIES.INSTANCE]: getInstanceOptions(intl.formatMessage), }; - const options = optionsMap[capabilities]; + const options = optionsMap[key]; const showContentUpdatesForm = options && !isItemNotesLoading && !isHoldingsNotesLoading; const sortedOptions = sortAlphabetically(options, intl.formatMessage({ id:'ui-bulk-edit.options.placeholder' })); diff --git a/src/components/BulkEditList/BulkEditListResult/Preview/Preview.js b/src/components/BulkEditList/BulkEditListResult/Preview/Preview.js index 24bd59b0..5022bd02 100644 --- a/src/components/BulkEditList/BulkEditListResult/Preview/Preview.js +++ b/src/components/BulkEditList/BulkEditListResult/Preview/Preview.js @@ -1,12 +1,14 @@ +import React from 'react'; import { FormattedMessage } from 'react-intl'; +import { useLocation } from 'react-router-dom'; +import PropTypes from 'prop-types'; + import { Headline, AccordionStatus, MessageBanner, } from '@folio/stripes/components'; -import PropTypes from 'prop-types'; -import { useLocation } from 'react-router-dom'; -import React from 'react'; + import css from './Preview.css'; import { PreviewAccordion } from './PreviewAccordion'; import { ErrorsAccordion } from './ErrorsAccordion'; @@ -15,7 +17,6 @@ import { useErrorsPreview, useRecordsPreview } from '../../../../hooks/api'; - import { CRITERIA, EDITING_STEPS, @@ -30,6 +31,7 @@ export const Preview = ({ id, title, isInitial, bulkDetails }) => { const search = new URLSearchParams(location.search); const step = search.get('step'); const capabilities = search.get('capabilities'); + const queryRecordType = search.get('queryRecordType'); const criteria = search.get('criteria'); const totalRecords = step === EDITING_STEPS.COMMIT ? bulkDetails?.processedNumOfRecords : bulkDetails?.matchedNumOfRecords; @@ -51,6 +53,8 @@ export const Preview = ({ id, title, isInitial, bulkDetails }) => { id, step, capabilities, + criteria, + queryRecordType, ...pagination, }); diff --git a/src/hooks/api/useRecordsPreview.js b/src/hooks/api/useRecordsPreview.js index 47c7ae1b..8923a104 100644 --- a/src/hooks/api/useRecordsPreview.js +++ b/src/hooks/api/useRecordsPreview.js @@ -19,6 +19,8 @@ export const useRecordsPreview = ({ capabilities, limit, offset, + criteria, + queryRecordType }) => { const intl = useIntl(); const { setVisibleColumns } = useContext(RootContext); @@ -40,6 +42,8 @@ export const useRecordsPreview = ({ data, intl, capabilities, + criteria, + queryRecordType }), [data]); // set initial and visible columns diff --git a/src/utils/mappers/mappers.js b/src/utils/mappers/mappers.js index 19174665..cc90462b 100644 --- a/src/utils/mappers/mappers.js +++ b/src/utils/mappers/mappers.js @@ -9,6 +9,7 @@ import { import { CAPABILITIES, + CRITERIA, CUSTOM_ENTITY_COLUMNS, } from '../../constants'; import { @@ -44,7 +45,7 @@ const formatData = ({ capability, column, data }) => { } }; -export const getMappedTableData = ({ data, capabilities, intl }) => { +export const getMappedTableData = ({ data, capabilities, criteria, queryRecordType, intl }) => { if (!data) { return { contentData: null, @@ -53,6 +54,8 @@ export const getMappedTableData = ({ data, capabilities, intl }) => { }; } + const key = criteria === CRITERIA.QUERY ? queryRecordType : capabilities; + const columns = data.header.map((cell) => ({ label: cell.value, value: cell.value, @@ -63,7 +66,7 @@ export const getMappedTableData = ({ data, capabilities, intl }) => { })); const columnMapping = columns.reduce((acc, { value, label, ignoreTranslation }) => { - acc[value] = ignoreTranslation ? value : intl.formatMessage({ id: `ui-bulk-edit.columns.${capabilities}.${label}` }); + acc[value] = ignoreTranslation ? value : intl.formatMessage({ id: `ui-bulk-edit.columns.${key}.${label}` }); return acc; }, {}); @@ -74,7 +77,7 @@ export const getMappedTableData = ({ data, capabilities, intl }) => { acc[column.value] = formatData({ column, - capability: capabilities, + capability: key, data: item, }); From af69c7e0493919aca0a908265f77c2ee428157e0 Mon Sep 17 00:00:00 2001 From: Uladzislau_Kutarkin Date: Wed, 14 Feb 2024 14:01:06 +0400 Subject: [PATCH 7/7] UIBULKED-404: CHANGELOG.md update --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fcd3bac0..c1963b54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ * [UIBULKED-367](https://issues.folio.org/browse/UIBULKED-367) Logs - Provide a link to file with identifiers of the records affected by query. * [UIBULKED-412](https://issues.folio.org/browse/UIBULKED-412) Not all but up to 10 note types are displayed in Bulk edit. * [UIBULKED-411](https://issues.folio.org/browse/UIBULKED-411) Refactoring of ListFilters component +* [UIBULKED-404](https://issues.folio.org/browse/UIBULKED-404) Render preview after query executed. ## [4.0.0](https://github.com/folio-org/ui-bulk-edit/tree/v4.0.0) (2023-10-12) @@ -93,8 +94,6 @@ * [UIBULKED-351](https://issues.folio.org/browse/UIBULKED-351) Hide Query tab * [UIBULKED-276](https://issues.folio.org/browse/UIBULKED-276) Rename "Instance" column for holdings records preview * [UIBULKED-352](https://issues.folio.org/browse/UIBULKED-352) Localize numbers displayed in bulk edit -* [UIBULKED-404](https://issues.folio.org/browse/UIBULKED-404)Render preview after query executed. - ## [3.0.5](https://github.com/folio-org/ui-bulk-edit/tree/v3.0.5) (2023-03-22)