From a06651ce2ef090834bd921f7763dde5745006d55 Mon Sep 17 00:00:00 2001
From: ihor-romaniuk <ihor.romaniuk@raccoongang.com>
Date: Wed, 16 Oct 2024 13:54:47 +0200
Subject: [PATCH] feat: [FC-0070] implement move xblock modal

---
 src/CourseAuthoringRoutes.jsx                 |    4 +-
 src/constants.js                              |    2 +
 src/course-unit/CourseUnit.jsx                |   57 +-
 src/course-unit/CourseUnit.scss               |    1 +
 src/course-unit/CourseUnit.test.jsx           |  284 ++-
 .../__mocks__/courseOutlineInfo.js            | 1683 +++++++++++++++++
 src/course-unit/__mocks__/index.js            |    1 +
 src/course-unit/constants.js                  |    2 +
 src/course-unit/context/hooks.test.tsx        |   24 +
 src/course-unit/context/hooks.tsx             |   12 +
 src/course-unit/context/iFrameContext.tsx     |   42 +
 src/course-unit/data/api.js                   |   49 +
 src/course-unit/data/selectors.js             |    3 +
 src/course-unit/data/slice.js                 |   21 +
 src/course-unit/data/thunk.js                 |   58 +
 src/course-unit/header-title/HeaderTitle.jsx  |    1 +
 src/course-unit/hooks.jsx                     |   60 +-
 src/course-unit/index.js                      |    1 +
 src/course-unit/messages.js                   |   30 +
 .../components/CategoryIndicator.tsx          |   26 +
 .../move-modal/components/EmptyMessage.tsx    |   17 +
 .../move-modal/components/ModalLoader.tsx     |    9 +
 .../move-modal/components/index.ts            |    3 +
 src/course-unit/move-modal/constants.ts       |   41 +
 src/course-unit/move-modal/hooks.tsx          |  234 +++
 src/course-unit/move-modal/index.scss         |   79 +
 src/course-unit/move-modal/index.tsx          |  164 ++
 src/course-unit/move-modal/interfaces.ts      |   82 +
 src/course-unit/move-modal/messages.ts        |   81 +
 src/course-unit/move-modal/moveModal.test.tsx |  182 ++
 src/course-unit/move-modal/utils.test.ts      |  175 ++
 src/course-unit/move-modal/utils.ts           |  116 ++
 .../xblock-container-iframe/index.tsx         |    8 +-
 .../tests/XblockContainerIframe.test.tsx      |    5 +-
 34 files changed, 3535 insertions(+), 22 deletions(-)
 create mode 100644 src/course-unit/__mocks__/courseOutlineInfo.js
 create mode 100644 src/course-unit/context/hooks.test.tsx
 create mode 100644 src/course-unit/context/hooks.tsx
 create mode 100644 src/course-unit/context/iFrameContext.tsx
 create mode 100644 src/course-unit/move-modal/components/CategoryIndicator.tsx
 create mode 100644 src/course-unit/move-modal/components/EmptyMessage.tsx
 create mode 100644 src/course-unit/move-modal/components/ModalLoader.tsx
 create mode 100644 src/course-unit/move-modal/components/index.ts
 create mode 100644 src/course-unit/move-modal/constants.ts
 create mode 100644 src/course-unit/move-modal/hooks.tsx
 create mode 100644 src/course-unit/move-modal/index.scss
 create mode 100644 src/course-unit/move-modal/index.tsx
 create mode 100644 src/course-unit/move-modal/interfaces.ts
 create mode 100644 src/course-unit/move-modal/messages.ts
 create mode 100644 src/course-unit/move-modal/moveModal.test.tsx
 create mode 100644 src/course-unit/move-modal/utils.test.ts
 create mode 100644 src/course-unit/move-modal/utils.ts

diff --git a/src/CourseAuthoringRoutes.jsx b/src/CourseAuthoringRoutes.jsx
index 0c9d2a1680..ded2f07eae 100644
--- a/src/CourseAuthoringRoutes.jsx
+++ b/src/CourseAuthoringRoutes.jsx
@@ -17,7 +17,7 @@ import ScheduleAndDetails from './schedule-and-details';
 import { GradingSettings } from './grading-settings';
 import CourseTeam from './course-team/CourseTeam';
 import { CourseUpdates } from './course-updates';
-import { CourseUnit } from './course-unit';
+import { CourseUnit, IframeProvider } from './course-unit';
 import { Certificates } from './certificates';
 import CourseExportPage from './export-page/CourseExportPage';
 import CourseImportPage from './import-page/CourseImportPage';
@@ -79,7 +79,7 @@ const CourseAuthoringRoutes = () => {
           <Route
             key={path}
             path={path}
-            element={<PageWrap><CourseUnit courseId={courseId} /></PageWrap>}
+            element={<PageWrap><IframeProvider><CourseUnit courseId={courseId} /></IframeProvider></PageWrap>}
           />
         ))}
         <Route
