diff --git a/src/course-home/data/__factories__/outlineTabData.factory.js b/src/course-home/data/__factories__/outlineTabData.factory.js
index 21a9ecd0..0a740c3d 100644
--- a/src/course-home/data/__factories__/outlineTabData.factory.js
+++ b/src/course-home/data/__factories__/outlineTabData.factory.js
@@ -29,6 +29,7 @@ Factory.define('outlineTabData')
upgrade_url: `${host}/dashboard`,
}))
.attrs({
+ has_scheduled_content: null,
access_expiration: null,
can_show_upgrade_sock: false,
cert_data: {
diff --git a/src/course-home/data/__snapshots__/redux.test.js.snap b/src/course-home/data/__snapshots__/redux.test.js.snap
index b6e46238..283e0455 100644
--- a/src/course-home/data/__snapshots__/redux.test.js.snap
+++ b/src/course-home/data/__snapshots__/redux.test.js.snap
@@ -382,6 +382,7 @@ Object {
"block-v1:edX+DemoX+Demo_Course+type@course+block@bcdabcdabcdabcdabcdabcdabcdabcd3": Object {
"effortActivities": undefined,
"effortTime": undefined,
+ "hasScheduledContent": false,
"id": "course-v1:edX+DemoX+Demo_Course_1",
"sectionIds": Array [
"block-v1:edX+DemoX+Demo_Course+type@chapter+block@bcdabcdabcdabcdabcdabcdabcdabcd2",
@@ -450,6 +451,7 @@ Object {
},
"handoutsHtml": "
",
"hasEnded": undefined,
+ "hasScheduledContent": null,
"id": "course-v1:edX+DemoX+Demo_Course_1",
"offer": null,
"resumeCourse": Object {
diff --git a/src/course-home/data/api.js b/src/course-home/data/api.js
index c06b6804..f1f59060 100644
--- a/src/course-home/data/api.js
+++ b/src/course-home/data/api.js
@@ -116,6 +116,7 @@ export function normalizeOutlineBlocks(courseId, blocks) {
id: courseId,
title: block.display_name,
sectionIds: block.children || [],
+ hasScheduledContent: block.has_scheduled_content,
};
break;
@@ -323,6 +324,7 @@ export async function getOutlineTabData(courseId) {
const datesWidget = camelCaseObject(data.dates_widget);
const enrollAlert = camelCaseObject(data.enroll_alert);
const handoutsHtml = data.handouts_html;
+ const hasScheduledContent = data.has_scheduled_content;
const hasEnded = data.has_ended;
const offer = camelCaseObject(data.offer);
const resumeCourse = camelCaseObject(data.resume_course);
@@ -341,6 +343,7 @@ export async function getOutlineTabData(courseId) {
datesWidget,
enrollAlert,
handoutsHtml,
+ hasScheduledContent,
hasEnded,
offer,
resumeCourse,
diff --git a/src/course-home/outline-tab/OutlineTab.jsx b/src/course-home/outline-tab/OutlineTab.jsx
index d7d65715..a6183bfb 100644
--- a/src/course-home/outline-tab/OutlineTab.jsx
+++ b/src/course-home/outline-tab/OutlineTab.jsx
@@ -23,6 +23,7 @@ import useCertificateAvailableAlert from './alerts/certificate-status-alert';
import useCourseEndAlert from './alerts/course-end-alert';
import useCourseStartAlert from './alerts/course-start-alert';
import usePrivateCourseAlert from './alerts/private-course-alert';
+import useScheduledContentAlert from './alerts/scheduled-content-alert';
import { useModel } from '../../generic/model-store';
import WelcomeMessage from './widgets/WelcomeMessage';
import ProctoringInfoPanel from './widgets/ProctoringInfoPanel';
@@ -90,6 +91,7 @@ function OutlineTab({ intl }) {
const courseEndAlert = useCourseEndAlert(courseId);
const certificateAvailableAlert = useCertificateAvailableAlert(courseId);
const privateCourseAlert = usePrivateCourseAlert(courseId);
+ const scheduledContentAlert = useScheduledContentAlert(courseId);
const rootCourseId = courses && Object.keys(courses)[0];
@@ -152,6 +154,7 @@ function OutlineTab({ intl }) {
...certificateAvailableAlert,
...courseEndAlert,
...courseStartAlert,
+ ...scheduledContentAlert,
}}
/>
)}
diff --git a/src/course-home/outline-tab/OutlineTab.test.jsx b/src/course-home/outline-tab/OutlineTab.test.jsx
index a0b81b59..138db7b4 100644
--- a/src/course-home/outline-tab/OutlineTab.test.jsx
+++ b/src/course-home/outline-tab/OutlineTab.test.jsx
@@ -694,6 +694,47 @@ describe('Outline Tab', () => {
expect(screen.queryByText('Verify your identity to earn a certificate!')).toBeInTheDocument();
});
});
+
+ describe('Scheduled Content Alert', () => {
+ it('appears correctly', async () => {
+ const now = new Date();
+ const { courseBlocks } = await buildMinimalCourseBlocks(courseId, 'Title', { hasScheduledContent: true });
+ const tomorrow = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
+ setMetadata({ is_enrolled: true });
+ setTabData({
+ course_blocks: { blocks: courseBlocks.blocks },
+ date_blocks: [
+ {
+ date_type: 'course-end-date',
+ date: tomorrow.toISOString(),
+ title: 'End',
+ },
+ ],
+ });
+ await fetchAndRender();
+ expect(screen.queryByText('More content is coming soon!')).toBeInTheDocument();
+ });
+ });
+ describe('Scheduled Content Alert not present without courseBlocks', () => {
+ it('appears correctly', async () => {
+ const now = new Date();
+ const tomorrow = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
+ setMetadata({ is_enrolled: true });
+ setTabData({
+ course_blocks: null,
+ date_blocks: [
+ {
+ date_type: 'course-end-date',
+ date: tomorrow.toISOString(),
+ title: 'End',
+ },
+ ],
+ });
+ await fetchAndRender();
+ expect(screen.getByRole('link', { name: 'Start Course' })).toBeInTheDocument();
+ expect(screen.queryByText('More content is coming soon!')).not.toBeInTheDocument();
+ });
+ });
});
describe('Certificate (web) Complete Alert', () => {
diff --git a/src/course-home/outline-tab/alerts/certificate-status-alert/CertificateStatusAlert.jsx b/src/course-home/outline-tab/alerts/certificate-status-alert/CertificateStatusAlert.jsx
index 47a1be18..ac375ac7 100644
--- a/src/course-home/outline-tab/alerts/certificate-status-alert/CertificateStatusAlert.jsx
+++ b/src/course-home/outline-tab/alerts/certificate-status-alert/CertificateStatusAlert.jsx
@@ -111,14 +111,14 @@ function CertificateStatusAlert({ intl, payload }) {
buttonMessage,
}) => (
-
+
{buttonVisible && (
-
+