Skip to content

Commit 49de9ad

Browse files
committed
feature: allow program to be restored after deletion
1 parent f4b2f3a commit 49de9ad

5 files changed

Lines changed: 121 additions & 13 deletions

File tree

src/actions.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,22 @@ export function deleteBenefitPlan(benefitPlan, clientMutationLabel) {
292292
);
293293
}
294294

295+
export function undoDeleteBenefitPlan(benefitPlan, clientMutationLabel) {
296+
const benefitPlanUuids = `ids: ["${benefitPlan?.id}"]`;
297+
const mutation = formatMutation('undoDeleteBenefitPlan', benefitPlanUuids, clientMutationLabel);
298+
const requestedDateTime = new Date();
299+
return graphql(
300+
mutation.payload,
301+
[REQUEST(ACTION_TYPE.MUTATION), SUCCESS(ACTION_TYPE.UNDO_DELETE_BENEFIT_PLAN), ERROR(ACTION_TYPE.MUTATION)],
302+
{
303+
actionType: ACTION_TYPE.UNDO_DELETE_BENEFIT_PLAN,
304+
clientMutationId: mutation.clientMutationId,
305+
clientMutationLabel,
306+
requestedDateTime,
307+
},
308+
);
309+
}
310+
295311
export function closeBenefitPlan(benefitPlan, clientMutationLabel) {
296312
const benefitPlanUuids = `ids: ["${benefitPlan?.id}"]`;
297313
const mutation = formatMutation('closeBenefitPlan', benefitPlanUuids, clientMutationLabel);

src/components/BenefitPlanSearcher.js

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@ import { connect } from 'react-redux';
1717
import { IconButton, Tooltip } from '@material-ui/core';
1818
import EditIcon from '@material-ui/icons/Edit';
1919
import DeleteIcon from '@material-ui/icons/Delete';
20+
import UndoIcon from '@material-ui/icons/Undo';
2021
import {
2122
DEFAULT_PAGE_SIZE,
2223
RIGHT_BENEFIT_PLAN_DELETE,
2324
RIGHT_BENEFIT_PLAN_UPDATE,
2425
ROWS_PER_PAGE_OPTIONS,
2526
} from '../constants';
26-
import { deleteBenefitPlan, fetchBenefitPlans } from '../actions';
27+
import { deleteBenefitPlan, undoDeleteBenefitPlan, fetchBenefitPlans } from '../actions';
2728
import BenefitPlanFilter from './BenefitPlanFilter';
2829

2930
function BenefitPlanSearcher({
@@ -39,6 +40,7 @@ function BenefitPlanSearcher({
3940
mutation,
4041
fetchBenefitPlans,
4142
deleteBenefitPlan,
43+
undoDeleteBenefitPlan,
4244
fetchingBenefitPlans,
4345
errorBenefitPlans,
4446
benefitPlans,
@@ -49,7 +51,10 @@ function BenefitPlanSearcher({
4951
beneficiaryStatus,
5052
}) {
5153
const [benefitPlanToDelete, setBenefitPlanToDelete] = useState(null);
54+
const [benefitPlanToUndo, setBenefitPlanToUndo] = useState(null);
5255
const [deletedBenefitPlanUuids, setDeletedBenefitPlanUuids] = useState([]);
56+
const [undoBenefitPlanUuids, setUndoBenefitPlanUuids] = useState([]);
57+
const [activeFilters, setActiveFilters] = useState([]);
5358
const prevSubmittingMutationRef = useRef();
5459

5560
const openDeleteBenefitPlanConfirmDialog = () => coreConfirm(
@@ -60,7 +65,16 @@ function BenefitPlanSearcher({
6065
formatMessage(intl, 'socialProtection', 'benefitPlan.delete.confirm.message'),
6166
);
6267

68+
const openUndoBenefitPlanConfirmDialog = () => coreConfirm(
69+
formatMessageWithValues(intl, 'socialProtection', 'benefitPlan.undo.confirm.title', {
70+
code: benefitPlanToUndo.code,
71+
name: benefitPlanToUndo.name,
72+
}),
73+
formatMessage(intl, 'socialProtection', 'benefitPlan.undo.confirm.message'),
74+
);
75+
6376
useEffect(() => benefitPlanToDelete && openDeleteBenefitPlanConfirmDialog(), [benefitPlanToDelete]);
77+
useEffect(() => benefitPlanToUndo && openUndoBenefitPlanConfirmDialog(), [benefitPlanToUndo]);
6478

6579
useEffect(() => {
6680
if (benefitPlanToDelete && confirmed) {
@@ -72,9 +86,21 @@ function BenefitPlanSearcher({
7286
);
7387
setDeletedBenefitPlanUuids([...deletedBenefitPlanUuids, benefitPlanToDelete.id]);
7488
}
89+
if (benefitPlanToUndo && confirmed) {
90+
undoDeleteBenefitPlan(
91+
benefitPlanToUndo,
92+
formatMessageWithValues(intl, 'socialProtection', 'benefitPlan.undo.mutationLabel', {
93+
name: benefitPlanToUndo?.name,
94+
}),
95+
);
96+
setUndoBenefitPlanUuids([...undoBenefitPlanUuids, benefitPlanToUndo.id]);
97+
}
7598
if (benefitPlanToDelete && confirmed !== null) {
7699
setBenefitPlanToDelete(null);
77100
}
101+
if (benefitPlanToUndo && confirmed !== null) {
102+
setBenefitPlanToUndo(null);
103+
}
78104
return () => confirmed && clearConfirm(false);
79105
}, [confirmed]);
80106

@@ -102,6 +128,9 @@ function BenefitPlanSearcher({
102128
if (rights.includes(RIGHT_BENEFIT_PLAN_UPDATE)) {
103129
headers.push('emptyLabel');
104130
}
131+
if (rights.includes(RIGHT_BENEFIT_PLAN_DELETE)) {
132+
headers.push('emptyLabel');
133+
}
105134
return headers;
106135
};
107136

@@ -115,6 +144,7 @@ function BenefitPlanSearcher({
115144
&& historyPush(modulesManager, history, 'socialProtection.route.benefitPlan', [benefitPlan?.id], newTab);
116145

117146
const onDelete = (benefitPlan) => setBenefitPlanToDelete(benefitPlan);
147+
const onUndo = (benefitPlan) => setBenefitPlanToUndo(benefitPlan);
118148

119149
const itemFormatters = () => {
120150
const formatters = [
@@ -139,16 +169,25 @@ function BenefitPlanSearcher({
139169
));
140170
}
141171
if (rights.includes(RIGHT_BENEFIT_PLAN_DELETE)) {
142-
formatters.push((benefitPlan) => (
143-
<Tooltip title={formatMessage(intl, 'benefitPlan', 'deleteButtonTooltip')}>
172+
formatters.push((benefitPlan) => (!benefitPlan?.isDeleted ? (
173+
<Tooltip title={formatMessage(intl, 'socialProtection', 'deleteButtonTooltip')}>
144174
<IconButton
145175
onClick={() => onDelete(benefitPlan)}
146176
disabled={deletedBenefitPlanUuids.includes(benefitPlan.id)}
147177
>
148178
<DeleteIcon />
149179
</IconButton>
150180
</Tooltip>
151-
));
181+
) : (
182+
<Tooltip title={formatMessage(intl, 'socialProtection', 'undoButtonTooltip')}>
183+
<IconButton
184+
onClick={() => onUndo(benefitPlan)}
185+
disabled={undoBenefitPlanUuids.includes(benefitPlan.id)}
186+
>
187+
<UndoIcon />
188+
</IconButton>
189+
</Tooltip>
190+
)));
152191
}
153192
return formatters;
154193
};
@@ -164,7 +203,8 @@ function BenefitPlanSearcher({
164203
['maxBeneficiaries', true],
165204
];
166205

167-
const isRowDisabled = (_, benefitPlan) => deletedBenefitPlanUuids.includes(benefitPlan.id);
206+
const isRowDisabled = (_, benefitPlan) => deletedBenefitPlanUuids.includes(benefitPlan.id)
207+
|| undoBenefitPlanUuids.includes(benefitPlan.id);
168208

169209
const defaultFilters = () => ({
170210
isDeleted: {
@@ -201,12 +241,23 @@ function BenefitPlanSearcher({
201241
/>
202242
);
203243

244+
const onFiltersApplied = (appliedFilters) => {
245+
setActiveFilters(appliedFilters);
246+
setDeletedBenefitPlanUuids([]);
247+
setUndoBenefitPlanUuids([]);
248+
};
249+
250+
const isDeletedFilterActive = !!activeFilters?.isDeleted?.value;
251+
const items = benefitPlans.filter((bp) => (
252+
isDeletedFilterActive ? !undoBenefitPlanUuids.includes(bp.id) : !deletedBenefitPlanUuids.includes(bp.id)
253+
));
254+
204255
return (
205256
<Searcher
206257
module="socialProtection"
207258
FilterPane={benefitPlanFilter}
208259
fetch={fetch}
209-
items={benefitPlans}
260+
items={items}
210261
itemsPageInfo={benefitPlansPageInfo}
211262
fetchedItems={fetchingBenefitPlans}
212263
errorItems={errorBenefitPlans}
@@ -224,6 +275,7 @@ function BenefitPlanSearcher({
224275
defaultFilters={defaultFilters()}
225276
rowDisabled={isRowDisabled}
226277
rowLocked={isRowDisabled}
278+
onFiltersApplied={onFiltersApplied}
227279
/>
228280
);
229281
}
@@ -243,6 +295,7 @@ const mapDispatchToProps = (dispatch) => bindActionCreators(
243295
{
244296
fetchBenefitPlans,
245297
deleteBenefitPlan,
298+
undoDeleteBenefitPlan,
246299
coreConfirm,
247300
clearConfirm,
248301
journalize,

src/pages/BenefitPlanPage.js

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ import _ from 'lodash';
1616
import { withTheme, withStyles } from '@material-ui/core/styles';
1717
import DeleteIcon from '@material-ui/icons/Delete';
1818
import PauseIcon from '@material-ui/icons/Pause';
19+
import UndoIcon from '@material-ui/icons/Undo';
1920
import {
2021
BENEFIT_PLAN_BENEFICIARIES_LIST_TAB_VALUE,
2122
RIGHT_BENEFICIARY_SEARCH,
2223
RIGHT_BENEFIT_PLAN_UPDATE,
2324
} from '../constants';
2425
import {
2526
fetchBenefitPlan, deleteBenefitPlan, closeBenefitPlan, updateBenefitPlan, clearBenefitPlan, createBenefitPlan,
27+
undoDeleteBenefitPlan,
2628
} from '../actions';
2729
import BenefitPlanHeadPanel from '../components/BenefitPlanHeadPanel';
2830
import BenefitPlanTabPanel from '../components/BenefitPlanTabPanel';
@@ -42,6 +44,7 @@ function BenefitPlanPage({
4244
benefitPlan,
4345
fetchBenefitPlan,
4446
deleteBenefitPlan,
47+
undoDeleteBenefitPlan,
4548
closeBenefitPlan,
4649
updateBenefitPlan,
4750
coreConfirm,
@@ -78,7 +81,10 @@ function BenefitPlanPage({
7881
useEffect(() => {
7982
if (prevSubmittingMutationRef.current && !submittingMutation) {
8083
journalize(mutation);
81-
if (mutation?.actionType === ACTION_TYPE.DELETE_BENEFIT_PLAN) {
84+
if ([
85+
ACTION_TYPE.DELETE_BENEFIT_PLAN,
86+
ACTION_TYPE.UNDO_DELETE_BENEFIT_PLAN,
87+
].includes(mutation?.actionType)) {
8288
back();
8389
}
8490
}
@@ -181,6 +187,24 @@ function BenefitPlanPage({
181187
);
182188
};
183189

190+
const undoDeleteBenefitPlanCallback = () => undoDeleteBenefitPlan(
191+
benefitPlan,
192+
formatMessageWithValues(intl, 'socialProtection', 'benefitPlan.undo.mutationLabel', {
193+
name: benefitPlan?.name,
194+
}),
195+
);
196+
197+
const openUndoBenefitPlanConfirmDialog = () => {
198+
setConfirmedAction(() => undoDeleteBenefitPlanCallback);
199+
coreConfirm(
200+
formatMessageWithValues(intl, 'socialProtection', 'benefitPlan.undo.confirm.title', {
201+
code: benefitPlan?.code,
202+
name: benefitPlan?.name,
203+
}),
204+
formatMessage(intl, 'socialProtection', 'benefitPlan.undo.confirm.message'),
205+
);
206+
};
207+
184208
const [childActiveTab, setChildActiveTab] = useState(BENEFIT_PLAN_BENEFICIARIES_LIST_TAB_VALUE);
185209

186210
const getBenefitPlanPanels = () => {
@@ -192,11 +216,17 @@ function BenefitPlanPage({
192216
};
193217

194218
const actions = [
195-
!!benefitPlan && {
196-
doIt: openDeleteBenefitPlanConfirmDialog,
197-
icon: <DeleteIcon />,
198-
tooltip: formatMessage(intl, 'socialProtection', 'deleteButtonTooltip'),
199-
}, !!benefitPlan && {
219+
!!benefitPlan && (
220+
benefitPlan.isDeleted ? {
221+
doIt: openUndoBenefitPlanConfirmDialog,
222+
icon: <UndoIcon />,
223+
tooltip: formatMessage(intl, 'socialProtection', 'undoButtonTooltip'),
224+
} : {
225+
doIt: openDeleteBenefitPlanConfirmDialog,
226+
icon: <DeleteIcon />,
227+
tooltip: formatMessage(intl, 'socialProtection', 'deleteButtonTooltip'),
228+
}),
229+
!!benefitPlan && !benefitPlan.isDeleted && {
200230
doIt: openStopBenefitPlanConfirmDialog,
201231
icon: <PauseIcon />,
202232
tooltip: formatMessage(intl, 'socialProtection', 'stopButtonTooltip'),
@@ -227,7 +257,7 @@ function BenefitPlanPage({
227257
rights={rights}
228258
actions={actions}
229259
setConfirmedAction={setConfirmedAction}
230-
readOnly={!!benefitPlanUuid}
260+
readOnly={!!benefitPlanUuid || editedBenefitPlan?.isDeleted}
231261
saveTooltip={formatMessage(
232262
intl,
233263
'socialProtection',
@@ -259,6 +289,7 @@ const mapDispatchToProps = (dispatch) => bindActionCreators({
259289
fetchBenefitPlan,
260290
clearBenefitPlan,
261291
deleteBenefitPlan,
292+
undoDeleteBenefitPlan,
262293
closeBenefitPlan,
263294
updateBenefitPlan,
264295
coreConfirm,

src/reducer.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export const ACTION_TYPE = {
2222
GET_BENEFIT_PLAN: 'BENEFIT_PLAN_BENEFIT_PLAN',
2323
CREATE_BENEFIT_PLAN: 'BENEFIT_PLAN_CREATE_BENEFIT_PLAN',
2424
DELETE_BENEFIT_PLAN: 'BENEFIT_PLAN_DELETE_BENEFIT_PLAN',
25+
UNDO_DELETE_BENEFIT_PLAN: 'BENEFIT_PLAN_UNDO_DELETE_BENEFIT_PLAN',
2526
CLOSE_BENEFIT_PLAN: 'BENEFIT_PLAN_CLOSE_BENEFIT_PLAN',
2627
UPDATE_BENEFIT_PLAN: 'BENEFIT_PLAN_UPDATE_BENEFIT_PLAN',
2728
BENEFIT_PLAN_CODE_FIELDS_VALIDATION: 'BENEFIT_PLAN_CODE_FIELDS_VALIDATION',
@@ -1000,6 +1001,8 @@ function reducer(
10001001
return dispatchMutationResp(state, 'createBenefitPlan', action);
10011002
case SUCCESS(ACTION_TYPE.DELETE_BENEFIT_PLAN):
10021003
return dispatchMutationResp(state, 'deleteBenefitPlan', action);
1004+
case SUCCESS(ACTION_TYPE.UNDO_DELETE_BENEFIT_PLAN):
1005+
return dispatchMutationResp(state, 'undoDeleteBenefitPlan', action);
10031006
case SUCCESS(ACTION_TYPE.UPDATE_BENEFIT_PLAN):
10041007
return dispatchMutationResp(state, 'updateBenefitPlan', action);
10051008
case SUCCESS(ACTION_TYPE.UPDATE_BENEFICIARY):

src/translations/en.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
"socialProtection.benefitPlan.delete.confirm.title": "Delete program {code} {name}",
44
"socialProtection.benefitPlan.delete.confirm.message": "Are you sure you want to delete the program?",
55
"socialProtection.benefitPlan.delete.mutationLabel": "Delete program {id}",
6+
"socialProtection.benefitPlan.undo.confirm.title": "Restore program {code} {name}?",
7+
"socialProtection.benefitPlan.undo.confirm.message": "This will undo the deletion and make the program active again. Do you want to continue?",
8+
"socialProtection.benefitPlan.undo.mutationLabel": "Restore program {name}",
69
"socialProtection.benefitPlan.update.mutationLabel": "Update program {id}",
710
"socialProtection.benefitPlan.create.mutationLabel": "Create program {id}",
811
"socialProtection.benefitPlan.searcherResultsTitle": "{benefitPlansTotalCount} Programs",
@@ -108,7 +111,9 @@
108111
"socialProtection.benefitPlan.suspend.confirm.title": "Suspend program {code} {name}",
109112
"socialProtection.benefitPlan.suspend.confirm.message": "Are you sure you want to suspend the program?",
110113
"socialProtection.benefitPlan.stopButtonTooltip": "Suspend",
114+
"socialProtection.deleteButtonTooltip": "Delete",
111115
"socialProtection.stopButtonTooltip": "Suspend",
116+
"socialProtection.undoButtonTooltip": "Restore",
112117
"socialProtection.benefitPackage.benefitPackageBenefitsTab.label": "Benefits",
113118
"socialProtection.benefitPlan.benefitPlanBeneficiaries.uploadHistoryTable.user": "User Uploaded",
114119
"socialProtection.resolveAllRemainingTasks": "Bulk Task Resolve",

0 commit comments

Comments
 (0)