Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions src/editors/AdvancedEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import React, { useEffect } from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useToggle } from '@openedx/paragon';
import {
ActionRow,
Icon,
IconButton,
ModalDialog,
ModalCloseButton,
Stack,
useToggle,
} from '@openedx/paragon';
import { Close, CloseFullscreen, OpenInFull } from '@openedx/paragon/icons';

import { LibraryBlock } from '../library-authoring/LibraryBlock';
import { EditorModalWrapper } from './containers/EditorContainer';
Expand All @@ -11,6 +20,8 @@ import messages from './messages';
import CancelConfirmModal from './containers/EditorContainer/components/CancelConfirmModal';
import { IframeProvider } from '../generic/hooks/context/iFrameContext';

import editorModalWrapperMessages from './containers/EditorContainer/messages';

interface AdvancedEditorProps {
usageKey: string,
onClose: (() => void) | null,
Expand All @@ -20,6 +31,7 @@ const AdvancedEditor = ({ usageKey, onClose }: AdvancedEditorProps) => {
const intl = useIntl();
const { showToast } = React.useContext(ToastContext);
const [isCancelConfirmOpen, openCancelConfirmModal, closeCancelConfirmModal] = useToggle(false);
const [isFullscreen, , , toggleFullscreen] = useToggle(false);

useEffect(() => {
const handleIframeMessage = (event) => {
Expand Down Expand Up @@ -49,7 +61,28 @@ const AdvancedEditor = ({ usageKey, onClose }: AdvancedEditorProps) => {

return (
<>
<EditorModalWrapper onClose={openCancelConfirmModal}>
<EditorModalWrapper onClose={openCancelConfirmModal} fullscreen={isFullscreen}>
<ModalDialog.Header>
<ActionRow>
<ModalDialog.Title>
{intl.formatMessage(editorModalWrapperMessages.modalTitle)}
</ModalDialog.Title>
<ActionRow.Spacer />
<Stack direction="horizontal" reversed gap={1}>
<ModalCloseButton
as={IconButton}
src={Close}
iconAs={Icon}
/>
<IconButton
src={isFullscreen ? CloseFullscreen : OpenInFull}
iconAs={Icon}
alt={intl.formatMessage(messages.advancedEditorFullscreenButtonAlt)}
onClick={toggleFullscreen}
/>
</Stack>
</ActionRow>
</ModalDialog.Header>
<IframeProvider>
<LibraryBlock
usageKey={usageKey}
Expand Down
68 changes: 50 additions & 18 deletions src/editors/containers/EditorContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,57 @@ import {
IconButton,
ModalDialog,
Spinner,
Stack,
Toast,
useToggle,
} from '@openedx/paragon';
import { Close } from '@openedx/paragon/icons';
import { Close, CloseFullscreen, OpenInFull } from '@openedx/paragon/icons';
import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';

import { parseErrorMsg } from '@src/library-authoring/add-content/AddContent';
import libraryMessages from '@src/library-authoring/add-content/messages';
import usePromptIfDirty from '@src/generic/promptIfDirty/usePromptIfDirty';

import { EditorComponent } from '../../EditorComponent';
import TitleHeader from './components/TitleHeader';
import * as hooks from './hooks';
import messages from './messages';
import { parseErrorMsg } from '../../../library-authoring/add-content/AddContent';
import libraryMessages from '../../../library-authoring/add-content/messages';

import './index.scss';
import usePromptIfDirty from '../../../generic/promptIfDirty/usePromptIfDirty';
import CancelConfirmModal from './components/CancelConfirmModal';

interface WrapperProps {
children: React.ReactNode;
}

export const EditorModalWrapper: React.FC<WrapperProps & { onClose: () => void }> = ({ children, onClose }) => {
export const EditorModalWrapper: React.FC<WrapperProps & { onClose: () => void, fullscreen?: boolean }> = (
{
children,
onClose,
fullscreen = false,
},
) => {
const intl = useIntl();

const title = intl.formatMessage(messages.modalTitle);
return (
<ModalDialog isOpen size="xl" isOverflowVisible={false} onClose={onClose} title={title}>{children}</ModalDialog>
<ModalDialog
isOpen
onClose={onClose}
title={title}
size={fullscreen ? 'fullscreen' : 'xl'}
isOverflowVisible={false}
hasCloseButton={false}
>
{children}
</ModalDialog>
);
};

export const EditorModalBody: React.FC<WrapperProps> = ({ children }) => <ModalDialog.Body className="pb-0">{ children }</ModalDialog.Body>;
export const EditorModalBody: React.FC<WrapperProps> = ({ children }) => <ModalDialog.Body className="pb-0">{children}</ModalDialog.Body>;

// eslint-disable-next-line react/jsx-no-useless-fragment
export const FooterWrapper: React.FC<WrapperProps> = ({ children }) => <>{ children }</>;
export const FooterWrapper: React.FC<WrapperProps> = ({ children }) => <>{children}</>;

interface Props extends EditorComponent {
children: React.ReactNode;
Expand All @@ -63,6 +81,7 @@ const EditorContainer: React.FC<Props> = ({
const [saved, setSaved] = React.useState(false);
const isInitialized = hooks.isInitialized();
const { isCancelConfirmOpen, openCancelConfirmModal, closeCancelConfirmModal } = hooks.cancelConfirmModalToggle();
const [isFullscreen, , , toggleFullscreen] = useToggle(false);
const handleCancel = hooks.handleCancel({ onClose, returnFunction });
const { createFailed, createFailedError } = hooks.createFailed();
const disableSave = !isInitialized;
Expand Down Expand Up @@ -97,8 +116,9 @@ const EditorContainer: React.FC<Props> = ({
handleCancel();
}
};

return (
<EditorModalWrapper onClose={confirmCancelIfDirty}>
<EditorModalWrapper onClose={confirmCancelIfDirty} fullscreen={isFullscreen}>
{createFailed && (
<Toast show onClose={clearCreateFailed}>
{parseErrorMsg(
Expand Down Expand Up @@ -127,15 +147,27 @@ const EditorContainer: React.FC<Props> = ({
/>
<ModalDialog.Header className="shadow-sm zindex-10">
<div className="d-flex flex-row justify-content-between">
<h2 className="h3 col pl-0">
<TitleHeader isInitialized={isInitialized} />
</h2>
<IconButton
src={Close}
iconAs={Icon}
onClick={confirmCancelIfDirty}
alt={intl.formatMessage(messages.exitButtonAlt)}
/>
<ActionRow>
<h2 className="h3 col pl-0">
<TitleHeader isInitialized={isInitialized} />
</h2>
<ActionRow.Spacer />
<Stack direction="horizontal" reversed gap={1}>
<IconButton
src={Close}
iconAs={Icon}
onClick={confirmCancelIfDirty}
alt={intl.formatMessage(messages.exitButtonAlt)}
autoFocus
/>
<IconButton
src={isFullscreen ? CloseFullscreen : OpenInFull}
iconAs={Icon}
alt={intl.formatMessage(messages.toggleFullscreenButtonLabel)}
onClick={toggleFullscreen}
/>
</Stack>
</ActionRow>
</div>
</ModalDialog.Header>
<EditorModalBody>
Expand Down
6 changes: 5 additions & 1 deletion src/editors/containers/EditorContainer/messages.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';

const messages = defineMessages({

cancelConfirmTitle: {
id: 'authoring.editorContainer.cancelConfirm.title',
defaultMessage: 'Exit the editor?',
Expand Down Expand Up @@ -57,6 +56,11 @@ const messages = defineMessages({
defaultMessage: 'Save',
description: 'Label for Save button',
},
toggleFullscreenButtonLabel: {
id: 'authoring.editorHeader.toggleFullscreen.label',
defaultMessage: 'Toggle Fullscreen',
description: 'Label for toggle fullscreen button',
},
});

export default messages;
5 changes: 5 additions & 0 deletions src/editors/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ const messages = defineMessages({
defaultMessage: 'An unexpected error occurred in the editor',
description: 'Generic error message shown when an error occurs in the Advanced Editor.',
},
advancedEditorFullscreenButtonAlt: {
id: 'authoring.advancedEditor.fullscreenButton.alt',
defaultMessage: 'Toggle Fullscreen',
description: 'Alt text for the Fullscreen button',
},
});

export default messages;
10 changes: 5 additions & 5 deletions src/generic/modal-iframe/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ export const SANDBOX_OPTIONS = [
].join(' ');

const ModalIframe = forwardRef<HTMLIFrameElement, ModalIframeProps>(
({ title, className, ...props }, ref: ForwardedRef<HTMLIFrameElement>) => (
({
title,
className = '',
...props
}, ref: ForwardedRef<HTMLIFrameElement>) => (
<iframe
title={title}
className={classNames('modal-iframe', className)}
Expand All @@ -36,8 +40,4 @@ const ModalIframe = forwardRef<HTMLIFrameElement, ModalIframeProps>(
),
);

ModalIframe.defaultProps = {
className: '',
};

export default ModalIframe;
6 changes: 4 additions & 2 deletions src/library-authoring/components/ComponentEditorModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { getConfig } from '@edx/frontend-platform';
import React from 'react';

import { useQueryClient } from '@tanstack/react-query';
import EditorPage from '../../editors/EditorPage';
import { getBlockType } from '../../generic/key-utils';

import EditorPage from '@src/editors/EditorPage';
import { getBlockType } from '@src/generic/key-utils';

import { useLibraryContext } from '../common/context/LibraryContext';
import { invalidateComponentData } from '../data/apiHooks';

Expand Down