diff --git a/src/constants.js b/src/constants.js
index f9e84c19de..163a16ef84 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -27,6 +27,8 @@ export const NOTIFICATION_MESSAGES = {
   copying: 'Copying',
   pasting: 'Pasting',
   discardChanges: 'Discarding changes',
+  moving: 'Moving',
+  undoMoving: 'Undo moving',
   publishing: 'Publishing',
   hidingFromStudents: 'Hiding from students',
   makingVisibleToStudents: 'Making visible to students',
diff --git a/src/course-unit/CourseUnit.jsx b/src/course-unit/CourseUnit.jsx
index a2c585522d..b235e832b9 100644
--- a/src/course-unit/CourseUnit.jsx
+++ b/src/course-unit/CourseUnit.jsx
@@ -2,10 +2,15 @@ import { useEffect } from 'react';
 import PropTypes from 'prop-types';
 import { useSelector } from 'react-redux';
 import { useParams } from 'react-router-dom';
-import { Container, Layout, Stack } from '@openedx/paragon';
+import {
+  Container, Layout, Stack, Button, TransitionReplace,
+} from '@openedx/paragon';
 import { getConfig } from '@edx/frontend-platform';
 import { useIntl, injectIntl } from '@edx/frontend-platform/i18n';
-import { Warning as WarningIcon } from '@openedx/paragon/icons';
+import {
+  Warning as WarningIcon,
+  CheckCircle as CheckCircleIcon,
+} from '@openedx/paragon/icons';
 
 import { getProcessingNotification } from '../generic/processing-notification/data/selectors';
 import SubHeader from '../generic/sub-header/SubHeader';
@@ -30,6 +35,7 @@ import LocationInfo from './sidebar/LocationInfo';
 import TagsSidebarControls from '../content-tags-drawer/tags-sidebar-controls';
 import { PasteNotificationAlert } from './clipboard';
 import XBlockContainerIframe from './xblock-container-iframe';
+import MoveModal from './move-modal';
 
 const CourseUnit = ({ courseId }) => {
   const { blockId } = useParams();
@@ -55,6 +61,13 @@ const CourseUnit = ({ courseId }) => {
     handleConfigureSubmit,
     courseVerticalChildren,
     canPasteComponent,
+    isMoveModalOpen,
+    openMoveModal,
+    closeMoveModal,
+    movedXBlockParams,
+    handleRollbackMovedXBlock,
+    handleCloseXBlockMovedAlert,
+    handleNavigateToTargetUnit,
   } = useCourseUnit({ courseId, blockId });
 
   useEffect(() => {
@@ -82,6 +95,40 @@ const CourseUnit = ({ courseId }) => {
     <>
       <Container size="xl" className="course-unit px-4">
         <section className="course-unit-container mb-4 mt-5">
+          <TransitionReplace>
+            {movedXBlockParams.isSuccess ? (
+              <AlertMessage
+                key="xblock-moved-alert"
+                data-testid="xblock-moved-alert"
+                show={movedXBlockParams.isSuccess}
+                variant="success"
+                icon={CheckCircleIcon}
+                title={movedXBlockParams.isUndo
+                  ? intl.formatMessage(messages.alertMoveCancelTitle)
+                  : intl.formatMessage(messages.alertMoveSuccessTitle)}
+                description={movedXBlockParams.isUndo
+                  ? intl.formatMessage(messages.alertMoveCancelDescription, { title: movedXBlockParams.title })
+                  : intl.formatMessage(messages.alertMoveSuccessDescription, { title: movedXBlockParams.title })}
+                aria-hidden={movedXBlockParams.isSuccess}
+                dismissible
+                actions={movedXBlockParams.isUndo ? null : [
+                  <Button
+                    onClick={handleRollbackMovedXBlock}
+                    key="xblock-moved-alert-undo-move-button"
+                  >
+                    {intl.formatMessage(messages.undoMoveButton)}
+                  </Button>,
+                  <Button
+                    onClick={handleNavigateToTargetUnit}
+                    key="xblock-moved-alert-new-location-button"
+                  >
+                    {intl.formatMessage(messages.newLocationButton)}
+                  </Button>,
+                ]}
+                onClose={handleCloseXBlockMovedAlert}
+              />
+            ) : null}
+          </TransitionReplace>
           <SubHeader
             hideBorder
             title={(
@@ -147,6 +194,12 @@ const CourseUnit = ({ courseId }) => {
                   text={intl.formatMessage(messages.pasteButtonText)}
                 />
               )}
+              <MoveModal
+                isOpenModal={isMoveModalOpen}
+                openModal={openMoveModal}
+                closeModal={closeMoveModal}
+                courseId={courseId}
+              />
             </Layout.Element>
             <Layout.Element>
               <Stack gap={3}>
diff --git a/src/course-unit/CourseUnit.scss b/src/course-unit/CourseUnit.scss
index 44a2c93d13..3ada01ca2f 100644
--- a/src/course-unit/CourseUnit.scss
+++ b/src/course-unit/CourseUnit.scss
@@ -3,6 +3,7 @@
 @import "./add-component/AddComponent";
 @import "./sidebar/Sidebar";
 @import "./header-title/HeaderTitle";
+@import "./move-modal";
 
 .course-unit__alert {
   margin-bottom: 1.75rem;
diff --git a/src/course-unit/CourseUnit.test.jsx b/src/course-unit/CourseUnit.test.jsx
index 3dec79de59..25e0274708 100644
--- a/src/course-unit/CourseUnit.test.jsx
+++ b/src/course-unit/CourseUnit.test.jsx
@@ -1,6 +1,6 @@
 import MockAdapter from 'axios-mock-adapter';
 import {
-  act, render, waitFor, fireEvent, within, screen,
+  act, render, waitFor, within, screen,
 } from '@testing-library/react';
 import userEvent from '@testing-library/user-event';
 import { IntlProvider } from '@edx/frontend-platform/i18n';
@@ -18,6 +18,7 @@ import {
   getCourseSectionVerticalApiUrl,
   getCourseUnitApiUrl,
   getCourseVerticalChildrenApiUrl,
+  getCourseOutlineInfoUrl,
   getXBlockBaseApiUrl,
   postXBlockBaseApiUrl,
 } from './data/api';
@@ -27,6 +28,8 @@ import {
   fetchCourseSectionVerticalData,
   fetchCourseUnitQuery,
   fetchCourseVerticalChildrenData,
+  getCourseOutlineInfoQuery,
+  patchUnitItemQuery,
 } from './data/thunk';
 import initializeStore from '../store';
 import {
@@ -36,6 +39,7 @@ import {
   courseUnitMock,
   courseVerticalChildrenMock,
   clipboardMockResponse,
+  courseOutlineInfoMock,
 } from './__mocks__';
 import { clipboardUnit } from '../__mocks__';
 import { executeThunk } from '../utils';
@@ -49,10 +53,12 @@ import { extractCourseUnitId } from './sidebar/utils';
 import CourseUnit from './CourseUnit';
 
 import configureModalMessages from '../generic/configure-modal/messages';
+import { getContentTaxonomyTagsApiUrl, getContentTaxonomyTagsCountApiUrl } from '../content-tags-drawer/data/api';
 import addComponentMessages from './add-component/messages';
-import { PUBLISH_TYPES, UNIT_VISIBILITY_STATES } from './constants';
+import { messageTypes, PUBLISH_TYPES, UNIT_VISIBILITY_STATES } from './constants';
+import { IframeProvider } from './context/iFrameContext';
+import moveModalMessages from './move-modal/messages';
 import messages from './messages';
-import { getContentTaxonomyTagsApiUrl, getContentTaxonomyTagsCountApiUrl } from '../content-tags-drawer/data/api';
 
 let axiosMock;
 let store;
@@ -108,7 +114,9 @@ global.BroadcastChannel = jest.fn(() => clipboardBroadcastChannelMock);
 const RootWrapper = () => (
   <AppProvider store={store}>
     <IntlProvider locale="en">
-      <CourseUnit courseId={courseId} />
+      <IframeProvider>
+        <CourseUnit courseId={courseId} />
+      </IframeProvider>
     </IntlProvider>
   </AppProvider>
 );
@@ -123,6 +131,7 @@ describe('<CourseUnit />', () => {
         roles: [],
       },
     });
+    window.scrollTo = jest.fn();
     global.localStorage.clear();
     store = initializeStore();
     axiosMock = new MockAdapter(getAuthenticatedHttpClient());
@@ -223,12 +232,13 @@ describe('<CourseUnit />', () => {
         .queryByRole('textbox', { name: headerTitleMessages.ariaLabelButtonEdit.defaultMessage });
     });
     expect(titleEditField).not.toBeInTheDocument();
-    fireEvent.click(editTitleButton);
+    userEvent.click(editTitleButton);
     titleEditField = getByRole('textbox', { name: headerTitleMessages.ariaLabelButtonEdit.defaultMessage });
-    fireEvent.change(titleEditField, { target: { value: newDisplayName } });
-    await act(async () => {
-      fireEvent.blur(titleEditField);
-    });
+
+    await userEvent.clear(titleEditField);
+    await userEvent.type(titleEditField, newDisplayName);
+    await userEvent.tab();
+
     expect(titleEditField).toHaveValue(newDisplayName);
 
     titleEditField = queryByRole('textbox', { name: headerTitleMessages.ariaLabelButtonEdit.defaultMessage });
@@ -393,12 +403,13 @@ describe('<CourseUnit />', () => {
     const unitHeaderTitle = getByTestId('unit-header-title');
 
     const editTitleButton = within(unitHeaderTitle).getByRole('button', { name: headerTitleMessages.altButtonEdit.defaultMessage });
-    fireEvent.click(editTitleButton);
+    userEvent.click(editTitleButton);
 
     const titleEditField = within(unitHeaderTitle).getByRole('textbox', { name: headerTitleMessages.ariaLabelButtonEdit.defaultMessage });
-    fireEvent.change(titleEditField, { target: { value: newDisplayName } });
 
-    await act(async () => fireEvent.blur(titleEditField));
+    await userEvent.clear(titleEditField);
+    await userEvent.type(titleEditField, newDisplayName);
+    await userEvent.tab();
 
     await waitFor(async () => {
       const units = getAllByTestId('course-unit-btn');
@@ -1061,4 +1072,253 @@ describe('<CourseUnit />', () => {
       )).not.toBeInTheDocument();
     });
   });
+
+  describe('Move functionality', () => {
+    const requestData = {
+      sourceLocator: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@867dddb6f55d410caaa9c1eb9c6743ec',
+      targetParentLocator: 'block-v1:edX+DemoX+Demo_Course+type@course+block@course',
+      title: 'Getting Started',
+      currentParentLocator: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@19a30717eff543078a5d94ae9d6c18a5',
+      isMoving: true,
+      callbackFn: jest.fn(),
+    };
+    const messageEvent = new MessageEvent('message', {
+      data: {
+        type: messageTypes.showMoveXBlockModal,
+        payload: {
+          sourceXBlockInfo: {
+            id: requestData.sourceLocator,
+            displayName: requestData.title,
+          },
+          sourceParentXBlockInfo: {
+            id: requestData.currentParentLocator,
+            category: 'vertical',
+            hasChildren: true,
+          },
+        },
+      },
+      origin: '*',
+    });
+
+    it('should display "Move Modal" on receive trigger message', async () => {
+      const {
+        getByText,
+        getByRole,
+      } = render(<RootWrapper />);
+
+      await act(async () => {
+        await waitFor(() => {
+          expect(getByText(unitDisplayName))
+            .toBeInTheDocument();
+        });
+
+        axiosMock
+          .onGet(getCourseOutlineInfoUrl(courseId))
+          .reply(200, courseOutlineInfoMock);
+        await executeThunk(getCourseOutlineInfoQuery(courseId), store.dispatch);
+
+        window.dispatchEvent(messageEvent);
+      });
+
+      expect(getByText(
+        moveModalMessages.moveModalTitle.defaultMessage.replace('{displayName}', requestData.title),
+      )).toBeInTheDocument();
+      expect(getByRole('button', { name: moveModalMessages.moveModalSubmitButton.defaultMessage })).toBeInTheDocument();
+      expect(getByRole('button', { name: moveModalMessages.moveModalCancelButton.defaultMessage })).toBeInTheDocument();
+    });
+
+    it('should navigates to xBlock current unit', async () => {
+      const {
+        getByText,
+        getByRole,
+      } = render(<RootWrapper />);
+
+      await act(async () => {
+        await waitFor(() => {
+          expect(getByText(unitDisplayName))
+            .toBeInTheDocument();
+        });
+
+        axiosMock
+          .onGet(getCourseOutlineInfoUrl(courseId))
+          .reply(200, courseOutlineInfoMock);
+        await executeThunk(getCourseOutlineInfoQuery(courseId), store.dispatch);
+
+        window.dispatchEvent(messageEvent);
+      });
+
+      expect(getByText(
+        moveModalMessages.moveModalTitle.defaultMessage.replace('{displayName}', requestData.title),
+      )).toBeInTheDocument();
+
+      const currentSection = courseOutlineInfoMock.child_info.children[1];
+      const currentSectionItemBtn = getByRole('button', {
+        name: `${currentSection.display_name} ${moveModalMessages.moveModalOutlineItemCurrentLocationText.defaultMessage} ${moveModalMessages.moveModalOutlineItemViewText.defaultMessage}`,
+      });
+      expect(currentSectionItemBtn).toBeInTheDocument();
+      userEvent.click(currentSectionItemBtn);
+
+      await waitFor(() => {
+        const currentSubsection = currentSection.child_info.children[0];
+        const currentSubsectionItemBtn = getByRole('button', {
+          name: `${currentSubsection.display_name} ${moveModalMessages.moveModalOutlineItemCurrentLocationText.defaultMessage} ${moveModalMessages.moveModalOutlineItemViewText.defaultMessage}`,
+        });
+        expect(currentSubsectionItemBtn).toBeInTheDocument();
+        userEvent.click(currentSubsectionItemBtn);
+      });
+
+      await waitFor(() => {
+        const currentComponentLocationText = getByText(
+          moveModalMessages.moveModalOutlineItemCurrentComponentLocationText.defaultMessage,
+        );
+        expect(currentComponentLocationText).toBeInTheDocument();
+      });
+    });
+
+    it('should allow move operation and handles it successfully', async () => {
+      const {
+        getByText,
+        getByRole,
+      } = render(<RootWrapper />);
+
+      axiosMock
+        .onPatch(postXBlockBaseApiUrl())
+        .reply(200, {});
+
+      axiosMock
+        .onGet(getCourseUnitApiUrl(blockId))
+        .reply(200, {});
+
+      await act(async () => {
+        await waitFor(() => {
+          expect(getByText(unitDisplayName))
+            .toBeInTheDocument();
+        });
+
+        axiosMock
+          .onGet(getCourseOutlineInfoUrl(courseId))
+          .reply(200, courseOutlineInfoMock);
+        await executeThunk(getCourseOutlineInfoQuery(courseId), store.dispatch);
+
+        window.dispatchEvent(messageEvent);
+      });
+
+      expect(getByText(
+        moveModalMessages.moveModalTitle.defaultMessage.replace('{displayName}', requestData.title),
+      )).toBeInTheDocument();
+
+      const currentSection = courseOutlineInfoMock.child_info.children[1];
+      const currentSectionItemBtn = getByRole('button', {
+        name: `${currentSection.display_name} ${moveModalMessages.moveModalOutlineItemCurrentLocationText.defaultMessage} ${moveModalMessages.moveModalOutlineItemViewText.defaultMessage}`,
+      });
+      expect(currentSectionItemBtn).toBeInTheDocument();
+      userEvent.click(currentSectionItemBtn);
+
+      const currentSubsection = currentSection.child_info.children[1];
+      await waitFor(() => {
+        const currentSubsectionItemBtn = getByRole('button', {
+          name: `${currentSubsection.display_name} ${moveModalMessages.moveModalOutlineItemViewText.defaultMessage}`,
+        });
+        expect(currentSubsectionItemBtn).toBeInTheDocument();
+        userEvent.click(currentSubsectionItemBtn);
+      });
+
+      await waitFor(() => {
+        const currentUnit = currentSubsection.child_info.children[0];
+        const currentUnitItemBtn = getByRole('button', {
+          name: `${currentUnit.display_name} ${moveModalMessages.moveModalOutlineItemViewText.defaultMessage}`,
+        });
+        expect(currentUnitItemBtn).toBeInTheDocument();
+        userEvent.click(currentUnitItemBtn);
+      });
+
+      const moveModalBtn = getByRole('button', {
+        name: moveModalMessages.moveModalSubmitButton.defaultMessage,
+      });
+      expect(moveModalBtn).toBeInTheDocument();
+      expect(moveModalBtn).not.toBeDisabled();
+      userEvent.click(moveModalBtn);
+
+      await waitFor(() => {
+        expect(window.scrollTo).toHaveBeenCalledWith({ top: 0, behavior: 'smooth' });
+        expect(window.scrollTo).toHaveBeenCalledTimes(1);
+      });
+    });
+
+    it('should display "Move Confirmation" alert after moving and undo operations', async () => {
+      const {
+        queryByRole,
+        getByText,
+      } = render(<RootWrapper />);
+
+      axiosMock
+        .onPatch(postXBlockBaseApiUrl())
+        .reply(200, {});
+
+      await executeThunk(patchUnitItemQuery({
+        sourceLocator: requestData.sourceLocator,
+        targetParentLocator: requestData.targetParentLocator,
+        title: requestData.title,
+        currentParentLocator: requestData.currentParentLocator,
+        isMoving: requestData.isMoving,
+        callbackFn: requestData.callbackFn,
+      }), store.dispatch);
+
+      const dismissButton = queryByRole('button', {
+        name: /dismiss/i, hidden: true,
+      });
+      const undoButton = queryByRole('button', {
+        name: messages.undoMoveButton.defaultMessage, hidden: true,
+      });
+      const newLocationButton = queryByRole('button', {
+        name: messages.newLocationButton.defaultMessage, hidden: true,
+      });
+
+      expect(getByText(messages.alertMoveSuccessTitle.defaultMessage)).toBeInTheDocument();
+      expect(getByText(`${requestData.title} has been moved`)).toBeInTheDocument();
+      expect(dismissButton).toBeInTheDocument();
+      expect(undoButton).toBeInTheDocument();
+      expect(newLocationButton).toBeInTheDocument();
+
+      userEvent.click(undoButton);
+
+      await waitFor(() => {
+        expect(getByText(messages.alertMoveCancelTitle.defaultMessage)).toBeInTheDocument();
+      });
+      expect(getByText(
+        messages.alertMoveCancelDescription.defaultMessage.replace('{title}', requestData.title),
+      )).toBeInTheDocument();
+      expect(dismissButton).toBeInTheDocument();
+      expect(undoButton).not.toBeInTheDocument();
+      expect(newLocationButton).not.toBeInTheDocument();
+    });
+
+    it('should navigate to new location by button click', async () => {
+      const {
+        queryByRole,
+      } = render(<RootWrapper />);
+
+      axiosMock
+        .onPatch(postXBlockBaseApiUrl())
+        .reply(200, {});
+
+      await executeThunk(patchUnitItemQuery({
+        sourceLocator: requestData.sourceLocator,
+        targetParentLocator: requestData.targetParentLocator,
+        title: requestData.title,
+        currentParentLocator: requestData.currentParentLocator,
+        isMoving: requestData.isMoving,
+        callbackFn: requestData.callbackFn,
+      }), store.dispatch);
+
+      const newLocationButton = queryByRole('button', {
+        name: messages.newLocationButton.defaultMessage, hidden: true,
+      });
+      userEvent.click(newLocationButton);
+      expect(mockedUsedNavigate).toHaveBeenCalledWith(
+        `/course/${courseId}/container/${blockId}/${requestData.currentParentLocator}`,
+        { replace: true },
+      );
+    });
+  });
 });
diff --git a/src/course-unit/__mocks__/courseOutlineInfo.js b/src/course-unit/__mocks__/courseOutlineInfo.js
new file mode 100644
index 0000000000..a5646c6fee
--- /dev/null
+++ b/src/course-unit/__mocks__/courseOutlineInfo.js
@@ -0,0 +1,1683 @@
+module.exports = {
+  id: 'block-v1:edX+DemoX+Demo_Course+type@course+block@course',
+  display_name: 'Demonstration Course',
+  category: 'course',
+  has_children: true,
+  video_sharing_enabled: true,
+  video_sharing_options: 'per-video',
+  video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+  unit_level_discussions: false,
+  child_info: {
+    category: 'chapter',
+    display_name: 'Section',
+    children: [
+      {
+        id: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@d8a6192ade314473a78242dfeedfbf5b',
+        display_name: 'Introduction',
+        category: 'chapter',
+        has_children: true,
+        video_sharing_enabled: true,
+        video_sharing_options: 'per-video',
+        video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+        child_info: {
+          category: 'sequential',
+          display_name: 'Subsection',
+          children: [
+            {
+              id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@edx_introduction',
+              display_name: 'Demo Course Overview',
+              category: 'sequential',
+              has_children: true,
+              video_sharing_enabled: true,
+              video_sharing_options: 'per-video',
+              video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+              child_info: {
+                category: 'vertical',
+                display_name: 'Unit',
+                children: [
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_0270f6de40fc',
+                    display_name: 'Introduction: Video and Sequences',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@030e35c4756a4ddc8d40b95fbbfff4d4',
+                          display_name: 'Blank HTML Page',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@f7cc083ff66d442eafafd48152881276',
+                          display_name: '“Blank HTML Page”的副本',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@video+block@0b9e39477cf34507a7a48f74be381fdd',
+                          display_name: 'Welcome!',
+                          category: 'video',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@video+block@6e72ebc448694e42ac56553af74304e7',
+                          display_name: 'Video',
+                          category: 'video',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                ],
+              },
+            },
+            {
+              id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@8c964a36521a42e3a221e7b8cf6c94fc',
+              display_name: 'Subsection',
+              category: 'sequential',
+              has_children: true,
+              video_sharing_enabled: true,
+              video_sharing_options: 'per-video',
+              video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+            },
+          ],
+        },
+      },
+      {
+        id: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@interactive_demonstrations',
+        display_name: 'Example Week 1: Getting Started',
+        category: 'chapter',
+        has_children: true,
+        video_sharing_enabled: true,
+        video_sharing_options: 'per-video',
+        video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+        child_info: {
+          category: 'sequential',
+          display_name: 'Subsection',
+          children: [
+            {
+              id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@19a30717eff543078a5d94ae9d6c18a5',
+              display_name: 'Lesson 1 - Getting Started',
+              category: 'sequential',
+              has_children: true,
+              video_sharing_enabled: true,
+              video_sharing_options: 'per-video',
+              video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+              child_info: {
+                category: 'vertical',
+                display_name: 'Unit',
+                children: [
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@867dddb6f55d410caaa9c1eb9c6743ec',
+                    display_name: 'Getting Started',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@82d599b014b246c7a9b5dfc750dc08a9',
+                          display_name: 'Getting Started',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@4f6c1b4e316a419ab5b6bf30e6c708e9',
+                    display_name: 'Working with Videos',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@6bcccc2d7343416e9e03fd7325b2f232',
+                          display_name: '',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@video+block@7e9b434e6de3435ab99bd3fb25bde807',
+                          display_name: 'A Shared Culture',
+                          category: 'video',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@412dc8dbb6674014862237b23c1f643f',
+                          display_name: 'Working with Videos',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@3dc16db8d14842e38324e95d4030b8a0',
+                    display_name: 'Videos on edX',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@0a3b4139f51a4917a3aff9d519b1eeb6',
+                          display_name: 'Videos on edX',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@video+block@5c90cffecd9b48b188cbfea176bf7fe9',
+                          display_name: 'Video',
+                          category: 'video',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@722085be27c84ac693cfebc8ac5da700',
+                          display_name: 'Videos on edX',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@4a1bba2a403f40bca5ec245e945b0d76',
+                    display_name: 'Video Demonstrations',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@ed5dccf14ae94353961f46fa07217491',
+                          display_name: '',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@9f9e1373cc8243b985c8750cc8acec7d',
+                          display_name: 'Video Demonstrations',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@256f17a44983429fb1a60802203ee4e0',
+                    display_name: 'Video Presentation Styles',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@c2f7008c9ccf4bd09d5d800c98fb0722',
+                          display_name: '',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@video+block@636541acbae448d98ab484b028c9a7f6',
+                          display_name: 'Connecting a Circuit and a Circuit Diagram',
+                          category: 'video',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@e2cb0e0994f84b0abfa5f4ae42ed9d44',
+                          display_name: 'Video Presentation Styles',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@e3601c0abee6427d8c17e6d6f8fdddd1',
+                    display_name: 'Interactive Questions',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@9cee77a606ea4c1aa5440e0ea5d0f618',
+                          display_name: 'Interactive Questions',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@3169f89efde2452993f2f2d9bc74f5b2',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@a79d59cd72034188a71d388f4954a606',
+                    display_name: 'Exciting Labs and Tools',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@ffcd6351126d4ca984409180e41d1b51',
+                          display_name: 'Exciting Labs and Tools',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@1c8d47c425724346a7968fa1bc745dcd',
+                          display_name: 'Labs and Tools',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@134df56c516a4a0dbb24dd5facef746e',
+                    display_name: 'Reading Assignments',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@e0254b911fa246218bd98bbdadffef06',
+                          display_name: 'Reading Assignments',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@2574c523e97b477a9d72fbb37bfb995f',
+                          display_name: 'Text',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@932e6f2ce8274072a355a94560216d1a',
+                          display_name: 'Perchance to Dream',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@303034da25524878a2e66fb57c91cf85',
+                          display_name: 'Attributing Blame',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@ffa5817d49e14fec83ad6187cbe16358',
+                          display_name: 'Reading Sample',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@d91b9e5d8bc64d57a1332d06bf2f2193',
+                    display_name: 'When Are Your Exams? ',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@9d5104b502f24ee89c3d2f4ce9d347cf',
+                          display_name: 'When Are Your Exams? ',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                ],
+              },
+            },
+            {
+              id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@basic_questions',
+              display_name: 'Homework - Question Styles',
+              category: 'sequential',
+              has_children: true,
+              video_sharing_enabled: true,
+              video_sharing_options: 'per-video',
+              video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+              child_info: {
+                category: 'vertical',
+                display_name: 'Unit',
+                children: [
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@2152d4a4aadc4cb0af5256394a3d1fc7',
+                    display_name: 'Pointing on a Picture',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@c554538a57664fac80783b99d9d6da7c',
+                          display_name: 'Pointing on a Picture Component',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@e5eac7e1a5a24f5fa7ed77bb6d136591',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@47dbd5f836544e61877a483c0b75606c',
+                    display_name: 'Drag and Drop',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@d2e35c1d294b4ba0b3b1048615605d2a',
+                          display_name: 'Drag and Drop',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@5ab88e67d46049b9aa694cb240c39cef',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@54bb9b142c6c4c22afc62bcb628f0e68',
+                    display_name: 'Multiple Choice Questions',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@a0effb954cca4759994f1ac9e9434bf4',
+                          display_name: 'Multiple Choice Questions',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@67c26b1e826e47aaa29757f62bcd1ad0',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_0c92347a5c00',
+                    display_name: 'Mathematical Expressions',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@Sample_Algebraic_Problem',
+                          display_name: 'Mathematical Expressions',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@870371212ba04dcf9536d7c7b8f3109e',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_1fef54c2b23b',
+                    display_name: 'Chemical Equations',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@Sample_ChemFormula_Problem',
+                          display_name: 'Chemical Equations',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@4d672c5893cb4f1dad0de67d2008522e',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@2889db1677a549abb15eb4d886f95d1c',
+                    display_name: 'Numerical Input',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@75f9562c77bc4858b61f907bb810d974',
+                          display_name: 'Numerical Input',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@501aed9d902349eeb2191fa505548de2',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@e8a5cc2aed424838853defab7be45e42',
+                    display_name: 'Text input',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@0d759dee4f9d459c8956136dbde55f02',
+                          display_name: 'Text Input',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@6244918637ed4ff4b5f94a840a7e4b43',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@fb6b62dbec4348528629cf2232b86aea',
+                    display_name: 'Instructor Programmed Responses',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [],
+                    },
+                  },
+                ],
+              },
+            },
+          ],
+        },
+      },
+      {
+        id: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@graded_interactions',
+        display_name: 'Example Week 2: Get Interactive',
+        category: 'chapter',
+        has_children: true,
+        video_sharing_enabled: true,
+        video_sharing_options: 'per-video',
+        video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+        child_info: {
+          category: 'sequential',
+          display_name: 'Subsection',
+          children: [
+            {
+              id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@simulations',
+              display_name: "Lesson 2 - Let's Get Interactive!",
+              category: 'sequential',
+              has_children: true,
+              video_sharing_enabled: true,
+              video_sharing_options: 'per-video',
+              video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+              child_info: {
+                category: 'vertical',
+                display_name: 'Unit',
+                children: [
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@d0d804e8863c4a95a659c04d8a2b2bc0',
+                    display_name: "Lesson 2 - Let's Get Interactive! ",
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@78d7d3642f3a4dbabbd1b017861aa5f2',
+                          display_name: "Lesson 2: Let's Get Interactive!",
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_2dbb0072785e',
+                    display_name: 'An Interactive Reference Table',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@html_07d547513285',
+                          display_name: 'An Interactive Reference Table',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@6f7a6670f87147149caeff6afa07a526',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_98cf62510471',
+                    display_name: 'Zooming Diagrams',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@700x_pathways',
+                          display_name: 'Zooming Diagrams',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@e0d7423118ab432582d03e8e8dad8e36',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_d32bf9b2242c',
+                    display_name: 'Electronic Sound Experiment',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@Lab_5B_Mosfet_Amplifier_Experiment',
+                          display_name: 'Electronic Sound Experiment',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@03f051f9a8814881a3783d2511613aa6',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@4e592689563243c484af947465eaef0d',
+                    display_name: 'New Unit',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@video+block@af7fe1335eb841cd81ce31c7ee8eb069',
+                          display_name: 'Video',
+                          category: 'video',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                ],
+              },
+            },
+            {
+              id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@graded_simulations',
+              display_name: 'Homework - Labs and Demos',
+              category: 'sequential',
+              has_children: true,
+              video_sharing_enabled: true,
+              video_sharing_options: 'per-video',
+              video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+              child_info: {
+                category: 'vertical',
+                display_name: 'Unit',
+                children: [
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@d6cee45205a449369d7ef8f159b22bdf',
+                    display_name: 'Labs and Demos',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@2bee8c4248e842a19ba1e73ed8d426c2',
+                          display_name: 'Labs and Demos',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_aae927868e55',
+                    display_name: 'Code Grader',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@891211e17f9a472290a5f12c7a6626d7',
+                          display_name: 'Code Grader',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@python_grader',
+                          display_name: 'problem',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@c6cd4bea43454aaea60ad01beb0cf213',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_c037f3757df1',
+                    display_name: 'Electric Circuit Simulator',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@d5a5caaf35e84ebc9a747038465dcfb4',
+                          display_name: 'Electronic Circuit Simulator',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@free_form_simulation',
+                          display_name: 'problem',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@logic_gate_problem',
+                          display_name: 'problem',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@4f06b358a96f4d1dae57d6d81acd06f2',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_bc69a47c6fae',
+                    display_name: 'Protein Creator',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@78e3719e864e45f3bee938461f3c3de6',
+                          display_name: 'Protein Builder',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@700x_proteinmake',
+                          display_name: 'Designing Proteins in Two Dimensions',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@ed01bcd164e64038a78964a16eac3edc',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@8f89194410954e768bde1764985454a7',
+                    display_name: 'Molecule Structures',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@9b9687073e904ae197799dc415df899f',
+                          display_name: 'Molecule Structures',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                ],
+              },
+            },
+            {
+              id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@175e76c4951144a29d46211361266e0e',
+              display_name: 'Homework - Essays',
+              category: 'sequential',
+              has_children: true,
+              video_sharing_enabled: true,
+              video_sharing_options: 'per-video',
+              video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+              child_info: {
+                category: 'vertical',
+                display_name: 'Unit',
+                children: [
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@fb79dcbad35b466a8c6364f8ffee9050',
+                    display_name: 'Peer Assessed Essays',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@openassessment+block@b24c33ea35954c7889e1d2944d3fe397',
+                          display_name: 'Open Response Assessment',
+                          category: 'openassessment',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@12ad4f3ff4c14114a6e629b00e000976',
+                          display_name: 'Peer Grading',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                ],
+              },
+            },
+          ],
+        },
+      },
+      {
+        id: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@social_integration',
+        display_name: 'Example Week 3: Be Social',
+        category: 'chapter',
+        has_children: true,
+        video_sharing_enabled: true,
+        video_sharing_options: 'per-video',
+        video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+        child_info: {
+          category: 'sequential',
+          display_name: 'Subsection',
+          children: [
+            {
+              id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@48ecb924d7fe4b66a230137626bfa93e',
+              display_name: 'Lesson 3 - Be Social',
+              category: 'sequential',
+              has_children: true,
+              video_sharing_enabled: true,
+              video_sharing_options: 'per-video',
+              video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+              child_info: {
+                category: 'vertical',
+                display_name: 'Unit',
+                children: [
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@3c4b575924bf4b75a2f3542df5c354fc',
+                    display_name: 'Be Social',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@f9f3a25e7bab46e583fd1fbbd7a2f6a0',
+                          display_name: 'Be Social',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_3888db0bc286',
+                    display_name: 'Discussion Forums',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@html_49b4494da2f7',
+                          display_name: 'Discussion Forums',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@discussion_5deb6081620d',
+                          display_name: 'Discussion Forums',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@312cb4faed17420e82ab3178fc3e251a',
+                    display_name: 'Getting Help',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@8bb218cccf8d40519a971ff0e4901ccf',
+                          display_name: 'Getting Help',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@7efc7bf4a47b4a6cb6595c32cde7712a',
+                    display_name: 'Homework - Find Your Study Buddy',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@87fa6792d79f4862be098e5169e93339',
+                          display_name: 'Blank HTML Page',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                ],
+              },
+            },
+            {
+              id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@dbe8fc027bcb4fe9afb744d2e8415855',
+              display_name: 'Homework - Find Your Study Buddy',
+              category: 'sequential',
+              has_children: true,
+              video_sharing_enabled: true,
+              video_sharing_options: 'per-video',
+              video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+              child_info: {
+                category: 'vertical',
+                display_name: 'Unit',
+                children: [
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@26d89b08f75d48829a63520ed8b0037d',
+                    display_name: 'Homework - Find Your Study Buddy',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@6018785795994726950614ce7d0f38c5',
+                          display_name: 'Find Your Study Buddy',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                ],
+              },
+            },
+            {
+              id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@6ab9c442501d472c8ed200e367b4edfa',
+              display_name: 'More Ways to Connect',
+              category: 'sequential',
+              has_children: true,
+              video_sharing_enabled: true,
+              video_sharing_options: 'per-video',
+              video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+              child_info: {
+                category: 'vertical',
+                display_name: 'Unit',
+                children: [
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@3f2c11aba9434e459676a7d7acc4d960',
+                    display_name: 'Google Hangout',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@d45779ad3d024a40a09ad8cc317c0970',
+                          display_name: 'Text',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@55cbc99f262443d886a25cf84594eafb',
+                          display_name: 'Text',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@ade92343df3d4953a40ab3adc8805390',
+                          display_name: 'Google Hangout',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                ],
+              },
+            },
+          ],
+        },
+      },
+      {
+        id: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@1414ffd5143b4b508f739b563ab468b7',
+        display_name: 'About Exams and Certificates',
+        category: 'chapter',
+        has_children: true,
+        video_sharing_enabled: true,
+        video_sharing_options: 'per-video',
+        video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+        child_info: {
+          category: 'sequential',
+          display_name: 'Subsection',
+          children: [
+            {
+              id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@workflow',
+              display_name: 'edX Exams',
+              category: 'sequential',
+              has_children: true,
+              video_sharing_enabled: true,
+              video_sharing_options: 'per-video',
+              video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+              child_info: {
+                category: 'vertical',
+                display_name: 'Unit',
+                children: [
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@934cc32c177d41b580c8413e561346b3',
+                    display_name: 'EdX Exams',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@8293139743f34377817d537b69911530',
+                          display_name: 'EdX Exams',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_f04afeac0131',
+                    display_name: 'Immediate Feedback',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@ex_practice_2',
+                          display_name: 'Immediate Feedback',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@4aba537a78774bd5a862485a8563c345',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@b6662b497c094bcc9b870d8270c90c93',
+                    display_name: 'Getting Answers',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@45d46192272c4f6db6b63586520bbdf4',
+                          display_name: 'Getting Answers',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@f480df4ce91347c5ae4301ddf6146238',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@f91d8d31f7cf48ce990f8d8745ae4cfa',
+                    display_name: 'Answering More Than Once',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@651e0945b77f42e0a4c89b8c3e6f5b3b',
+                          display_name: 'Answering More Than Once',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@b8cec2a19ebf463f90cd3544c7927b0e',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_ac391cde8a91',
+                    display_name: 'Limited Checks',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@ex_practice_limited_checks',
+                          display_name: 'Limited Checks',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@d1b84dcd39b0423d9e288f27f0f7f242',
+                          display_name: 'Few Checks',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@cd177caa62444fbca48aa8f843f09eac',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_36e0beb03f0a',
+                    display_name: 'Randomized Questions',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@problem+block@ex_practice_3',
+                          display_name: 'Randomized Questions',
+                          category: 'problem',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@ddede76df71045ffa16de9d1481d2119',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@1b0e2c2c84884b95b1c99fb678cc964c',
+                    display_name: 'Overall Grade Performance',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@f4a39219742149f781a1dda6f43a623c',
+                          display_name: 'Overall Grade',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@1a810b1a3b2447b998f0917d0e5a802b',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@c7e98fd39a6944edb6b286c32e1150ff',
+                    display_name: 'Passing a Course',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@5e009378f0b64585baa0a14b155974b9',
+                          display_name: 'Passing a Course',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@discussion+block@23e6eda482c04335af2bb265beacaf59',
+                          display_name: '',
+                          category: 'discussion',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@d6eaa391d2be41dea20b8b1bfbcb1c45',
+                    display_name: 'Getting Your edX Certificate',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@148ae8fa73ea460eb6f05505da0ba6e6',
+                          display_name: 'Getting Your edX Certificate',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@6b6bee43c7c641509da71c9299cc9f5a',
+                          display_name: 'Blank HTML Page',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                ],
+              },
+            },
+          ],
+        },
+      },
+      {
+        id: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@59666313a79946079f5ef4fff36e45f0',
+        display_name: 'IFrame',
+        category: 'chapter',
+        has_children: true,
+        video_sharing_enabled: true,
+        video_sharing_options: 'per-video',
+        video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+        child_info: {
+          category: 'sequential',
+          display_name: 'Subsection',
+          children: [
+            {
+              id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@f9fd819dfb224d118e4df4d46c648179',
+              display_name: 'Subsection',
+              category: 'sequential',
+              has_children: true,
+              video_sharing_enabled: true,
+              video_sharing_options: 'per-video',
+              video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+              child_info: {
+                category: 'vertical',
+                display_name: 'Unit',
+                children: [
+                  {
+                    id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@c8165538b5f04283879efc8e8deb2d92',
+                    display_name: 'Iframe',
+                    category: 'vertical',
+                    has_children: true,
+                    video_sharing_enabled: true,
+                    video_sharing_options: 'per-video',
+                    video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                    child_info: {
+                      children: [
+                        {
+                          id: 'block-v1:edX+DemoX+Demo_Course+type@html+block@fd3d0a72d0d344af9a53de144d83af1f',
+                          display_name: 'IFrame Tool',
+                          category: 'html',
+                          has_children: false,
+                          video_sharing_enabled: true,
+                          video_sharing_options: 'per-video',
+                          video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+                        },
+                      ],
+                    },
+                  },
+                ],
+              },
+            },
+            {
+              id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@a7deaeb85ee24470871c912536534a59',
+              display_name: 'Subsection',
+              category: 'sequential',
+              has_children: true,
+              video_sharing_enabled: true,
+              video_sharing_options: 'per-video',
+              video_sharing_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-quince.master/developing_course/social_sharing.html',
+            },
+          ],
+        },
+      },
+    ],
+  },
+};
diff --git a/src/course-unit/__mocks__/index.js b/src/course-unit/__mocks__/index.js
index 8810e61e07..bfbbb9a4bb 100644
--- a/src/course-unit/__mocks__/index.js
+++ b/src/course-unit/__mocks__/index.js
@@ -4,3 +4,4 @@ export { default as courseUnitMock } from './courseUnit';
 export { default as courseCreateXblockMock } from './courseCreateXblock';
 export { default as courseVerticalChildrenMock } from './courseVerticalChildren';
 export { default as clipboardMockResponse } from './clipboardResponse';
+export { default as courseOutlineInfoMock } from './courseOutlineInfo';
diff --git a/src/course-unit/constants.js b/src/course-unit/constants.js
index 60b199c21c..ebadb310b4 100644
--- a/src/course-unit/constants.js
+++ b/src/course-unit/constants.js
@@ -50,6 +50,8 @@ export const messageTypes = {
   modal: 'plugin.modal',
   resize: 'plugin.resize',
   videoFullScreen: 'plugin.videoFullScreen',
+  refreshXBlock: 'refreshXBlock',
+  showMoveXBlockModal: 'showMoveXBlockModal',
 };
 
 export const IFRAME_FEATURE_POLICY = (
diff --git a/src/course-unit/context/hooks.test.tsx b/src/course-unit/context/hooks.test.tsx
new file mode 100644
index 0000000000..fb94d57d11
--- /dev/null
+++ b/src/course-unit/context/hooks.test.tsx
@@ -0,0 +1,24 @@
+import { ReactNode } from 'react';
+import { renderHook } from '@testing-library/react-hooks';
+
+import { useIframe } from './hooks';
+import { IframeProvider } from './iFrameContext';
+
+describe('useIframe hook', () => {
+  it('throws an error when used outside of IframeProvider', () => {
+    const { result } = renderHook(() => useIframe());
+    expect(result.error).toEqual(new Error('useIframe must be used within an IframeProvider'));
+  });
+
+  it('returns context value when used inside IframeProvider', () => {
+    const wrapper = ({ children }: { children: ReactNode }) => (
+      <IframeProvider>
+        {children}
+      </IframeProvider>
+    );
+
+    const { result } = renderHook(() => useIframe(), { wrapper });
+    expect(result.current).toHaveProperty('setIframeRef');
+    expect(result.current).toHaveProperty('sendMessageToIframe');
+  });
+});
diff --git a/src/course-unit/context/hooks.tsx b/src/course-unit/context/hooks.tsx
new file mode 100644
index 0000000000..9760c07afc
--- /dev/null
+++ b/src/course-unit/context/hooks.tsx
@@ -0,0 +1,12 @@
+import { useContext } from 'react';
+
+import { IframeContext, IframeContextType } from './iFrameContext';
+
+// eslint-disable-next-line import/prefer-default-export
+export const useIframe = (): IframeContextType => {
+  const context = useContext(IframeContext);
+  if (!context) {
+    throw new Error('useIframe must be used within an IframeProvider');
+  }
+  return context;
+};
diff --git a/src/course-unit/context/iFrameContext.tsx b/src/course-unit/context/iFrameContext.tsx
new file mode 100644
index 0000000000..75418f0d39
--- /dev/null
+++ b/src/course-unit/context/iFrameContext.tsx
@@ -0,0 +1,42 @@
+import {
+  createContext, MutableRefObject, useRef, useCallback, useMemo, ReactNode,
+} from 'react';
+import { logError } from '@edx/frontend-platform/logging';
+
+export interface IframeContextType {
+  setIframeRef: (ref: MutableRefObject<HTMLIFrameElement | null>) => void;
+  sendMessageToIframe: (messageType: string, payload: unknown) => void;
+}
+
+export const IframeContext = createContext<IframeContextType | undefined>(undefined);
+
+export const IframeProvider: React.FC = ({ children }: { children: ReactNode }) => {
+  const iframeRef = useRef<HTMLIFrameElement | null>(null);
+  const setIframeRef = useCallback((ref: MutableRefObject<HTMLIFrameElement | null>) => {
+    iframeRef.current = ref.current;
+  }, []);
+
+  const sendMessageToIframe = useCallback((messageType: string, payload: any) => {
+    const iframeWindow = iframeRef?.current?.contentWindow;
+    if (iframeWindow) {
+      try {
+        iframeWindow.postMessage({ type: messageType, payload }, '*');
+      } catch (error) {
+        logError('Failed to send message to iframe:', error);
+      }
+    } else {
+      logError('Iframe is not accessible or loaded yet.');
+    }
+  }, [iframeRef]);
+
+  const value = useMemo(() => ({
+    setIframeRef,
+    sendMessageToIframe,
+  }), [setIframeRef, sendMessageToIframe]);
+
+  return (
+    <IframeContext.Provider value={value}>
+      {children}
+    </IframeContext.Provider>
+  );
+};
diff --git a/src/course-unit/data/api.js b/src/course-unit/data/api.js
index e699e8ad07..7ede6e0236 100644
--- a/src/course-unit/data/api.js
+++ b/src/course-unit/data/api.js
@@ -11,6 +11,7 @@ export const getCourseUnitApiUrl = (itemId) => `${getStudioBaseUrl()}/xblock/con
 export const getXBlockBaseApiUrl = (itemId) => `${getStudioBaseUrl()}/xblock/${itemId}`;
 export const getCourseSectionVerticalApiUrl = (itemId) => `${getStudioBaseUrl()}/api/contentstore/v1/container_handler/${itemId}`;
 export const getCourseVerticalChildrenApiUrl = (itemId) => `${getStudioBaseUrl()}/api/contentstore/v1/container/vertical/${itemId}/children`;
+export const getCourseOutlineInfoUrl = (courseId) => `${getStudioBaseUrl()}/course/${courseId}?format=concise`;
 export const postXBlockBaseApiUrl = () => `${getStudioBaseUrl()}/xblock/`;
 
 /**
@@ -157,3 +158,51 @@ export async function duplicateUnitItem(itemId, XBlockId) {
 
   return data;
 }
+
+/**
+ * @typedef {Object} courseOutline
+ * @property {string} id - The unique identifier of the course.
+ * @property {string} displayName - The display name of the course.
+ * @property {string} category - The category of the course (e.g., "course").
+ * @property {boolean} hasChildren - Whether the course has child items.
+ * @property {boolean} unitLevelDiscussions - Indicates if unit-level discussions are available.
+ * @property {Object} childInfo - Information about the child elements of the course.
+ * @property {string} childInfo.category - The category of the child (e.g., "chapter").
+ * @property {string} childInfo.display_name - The display name of the child element.
+ * @property {Array<Object>} childInfo.children - List of children within the child_info (could be empty).
+ */
+
+/**
+ * Get an object containing course outline data.
+ * @param {string} courseId - The identifier of the course.
+ * @returns {Promise<courseOutline>} - The course outline data.
+ */
+export async function getCourseOutlineInfo(courseId) {
+  const { data } = await getAuthenticatedHttpClient()
+    .get(getCourseOutlineInfoUrl(courseId));
+
+  return camelCaseObject(data);
+}
+
+/**
+ * @typedef {Object} moveInfo
+ * @property {string} moveSourceLocator - The locator of the source block being moved.
+ * @property {string} parentLocator - The locator of the parent block where the source is being moved to.
+ * @property {number} sourceIndex - The index position of the source block.
+ */
+
+/**
+ * Move a unit item to new unit.
+ * @param {string} sourceLocator - The ID of the item to be moved.
+ * @param {string} targetParentLocator - The ID of the XBlock associated with the item.
+ * @returns {Promise<moveInfo>} - The move information.
+ */
+export async function patchUnitItem(sourceLocator, targetParentLocator) {
+  const { data } = await getAuthenticatedHttpClient()
+    .patch(postXBlockBaseApiUrl(), {
+      parent_locator: targetParentLocator,
+      move_source_locator: sourceLocator,
+    });
+
+  return camelCaseObject(data);
+}
diff --git a/src/course-unit/data/selectors.js b/src/course-unit/data/selectors.js
index e445ddaf19..824b4545d4 100644
--- a/src/course-unit/data/selectors.js
+++ b/src/course-unit/data/selectors.js
@@ -13,6 +13,9 @@ export const getCourseSectionVertical = (state) => state.courseUnit.courseSectio
 export const getCourseId = (state) => state.courseDetail.courseId;
 export const getSequenceId = (state) => state.courseUnit.sequenceId;
 export const getCourseVerticalChildren = (state) => state.courseUnit.courseVerticalChildren;
+export const getCourseOutlineInfo = (state) => state.courseUnit.courseOutlineInfo;
+export const getCourseOutlineInfoLoadingStatus = (state) => state.courseUnit.courseOutlineInfoLoadingStatus;
+export const getMovedXBlockParams = (state) => state.courseUnit.movedXBlockParams;
 const getLoadingStatuses = (state) => state.courseUnit.loadingStatus;
 export const getIsLoading = createSelector(
   [getLoadingStatuses],
diff --git a/src/course-unit/data/slice.js b/src/course-unit/data/slice.js
index 39dbeb5a18..aab66ea260 100644
--- a/src/course-unit/data/slice.js
+++ b/src/course-unit/data/slice.js
@@ -20,6 +20,15 @@ const slice = createSlice({
     courseSectionVertical: {},
     courseVerticalChildren: { children: [], isPublished: true },
     staticFileNotices: {},
+    courseOutlineInfo: {},
+    courseOutlineInfoLoadingStatus: RequestStatus.IN_PROGRESS,
+    movedXBlockParams: {
+      isSuccess: false,
+      isUndo: false,
+      title: '',
+      sourceLocator: '',
+      targetParentLocator: '',
+    },
   },
   reducers: {
     fetchCourseItemSuccess: (state, { payload }) => {
@@ -103,6 +112,15 @@ const slice = createSlice({
     fetchStaticFileNoticesSuccess: (state, { payload }) => {
       state.staticFileNotices = payload;
     },
+    updateCourseOutlineInfo: (state, { payload }) => {
+      state.courseOutlineInfo = payload;
+    },
+    updateCourseOutlineInfoLoadingStatus: (state, { payload }) => {
+      state.courseOutlineInfoLoadingStatus = payload.status;
+    },
+    updateMovedXBlockParams: (state, { payload }) => {
+      state.movedXBlockParams = { ...state.movedXBlockParams, ...payload };
+    },
   },
 });
 
@@ -124,6 +142,9 @@ export const {
   deleteXBlock,
   duplicateXBlock,
   fetchStaticFileNoticesSuccess,
+  updateCourseOutlineInfo,
+  updateCourseOutlineInfoLoadingStatus,
+  updateMovedXBlockParams,
 } = slice.actions;
 
 export const {
diff --git a/src/course-unit/data/thunk.js b/src/course-unit/data/thunk.js
index 404903302e..a0d421eea3 100644
--- a/src/course-unit/data/thunk.js
+++ b/src/course-unit/data/thunk.js
@@ -18,6 +18,8 @@ import {
   handleCourseUnitVisibilityAndData,
   deleteUnitItem,
   duplicateUnitItem,
+  getCourseOutlineInfo,
+  patchUnitItem,
 } from './api';
 import {
   updateLoadingCourseUnitStatus,
@@ -35,6 +37,9 @@ import {
   deleteXBlock,
   duplicateXBlock,
   fetchStaticFileNoticesSuccess,
+  updateCourseOutlineInfo,
+  updateCourseOutlineInfoLoadingStatus,
+  updateMovedXBlockParams,
 } from './slice';
 import { getNotificationMessage } from './utils';
 
@@ -260,3 +265,56 @@ export function duplicateUnitItemQuery(itemId, xblockId) {
     }
   };
 }
+
+export function getCourseOutlineInfoQuery(courseId) {
+  return async (dispatch) => {
+    dispatch(updateCourseOutlineInfoLoadingStatus({ status: RequestStatus.IN_PROGRESS }));
+
+    try {
+      const result = await getCourseOutlineInfo(courseId);
+      if (result) {
+        dispatch(updateCourseOutlineInfo(result));
+        dispatch(updateCourseOutlineInfoLoadingStatus({ status: RequestStatus.SUCCESSFUL }));
+      }
+    } catch (error) {
+      handleResponseErrors(error, dispatch, updateSavingStatus);
+      dispatch(updateCourseOutlineInfoLoadingStatus({ status: RequestStatus.FAILED }));
+    }
+  };
+}
+
+export function patchUnitItemQuery({
+  sourceLocator = '',
+  targetParentLocator = '',
+  title,
+  currentParentLocator = '',
+  isMoving,
+  callbackFn,
+}) {
+  return async (dispatch) => {
+    dispatch(updateSavingStatus({ status: RequestStatus.PENDING }));
+    dispatch(showProcessingNotification(NOTIFICATION_MESSAGES[isMoving ? 'moving' : 'undoMoving']));
+
+    try {
+      await patchUnitItem(sourceLocator, isMoving ? targetParentLocator : currentParentLocator);
+      const xBlockParams = {
+        title,
+        isSuccess: true,
+        isUndo: !isMoving,
+        sourceLocator,
+        targetParentLocator,
+        currentParentLocator,
+      };
+      dispatch(updateMovedXBlockParams(xBlockParams));
+      dispatch(updateCourseOutlineInfo({}));
+      dispatch(updateCourseOutlineInfoLoadingStatus({ status: RequestStatus.IN_PROGRESS }));
+      const courseUnit = await getCourseUnitData(currentParentLocator);
+      dispatch(fetchCourseItemSuccess(courseUnit));
+      callbackFn();
+    } catch (error) {
+      handleResponseErrors(error, dispatch, updateSavingStatus);
+    } finally {
+      dispatch(hideProcessingNotification());
+    }
+  };
+}
diff --git a/src/course-unit/header-title/HeaderTitle.jsx b/src/course-unit/header-title/HeaderTitle.jsx
index 0d29404ba6..336d986fab 100644
--- a/src/course-unit/header-title/HeaderTitle.jsx
+++ b/src/course-unit/header-title/HeaderTitle.jsx
@@ -85,6 +85,7 @@ const HeaderTitle = ({
           onClose={closeConfigureModal}
           onConfigureSubmit={onConfigureSubmit}
           currentItemData={currentItemData}
+          isSelfPaced={false}
         />
       </div>
       {getVisibilityMessage()}
diff --git a/src/course-unit/hooks.jsx b/src/course-unit/hooks.jsx
index de24082a3d..2e9358a5ee 100644
--- a/src/course-unit/hooks.jsx
+++ b/src/course-unit/hooks.jsx
@@ -1,8 +1,10 @@
 import { useEffect } from 'react';
 import { useDispatch, useSelector } from 'react-redux';
 import { useNavigate, useSearchParams } from 'react-router-dom';
+import { useToggle } from '@openedx/paragon';
 
 import { RequestStatus } from '../data/constants';
+import { useCopyToClipboard } from '../generic/clipboard';
 import {
   createNewCourseXBlock,
   fetchCourseUnitQuery,
@@ -12,6 +14,8 @@ import {
   deleteUnitItemQuery,
   duplicateUnitItemQuery,
   editCourseUnitVisibilityAndData,
+  getCourseOutlineInfoQuery,
+  patchUnitItemQuery,
 } from './data/thunk';
 import {
   getCourseSectionVertical,
@@ -23,16 +27,23 @@ import {
   getSequenceStatus,
   getStaticFileNotices,
   getCanEdit,
+  getCourseOutlineInfo,
+  getMovedXBlockParams,
 } from './data/selectors';
-import { changeEditTitleFormOpen, updateQueryPendingStatus } from './data/slice';
-import { PUBLISH_TYPES } from './constants';
-
-import { useCopyToClipboard } from '../generic/clipboard';
+import {
+  changeEditTitleFormOpen,
+  updateQueryPendingStatus,
+  updateMovedXBlockParams,
+} from './data/slice';
+import { useIframe } from './context/hooks';
+import { messageTypes, PUBLISH_TYPES } from './constants';
 
 // eslint-disable-next-line import/prefer-default-export
 export const useCourseUnit = ({ courseId, blockId }) => {
   const dispatch = useDispatch();
   const [searchParams] = useSearchParams();
+  const { sendMessageToIframe } = useIframe();
+  const [isMoveModalOpen, openMoveModal, closeMoveModal] = useToggle(false);
 
   const courseUnit = useSelector(getCourseUnitData);
   const savingStatus = useSelector(getSavingStatus);
@@ -45,6 +56,8 @@ export const useCourseUnit = ({ courseId, blockId }) => {
   const navigate = useNavigate();
   const isTitleEditFormOpen = useSelector(state => state.courseUnit.isTitleEditFormOpen);
   const canEdit = useSelector(getCanEdit);
+  const courseOutlineInfo = useSelector(getCourseOutlineInfo);
+  const movedXBlockParams = useSelector(getMovedXBlockParams);
   const { currentlyVisibleToStudents } = courseUnit;
   const { sharedClipboardData, showPasteXBlock, showPasteUnit } = useCopyToClipboard(canEdit);
   const { canPasteComponent } = courseVerticalChildren;
@@ -113,6 +126,31 @@ export const useCourseUnit = ({ courseId, blockId }) => {
     },
   };
 
+  const handleRollbackMovedXBlock = () => {
+    const {
+      sourceLocator, targetParentLocator, title, currentParentLocator,
+    } = movedXBlockParams;
+    dispatch(patchUnitItemQuery({
+      sourceLocator,
+      targetParentLocator,
+      title,
+      currentParentLocator,
+      isMoving: false,
+      callbackFn: () => {
+        sendMessageToIframe(messageTypes.refreshXBlock, null);
+        window.scrollTo({ top: 0, behavior: 'smooth' });
+      },
+    }));
+  };
+
+  const handleCloseXBlockMovedAlert = () => {
+    dispatch(updateMovedXBlockParams({ isSuccess: false }));
+  };
+
+  const handleNavigateToTargetUnit = () => {
+    navigate(`/course/${courseId}/container/${movedXBlockParams.targetParentLocator}`);
+  };
+
   useEffect(() => {
     if (savingStatus === RequestStatus.SUCCESSFUL) {
       dispatch(updateQueryPendingStatus(true));
@@ -125,8 +163,15 @@ export const useCourseUnit = ({ courseId, blockId }) => {
     dispatch(fetchCourseVerticalChildrenData(blockId));
 
     handleNavigate(sequenceId);
+    dispatch(updateMovedXBlockParams({ isSuccess: false }));
   }, [courseId, blockId, sequenceId]);
 
+  useEffect(() => {
+    if (isMoveModalOpen && !Object.keys(courseOutlineInfo).length) {
+      dispatch(getCourseOutlineInfoQuery(courseId));
+    }
+  }, [isMoveModalOpen]);
+
   return {
     sequenceId,
     courseUnit,
@@ -149,5 +194,12 @@ export const useCourseUnit = ({ courseId, blockId }) => {
     handleConfigureSubmit,
     courseVerticalChildren,
     canPasteComponent,
+    isMoveModalOpen,
+    openMoveModal,
+    closeMoveModal,
+    handleRollbackMovedXBlock,
+    handleCloseXBlockMovedAlert,
+    movedXBlockParams,
+    handleNavigateToTargetUnit,
   };
 };
diff --git a/src/course-unit/index.js b/src/course-unit/index.js
index e6c38e561a..5c5928653b 100644
--- a/src/course-unit/index.js
+++ b/src/course-unit/index.js
@@ -1,2 +1,3 @@
 /* eslint-disable import/prefer-default-export */
 export { default as CourseUnit } from './CourseUnit';
+export { IframeProvider } from './context/iFrameContext';
diff --git a/src/course-unit/messages.js b/src/course-unit/messages.js
index 4f0418efe5..83779747a0 100644
--- a/src/course-unit/messages.js
+++ b/src/course-unit/messages.js
@@ -13,6 +13,36 @@ const messages = defineMessages({
     id: 'course-authoring.course-unit.paste-component.btn.text',
     defaultMessage: 'Paste component',
   },
+  alertMoveSuccessTitle: {
+    id: 'course-authoring.course-unit.alert.xblock.move.success.title',
+    defaultMessage: 'Success!',
+    description: 'Title for the success alert when an XBlock is moved successfully',
+  },
+  alertMoveSuccessDescription: {
+    id: 'course-authoring.course-unit.alert.xblock.move.success.description',
+    defaultMessage: '{title} has been moved',
+    description: 'Description for the success alert when an XBlock is moved successfully',
+  },
+  alertMoveCancelTitle: {
+    id: 'course-authoring.course-unit.alert.xblock.move.cancel.title',
+    defaultMessage: 'Move cancelled',
+    description: 'Title for the alert when moving an XBlock is cancelled',
+  },
+  alertMoveCancelDescription: {
+    id: 'course-authoring.course-unit.alert.xblock.move.cancel.description',
+    defaultMessage: '{title} has been moved back to its original location',
+    description: 'Description for the alert when moving an XBlock is cancelled and the XBlock is moved back to its original location',
+  },
+  undoMoveButton: {
+    id: 'course-authoring.course-unit.alert.xblock.move.undo.btn.text',
+    defaultMessage: 'Undo move',
+    description: 'Text for the button allowing users to undo a move action of an XBlock',
+  },
+  newLocationButton: {
+    id: 'course-authoring.course-unit.alert.xblock.new.location.btn.text',
+    defaultMessage: 'Take me to the new location',
+    description: 'Text for the button allowing users to navigate to the new location after an XBlock has been moved',
+  },
 });
 
 export default messages;
diff --git a/src/course-unit/move-modal/components/CategoryIndicator.tsx b/src/course-unit/move-modal/components/CategoryIndicator.tsx
new file mode 100644
index 0000000000..58160b51b4
--- /dev/null
+++ b/src/course-unit/move-modal/components/CategoryIndicator.tsx
@@ -0,0 +1,26 @@
+import { useIntl } from '@edx/frontend-platform/i18n';
+
+import messages from '../messages';
+
+const CategoryIndicator = ({ categoryText, displayName }: { categoryText: string, displayName: string }) => {
+  const intl = useIntl();
+  return (
+    <div className="xblock-items-category small text-gray-500">
+      <span className="sr-only">
+        {intl.formatMessage(messages.moveModalCategoryIndicatorAccessibilityText, {
+          categoryText,
+          displayName,
+        })}
+      </span>
+      <span
+        className="category-text"
+        aria-hidden="true"
+        data-testid="move-xblock-modal-category"
+      >
+        {categoryText}
+      </span>
+    </div>
+  );
+};
+
+export default CategoryIndicator;
diff --git a/src/course-unit/move-modal/components/EmptyMessage.tsx b/src/course-unit/move-modal/components/EmptyMessage.tsx
new file mode 100644
index 0000000000..99737b0aa3
--- /dev/null
+++ b/src/course-unit/move-modal/components/EmptyMessage.tsx
@@ -0,0 +1,17 @@
+import { useIntl } from '@edx/frontend-platform/i18n';
+
+import messages from '../messages';
+
+const EmptyMessage = ({ category, categoryText }: { category: string, categoryText: string }) => {
+  const intl = useIntl();
+  return (
+    <li className="xblock-no-child-message">
+      {intl.formatMessage(messages.moveModalEmptyCategoryText, {
+        category,
+        categoryText: categoryText.toLowerCase(),
+      })}
+    </li>
+  );
+};
+
+export default EmptyMessage;
diff --git a/src/course-unit/move-modal/components/ModalLoader.tsx b/src/course-unit/move-modal/components/ModalLoader.tsx
new file mode 100644
index 0000000000..0685d2b93f
--- /dev/null
+++ b/src/course-unit/move-modal/components/ModalLoader.tsx
@@ -0,0 +1,9 @@
+import { LoadingSpinner } from '../../../generic/Loading';
+
+const ModalLoader = () => (
+  <div className="move-xblock-modal-loading">
+    <LoadingSpinner />
+  </div>
+);
+
+export default ModalLoader;
diff --git a/src/course-unit/move-modal/components/index.ts b/src/course-unit/move-modal/components/index.ts
new file mode 100644
index 0000000000..4d07788092
--- /dev/null
+++ b/src/course-unit/move-modal/components/index.ts
@@ -0,0 +1,3 @@
+export { default as EmptyMessage } from './EmptyMessage';
+export { default as ModalLoader } from './ModalLoader';
+export { default as CategoryIndicator } from './CategoryIndicator';
diff --git a/src/course-unit/move-modal/constants.ts b/src/course-unit/move-modal/constants.ts
new file mode 100644
index 0000000000..d013ec4df7
--- /dev/null
+++ b/src/course-unit/move-modal/constants.ts
@@ -0,0 +1,41 @@
+import messages from './messages';
+
+export const CATEGORIES = {
+  TEXT: {
+    section: messages.moveModalBreadcrumbsSections,
+    subsection: messages.moveModalBreadcrumbsSubsections,
+    unit: messages.moveModalBreadcrumbsUnits,
+    component: messages.moveModalBreadcrumbsComponents,
+    group: messages.moveModalBreadcrumbsGroups,
+  },
+  KEYS: {
+    course: 'course',
+    chapter: 'chapter',
+    section: 'section',
+    sequential: 'sequential',
+    subsection: 'subsection',
+    vertical: 'vertical',
+    unit: 'unit',
+    component: 'component',
+    split_test: 'split_test',
+    group: 'group',
+  },
+  RELATION_MAP: {
+    course: 'section',
+    section: 'subsection',
+    subsection: 'unit',
+    unit: 'component',
+  },
+} as const;
+
+export const MOVE_DIRECTIONS = {
+  forward: 'forward',
+  backward: 'backward',
+} as const;
+
+export const BASIC_BLOCK_TYPES = [
+  'course',
+  'chapter',
+  'sequential',
+  'vertical',
+] as const;
diff --git a/src/course-unit/move-modal/hooks.tsx b/src/course-unit/move-modal/hooks.tsx
new file mode 100644
index 0000000000..69ad13470c
--- /dev/null
+++ b/src/course-unit/move-modal/hooks.tsx
@@ -0,0 +1,234 @@
+import {
+  useCallback, useEffect, useState, useMemo,
+} from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { useParams } from 'react-router-dom';
+import { useMediaQuery } from 'react-responsive';
+import { breakpoints } from '@openedx/paragon';
+import { useIntl } from '@edx/frontend-platform/i18n';
+
+import { RequestStatus } from '../../data/constants';
+import { useEventListener } from '../../generic/hooks';
+import { getCourseOutlineInfo, getCourseOutlineInfoLoadingStatus } from '../data/selectors';
+import { getCourseOutlineInfoQuery, patchUnitItemQuery } from '../data/thunk';
+import { useIframe } from '../context/hooks';
+import { messageTypes } from '../constants';
+import { CATEGORIES, MOVE_DIRECTIONS } from './constants';
+import {
+  findParentIds, getBreadcrumbs, getXBlockType, isValidCategory,
+} from './utils';
+import {
+  IState, IUseMoveModalParams, IUseMoveModalReturn, IXBlockInfo,
+} from './interfaces';
+
+// eslint-disable-next-line import/prefer-default-export
+export const useMoveModal = ({
+  isOpenModal, closeModal, openModal, courseId,
+}: IUseMoveModalParams): IUseMoveModalReturn => {
+  const { blockId } = useParams<{ blockId: string }>();
+  const intl = useIntl();
+  const dispatch = useDispatch();
+  const { sendMessageToIframe } = useIframe();
+  const courseOutlineInfo = useSelector(getCourseOutlineInfo);
+  const courseOutlineInfoLoadingStatus = useSelector(getCourseOutlineInfoLoadingStatus);
+
+  const initialValues = useMemo<IState>(() => ({
+    childrenInfo: { children: courseOutlineInfo.childInfo?.children ?? [], category: CATEGORIES.KEYS.section },
+    parentInfo: { parent: courseOutlineInfo, category: CATEGORIES.KEYS.course },
+    isValidMove: false,
+    sourceXBlockInfo: { current: {} as IXBlockInfo, parent: {} as IXBlockInfo },
+    visitedAncestors: [courseOutlineInfo],
+  }), [courseOutlineInfo]);
+
+  const [state, setState] = useState<IState>(initialValues);
+
+  const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.extraSmall.maxWidth });
+
+  const currentXBlockParentIds = useMemo(
+    () => findParentIds(courseOutlineInfo, state.sourceXBlockInfo.current.id as string),
+    [courseOutlineInfo, state.sourceXBlockInfo.current.id],
+  );
+
+  const receiveMessage = useCallback(({ data }: { data: any }) => {
+    const { payload, type } = data;
+
+    if (type === messageTypes.showMoveXBlockModal) {
+      setState((prevState) => ({
+        ...prevState,
+        sourceXBlockInfo: {
+          current: payload.sourceXBlockInfo,
+          parent: payload.sourceParentXBlockInfo,
+        },
+      }));
+      openModal();
+    }
+  }, [openModal]);
+
+  useEventListener('message', receiveMessage);
+
+  const updateParentItemsData = useCallback((direction?: string, newParentIndex?: string) => {
+    setState((prevState: IState) => {
+      if (!direction) {
+        return {
+          ...prevState,
+          parentInfo: {
+            parent: initialValues.parentInfo.parent,
+            category: initialValues.parentInfo.category,
+          },
+          visitedAncestors: [initialValues.parentInfo.parent],
+        };
+      }
+
+      if (
+        direction === MOVE_DIRECTIONS.forward && newParentIndex !== undefined
+        && prevState.childrenInfo.children[newParentIndex]
+      ) {
+        const newParent = prevState.childrenInfo.children[newParentIndex];
+        return {
+          ...prevState,
+          parentInfo: {
+            parent: newParent,
+            category: prevState.parentInfo.category,
+          },
+          visitedAncestors: [...prevState.visitedAncestors, newParent],
+        };
+      }
+
+      if (
+        direction === MOVE_DIRECTIONS.backward && newParentIndex !== undefined
+        && prevState.visitedAncestors[newParentIndex]
+      ) {
+        return {
+          ...prevState,
+          parentInfo: {
+            parent: prevState.visitedAncestors[newParentIndex],
+            category: prevState.parentInfo.category,
+          },
+          visitedAncestors: prevState.visitedAncestors.slice(0, parseInt(newParentIndex, 10) + 1),
+        };
+      }
+
+      return prevState;
+    });
+  }, [initialValues]);
+
+  const handleXBlockClick = useCallback((newParentIndex: string) => {
+    updateParentItemsData(MOVE_DIRECTIONS.forward, newParentIndex);
+  }, [updateParentItemsData]);
+
+  const handleBreadcrumbsClick = useCallback((newParentIndex: string) => {
+    updateParentItemsData(MOVE_DIRECTIONS.backward, newParentIndex);
+  }, [updateParentItemsData]);
+
+  const updateChildrenItemsData = useCallback(() => {
+    setState((prevState: IState) => ({
+      ...prevState,
+      childrenInfo: {
+        ...prevState.childrenInfo,
+        children: prevState.parentInfo.parent?.childInfo?.children || [],
+      },
+    }));
+  }, []);
+
+  const getCategoryText = useCallback(() => (
+    intl.formatMessage(CATEGORIES.TEXT[state.childrenInfo.category]) || ''
+  ), [intl, state.childrenInfo.category]);
+
+  const breadcrumbs = useMemo(() => (
+    getBreadcrumbs(state.visitedAncestors, intl.formatMessage)
+  ), [state.visitedAncestors]);
+
+  const setDisplayedXBlocksCategories = useCallback(() => {
+    setState((prevState) => {
+      const childCategory = CATEGORIES.KEYS.component;
+      const newParentCategory = getXBlockType(prevState.parentInfo.parent?.category || '');
+
+      if (prevState.parentInfo.category !== newParentCategory) {
+        return {
+          ...prevState,
+          parentInfo: {
+            ...prevState.parentInfo,
+            category: newParentCategory,
+          },
+          childrenInfo: {
+            ...prevState.childrenInfo,
+            category: CATEGORIES.RELATION_MAP[newParentCategory] || childCategory,
+          },
+        };
+      }
+      return prevState;
+    });
+  }, []);
+
+  const handleCLoseModal = useCallback(() => {
+    setState(initialValues);
+    closeModal();
+  }, [initialValues, closeModal]);
+
+  const enableMoveOperation = useCallback((targetParentXBlockInfo: IXBlockInfo) => {
+    const isValid = isValidCategory(state.sourceXBlockInfo.parent, targetParentXBlockInfo)
+      && state.sourceXBlockInfo.parent.id !== targetParentXBlockInfo.id // different parent
+      && state.sourceXBlockInfo.current.id !== targetParentXBlockInfo.id; // different source item
+
+    setState((prevState) => ({
+      ...prevState,
+      isValidMove: isValid,
+    }));
+  }, [isValidCategory, state.sourceXBlockInfo]);
+
+  const handleMoveXBlock = useCallback(() => {
+    const lastAncestor = state.visitedAncestors[state.visitedAncestors.length - 1];
+    dispatch(patchUnitItemQuery({
+      sourceLocator: state.sourceXBlockInfo.current.id,
+      targetParentLocator: lastAncestor.id,
+      title: state.sourceXBlockInfo.current.displayName,
+      currentParentLocator: blockId,
+      isMoving: true,
+      callbackFn: () => {
+        sendMessageToIframe(messageTypes.refreshXBlock, null);
+        closeModal();
+        window.scrollTo({ top: 0, behavior: 'smooth' });
+      },
+    }));
+  }, [state, dispatch, blockId, closeModal]);
+
+  useEffect(() => {
+    if (isOpenModal && !Object.keys(courseOutlineInfo).length) {
+      dispatch(getCourseOutlineInfoQuery(courseId));
+    }
+  }, [isOpenModal, courseOutlineInfo, courseId, dispatch]);
+
+  useEffect(() => {
+    if (isOpenModal && courseOutlineInfoLoadingStatus === RequestStatus.SUCCESSFUL) {
+      updateParentItemsData();
+    }
+  }, [courseOutlineInfoLoadingStatus, isOpenModal, updateParentItemsData]);
+
+  useEffect(() => {
+    if (isOpenModal && courseOutlineInfoLoadingStatus === RequestStatus.SUCCESSFUL) {
+      updateChildrenItemsData();
+      setDisplayedXBlocksCategories();
+      enableMoveOperation(state.parentInfo.parent);
+    }
+  }, [
+    state.parentInfo, isOpenModal, courseOutlineInfoLoadingStatus, updateChildrenItemsData,
+    setDisplayedXBlocksCategories, enableMoveOperation,
+  ]);
+
+  return {
+    isLoading: courseOutlineInfoLoadingStatus === RequestStatus.IN_PROGRESS,
+    isValidMove: state.isValidMove,
+    isExtraSmall,
+    parentInfo: state.parentInfo,
+    childrenInfo: state.childrenInfo,
+    displayName: state.sourceXBlockInfo.current.displayName,
+    sourceXBlockId: state.sourceXBlockInfo.current.id,
+    categoryText: getCategoryText(),
+    breadcrumbs,
+    currentXBlockParentIds,
+    handleXBlockClick,
+    handleBreadcrumbsClick,
+    handleCLoseModal,
+    handleMoveXBlock,
+  };
+};
diff --git a/src/course-unit/move-modal/index.scss b/src/course-unit/move-modal/index.scss
new file mode 100644
index 0000000000..b644898e2d
--- /dev/null
+++ b/src/course-unit/move-modal/index.scss
@@ -0,0 +1,79 @@
+.move-xblock-modal {
+    max-width: 57.5rem;
+
+    .move-xblock-modal-loading {
+        min-height: 10rem;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+    }
+
+    .pgn__modal-header,
+    .pgn__modal-footer {
+        z-index: 2;
+    }
+
+    .pgn__modal-header {
+        @include pgn-box-shadow(2, "centered");
+    }
+
+    .pgn__modal-footer {
+        @include pgn-box-shadow(2, "down");
+    }
+
+    .pgn__modal-body {
+        background: $white;
+        padding-left: 0;
+        padding-right: 0;
+    }
+
+    .pgn__breadcrumb {
+        border-bottom: 1px solid $light-300;
+        padding: map-get($spacers, 1) map-get($spacers, 4) $spacer;
+
+        .list-inline {
+            flex-wrap: wrap;
+        }
+
+        .list-inline-item {
+            &.active,
+            a.link-muted {
+                color: $dark-500;
+            }
+
+            a.link-muted {
+                cursor: pointer;
+            }
+        }
+    }
+
+    .xblock-items-category {
+        padding: $spacer map-get($spacers, 4) map-get($spacers, 2\.5);
+    }
+
+    .xblock-items-container {
+        list-style: none;
+    }
+
+    .xblock-item {
+        .btn,
+        .component {
+            display: flex;
+            border-radius: 0;
+            width: 100%;
+            gap: map-get($spacers, 2);
+            padding: .5625rem $spacer .5625rem map-get($spacers, 4);
+        }
+
+        .btn {
+            &:hover {
+                background: $light-300;
+                text-decoration: none;
+            }
+        }
+    }
+
+    .xblock-no-child-message {
+        text-align: center;
+    }
+}
diff --git a/src/course-unit/move-modal/index.tsx b/src/course-unit/move-modal/index.tsx
new file mode 100644
index 0000000000..7844d7c310
--- /dev/null
+++ b/src/course-unit/move-modal/index.tsx
@@ -0,0 +1,164 @@
+import React, { FC, useCallback } from 'react';
+import PropTypes from 'prop-types';
+import { useIntl } from '@edx/frontend-platform/i18n';
+import {
+  ActionRow,
+  Breadcrumb,
+  Button,
+  ModalDialog,
+} from '@openedx/paragon';
+import {
+  ArrowForwardIos as ArrowForwardIosIcon,
+} from '@openedx/paragon/icons';
+
+import { CATEGORIES } from './constants';
+import { IUseMoveModalParams, IXBlock, IXBlockInfo } from './interfaces';
+import { useMoveModal } from './hooks';
+import { EmptyMessage, ModalLoader, CategoryIndicator } from './components';
+import messages from './messages';
+
+const MoveModal: FC<IUseMoveModalParams> = ({
+  isOpenModal, closeModal, openModal, courseId,
+}) => {
+  const intl = useIntl();
+
+  const {
+    isLoading,
+    isValidMove,
+    isExtraSmall,
+    parentInfo,
+    childrenInfo,
+    displayName,
+    categoryText,
+    breadcrumbs,
+    sourceXBlockId,
+    currentXBlockParentIds,
+    handleXBlockClick,
+    handleBreadcrumbsClick,
+    handleCLoseModal,
+    handleMoveXBlock,
+  } = useMoveModal({
+    isOpenModal, closeModal, openModal, courseId,
+  });
+
+  const renderBreadcrumbs = useCallback(() => (
+    <Breadcrumb
+      ariaLabel={intl.formatMessage(messages.moveModalBreadcrumbsLabel)}
+      data-testid="move-xblock-modal-breadcrumbs"
+      isMobile={isExtraSmall}
+      links={breadcrumbs.slice(0, -1).map((breadcrumb, index) => (
+        { label: breadcrumb, 'data-parent-index': index }
+      ))}
+      activeLabel={breadcrumbs[breadcrumbs.length - 1]}
+      clickHandler={({ target }) => handleBreadcrumbsClick(target.dataset.parentIndex)}
+    />
+  ), [isExtraSmall, breadcrumbs, handleBreadcrumbsClick]);
+
+  const getCourseStructureItemButton = useCallback((xBlock: IXBlock, index: number) => (
+    <Button
+      variant="link"
+      className="button-forward text-left justify-content-start text-gray-700"
+      onClick={() => handleXBlockClick(index)}
+    >
+      <span className="xblock-display-name text-truncate">
+        {xBlock?.displayName}
+      </span>
+      {currentXBlockParentIds.includes(xBlock.id) && (
+        <span className="current-location text-nowrap mr-3">
+          {intl.formatMessage(messages.moveModalOutlineItemCurrentLocationText)}
+        </span>
+      )}
+      <ArrowForwardIosIcon className="ml-auto flex-shrink-0" />
+      <span className="sr-only">
+        {intl.formatMessage(messages.moveModalOutlineItemViewText)}
+      </span>
+    </Button>
+  ), [currentXBlockParentIds, handleXBlockClick]);
+
+  const renderCourseStructureItemSpan = useCallback((xBlock: IXBlock) => (
+    <span className="component text-left justify-content-start text-gray-700">
+      <span className="xblock-display-name text-truncate">
+        {xBlock?.displayName}
+      </span>
+      {currentXBlockParentIds.includes(xBlock.id) && (
+        <span className="current-location text-nowrap mr-3">
+          {intl.formatMessage(messages.moveModalOutlineItemCurrentComponentLocationText)}
+        </span>
+      )}
+    </span>
+  ), [currentXBlockParentIds]);
+
+  const renderCourseStructureListItem = useCallback((xBlock: IXBlock, index: number) => (
+    <li key={xBlock.id} className="xblock-item">
+      {sourceXBlockId !== xBlock.id && (xBlock?.childInfo || childrenInfo.category !== CATEGORIES.KEYS.component)
+        ? getCourseStructureItemButton(xBlock, index)
+        : renderCourseStructureItemSpan(xBlock)}
+    </li>
+  ), [sourceXBlockId, childrenInfo.category, getCourseStructureItemButton, renderCourseStructureItemSpan]);
+
+  return (
+    <ModalDialog
+      isOpen={isOpenModal}
+      onClose={handleCLoseModal}
+      size="xl"
+      className="move-xblock-modal"
+      hasCloseButton
+      isFullscreenOnMobile
+    >
+      <ModalDialog.Header>
+        <ModalDialog.Title>
+          {intl.formatMessage(messages.moveModalTitle, { displayName })}
+        </ModalDialog.Title>
+      </ModalDialog.Header>
+      <ModalDialog.Body>
+        {isLoading ? <ModalLoader /> : (
+          <>
+            {renderBreadcrumbs()}
+            <div className="xblock-list-container">
+              <CategoryIndicator
+                categoryText={categoryText}
+                displayName={displayName}
+              />
+              <ul className="xblock-items-container p-0 m-0">
+                {!childrenInfo.children?.length
+                  ? (
+                    <EmptyMessage
+                      category={parentInfo.category}
+                      categoryText={categoryText.toLowerCase()}
+                    />
+                  )
+                  : childrenInfo.children.map(
+                    (xBlock: IXBlock | IXBlockInfo, index: number) => (
+                      renderCourseStructureListItem(xBlock as IXBlock, index)
+                    ),
+                  )}
+              </ul>
+            </div>
+          </>
+        )}
+      </ModalDialog.Body>
+      <ModalDialog.Footer>
+        <ActionRow>
+          <ModalDialog.CloseButton variant="tertiary">
+            {intl.formatMessage(messages.moveModalCancelButton)}
+          </ModalDialog.CloseButton>
+          <Button
+            disabled={!isValidMove}
+            onClick={handleMoveXBlock}
+          >
+            {intl.formatMessage(messages.moveModalSubmitButton)}
+          </Button>
+        </ActionRow>
+      </ModalDialog.Footer>
+    </ModalDialog>
+  );
+};
+
+MoveModal.propTypes = {
+  isOpenModal: PropTypes.bool.isRequired,
+  closeModal: PropTypes.func.isRequired,
+  openModal: PropTypes.func.isRequired,
+  courseId: PropTypes.string.isRequired,
+};
+
+export default MoveModal;
diff --git a/src/course-unit/move-modal/interfaces.ts b/src/course-unit/move-modal/interfaces.ts
new file mode 100644
index 0000000000..3806acd707
--- /dev/null
+++ b/src/course-unit/move-modal/interfaces.ts
@@ -0,0 +1,82 @@
+export interface IXBlockInfo {
+  id: string;
+  displayName: string;
+  childInfo?: {
+    children?: IXBlockInfo[];
+  };
+  category?: string;
+  hasChildren?: boolean;
+}
+
+export interface IUseMoveModalParams {
+  isOpenModal: boolean;
+  closeModal: () => void;
+  openModal: () => void;
+  courseId: string;
+}
+
+export interface IUseMoveModalReturn {
+  isLoading: boolean;
+  isValidMove: boolean;
+  isExtraSmall: boolean;
+  parentInfo: {
+    parent: IXBlockInfo;
+    category: string;
+  };
+  childrenInfo: {
+    children: IXBlockInfo[];
+    category: string;
+  };
+  displayName: string;
+  sourceXBlockId: string;
+  categoryText: string;
+  breadcrumbs: string[];
+  currentXBlockParentIds: string[];
+  handleXBlockClick: (newParentIndex: string | number) => void;
+  handleBreadcrumbsClick: (newParentIndex: string | number) => void;
+  handleCLoseModal: () => void;
+  handleMoveXBlock: () => void;
+}
+
+export interface IState {
+  sourceXBlockInfo: {
+    current: IXBlockInfo;
+    parent: IXBlockInfo;
+  };
+  childrenInfo: {
+    children: IXBlockInfo[];
+    category: string;
+  };
+  parentInfo: {
+    parent: IXBlockInfo;
+    category: string;
+  };
+  visitedAncestors: IXBlockInfo[];
+  isValidMove: boolean;
+}
+
+export interface ITreeNode {
+  id: string;
+  childInfo?: {
+    children?: ITreeNode[];
+  };
+}
+
+export interface IAncestor {
+  category?: string;
+  displayName?: string;
+}
+
+export interface IXBlockChildInfo {
+  category?: string;
+  displayName?: string;
+  children?: IXBlock[];
+}
+
+export interface IXBlock {
+  id: string;
+  displayName: string;
+  category: string;
+  hasChildren: boolean;
+  childInfo?: IXBlockChildInfo;
+}
diff --git a/src/course-unit/move-modal/messages.ts b/src/course-unit/move-modal/messages.ts
new file mode 100644
index 0000000000..b1d71f2a66
--- /dev/null
+++ b/src/course-unit/move-modal/messages.ts
@@ -0,0 +1,81 @@
+import { defineMessages } from '@edx/frontend-platform/i18n';
+
+const messages = defineMessages({
+  moveModalTitle: {
+    id: 'course-authoring.course-unit.xblock.move.modal.title',
+    defaultMessage: 'Move: {displayName}',
+    description: 'Text for the move modal heading',
+  },
+  moveModalCancelButton: {
+    id: 'course-authoring.course-unit.xblock.move.modal.cancel.btn.text',
+    defaultMessage: 'Cancel',
+    description: 'Text for the button closing move modal of an XBlock',
+  },
+  moveModalSubmitButton: {
+    id: 'course-authoring.course-unit.xblock.move.modal.submit.btn.text',
+    defaultMessage: 'Move',
+    description: 'Text for the button submitting move modal of an XBlock',
+  },
+  moveModalBreadcrumbsBaseCategory: {
+    id: 'course-authoring.course-unit.xblock.move.modal.breadcrumbs.core.category.text',
+    defaultMessage: 'Course Outline',
+    description: 'Text for the core breadcrumbs item in move modal of an XBlock',
+  },
+  moveModalBreadcrumbsSections: {
+    id: 'course-authoring.course-unit.xblock.move.modal.breadcrumbs.sections.text',
+    defaultMessage: 'Sections',
+    description: 'Text for the sections breadcrumbs item in move modal of an XBlock',
+  },
+  moveModalBreadcrumbsSubsections: {
+    id: 'course-authoring.course-unit.xblock.move.modal.breadcrumbs.subsections.text',
+    defaultMessage: 'Subsections',
+    description: 'Text for the subsections breadcrumbs item in move modal of an XBlock',
+  },
+  moveModalBreadcrumbsUnits: {
+    id: 'course-authoring.course-unit.xblock.move.modal.breadcrumbs.units.text',
+    defaultMessage: 'Units',
+    description: 'Text for the units breadcrumbs item in move modal of an XBlock',
+  },
+  moveModalBreadcrumbsComponents: {
+    id: 'course-authoring.course-unit.xblock.move.modal.breadcrumbs.components.text',
+    defaultMessage: 'Components',
+    description: 'Text for the components breadcrumbs item in move modal of an XBlock',
+  },
+  moveModalBreadcrumbsGroups: {
+    id: 'course-authoring.course-unit.xblock.move.modal.breadcrumbs.groups.text',
+    defaultMessage: 'Groups',
+    description: 'Text for the groups breadcrumbs item in move modal of an XBlock',
+  },
+  moveModalBreadcrumbsLabel: {
+    id: 'course-authoring.course-unit.xblock.move.modal.breadcrumbs.label.text',
+    defaultMessage: 'Course Outline breadcrumb',
+    description: 'Text for the breadcrumbs label in move modal of an XBlock',
+  },
+  moveModalEmptyCategoryText: {
+    id: 'course-authoring.course-unit.xblock.move.modal.category.empty.text',
+    defaultMessage: 'This {category} has no {categoryText}',
+    description: 'Text for the category with empty children in move modal of an XBlock',
+  },
+  moveModalCategoryIndicatorAccessibilityText: {
+    id: 'course-authoring.course-unit.xblock.move.modal.category.accessibility.text',
+    defaultMessage: '{categoryText} in {displayName}',
+    description: 'Text for the category indicator accessibility in move modal of an XBlock',
+  },
+  moveModalOutlineItemCurrentLocationText: {
+    id: 'course-authoring.course-unit.xblock.move.modal.outline.item.location.text',
+    defaultMessage: '(Current location)',
+    description: 'Text for the outline item that indicates the current location in move modal of an XBlock',
+  },
+  moveModalOutlineItemCurrentComponentLocationText: {
+    id: 'course-authoring.course-unit.xblock.move.modal.outline.item.component.location.text',
+    defaultMessage: '(Currently selected)',
+    description: 'Text for the outline item that indicates the current component location in move modal of an XBlock',
+  },
+  moveModalOutlineItemViewText: {
+    id: 'course-authoring.course-unit.xblock.move.modal.outline.item.view.text',
+    defaultMessage: 'View child items',
+    description: 'Text for the outline item action description in move modal of an XBlock',
+  },
+});
+
+export default messages;
diff --git a/src/course-unit/move-modal/moveModal.test.tsx b/src/course-unit/move-modal/moveModal.test.tsx
new file mode 100644
index 0000000000..ba94e018a9
--- /dev/null
+++ b/src/course-unit/move-modal/moveModal.test.tsx
@@ -0,0 +1,182 @@
+import MockAdapter from 'axios-mock-adapter';
+import { render, waitFor, within } from '@testing-library/react';
+import { AppProvider } from '@edx/frontend-platform/react';
+import { IntlProvider } from '@edx/frontend-platform/i18n';
+import { camelCaseObject, initializeMockApp } from '@edx/frontend-platform';
+import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
+import userEvent from '@testing-library/user-event';
+
+import initializeStore from '../../store';
+import { getCourseOutlineInfoUrl } from '../data/api';
+import { courseOutlineInfoMock } from '../__mocks__';
+import { executeThunk } from '../../utils';
+import { getCourseOutlineInfoQuery } from '../data/thunk';
+import { IframeProvider } from '../context/iFrameContext';
+import { IXBlock } from './interfaces';
+import MoveModal from './index';
+import messages from './messages';
+
+let store;
+let axiosMock: MockAdapter;
+const courseId = '1234567890';
+const closeModalMockFn = jest.fn() as jest.MockedFunction<() => void>;
+const openModalMockFn = jest.fn() as jest.MockedFunction<() => void>;
+const scrollToMockFn = jest.fn() as jest.MockedFunction<() => void>;
+const sections: IXBlock[] | any = camelCaseObject(courseOutlineInfoMock)?.childInfo.children || [];
+const subsections: IXBlock[] = sections[1]?.childInfo?.children || [];
+const units: IXBlock[] = subsections[1]?.childInfo?.children || [];
+const components: IXBlock[] = units[0]?.childInfo?.children || [];
+
+const renderComponent = (props?: any) => render(
+  <AppProvider store={store}>
+    <IntlProvider locale="en">
+      <IframeProvider>
+        <MoveModal
+          isOpenModal
+          closeModal={closeModalMockFn}
+          openModal={openModalMockFn}
+          courseId={courseId}
+          {...props}
+        />
+      </IframeProvider>
+    </IntlProvider>
+  </AppProvider>,
+);
+
+describe('<MoveModal />', () => {
+  beforeEach(async () => {
+    initializeMockApp({
+      authenticatedUser: {
+        userId: 3,
+        username: 'abc123',
+        administrator: true,
+        roles: [],
+      },
+    });
+
+    window.scrollTo = scrollToMockFn;
+    store = initializeStore();
+    axiosMock = new MockAdapter(getAuthenticatedHttpClient());
+    axiosMock
+      .onGet(getCourseOutlineInfoUrl(courseId))
+      .reply(200, courseOutlineInfoMock);
+    await executeThunk(getCourseOutlineInfoQuery(courseId), store.dispatch);
+  });
+
+  it('renders loading indicator correctly', async () => {
+    axiosMock
+      .onGet(getCourseOutlineInfoUrl(courseId))
+      .reply(200, null);
+    await executeThunk(getCourseOutlineInfoQuery(courseId), store.dispatch);
+
+    const { getByText } = renderComponent();
+    expect(getByText('Loading...')).toBeInTheDocument();
+  });
+
+  it('renders component properly', () => {
+    const { getByText, getByRole, getByTestId } = renderComponent();
+    const breadcrumbs: HTMLElement = getByTestId('move-xblock-modal-breadcrumbs');
+    const categoryIndicator: HTMLElement = getByTestId('move-xblock-modal-category');
+
+    expect(getByText(messages.moveModalTitle.defaultMessage.replace(' {displayName}', ''))).toBeInTheDocument();
+    expect(within(breadcrumbs).getByText(messages.moveModalBreadcrumbsBaseCategory.defaultMessage)).toBeInTheDocument();
+    expect(
+      within(categoryIndicator).getByText(messages.moveModalBreadcrumbsSections.defaultMessage),
+    ).toBeInTheDocument();
+    expect(getByRole('button', { name: messages.moveModalSubmitButton.defaultMessage })).toBeInTheDocument();
+    expect(getByRole('button', { name: messages.moveModalCancelButton.defaultMessage })).toBeInTheDocument();
+
+    userEvent.click(getByRole('button', { name: messages.moveModalCancelButton.defaultMessage }));
+    expect(closeModalMockFn).toHaveBeenCalledTimes(1);
+  });
+
+  it('correctly navigates through the structure list', async () => {
+    const { getByText, getByRole, getByTestId } = renderComponent();
+    const breadcrumbs: HTMLElement = getByTestId('move-xblock-modal-breadcrumbs');
+    const categoryIndicator: HTMLElement = getByTestId('move-xblock-modal-category');
+
+    expect(within(breadcrumbs).getByText(messages.moveModalBreadcrumbsBaseCategory.defaultMessage)).toBeInTheDocument();
+    expect(
+      within(categoryIndicator).getByText(messages.moveModalBreadcrumbsSections.defaultMessage),
+    ).toBeInTheDocument();
+    sections.forEach((section) => {
+      expect(getByText(section.displayName)).toBeInTheDocument();
+    });
+    userEvent.click(getByRole('button', { name: new RegExp(sections[1].displayName, 'i') }));
+    await waitFor(() => {
+      expect(
+        within(categoryIndicator).getByText(messages.moveModalBreadcrumbsSubsections.defaultMessage),
+      ).toBeInTheDocument();
+      expect(within(breadcrumbs).getByText(sections[1].displayName)).toBeInTheDocument();
+      subsections.forEach((subsection) => {
+        expect(getByRole('button', { name: new RegExp(subsection.displayName, 'i') })).toBeInTheDocument();
+      });
+    });
+    userEvent.click(getByRole('button', { name: new RegExp(subsections[1].displayName, 'i') }));
+    await waitFor(() => {
+      expect(
+        within(categoryIndicator).getByText(messages.moveModalBreadcrumbsUnits.defaultMessage),
+      ).toBeInTheDocument();
+      expect(within(breadcrumbs).getByText(subsections[1].displayName)).toBeInTheDocument();
+      units.forEach((unit) => {
+        expect(getByRole('button', { name: new RegExp(unit.displayName, 'i') })).toBeInTheDocument();
+      });
+    });
+    userEvent.click(getByRole('button', { name: new RegExp(units[0].displayName, 'i') }));
+    await waitFor(() => {
+      expect(
+        within(categoryIndicator).getByText(messages.moveModalBreadcrumbsComponents.defaultMessage),
+      ).toBeInTheDocument();
+      expect(within(breadcrumbs).getByText(units[0].displayName)).toBeInTheDocument();
+      components.forEach((component) => {
+        if (component.displayName) {
+          expect(getByText(component.displayName)).toBeInTheDocument();
+        }
+      });
+    });
+  });
+
+  it('correctly navigates using breadcrumbs', async () => {
+    const { getByRole, getByTestId } = renderComponent();
+    const breadcrumbs: HTMLElement = getByTestId('move-xblock-modal-breadcrumbs');
+    const categoryIndicator: HTMLElement = getByTestId('move-xblock-modal-category');
+
+    await waitFor(() => {
+      userEvent.click(getByRole('button', { name: new RegExp(sections[1].displayName, 'i') }));
+      userEvent.click(getByRole('button', { name: new RegExp(subsections[1].displayName, 'i') }));
+      userEvent.click(within(breadcrumbs).getByText(sections[1].displayName));
+    });
+
+    await waitFor(() => {
+      expect(
+        within(categoryIndicator).getByText(messages.moveModalBreadcrumbsSubsections.defaultMessage),
+      ).toBeInTheDocument();
+      expect(within(breadcrumbs).getByText(sections[1].displayName)).toBeInTheDocument();
+      subsections.forEach((subsection) => (
+        expect(getByRole('button', { name: new RegExp(subsection.displayName, 'i') })).toBeInTheDocument()
+      ));
+    });
+  });
+
+  it('renders empty message when no components are provided', async () => {
+    const { getByText, getByRole } = renderComponent();
+
+    await waitFor(() => {
+      userEvent.click(getByRole('button', { name: new RegExp(sections[1].displayName, 'i') }));
+      userEvent.click(getByRole('button', { name: new RegExp(subsections[1].displayName, 'i') }));
+    });
+
+    await waitFor(() => {
+      const unitBtn = getByRole('button', { name: new RegExp(units[7].displayName, 'i') });
+      userEvent.click(unitBtn);
+    });
+
+    await waitFor(() => {
+      expect(getByText(
+        messages.moveModalEmptyCategoryText.defaultMessage
+          .replace('{category}', 'unit')
+          .replace('{categoryText}', 'components'),
+      )).toBeInTheDocument();
+    });
+  });
+});
diff --git a/src/course-unit/move-modal/utils.test.ts b/src/course-unit/move-modal/utils.test.ts
new file mode 100644
index 0000000000..8721787de2
--- /dev/null
+++ b/src/course-unit/move-modal/utils.test.ts
@@ -0,0 +1,175 @@
+import { CATEGORIES } from './constants';
+import { ITreeNode, IXBlockInfo, IAncestor } from './interfaces';
+import {
+  getXBlockType, findParentIds, isValidCategory, getBreadcrumbs,
+} from './utils';
+import messages from './messages';
+
+const mockFormatMessage = jest.fn((message) => message.defaultMessage);
+
+const tree: ITreeNode = {
+  id: 'root',
+  childInfo: {
+    children: [
+      {
+        id: 'child-1',
+        childInfo: {
+          children: [
+            {
+              id: 'grandchild-1',
+              childInfo: {
+                children: [],
+              },
+            },
+            {
+              id: 'grandchild-2',
+              childInfo: {
+                children: [],
+              },
+            },
+          ],
+        },
+      },
+      {
+        id: 'child-2',
+        childInfo: {
+          children: [],
+        },
+      },
+    ],
+  },
+};
+
+describe('getXBlockType utility', () => {
+  it('returns section for chapter category', () => {
+    const result = getXBlockType(CATEGORIES.KEYS.chapter);
+    expect(result).toBe(CATEGORIES.KEYS.section);
+  });
+
+  it('returns subsection for sequential category', () => {
+    const result = getXBlockType(CATEGORIES.KEYS.sequential);
+    expect(result).toBe(CATEGORIES.KEYS.subsection);
+  });
+
+  it('returns unit for vertical category', () => {
+    const result = getXBlockType(CATEGORIES.KEYS.vertical);
+    expect(result).toBe(CATEGORIES.KEYS.unit);
+  });
+
+  it('returns the same category if no match is found', () => {
+    const customCategory = 'custom-category';
+    const result = getXBlockType(customCategory);
+    expect(result).toBe(customCategory);
+  });
+});
+
+describe('findParentIds utility', () => {
+  it('returns path to target ID in the tree', () => {
+    const result = findParentIds(tree, 'grandchild-2');
+    expect(result).toEqual(['root', 'child-1', 'grandchild-2']);
+  });
+
+  it('returns empty array if target ID is not found', () => {
+    const result = findParentIds(tree, 'non-existent-id');
+    expect(result).toEqual([]);
+  });
+
+  it('returns path with only root when target ID is the root', () => {
+    const result = findParentIds(tree, 'root');
+    expect(result).toEqual(['root']);
+  });
+
+  it('returns empty array if tree is undefined', () => {
+    const result = findParentIds(undefined, 'some-id');
+    expect(result).toEqual([]);
+  });
+});
+
+describe('isValidCategory utility', () => {
+  const sourceParentInfo: IXBlockInfo = {
+    displayName: 'test-source-parent-name',
+    id: '12345',
+    category: 'chapter',
+    hasChildren: true,
+  };
+  const targetParentInfo: IXBlockInfo = {
+    displayName: 'test-target-parent-name',
+    id: '67890',
+    category: 'chapter',
+    hasChildren: true,
+  };
+
+  it('returns true when target and source categories are the same', () => {
+    const result = isValidCategory(sourceParentInfo, targetParentInfo);
+    expect(result).toBe(true);
+  });
+
+  it('returns false when categories are different', () => {
+    const result = isValidCategory(sourceParentInfo, { ...targetParentInfo, category: 'unit' });
+    expect(result).toBe(false);
+  });
+
+  it('converts source category to vertical if it has children and is not basic block type', () => {
+    const result = isValidCategory(
+      { ...sourceParentInfo, category: 'section' },
+      { ...targetParentInfo, category: 'vertical' },
+    );
+    expect(result).toBe(true);
+  });
+
+  it('converts target category to vertical if it has children and is not basic block type or split_test', () => {
+    const result = isValidCategory(
+      { ...sourceParentInfo, category: 'vertical' },
+      { ...targetParentInfo, category: 'section' },
+    );
+    expect(result).toBe(true);
+  });
+
+  it('returns false when categories are different after conversion', () => {
+    const result = isValidCategory(
+      { ...sourceParentInfo, category: 'chapter' },
+      { ...targetParentInfo, category: 'section' },
+    );
+    expect(result).toBe(false);
+  });
+});
+
+describe('getBreadcrumbs utility', () => {
+  it('returns correct breadcrumb labels for visited ancestors', () => {
+    const visitedAncestors: IAncestor[] = [
+      { category: 'chapter', displayName: 'Chapter 1' },
+      { category: 'section', displayName: 'Section 1' },
+    ];
+
+    const result = getBreadcrumbs(visitedAncestors, mockFormatMessage);
+
+    expect(result).toEqual(['Chapter 1', 'Section 1']);
+  });
+
+  it('returns base category label when category is course', () => {
+    const visitedAncestors: IAncestor[] = [
+      { category: CATEGORIES.KEYS.course, displayName: 'Course Name' },
+    ];
+
+    const result = getBreadcrumbs(visitedAncestors, mockFormatMessage);
+
+    expect(result).toEqual(['Course Outline']);
+    expect(mockFormatMessage).toHaveBeenCalledWith(messages.moveModalBreadcrumbsBaseCategory);
+  });
+
+  it('returns empty string if displayName is missing', () => {
+    const visitedAncestors: IAncestor[] = [
+      { category: 'chapter', displayName: '' },
+    ];
+
+    const result = getBreadcrumbs(visitedAncestors, mockFormatMessage);
+
+    expect(result).toEqual(['']);
+  });
+
+  it('returns empty array if visitedAncestors is not an array', () => {
+    const result = getBreadcrumbs(undefined as any, mockFormatMessage);
+
+    expect(result).toEqual([]);
+  });
+});
diff --git a/src/course-unit/move-modal/utils.ts b/src/course-unit/move-modal/utils.ts
new file mode 100644
index 0000000000..e875d672c6
--- /dev/null
+++ b/src/course-unit/move-modal/utils.ts
@@ -0,0 +1,116 @@
+import { BASIC_BLOCK_TYPES, CATEGORIES } from './constants';
+import { ITreeNode, IXBlockInfo, IAncestor } from './interfaces';
+import messages from './messages';
+
+/**
+ * Determines the XBlock type based on the provided category and parent information.
+ *
+ * @param {string} category - The category of the XBlock (e.g., 'chapter', 'sequential', 'vertical').
+ * @returns {string} - The determined XBlock type (e.g., 'section', 'subsection', 'unit').
+ */
+export const getXBlockType = (category: string): string => {
+  const categoryMap: { [key: string]: string } = {
+    [CATEGORIES.KEYS.chapter]: CATEGORIES.KEYS.section,
+    [CATEGORIES.KEYS.sequential]: CATEGORIES.KEYS.subsection,
+    [CATEGORIES.KEYS.vertical]: CATEGORIES.KEYS.unit,
+  };
+  return categoryMap[category] || category;
+};
+
+/**
+ * Recursively finds the parent IDs of the target ID in a hierarchical object structure.
+ * It returns an array of IDs leading to the target, including the target's own ID.
+ *
+ * @param {Object} tree - The hierarchical object to search through.
+ * @param {string} targetId - The ID of the target element for which to find the parent IDs.
+ * @returns {string[]}  - An array of IDs representing the path from the root to the target element.
+ */
+export const findParentIds = (
+  tree: ITreeNode | undefined,
+  targetId: string,
+): string[] => {
+  let path: string[] = [];
+
+  function traverse(node: ITreeNode | undefined, id: string, currentPath: string[]): boolean {
+    if (!node) {
+      return false;
+    }
+
+    currentPath.push(node.id);
+
+    if (node.id === id) {
+      path = currentPath.slice();
+      return true;
+    }
+
+    for (const child of node.childInfo?.children ?? []) {
+      if (traverse(child, id, currentPath)) {
+        return true;
+      }
+    }
+
+    currentPath.pop();
+    return false;
+  }
+
+  traverse(tree, targetId, []);
+  return path;
+};
+
+/**
+ * Checks if the target category is valid for moving.
+ * @param {Object} sourceParentInfo - Current parent information.
+ * @param {Object} targetParentInfo - Target parent information.
+ * @returns {boolean} - Returns true if moving is valid.
+ */
+export const isValidCategory = (
+  sourceParentInfo: IXBlockInfo,
+  targetParentInfo: IXBlockInfo,
+): boolean => {
+  let { category: sourceParentCategory } = sourceParentInfo;
+  let { category: targetParentCategory } = targetParentInfo;
+  const { hasChildren: sourceParentHasChildren } = sourceParentInfo;
+  const { hasChildren: targetParentHasChildren } = targetParentInfo;
+
+  if (
+    sourceParentHasChildren
+      && sourceParentCategory
+      && !(BASIC_BLOCK_TYPES as readonly string[]).includes(sourceParentCategory)
+  ) {
+    sourceParentCategory = CATEGORIES.KEYS.vertical;
+  }
+
+  if (
+    targetParentHasChildren
+      && targetParentCategory
+      && !(BASIC_BLOCK_TYPES as readonly string[]).includes(targetParentCategory)
+      && targetParentCategory !== CATEGORIES.KEYS.split_test
+  ) {
+    targetParentCategory = CATEGORIES.KEYS.vertical;
+  }
+
+  return targetParentCategory === sourceParentCategory;
+};
+
+/**
+ * Builds breadcrumbs based on visited ancestors.
+ * @param {Array} visitedAncestors - Array of ancestors.
+ * @param {Function} formatMessage - Intl formatting function.
+ * @returns {Array} - Array of breadcrumb elements.
+ */
+export const getBreadcrumbs = (
+  visitedAncestors: IAncestor[],
+  formatMessage: any,
+): string[] => {
+  if (!Array.isArray(visitedAncestors)) {
+    return [];
+  }
+
+  return visitedAncestors.map((ancestor) => {
+    if (ancestor?.category === CATEGORIES.KEYS.course) {
+      return formatMessage(messages.moveModalBreadcrumbsBaseCategory);
+    }
+
+    return ancestor?.displayName || '';
+  });
+};
diff --git a/src/course-unit/xblock-container-iframe/index.tsx b/src/course-unit/xblock-container-iframe/index.tsx
index df3e6528bf..761d637750 100644
--- a/src/course-unit/xblock-container-iframe/index.tsx
+++ b/src/course-unit/xblock-container-iframe/index.tsx
@@ -1,9 +1,10 @@
-import { useRef, FC } from 'react';
+import { useRef, useEffect, FC } from 'react';
 import PropTypes from 'prop-types';
 import { useIntl } from '@edx/frontend-platform/i18n';
 import { getConfig } from '@edx/frontend-platform';
 
 import { IFRAME_FEATURE_POLICY } from '../constants';
+import { useIframe } from '../context/hooks';
 import { useIFrameBehavior } from './hooks';
 import messages from './messages';
 
@@ -20,6 +21,7 @@ interface XBlockContainerIframeProps {
 const XBlockContainerIframe: FC<XBlockContainerIframeProps> = ({ blockId }) => {
   const intl = useIntl();
   const iframeRef = useRef<HTMLIFrameElement>(null);
+  const { setIframeRef } = useIframe();
 
   const iframeUrl = `${getConfig().STUDIO_BASE_URL}/container_embed/${blockId}`;
 
@@ -28,6 +30,10 @@ const XBlockContainerIframe: FC<XBlockContainerIframeProps> = ({ blockId }) => {
     iframeUrl,
   });
 
+  useEffect(() => {
+    setIframeRef(iframeRef);
+  }, [setIframeRef]);
+
   return (
     <iframe
       ref={iframeRef}
diff --git a/src/course-unit/xblock-container-iframe/tests/XblockContainerIframe.test.tsx b/src/course-unit/xblock-container-iframe/tests/XblockContainerIframe.test.tsx
index 3b940fda43..b3bee233b8 100644
--- a/src/course-unit/xblock-container-iframe/tests/XblockContainerIframe.test.tsx
+++ b/src/course-unit/xblock-container-iframe/tests/XblockContainerIframe.test.tsx
@@ -5,6 +5,7 @@ import { IntlProvider } from '@edx/frontend-platform/i18n';
 import { IFRAME_FEATURE_POLICY } from '../../constants';
 import { useIFrameBehavior } from '../hooks';
 import XBlockContainerIframe from '..';
+import { IframeProvider } from '../../context/iFrameContext';
 
 jest.mock('@edx/frontend-platform', () => ({
   getConfig: jest.fn(),
@@ -27,7 +28,9 @@ describe('<XBlockContainerIframe />', () => {
   it('renders correctly with the given blockId', () => {
     const { getByTitle } = render(
       <IntlProvider locale="en">
-        <XBlockContainerIframe blockId={blockId} />
+        <IframeProvider>
+          <XBlockContainerIframe blockId={blockId} />
+        </IframeProvider>
       </IntlProvider>,
     );
     const iframe = getByTitle('Course unit iframe');