AA-126: Update outline tab to be a little closer to LMS (#198)

- Changed it to use its own normalizeBlocks call (and stop sharing
  with courseware)
- Add green checkmarks for complete blocks
- Added icons, descriptions, and due dates for subsections
- Updated look of subsections to match LMS a bit more
This commit is contained in:
Michael Terry
2020-08-31 16:44:30 -04:00
committed by GitHub
parent c83389e7c5
commit 9cbe0b7c8b
8 changed files with 359 additions and 66 deletions

View File

@@ -1,7 +1,6 @@
import { camelCaseObject, getConfig } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
// TODO: Pull this normalization function up so we're not reaching into courseware
import { normalizeBlocks } from '../../courseware/data/api';
import { logError } from '@edx/frontend-platform/logging';
function normalizeCourseHomeCourseMetadata(metadata) {
const data = camelCaseObject(metadata);
@@ -15,6 +14,74 @@ function normalizeCourseHomeCourseMetadata(metadata) {
};
}
export function normalizeOutlineBlocks(courseId, blocks) {
const models = {
courses: {},
sections: {},
sequences: {},
};
Object.values(blocks).forEach(block => {
switch (block.type) {
case 'course':
models.courses[block.id] = {
id: courseId,
title: block.display_name,
sectionIds: block.children || [],
};
break;
case 'chapter':
models.sections[block.id] = {
complete: block.complete,
id: block.id,
title: block.display_name,
sequenceIds: block.children || [],
};
break;
case 'sequential':
models.sequences[block.id] = {
complete: block.complete,
description: block.description,
due: block.due,
icon: block.icon,
id: block.id,
showLink: !!block.lms_web_url, // we reconstruct the url ourselves as an MFE-internal <Link>
title: block.display_name,
};
break;
default:
logError(`Unexpected course block type: ${block.type} with ID ${block.id}. Expected block types are course, chapter, and sequential.`);
}
});
// Next go through each list and use their child lists to decorate those children with a
// reference back to their parent.
Object.values(models.courses).forEach(course => {
if (Array.isArray(course.sectionIds)) {
course.sectionIds.forEach(sectionId => {
const section = models.sections[sectionId];
section.courseId = course.id;
});
}
});
Object.values(models.sections).forEach(section => {
if (Array.isArray(section.sequenceIds)) {
section.sequenceIds.forEach(sequenceId => {
if (sequenceId in models.sequences) {
models.sequences[sequenceId].sectionId = section.id;
} else {
logError(`Section ${section.id} has child block ${sequenceId}, but that block is not in the list of sequences.`);
}
});
}
});
return models;
}
export async function getCourseHomeCourseMetadata(courseId) {
const url = `${getConfig().LMS_BASE_URL}/api/course_home/v1/course_metadata/${courseId}`;
const { data } = await getAuthenticatedHttpClient().get(url);
@@ -68,7 +135,7 @@ export async function getOutlineTabData(courseId) {
const {
data,
} = tabData;
const courseBlocks = normalizeBlocks(courseId, data.course_blocks.blocks);
const courseBlocks = normalizeOutlineBlocks(courseId, data.course_blocks.blocks);
const courseGoals = camelCaseObject(data.course_goals);
const courseExpiredHtml = data.course_expired_html;
const courseTools = camelCaseObject(data.course_tools);