feat: Add cancel button for editing an email (#49)

Right now, canceling edit mode is clunky. This adds a button to
explicitly cancel the mode for the editor.
This commit is contained in:
Thomas Tracy
2022-07-13 11:51:10 -04:00
committed by GitHub
parent b7275c1491
commit 3deaeece2c
5 changed files with 19 additions and 26 deletions

View File

@@ -1,6 +1,7 @@
import React, { useContext, useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import {
Button,
Form, Icon, StatefulButton, Toast, useToggle,
} from '@edx/paragon';
import {
@@ -19,11 +20,9 @@ import messages from './messages';
import { BulkEmailContext } from '../bulk-email-context';
import {
addRecipient,
clearDateTime,
clearEditor,
handleEditorChange,
removeRecipient,
setEditMode,
} from './data/actions';
import { editScheduledEmailThunk, postBulkEmailThunk } from './data/thunks';
import { getScheduledBulkEmailThunk } from '../bulk-email-task-manager/bulk-email-scheduled-emails-table/data/thunks';
@@ -103,7 +102,7 @@ function BulkEmailForm(props) {
}
};
const delayedEmailFormReset = useTimeout(resetEmailForm, 3000);
const delayedEmailFormReset = useTimeout(resetEmailForm, 3000, editor.editMode);
const onFormChange = (event) => dispatch(handleEditorChange(event.target.name, event.target.value));
@@ -162,19 +161,15 @@ function BulkEmailForm(props) {
};
useEffect(() => {
if (!!editor.scheduleDate || !!editor.scheduleTime) {
if (editor.editMode === true) {
toggleScheduled(true);
}
if (isScheduled) {
if (editor.editMode) {
setEmailFormStatus(FORM_SUBMIT_STATES.RESCHEDULE);
} else {
setEmailFormStatus(FORM_SUBMIT_STATES.SCHEDULE);
}
setEmailFormStatus(FORM_SUBMIT_STATES.RESCHEDULE);
} else if (isScheduled) {
setEmailFormStatus(FORM_SUBMIT_STATES.SCHEDULE);
} else {
setEmailFormStatus(FORM_SUBMIT_STATES.DEFAULT);
}
}, [isScheduled, editor.scheduleDate, editor.scheduleTime]);
}, [isScheduled, editor.editMode]);
const AlertMessage = () => (
<>
@@ -267,13 +262,7 @@ function BulkEmailForm(props) {
<Form.Checkbox
name="scheduleEmailBox"
checked={isScheduled}
onChange={() => toggleScheduled((prev) => {
if (prev) {
dispatch(clearDateTime());
dispatch(setEditMode(false));
}
return !prev;
})}
onChange={() => toggleScheduled((prev) => !prev)}
disabled={emailFormStatus === FORM_SUBMIT_STATES.PENDING}
>
{intl.formatMessage(messages.bulkEmailFormScheduleBox)}
@@ -290,10 +279,11 @@ function BulkEmailForm(props) {
<div
className={classNames('d-flex', {
'mt-n4.5': !isScheduled && !isMobile,
'flex-row-reverse justify-content-between align-items-end': !isMobile,
'flex-row-reverse align-items-end': !isMobile,
'border-top pt-2': isScheduled,
})}
>
{editor.editMode && <Button className="ml-2" variant="outline-brand" onClick={() => dispatch(clearEditor())}>Cancel</Button>}
<StatefulButton
className="send-email-btn"
variant="primary"

View File

@@ -15,6 +15,7 @@ export function editorReducer(state, action) {
scheduleTime: action.payload.scheduleTime || '',
schedulingId: action.payload.schedulingId || '',
emailId: action.payload.emailId || null,
editMode: action.payload.editMode || false,
};
case 'ADD_RECIPIENT':
return {
@@ -36,6 +37,7 @@ export function editorReducer(state, action) {
...state,
scheduleDate: '',
scheduleTime: '',
editMode: false,
};
case 'CLEAR_EDITOR':
return {

View File

@@ -14,7 +14,7 @@ import { BulkEmailContext } from '../../bulk-email-context';
import { deleteScheduledEmailThunk, getScheduledBulkEmailThunk } from './data/thunks';
import messages from './messages';
import ViewEmailModal from '../ViewEmailModal';
import { copyToEditor, setEditMode } from '../../bulk-email-form/data/actions';
import { copyToEditor } from '../../bulk-email-form/data/actions';
function flattenScheduledEmailsArray(emails) {
return emails.map((email) => ({
@@ -103,7 +103,6 @@ function BulkEmailScheduledEmailsTable({ intl }) {
const emailRecipients = targets.replaceAll('-', ':').split(', ');
const scheduleDate = formatDate(dateTime);
const scheduleTime = formatTime(dateTime);
dispatch(setEditMode(true));
dispatch(
copyToEditor({
emailId,
@@ -113,6 +112,7 @@ function BulkEmailScheduledEmailsTable({ intl }) {
scheduleDate,
scheduleTime,
schedulingId,
editMode: true,
}),
);
};

View File

@@ -75,6 +75,7 @@ describe('BulkEmailScheduledEmailsTable', () => {
it('properly formats data for editing mode', async () => {
const editorObj = {
editMode: true,
emailId: 1,
emailBody: '<p>body</p>',
emailSubject: 'subject',
@@ -92,7 +93,6 @@ describe('BulkEmailScheduledEmailsTable', () => {
render(renderBulkEmailScheduledEmailsTable());
fireEvent.click(await screen.findByLabelText('Edit'));
expect(actions.copyToEditor).toHaveBeenCalledWith(editorObj);
expect(actions.setEditMode).toHaveBeenCalledWith(true);
});
it('removes email when delete is pressed', async () => {
const axiosMock = new MockAdapter(getAuthenticatedHttpClient());

View File

@@ -8,16 +8,17 @@ import { useRef, useEffect } from 'react';
* and only allow one at a time.
* @param {function} callback The function to call once the delay ends
* @param {millisecond} delay time to delay function call
* @param {bool} cancel cancels the callback early if true
*/
export default function useTimeout(callback, delay) {
export default function useTimeout(callback, delay, cancel) {
const timeoutRef = useRef(null);
useEffect(() => {
const timeout = timeoutRef.current;
if (timeout) {
if (timeout || cancel) {
clearTimeout(timeout);
}
}, []);
}, [cancel]);
return () => {
if (timeoutRef.current) {