Improving file organization.

This commit is contained in:
David Joy
2020-01-10 11:52:37 -05:00
parent 0db7cabf29
commit 990cef31a3
12 changed files with 162 additions and 400 deletions

View File

@@ -0,0 +1,16 @@
/* eslint-disable import/prefer-default-export */
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { getConfig } from '@edx/frontend-platform';
export async function getCourseBlocks(courseId, username) {
const url = new URL(`${getConfig().LMS_BASE_URL}/api/courses/v2/blocks/`);
url.searchParams.append('course_id', decodeURIComponent(courseId));
url.searchParams.append('username', username);
url.searchParams.append('depth', 3);
url.searchParams.append('requested_fields', 'children');
const { data } = await getAuthenticatedHttpClient()
.get(url.href, {});
return data;
}

View File

@@ -0,0 +1,114 @@
import { useContext, useMemo, useState, useEffect } from 'react';
import { AppContext } from '@edx/frontend-platform/react';
import CourseStructureContext from '../CourseStructureContext';
import { getCourseBlocks } from './api';
import { findBlockAncestry, createBlocksMap, createSubSectionIdList, createUnitIdList } from './utils';
export function useBlockAncestry(blockId) {
const { blocks, loaded } = useContext(CourseStructureContext);
return useMemo(() => {
if (!loaded) {
return [];
}
return findBlockAncestry(
blocks,
blockId,
);
}, [blocks, blockId, loaded]);
}
export function useCourseStructure(courseId) {
const { authenticatedUser } = useContext(AppContext);
const [blocks, setBlocks] = useState(null);
const [loaded, setLoaded] = useState(false);
const [courseBlockId, setCourseBlockId] = useState();
useEffect(() => {
setLoaded(false);
getCourseBlocks(courseId, authenticatedUser.username).then((blocksData) => {
setBlocks(createBlocksMap(blocksData.blocks));
setCourseBlockId(blocksData.root);
setLoaded(true);
});
}, [courseId]);
return {
blocks, loaded, courseBlockId,
};
}
export function useCurrentCourse() {
const { loaded, courseBlockId, blocks } = useContext(CourseStructureContext);
return loaded ? blocks[courseBlockId] : null;
}
export function useCurrentSubSection() {
const { loaded, blocks, subSectionId } = useContext(CourseStructureContext);
return loaded ? blocks[subSectionId] : null;
}
export function useCurrentSection() {
const { loaded, blocks } = useContext(CourseStructureContext);
const subSection = useCurrentSubSection();
return loaded ? blocks[subSection.parentId] : null;
}
export function useCurrentUnit() {
const { loaded, blocks, unitId } = useContext(CourseStructureContext);
return loaded ? blocks[unitId] : null;
}
export function useUnitIds() {
const { loaded, blocks, courseBlockId } = useContext(CourseStructureContext);
return useMemo(
() => (loaded ? createUnitIdList(blocks, courseBlockId) : []),
[loaded, blocks, courseBlockId],
);
}
export function usePreviousUnit() {
const { loaded, blocks, unitId } = useContext(CourseStructureContext);
const unitIds = useUnitIds();
const currentUnitIndex = unitIds.indexOf(unitId);
if (currentUnitIndex === 0) {
return null;
}
return loaded ? blocks[unitIds[currentUnitIndex - 1]] : null;
}
export function useNextUnit() {
const { loaded, blocks, unitId } = useContext(CourseStructureContext);
const unitIds = useUnitIds();
const currentUnitIndex = unitIds.indexOf(unitId);
if (currentUnitIndex === unitIds.length - 1) {
return null;
}
return loaded ? blocks[unitIds[currentUnitIndex + 1]] : null;
}
export function useCurrentSubSectionUnits() {
const { blocks } = useContext(CourseStructureContext);
const subSection = useCurrentSubSection();
return subSection.children.map(id => blocks[id]);
}
export function useSubSectionIdList() {
const { loaded, blocks, courseBlockId } = useContext(CourseStructureContext);
const subSectionIdList = useMemo(
() => (loaded ? createSubSectionIdList(blocks, courseBlockId) : []),
[blocks, courseBlockId],
);
return subSectionIdList;
}

View File

@@ -0,0 +1,67 @@
/* eslint-disable no-plusplus */
import { camelCaseObject } from '@edx/frontend-platform';
export function createBlocksMap(blocksData) {
const blocks = {};
const blocksList = Object.values(blocksData);
// First go through the list and flesh out our blocks map, camelCasing the objects as we go.
for (let i = 0; i < blocksList.length; i++) {
const block = blocksList[i];
blocks[block.id] = camelCaseObject(block);
}
// Next go through the blocksList again - now that we've added them all to the blocks map - and
// append a parent ID to every child found in every `children` list, using the blocks map to find
// them.
for (let i = 0; i < blocksList.length; i++) {
const block = blocksList[i];
if (Array.isArray(block.children)) {
for (let j = 0; j < block.children.length; j++) {
const childId = block.children[j];
const child = blocks[childId];
child.parentId = block.id;
}
}
}
return blocks;
}
export function createSubSectionIdList(blocks, entryPointId, subSections = []) {
const block = blocks[entryPointId];
if (block.type === 'sequential') {
subSections.push(block.id);
}
if (Array.isArray(block.children)) {
for (let i = 0; i < block.children.length; i++) {
const childId = block.children[i];
createSubSectionIdList(blocks, childId, subSections);
}
}
return subSections;
}
export function createUnitIdList(blocks, entryPointId, units = []) {
const block = blocks[entryPointId];
if (block.type === 'vertical') {
units.push(block.id);
}
if (Array.isArray(block.children)) {
for (let i = 0; i < block.children.length; i++) {
const childId = block.children[i];
createUnitIdList(blocks, childId, units);
}
}
return units;
}
export function findBlockAncestry(blocks, blockId, descendents = []) {
const block = blocks[blockId];
descendents.unshift(block);
if (block.parentId === undefined) {
return descendents;
}
return findBlockAncestry(blocks, block.parentId, descendents);
}