Skip to content

Commit

Permalink
feat: listen to xblock interaction events
Browse files Browse the repository at this point in the history
feat: new edit modals
  • Loading branch information
PKulkoRaccoonGang committed Oct 25, 2024
1 parent e9e8ec4 commit cfcb208
Show file tree
Hide file tree
Showing 9 changed files with 262 additions and 37 deletions.
10 changes: 9 additions & 1 deletion src/course-unit/CourseUnit.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const CourseUnit = ({ courseId }) => {
isTitleEditFormOpen,
staticFileNotices,
currentlyVisibleToStudents,
unitXBlockActions,
sharedClipboardData,
showPasteXBlock,
showPasteUnit,
Expand All @@ -58,6 +59,7 @@ const CourseUnit = ({ courseId }) => {
handleTitleEdit,
handleCreateNewCourseXBlock,
handleConfigureSubmit,
courseVerticalChildren,
canPasteComponent,
isMoveModalOpen,
openMoveModal,
Expand Down Expand Up @@ -176,7 +178,13 @@ const CourseUnit = ({ courseId }) => {
courseId={courseId}
/>
)}
<XBlockContainerIframe blockId={blockId} />
<XBlockContainerIframe
courseId={courseId}
blockId={blockId}
unitXBlockActions={unitXBlockActions}
xblocks={courseVerticalChildren.children}
handleConfigureSubmit={handleConfigureSubmit}
/>
<AddComponent
blockId={blockId}
handleCreateNewCourseXBlock={handleCreateNewCourseXBlock}
Expand Down
6 changes: 6 additions & 0 deletions src/course-unit/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ export const messageTypes = {
videoFullScreen: 'plugin.videoFullScreen',
refreshXBlock: 'refreshXBlock',
showMoveXBlockModal: 'showMoveXBlockModal',
copyXBlock: 'copyXBlock',
manageXBlockAccess: 'manageXBlockAccess',
deleteXBlock: 'deleteXBlock',
duplicateXBlock: 'duplicateXBlock',
refreshPositions: 'refreshPositions',
newXBlockEditor: 'newXBlockEditor',
};

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

/**
* Duplicate a unit item.
* @param {string} itemId
* @param {string} XBlockId
* @returns {Promise<Object>}
*/
export async function duplicateUnitItem(itemId, XBlockId) {
const { data } = await getAuthenticatedHttpClient()
.post(postXBlockBaseApiUrl(), {
parent_locator: itemId,
duplicate_source_locator: XBlockId,
});

return data;
}

/**
* Get an object containing course outline data.
* @param {string} courseId - The identifier of the course.
Expand Down
2 changes: 1 addition & 1 deletion src/course-unit/data/slice.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const slice = createSlice({
title: '',
sourceLocator: '',
targetParentLocator: '',
}
},
},
reducers: {
fetchCourseItemSuccess: (state, { payload }) => {
Expand Down
20 changes: 19 additions & 1 deletion src/course-unit/data/thunk.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
getCourseVerticalChildren,
handleCourseUnitVisibilityAndData,
deleteUnitItem,
duplicateUnitItem,
getCourseOutlineInfo,
patchUnitItem,
} from './api';
Expand Down Expand Up @@ -206,7 +207,6 @@ export function fetchCourseVerticalChildrenData(itemId) {
};
}

// TODO: use for xblock delete functionality
export function deleteUnitItemQuery(itemId, xblockId) {
return async (dispatch) => {
dispatch(updateSavingStatus({ status: RequestStatus.PENDING }));
Expand All @@ -227,6 +227,24 @@ export function deleteUnitItemQuery(itemId, xblockId) {
};
}

export function duplicateUnitItemQuery(itemId, xblockId) {
return async (dispatch) => {
dispatch(updateSavingStatus({ status: RequestStatus.PENDING }));
dispatch(showProcessingNotification(NOTIFICATION_MESSAGES.duplicating));

try {
await duplicateUnitItem(itemId, xblockId);
const courseUnit = await getCourseUnitData(itemId);
dispatch(fetchCourseItemSuccess(courseUnit));
dispatch(hideProcessingNotification());
dispatch(updateSavingStatus({ status: RequestStatus.SUCCESSFUL }));
} catch (error) {
dispatch(hideProcessingNotification());
handleResponseErrors(error, dispatch, updateSavingStatus);
}
};
}

export function getCourseOutlineInfoQuery(courseId) {
return async (dispatch) => {
dispatch(updateCourseOutlineInfoLoadingStatus({ status: RequestStatus.IN_PROGRESS }));
Expand Down
13 changes: 9 additions & 4 deletions src/course-unit/hooks.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useContext, useEffect } from 'react';
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { useToggle } from '@openedx/paragon';
Expand All @@ -13,6 +13,7 @@ import {
fetchCourseSectionVerticalData,
fetchCourseVerticalChildrenData,
deleteUnitItemQuery,
duplicateUnitItemQuery,
editCourseUnitVisibilityAndData,
getCourseOutlineInfoQuery,
patchUnitItemQuery,
Expand All @@ -38,7 +39,6 @@ import {
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();
Expand Down Expand Up @@ -112,14 +112,18 @@ export const useCourseUnit = ({ courseId, blockId }) => {
);

const unitXBlockActions = {
// TODO: use for xblock delete functionality
handleDelete: (XBlockId) => {
dispatch(deleteUnitItemQuery(blockId, XBlockId));
},
handleDuplicate: (XBlockId) => {
dispatch(duplicateUnitItemQuery(blockId, XBlockId));
},
};

const handleRollbackMovedXBlock = () => {
const { sourceLocator, targetParentLocator, title, currentParentLocator } = movedXBlockParams;
const {
sourceLocator, targetParentLocator, title, currentParentLocator,
} = movedXBlockParams;
dispatch(patchUnitItemQuery({
sourceLocator,
targetParentLocator,
Expand Down Expand Up @@ -183,6 +187,7 @@ export const useCourseUnit = ({ courseId, blockId }) => {
handleTitleEditSubmit,
handleCreateNewCourseXBlock,
handleConfigureSubmit,
courseVerticalChildren,
canPasteComponent,
isMoveModalOpen,
openMoveModal,
Expand Down
9 changes: 8 additions & 1 deletion src/course-unit/sidebar/PublishControls.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { useToggle } from '@openedx/paragon';
import { InfoOutline as InfoOutlineIcon } from '@openedx/paragon/icons';
import { useIntl } from '@edx/frontend-platform/i18n';
import useCourseUnitData from './hooks';
import { useIframe } from '../context/hooks';
import { editCourseUnitVisibilityAndData } from '../data/thunk';
import { SidebarBody, SidebarFooter, SidebarHeader } from './components';
import { PUBLISH_TYPES } from '../constants';
import { PUBLISH_TYPES, messageTypes } from '../constants';
import { getCourseUnitData } from '../data/selectors';
import messages from './messages';
import ModalNotification from '../../generic/modal-notification';
Expand All @@ -20,6 +21,7 @@ const PublishControls = ({ blockId }) => {
visibleToStaffOnly,
} = useCourseUnitData(useSelector(getCourseUnitData));
const intl = useIntl();
const { sendMessageToIframe } = useIframe();

const [isDiscardModalOpen, openDiscardModal, closeDiscardModal] = useToggle(false);
const [isVisibleModalOpen, openVisibleModal, closeVisibleModal] = useToggle(false);
Expand All @@ -34,6 +36,11 @@ 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);
};

const handleCourseUnitPublish = () => {
Expand Down
Loading

0 comments on commit cfcb208

Please sign in to comment.