Skip to content

Commit

Permalink
UIBULKED-574 Updates to Errors component
Browse files Browse the repository at this point in the history
  • Loading branch information
vashjs committed Dec 23, 2024
1 parent 2345a2d commit 38a9ff6
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 96 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* [UIBULKED-585](https://folio-org.atlassian.net/browse/UUIBULKED-585) Adding missing translation and filters.
* [UIBULKED-561](https://folio-org.atlassian.net/browse/UUIBULKED-561) Add administrative data accordion to MARC bulk edit form.
* [UIBULKED-562](https://folio-org.atlassian.net/browse/UIBULKED-562) Include statistical code option on Instances bulk edit forms.
* [UIBULKED-574](https://folio-org.atlassian.net/browse/UIBULKED-574) Updates to Errors component.

## [4.2.2](https://github.com/folio-org/ui-bulk-edit/tree/v4.2.2) (2024-11-15)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
useStripes,
} from '@folio/stripes/core';

import { APPROACHES, EDITING_STEPS } from '../../../constants';
import { APPROACHES, EDITING_STEPS, RECORD_TYPES_MAPPING } from '../../../constants';
import { useSearchParams } from '../../../hooks';
import { RootContext } from '../../../context/RootContext';
import { BulkEditListResult } from '../BulkEditListResult';
Expand All @@ -26,6 +26,7 @@ export const BulkEditIdentifiers = ({
approach,
processedFileName,
initialFileName,
currentRecordType,
} = useSearchParams();

const {
Expand Down Expand Up @@ -57,7 +58,7 @@ export const BulkEditIdentifiers = ({
return (
<FormattedMessage
id={`ui-bulk-edit.list.logSubTitle.${step === EDITING_STEPS.UPLOAD ? 'matched' : 'changed'}`}
values={{ count: countOfRecords }}
values={{ count: countOfRecords, recordType: RECORD_TYPES_MAPPING[currentRecordType] }}
/>
);
}, [isIdentifierTabWithPreview, countOfRecords, step]);

Check warning on line 64 in src/components/BulkEditPane/BulkEditIdentifiers/BulkEditIdentifiers.js

View workflow job for this annotation

GitHub Actions / github-actions-ci

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

Check warning on line 64 in src/components/BulkEditPane/BulkEditIdentifiers/BulkEditIdentifiers.js

View workflow job for this annotation

GitHub Actions / github-actions-ci

React Hook useMemo has a missing dependency: 'currentRecordType'. Either include it or remove the dependency array
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
import React, { useState } from 'react';
import { PropTypes } from 'prop-types';
import { useLocation } from 'react-router-dom';
import { FormattedMessage } from 'react-intl';
import {
Accordion,
MultiColumnList,
Headline,
Icon,
TextLink,
TextLink, Layout, Checkbox,
} from '@folio/stripes/components';
import { useStripes } from '@folio/stripes/core';
import { PrevNextPagination } from '@folio/stripes-acq-components';
import css from '../Preview.css';
import { useSearchParams } from '../../../../../hooks';
import { CAPABILITIES, CRITERIA, ERROR_PARAMETERS_KEYS } from '../../../../../constants';

const visibleColumns = ['key', 'message'];
import { CAPABILITIES, ERROR_PARAMETERS_KEYS } from '../../../../../constants';

const getParam = (error, key) => error.parameters.find(param => param.key === key)?.value;

const columnMapping = {
type: <FormattedMessage id="ui-bulk-edit.list.errors.table.status" />,
key: <FormattedMessage id="ui-bulk-edit.list.errors.table.code" />,
message: <FormattedMessage id="ui-bulk-edit.list.errors.table.message" />,
};

const visibleColumns = Object.keys(columnMapping);

const renderErrorMessage = (error, isLinkAvailable) => {
const link = getParam(error, ERROR_PARAMETERS_KEYS.LINK);

Expand All @@ -45,10 +46,11 @@ const renderErrorMessage = (error, isLinkAvailable) => {

const ErrorsAccordion = ({
errors = [],
entries,
countOfErrors,
matched,
isInitial,
totalCountOfErrors,
loading,
pagination,
onChangePage,
}) => {
const { user, okapi } = useStripes();
const centralTenant = user?.user?.consortium?.centralTenantId;
Expand All @@ -58,42 +60,19 @@ const ErrorsAccordion = ({
const isLinkAvailable = (isCentralTenant && capabilities === CAPABILITIES.INSTANCE) || !isCentralTenant;

const resultsFormatter = {
type: () => <FormattedMessage id="ui-bulk-edit.list.errors.table.status.ERROR" />,
key: error => getParam(error, ERROR_PARAMETERS_KEYS.IDENTIFIER),
message: error => renderErrorMessage(error, isLinkAvailable),
};

const location = useLocation();
const { criteria } = useSearchParams();
const fileName = new URLSearchParams(location.search).get('fileName');
const errorLength = errors.length;

const [opened, setOpened] = useState(!!errorLength);
const [showWarnings, setShowWarnings] = useState(false);

const headLineTranslateKey = isInitial ? 'info' : 'infoProcessed';

const headLine = criteria === CRITERIA.QUERY ?
(
<FormattedMessage
id={`ui-bulk-edit.list.errors.query.${headLineTranslateKey}`}
values={{
entries,
matched,
errors: countOfErrors,
}}
/>
)
:
(
<FormattedMessage
id={`ui-bulk-edit.list.errors.${headLineTranslateKey}`}
values={{
fileName,
entries,
matched,
errors: countOfErrors,
}}
/>
);
const handleShowWarnings = () => {
setShowWarnings(prev => !prev);
};

return (
<div className={css.previewAccordion}>
Expand All @@ -106,16 +85,40 @@ const ErrorsAccordion = ({
>
<div className={css.errorAccordionOuter}>
<Headline size="medium" margin="small">
{headLine}
<Layout className="display-flex justified">
<FormattedMessage
id="ui-bulk-edit.list.errors.info"
values={{
errors: countOfErrors,
warnings: 0,
}}
/>
<Checkbox
label={<FormattedMessage id="ui-bulk-edit.list.errors.checkbox" />}
checked={showWarnings}
onChange={handleShowWarnings}
/>
</Layout>
</Headline>
<div className={css.errorAccordionList}>
<MultiColumnList
contentData={errors}
columnMapping={columnMapping}
formatter={resultsFormatter}
visibleColumns={visibleColumns}
autosize
/>
<div className={css.previewAccordionInner}>
<div className={css.previewAccordionList}>
<MultiColumnList
contentData={errors}
columnMapping={columnMapping}
formatter={resultsFormatter}
visibleColumns={visibleColumns}
loading={loading}
autosize
/>
</div>
{errors.length > 0 && (
<PrevNextPagination
{...pagination}
totalCount={totalCountOfErrors}
disabled={false}
onChange={onChangePage}
/>
)}
</div>
</div>
</Accordion>
Expand All @@ -125,10 +128,14 @@ const ErrorsAccordion = ({

ErrorsAccordion.propTypes = {
errors: PropTypes.arrayOf(PropTypes.object),
entries: PropTypes.number,
countOfErrors: PropTypes.number,
matched: PropTypes.number,
isInitial: PropTypes.bool,
totalCountOfErrors: PropTypes.number,
loading: PropTypes.bool,
pagination: {
limit: PropTypes.number,
offset: PropTypes.number,
},
onChangePage: PropTypes.func,
};

export default ErrorsAccordion;
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import ErrorsAccordion from './ErrorsAccordion';

const defaultProps = {
errors: errorsPreview.errors,
entries: 5,
countOfErrors: errorsPreview.errors.length,
matched: 4,
};

const renderPreviewAccordion = (history, props = defaultProps) => {
Expand All @@ -27,27 +25,17 @@ describe('ErrorsAccordion', () => {
it('should render preview accordion', () => {
const mockHistory = ['/bulk-edit/1/preview'];

renderPreviewAccordion(mockHistory, { ...defaultProps, initial: true });
renderPreviewAccordion(mockHistory, { ...defaultProps });

expect(screen.getByText(/errors.info/)).toBeVisible();
expect(screen.getByText(/errors.table.code/)).toBeVisible();
expect(screen.getByText(errorsPreview.errors[0].message)).toBeVisible();
});

it('should render preview accordion for bulk edit query', () => {
const mockHistory = ['/bulk-edit/1/preview?criteria=query'];

renderPreviewAccordion(mockHistory, { ...defaultProps, initial: true });

expect(screen.getByText(/errors.query.info/)).toBeVisible();
expect(screen.getByText(/errors.table.code/)).toBeVisible();
expect(screen.getByText(errorsPreview.errors[0].message)).toBeVisible();
});

it('should render with no axe errors', async () => {
const mockHistory = ['/bulk-edit/1/preview'];

renderPreviewAccordion(mockHistory, { ...defaultProps, initial: true });
renderPreviewAccordion(mockHistory, { ...defaultProps });

await runAxeTest({
rootNode: document.body,
Expand All @@ -57,26 +45,25 @@ describe('ErrorsAccordion', () => {
it('should render preview accordion', () => {
const mockHistory = ['/bulk-edit/1/preview'];

renderPreviewAccordion(mockHistory, { ...defaultProps, initial: false });
renderPreviewAccordion(mockHistory, { ...defaultProps });

expect(screen.getByText(/errors.infoProcessed/)).toBeVisible();
expect(screen.getByText(/errors.table.code/)).toBeVisible();
expect(screen.getByText(errorsPreview.errors[0].message)).toBeVisible();
});

it('should hide content when title was clicked', () => {
const mockHistory = ['/bulk-edit/1/preview'];

const { getByRole } = renderPreviewAccordion(mockHistory, { ...defaultProps, initial: false });
const { getByRole } = renderPreviewAccordion(mockHistory, { ...defaultProps });

expect(screen.getByText(/errors.infoProcessed/)).toBeVisible();
expect(screen.getByText(/list.errors.info/)).toBeVisible();

const titleButton = getByRole('button', { name: /ui-bulk-edit.list.errors.title/ });

userEvent.click(titleButton);

waitFor(() => {
expect(screen.getByText(/errors.infoProcessed/)).not.toBeVisible();
expect(screen.getByText(/list.errors.info/)).not.toBeVisible();
});
});
});
26 changes: 15 additions & 11 deletions src/components/BulkEditPane/BulkEditListResult/Preview/Preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import {
import {
CRITERIA,
EDITING_STEPS,
PAGINATION_CONFIG
PAGINATION_CONFIG,
ERRORS_PAGINATION_CONFIG
} from '../../../../constants';
import { usePagination } from '../../../../hooks/usePagination';
import { useBulkOperationStats } from '../../../../hooks/useBulkOperationStats';
Expand All @@ -36,13 +37,13 @@ export const Preview = ({ id, title, isInitial, bulkDetails }) => {
} = useSearchParams();

const totalRecords = step === EDITING_STEPS.COMMIT ? bulkDetails?.processedNumOfRecords : bulkDetails?.matchedNumOfRecords;
const totalErrors = step === EDITING_STEPS.COMMIT ? bulkDetails?.committedNumOfErrors : bulkDetails?.matchedNumOfErrors;
const isOtherTabProcessing = progress && criteria !== progress;
const isPreviewEnabled = !isOtherTabProcessing && Boolean(id);

const {
countOfRecords,
countOfErrors,
totalCount,
visibleColumns,
} = useBulkOperationStats({ bulkDetails, step });

Expand All @@ -64,15 +65,17 @@ export const Preview = ({ id, title, isInitial, bulkDetails }) => {
...pagination,
});

const { data } = useErrorsPreview({
const {
pagination: errorsPagination,
changePage: changeErrorPage,
} = usePagination(ERRORS_PAGINATION_CONFIG);

const { errors, isFetching: isErrorsFetching } = useErrorsPreview({
id,
queryOptions: {
enabled: isPreviewEnabled,
},
enabled: isPreviewEnabled,
...errorsPagination,
});

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

if (!((bulkDetails.fqlQuery && criteria === CRITERIA.QUERY) || (criteria !== CRITERIA.QUERY && !bulkDetails.fqlQuery))) {
return <NoResultsMessage />;
}
Expand Down Expand Up @@ -113,10 +116,11 @@ export const Preview = ({ id, title, isInitial, bulkDetails }) => {
{Boolean(errors?.length) && (
<ErrorsAccordion
errors={errors}
entries={totalCount}
matched={countOfRecords}
pagination={errorsPagination}
countOfErrors={countOfErrors}
isInitial={isInitial}
totalCountOfErrors={totalErrors}
loading={isErrorsFetching}
onChangePage={changeErrorPage}
/>
)}
</div>
Expand Down
5 changes: 3 additions & 2 deletions src/components/BulkEditPane/BulkEditQuery/BulkEditQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ import {
import { Pane } from '@folio/stripes/components';

import { BulkEditListResult } from '../BulkEditListResult';
import { APPROACHES, EDITING_STEPS } from '../../../constants';
import { APPROACHES, EDITING_STEPS, RECORD_TYPES_MAPPING } from '../../../constants';
import { useSearchParams } from '../../../hooks';
import { RootContext } from '../../../context/RootContext';

export const BulkEditQuery = ({ children, bulkDetails, actionMenu }) => {
const {
step,
approach,
currentRecordType
} = useSearchParams();
const intl = useIntl();

Expand Down Expand Up @@ -47,7 +48,7 @@ export const BulkEditQuery = ({ children, bulkDetails, actionMenu }) => {
return (
<FormattedMessage
id={`ui-bulk-edit.list.logSubTitle.${step === EDITING_STEPS.UPLOAD ? 'matched' : 'changed'}`}
values={{ count: countOfRecords }}
values={{ count: countOfRecords, recordType: RECORD_TYPES_MAPPING[currentRecordType] }}
/>
);
}, [isQueryTabWithPreview, countOfRecords, step]);

Check warning on line 54 in src/components/BulkEditPane/BulkEditQuery/BulkEditQuery.js

View workflow job for this annotation

GitHub Actions / github-actions-ci

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

Check warning on line 54 in src/components/BulkEditPane/BulkEditQuery/BulkEditQuery.js

View workflow job for this annotation

GitHub Actions / github-actions-ci

React Hook useMemo has a missing dependency: 'currentRecordType'. Either include it or remove the dependency array
Expand Down
12 changes: 12 additions & 0 deletions src/constants/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,19 @@ export const PAGINATION_CONFIG = {
offset: 0,
};

export const ERRORS_PAGINATION_CONFIG = {
limit: PREVIEW_LIMITS.ERRORS,
offset: 0,
};

export const ERROR_PARAMETERS_KEYS = {
IDENTIFIER: 'IDENTIFIER',
LINK: 'LINK',
};

export const RECORD_TYPES_MAPPING = {
[CAPABILITIES.HOLDING]: 'holding',
[CAPABILITIES.INSTANCE]: 'instance',
[CAPABILITIES.ITEM]: 'item',
[CAPABILITIES.USER]: 'user',
};
Loading

0 comments on commit 38a9ff6

Please sign in to comment.