Adding constants and renaming src/course to src/active-course

src/course was confusing.  And we had no constants for the various ‘loading’ strings all over the place.
This commit is contained in:
David Joy
2020-08-07 10:24:23 -04:00
parent aca3519a7d
commit d997431382
23 changed files with 121 additions and 93 deletions

View File

@@ -1,33 +1,33 @@
/* eslint-disable no-param-reassign */
import { createSlice } from '@reduxjs/toolkit';
export const LOADING = 'loading';
export const LOADED = 'loaded';
export const FAILED = 'failed';
export const DENIED = 'denied';
export const COURSE_LOADING = 'loading';
export const COURSE_LOADED = 'loaded';
export const COURSE_FAILED = 'failed';
export const COURSE_DENIED = 'denied';
const slice = createSlice({
name: 'activeCourse',
initialState: {
courseStatus: LOADING,
courseStatus: COURSE_LOADING,
courseId: null,
},
reducers: {
fetchCourseRequest: (state, { payload }) => {
state.courseId = payload.courseId;
state.courseStatus = LOADING;
state.courseStatus = COURSE_LOADING;
},
fetchCourseSuccess: (state, { payload }) => {
state.courseId = payload.courseId;
state.courseStatus = LOADED;
state.courseStatus = COURSE_LOADED;
},
fetchCourseFailure: (state, { payload }) => {
state.courseId = payload.courseId;
state.courseStatus = FAILED;
state.courseStatus = COURSE_FAILED;
},
fetchCourseDenied: (state, { payload }) => {
state.courseId = payload.courseId;
state.courseStatus = DENIED;
state.courseStatus = COURSE_DENIED;
},
},
});

View File

