From 580dc3b5b164c443346ee8151ad0540de91d52a0 Mon Sep 17 00:00:00 2001 From: David Joy Date: Fri, 3 Jan 2020 16:36:00 -0500 Subject: [PATCH] Parsing course structure and rendering breadcrumbs, subsection nav, and iframe. --- public/index.html | 2 +- src/index.scss | 39 +++ .../LearningSequencePage.jsx | 222 ++++++++++-------- .../SubSectionNavigation.jsx | 30 +++ 4 files changed, 200 insertions(+), 93 deletions(-) create mode 100644 src/learning-sequence/SubSectionNavigation.jsx diff --git a/public/index.html b/public/index.html index 17abf3a6..3f8576ac 100644 --- a/public/index.html +++ b/public/index.html @@ -1,7 +1,7 @@ - Application Template | edX + Course | edX diff --git a/src/index.scss b/src/index.scss index ab4e5a33..4f14c9c3 100755 --- a/src/index.scss +++ b/src/index.scss @@ -4,3 +4,42 @@ @import "~@edx/frontend-component-header/dist/index"; @import "~@edx/frontend-component-footer/dist/footer"; + +#root { + display: flex; + flex-direction: column; + height: 100vh; + + header { + flex: 0; + } + + main { + flex: 1; + display: flex; + flex-direction: column; + + iframe { + flex: 1; + margin: 0 -10px; + } + + nav { + display: flex; + flex-direction: row; + width: 100%; + + .unit-button { + flex: 1; + } + + button { + margin: 0px 5px; + } + } + } + + footer { + flex: 0; + } +} diff --git a/src/learning-sequence/LearningSequencePage.jsx b/src/learning-sequence/LearningSequencePage.jsx index 6f8161c4..0aa612e4 100644 --- a/src/learning-sequence/LearningSequencePage.jsx +++ b/src/learning-sequence/LearningSequencePage.jsx @@ -1,116 +1,154 @@ -import React, { useState, useEffect, useCallback, useRef } from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { camelCaseObject, getConfig } from '@edx/frontend-platform'; import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; +import { getConfig, camelCaseObject } from '@edx/frontend-platform'; +import { AppContext } from '@edx/frontend-platform/react'; +import { Breadcrumb } from '@edx/paragon'; import PageLoading from './PageLoading'; - import messages from './messages'; +import SubSectionNavigation from './SubSectionNavigation'; -function useApi(apiFunction, { - format = true, keepDataIfFailed = false, loadedIfFailed = false, refreshParams = [], -}) { - const [data, setData] = useState(null); - const [loading, setLoading] = useState(false); - const [loaded, setLoaded] = useState(false); - const [failed, setFailed] = useState(false); - const [error, setError] = useState(null); +async function getCourseBlocks(courseId, username) { + const queryParams = Object.entries({ + course_id: courseId, + username, + depth: 3, + requested_fields: 'children', + }).reduce((acc, [key, value]) => (acc === '' ? `?${key}=${value}` : `${acc}&${key}=${value}`), ''); - useEffect(() => { - setLoading(true); - apiFunction().then((response) => { - const result = format ? camelCaseObject(response.data) : response.data; - setData(result); - setLoaded(true); - setLoading(false); - setError(null); - setFailed(false); - }) - .catch((e) => { - if (keepDataIfFailed) { - setData(null); - } - setFailed(true); - setLoading(false); - if (loadedIfFailed) { - setLoaded(true); - } - setError(e); - }); - }, refreshParams); + const { data } = await getAuthenticatedHttpClient() + .get(`${getConfig().LMS_BASE_URL}/api/courses/v2/blocks/${queryParams}`, {}); - return { - data, - loading, - loaded, - failed, - error, - }; + return { models: organizeCourseModels(data.blocks), courseBlockId: data.root }; } -function LearningSequencePage(props) { - const iframeRef = useRef(null); +function organizeCourseModels(blocksMap) { + const models = {}; - const handleResizeIframe = useCallback(() => { - // TODO: This won't work because of crossdomain issues. Leaving here for reference once we're - // able to have the iFrame content publish resize events through postMessage - console.log('**** Resizing iframe...'); - const iframe = iframeRef.current; - const contentHeight = iframe.contentWindow.document.body.scrollHeight; - console.log(`**** Height is: ${contentHeight}`); - iframe.height = contentHeight + 20; - }); - - const { - data, - loading, - loaded, - } = useApi( - async () => getAuthenticatedHttpClient().get(`${getConfig().LMS_BASE_URL}/api/courses/v1/blocks/?course_id=${props.match.params.courseId}&username=staff&depth=all&block_types_filter=sequential&requested_fields=children`, {}), - { - keepDataIfFailed: false, - refreshParams: [ - props.match.params.courseId, - props.match.params.blockIndex, - ], - }, - ); - - console.log(data); - - if (loading) { - return ( - - ); + const blocks = Object.values(blocksMap); + for (let i = 0; i < blocks.length; i++) { + const block = blocks[i]; + models[block.id] = camelCaseObject(block); } - return ( -
-
-

Learning Sequence Page

- {loaded && data.blocks ? ( -