Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UIBULKED-404: Render preview after query executed #475

Merged
merged 9 commits into from
Feb 14, 2024
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -95,7 +96,6 @@
* [UIBULKED-352](https://issues.folio.org/browse/UIBULKED-352) Localize numbers displayed in bulk edit
* [UIBULKED-210](https://issues.folio.org/browse/UIBULKED-210) Improve user errors for invalid data - IncorrectTokenCountException error.


## [3.0.5](https://github.com/folio-org/ui-bulk-edit/tree/v3.0.5) (2023-03-22)

* [UIBULKED-264](https://issues.folio.org/browse/UIBULKED-264) "Download matched records (CSV)" option is enabled on the confirmation screen
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,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
}
Expand Down
15 changes: 10 additions & 5 deletions src/components/BulkEditActionMenu/BulkEditActionMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
BULK_VISIBLE_COLUMNS,
FILE_SEARCH_PARAMS,
FILE_TO_LINK,
CRITERIA,
} from '../../constants';
import {
useBulkPermissions,
Expand All @@ -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 {
Expand All @@ -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({
Expand Down Expand Up @@ -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,
}));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { BulkEditInAppTitle } from './BulkEditInAppTitle/BulkEditInAppTitle';
import { ContentUpdatesForm } from './ContentUpdatesForm/ContentUpdatesForm';
import {
CAPABILITIES,
CRITERIA,
getHoldingsOptions,
getInstanceOptions,
getItemsOptions,
Expand All @@ -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;
Expand All @@ -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' }));

Expand Down
24 changes: 19 additions & 5 deletions src/components/BulkEditList/BulkEditListResult/Preview/Preview.js
Original file line number Diff line number Diff line change
@@ -1,11 +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 css from './Preview.css';
import { PreviewAccordion } from './PreviewAccordion';
import { ErrorsAccordion } from './ErrorsAccordion';
Expand All @@ -14,16 +17,22 @@ import {
useErrorsPreview,
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 queryRecordType = search.get('queryRecordType');
const criteria = search.get('criteria');

const totalRecords = step === EDITING_STEPS.COMMIT ? bulkDetails?.processedNumOfRecords : bulkDetails?.matchedNumOfRecords;

Expand All @@ -44,13 +53,18 @@ export const Preview = ({ id, title, isInitial, bulkDetails }) => {
id,
step,
capabilities,
criteria,
queryRecordType,
...pagination,
});

const { data } = useErrorsPreview({ id });

const errors = data?.errors || [];

if (!((bulkDetails.fqlQuery && criteria === CRITERIA.QUERY) || (criteria !== CRITERIA.QUERY && !bulkDetails.fqlQuery))) {
return <NoResultsMessage />;
}
return (
<AccordionStatus>
<div className={css.previewContainer}>
Expand Down Expand Up @@ -95,7 +109,6 @@ export const Preview = ({ id, title, isInitial, bulkDetails }) => {
/>
)}
</div>

</div>
</AccordionStatus>
);
Expand All @@ -112,5 +125,6 @@ Preview.propTypes = {
processedNumOfRecords: PropTypes.number,
matchedNumOfErrors: PropTypes.number,
committedNumOfErrors: PropTypes.number,
fqlQuery: PropTypes.string
}),
};
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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',
Expand All @@ -27,9 +28,9 @@ const defaultProps = {
id: bulkOperation.id,
};

const renderPreview = (props = defaultProps) => {
const renderPreview = (props = defaultProps, criteria = 'query') => {
render(
<MemoryRouter initialEntries={['/bulk-edit/1?queryText=patronGroup%3D%3D"1"']}>
<MemoryRouter initialEntries={[`/bulk-edit/1?queryText=patronGroup%3D%3D"1"&criteria=${criteria}`]}>
<QueryClientProvider client={queryClient}>
<RootContext.Provider value={{ setCountOfRecords: setCountOfRecordsMock }}>
<Preview {...props} />
Expand Down Expand Up @@ -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();
});
});
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -18,21 +27,20 @@
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]);

Check warning on line 39 in src/components/BulkEditList/BulkEditListResult/PreviewContainer/PreviewContainer.js

View workflow job for this annotation

GitHub Actions / github-actions-ci

React Hook useMemo has a missing dependency: 'intl'. Either include it or remove the dependency array

Check warning on line 39 in src/components/BulkEditList/BulkEditListResult/PreviewContainer/PreviewContainer.js

View workflow job for this annotation

GitHub Actions / github-actions-ci

React Hook useMemo has a missing dependency: 'intl'. Either include it or remove the dependency array

const isInitial = step === EDITING_STEPS.UPLOAD;

if (criteria !== CRITERIA.IDENTIFIER) {
if (criteria === CRITERIA.LOGS) {
return <NoResultsMessage />;
} else if (isLoading) {
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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,
Expand Down Expand Up @@ -56,6 +63,7 @@ export const QueryTab = () => {
testQueryDataSource,
getParamsSource,
cancelQueryDataSource,
runQueryDataSource
} = useQueryPlugin(recordTypeId);

const handleCapabilityChange = (e) => {
Expand All @@ -71,6 +79,13 @@ export const QueryTab = () => {
setVisibleColumns(null);
};

const onQueryRunSuccess = ({ id }) => {
history.replace({
pathname: `/bulk-edit/${id}/progress`,
search: buildSearch({}, location.search),
});
};


return (
<>
Expand All @@ -91,6 +106,8 @@ export const QueryTab = () => {
queryDetailsDataSource={queryDetailsDataSource}
onQueryRunFail={() => {}}
cancelQueryDataSource={cancelQueryDataSource}
onQueryRunSuccess={onQueryRunSuccess}
runQueryDataSource={runQueryDataSource}
/>
</>
);
Expand Down
9 changes: 9 additions & 0 deletions src/hooks/api/useQueryPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
};
4 changes: 4 additions & 0 deletions src/hooks/api/useRecordsPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export const useRecordsPreview = ({
capabilities,
limit,
offset,
criteria,
queryRecordType
}) => {
const intl = useIntl();
const { setVisibleColumns } = useContext(RootContext);
Expand All @@ -40,6 +42,8 @@ export const useRecordsPreview = ({
data,
intl,
capabilities,
criteria,
queryRecordType
}), [data]);

// set initial and visible columns
Expand Down
Loading
Loading