Skip to content

Commit 70948cd

Browse files
committed
refactor: update plugins with context data
1 parent 75f449c commit 70948cd

File tree

7 files changed

+101
-119
lines changed

7 files changed

+101
-119
lines changed
Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,30 @@
11
import React from 'react';
2-
import PropTypes from 'prop-types';
32
import { Form } from '@edx/paragon';
43
import { useIntl } from '@edx/frontend-platform/i18n';
54
import TextEditor from '@communications-app/src/components/bulk-email-tool/text-editor/TextEditor';
5+
import { useSelector, useDispatch } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context';
6+
import { actionCreators as formActions } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context/reducer';
67

78
import messages from './messages';
89

9-
const BodyForm = ({ formState, setFormState }) => {
10+
const BodyForm = () => {
1011
const intl = useIntl();
11-
const { body, isFormSubmitted = false } = formState ?? {};
12+
const formData = useSelector((state) => state.form);
13+
const dispatch = useDispatch();
14+
const { body, isFormSubmitted = false } = formData;
15+
1216
const handleChangeTextEditor = (value) => {
13-
setFormState({ ...formState, body: { value } });
17+
dispatch(formActions.updateForm({ body: value }));
1418
};
1519

16-
const bodyValidation = body.value.length > 0;
20+
const bodyValidation = body.length > 0;
1721

1822
return (
1923
<Form.Group controlId="emailBody">
2024
<Form.Label className="h3 text-primary-500">{intl.formatMessage(messages.bodyFormFieldLabel)}</Form.Label>
2125
<TextEditor
2226
onChange={handleChangeTextEditor}
23-
value={body.value}
27+
value={body}
2428
/>
2529
{isFormSubmitted && !bodyValidation && (
2630
<Form.Control.Feedback className="px-3" hasIcon type="invalid">
@@ -31,14 +35,4 @@ const BodyForm = ({ formState, setFormState }) => {
3135
);
3236
};
3337

34-
BodyForm.defaultProps = {
35-
formState: {},
36-
setFormState: () => {},
37-
};
38-
39-
BodyForm.propTypes = {
40-
formState: PropTypes.shape({}),
41-
setFormState: PropTypes.func,
42-
};
43-
4438
export default BodyForm;

plugins/communications-app/RecipientsForm/index.jsx

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,43 @@ import React, { useEffect, useState } from 'react';
22
import PropTypes from 'prop-types';
33
import { Form } from '@edx/paragon';
44
import { FormattedMessage } from '@edx/frontend-platform/i18n';
5+
import { useSelector, useDispatch } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context';
6+
import { actionCreators as formActions } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context/reducer';
57

68
import './styles.scss';
79

810
const disableIsHasLearners = ['track', 'cohort'];
911

10-
const RecipientsForm = ({ formState, setFormState }) => {
11-
const {
12-
isFormSubmitted, emailRecipients, isEditMode, cohorts: additionalCohorts,
13-
} = formState ?? {};
12+
const RecipientsForm = (props) => {
13+
const { cohorts: additionalCohorts } = props;
14+
const formData = useSelector((state) => state.form);
15+
const dispatch = useDispatch();
16+
const { isEditMode, emailRecipients, isFormSubmitted } = formData;
1417

15-
const { value: emailRecipientsInitial } = emailRecipients;
1618
const [selectedGroups, setSelectedGroups] = useState([]);
1719
const hasAllLearnersSelected = selectedGroups.some((group) => group === 'learners');
1820

1921
const handleChangeCheckBoxes = ({ target: { value, checked } }) => {
20-
const { value: emailRecipientsValue } = emailRecipients;
21-
2222
let newValue;
2323

2424
if (checked) {
25-
const uniqueSet = new Set([...emailRecipientsValue, value]);
25+
const uniqueSet = new Set([...emailRecipients, value]);
2626
newValue = Array.from(uniqueSet);
2727
} else {
28-
newValue = emailRecipientsValue.filter((item) => item !== value);
28+
newValue = emailRecipients.filter((item) => item !== value);
2929
}
3030

3131
if (checked && value === 'learners') {
3232
newValue = newValue.filter(item => !disableIsHasLearners.some(disabled => item.includes(disabled)));
3333
}
3434

35-
setFormState({ ...formState, emailRecipients: { ...emailRecipients, value: newValue } });
35+
dispatch(formActions.updateForm({ emailRecipients: newValue }));
3636
setSelectedGroups(newValue);
3737
};
3838

3939
useEffect(() => {
40-
setSelectedGroups(emailRecipientsInitial);
41-
// eslint-disable-next-line react-hooks/exhaustive-deps
42-
}, [isEditMode]);
40+
setSelectedGroups(emailRecipients);
41+
}, [isEditMode, emailRecipients.length, emailRecipients]);
4342

4443
return (
4544
<Form.Group>
@@ -135,30 +134,28 @@ const RecipientsForm = ({ formState, setFormState }) => {
135134
</Form.Checkbox>
136135
</Form.CheckboxSet>
137136
{ isFormSubmitted && selectedGroups.length === 0 && (
138-
<Form.Control.Feedback
139-
className="px-3"
140-
hasIcon
141-
type="invalid"
142-
>
143-
<FormattedMessage
144-
id="bulk.email.form.recipients.error"
145-
defaultMessage="At least one recipient is required"
146-
description="An Error message located under the recipients list. Visible only on failure"
147-
/>
148-
</Form.Control.Feedback>
137+
<Form.Control.Feedback
138+
className="px-3"
139+
type="invalid"
140+
hasIcon
141+
>
142+
<FormattedMessage
143+
id="bulk.email.form.recipients.error"
144+
defaultMessage="At least one recipient is required"
145+
description="An Error message located under the recipients list. Visible only on failure"
146+
/>
147+
</Form.Control.Feedback>
149148
)}
150149
</Form.Group>
151150
);
152151
};
153152

154153
RecipientsForm.defaultProps = {
155-
formState: {},
156-
setFormState: () => {},
154+
cohorts: [],
157155
};
158156

159157
RecipientsForm.propTypes = {
160-
formState: PropTypes.shape({}),
161-
setFormState: PropTypes.func,
158+
cohorts: PropTypes.arrayOf(PropTypes.string),
162159
};
163160

164161
export default RecipientsForm;

plugins/communications-app/ScheduleSection/index.jsx

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,27 @@ import { getConfig } from '@edx/frontend-platform';
1919
import { useIntl } from '@edx/frontend-platform/i18n';
2020
import ScheduleEmailForm from '@communications-app/src/components/bulk-email-tool/bulk-email-form/ScheduleEmailForm';
2121
import useMobileResponsive from '@communications-app/src/utils/useMobileResponsive';
22+
import { useSelector, useDispatch } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context';
23+
import { actionCreators as formActions } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context/reducer';
2224

2325
import messages from './messages';
2426

2527
const formStatusToast = ['error', 'complete', 'completeSchedule'];
2628

27-
const ScheduleSection = ({ formState, setFormState, openTaskAlert }) => {
29+
const ScheduleSection = ({ openTaskAlert }) => {
2830
const intl = useIntl();
2931
const isMobile = useMobileResponsive();
3032
const [scheduleInputChanged, isScheduleInputChanged] = useState(false);
33+
const formData = useSelector((state) => state.form);
34+
const dispatch = useDispatch();
3135
const {
3236
isScheduled,
3337
scheduleDate = '',
3438
scheduleTime = '',
3539
isEditMode,
3640
formStatus,
3741
isScheduledSubmitted = false,
38-
} = formState ?? {};
42+
} = formData;
3943

4044
const formStatusErrors = {
4145
error: intl.formatMessage(messages.ScheduleSectionSubmitFormError),
@@ -46,14 +50,19 @@ const ScheduleSection = ({ formState, setFormState, openTaskAlert }) => {
4650
const handleChangeScheduled = () => {
4751
const newSchedule = !isScheduled;
4852
const newFormStatus = newSchedule ? 'schedule' : 'default';
49-
setFormState({ ...formState, formStatus: newFormStatus, isScheduled: newSchedule });
53+
// setFormState({ ...formState, formStatus: newFormStatus, isScheduled: newSchedule });
54+
dispatch(formActions.updateForm({ formStatus: newFormStatus, isScheduled: newSchedule }));
5055
};
5156

5257
const handleScheduleDate = ({ target: { name, value } }) => {
53-
setFormState({ ...formState, [name]: value });
58+
dispatch(formActions.updateForm({ [name]: value }));
5459
if (!scheduleInputChanged) {
5560
isScheduleInputChanged(true);
5661
}
62+
/* setFormState({ ...formState, [name]: value });
63+
if (!scheduleInputChanged) {
64+
isScheduleInputChanged(true);
65+
} */
5766
};
5867

5968
const scheduleFields = isScheduledSubmitted ? scheduleDate.length > 0 && scheduleTime.length > 0
@@ -62,24 +71,11 @@ const ScheduleSection = ({ formState, setFormState, openTaskAlert }) => {
6271
const checkIsValidSchedule = isScheduled ? scheduleFields : true;
6372

6473
const handleResetFormValues = () => {
65-
const { emailRecipients, subject, body } = formState ?? {};
66-
const newRecipientsValue = { ...emailRecipients, value: [] };
67-
const newSubjectValue = { ...subject, value: '' };
68-
const newBodyValue = { ...body, value: '' };
69-
70-
setFormState({
71-
...formState,
72-
emailRecipients: newRecipientsValue,
73-
subject: newSubjectValue,
74-
body: newBodyValue,
75-
scheduleDate: '',
76-
scheduleTime: '',
77-
isScheduled: false,
78-
isEditMode: false,
79-
formStatus: 'default',
80-
isScheduleButtonClicked: false,
81-
isScheduledSubmitted: false,
82-
});
74+
dispatch(formActions.resetForm());
75+
};
76+
77+
const handleCloseToast = () => {
78+
dispatch(formActions.updateForm({ formStatus: 'default' }));
8379
};
8480

8581
return (
@@ -90,7 +86,7 @@ const ScheduleSection = ({ formState, setFormState, openTaskAlert }) => {
9086
name="scheduleEmailBox"
9187
checked={isScheduled}
9288
onChange={handleChangeScheduled}
93-
disabled={formState === 'pending'}
89+
disabled={formStatus === 'pending'}
9490
>
9591
{intl.formatMessage(messages.ScheduleSectionSubmitScheduleBox)}
9692
</Form.Checkbox>
@@ -124,11 +120,13 @@ const ScheduleSection = ({ formState, setFormState, openTaskAlert }) => {
124120

125121
<StatefulButton
126122
className="send-email-btn"
123+
data-testid="send-email-btn"
127124
variant="primary"
128125
onClick={(event) => {
129126
event.preventDefault();
130127
if (formStatus === 'schedule' && !isScheduledSubmitted) {
131-
setFormState({ ...formState, isScheduleButtonClicked: true });
128+
dispatch(formActions.updateForm({ isScheduleButtonClicked: true }));
129+
// setFormState({ ...formState, isScheduleButtonClicked: true });
132130
}
133131
openTaskAlert();
134132
}}
@@ -160,24 +158,20 @@ const ScheduleSection = ({ formState, setFormState, openTaskAlert }) => {
160158

161159
<Toast
162160
show={formStatusToast.includes(formStatus)}
163-
onClose={() => { setFormState({ ...formState, formStatus: 'default' }); }}
161+
onClose={handleCloseToast}
164162
>
165-
{formStatusErrors[formStatus] || null}
163+
{formStatusErrors[formStatus] || ''}
166164
</Toast>
167165
</div>
168166
</Form.Group>
169167
);
170168
};
171169

172170
ScheduleSection.defaultProps = {
173-
formState: {},
174-
setFormState: () => {},
175171
openTaskAlert: () => {},
176172
};
177173

178174
ScheduleSection.propTypes = {
179-
formState: PropTypes.shape({}),
180-
setFormState: PropTypes.func,
181175
openTaskAlert: PropTypes.func,
182176
};
183177

plugins/communications-app/ScheduleSection/messages.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const messages = defineMessages({
1313
},
1414
ScheduleSectionSubmitFormError: {
1515
id: 'schedule.section.submit.error',
16-
defaultMessage: 'An error occured while attempting to send the email.',
16+
defaultMessage: 'An error occurred while attempting to send the email.',
1717
description: 'An Error message located under the submit button for the email form. Visible only on a failure.',
1818
},
1919
ScheduleSectionSubmitFormSuccess: {
Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
import React from 'react';
2-
import PropTypes from 'prop-types';
32
import { Form } from '@edx/paragon';
43
import { useIntl } from '@edx/frontend-platform/i18n';
4+
import { useSelector, useDispatch } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context';
5+
import { actionCreators as formActions } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context/reducer';
56

67
import messages from './messages';
78

8-
const SubjectForm = ({ formState, setFormState }) => {
9+
const SubjectForm = () => {
910
const intl = useIntl();
10-
const { subject, isFormSubmitted } = formState ?? {};
11+
const formData = useSelector((state) => state.form);
12+
const dispatch = useDispatch();
13+
const { subject, isFormSubmitted } = formData;
14+
1115
const handleChangeEmailSubject = ({ target: { value } }) => {
12-
setFormState({ ...formState, subject: { value } });
16+
dispatch(formActions.updateForm({ subject: value }));
1317
};
1418

15-
const subjectValidation = subject.value.length > 0;
19+
const subjectValidation = subject.length > 0;
1620

1721
return (
1822
<Form.Group controlId="emailSubject" className="my-5">
@@ -21,7 +25,7 @@ const SubjectForm = ({ formState, setFormState }) => {
2125
name="emailSubject"
2226
className="w-lg-50"
2327
onChange={handleChangeEmailSubject}
24-
value={subject.value}
28+
value={subject}
2529
/>
2630
{ isFormSubmitted && !subjectValidation && (
2731
<Form.Control.Feedback className="px-3" hasIcon type="invalid">
@@ -32,14 +36,4 @@ const SubjectForm = ({ formState, setFormState }) => {
3236
);
3337
};
3438

35-
SubjectForm.defaultProps = {
36-
formState: {},
37-
setFormState: () => {},
38-
};
39-
40-
SubjectForm.propTypes = {
41-
formState: PropTypes.shape({}),
42-
setFormState: PropTypes.func,
43-
};
44-
4539
export default SubjectForm;

0 commit comments

Comments
 (0)