* Do not redirect when the sequenceId is not valid That is, if firstSequenceId is null or undefined. This prevents the url becoming bogus but does cause the course contents display to become stuck with the loading message. * Detect invalid sequence when loading If the course has no sections or the first section has no sub-sections, then sequence will be null. Before the redirection fix, this would cause an error, but after, the sequenceStatus never leaves the loading state. Thus, if still loading and the sequence is null, return the no.content message. * Check sequenceId instead of sequence From David Joy: During initial page load, I expect there's a period of time before the course blocks API and the sequence metadata API come back where the sequenceStatus is loading but the sequence is still false, meaning that we'll see a flash of this 'no content' messaging for a moment before the data comes in. If we instead check whether sequenceId is null here, that may give us a more accurate condition. The sequenceId in redux is only populated when we begin to request a sequence (fetchSequence thunk). If we have no sequence ID in the URL route, then fetchSequence never happens and the sequenceId in redux stays null. * Fix up some additional errors Piotr found This fixes errors caused by deleting units or subsections. * Move test for unit validity to SequenceContent
74 lines
1.8 KiB
JavaScript
74 lines
1.8 KiB
JavaScript
import React, { Suspense, useEffect } from 'react';
|
|
import PropTypes from 'prop-types';
|
|
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
|
import PageLoading from '../../../generic/PageLoading';
|
|
import { useModel } from '../../../generic/model-store';
|
|
|
|
import messages from './messages';
|
|
import Unit from './Unit';
|
|
|
|
const ContentLock = React.lazy(() => import('./content-lock'));
|
|
|
|
function SequenceContent({
|
|
gated, intl, courseId, sequenceId, unitId, unitLoadedHandler,
|
|
}) {
|
|
const sequence = useModel('sequences', sequenceId);
|
|
|
|
// Go back to the top of the page whenever the unit or sequence changes.
|
|
useEffect(() => {
|
|
global.scrollTo(0, 0);
|
|
}, [sequenceId, unitId]);
|
|
|
|
if (gated) {
|
|
return (
|
|
<Suspense
|
|
fallback={(
|
|
<PageLoading
|
|
srMessage={intl.formatMessage(messages['learn.loading.content.lock'])}
|
|
/>
|
|
)}
|
|
>
|
|
<ContentLock
|
|
courseId={courseId}
|
|
sequenceTitle={sequence.title}
|
|
prereqSectionName={sequence.gatedContent.gatedSectionName}
|
|
prereqId={sequence.gatedContent.prereqId}
|
|
/>
|
|
</Suspense>
|
|
);
|
|
}
|
|
|
|
const unit = useModel('units', unitId);
|
|
if (!unitId || !unit) {
|
|
return (
|
|
<div>
|
|
{intl.formatMessage(messages['learn.sequence.no.content'])}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Unit
|
|
courseId={courseId}
|
|
key={unitId}
|
|
id={unitId}
|
|
onLoaded={unitLoadedHandler}
|
|
/>
|
|
);
|
|
}
|
|
|
|
SequenceContent.propTypes = {
|
|
gated: PropTypes.bool.isRequired,
|
|
courseId: PropTypes.string.isRequired,
|
|
sequenceId: PropTypes.string.isRequired,
|
|
unitId: PropTypes.string,
|
|
unitLoadedHandler: PropTypes.func.isRequired,
|
|
intl: intlShape.isRequired,
|
|
};
|
|
|
|
SequenceContent.defaultProps = {
|
|
unitId: null,
|
|
};
|
|
|
|
export default injectIntl(SequenceContent);
|