Skip to content

Commit

Permalink
refactor: courseware sidebar logic according to the backand refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
ihor-romaniuk committed May 7, 2024
1 parent 47216be commit 9edafba
Show file tree
Hide file tree
Showing 13 changed files with 67 additions and 87 deletions.
9 changes: 3 additions & 6 deletions src/course-home/data/__snapshots__/redux.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ Object {
"courseId": null,
"courseOutline": Object {},
"courseOutlineShouldUpdate": false,
"courseOutlineSidebarSettings": Object {},
"courseOutlineStatus": "loading",
"courseStatus": "loading",
"rightSidebarSettings": Object {},
"coursewareOutlineSidebarSettings": Object {},
"sequenceId": null,
"sequenceMightBeUnit": false,
"sequenceStatus": "loading",
Expand Down Expand Up @@ -409,10 +408,9 @@ Object {
"courseId": null,
"courseOutline": Object {},
"courseOutlineShouldUpdate": false,
"courseOutlineSidebarSettings": Object {},
"courseOutlineStatus": "loading",
"courseStatus": "loading",
"rightSidebarSettings": Object {},
"coursewareOutlineSidebarSettings": Object {},
"sequenceId": null,
"sequenceMightBeUnit": false,
"sequenceStatus": "loading",
Expand Down Expand Up @@ -683,10 +681,9 @@ Object {
"courseId": null,
"courseOutline": Object {},
"courseOutlineShouldUpdate": false,
"courseOutlineSidebarSettings": Object {},
"courseOutlineStatus": "loading",
"courseStatus": "loading",
"rightSidebarSettings": Object {},
"coursewareOutlineSidebarSettings": Object {},
"sequenceId": null,
"sequenceMightBeUnit": false,
"sequenceStatus": "loading",
Expand Down
4 changes: 2 additions & 2 deletions src/courseware/course/Course.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ const Course = ({
} = useModel('courseHomeMeta', courseId);
const sequence = useModel('sequences', sequenceId);
const section = useModel('sections', sequence ? sequence.sectionId : null);
const { enabled: isEnabledOutlineSidebar = false } = useSelector(getCoursewareOutlineSidebarSettings);
const navigationDisabled = isEnabledOutlineSidebar || (sequence?.navigationDisabled ?? false);
const { enableNavigationSidebar } = useSelector(getCoursewareOutlineSidebarSettings);
const navigationDisabled = enableNavigationSidebar || (sequence?.navigationDisabled ?? false);

const pageTitleBreadCrumbs = [
sequence,
Expand Down
2 changes: 1 addition & 1 deletion src/courseware/course/Course.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ describe('Course', () => {
{ courseId: courseMetadata.id },
));
const testStore = await initializeTestStore({
courseMetadata, unitBlocks, outlineSidebarSettings: { enabled: false },
courseMetadata, unitBlocks, enableNavigationSidebar: { enable_navigation_sidebar: false },
}, false);
const { courseware, models } = testStore.getState();
const { courseId, sequenceId } = courseware;
Expand Down
4 changes: 2 additions & 2 deletions src/courseware/course/sidebar/SidebarContextProvider.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {

import { useModel } from '@src/generic/model-store';
import { getLocalStorage, setLocalStorage } from '@src/data/localStorage';
import { getRightSidebarSettings } from '../../data/selectors';
import { getCoursewareOutlineSidebarSettings } from '../../data/selectors';

import * as discussionsSidebar from './sidebars/discussions';
import * as notificationsSidebar from './sidebars/notifications';
Expand All @@ -25,7 +25,7 @@ const SidebarProvider = ({
const shouldDisplayFullScreen = useWindowSize().width < breakpoints.extraLarge.minWidth;
const shouldDisplaySidebarOpen = useWindowSize().width > breakpoints.extraLarge.minWidth;
const query = new URLSearchParams(window.location.search);
const isDefaultDisplayRightSidebar = useSelector(getRightSidebarSettings).enabled;
const isDefaultDisplayRightSidebar = useSelector(getCoursewareOutlineSidebarSettings).alwaysOpenAuxiliarySidebar;
const isInitiallySidebarOpen = shouldDisplaySidebarOpen || query.get('sidebar') === 'true';

let initialSidebar = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ describe('<CourseOutlineTray />', () => {
});

it('doesn\'t render when outline sidebar is disabled', async () => {
await initTestStore({ outlineSidebarSettings: { enabled: false } });
await initTestStore({ enableNavigationSidebar: { enable_navigation_sidebar: false } });
renderWithProvider();

await expect(screen.queryByText(messages.loading.defaultMessage)).not.toBeInTheDocument();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('<CourseOutlineTrigger />', () => {

it('renders correctly for desktop when sidebar is enabled', async () => {
const mockToggleSidebar = jest.fn();
await initTestStore({ outlineSidebarSettings: { enabled: true } });
await initTestStore({ enableNavigationSidebar: { enable_navigation_sidebar: true } });
renderWithProvider({ toggleSidebar: mockToggleSidebar }, { isMobileView: false });

const toggleButton = await screen.getByRole('button', {
Expand All @@ -60,7 +60,7 @@ describe('<CourseOutlineTrigger />', () => {

it('renders correctly for mobile when sidebar is enabled', async () => {
const mockToggleSidebar = jest.fn();
await initTestStore({ outlineSidebarSettings: { enabled: true } });
await initTestStore({ enableNavigationSidebar: { enable_navigation_sidebar: true } });
renderWithProvider({
toggleSidebar: mockToggleSidebar,
shouldDisplayFullScreen: true,
Expand All @@ -79,7 +79,7 @@ describe('<CourseOutlineTrigger />', () => {

it('changes current sidebar value on click', async () => {
const mockToggleSidebar = jest.fn();
await initTestStore({ outlineSidebarSettings: { enabled: true } });
await initTestStore({ enableNavigationSidebar: { enable_navigation_sidebar: true } });
renderWithProvider({
toggleSidebar: mockToggleSidebar,
shouldDisplayFullScreen: true,
Expand All @@ -98,7 +98,7 @@ describe('<CourseOutlineTrigger />', () => {
});

it('does not render when isEnabled is false', async () => {
await initTestStore({ outlineSidebarSettings: { enabled: false } });
await initTestStore({ enableNavigationSidebar: { enable_navigation_sidebar: false } });
renderWithProvider({}, { isMobileView: false });

const toggleButton = await screen.queryByRole('button', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ID } from './constants';
// eslint-disable-next-line import/prefer-default-export
export const useCourseOutlineSidebar = () => {
const isCollapsedOutlineSidebar = window.sessionStorage.getItem('hideCourseOutlineSidebar');
const { enabled: isEnabledSidebar } = useSelector(getCoursewareOutlineSidebarSettings);
const { enableNavigationSidebar: isEnabledSidebar } = useSelector(getCoursewareOutlineSidebarSettings);
const {
unitId,
courseId,
Expand Down
25 changes: 9 additions & 16 deletions src/courseware/data/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,23 +100,16 @@ export async function getCourseOutline(courseId) {
}

/**
* Get waffle flag value that enable courseware outline sidebar.
* Get waffle flag value that enable courseware outline sidebar and always open auxiliary sidebar.
* @param {string} courseId - The unique identifier for the course.
* @returns {Promise<{enabled: boolean}>} - The boolean value of enabling of the outline sidebar.
* @returns {Promise<{enable_navigation_sidebar: boolean, enable_navigation_sidebar: boolean}>} - The object
* of boolean values of enabling of the outline sidebar and is always open auxiliary sidebar.
*/
export async function getCoursewareOutlineSidebarEnabledFlag(courseId) {
const url = new URL(`${getConfig().LMS_BASE_URL}/courses/${courseId}/courseware-sidebar/enabled/`);
export async function getCoursewareOutlineSidebarToggles(courseId) {
const url = new URL(`${getConfig().LMS_BASE_URL}/courses/${courseId}/courseware-navigation-sidebar/toggles/`);
const { data } = await getAuthenticatedHttpClient().get(url.href);
return { enabled: data.enabled || false };
}

/**
* Get the waffle flag value that default opens the courseware discussion sidebar.
* @param {string} courseId - The unique identifier for the course.
* @returns {Promise<{enabled: boolean}>} - The boolean value of default opening of the discussion sidebar.
*/
export async function getRightSidebarDefaultOpeningFlag(courseId) {
const url = new URL(`${getConfig().LMS_BASE_URL}/courses/${courseId}/show-default-right-sidebar/enabled/`);
const { data } = await getAuthenticatedHttpClient().get(url.href);
return { enabled: data.enabled || false };
return {
enable_navigation_sidebar: data.enable_navigation_sidebar || false,
always_open_auxiliary_sidebar: data.always_open_auxiliary_sidebar || false,
};
}
33 changes: 19 additions & 14 deletions src/courseware/data/redux.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ describe('Data layer integration tests', () => {
const sequenceUrl = `${sequenceBaseUrl}/${sequenceMetadata.item_id}`;
const sequenceId = sequenceBlocks[0].id;
const unitId = unitBlocks[0].id;
const outlineSidebarSettingsUrl = `${getConfig().LMS_BASE_URL}/courses/${courseId}/courseware-sidebar/enabled/`;
const rightSidebarSettingsUrl = `${getConfig().LMS_BASE_URL}/courses/${courseId}/show-default-right-sidebar/enabled/`;
const coursewareSidebarSettingsUrl = `${getConfig().LMS_BASE_URL}/courses/${courseId}/courseware-navigation-sidebar/toggles/`;

let store;

Expand All @@ -60,8 +59,7 @@ describe('Data layer integration tests', () => {
it('Should fail to fetch course and blocks if request error happens', async () => {
axiosMock.onGet(courseUrl).networkError();
axiosMock.onGet(learningSequencesUrlRegExp).networkError();
axiosMock.onGet(outlineSidebarSettingsUrl).networkError();
axiosMock.onGet(rightSidebarSettingsUrl).networkError();
axiosMock.onGet(coursewareSidebarSettingsUrl).networkError();

await executeThunk(thunks.fetchCourse(courseId), store.dispatch);

Expand All @@ -70,8 +68,7 @@ describe('Data layer integration tests', () => {
courseId,
courseOutline: {},
courseStatus: FAILED,
courseOutlineSidebarSettings: {},
rightSidebarSettings: {},
coursewareOutlineSidebarSettings: {},
courseOutlineStatus: LOADING,
sequenceId: null,
sequenceMightBeUnit: false,
Expand Down Expand Up @@ -113,8 +110,10 @@ describe('Data layer integration tests', () => {
axiosMock.onGet(courseHomeMetadataUrl).reply(200, courseHomeMetadata);
axiosMock.onGet(courseUrl).reply(200, courseMetadata);
axiosMock.onGet(learningSequencesUrlRegExp).reply(200, buildOutlineFromBlocks(courseBlocks));
axiosMock.onGet(outlineSidebarSettingsUrl).reply(200, { enabled: true });
axiosMock.onGet(rightSidebarSettingsUrl).reply(200, { enabled: true });
axiosMock.onGet(coursewareSidebarSettingsUrl).reply(200, {
enable_navigation_sidebar: true,
always_open_auxiliary_sidebar: true,
});

await executeThunk(thunks.fetchCourse(courseId), store.dispatch);

Expand All @@ -124,8 +123,10 @@ describe('Data layer integration tests', () => {
expect(state.courseware.courseId).toEqual(courseId);
expect(state.courseware.sequenceStatus).toEqual('loading');
expect(state.courseware.sequenceId).toEqual(null);
expect(state.courseware.courseOutlineSidebarSettings).toEqual({ enabled: true });
expect(state.courseware.rightSidebarSettings).toEqual({ enabled: true });
expect(state.courseware.coursewareOutlineSidebarSettings).toEqual({
enableNavigationSidebar: true,
alwaysOpenAuxiliarySidebar: true,
});

// check that at least one key camel cased, thus course data normalized
expect(state.models.coursewareMeta[courseId].marketingUrl).not.toBeUndefined();
Expand All @@ -137,8 +138,10 @@ describe('Data layer integration tests', () => {
axiosMock.onGet(courseHomeMetadataUrl).reply(200, courseHomeMetadata);
axiosMock.onGet(courseUrl).reply(200, courseMetadata);
axiosMock.onGet(learningSequencesUrlRegExp).reply(200, simpleOutline);
axiosMock.onGet(outlineSidebarSettingsUrl).reply(200, { enabled: false });
axiosMock.onGet(rightSidebarSettingsUrl).reply(200, { enabled: false });
axiosMock.onGet(coursewareSidebarSettingsUrl).reply(200, {
enable_navigation_sidebar: false,
always_open_auxiliary_sidebar: false,
});

await executeThunk(thunks.fetchCourse(courseId), store.dispatch);

Expand All @@ -148,8 +151,10 @@ describe('Data layer integration tests', () => {
expect(state.courseware.courseId).toEqual(courseId);
expect(state.courseware.sequenceStatus).toEqual('loading');
expect(state.courseware.sequenceId).toEqual(null);
expect(state.courseware.courseOutlineSidebarSettings).toEqual({ enabled: false });
expect(state.courseware.rightSidebarSettings).toEqual({ enabled: false });
expect(state.courseware.coursewareOutlineSidebarSettings).toEqual({
enableNavigationSidebar: false,
alwaysOpenAuxiliarySidebar: false,
});

// check that at least one key camel cased, thus course data normalized
expect(state.models.coursewareMeta[courseId].marketingUrl).not.toBeUndefined();
Expand Down
4 changes: 1 addition & 3 deletions src/courseware/data/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ export const getCourseOutline = state => state.courseware.courseOutline;

export const getCourseOutlineStatus = state => state.courseware.courseOutlineStatus;

export const getCoursewareOutlineSidebarSettings = state => state.courseware.courseOutlineSidebarSettings;

export const getRightSidebarSettings = state => state.courseware.rightSidebarSettings;
export const getCoursewareOutlineSidebarSettings = state => state.courseware.coursewareOutlineSidebarSettings;

export const getCourseOutlineShouldUpdate = state => state.courseware.courseOutlineShouldUpdate;
13 changes: 4 additions & 9 deletions src/courseware/data/slice.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ const slice = createSlice({
sequenceMightBeUnit: false,
sequenceStatus: LOADING,
courseOutline: {},
courseOutlineSidebarSettings: {},
rightSidebarSettings: {},
coursewareOutlineSidebarSettings: {},
courseOutlineStatus: LOADING,
courseOutlineShouldUpdate: false,
},
Expand Down Expand Up @@ -65,11 +64,8 @@ const slice = createSlice({
state.courseOutline = {};
state.courseOutlineStatus = FAILED;
},
setCoursewareOutlineSidebarSettings: (state, { payload }) => {
state.courseOutlineSidebarSettings = payload;
},
setRightSidebarSettings: (state, { payload }) => {
state.rightSidebarSettings = payload;
setCoursewareOutlineSidebarToggles: (state, { payload }) => {
state.coursewareOutlineSidebarSettings = payload;
},
updateCourseOutlineCompletion: (state, { payload }) => {
const { unitId, isComplete: isUnitComplete } = payload;
Expand Down Expand Up @@ -125,8 +121,7 @@ export const {
fetchCourseOutlineRequest,
fetchCourseOutlineSuccess,
fetchCourseOutlineFailure,
setCoursewareOutlineSidebarSettings,
setRightSidebarSettings,
setCoursewareOutlineSidebarToggles,
updateCourseOutlineCompletion,
} = slice.actions;

Expand Down
35 changes: 13 additions & 22 deletions src/courseware/data/thunks.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import {
getCourseMetadata,
getCourseOutline,
getCourseTopics,
getCoursewareOutlineSidebarEnabledFlag,
getRightSidebarDefaultOpeningFlag,
getCoursewareOutlineSidebarToggles,
getLearningSequencesOutline,
getSequenceMetadata,
postIntegritySignature,
Expand All @@ -27,8 +26,7 @@ import {
fetchCourseOutlineRequest,
fetchCourseOutlineSuccess,
fetchCourseOutlineFailure,
setCoursewareOutlineSidebarSettings,
setRightSidebarSettings,
setCoursewareOutlineSidebarToggles,
updateCourseOutlineCompletion,
} from './slice';

Expand All @@ -39,19 +37,16 @@ export function fetchCourse(courseId) {
getCourseMetadata(courseId),
getLearningSequencesOutline(courseId),
getCourseHomeCourseMetadata(courseId, 'courseware'),
getCoursewareOutlineSidebarEnabledFlag(courseId),
getRightSidebarDefaultOpeningFlag(courseId),
getCoursewareOutlineSidebarToggles(courseId),
]).then(([
courseMetadataResult,
learningSequencesOutlineResult,
courseHomeMetadataResult,
courseOutlineSidebarDisableFlagResult,
rightSidebarDefaultOpenFlagResult]) => {
coursewareOutlineSidebarTogglesResult]) => {
const fetchedMetadata = courseMetadataResult.status === 'fulfilled';
const fetchedCourseHomeMetadata = courseHomeMetadataResult.status === 'fulfilled';
const fetchedOutline = learningSequencesOutlineResult.status === 'fulfilled';
const fetchedOutlineSidebarEnableFlag = courseOutlineSidebarDisableFlagResult.status === 'fulfilled';
const fetchedRightSidebarDefaultOpenFlag = rightSidebarDefaultOpenFlagResult.status === 'fulfilled';
const fetchedCoursewareOutlineSidebarTogglesResult = coursewareOutlineSidebarTogglesResult.status === 'fulfilled';

if (fetchedMetadata) {
dispatch(addModel({
Expand Down Expand Up @@ -91,16 +86,12 @@ export function fetchCourse(courseId) {
}));
}

if (fetchedOutlineSidebarEnableFlag) {
dispatch(setCoursewareOutlineSidebarSettings({
enabled: courseOutlineSidebarDisableFlagResult.value.enabled,
}));
}

if (fetchedRightSidebarDefaultOpenFlag) {
dispatch(setRightSidebarSettings({
enabled: rightSidebarDefaultOpenFlagResult.value.enabled,
}));
if (fetchedCoursewareOutlineSidebarTogglesResult) {
const {
enable_navigation_sidebar: enableNavigationSidebar,
always_open_auxiliary_sidebar: alwaysOpenAuxiliarySidebar,
} = coursewareOutlineSidebarTogglesResult.value;
dispatch(setCoursewareOutlineSidebarToggles({ enableNavigationSidebar, alwaysOpenAuxiliarySidebar }));
}

// Log errors for each request if needed. Outline failures may occur
Expand All @@ -121,8 +112,8 @@ export function fetchCourse(courseId) {
if (!fetchedCourseHomeMetadata) {
logError(courseHomeMetadataResult.reason);
}
if (!fetchedOutlineSidebarEnableFlag) {
logError(courseOutlineSidebarDisableFlagResult.reason);
if (!fetchedCoursewareOutlineSidebarTogglesResult) {
logError(fetchedCoursewareOutlineSidebarTogglesResult.reason);
}
if (fetchedMetadata && fetchedCourseHomeMetadata) {
if (courseHomeMetadataResult.value.courseAccess.hasAccess && fetchedOutline) {
Expand Down
13 changes: 7 additions & 6 deletions src/setupTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,21 +162,22 @@ export async function initializeTestStore(options = {}, overrideStore = true) {
const learningSequencesUrlRegExp = new RegExp(`${getConfig().LMS_BASE_URL}/api/learning_sequences/v1/course_outline/*`);
let courseHomeMetadataUrl = `${getConfig().LMS_BASE_URL}/api/course_home/course_metadata/${courseMetadata.id}`;
const discussionConfigUrl = new RegExp(`${getConfig().LMS_BASE_URL}/api/discussion/v1/courses/*`);
const outlineSidebarSettingsUrl = `${getConfig().LMS_BASE_URL}/courses/${courseMetadata.id}/courseware-sidebar/enabled/`;
const rightSidebarSettingsUrl = `${getConfig().LMS_BASE_URL}/courses/${courseMetadata.id}/show-default-right-sidebar/enabled/`;
const coursewareSidebarSettingsUrl = `${getConfig().LMS_BASE_URL}/courses/${courseMetadata.id}/courseware-navigation-sidebar/toggles/`;
const outlineSidebarUrl = `${getConfig().LMS_BASE_URL}/api/course_home/v1/navigation/${courseMetadata.id}`;
courseHomeMetadataUrl = appendBrowserTimezoneToUrl(courseHomeMetadataUrl);

const provider = options?.provider || 'legacy';
const outlineSidebarSettings = options.outlineSidebarSettings || { enabled: true };
const rightSidebarSettings = options.rightSidebarSettings || { enabled: true };
const enableNavigationSidebar = options.enableNavigationSidebar || { enable_navigation_sidebar: true };
const alwaysOpenAuxiliarySidebar = options.alwaysOpenAuxiliarySidebar || { always_open_auxiliary_sidebar: true };

axiosMock.onGet(courseMetadataUrl).reply(200, courseMetadata);
axiosMock.onGet(courseHomeMetadataUrl).reply(200, courseHomeMetadata);
axiosMock.onGet(learningSequencesUrlRegExp).reply(200, buildOutlineFromBlocks(courseBlocks));
axiosMock.onGet(discussionConfigUrl).reply(200, { provider });
axiosMock.onGet(outlineSidebarSettingsUrl).reply(200, outlineSidebarSettings);
axiosMock.onGet(rightSidebarSettingsUrl).reply(200, rightSidebarSettings);
axiosMock.onGet(coursewareSidebarSettingsUrl).reply(200, {
...enableNavigationSidebar,
...alwaysOpenAuxiliarySidebar,
});

axiosMock.onGet(outlineSidebarUrl).reply(200, {
...courseBlocks,
Expand Down

0 comments on commit 9edafba

Please sign in to comment.