diff --git a/.env b/.env
index a8774b81..83803d07 100644
--- a/.env
+++ b/.env
@@ -17,6 +17,7 @@ FAVICON_URL=null
MARKETING_SITE_BASE_URL=null
ORDER_HISTORY_URL=null
REFRESH_ACCESS_TOKEN_ENDPOINT=null
+SEARCH_CATALOG_URL=null
SEGMENT_KEY=null
SITE_NAME=null
SOCIAL_UTM_MILESTONE_CAMPAIGN=null
diff --git a/.env.development b/.env.development
index 3475c068..bbfa8af4 100644
--- a/.env.development
+++ b/.env.development
@@ -17,6 +17,7 @@ MARKETING_SITE_BASE_URL='http://localhost:18000'
ORDER_HISTORY_URL='http://localhost:1996/orders'
PORT=2000
REFRESH_ACCESS_TOKEN_ENDPOINT='http://localhost:18000/login_refresh'
+SEARCH_CATALOG_URL='http://localhost:18000/courses'
SEGMENT_KEY=null
SITE_NAME='edX'
SOCIAL_UTM_MILESTONE_CAMPAIGN='edxmilestone'
diff --git a/.env.test b/.env.test
index 09d05b40..09318fae 100644
--- a/.env.test
+++ b/.env.test
@@ -17,6 +17,7 @@ MARKETING_SITE_BASE_URL='http://localhost:18000'
ORDER_HISTORY_URL='http://localhost:1996/orders'
PORT=2000
REFRESH_ACCESS_TOKEN_ENDPOINT='http://localhost:18000/login_refresh'
+SEARCH_CATALOG_URL='http://localhost:18000/courses'
SEGMENT_KEY=null
SITE_NAME='edX'
SOCIAL_UTM_MILESTONE_CAMPAIGN='edxmilestone'
diff --git a/src/courseware/course/course-exit/CatalogSuggestion.jsx b/src/courseware/course/course-exit/CatalogSuggestion.jsx
new file mode 100644
index 00000000..1ee21d89
--- /dev/null
+++ b/src/courseware/course/course-exit/CatalogSuggestion.jsx
@@ -0,0 +1,54 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { useSelector } from 'react-redux';
+
+import { getConfig } from '@edx/frontend-platform';
+import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
+import {
+ FormattedMessage, injectIntl, intlShape,
+} from '@edx/frontend-platform/i18n';
+import { Hyperlink } from '@edx/paragon';
+import { faSearch } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+
+import { useModel } from '../../../generic/model-store';
+
+import messages from './messages';
+import { logClick } from './utils';
+
+function CatalogSuggestion({ intl, variant }) {
+ const { courseId } = useSelector(state => state.courseware);
+ const { org } = useModel('courses', courseId);
+ const { administrator } = getAuthenticatedUser();
+
+ const searchOurCatalogLink = (
+ logClick(org, courseId, administrator, 'catalog_search', { variant })}
+ >
+ {intl.formatMessage(messages.searchOurCatalogLink)}
+
+ );
+
+ return (
+
+ );
+}
+
+CatalogSuggestion.propTypes = {
+ intl: intlShape.isRequired,
+ variant: PropTypes.string.isRequired,
+};
+
+export default injectIntl(CatalogSuggestion);
diff --git a/src/courseware/course/course-exit/CourseCelebration.jsx b/src/courseware/course/course-exit/CourseCelebration.jsx
index db2f2ce5..f846fb00 100644
--- a/src/courseware/course/course-exit/CourseCelebration.jsx
+++ b/src/courseware/course/course-exit/CourseCelebration.jsx
@@ -12,6 +12,7 @@ import { Alert, Button, Hyperlink } from '@edx/paragon';
import { getConfig } from '@edx/frontend-platform';
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
+import CatalogSuggestion from './CatalogSuggestion';
import CelebrationMobile from './assets/celebration_456x328.gif';
import CelebrationDesktop from './assets/celebration_750x540.gif';
import certificate from '../../../generic/assets/edX_verified_certificate.png';
@@ -119,7 +120,7 @@ function CourseCelebration({ intl }) {
}
buttonEvent = 'view_cert';
visitEvent = 'celebration_with_cert';
- footnote = ;
+ footnote = ;
break;
case 'earned_but_not_available': {
const endDate = ;
@@ -146,7 +147,7 @@ function CourseCelebration({ intl }) {
>
);
visitEvent = 'celebration_with_unavailable_cert';
- footnote = ;
+ footnote = ;
break;
}
case 'requesting':
@@ -155,12 +156,12 @@ function CourseCelebration({ intl }) {
certHeader = intl.formatMessage(messages.certificateHeaderRequestable);
message = ({intl.formatMessage(messages.requestCertificateBodyText)}
);
visitEvent = 'celebration_with_requestable_cert';
- footnote = ;
+ footnote = ;
break;
case 'unverified':
certHeader = intl.formatMessage(messages.certificateHeaderUnverified);
visitEvent = 'celebration_unverified';
- footnote = ;
+ footnote = ;
if (verificationStatus === 'pending') {
message = ({intl.formatMessage(messages.verificationPending)}
);
} else {
@@ -215,7 +216,7 @@ function CourseCelebration({ intl }) {
if (verifiedMode.accessExpirationDate) {
footnote = ;
} else {
- footnote = ;
+ footnote = ;
}
}
break;
@@ -323,6 +324,7 @@ function CourseCelebration({ intl }) {
/>
))}
{footnote}
+
>
diff --git a/src/courseware/course/course-exit/CourseNonPassing.jsx b/src/courseware/course/course-exit/CourseNonPassing.jsx
index bb090611..bb15a4b8 100644
--- a/src/courseware/course/course-exit/CourseNonPassing.jsx
+++ b/src/courseware/course/course-exit/CourseNonPassing.jsx
@@ -9,6 +9,7 @@ import { getConfig } from '@edx/frontend-platform';
import { useModel } from '../../../generic/model-store';
+import CatalogSuggestion from './CatalogSuggestion';
import DashboardFootnote from './DashboardFootnote';
import messages from './messages';
import { logClick, logVisit } from './utils';
@@ -48,7 +49,8 @@ function CourseNonPassing({ intl }) {
)}
-
+
+
>
);
diff --git a/src/courseware/course/course-exit/DashboardFootnote.jsx b/src/courseware/course/course-exit/DashboardFootnote.jsx
index ab10c22c..512a816b 100644
--- a/src/courseware/course/course-exit/DashboardFootnote.jsx
+++ b/src/courseware/course/course-exit/DashboardFootnote.jsx
@@ -1,5 +1,8 @@
import React from 'react';
+import PropTypes from 'prop-types';
+import { useSelector } from 'react-redux';
+import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
import {
FormattedMessage, injectIntl, intlShape,
} from '@edx/frontend-platform/i18n';
@@ -7,15 +10,23 @@ import { Hyperlink } from '@edx/paragon';
import { faCalendarAlt } from '@fortawesome/free-regular-svg-icons';
import { getConfig } from '@edx/frontend-platform';
+import { useModel } from '../../../generic/model-store';
+
import Footnote from './Footnote';
import messages from './messages';
+import { logClick } from './utils';
+
+function DashboardFootnote({ intl, variant }) {
+ const { courseId } = useSelector(state => state.courseware);
+ const { org } = useModel('courses', courseId);
+ const { administrator } = getAuthenticatedUser();
-function DashboardFootnote({ intl }) {
const dashboardLink = (
logClick(org, courseId, administrator, 'dashboard_footnote', { variant })}
>
{intl.formatMessage(messages.dashboardLink)}
@@ -37,6 +48,7 @@ function DashboardFootnote({ intl }) {
DashboardFootnote.propTypes = {
intl: intlShape.isRequired,
+ variant: PropTypes.string.isRequired,
};
export default injectIntl(DashboardFootnote);
diff --git a/src/courseware/course/course-exit/messages.js b/src/courseware/course/course-exit/messages.js
index 9d449d0f..01dcbc85 100644
--- a/src/courseware/course/course-exit/messages.js
+++ b/src/courseware/course/course-exit/messages.js
@@ -114,6 +114,11 @@ const messages = defineMessages({
defaultMessage: 'Request certificate',
description: 'Button to request the course certificate',
},
+ searchOurCatalogLink: {
+ id: 'courseExit.searchOurCatalogLink',
+ defaultMessage: 'Search our catalog',
+ description: 'First part of a sentence that continues afterward',
+ },
shareHeader: {
id: 'courseCelebration.shareHeader',
defaultMessage: 'You have completed your course. Share your success on social media or email.',
diff --git a/src/courseware/course/course-exit/utils.js b/src/courseware/course/course-exit/utils.js
index d76b05ba..a89e2dcf 100644
--- a/src/courseware/course/course-exit/utils.js
+++ b/src/courseware/course/course-exit/utils.js
@@ -72,7 +72,7 @@ function getCourseExitText(courseId, intl) {
// Meant to be used as part of a button's onClick handler.
// For convenience, you can pass a falsy event and it will be ignored.
-const logClick = (org, courseId, administrator, event) => {
+const logClick = (org, courseId, administrator, event, extraProperties) => {
if (!event) {
return;
}
@@ -81,6 +81,7 @@ const logClick = (org, courseId, administrator, event) => {
org_key: org,
courserun_key: courseId,
is_staff: administrator,
+ ...extraProperties,
});
};
diff --git a/src/index.jsx b/src/index.jsx
index 99100bf6..b9cd193d 100755
--- a/src/index.jsx
+++ b/src/index.jsx
@@ -79,7 +79,9 @@ initialize({
config: () => {
mergeConfig({
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,
+ SEARCH_CATALOG_URL: process.env.SEARCH_CATALOG_URL || null,
SOCIAL_UTM_MILESTONE_CAMPAIGN: process.env.SOCIAL_UTM_MILESTONE_CAMPAIGN || null,
STUDIO_BASE_URL: process.env.STUDIO_BASE_URL || null,
SUPPORT_URL: process.env.SUPPORT_URL || null,
@@ -88,7 +90,6 @@ initialize({
SUPPORT_URL_VERIFIED_CERTIFICATE: process.env.SUPPORT_URL_VERIFIED_CERTIFICATE || null,
TWITTER_HASHTAG: process.env.TWITTER_HASHTAG || null,
TWITTER_URL: process.env.TWITTER_URL || null,
- ENTERPRISE_LEARNER_PORTAL_HOSTNAME: process.env.ENTERPRISE_LEARNER_PORTAL_HOSTNAME || null,
}, 'LearnerAppConfig');
},
},