Skip to content

Commit b66d188

Browse files
Merge pull request #359 from ajit3190/develop_verify_for_mrm
Develop verify for mrm
2 parents 0d4952b + d5eda3b commit b66d188

File tree

14 files changed

+275
-14
lines changed

14 files changed

+275
-14
lines changed

app/javascript/components/permissions/constants.js

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ export const ACTIONS = {
111111
SERVICES_SECTION_FROM_CASE: "services_section_from_case",
112112
SYNC_EXTERNAL: "sync_external",
113113
TRANSFER: "transfer",
114+
VERIFY_MRM: "verify_mrm",
114115
VIEW_INCIDENT_FROM_CASE: "view_incident_from_case",
115116
VIEW_REGISTRY_RECORD: "view_registry_record",
116117
VIOLATIONS: "violations",

app/javascript/components/permissions/constants.unit.test.js

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ describe("Verifying config constant", () => {
119119
"WORKFLOW_REPORT",
120120
"SYNC_EXTERNAL",
121121
"TRANSFER",
122+
"VERIFY_MRM",
122123
"VIEW_FAMILY_RECORD",
123124
"VIEW_INCIDENT_FROM_CASE",
124125
"VIEW_REGISTRY_RECORD",

app/javascript/components/record-actions/constants.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,6 @@ export const RECORD_ACTION_ABILITIES = {
6363
canRequestGbvClosure: [ACTIONS.MANAGE, ACTIONS.REQUEST_APPROVAL_GBV_CLOSURE],
6464
canShowExports: SHOW_EXPORTS,
6565
canTransfer: [ACTIONS.MANAGE, ACTIONS.TRANSFER],
66-
canMarkForOffline: [ACTIONS.MANAGE, ACTIONS.MARK_FOR_OFFLINE]
66+
canMarkForOffline: [ACTIONS.MANAGE, ACTIONS.MARK_FOR_OFFLINE],
67+
canVerify: [ACTIONS.MANAGE,ACTIONS.VERIFY_MRM]
6768
};

app/javascript/components/record-actions/constants.unit.test.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ describe("<RecordActions /> - Constants", () => {
6969
"canRequestGbvClosure",
7070
"canShowExports",
7171
"canTransfer",
72-
"canMarkForOffline"
72+
"canMarkForOffline",
73+
"canVerify"
7374
].forEach(property => {
7475
expect(recordActionAbilities).to.have.property(property);
7576
delete recordActionAbilities[property];

app/javascript/components/record-form/form/subforms/styles.css

+16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
/* Copyright (c) 2014 - 2023 UNICEF. All rights reserved. */
22

3+
.verifiedSpan{
4+
color: var(--c-white);
5+
height: 25px;
6+
font-size: var(--fs-13);
7+
font-weight: 600;
8+
float: right;
9+
top: 12px;
10+
position: absolute;
11+
left: 79%;
12+
width: 115px;
13+
}
314
.secondarySubformHeader {
415
font-size: var(--fs-12);
516
color: var(--c-dark-grey);
@@ -196,3 +207,8 @@
196207
padding-top: 0px;
197208
}
198209
}
210+
211+
.keyboardDatePickerWrapper {
212+
display: flex;
213+
justify-content: space-between;
214+
}

app/javascript/components/record-form/form/subforms/subform-fields/component.jsx

+1
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ const Component = ({
178178
renderSecondaryText={Boolean(entryFilter)}
179179
associatedViolations={associatedViolations}
180180
parentTitle={parentTitle}
181+
mode={mode}
181182
/>
182183
<ListItemSecondaryAction classes={{ root: css.listActions }}>
183184
{isTracesSubform && <TracingRequestStatus values={values[index]} />}

app/javascript/components/record-form/form/subforms/subform-fields/components/violation-item/component.jsx

+140-5
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,128 @@
1-
// Copyright (c) 2014 - 2023 UNICEF. All rights reserved.
2-
1+
import { useEffect, useState } from "react";
2+
import { useDispatch } from "react-redux";
33
import PropTypes from "prop-types";
4-
import { ListItemText } from "@material-ui/core";
4+
import { ListItemText, Button } from "@material-ui/core";
5+
import { useParams } from "react-router-dom";
6+
import { KeyboardDatePicker, MuiPickersUtilsProvider } from "@material-ui/pickers";
7+
import DateFnsUtils from "@date-io/date-fns";
58

9+
import ActionDialog from "../../../../../../action-dialog";
610
import ViolationTitle from "../violation-title";
711
import css from "../../../styles.css";
12+
import { saveRecord } from "../../../../../../records";
13+
import { usePermissions } from "../../../../../../permissions";
14+
import { RECORD_ACTION_ABILITIES } from "../../../../../../record-actions/constants";
15+
import { useI18n } from "../../../../../../i18n";
16+
import { toServerDateFormat } from "../../../../../../../libs";
817

9-
import { NAME } from "./constants";
18+
import VerifySelect from "./select";
1019
import { getViolationTallyLabel } from "./utils";
20+
import { NAME } from "./constants";
1121

12-
const Component = ({ fields, values, locale, displayName, index, collapsedFieldValues }) => {
22+
const Component = ({ fields, values, locale, displayName, index, collapsedFieldValues, mode }) => {
1323
const currentValues = values[index];
24+
const verifyParams = useParams();
25+
const i18n = useI18n();
26+
const DATE_FORMAT = "dd-MMM-yyyy";
27+
28+
// State variables
29+
const dispatch = useDispatch();
30+
const [verifyModal, setVerifyModal] = useState(false);
31+
const [verificationValue, setVerificationValue] = useState(currentValues?.ctfmr_verified || "");
32+
const [selectedDate, setSelectedDate] = useState(new Date());
33+
const [validationError, setValidationError] = useState("");
34+
const maxDate = new Date();
35+
36+
useEffect(() => {
37+
// Changing dropdown select value when backend data updated
38+
setVerificationValue(currentValues?.ctfmr_verified);
39+
}, [currentValues?.ctfmr_verified]);
40+
41+
const handleDropdownDate = date => {
42+
if (selectedDate) {
43+
setSelectedDate(date);
44+
} else {
45+
setValidationError("date should not be null");
46+
setSelectedDate(null);
47+
}
48+
};
49+
50+
const handleOpenVerifyModal = (idx, event) => {
51+
// To open verify dialog confirmation popup
52+
event.stopPropagation();
53+
setVerifyModal(true);
54+
};
55+
56+
const cancelVerifyHandler = () => {
57+
// To close verify dialog popup
58+
setVerifyModal(false);
59+
};
1460

61+
const { canVerify } = usePermissions("incidents", RECORD_ACTION_ABILITIES); // check permission to verify violations
1562
const violationTally = getViolationTallyLabel(fields, currentValues, locale);
1663

64+
const handleOk = () => {
65+
// To update the verify status to Verified
66+
67+
dispatch(
68+
saveRecord(
69+
verifyParams.recordType,
70+
"update",
71+
{
72+
data: {
73+
[currentValues.type]: [
74+
{
75+
unique_id: currentValues.unique_id,
76+
ctfmr_verified: verificationValue,
77+
ctfmr_verified_date: toServerDateFormat(selectedDate)
78+
}
79+
]
80+
}
81+
}, // Save API Call
82+
verifyParams.id,
83+
"Updated successfully",
84+
"",
85+
false,
86+
false
87+
)
88+
);
89+
// close();
90+
};
91+
92+
// Define VerifySelect component
93+
const VerifySelectComponent = (
94+
<VerifySelect selectedValue={verificationValue} setSelectedValue={setVerificationValue} />
95+
);
96+
97+
const keyboardDatePickerInputStyles = {
98+
borderColor: validationError ? "red" : undefined,
99+
marginLeft: "5px" // Add left margin here
100+
};
101+
102+
// Define MuiPickersUtilsProvider component
103+
const MuiPickersUtilsProviderComponent = (
104+
<MuiPickersUtilsProvider utils={DateFnsUtils}>
105+
<div className={css.keyboardDatePickerWrapper}>
106+
<KeyboardDatePicker
107+
variant="inline"
108+
format={DATE_FORMAT}
109+
margin="normal"
110+
id="date-picker-inline"
111+
value={selectedDate}
112+
onChange={handleDropdownDate}
113+
error={!!validationError}
114+
maxDate={maxDate} // Disable future dates
115+
InputProps={{
116+
style: keyboardDatePickerInputStyles
117+
}}
118+
KeyboardButtonProps={{
119+
"aria-label": i18n.t("key_performance_indicators.date_range_dialog.aria-labels.from")
120+
}}
121+
/>
122+
</div>
123+
</MuiPickersUtilsProvider>
124+
);
125+
17126
return (
18127
<ListItemText
19128
id="subform-header-button"
@@ -26,7 +135,32 @@ const Component = ({ fields, values, locale, displayName, index, collapsedFieldV
26135
</div>
27136
}
28137
>
138+
{canVerify && mode.isShow ? (
139+
<Button
140+
onClick={event => handleOpenVerifyModal(index, event)}
141+
id={`verify-button-${index}`}
142+
className={css.verifiedSpan}
143+
color="primary"
144+
variant="contained"
145+
size="small"
146+
disableElevation
147+
>
148+
{i18n.t("incidents.change_status")}
149+
</Button>
150+
) : null}
29151
<ViolationTitle title={displayName?.[locale]} values={currentValues} fields={fields} />
152+
153+
<ActionDialog
154+
open={verifyModal}
155+
successHandler={handleOk}
156+
cancelHandler={cancelVerifyHandler}
157+
dialogTitle={i18n.t("incidents.change_status")}
158+
confirmButtonLabel={i18n.t("buttons.update")}
159+
maxSize="xs"
160+
>
161+
{VerifySelectComponent}
162+
{verificationValue === "verified" ? MuiPickersUtilsProviderComponent : null}
163+
</ActionDialog>
30164
</ListItemText>
31165
);
32166
};
@@ -37,6 +171,7 @@ Component.propTypes = {
37171
fields: PropTypes.array.isRequired,
38172
index: PropTypes.number.isRequired,
39173
locale: PropTypes.string.isRequired,
174+
mode: PropTypes.object.isRequired,
40175
values: PropTypes.array.isRequired
41176
};
42177

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { Box, FormControl, MenuItem, Select } from "@material-ui/core";
2+
import useOptions from "../../../../../../form/use-options";
3+
import { LOOKUPS } from "../../../../../../../config";
4+
import css from "./styles.css"
5+
import PropTypes from "prop-types";
6+
7+
const MENU_PROPS = {
8+
getContentAnchorEl: null,
9+
anchorOrigin: {
10+
vertical: "bottom",
11+
horizontal: 'left'
12+
},
13+
transformOrigin: {
14+
vertical: "top",
15+
horizontal: 'left'
16+
}
17+
}
18+
19+
const Component = ({ selectedValue, setSelectedValue }) => {
20+
21+
const verificationStatus = useOptions({ source: LOOKUPS.verification_status });
22+
23+
const handleChange = (event) => { // Change dropdown value
24+
setSelectedValue(event.target.value);
25+
};
26+
27+
const onSel = true;
28+
29+
return (
30+
<Box className={css.selectWrapper}>
31+
<FormControl fullWidth classes={{
32+
root: css.verifyFormControlRoot
33+
}}>
34+
<Select
35+
value={selectedValue}
36+
onChange={handleChange}
37+
onSel={onSel}
38+
MenuProps={MENU_PROPS}
39+
classes={{
40+
root: css.verifySelectComponent,
41+
select: css.verifySelectComponentSelect
42+
}}
43+
variant="outlined"
44+
fullWidth
45+
>
46+
{
47+
verificationStatus.map((option) => (
48+
<MenuItem key={option.id} value={option.id} style={{ display: option.id === (selectedValue) ? 'none' : 'block' }}>{option.display_text}</MenuItem>
49+
))
50+
}
51+
</Select>
52+
</FormControl>
53+
</Box>
54+
);
55+
}
56+
Component.propTypes = {
57+
selectedValue: PropTypes.string,
58+
setSelectedValue: PropTypes.string
59+
};
60+
61+
Component.displayName = "VerifySelect";
62+
63+
export default Component;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
.verifyFormControlRoot {
3+
padding: 4px;
4+
}
5+
6+
.verifySelectComponent {
7+
padding: 12px !important;
8+
border-radius: 4px;
9+
border-bottom: none;
10+
}
11+
12+
.verifySelectComponentSelect, .verifySelectComponentSelect:focus {
13+
border-radius: 4px;
14+
}
15+
16+
.verifySelectComponent[aria-expanded="true"], .verifySelectComponent:focus {
17+
outline: 4px solid var(--c-light-blue-rgba);
18+
}
19+
20+
.selectWrapper {
21+
min-width: 150px;
22+
}

app/javascript/components/record-form/form/subforms/subform-fields/components/violation-title/component.jsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ const Component = ({ title, values, fields }) => {
2222
) : null;
2323

2424
return (
25-
<div className={css.container}>
26-
<div className={css.title}>
25+
<div className={css.container} >
26+
<div className={css.titleViolation} >
2727
{title} {renderShortUniqueId}
2828
</div>
2929
<div>{renderChipStatus}</div>

app/javascript/components/record-form/form/subforms/subform-fields/components/violation-title/styles.css

+12-2
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,26 @@
44
color: var(--c-white);
55
border: solid 1px var(--c-blue);
66
background-color: var(--c-blue);
7+
width: 120px ;
8+
word-wrap: normal;
79
}
810

911
.container {
1012
display: inline-flex;
1113
gap: var(--sp-2);
12-
align-items: center;
14+
align-items: flex-start;
1315
}
1416

1517
.title {
1618
display: flex;
1719
align-items: center;
1820
margin-top: 0.1em;
19-
}
21+
}
22+
23+
.titleViolation {
24+
display: flex;
25+
align-items: center;
26+
margin-top: 0.1em;
27+
width: 300px !important;
28+
word-wrap: normal !important;
29+
}

0 commit comments

Comments
 (0)