feat: Sidebar refactor and add support for discussions sidebar. (#762)
squash!: remove unnecessary styling and migrate to bootstrap and other review feedback
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import { Factory } from 'rosie'; // eslint-disable-line import/no-extraneous-dependencies
|
||||
|
||||
Factory.define('discussionTopic')
|
||||
.option('topicPrefix', null, '')
|
||||
.option('courseId', null, 'course-v1:edX+DemoX+Demo_Course')
|
||||
.sequence('id', ['topicPrefix'], (idx, topicPrefix) => `${topicPrefix}topic-${idx}`)
|
||||
.sequence('name', ['topicPrefix'], (idx, topicPrefix) => `${topicPrefix}topic ${idx}`)
|
||||
.sequence(
|
||||
'usage_key',
|
||||
['id', 'courseId'],
|
||||
(idx, id, courseId) => `block-v1:${courseId.replace('course-v1:', '')}+type@vertical+block@${id}`,
|
||||
)
|
||||
.attr('enabled_in_context', null, true)
|
||||
.attr('thread_counts', [], {
|
||||
discussion: 0,
|
||||
question: 0,
|
||||
});
|
||||
|
||||
// Given a pre-build units state, build topics from it.
|
||||
export function buildTopicsFromUnits(units) {
|
||||
return Object.values(units).map(unit => Factory.build('discussionTopic', { usage_key: unit.id }));
|
||||
}
|
||||
@@ -2,3 +2,4 @@ import './courseMetadata.factory';
|
||||
import './sequenceMetadata.factory';
|
||||
import './courseRecommendations.factory';
|
||||
import './learningSequencesOutline.factory';
|
||||
import './discussionTopics.factory';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getConfig, camelCaseObject } from '@edx/frontend-platform';
|
||||
import { camelCaseObject, getConfig } from '@edx/frontend-platform';
|
||||
import { getAuthenticatedHttpClient, getAuthenticatedUser } from '@edx/frontend-platform/auth';
|
||||
import { getTimeOffsetMillis } from '../../course-home/data/api';
|
||||
import { appendBrowserTimezoneToUrl } from '../../utils';
|
||||
@@ -71,7 +71,7 @@ export async function getSequenceForUnitDeprecated(courseId, unitId) {
|
||||
url.searchParams.append('course_id', courseId);
|
||||
url.searchParams.append('username', authenticatedUser ? authenticatedUser.username : '');
|
||||
url.searchParams.append('depth', 3);
|
||||
url.searchParams.append('requested_fields', 'children');
|
||||
url.searchParams.append('requested_fields', 'children,discussions_url');
|
||||
|
||||
const { data } = await getAuthenticatedHttpClient().get(url.href, {});
|
||||
const parent = Object.values(data.blocks).find(block => block.type === 'sequential' && block.children.includes(unitId));
|
||||
@@ -227,8 +227,21 @@ export async function postIntegritySignature(courseId) {
|
||||
);
|
||||
return camelCaseObject(data);
|
||||
}
|
||||
|
||||
export async function sendActivationEmail() {
|
||||
const url = new URL(`${getConfig().LMS_BASE_URL}/api/send_account_activation_email`);
|
||||
const { data } = await getAuthenticatedHttpClient().post(url.href, {});
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function getCourseDiscussionConfig(courseId) {
|
||||
const url = `${getConfig().LMS_BASE_URL}/api/discussion/v1/courses/${courseId}`;
|
||||
const { data } = await getAuthenticatedHttpClient().get(url);
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function getCourseTopics(courseId) {
|
||||
const { data } = await getAuthenticatedHttpClient()
|
||||
.get(`${getConfig().LMS_BASE_URL}/api/discussion/v2/course_topics/${courseId}`);
|
||||
return camelCaseObject(data);
|
||||
}
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
import { logError, logInfo } from '@edx/frontend-platform/logging';
|
||||
import { getCourseHomeCourseMetadata } from '../../course-home/data/api';
|
||||
import {
|
||||
addModel, addModelsMap, updateModel, updateModels, updateModelsMap,
|
||||
} from '../../generic/model-store';
|
||||
import {
|
||||
getBlockCompletion,
|
||||
getCourseDiscussionConfig,
|
||||
getCourseMetadata,
|
||||
getCourseTopics,
|
||||
getLearningSequencesOutline,
|
||||
getSequenceMetadata,
|
||||
postIntegritySignature,
|
||||
postSequencePosition,
|
||||
} from './api';
|
||||
import { getCourseHomeCourseMetadata } from '../../course-home/data/api';
|
||||
import {
|
||||
updateModel, addModel, updateModelsMap, addModelsMap, updateModels,
|
||||
} from '../../generic/model-store';
|
||||
import {
|
||||
fetchCourseDenied,
|
||||
fetchCourseFailure,
|
||||
fetchCourseRequest,
|
||||
fetchCourseSuccess,
|
||||
fetchCourseFailure,
|
||||
fetchCourseDenied,
|
||||
fetchSequenceFailure,
|
||||
fetchSequenceRequest,
|
||||
fetchSequenceSuccess,
|
||||
fetchSequenceFailure,
|
||||
} from './slice';
|
||||
|
||||
export function fetchCourse(courseId) {
|
||||
@@ -231,3 +233,23 @@ export function saveIntegritySignature(courseId, isMasquerading) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function getCourseDiscussionTopics(courseId) {
|
||||
return async (dispatch) => {
|
||||
try {
|
||||
const config = await getCourseDiscussionConfig(courseId);
|
||||
// Only load topics for the openedx provider, the legacy provider uses
|
||||
// the xblock
|
||||
if (config.provider === 'openedx') {
|
||||
const topics = await getCourseTopics(courseId);
|
||||
dispatch(updateModels({
|
||||
modelType: 'discussionTopics',
|
||||
models: topics,
|
||||
idField: 'usageKey',
|
||||
}));
|
||||
}
|
||||
} catch (error) {
|
||||
logError(error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user