+ {intl.formatMessage(messages.contactSupport)}
+
+ ),
+ }}
+ />
+ );
+
+ const header = error
+ ? intl.formatMessage(messages.errorHeader)
+ : intl.formatMessage(messages.header);
+ const description = error
+ ? errorDescription
+ : intl.formatMessage(messages.description, { courseTitle });
+
+ return (
+ <>
+
+ {header}
+ {description}
+
+ >
+ );
+}
+
+ResultPage.defaultProps = {
+ courseTitle: null,
+ error: false,
+};
+
+ResultPage.propTypes = {
+ courseTitle: PropTypes.string,
+ error: PropTypes.bool,
+ intl: intlShape.isRequired,
+};
+
+export default injectIntl(ResultPage);
diff --git a/src/course-home/goal-unsubscribe/index.jsx b/src/course-home/goal-unsubscribe/index.jsx
new file mode 100644
index 00000000..3c8b672c
--- /dev/null
+++ b/src/course-home/goal-unsubscribe/index.jsx
@@ -0,0 +1,3 @@
+import GoalUnsubscribe from './GoalUnsubscribe';
+
+export default GoalUnsubscribe;
diff --git a/src/course-home/goal-unsubscribe/messages.js b/src/course-home/goal-unsubscribe/messages.js
new file mode 100644
index 00000000..db789dfa
--- /dev/null
+++ b/src/course-home/goal-unsubscribe/messages.js
@@ -0,0 +1,30 @@
+import { defineMessages } from '@edx/frontend-platform/i18n';
+
+const messages = defineMessages({
+ contactSupport: {
+ id: 'learning.goals.unsubscribe.contact',
+ defaultMessage: 'contact support',
+ },
+ description: {
+ id: 'learning.goals.unsubscribe.description',
+ defaultMessage: 'You will no longer receive email reminders about your goal for {courseTitle}.',
+ },
+ errorHeader: {
+ id: 'learning.goals.unsubscribe.errorHeader',
+ defaultMessage: 'Something went wrong',
+ },
+ goToDashboard: {
+ id: 'learning.goals.unsubscribe.goToDashboard',
+ defaultMessage: 'Go to dashboard',
+ },
+ header: {
+ id: 'learning.goals.unsubscribe.header',
+ defaultMessage: 'You’ve unsubscribed from goal reminders',
+ },
+ loading: {
+ id: 'learning.goals.unsubscribe.loading',
+ defaultMessage: 'Unsubscribing…',
+ },
+});
+
+export default messages;
diff --git a/src/course-home/goal-unsubscribe/unsubscribe.svg b/src/course-home/goal-unsubscribe/unsubscribe.svg
new file mode 100644
index 00000000..68e720e0
--- /dev/null
+++ b/src/course-home/goal-unsubscribe/unsubscribe.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/course-home/outline-tab/OutlineTab.test.jsx b/src/course-home/outline-tab/OutlineTab.test.jsx
index bc0a3b80..1fb00eb9 100644
--- a/src/course-home/outline-tab/OutlineTab.test.jsx
+++ b/src/course-home/outline-tab/OutlineTab.test.jsx
@@ -24,11 +24,11 @@ describe('Outline Tab', () => {
let axiosMock;
const courseId = 'course-v1:edX+Test+run';
- let courseMetadataUrl = `${getConfig().LMS_BASE_URL}/api/course_home/v1/course_metadata/${courseId}`;
+ let courseMetadataUrl = `${getConfig().LMS_BASE_URL}/api/course_home/course_metadata/${courseId}`;
courseMetadataUrl = appendBrowserTimezoneToUrl(courseMetadataUrl);
const enrollmentUrl = `${getConfig().LMS_BASE_URL}/api/enrollment/v1/enrollment`;
- const goalUrl = `${getConfig().LMS_BASE_URL}/api/course_home/v1/save_course_goal`;
- const outlineUrl = `${getConfig().LMS_BASE_URL}/api/course_home/v1/outline/${courseId}`;
+ const goalUrl = `${getConfig().LMS_BASE_URL}/api/course_home/save_course_goal`;
+ const outlineUrl = `${getConfig().LMS_BASE_URL}/api/course_home/outline/${courseId}`;
const proctoringInfoUrl = `${getConfig().LMS_BASE_URL}/api/edx_proctoring/v1/user_onboarding/status?is_learning_mfe=true&course_id=${encodeURIComponent(courseId)}`;
const store = initializeStore();
diff --git a/src/course-home/progress-tab/ProgressTab.test.jsx b/src/course-home/progress-tab/ProgressTab.test.jsx
index 2558b003..bdcd8df1 100644
--- a/src/course-home/progress-tab/ProgressTab.test.jsx
+++ b/src/course-home/progress-tab/ProgressTab.test.jsx
@@ -20,9 +20,9 @@ describe('Progress Tab', () => {
let axiosMock;
const courseId = 'course-v1:edX+Test+run';
- let courseMetadataUrl = `${getConfig().LMS_BASE_URL}/api/course_home/v1/course_metadata/${courseId}`;
+ let courseMetadataUrl = `${getConfig().LMS_BASE_URL}/api/course_home/course_metadata/${courseId}`;
courseMetadataUrl = appendBrowserTimezoneToUrl(courseMetadataUrl);
- const progressUrl = new RegExp(`${getConfig().LMS_BASE_URL}/api/course_home/v1/progress/*`);
+ const progressUrl = new RegExp(`${getConfig().LMS_BASE_URL}/api/course_home/progress/*`);
const store = initializeStore();
const defaultMetadata = Factory.build('courseHomeMetadata', { id: courseId });
diff --git a/src/generic/PageLoading.jsx b/src/generic/PageLoading.jsx
index d7a81295..1ffc783e 100644
--- a/src/generic/PageLoading.jsx
+++ b/src/generic/PageLoading.jsx
@@ -1,6 +1,8 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
+import { Spinner } from '@edx/paragon';
+
export default class PageLoading extends Component {
renderSrMessage() {
if (!this.props.srMessage) {
@@ -23,9 +25,9 @@ export default class PageLoading extends Component {
height: '50vh',
}}
>
-
+
{this.renderSrMessage()}
-
+
);
diff --git a/src/index.jsx b/src/index.jsx
index ff42d84a..f25efc06 100755
--- a/src/index.jsx
+++ b/src/index.jsx
@@ -10,7 +10,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { Switch } from 'react-router-dom';
-import Footer, { messages as footerMessages } from '@edx/frontend-component-footer';
+import { messages as footerMessages } from '@edx/frontend-component-footer';
import appMessages from './i18n';
import { UserMessagesProvider } from './generic/user-messages';
@@ -21,6 +21,7 @@ import { CourseExit } from './courseware/course/course-exit';
import CoursewareContainer from './courseware';
import CoursewareRedirectLandingPage from './courseware/CoursewareRedirectLandingPage';
import DatesTab from './course-home/dates-tab';
+import GoalUnsubscribe from './course-home/goal-unsubscribe';
import ProgressTab from './course-home/progress-tab/ProgressTab';
import { TabContainer } from './tab-page';
@@ -33,6 +34,7 @@ subscribe(APP_READY, () => {
+
@@ -73,7 +75,6 @@ subscribe(APP_READY, () => {
component={CoursewareContainer}
/>
-
,
document.getElementById('root'),
@@ -88,6 +89,7 @@ initialize({
handlers: {
config: () => {
mergeConfig({
+ CONTACT_URL: process.env.CONTACT_URL || null,
CREDENTIALS_BASE_URL: process.env.CREDENTIALS_BASE_URL || null,
ENTERPRISE_LEARNER_PORTAL_HOSTNAME: process.env.ENTERPRISE_LEARNER_PORTAL_HOSTNAME || null,
INSIGHTS_BASE_URL: process.env.INSIGHTS_BASE_URL || null,
diff --git a/src/setupTest.js b/src/setupTest.js
index 4fb05c6e..2fb761b6 100755
--- a/src/setupTest.js
+++ b/src/setupTest.js
@@ -73,6 +73,7 @@ export const authenticatedUser = {
export function initializeMockApp() {
mergeConfig({
+ CONTACT_URL: process.env.CONTACT_URL || null,
INSIGHTS_BASE_URL: process.env.INSIGHTS_BASE_URL || null,
STUDIO_BASE_URL: process.env.STUDIO_BASE_URL || null,
TWITTER_URL: process.env.TWITTER_URL || null,
diff --git a/src/tab-page/LoadedTabPage.jsx b/src/tab-page/LoadedTabPage.jsx
index 34598274..b901b4d0 100644
--- a/src/tab-page/LoadedTabPage.jsx
+++ b/src/tab-page/LoadedTabPage.jsx
@@ -5,7 +5,7 @@ import { Helmet } from 'react-helmet';
import { getConfig } from '@edx/frontend-platform';
import { useToggle } from '@edx/paragon';
-import { Header, CourseTabsNavigation } from '../course-header';
+import { CourseTabsNavigation } from '../course-header';
import { useModel } from '../generic/model-store';
import { AlertList } from '../generic/user-messages';
import StreakModal from '../shared/streak-celebration';
@@ -22,8 +22,6 @@ function LoadedTabPage({
}) {
const {
originalUserIsStaff,
- number,
- org,
tabs,
title,
celebrations,
@@ -47,11 +45,6 @@ function LoadedTabPage({
{`${activeTab ? `${activeTab.title} | ` : ''}${title} | ${getConfig().SITE_NAME}`}
-
{originalUserIsStaff && (
+
>
);
}
@@ -68,7 +73,13 @@ function TabPage({ intl, ...props }) {
>
{toastHeader}
+
+
>
);
}
@@ -80,6 +91,7 @@ function TabPage({ intl, ...props }) {
{intl.formatMessage(messages.failure)}
+
>
);
}