Skip to content

Commit 71816a2

Browse files
committed
feat: Enable Delete in all container info sidebars
1 parent 0fd1d2e commit 71816a2

5 files changed

Lines changed: 98 additions & 77 deletions

File tree

src/CourseAuthoringContext.tsx

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { getConfig } from '@edx/frontend-platform';
22
import {
3-
createContext, useContext, useEffect, useMemo, useState,
3+
createContext, useCallback, useContext, useEffect, useMemo, useState,
44
} from 'react';
55
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
6-
import { useCreateCourseBlock, useDuplicateItem } from '@src/course-outline/data/apiHooks';
6+
import { useCreateCourseBlock, useDeleteCourseItem, useDuplicateItem } from '@src/course-outline/data/apiHooks';
77
import { useDispatch, useSelector } from 'react-redux';
88
import { useNavigate } from 'react-router';
99
import { getOutlineIndexData, getSectionsList } from '@src/course-outline/data/selectors';
@@ -14,6 +14,10 @@ import { useCourseDetails, useWaffleFlags } from './data/apiHooks';
1414
import { RequestStatusType } from './data/constants';
1515
import { arrayMove } from '@dnd-kit/sortable';
1616
import { fetchCourseOutlineIndexQuery, setSectionOrderListQuery, setSubsectionOrderListQuery, setUnitOrderListQuery } from './course-outline/data/thunk';
17+
import { useToggle } from '@openedx/paragon';
18+
import { getBlockType } from './generic/key-utils';
19+
import { COURSE_BLOCK_NAMES } from './constants';
20+
import { deleteSection, deleteSubsection, deleteUnit } from './course-outline/data/slice';
1721