@@ -1,10 +1,10 @@
export { activeCourseSelector } from './data/selectors';
export {
reducer,
LOADING,
LOADED,
FAILED,
DENIED,
COURSE_LOADING,
COURSE_LOADED,
COURSE_FAILED,
COURSE_DENIED,
fetchCourseRequest,
fetchCourseSuccess,
fetchCourseFailure,

View File

@@ -1,16 +1,14 @@
import { Factory } from 'rosie';
import MockAdapter from 'axios-mock-adapter';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { getConfig } from '@edx/frontend-platform';
import * as thunks from './thunks';
import executeThunk from '../../utils';
import { COURSE_LOADED, COURSE_LOADING, COURSE_FAILED } from '../../active-course';
import initializeMockApp from '../../setupTest';
import initializeStore from '../../store';
import { LOADING, FAILED } from '../../course';
import executeThunk from '../../utils';
import * as thunks from './thunks';
const { loggingService } = initializeMockApp();
@@ -43,7 +41,7 @@ describe('Data layer integration tests', () => {
it('Should initialize store', () => {
expect(store.getState().activeCourse.courseId).toBeNull();
expect(store.getState().activeCourse.courseStatus).toEqual(LOADING);
expect(store.getState().activeCourse.courseStatus).toEqual(COURSE_LOADING);
});
describe('Test fetchDatesTab', () => {
@@ -57,7 +55,7 @@ describe('Data layer integration tests', () => {
await executeThunk(thunks.fetchDatesTab(courseId), store.dispatch);
expect(loggingService.logError).toHaveBeenCalled();
expect(store.getState().activeCourse.courseStatus).toEqual(FAILED);
expect(store.getState().activeCourse.courseStatus).toEqual(COURSE_FAILED);
});
it('Should fetch, normalize, and save metadata', async () => {
@@ -72,7 +70,7 @@ describe('Data layer integration tests', () => {
await executeThunk(thunks.fetchDatesTab(courseId), store.dispatch);
const state = store.getState();
expect(state.activeCourse.courseStatus).toEqual('loaded');
expect(state.activeCourse.courseStatus).toEqual(COURSE_LOADED);
expect(state.activeCourse.courseId).toEqual(courseId);
expect(state.courseHome.displayResetDatesToast).toBe(false);
@@ -111,7 +109,7 @@ describe('Data layer integration tests', () => {
await executeThunk(thunks.fetchOutlineTab(courseId), store.dispatch);
expect(loggingService.logError).toHaveBeenCalled();
expect(store.getState().activeCourse.courseStatus).toEqual('failed');
expect(store.getState().activeCourse.courseStatus).toEqual(COURSE_FAILED);
});
it('Should fetch, normalize, and save metadata', async () => {
@@ -126,7 +124,7 @@ describe('Data layer integration tests', () => {
await executeThunk(thunks.fetchOutlineTab(courseId), store.dispatch);
const state = store.getState();
expect(state.activeCourse.courseStatus).toEqual('loaded');
expect(state.activeCourse.courseStatus).toEqual(COURSE_LOADED);
expect(state.courseHome.displayResetDatesToast).toBe(false);
// Validate course

View File

@@ -1,10 +1,6 @@
/* eslint-disable no-param-reassign */
import { createSlice } from '@reduxjs/toolkit';
export const LOADING = 'loading';
export const LOADED = 'loaded';
export const FAILED = 'failed';
const slice = createSlice({
name: 'course-home',
initialState: {

View File

@@ -17,7 +17,7 @@ import {
fetchCourseRequest,
fetchCourseSuccess,
fetchCourseFailure,
} from '../../course';
} from '../../active-course';
import {
toggleResetDatesToast,

View File

@@ -13,15 +13,20 @@ import {
fetchSequence,
getResumeBlock,
saveSequencePosition,
SEQUENCE_LOADED,
SEQUENCE_LOADING,
SEQUENCE_FAILED,
} from './data';
import { TabPage } from '../tab-page';
import {
activeCourseSelector, COURSE_LOADED, COURSE_LOADING, COURSE_FAILED, COURSE_DENIED,
} from '../active-course';
import Course from './course';
import { handleNextSectionCelebration } from './course/celebration';
import { activeCourseSelector } from '../course';
const checkExamRedirect = memoize((sequenceStatus, sequence) => {
if (sequenceStatus === 'loaded') {
if (sequenceStatus === SEQUENCE_LOADED) {
if (sequence.isTimeLimited && sequence.lmsWebUrl !== undefined) {
global.location.assign(sequence.lmsWebUrl);
}
@@ -29,7 +34,7 @@ const checkExamRedirect = memoize((sequenceStatus, sequence) => {
});
const checkResumeRedirect = memoize((courseStatus, courseId, sequenceId, firstSequenceId) => {
if (courseStatus === 'loaded' && !sequenceId) {
if (courseStatus === COURSE_LOADED && !sequenceId) {
// Note that getResumeBlock is just an API call, not a redux thunk.
getResumeBlock(courseId).then((data) => {
// This is a replace because we don't want this change saved in the browser's history.
@@ -43,7 +48,7 @@ const checkResumeRedirect = memoize((courseStatus, courseId, sequenceId, firstSe
});
const checkContentRedirect = memoize((courseId, sequenceStatus, sequenceId, sequence, unitId) => {
if (sequenceStatus === 'loaded' && sequenceId && !unitId) {
if (sequenceStatus === SEQUENCE_LOADED && sequenceId && !unitId) {
if (sequence.unitIds !== undefined && sequence.unitIds.length > 0) {
const nextUnitId = sequence.unitIds[sequence.activeUnitIndex];
// This is a replace because we don't want this change saved in the browser's history.
@@ -60,7 +65,7 @@ class CoursewareContainer extends Component {
sequenceStatus,
sequence,
} = this.props;
if (sequenceStatus === 'loaded' && sequence.saveUnitPosition && unitId) {
if (sequenceStatus === SEQUENCE_LOADED && sequence.saveUnitPosition && unitId) {
const activeUnitIndex = sequence.unitIds.indexOf(unitId);
this.props.saveSequencePosition(courseId, sequenceId, activeUnitIndex);
}
@@ -208,7 +213,7 @@ class CoursewareContainer extends Component {
},
} = this.props;
if (courseStatus === 'denied') {
if (courseStatus === COURSE_DENIED) {
return this.renderDenied();
}
@@ -258,8 +263,8 @@ CoursewareContainer.propTypes = {
sequenceId: PropTypes.string,
firstSequenceId: PropTypes.string,
unitId: PropTypes.string,
courseStatus: PropTypes.oneOf(['loaded', 'loading', 'failed', 'denied']).isRequired,
sequenceStatus: PropTypes.oneOf(['loaded', 'loading', 'failed']).isRequired,
courseStatus: PropTypes.oneOf([COURSE_LOADED, COURSE_LOADING, COURSE_FAILED, COURSE_DENIED]).isRequired,
sequenceStatus: PropTypes.oneOf([SEQUENCE_LOADED, SEQUENCE_LOADING, SEQUENCE_FAILED]).isRequired,
nextSequence: sequenceShape,
previousSequence: sequenceShape,
course: courseShape,
@@ -292,7 +297,7 @@ const sequenceIdsSelector = createSelector(
activeCourseSelector,
(state) => state.models.sections,
(courseStatus, course, sectionsById) => {
if (courseStatus !== 'loaded') {
if (courseStatus !== COURSE_LOADED) {
return [];
}
const { sectionIds = [] } = course;
@@ -333,7 +338,7 @@ const firstSequenceIdSelector = createSelector(
activeCourseSelector,
(state) => state.models.sections || {},
(courseStatus, course, sectionsById) => {
if (courseStatus !== 'loaded') {
if (courseStatus !== COURSE_LOADED) {
return null;
}
const { sectionIds = [] } = course;

View File

@@ -6,6 +6,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faHome } from '@fortawesome/free-solid-svg-icons';
import { useSelector } from 'react-redux';
import { useModel } from '../../generic/model-store';
import { COURSE_LOADED } from '../../active-course';
import { SEQUENCE_LOADED } from '../data';
function CourseBreadcrumb({
url, children, withSeparator, ...attrs
@@ -44,7 +46,7 @@ export default function CourseBreadcrumbs({
const sequenceStatus = useSelector(state => state.courseware.sequenceStatus);
const links = useMemo(() => {
if (courseStatus === 'loaded' && sequenceStatus === 'loaded') {
if (courseStatus === COURSE_LOADED && sequenceStatus === SEQUENCE_LOADED) {
return [section, sequence].filter(node => !!node).map((node) => ({
id: node.id,
label: node.title,

View File

@@ -1,15 +1,18 @@
import MockAdapter from 'axios-mock-adapter';
import { getAuthenticatedHttpClient, getAuthenticatedUser } from '@edx/frontend-platform/auth';
import { getConfig } from '@edx/frontend-platform';
import * as thunks from './thunks';
import executeThunk from '../../../../utils';
import initializeMockApp from '../../../../setupTest';
import initializeStore from '../../../../store';
import {
addBookmark,
removeBookmark,
BOOKMARK_FAILED,
BOOKMARK_LOADED,
} from './thunks';
const { loggingService } = initializeMockApp();
const axiosMock = new MockAdapter(getAuthenticatedHttpClient());
@@ -32,24 +35,24 @@ describe('Data layer integration tests', () => {
it('Should fail to create bookmark in case of error', async () => {
axiosMock.onPost(createBookmarkURL).networkError();
await executeThunk(thunks.addBookmark(unitId), store.dispatch);
await executeThunk(addBookmark(unitId), store.dispatch);
expect(loggingService.logError).toHaveBeenCalled();
expect(axiosMock.history.post[0].url).toEqual(createBookmarkURL);
expect(store.getState().models.units[unitId]).toEqual(expect.objectContaining({
bookmarked: false,
bookmarkedUpdateState: 'failed',
bookmarkedUpdateState: BOOKMARK_FAILED,
}));
});
it('Should create bookmark and update model state', async () => {
axiosMock.onPost(createBookmarkURL).reply(201);
await executeThunk(thunks.addBookmark(unitId), store.dispatch);
await executeThunk(addBookmark(unitId), store.dispatch);
expect(store.getState().models.units[unitId]).toEqual(expect.objectContaining({
bookmarked: true,
bookmarkedUpdateState: 'loaded',
bookmarkedUpdateState: BOOKMARK_LOADED,
}));
});
});
@@ -60,24 +63,24 @@ describe('Data layer integration tests', () => {
it('Should fail to remove bookmark in case of error', async () => {
axiosMock.onDelete(deleteBookmarkURL).networkError();
await executeThunk(thunks.removeBookmark(unitId), store.dispatch);
await executeThunk(removeBookmark(unitId), store.dispatch);
expect(loggingService.logError).toHaveBeenCalled();
expect(axiosMock.history.delete[0].url).toEqual(deleteBookmarkURL);
expect(store.getState().models.units[unitId]).toEqual(expect.objectContaining({
bookmarked: true,
bookmarkedUpdateState: 'failed',
bookmarkedUpdateState: BOOKMARK_FAILED,
}));
});
it('Should delete bookmark and update model state', async () => {
axiosMock.onDelete(deleteBookmarkURL).reply(201);
await executeThunk(thunks.removeBookmark(unitId), store.dispatch);
await executeThunk(removeBookmark(unitId), store.dispatch);
expect(store.getState().models.units[unitId]).toEqual(expect.objectContaining({
bookmarked: false,
bookmarkedUpdateState: 'loaded',
bookmarkedUpdateState: BOOKMARK_LOADED,
}));
});
});

View File

@@ -5,6 +5,10 @@ import {
} from './api';
import { updateModel } from '../../../../generic/model-store';
export const BOOKMARK_LOADING = 'loading';
export const BOOKMARK_LOADED = 'loaded';
export const BOOKMARK_FAILED = 'failed';
export function addBookmark(unitId) {
return async (dispatch) => {
// Optimistically update the bookmarked flag.
@@ -13,7 +17,7 @@ export function addBookmark(unitId) {
model: {
id: unitId,
bookmarked: true,
bookmarkedUpdateState: 'loading',
bookmarkedUpdateState: BOOKMARK_LOADING,
},
}));
@@ -24,7 +28,7 @@ export function addBookmark(unitId) {
model: {
id: unitId,
bookmarked: true,
bookmarkedUpdateState: 'loaded',
bookmarkedUpdateState: BOOKMARK_LOADED,
},
}));
} catch (error) {
@@ -34,7 +38,7 @@ export function addBookmark(unitId) {
model: {
id: unitId,
bookmarked: false,
bookmarkedUpdateState: 'failed',
bookmarkedUpdateState: BOOKMARK_FAILED,
},
}));
}
@@ -49,7 +53,7 @@ export function removeBookmark(unitId) {
model: {
id: unitId,
bookmarked: false,
bookmarkedUpdateState: 'loading',
bookmarkedUpdateState: BOOKMARK_LOADING,
},
}));
try {
@@ -59,7 +63,7 @@ export function removeBookmark(unitId) {
model: {
id: unitId,
bookmarked: false,
bookmarkedUpdateState: 'loaded',
bookmarkedUpdateState: BOOKMARK_LOADED,
},
}));
} catch (error) {
@@ -69,7 +73,7 @@ export function removeBookmark(unitId) {
model: {
id: unitId,
bookmarked: true,
bookmarkedUpdateState: 'failed',
bookmarkedUpdateState: BOOKMARK_FAILED,
},
}));
}

View File

@@ -1,3 +1,9 @@
export { default as BookmarkButton } from './BookmarkButton';
export { default as BookmarkFilledIcon } from './BookmarkFilledIcon';
export { default as BookmarkOutlineIcon } from './BookmarkFilledIcon';
export {
BOOKMARK_LOADING,
BOOKMARK_LOADED,
BOOKMARK_FAILED,
} from './data/thunks';

View File

@@ -15,6 +15,7 @@ import CourseLicense from '../course-license';
import messages from './messages';
import { SequenceNavigation, UnitNavigation } from './sequence-navigation';
import SequenceContent from './SequenceContent';
import { SEQUENCE_LOADED, SEQUENCE_LOADING } from '../../data';
function Sequence({
unitId,
@@ -73,7 +74,7 @@ function Sequence({
const { add, remove } = useContext(UserMessagesContext);
useEffect(() => {
let id = null;
if (sequenceStatus === 'loaded') {
if (sequenceStatus === SEQUENCE_LOADED) {
if (sequence.bannerText) {
id = add({
code: null,
@@ -101,7 +102,7 @@ function Sequence({
}
}, [unit]);
if (sequenceStatus === 'loading') {
if (sequenceStatus === SEQUENCE_LOADING) {
if (!sequenceId) {
return (<div> {intl.formatMessage(messages['learn.sequence.no.content'])} </div>);
}
@@ -114,7 +115,7 @@ function Sequence({
const gated = sequence && sequence.gatedContent !== undefined && sequence.gatedContent.gated;
if (sequenceStatus === 'loaded') {
if (sequenceStatus === SEQUENCE_LOADED) {
return (
<div className="sequence-container">
<div className="sequence">

View File

@@ -15,6 +15,7 @@ import { useModel } from '../../../generic/model-store';
import PageLoading from '../../../generic/PageLoading';
import { resetDeadlines } from '../../../course-home/data/thunks';
import { fetchCourse } from '../../data/thunks';
import { BOOKMARK_LOADING } from '../bookmark';
const LockPaywall = React.lazy(() => import('./lock-paywall'));
@@ -106,7 +107,7 @@ function Unit({
<BookmarkButton
unitId={unit.id}
isBookmarked={unit.bookmarked}
isProcessing={unit.bookmarkedUpdateState === 'loading'}
isProcessing={unit.bookmarkedUpdateState === BOOKMARK_LOADING}
/>
{ contentTypeGatingEnabled && unit.graded && (
<Suspense

View File

@@ -5,13 +5,14 @@ import classNames from 'classnames';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import { useSelector } from 'react-redux';
import { useModel } from '../../../../generic/model-store';
import UnitButton from './UnitButton';
import SequenceNavigationTabs from './SequenceNavigationTabs';
import { useSequenceNavigationMetadata } from './hooks';
import { useModel } from '../../../../generic/model-store';
import { LOADED } from '../../../data/slice';
import { SEQUENCE_LOADED } from '../../../data';
export default function SequenceNavigation({
unitId,
@@ -24,7 +25,7 @@ export default function SequenceNavigation({
const sequence = useModel('sequences', sequenceId);
const { isFirstUnit, isLastUnit } = useSequenceNavigationMetadata(sequenceId, unitId);
const sequenceStatus = useSelector(state => state.courseware.sequenceStatus);
const isLocked = sequenceStatus === LOADED ? (
const isLocked = sequenceStatus === SEQUENCE_LOADED ? (
sequence.gatedContent !== undefined && sequence.gatedContent.gated
) : undefined;
@@ -49,7 +50,7 @@ export default function SequenceNavigation({
);
};
return sequenceStatus === LOADED && (
return sequenceStatus === SEQUENCE_LOADED && (
<nav className={classNames('sequence-navigation', className)}>
<Button className="previous-btn" onClick={previousSequenceHandler} disabled={isFirstUnit}>
<FontAwesomeIcon icon={faChevronLeft} className="mr-2" size="sm" />

View File

@@ -1,7 +1,9 @@
/* eslint-disable import/prefer-default-export */
import { useSelector } from 'react-redux';
import { useModel } from '../../../../generic/model-store';
import { COURSE_LOADED } from '../../../../active-course';
import { sequenceIdsSelector } from '../../../data/selectors';
export function useSequenceNavigationMetadata(currentSequenceId, currentUnitId) {
@@ -10,7 +12,7 @@ export function useSequenceNavigationMetadata(currentSequenceId, currentUnitId)
const courseStatus = useSelector(state => state.activeCourse.courseStatus);
// If we don't know the sequence and unit yet, then assume no.
if (courseStatus !== 'loaded' || !currentSequenceId || !currentUnitId) {
if (courseStatus !== COURSE_LOADED || !currentSequenceId || !currentUnitId) {
return { isFirstUnit: false, isLastUnit: false };
}
const isFirstSequence = sequenceIds.indexOf(currentSequenceId) === 0;

View File

@@ -10,4 +10,9 @@ export {
export {
sequenceIdsSelector,
} from './selectors';
export { reducer } from './slice';
export {
reducer,
SEQUENCE_LOADING,
SEQUENCE_LOADED,
SEQUENCE_FAILED,
} from './slice';

View File

@@ -11,6 +11,8 @@ import executeThunk from '../../utils';
import buildSimpleCourseBlocks from './__factories__/courseBlocks.factory';
import initializeMockApp from '../../setupTest';
import initializeStore from '../../store';
import { SEQUENCE_LOADING, SEQUENCE_LOADED, SEQUENCE_FAILED } from './slice';
import { COURSE_LOADED, COURSE_FAILED, COURSE_DENIED } from '../../active-course';
const { loggingService } = initializeMockApp();
@@ -55,7 +57,7 @@ describe('Data layer integration tests', () => {
expect(loggingService.logError).toHaveBeenCalled();
expect(store.getState().activeCourse).toEqual(expect.objectContaining({
courseId,
courseStatus: 'failed',
courseStatus: COURSE_FAILED,
}));
});
@@ -78,7 +80,7 @@ describe('Data layer integration tests', () => {
const state = store.getState();
expect(state.activeCourse.courseStatus).toEqual('denied');
expect(state.activeCourse.courseStatus).toEqual(COURSE_DENIED);
// check that at least one key camel cased, thus course data normalized
expect(state.models.courses[forbiddenCourseMetadata.id].canLoadCourseware).not.toBeUndefined();
@@ -92,9 +94,9 @@ describe('Data layer integration tests', () => {
const state = store.getState();
expect(state.activeCourse.courseStatus).toEqual('loaded');
expect(state.activeCourse.courseStatus).toEqual(COURSE_LOADED);
expect(state.activeCourse.courseId).toEqual(courseId);
expect(state.courseware.sequenceStatus).toEqual('loading');
expect(state.courseware.sequenceStatus).toEqual(SEQUENCE_LOADING);
expect(state.courseware.sequenceId).toEqual(null);
// check that at least one key camel cased, thus course data normalized
@@ -109,7 +111,7 @@ describe('Data layer integration tests', () => {
await executeThunk(thunks.fetchSequence(sequenceId), store.dispatch);
expect(loggingService.logError).toHaveBeenCalled();
expect(store.getState().courseware.sequenceStatus).toEqual('failed');
expect(store.getState().courseware.sequenceStatus).toEqual(SEQUENCE_FAILED);
});
it('Should fetch and normalize metadata, and then update existing models with sequence metadata', async () => {
@@ -139,9 +141,9 @@ describe('Data layer integration tests', () => {
// Update our state variable again.
state = store.getState();
expect(state.activeCourse.courseStatus).toEqual('loaded');
expect(state.activeCourse.courseStatus).toEqual(COURSE_LOADED);
expect(state.activeCourse.courseId).toEqual(courseId);
expect(state.courseware.sequenceStatus).toEqual('loading');
expect(state.courseware.sequenceStatus).toEqual(SEQUENCE_LOADING);
expect(state.courseware.sequenceId).toEqual(null);
await executeThunk(thunks.fetchSequence(sequenceId), store.dispatch);
@@ -163,9 +165,9 @@ describe('Data layer integration tests', () => {
}),
});
expect(state.activeCourse.courseStatus).toEqual('loaded');
expect(state.activeCourse.courseStatus).toEqual(COURSE_LOADED);
expect(state.activeCourse.courseId).toEqual(courseId);
expect(state.courseware.sequenceStatus).toEqual('loaded');
expect(state.courseware.sequenceStatus).toEqual(SEQUENCE_LOADED);
expect(state.courseware.sequenceId).toEqual(sequenceId);
});
});

View File

@@ -1,6 +1,8 @@
/* eslint-disable import/prefer-default-export */
import { COURSE_LOADED } from '../../active-course';
export function sequenceIdsSelector(state) {
if (state.activeCourse.courseStatus !== 'loaded') {
if (state.activeCourse.courseStatus !== COURSE_LOADED) {
return [];
}
const { sectionIds = [] } = state.models.courses[state.activeCourse.courseId];

View File

@@ -1,29 +1,28 @@
/* eslint-disable no-param-reassign */
import { createSlice } from '@reduxjs/toolkit';
export const LOADING = 'loading';
export const LOADED = 'loaded';
export const FAILED = 'failed';
export const DENIED = 'denied';
export const SEQUENCE_LOADING = 'loading';
export const SEQUENCE_LOADED = 'loaded';
export const SEQUENCE_FAILED = 'failed';
const slice = createSlice({
name: 'courseware',
initialState: {
sequenceStatus: 'loading',
sequenceStatus: SEQUENCE_LOADING,
sequenceId: null,
},
reducers: {
fetchSequenceRequest: (state, { payload }) => {
state.sequenceId = payload.sequenceId;
state.sequenceStatus = LOADING;
state.sequenceStatus = SEQUENCE_LOADING;
},
fetchSequenceSuccess: (state, { payload }) => {
state.sequenceId = payload.sequenceId;
state.sequenceStatus = LOADED;
state.sequenceStatus = SEQUENCE_LOADED;
},
fetchSequenceFailure: (state, { payload }) => {
state.sequenceId = payload.sequenceId;
state.sequenceStatus = FAILED;
state.sequenceStatus = SEQUENCE_FAILED;
},
},
});

View File

@@ -14,7 +14,7 @@ import {
fetchCourseSuccess,
fetchCourseFailure,
fetchCourseDenied,
} from '../../course';
} from '../../active-course';
import {
fetchSequenceRequest,
fetchSequenceSuccess,

View File

@@ -14,7 +14,7 @@ import { configureStore } from '@reduxjs/toolkit';
import { IntlProvider } from 'react-intl';
import MockAdapter from 'axios-mock-adapter';
import AppProvider from '@edx/frontend-platform/react/AppProvider';
import { reducer as activeCourseReducer } from './course';
import { reducer as activeCourseReducer } from './active-course';
import { reducer as coursewareReducer } from './courseware/data/slice';
import { reducer as modelsReducer } from './generic/model-store';
import { UserMessagesProvider } from './generic/user-messages';

View File

@@ -1,6 +1,6 @@
import { configureStore } from '@reduxjs/toolkit';
import { reducer as activeCourseReducer } from './course';
import { reducer as activeCourseReducer } from './active-course';
import { reducer as courseHomeReducer } from './course-home';
import { reducer as coursewareReducer } from './courseware';
import { reducer as modelsReducer } from './generic/model-store';

View File

@@ -10,6 +10,7 @@ import messages from './messages';
import LoadedTabPage from './LoadedTabPage';
import LearningToast from '../toast/LearningToast';
import { toggleResetDatesToast } from '../course-home/data/slice';
import { COURSE_LOADED, COURSE_LOADING } from '../active-course';
function TabPage({
intl,
@@ -22,7 +23,7 @@ function TabPage({
} = useSelector(state => state.courseHome);
const dispatch = useDispatch();
if (courseStatus === 'loading') {
if (courseStatus === COURSE_LOADING) {
return (
<>
<Header />
@@ -33,7 +34,7 @@ function TabPage({
);
}
if (courseStatus === 'loaded') {
if (courseStatus === COURSE_LOADED) {
return (
<>
<LearningToast