From ee2dffa204102b223d19b7851666af3ff26f2667 Mon Sep 17 00:00:00 2001 From: johnvente Date: Fri, 22 Dec 2023 16:25:03 -0500 Subject: [PATCH] refactor: update plugins with context data --- plugins/communications-app/BodyForm/index.jsx | 26 ++++----- .../RecipientsForm/index.jsx | 53 ++++++++--------- .../ScheduleSection/index.jsx | 54 ++++++++---------- .../ScheduleSection/messages.js | 2 +- .../communications-app/SubjectForm/index.jsx | 26 ++++----- .../TaskAlertModalForm/index.jsx | 57 ++++++++++--------- .../TaskAlertModalForm/messages.js | 2 +- 7 files changed, 101 insertions(+), 119 deletions(-) diff --git a/plugins/communications-app/BodyForm/index.jsx b/plugins/communications-app/BodyForm/index.jsx index d5569ede..2ca2f073 100644 --- a/plugins/communications-app/BodyForm/index.jsx +++ b/plugins/communications-app/BodyForm/index.jsx @@ -1,26 +1,30 @@ import React from 'react'; -import PropTypes from 'prop-types'; import { Form } from '@edx/paragon'; import { useIntl } from '@edx/frontend-platform/i18n'; import TextEditor from '@communications-app/src/components/bulk-email-tool/text-editor/TextEditor'; +import { useSelector, useDispatch } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context'; +import { actionCreators as formActions } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context/reducer'; import messages from './messages'; -const BodyForm = ({ formState, setFormState }) => { +const BodyForm = () => { const intl = useIntl(); - const { body, isFormSubmitted = false } = formState ?? {}; + const formData = useSelector((state) => state.form); + const dispatch = useDispatch(); + const { body, isFormSubmitted = false } = formData; + const handleChangeTextEditor = (value) => { - setFormState({ ...formState, body: { value } }); + dispatch(formActions.updateForm({ body: value })); }; - const bodyValidation = body.value.length > 0; + const bodyValidation = body.length > 0; return ( {intl.formatMessage(messages.bodyFormFieldLabel)} {isFormSubmitted && !bodyValidation && ( @@ -31,14 +35,4 @@ const BodyForm = ({ formState, setFormState }) => { ); }; -BodyForm.defaultProps = { - formState: {}, - setFormState: () => {}, -}; - -BodyForm.propTypes = { - formState: PropTypes.shape({}), - setFormState: PropTypes.func, -}; - export default BodyForm; diff --git a/plugins/communications-app/RecipientsForm/index.jsx b/plugins/communications-app/RecipientsForm/index.jsx index 5bac3daf..19e3c02c 100644 --- a/plugins/communications-app/RecipientsForm/index.jsx +++ b/plugins/communications-app/RecipientsForm/index.jsx @@ -2,44 +2,43 @@ import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { Form } from '@edx/paragon'; import { FormattedMessage } from '@edx/frontend-platform/i18n'; +import { useSelector, useDispatch } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context'; +import { actionCreators as formActions } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context/reducer'; import './styles.scss'; const disableIsHasLearners = ['track', 'cohort']; -const RecipientsForm = ({ formState, setFormState }) => { - const { - isFormSubmitted, emailRecipients, isEditMode, cohorts: additionalCohorts, - } = formState ?? {}; +const RecipientsForm = (props) => { + const { cohorts: additionalCohorts } = props; + const formData = useSelector((state) => state.form); + const dispatch = useDispatch(); + const { isEditMode, emailRecipients, isFormSubmitted } = formData; - const { value: emailRecipientsInitial } = emailRecipients; const [selectedGroups, setSelectedGroups] = useState([]); const hasAllLearnersSelected = selectedGroups.some((group) => group === 'learners'); const handleChangeCheckBoxes = ({ target: { value, checked } }) => { - const { value: emailRecipientsValue } = emailRecipients; - let newValue; if (checked) { - const uniqueSet = new Set([...emailRecipientsValue, value]); + const uniqueSet = new Set([...emailRecipients, value]); newValue = Array.from(uniqueSet); } else { - newValue = emailRecipientsValue.filter((item) => item !== value); + newValue = emailRecipients.filter((item) => item !== value); } if (checked && value === 'learners') { newValue = newValue.filter(item => !disableIsHasLearners.some(disabled => item.includes(disabled))); } - setFormState({ ...formState, emailRecipients: { ...emailRecipients, value: newValue } }); + dispatch(formActions.updateForm({ emailRecipients: newValue })); setSelectedGroups(newValue); }; useEffect(() => { - setSelectedGroups(emailRecipientsInitial); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isEditMode]); + setSelectedGroups(emailRecipients); + }, [isEditMode, emailRecipients.length, emailRecipients]); return ( @@ -135,30 +134,28 @@ const RecipientsForm = ({ formState, setFormState }) => { { isFormSubmitted && selectedGroups.length === 0 && ( - - - + + + )} ); }; RecipientsForm.defaultProps = { - formState: {}, - setFormState: () => {}, + cohorts: [], }; RecipientsForm.propTypes = { - formState: PropTypes.shape({}), - setFormState: PropTypes.func, + cohorts: PropTypes.arrayOf(PropTypes.string), }; export default RecipientsForm; diff --git a/plugins/communications-app/ScheduleSection/index.jsx b/plugins/communications-app/ScheduleSection/index.jsx index a5dcd016..3c87d3de 100644 --- a/plugins/communications-app/ScheduleSection/index.jsx +++ b/plugins/communications-app/ScheduleSection/index.jsx @@ -19,15 +19,19 @@ import { getConfig } from '@edx/frontend-platform'; import { useIntl } from '@edx/frontend-platform/i18n'; import ScheduleEmailForm from '@communications-app/src/components/bulk-email-tool/bulk-email-form/ScheduleEmailForm'; import useMobileResponsive from '@communications-app/src/utils/useMobileResponsive'; +import { useSelector, useDispatch } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context'; +import { actionCreators as formActions } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context/reducer'; import messages from './messages'; const formStatusToast = ['error', 'complete', 'completeSchedule']; -const ScheduleSection = ({ formState, setFormState, openTaskAlert }) => { +const ScheduleSection = ({ openTaskAlert }) => { const intl = useIntl(); const isMobile = useMobileResponsive(); const [scheduleInputChanged, isScheduleInputChanged] = useState(false); + const formData = useSelector((state) => state.form); + const dispatch = useDispatch(); const { isScheduled, scheduleDate = '', @@ -35,7 +39,7 @@ const ScheduleSection = ({ formState, setFormState, openTaskAlert }) => { isEditMode, formStatus, isScheduledSubmitted = false, - } = formState ?? {}; + } = formData; const formStatusErrors = { error: intl.formatMessage(messages.ScheduleSectionSubmitFormError), @@ -46,14 +50,19 @@ const ScheduleSection = ({ formState, setFormState, openTaskAlert }) => { const handleChangeScheduled = () => { const newSchedule = !isScheduled; const newFormStatus = newSchedule ? 'schedule' : 'default'; - setFormState({ ...formState, formStatus: newFormStatus, isScheduled: newSchedule }); + // setFormState({ ...formState, formStatus: newFormStatus, isScheduled: newSchedule }); + dispatch(formActions.updateForm({ formStatus: newFormStatus, isScheduled: newSchedule })); }; const handleScheduleDate = ({ target: { name, value } }) => { - setFormState({ ...formState, [name]: value }); + dispatch(formActions.updateForm({ [name]: value })); if (!scheduleInputChanged) { isScheduleInputChanged(true); } + /* setFormState({ ...formState, [name]: value }); + if (!scheduleInputChanged) { + isScheduleInputChanged(true); + } */ }; const scheduleFields = isScheduledSubmitted ? scheduleDate.length > 0 && scheduleTime.length > 0 @@ -62,24 +71,11 @@ const ScheduleSection = ({ formState, setFormState, openTaskAlert }) => { const checkIsValidSchedule = isScheduled ? scheduleFields : true; const handleResetFormValues = () => { - const { emailRecipients, subject, body } = formState ?? {}; - const newRecipientsValue = { ...emailRecipients, value: [] }; - const newSubjectValue = { ...subject, value: '' }; - const newBodyValue = { ...body, value: '' }; - - setFormState({ - ...formState, - emailRecipients: newRecipientsValue, - subject: newSubjectValue, - body: newBodyValue, - scheduleDate: '', - scheduleTime: '', - isScheduled: false, - isEditMode: false, - formStatus: 'default', - isScheduleButtonClicked: false, - isScheduledSubmitted: false, - }); + dispatch(formActions.resetForm()); + }; + + const handleCloseToast = () => { + dispatch(formActions.updateForm({ formStatus: 'default' })); }; return ( @@ -90,7 +86,7 @@ const ScheduleSection = ({ formState, setFormState, openTaskAlert }) => { name="scheduleEmailBox" checked={isScheduled} onChange={handleChangeScheduled} - disabled={formState === 'pending'} + disabled={formStatus === 'pending'} > {intl.formatMessage(messages.ScheduleSectionSubmitScheduleBox)} @@ -124,11 +120,13 @@ const ScheduleSection = ({ formState, setFormState, openTaskAlert }) => { { event.preventDefault(); if (formStatus === 'schedule' && !isScheduledSubmitted) { - setFormState({ ...formState, isScheduleButtonClicked: true }); + dispatch(formActions.updateForm({ isScheduleButtonClicked: true })); + // setFormState({ ...formState, isScheduleButtonClicked: true }); } openTaskAlert(); }} @@ -160,9 +158,9 @@ const ScheduleSection = ({ formState, setFormState, openTaskAlert }) => { { setFormState({ ...formState, formStatus: 'default' }); }} + onClose={handleCloseToast} > - {formStatusErrors[formStatus] || null} + {formStatusErrors[formStatus] || ''} @@ -170,14 +168,10 @@ const ScheduleSection = ({ formState, setFormState, openTaskAlert }) => { }; ScheduleSection.defaultProps = { - formState: {}, - setFormState: () => {}, openTaskAlert: () => {}, }; ScheduleSection.propTypes = { - formState: PropTypes.shape({}), - setFormState: PropTypes.func, openTaskAlert: PropTypes.func, }; diff --git a/plugins/communications-app/ScheduleSection/messages.js b/plugins/communications-app/ScheduleSection/messages.js index 75baf818..e795715d 100644 --- a/plugins/communications-app/ScheduleSection/messages.js +++ b/plugins/communications-app/ScheduleSection/messages.js @@ -13,7 +13,7 @@ const messages = defineMessages({ }, ScheduleSectionSubmitFormError: { id: 'schedule.section.submit.error', - defaultMessage: 'An error occured while attempting to send the email.', + defaultMessage: 'An error occurred while attempting to send the email.', description: 'An Error message located under the submit button for the email form. Visible only on a failure.', }, ScheduleSectionSubmitFormSuccess: { diff --git a/plugins/communications-app/SubjectForm/index.jsx b/plugins/communications-app/SubjectForm/index.jsx index f44ad055..f7d6dc50 100644 --- a/plugins/communications-app/SubjectForm/index.jsx +++ b/plugins/communications-app/SubjectForm/index.jsx @@ -1,18 +1,22 @@ import React from 'react'; -import PropTypes from 'prop-types'; import { Form } from '@edx/paragon'; import { useIntl } from '@edx/frontend-platform/i18n'; +import { useSelector, useDispatch } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context'; +import { actionCreators as formActions } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context/reducer'; import messages from './messages'; -const SubjectForm = ({ formState, setFormState }) => { +const SubjectForm = () => { const intl = useIntl(); - const { subject, isFormSubmitted } = formState ?? {}; + const formData = useSelector((state) => state.form); + const dispatch = useDispatch(); + const { subject, isFormSubmitted } = formData; + const handleChangeEmailSubject = ({ target: { value } }) => { - setFormState({ ...formState, subject: { value } }); + dispatch(formActions.updateForm({ subject: value })); }; - const subjectValidation = subject.value.length > 0; + const subjectValidation = subject.length > 0; return ( @@ -21,7 +25,7 @@ const SubjectForm = ({ formState, setFormState }) => { name="emailSubject" className="w-lg-50" onChange={handleChangeEmailSubject} - value={subject.value} + value={subject} /> { isFormSubmitted && !subjectValidation && ( @@ -32,14 +36,4 @@ const SubjectForm = ({ formState, setFormState }) => { ); }; -SubjectForm.defaultProps = { - formState: {}, - setFormState: () => {}, -}; - -SubjectForm.propTypes = { - formState: PropTypes.shape({}), - setFormState: PropTypes.func, -}; - export default SubjectForm; diff --git a/plugins/communications-app/TaskAlertModalForm/index.jsx b/plugins/communications-app/TaskAlertModalForm/index.jsx index 52ccb031..308dbc0e 100644 --- a/plugins/communications-app/TaskAlertModalForm/index.jsx +++ b/plugins/communications-app/TaskAlertModalForm/index.jsx @@ -1,48 +1,45 @@ -import React, { useCallback, useContext } from 'react'; +import React, { useContext } from 'react'; import PropTypes from 'prop-types'; import TaskAlertModal from '@communications-app/src/components/bulk-email-tool/task-alert-modal'; import { getScheduledBulkEmailThunk } from '@communications-app/src/components/bulk-email-tool/bulk-email-task-manager/bulk-email-scheduled-emails-table/data/thunks'; import { BulkEmailContext } from '@communications-app/src/components/bulk-email-tool/bulk-email-context'; +import { useSelector, useDispatch } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context'; +import { actionCreators as formActions } from '@communications-app/src/components/bulk-email-tool/bulk-email-form/BuildEmailFormExtensible/context/reducer'; import { postBulkEmailInstructorTask, patchScheduledBulkEmailInstructorTask } from './api'; import { AlertMessage, EditMessage } from './AlertTypes'; const TaskAlertModalForm = ({ - formState, - setFormState, + courseId, isTaskAlertOpen, closeTaskAlert, }) => { const [, dispatch] = useContext(BulkEmailContext); + const formData = useSelector((state) => state.form); + const dispatchForm = useDispatch(); const { isScheduled, - emailRecipients = { value: [] }, + emailRecipients, scheduleDate = '', scheduleTime = '', isEditMode = false, subject, - courseId = '', emailId = '', schedulingId = '', body, isScheduleButtonClicked = false, isFormSubmitted = false, - } = formState ?? {}; + } = formData; - // eslint-disable-next-line react-hooks/exhaustive-deps - const changeFormStatus = useCallback((status) => setFormState({ ...formState, formStatus: status }), []); + const changeFormStatus = (status) => dispatchForm(formActions.updateForm({ formStatus: status })); const handlePostEmailTask = async () => { - const emailRecipientsValue = emailRecipients.value; - const emailSubject = subject.value; - const emailBody = body.value; - const emailData = new FormData(); emailData.append('action', 'send'); - emailData.append('send_to', JSON.stringify(emailRecipientsValue)); - emailData.append('subject', emailSubject); - emailData.append('message', emailBody); + emailData.append('send_to', JSON.stringify(emailRecipients)); + emailData.append('subject', subject); + emailData.append('message', body); if (isScheduled) { emailData.append('schedule', new Date(`${scheduleDate} ${scheduleTime}`).toISOString()); @@ -61,9 +58,9 @@ const TaskAlertModalForm = ({ }; const handlePatchEmailTask = async () => { - const emailRecipientsValue = emailRecipients.value; - const emailSubject = subject.value; - const emailBody = body.value; + const emailRecipientsValue = emailRecipients; + const emailSubject = subject; + const emailBody = body; const emailData = { email: { @@ -88,8 +85,8 @@ const TaskAlertModalForm = ({ const createEmailTask = async () => { const isScheduleValid = isScheduled ? scheduleDate.length > 0 && scheduleTime.length > 0 : true; - const isFormValid = emailRecipients.value.length > 0 && subject.value.length > 0 - && body.value.length > 0 && isScheduleValid; + const isFormValid = emailRecipients.length > 0 && subject.length > 0 + && body.length > 0 && isScheduleValid; if (isFormValid && isEditMode) { await handlePatchEmailTask(); @@ -99,7 +96,9 @@ const TaskAlertModalForm = ({ await handlePostEmailTask(); } - dispatch(getScheduledBulkEmailThunk(courseId, 1)); + if (isFormValid) { + dispatch(getScheduledBulkEmailThunk(courseId, 1)); + } }; return ( @@ -108,15 +107,15 @@ const TaskAlertModalForm = ({ alertMessage={isEditMode ? ( ) : ( )} @@ -125,10 +124,12 @@ const TaskAlertModalForm = ({ if (event.target.name === 'continue') { if (!isFormSubmitted) { - setFormState({ ...formState, isFormSubmitted: true }); + // setFormState({ ...formState, isFormSubmitted: true }); + dispatchForm(formActions.updateForm({ isFormSubmitted: true })); } if (isScheduleButtonClicked) { - setFormState({ ...formState, isScheduledSubmitted: true }); + // setFormState({ ...formState, isScheduledSubmitted: true }); + dispatchForm(formActions.updateForm({ isScheduledSubmitted: true })); } createEmailTask(); @@ -139,6 +140,7 @@ const TaskAlertModalForm = ({ }; TaskAlertModalForm.defaultProps = { + courseId: '', formState: {}, setFormState: () => {}, openTaskAlert: () => {}, @@ -147,6 +149,7 @@ TaskAlertModalForm.defaultProps = { }; TaskAlertModalForm.propTypes = { + courseId: PropTypes.string, formState: PropTypes.shape({}), setFormState: PropTypes.func, openTaskAlert: PropTypes.func, diff --git a/plugins/communications-app/TaskAlertModalForm/messages.js b/plugins/communications-app/TaskAlertModalForm/messages.js index c49310c3..dfb0abc1 100644 --- a/plugins/communications-app/TaskAlertModalForm/messages.js +++ b/plugins/communications-app/TaskAlertModalForm/messages.js @@ -13,7 +13,7 @@ const messages = defineMessages({ }, ScheduleSectionSubmitFormError: { id: 'schedule.section.submit.error', - defaultMessage: 'An error occured while attempting to send the email.', + defaultMessage: 'An error occurred while attempting to send the email.', description: 'An Error message located under the submit button for the email form. Visible only on a failure.', }, ScheduleSectionSubmitFormSuccess: {