Skip to content

Commit

Permalink
UIBULKED-561 Add administrative data accordion to MARC bulk edit form
Browse files Browse the repository at this point in the history
  • Loading branch information
vashjs committed Dec 4, 2024
1 parent 4126e2c commit 8eeacc5
Show file tree
Hide file tree
Showing 43 changed files with 706 additions and 659 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* [UIBULKED-587](https://folio-org.atlassian.net/browse/UIBULKED-587) Only Users from the first page are displayed in "Users" dropdown on "Logs" page.
* [UIBULKED-560](https://folio-org.atlassian.net/browse/UIBULKED-560) Update actions menu.
* [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.

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

Expand Down
8 changes: 4 additions & 4 deletions src/components/BulkEditActionMenu/BulkEditActionMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const BulkEditActionMenu = ({
hasEditPerm
&& isInitialStep
&& [JOB_STATUSES.DATA_MODIFICATION, JOB_STATUSES.REVIEW_CHANGES, JOB_STATUSES.REVIEWED_NO_MARC_RECORDS].includes(bulkDetails?.status);
const isStartMarkActive = (isStartBulkInAppActive || hasInstanceAndMarcEditPerm || hasInventoryAndMarcEditPerm) && currentRecordType === CAPABILITIES.INSTANCE && isInitialStep
const isStartMarcActive = (isStartBulkInAppActive || hasInstanceAndMarcEditPerm || hasInventoryAndMarcEditPerm) && currentRecordType === CAPABILITIES.INSTANCE && isInitialStep
&& [JOB_STATUSES.DATA_MODIFICATION, JOB_STATUSES.REVIEW_CHANGES, JOB_STATUSES.REVIEWED_NO_MARC_RECORDS].includes(bulkDetails?.status);

const isStartManualButtonVisible = isStartBulkCsvActive && isInitialStep && countOfRecords > 0 && criteria !== CRITERIA.QUERY && !isECS;
Expand Down Expand Up @@ -146,7 +146,7 @@ const BulkEditActionMenu = ({
</Icon>
</Button>
)}
{isStartMarkActive && (
{isStartMarcActive && (
<ActionMenuGroup
title={<FormattedMessage id="ui-bulk-edit.menuGroup.startEdit" />}
>
Expand All @@ -163,9 +163,9 @@ const BulkEditActionMenu = ({
)}
{(hasInstanceAndMarcEditPerm || hasInventoryAndMarcEditPerm) && (
<Button
data-testid="startMarkAction"
data-testid="startMarcAction"
buttonStyle="dropdownItem"
onClick={() => handleOnStartEdit(APPROACHES.MARK)}
onClick={() => handleOnStartEdit(APPROACHES.MARC)}
>
<Icon icon="edit">
<FormattedMessage id="ui-bulk-edit.start.edit.marc" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ export const BulkEditIdentifiers = ({

const paneTitle = useMemo(() => {
if ((processedFileName || initialFileName) && isIdentifierTabWithPreview) {
const id = approach === APPROACHES.MARK
? 'ui-bulk-edit.meta.title.uploadedFile.mark'
const id = approach === APPROACHES.MARC
? 'ui-bulk-edit.meta.title.uploadedFile.marc'
: 'ui-bulk-edit.meta.title.uploadedFile';
return (
<FormattedMessage
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,80 @@
import React from 'react';
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { useIntl } from 'react-intl';

import { checkIfUserInCentralTenant, useStripes } from '@folio/stripes/core';

import { BulkEditLayer } from '../BulkEditListResult/BulkEditInAppLayer/BulkEditLayer';
import { BulkEditInApp } from '../BulkEditListResult/BulkEditInApp/BulkEditInApp';
import { BulkEditPreviewModal } from '../BulkEditListResult/BulkEditInAppPreviewModal/BulkEditPreviewModal';
import { getContentUpdatesBody } from '../BulkEditListResult/BulkEditInApp/ContentUpdatesForm/helpers';
import { QUERY_KEY_DOWNLOAD_PREVIEW_MODAL, useContentUpdate } from '../../../hooks/api';
import {
getContentUpdatesBody,
getMappedContentUpdates,
isContentUpdatesFormValid
} from '../BulkEditListResult/BulkEditInApp/ContentUpdatesForm/helpers';
import {
QUERY_KEY_DOWNLOAD_PREVIEW_MODAL,
useBulkOperationTenants,
useContentUpdate,
useHoldingsNotes,
useHoldingsNotesEcs,
useInstanceNotes,
useItemNotes,
useItemNotesEcs
} from '../../../hooks/api';
import { useConfirmChanges } from '../../../hooks/useConfirmChanges';
import { savePreviewFile } from '../../../utils/files';
import { useSearchParams } from '../../../hooks';
import {
CAPABILITIES,
getHoldingsOptions,
getInstanceOptions,
getItemsOptions,
getUserOptions
} from '../../../constants';
import { removeDuplicatesByValue } from '../../../utils/helpers';
import { sortAlphabetically } from '../../../utils/sortAlphabetically';


export const BulkEditInAppLayer = ({
bulkOperationId,
contentUpdates,
setContentUpdates,
isInAppLayerOpen,
paneProps,
isInAppFormValid,
closeInAppLayer,
onInAppLayerClose,
}) => {
const stripes = useStripes();
const isCentralTenant = checkIfUserInCentralTenant(stripes);

const { formatMessage } = useIntl();
const { currentRecordType } = useSearchParams();

const isItemRecordType = currentRecordType === CAPABILITIES.ITEM;
const isHoldingsRecordType = currentRecordType === CAPABILITIES.HOLDING;
const isInstanceRecordType = currentRecordType === CAPABILITIES.INSTANCE;

const { data: tenants, isLoading } = useBulkOperationTenants(bulkOperationId);
const { itemNotes, isItemNotesLoading } = useItemNotes({ enabled: isItemRecordType });
const { holdingsNotes, isHoldingsNotesLoading } = useHoldingsNotes({ enabled: isHoldingsRecordType });
const { instanceNotes, isInstanceNotesLoading } = useInstanceNotes({ enabled: isInstanceRecordType });
const { notesEcs: itemNotesEcs, isFetching: isItemsNotesEcsLoading } = useItemNotesEcs(tenants, 'option', { enabled: isItemRecordType && isCentralTenant && !isLoading });
const { notesEcs: holdingsNotesEcs, isFetching: isHoldingsNotesEcsLoading } = useHoldingsNotesEcs(tenants, 'option', { enabled: isHoldingsRecordType && isCentralTenant && !isLoading });

const options = ({
[CAPABILITIES.ITEM]: getItemsOptions(formatMessage, removeDuplicatesByValue(isCentralTenant ? itemNotesEcs : itemNotes, tenants)),
[CAPABILITIES.USER]: getUserOptions(formatMessage),
[CAPABILITIES.HOLDING]: getHoldingsOptions(formatMessage, isCentralTenant ? removeDuplicatesByValue(holdingsNotesEcs, tenants) : holdingsNotes),
[CAPABILITIES.INSTANCE]: getInstanceOptions(formatMessage, instanceNotes),
})[currentRecordType];

const areAllOptionsLoaded = options && !isItemNotesLoading && !isInstanceNotesLoading && !isItemsNotesEcsLoading && !isHoldingsNotesLoading && !isHoldingsNotesEcsLoading;
const sortedOptions = sortAlphabetically(options, formatMessage({ id:'ui-bulk-edit.options.placeholder' }));

const { contentUpdate } = useContentUpdate({ id: bulkOperationId });

const [fields, setFields] = useState([]);
const contentUpdates = getMappedContentUpdates(fields, options);
const isInAppFormValid = isContentUpdatesFormValid(contentUpdates);

const {
isPreviewModalOpened,
isPreviewLoading,
Expand All @@ -31,7 +85,6 @@ export const BulkEditInAppLayer = ({
closePreviewModal,
} = useConfirmChanges({
queryDownloadKey: QUERY_KEY_DOWNLOAD_PREVIEW_MODAL,
updateFn: contentUpdate,
bulkOperationId,
onDownloadSuccess: (fileData, searchParams) => {
const { approach, initialFileName } = searchParams;
Expand All @@ -47,30 +100,35 @@ export const BulkEditInAppLayer = ({

const handleChangesCommited = () => {
closePreviewModal();
closeInAppLayer();
onInAppLayerClose();
};

const handleConfirm = () => {
const contentUpdatesBody = getContentUpdatesBody({
const contentUpdateBody = getContentUpdatesBody({
bulkOperationId,
contentUpdates,
totalRecords,
});

confirmChanges({ contentUpdates: contentUpdatesBody });
confirmChanges([
contentUpdate(contentUpdateBody)
]);
};

return (
<>
<BulkEditLayer
isLayerOpen={isInAppLayerOpen}
isConfirmDisabled={!isInAppFormValid}
onLayerClose={closeInAppLayer}
onLayerClose={onInAppLayerClose}
onConfirm={handleConfirm}
{...paneProps}
>
<BulkEditInApp
onContentUpdatesChanged={setContentUpdates}
fields={fields}
setFields={setFields}
options={sortedOptions}
areAllOptionsLoaded={areAllOptionsLoaded}
/>
</BulkEditLayer>

Expand All @@ -88,14 +146,7 @@ export const BulkEditInAppLayer = ({

BulkEditInAppLayer.propTypes = {
bulkOperationId: PropTypes.string,
contentUpdates: PropTypes.arrayOf(PropTypes.object),
setContentUpdates: PropTypes.func,
isInAppLayerOpen: PropTypes.bool,
isPreviewModalOpened: PropTypes.bool,
paneProps: PropTypes.object,
isInAppFormValid: PropTypes.bool,
closeInAppLayer: PropTypes.func,
openInAppPreviewModal: PropTypes.func,
closeInAppPreviewModal: PropTypes.func,
closePreviewAndLayer: PropTypes.func,
onInAppLayerClose: PropTypes.func,
};
Original file line number Diff line number Diff line change
@@ -1,97 +1,21 @@
import PropTypes from 'prop-types';
import { FormattedMessage, useIntl } from 'react-intl';
import { useContext, useEffect, useMemo, useState } from 'react';
import uniqueId from 'lodash/uniqueId';
import { FormattedMessage } from 'react-intl';
import { useContext } from 'react';

import {
Headline,
Accordion,
Loading,
Layout,
} from '@folio/stripes/components';
import {
checkIfUserInCentralTenant,
useStripes,
} from '@folio/stripes/core';

import { BulkEditInAppTitle } from './BulkEditInAppTitle/BulkEditInAppTitle';
import { ContentUpdatesForm } from './ContentUpdatesForm/ContentUpdatesForm';
import {
CAPABILITIES,
getHoldingsOptions,
getInstanceOptions,
getItemsOptions,
getUserOptions
} from '../../../../constants';
import {
useItemNotes,
useHoldingsNotes,
useInstanceNotes,
useBulkOperationTenants,
useHoldingsNotesEcs,
useItemNotesEcs
} from '../../../../hooks/api';
import { sortAlphabetically } from '../../../../utils/sortAlphabetically';
import {
usePathParams,
useSearchParams
} from '../../../../hooks';
import { getDefaultActions } from './ContentUpdatesForm/helpers';

import { RootContext } from '../../../../context/RootContext';
import { removeDuplicatesByValue } from '../../../../utils/helpers';

export const BulkEditInApp = ({
onContentUpdatesChanged,
}) => {
export const BulkEditInApp = ({ areAllOptionsLoaded, options, fields, setFields }) => {
const { title } = useContext(RootContext);
const stripes = useStripes();
const isCentralTenant = checkIfUserInCentralTenant(stripes);

const { formatMessage } = useIntl();
const { currentRecordType } = useSearchParams();
const { id: bulkOperationId } = usePathParams('/bulk-edit/:id');
const [fields, setFields] = useState([]);

const isItemRecordType = currentRecordType === CAPABILITIES.ITEM;
const isHoldingsRecordType = currentRecordType === CAPABILITIES.HOLDING;
const isInstanceRecordType = currentRecordType === CAPABILITIES.INSTANCE;

const { data: tenants, isLoading } = useBulkOperationTenants(bulkOperationId);
const { itemNotes, isItemNotesLoading } = useItemNotes({ enabled: isItemRecordType });
const { holdingsNotes, isHoldingsNotesLoading } = useHoldingsNotes({ enabled: isHoldingsRecordType });
const { instanceNotes, isInstanceNotesLoading } = useInstanceNotes({ enabled: isInstanceRecordType });
const { notesEcs: itemNotesEcs, isFetching: isItemsNotesEcsLoading } = useItemNotesEcs(tenants, 'option', { enabled: isItemRecordType && isCentralTenant && !isLoading });
const { notesEcs: holdingsNotesEcs, isFetching: isHoldingsNotesEcsLoading } = useHoldingsNotesEcs(tenants, 'option', { enabled: isHoldingsRecordType && isCentralTenant && !isLoading });

const options = useMemo(() => ({
[CAPABILITIES.ITEM]: getItemsOptions(formatMessage, removeDuplicatesByValue(isCentralTenant ? itemNotesEcs : itemNotes, tenants)),
[CAPABILITIES.USER]: getUserOptions(formatMessage),
[CAPABILITIES.HOLDING]: getHoldingsOptions(formatMessage, isCentralTenant ? removeDuplicatesByValue(holdingsNotesEcs, tenants) : holdingsNotes),
[CAPABILITIES.INSTANCE]: getInstanceOptions(formatMessage, instanceNotes),
})[currentRecordType], [formatMessage, isCentralTenant, itemNotesEcs, itemNotes, tenants, holdingsNotesEcs, holdingsNotes, instanceNotes, currentRecordType]);

const showContentUpdatesForm = options && !isItemNotesLoading && !isInstanceNotesLoading && !isItemsNotesEcsLoading && !isHoldingsNotesLoading && !isHoldingsNotesEcsLoading;
const sortedOptions = sortAlphabetically(options, formatMessage({ id:'ui-bulk-edit.options.placeholder' }));

const fieldTemplate = useMemo(() => {
return ({
id: uniqueId(),
options,
option: '',
tenants: [],
actionsDetails: getDefaultActions({
option: '',
capability: currentRecordType,
options,
formatMessage
}),
});
}, [currentRecordType, formatMessage, options]);

useEffect(() => {
setFields([fieldTemplate]);
}, [fieldTemplate]);

return (
<>
Expand All @@ -101,15 +25,15 @@ export const BulkEditInApp = ({
<Accordion
label={<FormattedMessage id="ui-bulk-edit.layer.title" />}
>
{showContentUpdatesForm ? (
{areAllOptionsLoaded ? (
<>
<BulkEditInAppTitle fields={fields} />
<BulkEditInAppTitle
fields={fields}
/>
<ContentUpdatesForm
fieldTemplate={fieldTemplate}
fields={fields}
setFields={setFields}
options={sortedOptions}
onContentUpdatesChanged={onContentUpdatesChanged}
options={options}
/>
</>
) : (
Expand All @@ -123,5 +47,8 @@ export const BulkEditInApp = ({
};

BulkEditInApp.propTypes = {
onContentUpdatesChanged: PropTypes.func,
areAllOptionsLoaded: PropTypes.bool.isRequired,
options: PropTypes.arrayOf(PropTypes.object),
fields: PropTypes.arrayOf(PropTypes.object).isRequired,
setFields: PropTypes.func.isRequired,
};
Loading

0 comments on commit 8eeacc5

Please sign in to comment.