Files
frontend-app-authoring/src/library-authoring/LibraryBlock/LibraryBlock.tsx
Navin Karkera a43027b328 feat: library unit page skeleton [FC-0083] (#1779)
* View a unit page, which has its own URL
* Components appear within a unit as full previews. Their top bar shows type icon and title on the left, and draft status (if any), tag count, overflow menu, and drag handle on the right.
* Components have an overflow menu within a unit
* Components can be selected within a unit
* When components are selected, the standard component sidebar appears. The preview tab is hidden, since component previews are visible in the main content area.
* Components within a unit full-page view have hover and selected states
* Unit sidebar preview.
* Frontend implementation Drag-n-drop components to reorder them in unit.
2025-04-11 13:50:40 -05:00

72 lines
2.2 KiB
TypeScript

import { useIntl } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform';
import messages from './messages';
import { IFRAME_FEATURE_POLICY } from '../../constants';
import { useIframeBehavior } from '../../generic/hooks/useIframeBehavior';
import { useIframe } from '../../generic/hooks/context/hooks';
import { useIframeContent } from '../../generic/hooks/useIframeContent';
export type VersionSpec = 'published' | 'draft' | number;
interface LibraryBlockProps {
onBlockNotification?: (event: { eventType: string; [key: string]: any }) => void;
usageKey: string;
version?: VersionSpec;
view?: string;
scrolling?: string;
}
/**
* React component that displays an XBlock in a sandboxed IFrame.
*
* The IFrame is resized responsively so that it fits the content height.
*
* We use an IFrame so that the XBlock code, including user-authored HTML,
* cannot access things like the user's cookies, nor can it make GET/POST
* requests as the user. However, it is allowed to call any XBlock handlers.
*/
export const LibraryBlock = ({
onBlockNotification,
usageKey,
version,
view,
scrolling = 'no',
}: LibraryBlockProps) => {
const { iframeRef, setIframeRef } = useIframe();
const xblockView = view ?? 'student_view';
const studioBaseUrl = getConfig().STUDIO_BASE_URL;
const intl = useIntl();
const queryStr = version ? `?version=${version}` : '';
const iframeUrl = `${studioBaseUrl}/xblocks/v2/${usageKey}/embed/${xblockView}/${queryStr}`;
const { iframeHeight } = useIframeBehavior({
id: usageKey,
iframeUrl,
iframeRef,
onBlockNotification,
});
useIframeContent(iframeRef, setIframeRef);
return (
<iframe
ref={iframeRef}
title={intl.formatMessage(messages.iframeTitle)}
src={iframeUrl}
data-testid="block-preview"
name={`xblock-iframe-${usageKey}`}
id={`xblock-iframe-${usageKey}`}
frameBorder="0"
loading="lazy"
referrerPolicy="origin"
style={{
width: '100%', height: iframeHeight, pointerEvents: 'auto', minHeight: '700px',
}}
allow={IFRAME_FEATURE_POLICY}
allowFullScreen
scrolling={scrolling}
/>
);
};