diff --git a/src/editors/AdvancedEditor.test.tsx b/src/editors/AdvancedEditor.test.tsx
index fcbd4a886..635069f35 100644
--- a/src/editors/AdvancedEditor.test.tsx
+++ b/src/editors/AdvancedEditor.test.tsx
@@ -4,6 +4,9 @@ import {
render,
initializeMocks,
waitFor,
+ screen,
+ act,
+ fireEvent,
} from '../testUtils';
import AdvancedEditor from './AdvancedEditor';
@@ -17,7 +20,7 @@ describe('AdvancedEditor', () => {
initializeMocks();
});
- it('should call onClose when receiving "cancel-clicked" message', () => {
+ it('should call onClose when receiving "cancel-clicked" message', async () => {
render();
const messageEvent = new MessageEvent('message', {
@@ -28,8 +31,17 @@ describe('AdvancedEditor', () => {
origin: getConfig().STUDIO_BASE_URL,
});
- window.dispatchEvent(messageEvent);
+ act(() => {
+ // Send cancel event
+ window.dispatchEvent(messageEvent);
+ });
+ // Expect open cancel confimation modal
+ expect(await screen.findByText(/Are you sure you want to exit the editor/)).toBeInTheDocument();
+ // Click on "OK"
+ const confirmButton = await screen.findByRole('button', { name: 'OK' });
+ fireEvent.click(confirmButton);
+ // Should call `onClose`
expect(onCloseMock).toHaveBeenCalled();
});
diff --git a/src/editors/AdvancedEditor.tsx b/src/editors/AdvancedEditor.tsx
index 17e6c82b0..5a14d2cce 100644
--- a/src/editors/AdvancedEditor.tsx
+++ b/src/editors/AdvancedEditor.tsx
@@ -1,20 +1,24 @@
import React, { useEffect } from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
+import { useToggle } from '@openedx/paragon';
import { LibraryBlock } from '../library-authoring/LibraryBlock';
import { EditorModalWrapper } from './containers/EditorContainer';
import { ToastContext } from '../generic/toast-context';
+
import messages from './messages';
+import CancelConfirmModal from './containers/EditorContainer/components/CancelConfirmModal';
interface AdvancedEditorProps {
usageKey: string,
- onClose: Function | null,
+ onClose: (() => void) | null,
}
const AdvancedEditor = ({ usageKey, onClose }: AdvancedEditorProps) => {
const intl = useIntl();
const { showToast } = React.useContext(ToastContext);
+ const [isCancelConfirmOpen, openCancelConfirmModal, closeCancelConfirmModal] = useToggle(false);
useEffect(() => {
const handleIframeMessage = (event) => {
@@ -25,9 +29,9 @@ const AdvancedEditor = ({ usageKey, onClose }: AdvancedEditorProps) => {
if (event.data.type === 'xblock-event') {
const { eventName, data } = event.data;
- if (onClose && (eventName === 'cancel'
- || (eventName === 'save' && data.state === 'end'))
- ) {
+ if (eventName === 'cancel') {
+ openCancelConfirmModal();
+ } else if (onClose && eventName === 'save' && data.state === 'end') {
onClose();
} else if (eventName === 'error') {
showToast(intl.formatMessage(messages.advancedEditorGenericError));
@@ -43,12 +47,19 @@ const AdvancedEditor = ({ usageKey, onClose }: AdvancedEditorProps) => {
}, []);
return (
- void}>
-
+
+
+
+
-
+ >
);
};
diff --git a/src/editors/containers/EditorContainer/components/CancelConfirmModal.tsx b/src/editors/containers/EditorContainer/components/CancelConfirmModal.tsx
new file mode 100644
index 000000000..a0860c0fc
--- /dev/null
+++ b/src/editors/containers/EditorContainer/components/CancelConfirmModal.tsx
@@ -0,0 +1,38 @@
+import { Button } from '@openedx/paragon';
+import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
+import BaseModal from '../../../sharedComponents/BaseModal';
+import messages from '../messages';
+
+interface CancelConfirmModalProps {
+ isOpen: boolean,
+ closeCancelConfirmModal: () => void,
+ onCloseEditor: (() => void) | null,
+}
+
+const CancelConfirmModal = ({
+ isOpen,
+ closeCancelConfirmModal,
+ onCloseEditor,
+}: CancelConfirmModalProps) => {
+ const intl = useIntl();
+ return (
+ onCloseEditor?.()}
+ >
+
+
+ )}
+ isOpen={isOpen}
+ close={closeCancelConfirmModal}
+ title={intl.formatMessage(messages.cancelConfirmTitle)}
+ >
+
+
+ );
+};
+
+export default CancelConfirmModal;
diff --git a/src/editors/containers/EditorContainer/index.tsx b/src/editors/containers/EditorContainer/index.tsx
index eb9e08ab2..bc22c360d 100644
--- a/src/editors/containers/EditorContainer/index.tsx
+++ b/src/editors/containers/EditorContainer/index.tsx
@@ -15,12 +15,12 @@ import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
import { EditorComponent } from '../../EditorComponent';
import { useEditorContext } from '../../EditorContext';
-import BaseModal from '../../sharedComponents/BaseModal';
import TitleHeader from './components/TitleHeader';
import * as hooks from './hooks';
import messages from './messages';
import './index.scss';
import usePromptIfDirty from '../../../generic/promptIfDirty/usePromptIfDirty';
+import CancelConfirmModal from './components/CancelConfirmModal';
interface WrapperProps {
children: React.ReactNode;
@@ -118,29 +118,16 @@ const EditorContainer: React.FC = ({
)}
- {
- handleCancel();
- if (returnFunction) {
- closeCancelConfirmModal();
- }
- }}
- >
-
-
- )}
+ {
- closeCancelConfirmModal();
+ closeCancelConfirmModal={closeCancelConfirmModal}
+ onCloseEditor={() => {
+ handleCancel();
+ if (returnFunction) {
+ closeCancelConfirmModal();
+ }
}}
- title={intl.formatMessage(messages.cancelConfirmTitle)}
- >
-
-
+ />