Skip to content

Commit

Permalink
OM-320: add bulk delete of workers
Browse files Browse the repository at this point in the history
  • Loading branch information
olewandowski1 committed Oct 9, 2024
1 parent 13359e0 commit 7da0817
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 4 deletions.
26 changes: 24 additions & 2 deletions src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -284,10 +284,10 @@ export function clearWorkerVoucherExport() {
};
}

export function fetchWorkers(modulesManager, params) {
export function fetchWorkers(modulesManager, params, actionType = ACTION_TYPE.GET_WORKERS) {
const queryParams = [...params];
const payload = formatPageQueryWithCount('worker', queryParams, WORKER_PROJECTION(modulesManager));
return graphql(payload, ACTION_TYPE.GET_WORKERS);
return graphql(payload, actionType);
}

export function fetchWorker(modulesManager, params) {
Expand Down Expand Up @@ -497,6 +497,28 @@ export function deleteWorkerFromEconomicUnit(economicUnit, workerToDelete, clien
);
}

export function deleteWorkersFromEconomicUnit(economicUnit, workersToDelete, clientMutationLabel) {
const workersUuids = workersToDelete.map((worker) => worker.uuid);
const mutationInput = `
${economicUnit.code ? `economicUnitCode: "${economicUnit.code}"` : ''}
${workersUuids?.length ? `uuids: [${workersUuids.map((uuid) => `"${uuid}"`).join(', ')}]` : ''}
`;

const mutation = formatMutation('deleteWorker', mutationInput, clientMutationLabel);
const requestedDateTime = new Date();

return graphql(
mutation.payload,
[REQUEST(ACTION_TYPE.MUTATION), SUCCESS(ACTION_TYPE.DELETE_WORKERS), ERROR(ACTION_TYPE.MUTATION)],
{
actionType: ACTION_TYPE.DELETE_WORKERS,
clientMutationId: mutation.clientMutationId,
clientMutationLabel,
requestedDateTime,
},
);
}

export function validateMConnectWorker(nationalId, economicUnitCode) {
return graphqlWithVariables(
`
Expand Down
18 changes: 18 additions & 0 deletions src/components/WorkerSearcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,17 @@ import {
ADMIN_RIGHT,
DEFAULT_PAGE_SIZE,
EMPTY_OBJECT,
EMPTY_STRING,
INSPECTOR_RIGHT,
MODULE_NAME,
RIGHT_WORKER_DELETE,
RIGHT_WORKER_SEARCH,
ROWS_PER_PAGE_OPTIONS,
} from '../constants';
import WorkerFilter from './WorkerFilter';
import { ACTION_TYPE } from '../reducer';

const WORKER_SEARCHER_ACTION_CONTRIBUTION_KEY = 'workerVoucher.WorkerSearcherAction.select';

function WorkerSearcher({ downloadWorkers, fetchWorkers: fetchWorkersAction, clearWorkersExport }) {
const history = useHistory();
Expand All @@ -56,6 +60,9 @@ function WorkerSearcher({ downloadWorkers, fetchWorkers: fetchWorkersAction, cle
} = useSelector((state) => state.workerVoucher);
const { economicUnit } = useSelector((state) => state.policyHolder);
const isAdminOrInspector = rights.includes(INSPECTOR_RIGHT) || rights.includes(ADMIN_RIGHT);
const isAuthorized = rights.includes(RIGHT_WORKER_DELETE)
&& (rights.includes(ADMIN_RIGHT)
|| !rights.includes(INSPECTOR_RIGHT));

const { formatMessage, formatMessageWithValues } = useTranslations(MODULE_NAME, modulesManager);

Expand Down Expand Up @@ -95,6 +102,12 @@ function WorkerSearcher({ downloadWorkers, fetchWorkers: fetchWorkersAction, cle
[economicUnit],
);

const fetchAllAvailableWorkers = () => fetchWorkersAction(
modulesManager,
[`economicUnitCode:"${economicUnit.code}"`],
ACTION_TYPE.REQUEST,
);

const headers = () => [
'workerVoucher.worker.chfId',
'workerVoucher.worker.lastName',
Expand Down Expand Up @@ -230,6 +243,11 @@ function WorkerSearcher({ downloadWorkers, fetchWorkers: fetchWorkersAction, cle
return (
<>
<Searcher
withSelection={isAuthorized ? 'multiple' : false}
selectWithCheckbox={!!isAuthorized}
actionsContributionKey={isAuthorized ? WORKER_SEARCHER_ACTION_CONTRIBUTION_KEY : EMPTY_STRING}
selectionMessage="workerVoucher.WorkerSearcher.selection"
getAllItems={fetchAllAvailableWorkers}
module="workerVoucher"
FilterPane={workerFilters}
fetch={fetchWorkers}
Expand Down
93 changes: 93 additions & 0 deletions src/components/WorkerSearcherSelectActions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React, { useEffect, useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';

import { MenuItem, Tooltip } from '@material-ui/core';
import { makeStyles } from '@material-ui/styles';

import { SelectDialog, journalize, useTranslations } from '@openimis/fe-core';
import { deleteWorkersFromEconomicUnit } from '../actions';
import { MODULE_NAME } from '../constants';

const useStyles = makeStyles(() => ({
uppercase: {
textTransform: 'uppercase',
},
}));

function WorkerSearcherSelectActions({
selection: selectedWorkers,
refetch: refetchWorkers,
clearSelected,
withSelection,
}) {
const prevSubmittingMutationRef = useRef();
const prevEconomicUnitRef = useRef();
const [isBulkDeleteDialogOpen, setBulkDeleteDialogOpen] = useState(false);
const { economicUnit } = useSelector((state) => state.policyHolder);
const { mutation, submittingMutation } = useSelector((state) => state.workerVoucher);
const dispatch = useDispatch();
const classes = useStyles();
const { formatMessage } = useTranslations(MODULE_NAME);
const isWorkerSelected = !!selectedWorkers.length;

const onBulkDeleteConfirm = async () => {
try {
await dispatch(deleteWorkersFromEconomicUnit(economicUnit, selectedWorkers, 'Bulk Delete Workers'));
refetchWorkers();
} catch (error) {
// eslint-disable-next-line no-console
console.log('[WORKER_SEARCHER_SELECT_ACTIONS]: Bulk delete failed.', error);
} finally {
setBulkDeleteDialogOpen(false);
}
};

const onBulkDeleteClose = () => setBulkDeleteDialogOpen(false);

useEffect(() => {
if (prevEconomicUnitRef.current !== undefined && prevEconomicUnitRef.current !== economicUnit) {
if (selectedWorkers.length) {
clearSelected();
}
}

prevEconomicUnitRef.current = economicUnit;
}, [economicUnit, selectedWorkers, clearSelected]);

useEffect(() => {
if (prevSubmittingMutationRef.current && !submittingMutation) {
dispatch(journalize(mutation));
}
}, [submittingMutation]);

useEffect(() => {
prevSubmittingMutationRef.current = submittingMutation;
});

if (!withSelection) {
return null;
}

return (
<>
<Tooltip title={formatMessage('workerVoucher.tooltip.bulkDelete')}>
<MenuItem onClick={setBulkDeleteDialogOpen} disabled={!isWorkerSelected}>
<span className={classes.uppercase}>{formatMessage('workerVoucher.WorkerSearcherSelectActions.delete')}</span>
</MenuItem>
</Tooltip>
<SelectDialog
module={MODULE_NAME}
confirmState={isBulkDeleteDialogOpen}
onConfirm={onBulkDeleteConfirm}
onClose={onBulkDeleteClose}
confirmTitle="workerVoucher.WorkerSearcherSelectActions.dialog.title"
confirmMessageWithValues="workerVoucher.WorkerSearcherSelectActions.dialog.message"
translationVariables={{ count: selectedWorkers.length }}
confirmationButton="workerVoucher.WorkerSearcherSelectActions.dialog.confirm"
rejectionButton="workerVoucher.WorkerSearcherSelectActions.dialog.abandon"
/>
</>
);
}

export default WorkerSearcherSelectActions;
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import MobileAppPasswordManagement from './pages/MobileAppPasswordManagement';
import BillVoucherHeadPanel from './components/BillVoucherHeadPanel';
import WorkersPage from './pages/WorkersPage';
import WorkerDetailsPage from './pages/WorkerDetailsPage';
import WorkerSearcherSelectActions from './components/WorkerSearcherSelectActions';

const ROUTE_WORKER_VOUCHERS_LIST = 'voucher/vouchers';
const ROUTE_WORKER_VOUCHER = 'voucher/vouchers/voucher';
Expand Down Expand Up @@ -148,6 +149,7 @@ const DEFAULT_CONFIG = {
},
],
'workerVoucher.VoucherHeadPanel': [BillVoucherHeadPanel],
'workerVoucher.WorkerSearcherAction.select': WorkerSearcherSelectActions,
};

export const WorkerVoucherModule = (cfg) => ({ ...DEFAULT_CONFIG, ...cfg });
6 changes: 5 additions & 1 deletion src/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {

export const ACTION_TYPE = {
MUTATION: 'WORKER_VOUCHER_MUTATION',
REQUEST: 'WORKER_VOUCHER_REQUEST',
ACQUIRE_GENERIC_VOUCHER: 'WORKER_VOUCHER_ACQUIRE_GENERIC_VOUCHER',
ACQUIRE_SPECIFIC_VOUCHER: 'WORKER_VOUCHER_ACQUIRE_SPECIFIC_VOUCHER',
ASSIGN_VOUCHERS: 'WORKER_VOUCHER_ASSIGN_VOUCHERS',
Expand All @@ -30,7 +31,8 @@ export const ACTION_TYPE = {
GET_WORKER: 'WORKER_VOUCHER_GET_WORKER',
WORKERS_EXPORT: 'WORKER_VOUCHER_WORKERS_EXPORT',
VOUCHER_COUNT: 'WORKER_VOUCHER_VOUCHER_COUNT',
DELETE_WORKER: 'WORKER_VOUCHER_DELETE_WORKER'
DELETE_WORKER: 'WORKER_VOUCHER_DELETE_WORKER',
DELETE_WORKERS: 'WORKER_VOUCHER_DELETE_WORKERS',
};

const STORE_STATE = {
Expand Down Expand Up @@ -314,6 +316,8 @@ function reducer(state = STORE_STATE, action) {
return dispatchMutationResp(state, 'createWorker', action);
case SUCCESS(ACTION_TYPE.DELETE_WORKER):
return dispatchMutationResp(state, 'deleteWorker', action);
case SUCCESS(ACTION_TYPE.DELETE_WORKERS):
return dispatchMutationResp(state, 'deleteWorker', action);
case SUCCESS(ACTION_TYPE.MANAGE_VOUCHER_PRICE):
return dispatchMutationResp(state, 'createBusinessConfig', action);
case SUCCESS(ACTION_TYPE.DELETE_VOUCHER_PRICE):
Expand Down
9 changes: 8 additions & 1 deletion src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"workerVoucher.createdDate": "Created Date",
"workerVoucher.tooltip.details": "View details",
"workerVoucher.tooltip.delete": "Delete Worker",
"workerVoucher.tooltip.bulkDelete": "Delete Worker(s)",
"workerVoucher.voucherPrice.delete": "Delete",
"workerVoucher.placeholder.any": "Any",
"workerVoucher.status.AWAITING_PAYMENT": "AWAITING PAYMENT",
Expand Down Expand Up @@ -138,5 +139,11 @@
"workerVoucher.WorkerMConnectAddForm.search": "Search",
"workerVoucher.WorkerMConnectAddForm.notFound": "Worker not found. Ensure that the National ID is correct and try again.",
"workerVoucher.WorkerMConnectAddForm.tip": "As an Employer, you can add a worker to the system by searching for the worker's National ID. Once the worker is found, you can save the form and add the worker to your list of workers.",
"workerVoucher.WorkerMConnectAddForm.detail": "Type the worker's National ID and get the worker's details. Ensure that the National ID is correct."
"workerVoucher.WorkerMConnectAddForm.detail": "Type the worker's National ID and get the worker's details. Ensure that the National ID is correct.",
"workerVoucher.WorkerSearcher.selection": "Selected {count} workers",
"workerVoucher.WorkerSearcherSelectActions.delete": "Delete Selected Workers",
"workerVoucher.WorkerSearcherSelectActions.dialog.title": "Are you sure you want to proceed?",
"workerVoucher.WorkerSearcherSelectActions.dialog.message": "You are about to delete the selected workers ({count}). This action cannot be undone. Please confirm if you wish to proceed with this action.",
"workerVoucher.WorkerSearcherSelectActions.dialog.confirm": "Delete",
"workerVoucher.WorkerSearcherSelectActions.dialog.abandon": "Cancel"
}

0 comments on commit 7da0817

Please sign in to comment.