Skip to content

Commit

Permalink
UIREQMED-42: Add Decline Action for Mediated request with status of N…
Browse files Browse the repository at this point in the history
…ew - Awaiting confirmation
  • Loading branch information
Dmitriy-Litvinenko committed Nov 11, 2024
1 parent cfe0c4d commit 85ac249
Show file tree
Hide file tree
Showing 13 changed files with 319 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* Implement functionality for editing mediated request. Refs UIREQMED-22.
* *BREAKING* Migrate to new `mod-circulation-bff` endpoints. Refs UIREQMED-39.
* Add circulation-storage.staff-slips.collection.get for get staff-slips on Send item in transit. Refs UIREQMED-55.
* Add Decline Action for Mediated request with status of New - Awaiting confirmation. Refs UIREQMED-42.

## [1.1.0](https://github.com/folio-org/ui-requests-mediated/tree/v1.1.0) (2024-10-30)
* Update github actions. Refs UIREQMED-14.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@
],
"subPermissions": [
"ui-requests-mediated.view",
"requests-mediated.mediated-request.item.delete"
"requests-mediated.decline-mediated-request.execute"
],
"visible": true
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import {
useState,
} from 'react';
import PropTypes from 'prop-types';
import {
useHistory,
Expand All @@ -14,6 +17,7 @@ import {
import {
IfPermission,
TitleManager,
useOkapiKy,
} from '@folio/stripes/core';
import {
Button,
Expand All @@ -31,6 +35,7 @@ import TitleInformation from '../TitleInformation';
import MediatedRequestInformation from '../MediatedRequestInformation';
import ItemDetail from '../ItemDetail';
import UserDetail from '../UserDetail';
import DeclineModal from './components/DeclineModal';
import {
useMediatedRequestById,
useUserById,
Expand All @@ -52,6 +57,7 @@ import {
getPatronGroup,
getUserPreferences,
getReferredRecordData,
confirmDeclineModal,
} from '../../../../utils';

const DETAIL_PANE_WIDTH = '44%';
Expand All @@ -64,22 +70,40 @@ const MediatedRequestsDetail = ({
stripes,
patronGroups,
setRequest,
updateMediatedRequestList,
}) => {
const history = useHistory();
const location = useLocation();
const ky = useOkapiKy();
const mediatedRequestIdFromPathname = location.pathname.substring(location.pathname.lastIndexOf('/') + 1);

const { formatMessage } = useIntl();
const {
mediatedRequest,
isFetching,
shouldUpdateMediatedRequestById,
setShouldUpdateMediatedRequestById,
} = useMediatedRequestById(mediatedRequestIdFromPathname);
const { userData } = useUserById(mediatedRequest?.requesterId, isFetching);
const { servicePoints } = useServicePoints();
const mediatedRequestsActivitiesUrl = getMediatedRequestsActivitiesUrl();

setRequest(mediatedRequest);

const [declineModalOpen, setDeclineModalOpen] = useState(false);
const onOpenDeclineModal = () => setDeclineModalOpen(true);
const declineModalState = {
shouldUpdateMediatedRequestById,
setShouldUpdateMediatedRequestById,
setDeclineModalOpen,
};
const declineModalProps = {
ky,
url: `requests-mediated/mediated-requests/${mediatedRequestIdFromPathname}/decline`,
updateMediatedRequestList,
};
const onConfirmDeclineModal = () => confirmDeclineModal(declineModalState, declineModalProps);
const onCloseDeclineModal = () => setDeclineModalOpen(false);
const isActionMenuVisible = () => (
get(mediatedRequest, MEDIATED_REQUESTS_RECORD_FIELD_PATH[MEDIATED_REQUESTS_RECORD_FIELD_NAME.STATUS], DEFAULT_VIEW_VALUE) === MEDIATED_REQUEST_STATUS.NEW_AWAITING_CONFIRMATION
? stripes.hasPerm('ui-requests-mediated.requests-mediated.view-confirm.execute') || stripes.hasPerm('ui-requests-mediated.requests-mediated.view-create-edit.execute') || stripes.hasPerm('ui-requests-mediated.requests-mediated.view-decline.execute')
Expand All @@ -96,6 +120,10 @@ const MediatedRequestsDetail = ({
onToggle();
history.push(`${mediatedRequestsActivitiesUrl}/edit/${mediatedRequestIdFromPathname}`);
};
const handleDecline = () => {
onOpenDeclineModal();
onToggle();
};

return (
<>
Expand All @@ -114,7 +142,7 @@ const MediatedRequestsDetail = ({
<Button
buttonStyle="dropdownItem"
marginBottom0
onClick={onToggle}
onClick={handleDecline}
>
<Icon icon={ICONS.TIMES_CIRCLE}>
<FormattedMessage id="ui-requests-mediated.mediatedRequestDetails.actionMenu.decline" />
Expand Down Expand Up @@ -218,6 +246,12 @@ const MediatedRequestsDetail = ({
hideAssignButton
/>
</AccordionStatus>
<DeclineModal
open={declineModalOpen}
title={get(mediatedRequest, MEDIATED_REQUESTS_RECORD_FIELD_PATH[MEDIATED_REQUESTS_RECORD_FIELD_NAME.TITLE], DEFAULT_VIEW_VALUE)}
onConfirm={onConfirmDeclineModal}
onClose={onCloseDeclineModal}
/>
</>
}
</Pane>
Expand All @@ -227,6 +261,7 @@ const MediatedRequestsDetail = ({
MediatedRequestsDetail.propTypes = {
stripes: PropTypes.object.isRequired,
setRequest: PropTypes.func.isRequired,
updateMediatedRequestList: PropTypes.func.isRequired,
patronGroups: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.string,
group: PropTypes.string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
fireEvent,
render,
screen,
act,

Check warning on line 7 in src/components/MediatedRequestsActivities/components/MediatedRequestsDetail/MediatedRequestsDetail.test.js

View workflow job for this annotation

GitHub Actions / build-npm

'act' is defined but never used. Allowed unused vars must match /React/u

Check warning on line 7 in src/components/MediatedRequestsActivities/components/MediatedRequestsDetail/MediatedRequestsDetail.test.js

View workflow job for this annotation

GitHub Actions / build-npm

'act' is defined but never used. Allowed unused vars must match /React/u
} from '@folio/jest-config-stripes/testing-library/react';
import { NotesSmartAccordion } from '@folio/stripes/smart-components';
import { TitleManager } from '@folio/stripes/core';
Expand Down Expand Up @@ -57,6 +58,8 @@ const labelIds = {
requesterAccordion: 'ui-requests-mediated.mediatedRequestDetail.requester.accordionLabel',
noItemInformation: 'ui-requests-mediated.mediatedRequestDetail.item.noInformation',
editAndConfirmButton: 'ui-requests-mediated.mediatedRequestDetails.actionMenu.editAndConfirm',
declineButton: 'ui-requests-mediated.mediatedRequestDetails.actionMenu.decline',
declineModalTitle: 'ui-requests-mediated.declineModal.title',
};

describe('MediatedRequestsDetail', () => {
Expand Down Expand Up @@ -349,5 +352,11 @@ describe('MediatedRequestsDetail', () => {

expect(push).toHaveBeenCalledWith(`${getMediatedRequestsActivitiesUrl()}/edit/id`);
});

it('should render "Decline" button', () => {
const declineButton = screen.getByText(labelIds.declineButton);

expect(declineButton).toBeInTheDocument();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import {
Button,
Modal,
ModalFooter,
} from '@folio/stripes/components';

const DeclineModal = ({
open,
title,
onConfirm,
onClose,
}) => {
const footer = (
<ModalFooter>
<Button
data-testid="confirmButton"
buttonStyle="primary"
onClick={onConfirm}
>
<FormattedMessage id="ui-requests-mediated.declineModal.confirm" />
</Button>
<Button
data-testid="backButton"
onClick={onClose}
>
<FormattedMessage id="ui-requests-mediated.declineModal.back" />
</Button>
</ModalFooter>
);

return (
<Modal
dismissible
label={<FormattedMessage id="ui-requests-mediated.declineModal.title" />}
open={open}
size="small"
footer={footer}
onClose={onClose}
>
<FormattedMessage
id="ui-requests-mediated.declineModal.message"
values={{ title }}
/>
</Modal>
);
};

DeclineModal.propTypes = {
open: PropTypes.bool.isRequired,
title: PropTypes.string.isRequired,
onConfirm: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
};

export default DeclineModal;
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import {
render,
screen,
fireEvent,
} from '@folio/jest-config-stripes/testing-library/react';

import DeclineModal from './DeclineModal';

const testIds = {
confirmButton: 'confirmButton',
backButton: 'backButton',
};
const messageIds = {
title: 'ui-requests-mediated.declineModal.title',
message: 'ui-requests-mediated.declineModal.message',
confirmButton: 'ui-requests-mediated.declineModal.confirm',
backButton: 'ui-requests-mediated.declineModal.back',
};
const defaultProps = {
open: true,
title: 'Title',
onConfirm: jest.fn(),
onClose: jest.fn(),
};

describe('DeclineModal', () => {
afterEach(() => {
jest.clearAllMocks();
});

beforeEach(() => {
render(
<DeclineModal {...defaultProps} />
);
});

it('should render title', () => {
expect(screen.getByText(messageIds.title)).toBeVisible();
});

it('should render message', () => {
expect(screen.getByText(messageIds.message)).toBeVisible();
});

describe('Confirm button', () => {
it('should render confirm button', () => {
expect(screen.getByTestId(testIds.confirmButton)).toBeVisible();
});

it('should render confirm button text', () => {
expect(screen.getByText(messageIds.confirmButton)).toBeVisible();
});

it('should call onConfirm', () => {
fireEvent.click(screen.getByTestId(testIds.confirmButton));

expect(defaultProps.onConfirm).toHaveBeenCalled();
});
});

describe('Back button', () => {
it('should render back button', () => {
expect(screen.getByTestId(testIds.backButton)).toBeVisible();
});

it('should render back button text', () => {
expect(screen.getByText(messageIds.backButton)).toBeVisible();
});

it('should call onClose', () => {
fireEvent.click(screen.getByTestId(testIds.backButton));

expect(defaultProps.onClose).toHaveBeenCalled();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './DeclineModal';
10 changes: 9 additions & 1 deletion src/hooks/useMediatedRequestById/useMediatedRequestById.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import {
useState,
} from 'react';

import { useQuery } from 'react-query';

import {
Expand All @@ -6,20 +10,24 @@ import {
} from '@folio/stripes/core';

const useMediatedRequestById = (mediatedRequestId) => {
const [shouldUpdateMediatedRequestById, setShouldUpdateMediatedRequestById] = useState(0);

const ky = useOkapiKy();
const [namespace] = useNamespace({ key: 'mediatedRequest' });
const {
data,
isFetching,
} = useQuery(
[namespace, mediatedRequestId],
[namespace, mediatedRequestId, shouldUpdateMediatedRequestById],
() => ky.get(`requests-mediated/mediated-requests/${mediatedRequestId}`).json(),
{ enabled: Boolean(mediatedRequestId) },
);

return {
isFetching,
mediatedRequest: data,
shouldUpdateMediatedRequestById,
setShouldUpdateMediatedRequestById,
};
};

Expand Down
28 changes: 27 additions & 1 deletion src/routes/MediatedRequestsActivitiesContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,21 @@ export const buildQuery = (queryParams, pathComponents, resourceData, logger, pr
return getCql(queryParams, pathComponents, resourceData, logger, props);
};

export const updateMediatedRequestList = (source, props) => {
const {
location,
history,
} = props;
const {
resources: {
query,
},
} = source;
const url = buildUrl(location, query);

history.push(url);
};

class MediatedRequestsActivitiesContainer extends React.Component {
static manifest = Object.freeze({
query: {
Expand All @@ -62,6 +77,7 @@ class MediatedRequestsActivitiesContainer extends React.Component {
query: buildQuery,
},
},
resourceShouldRefresh: true,
throwErrors: false,
},
reportRecords: {
Expand Down Expand Up @@ -161,6 +177,10 @@ class MediatedRequestsActivitiesContainer extends React.Component {
}
};

updateMediatedRequestList = () => {
updateMediatedRequestList(this.source, this.props);
};

render() {
if (this.source) {
this.source.update(this.props, MEDIATED_REQUESTS_RECORDS_NAME);
Expand All @@ -176,7 +196,13 @@ class MediatedRequestsActivitiesContainer extends React.Component {
mutator={this.props.mutator}
settings={this.props.settings}
>
{this.props.children}
{
React.Children.map(
this.props.children, child => React.cloneElement(child, {
updateMediatedRequestList: this.updateMediatedRequestList,
})
)
}
</MediatedRequestsActivities>
);
}
Expand Down
Loading

0 comments on commit 85ac249

Please sign in to comment.