diff --git a/CHANGELOG.md b/CHANGELOG.md index 4392a3e5..35949477 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## 6.1.0 (IN PROGRESS) +* Add "Mark late" action to the piece form action menu. Refs UIREC-413. + ## [6.0.5](https://github.com/folio-org/ui-receiving/tree/v6.0.5) (2024-12-13) [Full Changelog](https://github.com/folio-org/ui-receiving/compare/v6.0.4...v6.0.5) diff --git a/src/Piece/PieceForm/PieceForm.js b/src/Piece/PieceForm/PieceForm.js index 51b0c0f2..6fd565ad 100644 --- a/src/Piece/PieceForm/PieceForm.js +++ b/src/Piece/PieceForm/PieceForm.js @@ -213,6 +213,7 @@ const PieceForm = ({ [PIECE_ACTION_NAMES.unReceive]: isEditDisabled, [PIECE_ACTION_NAMES.sendClaim]: isEditDisabled, [PIECE_ACTION_NAMES.delayClaim]: isEditDisabled, + [PIECE_ACTION_NAMES.markLate]: isEditDisabled, }; const start = ( diff --git a/src/Piece/PieceForm/PieceFormActionButtons/PieceFormActionButtons.js b/src/Piece/PieceForm/PieceFormActionButtons/PieceFormActionButtons.js index 79eea069..7e5435fd 100644 --- a/src/Piece/PieceForm/PieceFormActionButtons/PieceFormActionButtons.js +++ b/src/Piece/PieceForm/PieceFormActionButtons/PieceFormActionButtons.js @@ -1,5 +1,6 @@ -import { useState } from 'react'; +import noop from 'lodash/noop'; import PropTypes from 'prop-types'; +import { useRef } from 'react'; import { FormattedMessage } from 'react-intl'; import { @@ -28,21 +29,18 @@ export const PieceFormActionButtons = ({ onUnreceivePiece, status = PIECE_STATUS.expected, }) => { - const [actionsKey, setActionsKey] = useState(new Date()); + const onToggleRef = useRef(noop); const actionMenu = getPieceActionMenu({ actionsDisabled, isEditMode, onClaimDelay, onClaimSend, - onCreateAnotherPiece: () => { - setActionsKey(new Date()); - - return onCreateAnotherPiece(); - }, + onCreateAnotherPiece, onDelete, onReceive, onStatusChange, + onToggle: onToggleRef.current, onUnreceivePiece, status, }); @@ -77,7 +75,6 @@ export const PieceFormActionButtons = ({ - - {actionMenu} - + {({ onToggle }) => { + onToggleRef.current = onToggle; + + return ( + + {actionMenu} + + ); + }} ); diff --git a/src/Piece/PieceForm/PieceFormActionButtons/constants.js b/src/Piece/PieceForm/PieceFormActionButtons/constants.js index 6f423d4e..d6e35765 100644 --- a/src/Piece/PieceForm/PieceFormActionButtons/constants.js +++ b/src/Piece/PieceForm/PieceFormActionButtons/constants.js @@ -1,3 +1,4 @@ +import without from 'lodash/without'; import { FormattedMessage } from 'react-intl'; import { @@ -12,6 +13,7 @@ export const EXPECTED_PIECES_ACTIONS = [ PIECE_ACTION_NAMES.saveAndCreate, PIECE_ACTION_NAMES.quickReceive, PIECE_ACTION_NAMES.sendClaim, + PIECE_ACTION_NAMES.markLate, PIECE_ACTION_NAMES.delayClaim, PIECE_ACTION_NAMES.unReceivable, PIECE_ACTION_NAMES.delete, @@ -21,7 +23,7 @@ export const PIECE_ACTIONS_BY_STATUS = { [PIECE_STATUS.expected]: EXPECTED_PIECES_ACTIONS, [PIECE_STATUS.claimDelayed]: EXPECTED_PIECES_ACTIONS, [PIECE_STATUS.claimSent]: EXPECTED_PIECES_ACTIONS, - [PIECE_STATUS.late]: EXPECTED_PIECES_ACTIONS, + [PIECE_STATUS.late]: without(EXPECTED_PIECES_ACTIONS, PIECE_ACTION_NAMES.markLate), [PIECE_STATUS.received]: [ PIECE_ACTION_NAMES.saveAndCreate, PIECE_ACTION_NAMES.unReceive, @@ -40,17 +42,21 @@ export const PIECE_ACTIONS = ({ onClaimDelay, onClaimSend, onCreateAnotherPiece, - onStatusChange, onDelete, onReceive, + onStatusChange, + onToggle, onUnreceivePiece, }) => ({ [PIECE_ACTION_NAMES.delayClaim]: ( ), + [PIECE_ACTION_NAMES.markLate]: ( + + ), }); diff --git a/src/Piece/PieceForm/PieceFormActionButtons/utils.test.js b/src/Piece/PieceForm/PieceFormActionButtons/utils.test.js index 9b2b89cd..ad6b780b 100644 --- a/src/Piece/PieceForm/PieceFormActionButtons/utils.test.js +++ b/src/Piece/PieceForm/PieceFormActionButtons/utils.test.js @@ -7,36 +7,49 @@ import { getPieceActionMenu } from './utils'; const { expected, unreceivable, received } = PIECE_STATUS; describe('getPieceActionMenus', () => { + const onToggle = jest.fn(); + it('should return empty array if status is not provided', () => { - const result = getPieceActionMenu({}); + const result = getPieceActionMenu({ onToggle }); expect(result).toEqual([]); }); it('should return empty array if status is not in PIECE_ACTIONS_BY_STATUS', () => { - const result = getPieceActionMenu({ status: 'status' }); + const result = getPieceActionMenu({ + onToggle, + status: 'status', + }); expect(result).toEqual([]); }); it('should return array of action menus', () => { - const result = getPieceActionMenu({ status: expected }); + const result = getPieceActionMenu({ + onToggle, + 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, isEditMode: false }); + const result = getPieceActionMenu({ + onToggle, + status: expected, + isEditMode: false, + }); expect(result).toContain(null); }); it('should `delete` button be disabled', () => { const result = getPieceActionMenu({ - status: expected, actionsDisabled: { [PIECE_ACTION_NAMES.delete]: true }, isEditMode: true, + onToggle, + status: expected, }); const deleteButton = result.find(i => i.props['data-testid'] === 'delete-piece-button'); @@ -47,7 +60,11 @@ describe('getPieceActionMenus', () => { describe('expect action', () => { it('should `onStatusChange` be called with `Expected` status value', () => { const onStatusChange = jest.fn(); - const result = getPieceActionMenu({ status: unreceivable, onStatusChange }); + const result = getPieceActionMenu({ + status: unreceivable, + onStatusChange, + onToggle, + }); const expectButton = result.find(i => i.props['data-testid'] === 'expect-piece-button'); expectButton.props.onClick(); @@ -59,7 +76,11 @@ describe('getPieceActionMenus', () => { describe('unReceive action', () => { it('should `onUnreceivePiece` be called with `Expected` status value', () => { const onUnreceivePiece = jest.fn(); - const result = getPieceActionMenu({ status: received, onUnreceivePiece }); + const result = getPieceActionMenu({ + status: received, + onToggle, + onUnreceivePiece, + }); const receiveButton = result.find(i => i.props['data-testid'] === 'unReceive-piece-button'); receiveButton.props.onClick(); @@ -71,7 +92,11 @@ describe('getPieceActionMenus', () => { describe('unReceivable action', () => { it('should `onStatusChange` be called with `Unreceivable` status value', () => { const onStatusChange = jest.fn(); - const result = getPieceActionMenu({ status: expected, onStatusChange }); + const result = getPieceActionMenu({ + status: expected, + onStatusChange, + onToggle, + }); const receiveButton = result.find(i => i.props['data-testid'] === 'unReceivable-piece-button'); receiveButton.props.onClick(); @@ -79,4 +104,21 @@ describe('getPieceActionMenus', () => { expect(onStatusChange).toHaveBeenCalledWith(PIECE_STATUS.unreceivable); }); }); + + describe('"Mark late" action', () => { + it('should call `onStatusChange` with `Late` status value', () => { + const onStatusChange = jest.fn(); + + const result = getPieceActionMenu({ + status: expected, + onStatusChange, + onToggle, + }); + const markLateButton = result.find(i => i.props['data-testid'] === 'mark-late-piece-button'); + + markLateButton.props.onClick(); + + expect(onStatusChange).toHaveBeenCalledWith(PIECE_STATUS.late); + }); + }); }); diff --git a/src/Piece/constants.js b/src/Piece/constants.js index a61375bc..b1af826a 100644 --- a/src/Piece/constants.js +++ b/src/Piece/constants.js @@ -199,6 +199,7 @@ export const PIECE_ACTION_NAMES = { saveAndClose: 'saveAndClose', saveAndCreate: 'saveAndCreate', quickReceive: 'quickReceive', + markLate: 'markLate', sendClaim: 'sendClaim', delayClaim: 'delayClaim', unReceivable: 'unReceivable', diff --git a/translations/ui-receiving/en.json b/translations/ui-receiving/en.json index 480c5a5f..0ace1d2f 100644 --- a/translations/ui-receiving/en.json +++ b/translations/ui-receiving/en.json @@ -208,6 +208,7 @@ "piece.action.button.unReceive": "Unreceive", "piece.action.button.delete": "Delete", "piece.action.button.expect": "Expect", + "piece.action.button.markLate": "Mark late", "piece.callNumber": "Call number", "piece.displaySummary": "Display summary", "piece.copyNumber": "Copy number",