Skip to content

Commit

Permalink
UIREC-292 Provide independent 'disabled' status for piece actions (#478)
Browse files Browse the repository at this point in the history
* UIREC-292 Provide independent 'disabled' status for piece actions

* UIREC-292 Handle create another piece state

* provide default value

* update comment

* fix test

* Mock resize observer
  • Loading branch information
usavkov-epam authored and NikitaSedyx committed Feb 21, 2024
1 parent da83766 commit 2e3d53f
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 26 deletions.
21 changes: 19 additions & 2 deletions src/TitleDetails/AddPieceModal/AddPieceModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import includes from 'lodash/includes';
import PropTypes from 'prop-types';
import {
useCallback,
useEffect,
useMemo,
useRef,
} from 'react';
Expand Down Expand Up @@ -59,6 +60,7 @@ import { DeletePieceModal } from '../DeletePieceModal';
import { DeleteHoldingsModal } from '../DeleteHoldingsModal';
import { SendClaimModal } from '../SendClaimModal';
import { ModalActionButtons } from './ModalActionButtons';
import { PIECE_ACTION_NAMES } from './ModalActionButtons/constants';
import { ReceivingStatusChangeLog } from './ReceivingStatusChangeLog';

const AddPieceModal = ({
Expand Down Expand Up @@ -98,6 +100,14 @@ const AddPieceModal = ({
receivingStatus,
} = formValues;

/*
When the "saveAndCreate" action is triggered, `isCreateAnother` is passed as an initial value to apply validations.
This param should be reset to `false` after the component init.
*/
useEffect(() => {
change('isCreateAnother', false);
}, [change]);

const isLocationRequired = includes(createInventoryValues[format], INVENTORY_RECORDS_TYPE.instanceAndHolding);
const isNotReceived = receivingStatus !== PIECE_STATUS.received;
const labelId = id ? 'ui-receiving.piece.addPieceModal.editTitle' : 'ui-receiving.piece.addPieceModal.title';
Expand Down Expand Up @@ -196,6 +206,14 @@ const AddPieceModal = ({
onStatusChange(PIECE_STATUS.claimSent);
}, [batch, change, onStatusChange]);

const actionsDisabled = {
[PIECE_ACTION_NAMES.quickReceive]: disabled,
[PIECE_ACTION_NAMES.saveAndClose]: disabled,
[PIECE_ACTION_NAMES.saveAndCreate]: disabled,
[PIECE_ACTION_NAMES.unReceivable]: disabled,
[PIECE_ACTION_NAMES.delete]: !canDeletePiece,
};

const start = (
<Button
data-test-add-piece-cancel
Expand All @@ -207,8 +225,7 @@ const AddPieceModal = ({
);
const end = (
<ModalActionButtons
canDeletePiece={canDeletePiece}
disabled={disabled}
actionsDisabled={actionsDisabled}
isCreateAnother={isCreateAnother}
isEditMode={Boolean(id)}
onCreateAnotherPiece={onCreateAnotherPiece}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import {
} from '@folio/stripes/components';
import { PIECE_STATUS } from '@folio/stripes-acq-components';

import { PIECE_ACTION_NAMES } from './constants';
import { getPieceActionMenu } from './utils';

import css from './ModalActionButtons.css';

export const ModalActionButtons = ({
actionsDisabled,
canDeletePiece,
disabled,
isEditMode,
onClaimDelay,
onClaimSend,
Expand All @@ -27,8 +28,8 @@ export const ModalActionButtons = ({
status,
}) => {
const actionMenu = getPieceActionMenu({
actionsDisabled,
canDeletePiece,
disabled,
isEditMode,
onClaimDelay,
onClaimSend,
Expand All @@ -39,13 +40,14 @@ export const ModalActionButtons = ({
status,
});
const saveButtonLabelId = 'ui-receiving.piece.actions.saveAndClose';
const isSaveDisabled = actionsDisabled[PIECE_ACTION_NAMES.saveAndClose];

if (actionMenu.length === 0) {
return (
<Button
buttonStyle="primary"
data-test-add-piece-save
disabled={disabled}
disabled={isSaveDisabled}
onClick={onSave}
marginBottom0
>
Expand All @@ -59,7 +61,7 @@ export const ModalActionButtons = ({
<Button
buttonStyle="primary"
data-test-add-piece-save
disabled={disabled}
disabled={isSaveDisabled}
onClick={onSave}
marginBottom0
buttonClass={css.saveButton}
Expand All @@ -83,8 +85,8 @@ export const ModalActionButtons = ({
};

ModalActionButtons.propTypes = {
actionsDisabled: PropTypes.objectOf(PropTypes.bool),
canDeletePiece: PropTypes.bool,
disabled: PropTypes.bool,
isEditMode: PropTypes.bool.isRequired,
onClaimDelay: PropTypes.func.isRequired,
onClaimSend: PropTypes.func.isRequired,
Expand All @@ -97,7 +99,7 @@ ModalActionButtons.propTypes = {
};

ModalActionButtons.defaultProps = {
actionsDisabled: {},
canDeletePiece: false,
disabled: false,
status: PIECE_STATUS.expected,
};
20 changes: 10 additions & 10 deletions src/TitleDetails/AddPieceModal/ModalActionButtons/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
import { PIECE_STATUS } from '@folio/stripes-acq-components';

export const PIECE_ACTION_NAMES = {
saveAndClose: 'saveAndClose',
saveAndCreate: 'saveAndCreate',
quickReceive: 'quickReceive',
sendClaim: 'sendClaim',
Expand Down Expand Up @@ -44,8 +45,7 @@ export const PIECE_ACTIONS_BY_STATUS = {
};

export const PIECE_ACTIONS = ({
canDeletePiece,
disabled,
actionsDisabled = {},
isEditMode,
onClaimDelay,
onClaimSend,
Expand All @@ -56,7 +56,7 @@ export const PIECE_ACTIONS = ({
}) => ({
delayClaim: (
<Button
disabled={disabled}
disabled={actionsDisabled[PIECE_ACTION_NAMES.delayClaim]}
buttonStyle="dropdownItem"
data-testid="delay-claim-button"
onClick={onClaimDelay}
Expand All @@ -71,7 +71,7 @@ export const PIECE_ACTIONS = ({
onClick={onDelete}
buttonStyle="dropdownItem"
data-testid="delete-piece-button"
disabled={!canDeletePiece || disabled}
disabled={actionsDisabled[PIECE_ACTION_NAMES.delete]}
>
<Icon icon="trash">
<FormattedMessage id="ui-receiving.piece.action.button.delete" />
Expand All @@ -80,7 +80,7 @@ export const PIECE_ACTIONS = ({
) : null,
expect: (
<Button
disabled={disabled}
disabled={actionsDisabled[PIECE_ACTION_NAMES.expect]}
buttonStyle="dropdownItem"
data-testid="expect-piece-button"
onClick={() => onStatusChange(PIECE_STATUS.expected)}
Expand All @@ -92,7 +92,7 @@ export const PIECE_ACTIONS = ({
),
quickReceive: (
<Button
disabled={disabled}
disabled={actionsDisabled[PIECE_ACTION_NAMES.quickReceive]}
data-testid="quickReceive"
buttonStyle="dropdownItem"
onClick={onReceive}
Expand All @@ -104,7 +104,7 @@ export const PIECE_ACTIONS = ({
),
saveAndCreate: (
<Button
disabled={disabled}
disabled={actionsDisabled[PIECE_ACTION_NAMES.saveAndCreate]}
buttonStyle="dropdownItem"
data-testid="create-another-piece-button"
onClick={onCreateAnotherPiece}
Expand All @@ -116,7 +116,7 @@ export const PIECE_ACTIONS = ({
),
sendClaim: (
<Button
disabled={disabled}
disabled={actionsDisabled[PIECE_ACTION_NAMES.sendClaim]}
buttonStyle="dropdownItem"
data-testid="send-claim-button"
onClick={onClaimSend}
Expand All @@ -128,7 +128,7 @@ export const PIECE_ACTIONS = ({
),
unReceive: (
<Button
disabled={disabled}
disabled={actionsDisabled[PIECE_ACTION_NAMES.unReceive]}
buttonStyle="dropdownItem"
data-testid="unReceive-piece-button"
onClick={() => onStatusChange(PIECE_STATUS.expected)}
Expand All @@ -140,7 +140,7 @@ export const PIECE_ACTIONS = ({
),
unReceivable: (
<Button
disabled={disabled}
disabled={actionsDisabled[PIECE_ACTION_NAMES.unReceivable]}
buttonStyle="dropdownItem"
data-testid="unReceivable-piece-button"
onClick={() => onStatusChange(PIECE_STATUS.unreceivable)}
Expand Down
23 changes: 15 additions & 8 deletions src/TitleDetails/AddPieceModal/ModalActionButtons/utils.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { PIECE_STATUS } from '@folio/stripes-acq-components';

import { PIECE_ACTIONS_BY_STATUS } from './constants';
import {
PIECE_ACTIONS_BY_STATUS,
PIECE_ACTION_NAMES,
} from './constants';
import { getPieceActionMenu } from './utils';

const { expected, unreceivable, received } = PIECE_STATUS;
Expand All @@ -19,20 +22,24 @@ describe('getPieceActionMenus', () => {
});

it('should return array of action menus', () => {
const result = getPieceActionMenu({ status: expected, disabled: false });
const result = getPieceActionMenu({ status: expected });

expect(result).toHaveLength(PIECE_ACTIONS_BY_STATUS[expected].length);
});

describe('delete action', () => {
it('should not return `delete` action menu if `isEditMode` is false', () => {
const result = getPieceActionMenu({ status: expected, disabled: false, isEditMode: false });
const result = getPieceActionMenu({ status: expected, isEditMode: false });

expect(result).toContain(null);
});

it('should `delete` button be disabled if `canDeletePiece` is false', () => {
const result = getPieceActionMenu({ status: expected, disabled: false, isEditMode: true, canDeletePiece: false });
it('should `delete` button be disabled', () => {
const result = getPieceActionMenu({
status: expected,
actionsDisabled: { [PIECE_ACTION_NAMES.delete]: true },
isEditMode: true,
});
const deleteButton = result.find(i => i.props['data-testid'] === 'delete-piece-button');

expect(deleteButton.props).toEqual(expect.objectContaining({ disabled: true }));
Expand All @@ -42,7 +49,7 @@ describe('getPieceActionMenus', () => {
describe('expect action', () => {
it('should `onStatusChange` be called with `Expected` status value', () => {
const onStatusChange = jest.fn();
const result = getPieceActionMenu({ status: unreceivable, disabled: true, onStatusChange });
const result = getPieceActionMenu({ status: unreceivable, onStatusChange });
const expectButton = result.find(i => i.props['data-testid'] === 'expect-piece-button');

expectButton.props.onClick();
Expand All @@ -54,7 +61,7 @@ describe('getPieceActionMenus', () => {
describe('unReceive action', () => {
it('should `onStatusChange` be called with `Expected` status value', () => {
const onStatusChange = jest.fn();
const result = getPieceActionMenu({ status: received, disabled: false, onStatusChange });
const result = getPieceActionMenu({ status: received, onStatusChange });
const receiveButton = result.find(i => i.props['data-testid'] === 'unReceive-piece-button');

receiveButton.props.onClick();
Expand All @@ -66,7 +73,7 @@ describe('getPieceActionMenus', () => {
describe('unReceivable action', () => {
it('should `onStatusChange` be called with `Unreceivable` status value', () => {
const onStatusChange = jest.fn();
const result = getPieceActionMenu({ status: expected, disabled: false, onStatusChange });
const result = getPieceActionMenu({ status: expected, onStatusChange });
const receiveButton = result.find(i => i.props['data-testid'] === 'unReceivable-piece-button');

receiveButton.props.onClick();
Expand Down
1 change: 1 addition & 0 deletions src/TitleDetails/TitleDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ const TitleDetails = ({
const pieceFormValues = {
...omit(piece, ['id', 'itemId', 'receivingStatus', 'receivedDate']),
isCreateItem: piece?.itemId ? true : piece?.isCreateItem,
isCreateAnother: true,
};

setPieceValues(pieceFormValues);
Expand Down
1 change: 1 addition & 0 deletions test/jest/__mock__/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
import './createRange.mock';
import './resizeObserver.mock';
5 changes: 5 additions & 0 deletions test/jest/__mock__/resizeObserver.mock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
global.ResizeObserver = jest.fn().mockImplementation(() => ({
observe: jest.fn(),
unobserve: jest.fn(),
disconnect: jest.fn(),
}));

0 comments on commit 2e3d53f

Please sign in to comment.