diff --git a/src/constants.js b/src/constants.js
index bf4696d734..411d3f2486 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -78,5 +78,5 @@ export const REGEX_RULES = {
};
export const IFRAME_FEATURE_POLICY = (
- 'microphone *; camera *; midi *; geolocation *; encrypted-media *, clipboard-write *'
+ 'microphone *; camera *; midi *; geolocation *; encrypted-media *; clipboard-write *'
);
diff --git a/src/course-unit/CourseUnit.test.jsx b/src/course-unit/CourseUnit.test.jsx
index 8b13e30a60..6d64615de0 100644
--- a/src/course-unit/CourseUnit.test.jsx
+++ b/src/course-unit/CourseUnit.test.jsx
@@ -1687,15 +1687,11 @@ describe('', () => {
waitFor(() => {
const iframe = getByTitle(xblockContainerIframeMessages.xblockIframeTitle.defaultMessage);
- const currentXBlockId = courseVerticalChildrenMock.children[0].block_id;
+ const usageId = courseVerticalChildrenMock.children[0].block_id;
expect(iframe).toBeInTheDocument();
- simulatePostMessageEvent(messageTypes.currentXBlockId, {
- id: currentXBlockId,
- });
-
simulatePostMessageEvent(messageTypes.manageXBlockAccess, {
- id: currentXBlockId,
+ usageId,
});
});
@@ -1717,7 +1713,7 @@ describe('', () => {
const iframe = getByTitle(xblockContainerIframeMessages.xblockIframeTitle.defaultMessage);
expect(iframe).toBeInTheDocument();
simulatePostMessageEvent(messageTypes.manageXBlockAccess, {
- id: courseVerticalChildrenMock.children[0].block_id,
+ usageId: courseVerticalChildrenMock.children[0].block_id,
});
});
@@ -1752,7 +1748,7 @@ describe('', () => {
const iframe = getByTitle(xblockContainerIframeMessages.xblockIframeTitle.defaultMessage);
expect(iframe).toBeInTheDocument();
simulatePostMessageEvent(messageTypes.manageXBlockAccess, {
- id: courseVerticalChildrenMock.children[0].block_id,
+ usageId: courseVerticalChildrenMock.children[0].block_id,
});
});
@@ -1816,6 +1812,7 @@ describe('', () => {
waitFor(() => {
simulatePostMessageEvent(messageTypes.duplicateXBlock, {});
+ simulatePostMessageEvent(messageTypes.newXBlockEditor, {});
expect(mockedUsedNavigate)
.toHaveBeenCalledWith(`/course/${courseId}/editor/html/${targetBlockId}`, { replace: true });
});
diff --git a/src/course-unit/constants.js b/src/course-unit/constants.js
index 5c147be8f4..b19c7ba378 100644
--- a/src/course-unit/constants.js
+++ b/src/course-unit/constants.js
@@ -61,7 +61,6 @@ export const messageTypes = {
duplicateXBlock: 'duplicateXBlock',
refreshXBlockPositions: 'refreshPositions',
newXBlockEditor: 'newXBlockEditor',
- currentXBlockId: 'currentXBlockId',
toggleCourseXBlockDropdown: 'toggleCourseXBlockDropdown',
};
@@ -75,3 +74,9 @@ export const COMPONENT_TYPES = {
video: 'video',
dragAndDrop: 'drag-and-drop-v2',
};
+
+export const COMPONENT_TYPES_WITH_NEW_EDITOR = {
+ html: 'html',
+ problem: 'problem',
+ video: 'video',
+};
diff --git a/src/course-unit/xblock-container-iframe/hooks/index.ts b/src/course-unit/xblock-container-iframe/hooks/index.ts
new file mode 100644
index 0000000000..c49993dc1e
--- /dev/null
+++ b/src/course-unit/xblock-container-iframe/hooks/index.ts
@@ -0,0 +1,5 @@
+export { useIframeMessages } from './useIframeMessages';
+export { useIframeContent } from './useIframeContent';
+export { useMessageHandlers } from './useMessageHandlers';
+export { useIFrameBehavior } from './useIFrameBehavior';
+export { useLoadBearingHook } from './useLoadBearingHook';
diff --git a/src/course-unit/xblock-container-iframe/tests/hooks.test.tsx b/src/course-unit/xblock-container-iframe/hooks/tests/hooks.test.tsx
similarity index 97%
rename from src/course-unit/xblock-container-iframe/tests/hooks.test.tsx
rename to src/course-unit/xblock-container-iframe/hooks/tests/hooks.test.tsx
index 13b5467622..8883efb04d 100644
--- a/src/course-unit/xblock-container-iframe/tests/hooks.test.tsx
+++ b/src/course-unit/xblock-container-iframe/hooks/tests/hooks.test.tsx
@@ -3,8 +3,8 @@ import { renderHook, act } from '@testing-library/react-hooks';
import { useKeyedState } from '@edx/react-unit-test-utils';
import { logError } from '@edx/frontend-platform/logging';
-import { stateKeys, messageTypes } from '../../constants';
-import { useIFrameBehavior, useLoadBearingHook } from '../hooks';
+import { stateKeys, messageTypes } from '../../../constants';
+import { useLoadBearingHook, useIFrameBehavior } from '..';
jest.mock('@edx/react-unit-test-utils', () => ({
useKeyedState: jest.fn(),
diff --git a/src/course-unit/xblock-container-iframe/hooks/types.ts b/src/course-unit/xblock-container-iframe/hooks/types.ts
new file mode 100644
index 0000000000..3974656c49
--- /dev/null
+++ b/src/course-unit/xblock-container-iframe/hooks/types.ts
@@ -0,0 +1,25 @@
+export type UseMessageHandlersTypes = {
+ courseId: string;
+ navigate: (path: string) => void;
+ dispatch: (action: any) => void;
+ setIframeOffset: (height: number) => void;
+ handleDeleteXBlock: (usageId: string) => void;
+ handleRefetchXBlocks: () => void;
+ handleDuplicateXBlock: (blockType: string, usageId: string) => void;
+ handleManageXBlockAccess: (usageId: string) => void;
+};
+
+export type MessageHandlersTypes = Record void>;
+
+export interface UseIFrameBehaviorTypes {
+ id: string;
+ iframeUrl: string;
+ onLoaded?: boolean;
+}
+
+export interface UseIFrameBehaviorReturnTypes {
+ iframeHeight: number;
+ handleIFrameLoad: () => void;
+ showError: boolean;
+ hasLoaded: boolean;
+}
diff --git a/src/course-unit/xblock-container-iframe/hooks.tsx b/src/course-unit/xblock-container-iframe/hooks/useIFrameBehavior.tsx
similarity index 58%
rename from src/course-unit/xblock-container-iframe/hooks.tsx
rename to src/course-unit/xblock-container-iframe/hooks/useIFrameBehavior.tsx
index 1a81e7852a..832ac94cd3 100644
--- a/src/course-unit/xblock-container-iframe/hooks.tsx
+++ b/src/course-unit/xblock-container-iframe/hooks/useIFrameBehavior.tsx
@@ -1,57 +1,12 @@
-import {
- useState, useLayoutEffect, useCallback, useEffect,
-} from 'react';
+import { useCallback, useEffect } from 'react';
import { logError } from '@edx/frontend-platform/logging';
// eslint-disable-next-line import/no-extraneous-dependencies
import { useKeyedState } from '@edx/react-unit-test-utils';
-import { useEventListener } from '../../generic/hooks';
-import { stateKeys, messageTypes } from '../constants';
-
-interface UseIFrameBehaviorParams {
- id: string;
- iframeUrl: string;
- onLoaded?: boolean;
-}
-
-interface UseIFrameBehaviorReturn {
- iframeHeight: number;
- handleIFrameLoad: () => void;
- showError: boolean;
- hasLoaded: boolean;
-}
-
-/**
- * We discovered an error in Firefox where - upon iframe load - React would cease to call any
- * useEffect hooks until the user interacts with the page again. This is particularly confusing
- * when navigating between sequences, as the UI partially updates leaving the user in a nebulous
- * state.
- *
- * We were able to solve this error by using a layout effect to update some component state, which
- * executes synchronously on render. Somehow this forces React to continue it's lifecycle
- * immediately, rather than waiting for user interaction. This layout effect could be anywhere in
- * the parent tree, as far as we can tell - we chose to add a conspicuously 'load bearing' (that's
- * a joke) one here so it wouldn't be accidentally removed elsewhere.
- *
- * If we remove this hook when one of these happens:
- * 1. React figures out that there's an issue here and fixes a bug.
- * 2. We cease to use an iframe for unit rendering.
- * 3. Firefox figures out that there's an issue in their iframe loading and fixes a bug.
- * 4. We stop supporting Firefox.
- * 5. An enterprising engineer decides to create a repo that reproduces the problem, submits it to
- * Firefox/React for review, and they kindly help us figure out what in the world is happening
- * so we can fix it.
- *
- * This hook depends on the unit id just to make sure it re-evaluates whenever the ID changes. If
- * we change whether or not the Unit component is re-mounted when the unit ID changes, this may
- * become important, as this hook will otherwise only evaluate the useLayoutEffect once.
- */
-export const useLoadBearingHook = (id: string): void => {
- const setValue = useState(0)[1];
- useLayoutEffect(() => {
- setValue(currentValue => currentValue + 1);
- }, [id]);
-};
+import { useEventListener } from '../../../generic/hooks';
+import { stateKeys, messageTypes } from '../../constants';
+import { useLoadBearingHook } from './useLoadBearingHook';
+import { UseIFrameBehaviorTypes, UseIFrameBehaviorReturnTypes } from './types';
/**
* Custom hook to manage iframe behavior.
@@ -70,7 +25,7 @@ export const useIFrameBehavior = ({
id,
iframeUrl,
onLoaded = true,
-}: UseIFrameBehaviorParams): UseIFrameBehaviorReturn => {
+}: UseIFrameBehaviorTypes): UseIFrameBehaviorReturnTypes => {
// Do not remove this hook. See function description.
useLoadBearingHook(id);
diff --git a/src/course-unit/xblock-container-iframe/hooks/useIframeContent.tsx b/src/course-unit/xblock-container-iframe/hooks/useIframeContent.tsx
new file mode 100644
index 0000000000..abbc98b212
--- /dev/null
+++ b/src/course-unit/xblock-container-iframe/hooks/useIframeContent.tsx
@@ -0,0 +1,33 @@
+import { useEffect, useCallback, RefObject } from 'react';
+
+import { messageTypes } from '../../constants';
+
+/**
+ * Hook for managing iframe content and providing utilities to interact with the iframe.
+ *
+ * @param {React.RefObject} iframeRef - A React ref for the iframe element.
+ * @param {(ref: React.RefObject) => void} setIframeRef -
+ * A function to associate the iframeRef with the parent context.
+ * @param {(type: string, payload: any) => void} sendMessageToIframe - A function to send messages to the iframe.
+ *
+ * @returns {Object} - An object containing utility functions.
+ * @returns {() => void} return.refreshIframeContent -
+ * A function to refresh the iframe content by sending a specific message.
+ */
+export const useIframeContent = (
+ iframeRef: RefObject,
+ setIframeRef: (ref: RefObject) => void,
+ sendMessageToIframe: (type: string, payload: any) => void,
+): { refreshIframeContent: () => void } => {
+ useEffect(() => {
+ setIframeRef(iframeRef);
+ }, [setIframeRef, iframeRef]);
+
+ // TODO: this artificial delay is a temporary solution
+ // to ensure the iframe content is properly refreshed.
+ const refreshIframeContent = useCallback(() => {
+ setTimeout(() => sendMessageToIframe(messageTypes.refreshXBlock, null), 1000);
+ }, [sendMessageToIframe]);
+
+ return { refreshIframeContent };
+};
diff --git a/src/course-unit/xblock-container-iframe/hooks/useIframeMessages.tsx b/src/course-unit/xblock-container-iframe/hooks/useIframeMessages.tsx
new file mode 100644
index 0000000000..fd30063129
--- /dev/null
+++ b/src/course-unit/xblock-container-iframe/hooks/useIframeMessages.tsx
@@ -0,0 +1,21 @@
+import { useEffect } from 'react';
+
+/**
+ * Hook for managing and handling messages received by the iframe.
+ *
+ * @param {Record void>} messageHandlers -
+ * A mapping of message types to their corresponding handler functions.
+ */
+export const useIframeMessages = (messageHandlers: Record void>) => {
+ useEffect(() => {
+ const handleMessage = (event: MessageEvent) => {
+ const { type, payload } = event.data || {};
+ console.log('event.data ===============>', event.data);
+ if (type in messageHandlers) {
+ messageHandlers[type](payload);
+ }
+ };
+ window.addEventListener('message', handleMessage);
+ return () => window.removeEventListener('message', handleMessage);
+ }, [messageHandlers]);
+};
diff --git a/src/course-unit/xblock-container-iframe/hooks/useLoadBearingHook.tsx b/src/course-unit/xblock-container-iframe/hooks/useLoadBearingHook.tsx
new file mode 100644
index 0000000000..73a38b0223
--- /dev/null
+++ b/src/course-unit/xblock-container-iframe/hooks/useLoadBearingHook.tsx
@@ -0,0 +1,33 @@
+import { useLayoutEffect, useState } from 'react';
+
+/**
+ * We discovered an error in Firefox where - upon iframe load - React would cease to call any
+ * useEffect hooks until the user interacts with the page again. This is particularly confusing
+ * when navigating between sequences, as the UI partially updates leaving the user in a nebulous
+ * state.
+ *
+ * We were able to solve this error by using a layout effect to update some component state, which
+ * executes synchronously on render. Somehow this forces React to continue it's lifecycle
+ * immediately, rather than waiting for user interaction. This layout effect could be anywhere in
+ * the parent tree, as far as we can tell - we chose to add a conspicuously 'load bearing' (that's
+ * a joke) one here so it wouldn't be accidentally removed elsewhere.
+ *
+ * If we remove this hook when one of these happens:
+ * 1. React figures out that there's an issue here and fixes a bug.
+ * 2. We cease to use an iframe for unit rendering.
+ * 3. Firefox figures out that there's an issue in their iframe loading and fixes a bug.
+ * 4. We stop supporting Firefox.
+ * 5. An enterprising engineer decides to create a repo that reproduces the problem, submits it to
+ * Firefox/React for review, and they kindly help us figure out what in the world is happening
+ * so we can fix it.
+ *
+ * This hook depends on the unit id just to make sure it re-evaluates whenever the ID changes. If
+ * we change whether or not the Unit component is re-mounted when the unit ID changes, this may
+ * become important, as this hook will otherwise only evaluate the useLayoutEffect once.
+ */
+export const useLoadBearingHook = (id: string): void => {
+ const setValue = useState(0)[1];
+ useLayoutEffect(() => {
+ setValue(currentValue => currentValue + 1);
+ }, [id]);
+};
diff --git a/src/course-unit/xblock-container-iframe/hooks/useMessageHandlers.tsx b/src/course-unit/xblock-container-iframe/hooks/useMessageHandlers.tsx
new file mode 100644
index 0000000000..974f7bf0c6
--- /dev/null
+++ b/src/course-unit/xblock-container-iframe/hooks/useMessageHandlers.tsx
@@ -0,0 +1,38 @@
+import { useMemo } from 'react';
+
+import { copyToClipboard } from '../../../generic/data/thunks';
+import { messageTypes } from '../../constants';
+import { MessageHandlersTypes, UseMessageHandlersTypes } from './types';
+
+/**
+ * Hook for creating message handlers used to handle iframe messages.
+ *
+ * @param params - The parameters required to create message handlers.
+ * @returns {MessageHandlersTypes} - An object mapping message types to their handler functions.
+ */
+export const useMessageHandlers = ({
+ courseId,
+ navigate,
+ dispatch,
+ setIframeOffset,
+ handleDeleteXBlock,
+ handleRefetchXBlocks,
+ handleDuplicateXBlock,
+ handleManageXBlockAccess,
+}: UseMessageHandlersTypes): MessageHandlersTypes => useMemo(() => ({
+ [messageTypes.copyXBlock]: ({ usageId }) => dispatch(copyToClipboard(usageId)),
+ [messageTypes.deleteXBlock]: ({ usageId }) => handleDeleteXBlock(usageId),
+ [messageTypes.newXBlockEditor]: ({ blockType, usageId }) => navigate(`/course/${courseId}/editor/${blockType}/${usageId}`),
+ [messageTypes.duplicateXBlock]: ({ blockType, usageId }) => handleDuplicateXBlock(blockType, usageId),
+ [messageTypes.manageXBlockAccess]: ({ usageId }) => handleManageXBlockAccess(usageId),
+ [messageTypes.refreshXBlockPositions]: handleRefetchXBlocks,
+ [messageTypes.toggleCourseXBlockDropdown]: ({
+ courseXBlockDropdownHeight,
+ }: { courseXBlockDropdownHeight: number }) => setIframeOffset(courseXBlockDropdownHeight),
+}), [
+ courseId,
+ handleDeleteXBlock,
+ handleRefetchXBlocks,
+ handleDuplicateXBlock,
+ handleManageXBlockAccess,
+]);
diff --git a/src/course-unit/xblock-container-iframe/index.tsx b/src/course-unit/xblock-container-iframe/index.tsx
index b26ae8e0ed..854abefc16 100644
--- a/src/course-unit/xblock-container-iframe/index.tsx
+++ b/src/course-unit/xblock-container-iframe/index.tsx
@@ -2,25 +2,28 @@ import {
useRef, FC, useEffect, useState, useMemo, useCallback,
} from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
-import { getConfig } from '@edx/frontend-platform';
import { useToggle } from '@openedx/paragon';
import { useDispatch } from 'react-redux';
import { useNavigate } from 'react-router-dom';
import DeleteModal from '../../generic/delete-modal/DeleteModal';
import ConfigureModal from '../../generic/configure-modal/ConfigureModal';
-import { copyToClipboard } from '../../generic/data/thunks';
-import { COURSE_BLOCK_NAMES, IFRAME_FEATURE_POLICY } from '../../constants';
-import { messageTypes, COMPONENT_TYPES } from '../constants';
+import { IFRAME_FEATURE_POLICY } from '../../constants';
+import { COMPONENT_TYPES_WITH_NEW_EDITOR } from '../constants';
import { fetchCourseUnitQuery } from '../data/thunk';
import { useIframe } from '../context/hooks';
-import { useIFrameBehavior } from './hooks';
+import {
+ useMessageHandlers,
+ useIframeContent,
+ useIframeMessages,
+ useIFrameBehavior,
+} from './hooks';
+import { formatAccessManagedXBlockData, getIframeUrl } from './utils';
import messages from './messages';
import {
XBlockContainerIframeProps,
- XBlockDataTypes,
- MessagePayloadTypes,
+ AccessManagedXBlockDataTypes,
} from './types';
const XBlockContainerIframe: FC = ({
@@ -33,133 +36,102 @@ const XBlockContainerIframe: FC = ({
const [isDeleteModalOpen, openDeleteModal, closeDeleteModal] = useToggle(false);
const [isConfigureModalOpen, openConfigureModal, closeConfigureModal] = useToggle(false);
- const { setIframeRef, sendMessageToIframe } = useIframe();
- const [currentXBlockId, setCurrentXBlockId] = useState(null);
- const [currentXBlockData, setCurrentXBlockData] = useState({});
- const [courseXBlockIframeOffset, setCourseXBlockIframeOffset] = useState(0);
+ const [accessManagedXBlockData, setAccessManagedXBlockData] = useState({});
+ const [iframeOffset, setIframeOffset] = useState(0);
+ const [deleteXBlockId, setDeleteXBlockId] = useState(null);
+ const [configureXBlockId, setConfigureXBlockId] = useState(null);
- const iframeUrl = useMemo(() => `${getConfig().STUDIO_BASE_URL}/container_embed/${blockId}`, [blockId]);
+ const iframeUrl = useMemo(() => getIframeUrl(blockId), [blockId]);
+
+ const { setIframeRef, sendMessageToIframe } = useIframe();
+ const { iframeHeight } = useIFrameBehavior({ id: blockId, iframeUrl });
+ const { refreshIframeContent } = useIframeContent(iframeRef, setIframeRef, sendMessageToIframe);
useEffect(() => {
setIframeRef(iframeRef);
}, [setIframeRef]);
- useEffect(() => {
- if (currentXBlockId) {
- const foundXBlockInfo = courseVerticalChildren?.find(xblock => xblock.blockId === currentXBlockId);
- if (foundXBlockInfo) {
- const { name, userPartitionInfo, blockType } = foundXBlockInfo;
-
- setCurrentXBlockData({
- category: COURSE_BLOCK_NAMES.component.id,
- displayName: name,
- userPartitionInfo,
- showCorrectness: 'always',
- blockType,
- id: currentXBlockId,
- });
- }
- }
- }, [isConfigureModalOpen, currentXBlockId, courseVerticalChildren]);
-
- const handleRefreshIframe = useCallback(() => {
- // TODO: this artificial delay is a temporary solution
- // to ensure the iframe content is properly refreshed.
- setTimeout(() => {
- sendMessageToIframe(messageTypes.refreshXBlock, null);
- }, 1000);
- }, [sendMessageToIframe]);
-
const handleDuplicateXBlock = useCallback(
- (xblockData: XBlockDataTypes) => {
- const duplicateAndNavigate = (blockType: string) => {
- unitXBlockActions.handleDuplicate(xblockData.id);
- if ([COMPONENT_TYPES.html, COMPONENT_TYPES.problem, COMPONENT_TYPES.video].includes(blockType)) {
- navigate(`/course/${courseId}/editor/${blockType}/${xblockData.id}`);
- }
- handleRefreshIframe();
- };
-
- duplicateAndNavigate(xblockData.blockType);
+ (blockType: string, usageId: string) => {
+ unitXBlockActions.handleDuplicate(usageId);
+ if (COMPONENT_TYPES_WITH_NEW_EDITOR[blockType]) {
+ navigate(`/course/${courseId}/editor/${blockType}/${usageId}`);
+ }
+ refreshIframeContent();
},
- [unitXBlockActions, courseId, navigate, handleRefreshIframe],
+ [unitXBlockActions, courseId, navigate, refreshIframeContent],
);
- const handleRefetchXBlocks = useCallback(() => {
- // TODO: this artificial delay is a temporary solution
- // to ensure the iframe content is properly refreshed.
- setTimeout(() => {
- dispatch(fetchCourseUnitQuery(blockId));
- }, 1000);
- }, [dispatch, blockId]);
-
- useEffect(() => {
- const messageHandlers: Record void> = {
- [messageTypes.deleteXBlock]: openDeleteModal,
- [messageTypes.manageXBlockAccess]: () => openConfigureModal(),
- [messageTypes.copyXBlock]: () => dispatch(copyToClipboard(currentXBlockId)),
- [messageTypes.duplicateXBlock]: () => handleDuplicateXBlock(currentXBlockData),
- [messageTypes.refreshXBlockPositions]: handleRefetchXBlocks,
- [messageTypes.newXBlockEditor]: ({ url }) => navigate(`/course/${courseId}/editor${url}`),
- [messageTypes.currentXBlockId]: ({ id }) => setCurrentXBlockId(id),
- [messageTypes.toggleCourseXBlockDropdown]: ({
- courseXBlockDropdownHeight,
- }) => setCourseXBlockIframeOffset(courseXBlockDropdownHeight),
- };
-
- const handleMessage = (event: MessageEvent) => {
- const { type, payload } = event.data || {};
-
- if (type && messageHandlers[type]) {
- messageHandlers[type](payload);
- }
- };
-
- window.addEventListener('message', handleMessage);
+ const handleDeleteXBlock = (usageId: string) => {
+ setDeleteXBlockId(usageId);
+ openDeleteModal();
+ };
- return () => {
- window.removeEventListener('message', handleMessage);
- };
- }, [dispatch, blockId, courseVerticalChildren, currentXBlockId, currentXBlockData]);
+ const handleManageXBlockAccess = (usageId: string) => {
+ openConfigureModal();
+ setConfigureXBlockId(usageId);
+ const foundXBlock = courseVerticalChildren?.find(xblock => xblock.blockId === usageId);
+ console.log('================================ foundXBlock =================================', foundXBlock);
+ if (foundXBlock) {
+ console.log('================================ HELOOO =================================');
+ setAccessManagedXBlockData(formatAccessManagedXBlockData(foundXBlock, usageId));
+ }
+ };
- const { iframeHeight } = useIFrameBehavior({
- id: blockId,
- iframeUrl,
- });
+ const handleRefetchXBlocks = useCallback(() => {
+ setTimeout(() => dispatch(fetchCourseUnitQuery(blockId)), 1000);
+ }, [dispatch, blockId]);
- const handleDeleteItemSubmit = () => {
- if (currentXBlockId) {
- unitXBlockActions.handleDelete(currentXBlockId);
+ const onDeleteSubmit = () => {
+ if (deleteXBlockId) {
+ unitXBlockActions.handleDelete(deleteXBlockId);
closeDeleteModal();
- handleRefreshIframe();
+ refreshIframeContent();
}
};
- const onConfigureSubmit = (...args: any[]) => {
- if (currentXBlockId) {
- handleConfigureSubmit(currentXBlockId, ...args, closeConfigureModal);
- handleRefreshIframe();
+ const onManageXBlockAccessSubmit = (...args: any[]) => {
+ if (configureXBlockId) {
+ handleConfigureSubmit(configureXBlockId, ...args, closeConfigureModal);
+ setAccessManagedXBlockData({});
+ refreshIframeContent();
}
};
+ const messageHandlers = useMessageHandlers({
+ courseId,
+ navigate,
+ dispatch,
+ setIframeOffset,
+ handleDeleteXBlock,
+ handleRefetchXBlocks,
+ handleDuplicateXBlock,
+ handleManageXBlockAccess,
+ });
+
+ useIframeMessages(messageHandlers);
+
return (
<>
- {currentXBlockId && (
+ {Object.keys(accessManagedXBlockData).length ? (
{
+ closeConfigureModal();
+ setAccessManagedXBlockData({});
+ }}
+ onConfigureSubmit={onManageXBlockAccessSubmit}
+ currentItemData={accessManagedXBlockData as AccessManagedXBlockDataTypes}
isSelfPaced={false}
/>
- )}
+ ) : null}