1822
type ModalState = {
1923
value?: XBlock | UnitXBlock;
@@ -46,6 +50,10 @@ export type CourseAuthoringContextData = {
4650
restoreSectionList: () => void;
4751
setSections: React.Dispatch<React.SetStateAction<XBlock[]>>;
4852
isDuplicatingItem: boolean;
53+
isDeleteModalOpen: boolean;
54+
openDeleteModal: () => void;
55+
closeDeleteModal: () => void;
56+
getHandleDeleteItemSubmit: (callback: () => void) => () => Promise<void>;
4957
handleDuplicateSectionSubmit: () => void;
5058
handleDuplicateSubsectionSubmit: () => void;
5159
handleDuplicateUnitSubmit: () => void;
@@ -96,6 +104,8 @@ export const CourseAuthoringProvider = ({
96104
] = useToggleWithValue<ModalState>();
97105
const sectionsList = useSelector(getSectionsList);
98106
const [sections, setSections] = useState<XBlock[]>(sectionsList);
107+
const [isDeleteModalOpen, openDeleteModal, closeDeleteModal] = useToggle(false);
108+
99109

100110
const restoreSectionList = () => {
101111
setSections(() => [...sectionsList]);
@@ -272,6 +282,68 @@ export const CourseAuthoringProvider = ({
272282
}
273283
};
274284

285+
const deleteMutation = useDeleteCourseItem();
286+
287+
const getHandleDeleteItemSubmit = useCallback((callback: () => void) => {
288+
return async () => {
289+
// istanbul ignore if
290+
if (!currentSelection) {
291+
return;
292+
}
293+
const category = getBlockType(currentSelection.currentId);
294+
switch (category) {
295+
case COURSE_BLOCK_NAMES.chapter.id:
296+
await deleteMutation.mutateAsync(
297+
{ itemId: currentSelection.currentId },
298+
{
299+
onSettled: () => dispatch(deleteSection({ itemId: currentSelection.currentId })),
300+
},
301+
);
302+
break;
303+
case COURSE_BLOCK_NAMES.sequential.id:
304+
await deleteMutation.mutateAsync(
305+
{ itemId: currentSelection.currentId, sectionId: currentSelection.sectionId },
306+
{
307+
onSettled: () => dispatch(deleteSubsection({
308+
itemId: currentSelection.currentId,
309+
sectionId: currentSelection.sectionId,
310+
})),
311+
},
312+
);
313+
break;
314+
case COURSE_BLOCK_NAMES.vertical.id:
315+
await deleteMutation.mutateAsync(
316+
{
317+
itemId: currentSelection.currentId,
318+
subsectionId: currentSelection.subsectionId,
319+
sectionId: currentSelection.sectionId,
320+
},
321+
{
322+
onSettled: () => dispatch(deleteUnit({
323+
itemId: currentSelection.currentId,
324+
subsectionId: currentSelection.subsectionId,
325+
sectionId: currentSelection.sectionId,
326+
})),
327+
},
328+
);
329+
break;
330+
default:
331+
// istanbul ignore next
332+
throw new Error(`Unrecognized category ${category}`);
333+
}
334+
closeDeleteModal();
335+
callback();
336+
};
337+
}, [
338+
deleteMutation,
339+
closeDeleteModal,
340+
currentSelection,
341+
dispatch,
342+
deleteSection,
343+
deleteUnit,
344+
deleteSubsection,
345+
]);
346+
275347
const context = useMemo<CourseAuthoringContextData>(() => ({
276348
courseId,
277349
courseUsageKey,
@@ -296,6 +368,10 @@ export const CourseAuthoringProvider = ({
296368
restoreSectionList,
297369
setSections,
298370
isDuplicatingItem,
371+
isDeleteModalOpen,
372+
openDeleteModal,
373+
closeDeleteModal,
374+
getHandleDeleteItemSubmit,
299375
handleDuplicateSectionSubmit,
300376
handleDuplicateSubsectionSubmit,
301377
handleDuplicateUnitSubmit,
@@ -329,6 +405,10 @@ export const CourseAuthoringProvider = ({
329405
restoreSectionList,
330406
setSections,
331407
isDuplicatingItem,
408+
isDeleteModalOpen,
409+
openDeleteModal,
410+
closeDeleteModal,
411+
getHandleDeleteItemSubmit,
332412
handleDuplicateSectionSubmit,
333413
handleDuplicateSubsectionSubmit,
334414
handleSectionDragAndDrop,

src/course-outline/hooks.jsx

Lines changed: 10 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ import {
2424
} from '@src/course-outline/data/apiHooks';
2525
import { COURSE_BLOCK_NAMES } from './constants';
2626
import {
27-
deleteSection,
28-
deleteSubsection,
29-
deleteUnit,
3027
updateSavingStatus,
3128
} from './data/slice';
3229
import {
@@ -45,9 +42,7 @@ import {
4542
fetchCourseLaunchQuery,
4643
fetchCourseOutlineIndexQuery,
4744
fetchCourseReindexQuery,
48-
setSectionOrderListQuery,
4945
setVideoSharingOptionQuery,
50-
setSubsectionOrderListQuery,
5146
dismissNotificationQuery,
5247
syncDiscussionsTopics,
5348
} from './data/thunk';
@@ -61,6 +56,10 @@ const useCourseOutline = ({ courseId }) => {
6156
currentUnlinkModalData,
6257
closeUnlinkModal,
6358
isDuplicatingItem,
59+
isDeleteModalOpen,
60+
openDeleteModal,
61+
closeDeleteModal,
62+
getHandleDeleteItemSubmit,
6463
handleDuplicateSectionSubmit,
6564
handleDuplicateSubsectionSubmit,
6665
handleDuplicateUnitSubmit,
@@ -70,6 +69,12 @@ const useCourseOutline = ({ courseId }) => {
7069
} = useCourseAuthoringContext();
7170
const { selectedContainerState, clearSelection } = useOutlineSidebarContext();
7271

72+
const handleDeleteItemSubmit = getHandleDeleteItemSubmit(() => {
73+
if (selectedContainerState.currentId === currentSelection?.currentId) {
74+
clearSelection();
75+
}
76+
});
77+
7378
const {
7479
reindexLink,
7580
courseStructure,
@@ -99,8 +104,6 @@ const useCourseOutline = ({ courseId }) => {
99104
const [showSuccessAlert, setShowSuccessAlert] = useState(false);
100105
const [isHighlightsModalOpen, openHighlightsModal, closeHighlightsModal] = useToggle(false);
101106
const [isConfigureModalOpen, openConfigureModal, closeConfigureModal] = useToggle(false);
102-
const [isDeleteModalOpen, openDeleteModal, closeDeleteModal] = useToggle(false);
103-
const queryClient = useQueryClient();
104107

105108
const isSavingStatusFailed = savingStatus === RequestStatus.FAILED || genericSavingStatus === RequestStatus.FAILED;
106109

@@ -236,71 +239,6 @@ const useCourseOutline = ({ courseId }) => {
236239
handleConfigureModalClose();
237240
};
238241

239-
const deleteMutation = useDeleteCourseItem();
240-
241-
const handleDeleteItemSubmit = useCallback(async () => {
242-
// istanbul ignore if
243-
if (!currentSelection) {
244-
return;
245-
}
246-
const category = getBlockType(currentSelection.currentId);
247-
switch (category) {
248-
case COURSE_BLOCK_NAMES.chapter.id:
249-
await deleteMutation.mutateAsync(
250-
{ itemId: currentSelection.currentId },
251-
{
252-
onSettled: () => dispatch(deleteSection({ itemId: currentSelection.currentId })),
253-
},
254-
);
255-
break;
256-
case COURSE_BLOCK_NAMES.sequential.id:
257-
await deleteMutation.mutateAsync(
258-
{ itemId: currentSelection.currentId, sectionId: currentSelection.sectionId },
259-
{
260-
onSettled: () => dispatch(deleteSubsection({
261-
itemId: currentSelection.currentId,
262-
sectionId: currentSelection.sectionId,
263-
})),
264-
},
265-
);
266-
break;
267-
case COURSE_BLOCK_NAMES.vertical.id:
268-
await deleteMutation.mutateAsync(
269-
{
270-
itemId: currentSelection.currentId,
271-
subsectionId: currentSelection.subsectionId,
272-
sectionId: currentSelection.sectionId,
273-
},
274-
{
275-
onSettled: () => dispatch(deleteUnit({
276-
itemId: currentSelection.currentId,
277-
subsectionId: currentSelection.subsectionId,
278-
sectionId: currentSelection.sectionId,
279-
})),
280-
},
281-
);
282-
break;
283-
default:
284-
// istanbul ignore next
285-
throw new Error(`Unrecognized category ${category}`);
286-
}
287-
closeDeleteModal();
288-
if (selectedContainerState.currentId === currentSelection?.currentId) {
289-
clearSelection();
290-
}
291-
}, [
292-
deleteMutation,
293-
clearSelection,
294-
closeDeleteModal,
295-
queryClient,
296-
currentSelection,
297-
courseOutlineQueryKeys,
298-
dispatch,
299-
deleteSection,
300-
deleteUnit,
301-
deleteSubsection,
302-
]);
303-
304242
const handleVideoSharingOptionChange = (value) => {
305243
dispatch(setVideoSharingOptionQuery(courseId, value));
306244
};

src/course-outline/outline-sidebar/info-sidebar/SectionInfoSidebar.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export const SectionSidebar = () => {
2626
handleDuplicateSectionSubmit,
2727
sections,
2828
updateSectionOrderByIndex,
29+
openDeleteModal,
2930
} = useCourseAuthoringContext();
3031

3132
const handlePublish = () => {
@@ -62,7 +63,7 @@ export const SectionSidebar = () => {
6263
onClickMoveUp: () => handleMove(-1),
6364
onClickMoveDown: () => handleMove(1),
6465
onClickUnlink: () => {},
65-
onClickDelete: () => {},
66+
onClickDelete: openDeleteModal,
6667
onClickViewLibrary: () => {},
6768
}}
6869
/>

src/course-outline/outline-sidebar/info-sidebar/SubsectionInfoSidebar.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export const SubsectionSidebar = () => {
3333
handleDuplicateSubsectionSubmit,
3434
sections,
3535
updateSubsectionOrderByIndex,
36+
openDeleteModal,
3637
} = useCourseAuthoringContext();
3738

3839
const handlePublish = () => {
@@ -104,7 +105,7 @@ export const SubsectionSidebar = () => {
104105
onClickMoveUp: () => handleMove(-1),
105106
onClickMoveDown: () => handleMove(1),
106107
onClickUnlink: () => {},
107-
onClickDelete: () => {},
108+
onClickDelete: openDeleteModal,
108109
onClickViewLibrary: () => {},
109110
}}
110111
/>

src/course-outline/outline-sidebar/info-sidebar/UnitInfoSidebar.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export const UnitSidebar = () => {
4141
handleDuplicateUnitSubmit,
4242
sections,
4343
updateUnitOrderByIndex,
44+
openDeleteModal,
4445
} = useCourseAuthoringContext();
4546

4647
const handlePublish = () => {
@@ -128,7 +129,7 @@ export const UnitSidebar = () => {
128129
onClickMoveUp: () => handleMove(-1),
129130
onClickMoveDown: () => handleMove(1),
130131
onClickUnlink: () => {},
131-
onClickDelete: () => {},
132+
onClickDelete: openDeleteModal,
132133
onClickViewLibrary: () => {},
133134
onClickCopy: () => {},
134135
onClickCopyLocation: () => {},

0 commit comments

Comments
 (0)