feat: handle edit modals from advanced xblocks (#1445)

Adds new message types, updates message handlers, and implements a new modal iframe for legacy XBlock editing.
This commit is contained in:
Peter Kulko
2025-02-20 12:05:48 -08:00
committed by GitHub
parent 2befd82e51
commit 7e4ecff4e8
15 changed files with 353 additions and 25 deletions

View File

@@ -0,0 +1,34 @@
import { render } from '@testing-library/react';
import { IFRAME_FEATURE_POLICY } from '../../constants';
import ModalIframe, { SANDBOX_OPTIONS } from '.';
describe('ModalIframe Component', () => {
const title = 'Legacy Edit Modal';
const src = 'edit/xblock';
it('renders without crashing', async () => {
const { getByRole } = render(<ModalIframe title={title} src={src} />);
expect(getByRole('dialog')).toBeInTheDocument();
});
it('renders iframe with correct src', () => {
const { getByTitle } = render(<ModalIframe title={title} src={src} />);
const iframe = getByTitle(title);
expect(iframe).toBeInTheDocument();
expect(iframe).toHaveAttribute('src', src);
expect(iframe).toHaveAttribute('allow', IFRAME_FEATURE_POLICY);
expect(iframe).toHaveAttribute('class', 'modal-iframe');
expect(iframe).toHaveAttribute('referrerpolicy', 'origin');
expect(iframe).toHaveAttribute('sandbox', SANDBOX_OPTIONS);
expect(iframe).toHaveAttribute('scrolling', 'no');
});
it('does not render when showLegacyEditModal is false', () => {
const { container } = render(<ModalIframe title={title} src={src} />);
expect(container.firstChild).not.toBeNull();
});
});

View File

@@ -0,0 +1,13 @@
.modal-iframe {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: $zindex-modal;
iframe {
width: inherit;
height: inherit;
}
}

View File

@@ -0,0 +1,43 @@
import { forwardRef, ForwardedRef, IframeHTMLAttributes } from 'react';
import classNames from 'classnames';
import { IFRAME_FEATURE_POLICY } from '../../constants';
interface ModalIframeProps extends IframeHTMLAttributes<HTMLIFrameElement> {
title: string;
className?: string;
}
export const SANDBOX_OPTIONS = [
'allow-forms',
'allow-modals',
'allow-popups',
'allow-popups-to-escape-sandbox',
'allow-presentation',
'allow-same-origin',
'allow-scripts',
'allow-top-navigation-by-user-activation',
].join(' ');
const ModalIframe = forwardRef<HTMLIFrameElement, ModalIframeProps>(
({ title, className, ...props }, ref: ForwardedRef<HTMLIFrameElement>) => (
<iframe
title={title}
className={classNames('modal-iframe', className)}
allow={IFRAME_FEATURE_POLICY}
referrerPolicy="origin"
frameBorder="0"
scrolling="no"
ref={ref}
role="dialog"
sandbox={SANDBOX_OPTIONS}
{...props}
/>
),
);
ModalIframe.defaultProps = {
className: '',
};
export default ModalIframe;

View File

@@ -39,6 +39,7 @@ const SavingErrorAlert = ({
<AlertMessage
show={showAlert}
variant="danger"
data-testid="saving-error-alert"
icon={WarningIcon}
title={intl.formatMessage(messages.warningTitle)}
description={

View File

@@ -13,3 +13,4 @@
@import "./configure-modal/ConfigureModal";
@import "./drag-helper/SortableItem";
@import "./block-type-utils";
@import "./modal-iframe"