1+ import { getConfig } from '@edx/frontend-platform' ;
12import { createContext , useContext , useMemo } from 'react' ;
23import { getAuthenticatedUser } from '@edx/frontend-platform/auth' ;
4+ import { useCreateCourseBlock } from '@src/course-outline/data/apiHooks' ;
5+ import { getCourseItem } from '@src/course-outline/data/api' ;
6+ import { useDispatch , useSelector } from 'react-redux' ;
7+ import { addSection , addSubsection , updateSavingStatus } from '@src/course-outline/data/slice' ;
8+ import { addNewSectionQuery , addNewSubsectionQuery , addNewUnitQuery } from '@src/course-outline/data/thunk' ;
9+ import { useNavigate } from 'react-router' ;
10+ import { getOutlineIndexData } from '@src/course-outline/data/selectors' ;
11+ import { RequestStatus , RequestStatusType } from './data/constants' ;
12+ import { useCourseDetails , useWaffleFlags } from './data/apiHooks' ;
313import { CourseDetailsData } from './data/api' ;
4- import { useCourseDetails } from './data/apiHooks' ;
5- import { RequestStatusType } from './data/constants' ;
614
715export type CourseAuthoringContextData = {
816 /** The ID of the current course */
917 courseId : string ;
18+ courseUsageKey : string ;
1019 courseDetails ?: CourseDetailsData ;
1120 courseDetailStatus : RequestStatusType ;
1221 canChangeProviders : boolean ;
22+ handleAddSectionFromLibrary : ReturnType < typeof useCreateCourseBlock > ;
23+ handleAddSubsectionFromLibrary : ReturnType < typeof useCreateCourseBlock > ;
24+ handleAddUnitFromLibrary : ReturnType < typeof useCreateCourseBlock > ;
25+ handleNewSectionSubmit : ( ) => void ;
26+ handleNewSubsectionSubmit : ( sectionId : string ) => void ;
27+ handleNewUnitSubmit : ( subsectionId : string ) => void ;
28+ openUnitPage : ( locator : string ) => void ;
29+ getUnitUrl : ( locator : string ) => string ;
1330} ;
1431
1532/**
@@ -30,23 +47,103 @@ export const CourseAuthoringProvider = ({
3047 children,
3148 courseId,
3249} : CourseAuthoringProviderProps ) => {
50+ const dispatch = useDispatch ( ) ;
51+ const navigate = useNavigate ( ) ;
52+ const waffleFlags = useWaffleFlags ( ) ;
3353 const { data : courseDetails , status : courseDetailStatus } = useCourseDetails ( courseId ) ;
3454 const canChangeProviders = getAuthenticatedUser ( ) . administrator || new Date ( courseDetails ?. start ?? 0 ) > new Date ( ) ;
55+ const { courseStructure } = useSelector ( getOutlineIndexData ) ;
56+ const { id : courseUsageKey } = courseStructure || { } ;
3557
36- const context = useMemo < CourseAuthoringContextData > ( ( ) => {
37- const contextValue = {
38- courseId ,
39- courseDetails ,
40- courseDetailStatus ,
41- canChangeProviders ,
42- } ;
58+ const getUnitUrl = ( locator : string ) => {
59+ if ( getConfig ( ) . ENABLE_UNIT_PAGE === 'true' && waffleFlags . useNewUnitPage ) {
60+ // instanbul ignore next
61+ return `/course/ ${ courseId } /container/ ${ locator } ` ;
62+ }
63+ return ` ${ getConfig ( ) . STUDIO_BASE_URL } /container/ ${ locator } ` ;
64+ } ;
4365
44- return contextValue ;
45- } , [
66+ /**
67+ * Open the unit page for a given locator.
68+ */
69+ const openUnitPage = ( locator : string ) => {
70+ const url = getUnitUrl ( locator ) ;
71+ if ( getConfig ( ) . ENABLE_UNIT_PAGE === 'true' && waffleFlags . useNewUnitPage ) {
72+ // instanbul ignore next
73+ navigate ( url ) ;
74+ } else {
75+ window . location . assign ( url ) ;
76+ }
77+ } ;
78+
79+ const handleNewSectionSubmit = ( ) => {
80+ dispatch ( addNewSectionQuery ( courseUsageKey ) ) ;
81+ } ;
82+
83+ const handleNewSubsectionSubmit = ( sectionId : string ) => {
84+ dispatch ( addNewSubsectionQuery ( sectionId ) ) ;
85+ } ;
86+
87+ const handleNewUnitSubmit = ( subsectionId : string ) => {
88+ dispatch ( addNewUnitQuery ( subsectionId , openUnitPage ) ) ;
89+ } ;
90+
91+ const handleAddSectionFromLibrary = useCreateCourseBlock ( async ( locator ) => {
92+ try {
93+ const data = await getCourseItem ( locator ) ;
94+ // instanbul ignore next
95+ // Page should scroll to newly added section.
96+ data . shouldScroll = true ;
97+ dispatch ( addSection ( data ) ) ;
98+ } catch {
99+ dispatch ( updateSavingStatus ( { status : RequestStatus . FAILED } ) ) ;
100+ }
101+ } ) ;
102+
103+ const handleAddSubsectionFromLibrary = useCreateCourseBlock ( async ( locator , parentLocator ) => {
104+ try {
105+ const data = await getCourseItem ( locator ) ;
106+ data . shouldScroll = true ;
107+ // Page should scroll to newly added subsection.
108+ dispatch ( addSubsection ( { parentLocator, data } ) ) ;
109+ } catch {
110+ dispatch ( updateSavingStatus ( { status : RequestStatus . FAILED } ) ) ;
111+ }
112+ } ) ;
113+
114+ /**
115+ * import a unit block from library and redirect user to this unit page.
116+ */
117+ const handleAddUnitFromLibrary = useCreateCourseBlock ( openUnitPage ) ;
118+
119+ const context = useMemo < CourseAuthoringContextData > ( ( ) => ( {
120+ courseId,
121+ courseUsageKey,
122+ courseDetails,
123+ courseDetailStatus,
124+ canChangeProviders,
125+ handleNewSectionSubmit,
126+ handleNewSubsectionSubmit,
127+ handleNewUnitSubmit,
128+ handleAddSectionFromLibrary,
129+ handleAddSubsectionFromLibrary,
130+ handleAddUnitFromLibrary,
131+ getUnitUrl,
132+ openUnitPage,
133+ } ) , [
46134 courseId ,
135+ courseUsageKey ,
47136 courseDetails ,
48137 courseDetailStatus ,
49138 canChangeProviders ,
139+ handleNewSectionSubmit ,
140+ handleNewSubsectionSubmit ,
141+ handleNewUnitSubmit ,
142+ handleAddSectionFromLibrary ,
143+ handleAddSubsectionFromLibrary ,
144+ handleAddUnitFromLibrary ,
145+ getUnitUrl ,
146+ openUnitPage ,
50147 ] ) ;
51148
52149 return (
0 commit comments