Skip to content

Commit

Permalink
feat: new edit modals
Browse files Browse the repository at this point in the history
  • Loading branch information
PKulkoRaccoonGang committed Oct 24, 2024
1 parent 02e30fe commit 42da735
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 68 deletions.
18 changes: 2 additions & 16 deletions src/course-unit/CourseUnit.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState, useMemo } from 'react';
import { useEffect } from 'react';
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';
Expand Down Expand Up @@ -60,7 +60,6 @@ const CourseUnit = ({ courseId }) => {
handleCreateNewCourseXBlock,
handleConfigureSubmit,
courseVerticalChildren,
handleXBlockDragAndDrop,
canPasteComponent,
isMoveModalOpen,
openMoveModal,
Expand All @@ -70,18 +69,11 @@ const CourseUnit = ({ courseId }) => {
handleCloseXBlockMovedAlert,
handleNavigateToTargetUnit,
} = useCourseUnit({ courseId, blockId });
const initialXBlocksData = useMemo(() => courseVerticalChildren.children ?? [], [courseVerticalChildren.children]);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [unitXBlocks, setUnitXBlocks] = useState(initialXBlocksData);

useEffect(() => {
document.title = getPageHeadTitle('', unitTitle);
}, [unitTitle]);

useEffect(() => {
setUnitXBlocks(courseVerticalChildren.children);
}, [courseVerticalChildren.children]);

const {
isShow: isShowProcessingNotification,
title: processingNotificationTitle,
Expand All @@ -99,12 +91,6 @@ const CourseUnit = ({ courseId }) => {
);
}

const finalizeXBlockOrder = () => (newXBlocks) => {
handleXBlockDragAndDrop(newXBlocks.map(xBlock => xBlock.id), () => {
setUnitXBlocks(initialXBlocksData);
});
};

return (
<>
<Container size="xl" className="course-unit px-4">
Expand Down Expand Up @@ -193,11 +179,11 @@ const CourseUnit = ({ courseId }) => {
/>
)}
<XBlockContainerIframe
courseId={courseId}
blockId={blockId}
unitXBlockActions={unitXBlockActions}
xblocks={courseVerticalChildren.children}
handleConfigureSubmit={handleConfigureSubmit}
finalizeXBlockOrder={finalizeXBlockOrder}
/>
<AddComponent
blockId={blockId}
Expand Down
1 change: 1 addition & 0 deletions src/course-unit/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const messageTypes = {
deleteXBlock: 'deleteXBlock',
duplicateXBlock: 'duplicateXBlock',
refreshPositions: 'refreshPositions',
newXBlockEditor: 'newXBlockEditor',
};

export const IFRAME_FEATURE_POLICY = (
Expand Down
13 changes: 0 additions & 13 deletions src/course-unit/data/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,19 +150,6 @@ export async function duplicateUnitItem(itemId, XBlockId) {
return data;
}

/**
* Sets the order list of XBlocks.
* @param {string} blockId - The identifier of the course unit.
* @param {Object[]} children - The array of child elements representing the updated order of XBlocks.
* @returns {Promise<Object>} - A promise that resolves to the updated data after setting the XBlock order.
*/
export async function setXBlockOrderList(blockId, children) {
const { data } = await getAuthenticatedHttpClient()
.put(getXBlockBaseApiUrl(blockId), { children });

return data;
}

/**
* Get an object containing course outline data.
* @param {string} courseId - The identifier of the course.
Expand Down
25 changes: 0 additions & 25 deletions src/course-unit/data/thunk.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
handleCourseUnitVisibilityAndData,
deleteUnitItem,
duplicateUnitItem,
setXBlockOrderList,
getCourseOutlineInfo,
patchUnitItem,
} from './api';
Expand Down Expand Up @@ -48,7 +47,6 @@ export function fetchCourseUnitQuery(courseId) {

try {
const courseUnit = await getCourseUnitData(courseId);
console.log('courseUnit =========>', courseUnit);
dispatch(fetchCourseItemSuccess(courseUnit));
dispatch(updateLoadingCourseUnitStatus({ status: RequestStatus.SUCCESSFUL }));
return true;
Expand Down Expand Up @@ -247,29 +245,6 @@ export function duplicateUnitItemQuery(itemId, xblockId) {
};
}

export function setXBlockOrderListQuery(blockId, xblockListIds, restoreCallback) {
return async (dispatch) => {
dispatch(updateSavingStatus({ status: RequestStatus.PENDING }));
dispatch(showProcessingNotification(NOTIFICATION_MESSAGES.saving));

try {
await setXBlockOrderList(blockId, xblockListIds).then(async (result) => {
if (result) {
// dispatch(reorderXBlockList(xblockListIds));
dispatch(updateSavingStatus({ status: RequestStatus.SUCCESSFUL }));
const courseUnit = await getCourseUnitData(blockId);
dispatch(fetchCourseItemSuccess(courseUnit));
}
});
} catch (error) {
restoreCallback();
handleResponseErrors(error, dispatch, updateSavingStatus);
} finally {
dispatch(hideProcessingNotification());
}
};
}

export function getCourseOutlineInfoQuery(courseId) {
return async (dispatch) => {
dispatch(updateCourseOutlineInfoLoadingStatus({ status: RequestStatus.IN_PROGRESS }));
Expand Down
6 changes: 0 additions & 6 deletions src/course-unit/hooks.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
fetchCourseVerticalChildrenData,
deleteUnitItemQuery,
duplicateUnitItemQuery,
setXBlockOrderListQuery,
editCourseUnitVisibilityAndData,
getCourseOutlineInfoQuery,
patchUnitItemQuery,
Expand Down Expand Up @@ -121,10 +120,6 @@ export const useCourseUnit = ({ courseId, blockId }) => {
},
};

const handleXBlockDragAndDrop = (xblockListIds, restoreCallback) => {
dispatch(setXBlockOrderListQuery(blockId, xblockListIds, restoreCallback));
};

const handleRollbackMovedXBlock = () => {
const {
sourceLocator, targetParentLocator, title, currentParentLocator,
Expand Down Expand Up @@ -193,7 +188,6 @@ export const useCourseUnit = ({ courseId, blockId }) => {
handleCreateNewCourseXBlock,
handleConfigureSubmit,
courseVerticalChildren,
handleXBlockDragAndDrop,
canPasteComponent,
isMoveModalOpen,
openMoveModal,
Expand Down
2 changes: 2 additions & 0 deletions src/course-unit/sidebar/PublishControls.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ const PublishControls = ({ blockId }) => {
const handleCourseUnitDiscardChanges = () => {
closeDiscardModal();
dispatch(editCourseUnitVisibilityAndData(blockId, PUBLISH_TYPES.discardChanges));
// TODO: this artificial delay is a temporary solution
// to ensure the iframe content is properly refreshed.
setTimeout(() => {
sendMessageToIframe(messageTypes.refreshXBlock, null);
}, 1000);
Expand Down
36 changes: 28 additions & 8 deletions src/course-unit/xblock-container-iframe/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useIntl } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform';
import { useToggle } from '@openedx/paragon';
import { useDispatch } from 'react-redux';
import { useNavigate } from 'react-router-dom';

import DeleteModal from '../../generic/delete-modal/DeleteModal';
import ConfigureModal from '../../generic/configure-modal/ConfigureModal';
Expand All @@ -19,6 +20,7 @@ import messages from './messages';
const IFRAME_BOTTOM_OFFSET = 220;

interface XBlockContainerIframeProps {
courseId: string;
blockId: string;
unitXBlockActions: {
handleDelete: (XBlockId: string) => void;
Expand Down Expand Up @@ -60,18 +62,19 @@ interface XBlockContainerIframeProps {
}

const XBlockContainerIframe: FC<XBlockContainerIframeProps> = ({
blockId, unitXBlockActions, xblocks, handleConfigureSubmit, finalizeXBlockOrder,
courseId, blockId, unitXBlockActions, xblocks, handleConfigureSubmit,
}) => {
const intl = useIntl();
const iframeRef = useRef<HTMLIFrameElement>(null);
const dispatch = useDispatch();
const { setIframeRef, sendMessageToIframe } = useIframe();
const navigate = useNavigate();

const [deleteXblockId, setDeleteXblockId] = useState<string | null>(null);
const [editXblockId, setEditXblockId] = useState<string | null>(null);
const [currentXblockData, setCurrentXblockData] = useState<Record<string, any>>({});
const [isDeleteModalOpen, openDeleteModal, closeDeleteModal] = useToggle(false);
const [isConfigureModalOpen, openConfigureModal, closeConfigureModal] = useToggle(false);
const { setIframeRef, sendMessageToIframe } = useIframe();
const [editXblockId, setEditXblockId] = useState<string | null>(null);
const [currentXblockData, setCurrentXblockData] = useState<Record<string, any>>({});

const iframeUrl = `${getConfig().STUDIO_BASE_URL}/container_embed/${blockId}`;

Expand All @@ -87,13 +90,16 @@ const XBlockContainerIframe: FC<XBlockContainerIframeProps> = ({
const handleConfigure = (id: string) => {
openConfigureModal();
setEditXblockId(id);
const foundBlock = xblocks?.find(block => block.blockId === id);

if (foundBlock) {
const foundXBlockInfo = xblocks?.find(block => block.blockId === id);

if (foundXBlockInfo) {
const { name, userPartitionInfo } = foundXBlockInfo;

setCurrentXblockData({
category: COURSE_BLOCK_NAMES.component.id,
displayName: foundBlock.name,
userPartitionInfo: foundBlock.userPartitionInfo,
displayName: name,
userPartitionInfo,
showCorrectness: 'always',
});
}
Expand All @@ -106,29 +112,39 @@ const XBlockContainerIframe: FC<XBlockContainerIframeProps> = ({
const handleDuplicateXBlock = (id) => {
if (id) {
unitXBlockActions.handleDuplicate(id);
// TODO: this artificial delay is a temporary solution
// to ensure the iframe content is properly refreshed.
setTimeout(() => {
sendMessageToIframe(messageTypes.refreshXBlock, null);
}, 1000);
}
};

const handleRefreshXBlocks = () => {
// TODO: this artificial delay is a temporary solution
// to ensure the iframe content is properly refreshed.
setTimeout(() => {
dispatch(fetchCourseUnitQuery(blockId));
}, 1000);
};

const navigateToNewXBlockEditor = (url: string) => {
navigate(`/course/${courseId}/editor${url}`);
};

useEffect(() => {
const messageHandlers: Record<string, (payload) => void> = {
[messageTypes.deleteXBlock]: (payload) => handleDelete(payload.id),
[messageTypes.manageXBlockAccess]: (payload) => handleConfigure(payload.id),
[messageTypes.copyXBlock]: (payload) => handleCopy(payload.id),
[messageTypes.duplicateXBlock]: (payload) => handleDuplicateXBlock(payload.id),
[messageTypes.refreshPositions]: handleRefreshXBlocks,
[messageTypes.newXBlockEditor]: (payload) => navigateToNewXBlockEditor(payload.url),
};

const handleMessage = (event: MessageEvent) => {
const { type, payload } = event.data || {};
console.log('MESSAGE FROM IFRAME =================>', { type, payload });
if (type && messageHandlers[type]) {
messageHandlers[type](payload);
}
Expand All @@ -150,6 +166,8 @@ const XBlockContainerIframe: FC<XBlockContainerIframeProps> = ({
if (deleteXblockId) {
unitXBlockActions.handleDelete(deleteXblockId);
closeDeleteModal();
// TODO: this artificial delay is a temporary solution
// to ensure the iframe content is properly refreshed.
setTimeout(() => {
sendMessageToIframe(messageTypes.refreshXBlock, null);
}, 1000);
Expand All @@ -159,6 +177,8 @@ const XBlockContainerIframe: FC<XBlockContainerIframeProps> = ({
const onConfigureSubmit = (...args: any[]) => {
if (editXblockId) {
handleConfigureSubmit(editXblockId, ...args, closeConfigureModal);
// TODO: this artificial delay is a temporary solution
// to ensure the iframe content is properly refreshed.
setTimeout(() => {
sendMessageToIframe(messageTypes.refreshXBlock, null);
}, 1000);
Expand Down
3 changes: 3 additions & 0 deletions src/editors/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ export const initializeApp = ({ dispatch, data }) => useEffect(
);

export const navigateTo = (destination) => {
// TODO: once the "Remove backend redirects (use SPA functionality)" PR (#1372) is merged,
// the editor will utilize SPA functionality, allowing navigation back
// to the course unit page without a full page reload.
window.location.assign(destination);
};

Expand Down

0 comments on commit 42da735

Please sign in to comment.