diff --git a/src/containers/LearnerDashboardHeader/AuthenticatedUserDropdown.jsx b/src/containers/LearnerDashboardHeader/AuthenticatedUserDropdown.jsx
index c0ba261..34e4e5d 100644
--- a/src/containers/LearnerDashboardHeader/AuthenticatedUserDropdown.jsx
+++ b/src/containers/LearnerDashboardHeader/AuthenticatedUserDropdown.jsx
@@ -9,7 +9,7 @@ import { AvatarButton, Dropdown } from '@edx/paragon';
import { hooks as appHooks } from 'data/redux';
import urls from 'data/services/lms/urls';
-import { useIsCollapsed } from './hooks';
+import { useIsCollapsed, findCoursesNavDropdownClicked } from './hooks';
import messages from './messages';
export const AuthenticatedUserDropdown = ({ username }) => {
@@ -17,6 +17,7 @@ export const AuthenticatedUserDropdown = ({ username }) => {
const { authenticatedUser } = React.useContext(AppContext);
const { profileImage } = authenticatedUser;
const dashboard = appHooks.useEnterpriseDashboardData();
+ const { courseSearchUrl } = appHooks.usePlatformSettingsData();
const isCollapsed = useIsCollapsed();
return (
@@ -48,9 +49,14 @@ export const AuthenticatedUserDropdown = ({ username }) => {
{formatMessage(messages.profile)}
{isCollapsed && (
-
- {formatMessage(messages.viewPrograms)}
-
+ <>
+
+ {formatMessage(messages.viewPrograms)}
+
+
+ {formatMessage(messages.exploreCourses)}
+
+ >
)}
{formatMessage(messages.account)}
diff --git a/src/containers/LearnerDashboardHeader/AuthenticatedUserDropdown.test.jsx b/src/containers/LearnerDashboardHeader/AuthenticatedUserDropdown.test.jsx
index 0a8a9e8..fe76384 100644
--- a/src/containers/LearnerDashboardHeader/AuthenticatedUserDropdown.test.jsx
+++ b/src/containers/LearnerDashboardHeader/AuthenticatedUserDropdown.test.jsx
@@ -14,10 +14,14 @@ jest.mock('@edx/frontend-platform/react', () => ({
jest.mock('data/redux', () => ({
hooks: {
useEnterpriseDashboardData: jest.fn(),
+ usePlatformSettingsData: jest.fn(() => ({
+ courseSearchUrl: 'test-course-search-url',
+ })),
},
}));
jest.mock('containers/LearnerDashboardHeader/hooks', () => ({
useIsCollapsed: jest.fn(),
+ findCoursesNavDropdownClicked: (href) => jest.fn().mockName(`findCoursesNavDropdownClicked('${href}')`),
}));
describe('AuthenticatedUserDropdown', () => {
diff --git a/src/containers/LearnerDashboardHeader/__snapshots__/AuthenticatedUserDropdown.test.jsx.snap b/src/containers/LearnerDashboardHeader/__snapshots__/AuthenticatedUserDropdown.test.jsx.snap
index 76e01aa..e4c3d5b 100644
--- a/src/containers/LearnerDashboardHeader/__snapshots__/AuthenticatedUserDropdown.test.jsx.snap
+++ b/src/containers/LearnerDashboardHeader/__snapshots__/AuthenticatedUserDropdown.test.jsx.snap
@@ -50,6 +50,12 @@ exports[`AuthenticatedUserDropdown snapshots with enterprise dashboard 1`] = `
>
View Programs
+
+ Explore courses
+
diff --git a/src/containers/LearnerDashboardHeader/__snapshots__/index.test.jsx.snap b/src/containers/LearnerDashboardHeader/__snapshots__/index.test.jsx.snap
index 6fee45f..65337f2 100644
--- a/src/containers/LearnerDashboardHeader/__snapshots__/index.test.jsx.snap
+++ b/src/containers/LearnerDashboardHeader/__snapshots__/index.test.jsx.snap
@@ -28,8 +28,16 @@ exports[`LearnerDashboardHeader snapshots with collapsed 1`] = `
/>
+
@@ -66,6 +74,14 @@ exports[`LearnerDashboardHeader snapshots without collapsed 1`] = `
+
diff --git a/src/containers/LearnerDashboardHeader/hooks.js b/src/containers/LearnerDashboardHeader/hooks.js
index fa52e5d..3e683fd 100644
--- a/src/containers/LearnerDashboardHeader/hooks.js
+++ b/src/containers/LearnerDashboardHeader/hooks.js
@@ -1,5 +1,7 @@
import React from 'react';
import { useWindowSize, breakpoints } from '@edx/paragon';
+import track from 'tracking';
+import { linkNames } from 'tracking/constants';
export const useIsCollapsed = () => {
const { width } = useWindowSize();
@@ -7,4 +9,16 @@ export const useIsCollapsed = () => {
return isCollapsed;
};
-export default { useIsCollapsed };
+export const findCoursesNavClicked = (href) => track.findCourses.findCoursesClicked(href, {
+ linkName: linkNames.learnerHomeNavExplore,
+});
+
+export const findCoursesNavDropdownClicked = (href) => track.findCourses.findCoursesClicked(href, {
+ linkName: linkNames.learnerHomeNavDropdownExplore,
+});
+
+export default {
+ useIsCollapsed,
+ findCoursesNavClicked,
+ findCoursesNavDropdownClicked,
+};
diff --git a/src/containers/LearnerDashboardHeader/hooks.test.js b/src/containers/LearnerDashboardHeader/hooks.test.js
index 296deb7..79ea527 100644
--- a/src/containers/LearnerDashboardHeader/hooks.test.js
+++ b/src/containers/LearnerDashboardHeader/hooks.test.js
@@ -1,5 +1,15 @@
import { useWindowSize, breakpoints } from '@edx/paragon';
-import { useIsCollapsed } from './hooks';
+import track from 'tracking';
+import { linkNames } from 'tracking/constants';
+import { useIsCollapsed, findCoursesNavClicked, findCoursesNavDropdownClicked } from './hooks';
+
+jest.mock('tracking', () => ({
+ findCourses: {
+ findCoursesClicked: jest.fn(),
+ },
+}));
+
+const url = 'http://example.com';
describe('LearnerDashboardHeader hooks', () => {
describe('useIsCollapsed', () => {
@@ -12,4 +22,22 @@ describe('LearnerDashboardHeader hooks', () => {
expect(useIsCollapsed()).toEqual(true);
});
});
+
+ describe('findCoursesNavClicked', () => {
+ test('calls tracking with nav link name', () => {
+ findCoursesNavClicked(url);
+ expect(track.findCourses.findCoursesClicked).toHaveBeenCalledWith(url, {
+ linkName: linkNames.learnerHomeNavExplore,
+ });
+ });
+ });
+
+ describe('findCoursesNavDropdownClicked', () => {
+ test('calls tracking with dropdown link name', () => {
+ findCoursesNavDropdownClicked(url);
+ expect(track.findCourses.findCoursesClicked).toHaveBeenCalledWith(url, {
+ linkName: linkNames.learnerHomeNavDropdownExplore,
+ });
+ });
+ });
});
diff --git a/src/containers/LearnerDashboardHeader/index.jsx b/src/containers/LearnerDashboardHeader/index.jsx
index 42ceec7..60f35ab 100644
--- a/src/containers/LearnerDashboardHeader/index.jsx
+++ b/src/containers/LearnerDashboardHeader/index.jsx
@@ -2,18 +2,21 @@ import React, { useContext } from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import { AppContext } from '@edx/frontend-platform/react';
-import { Program } from '@edx/paragon/icons';
-import { Button, Image } from '@edx/paragon';
+import { Program, Search } from '@edx/paragon/icons';
+import {
+ Button, Image, IconButton, Icon,
+} from '@edx/paragon';
import topBanner from 'assets/top_stripe.svg';
import MasqueradeBar from 'containers/MasqueradeBar';
import urls from 'data/services/lms/urls';
+import { hooks as appHooks } from 'data/redux';
import AuthenticatedUserDropdown from './AuthenticatedUserDropdown';
import GreetingBanner from './GreetingBanner';
import ConfirmEmailBanner from './ConfirmEmailBanner';
-import { useIsCollapsed } from './hooks';
+import { useIsCollapsed, findCoursesNavClicked } from './hooks';
import messages from './messages';
import './index.scss';
@@ -25,6 +28,9 @@ export const UserMenu = () => {
export const LearnerDashboardHeader = () => {
const { formatMessage } = useIntl();
const isCollapsed = useIsCollapsed();
+ const { courseSearchUrl } = appHooks.usePlatformSettingsData();
+
+ const exploreCoursesClick = findCoursesNavClicked(courseSearchUrl);
return (
<>
@@ -43,9 +49,33 @@ export const LearnerDashboardHeader = () => {
{isCollapsed && }
- {isCollapsed
- ? (
)
- : ()}
+ {isCollapsed ? (
+
+
+
+
+ ) : (
+ <>
+
+
+ >
+ )}
{!isCollapsed && }
diff --git a/src/containers/LearnerDashboardHeader/index.test.jsx b/src/containers/LearnerDashboardHeader/index.test.jsx
index 4fbab24..7208a31 100644
--- a/src/containers/LearnerDashboardHeader/index.test.jsx
+++ b/src/containers/LearnerDashboardHeader/index.test.jsx
@@ -14,6 +14,14 @@ jest.mock('@edx/frontend-platform/react', () => ({
}));
jest.mock('./hooks', () => ({
useIsCollapsed: jest.fn(),
+ findCoursesNavClicked: (href) => jest.fn().mockName(`findCoursesNavClicked('${href}')`),
+}));
+jest.mock('data/redux', () => ({
+ hooks: {
+ usePlatformSettingsData: jest.fn(() => ({
+ courseSearchUrl: 'test-course-search-url',
+ })),
+ },
}));
jest.mock('containers/MasqueradeBar', () => 'MasqueradeBar');
diff --git a/src/containers/LearnerDashboardHeader/messages.js b/src/containers/LearnerDashboardHeader/messages.js
index 117d6d5..3105055 100644
--- a/src/containers/LearnerDashboardHeader/messages.js
+++ b/src/containers/LearnerDashboardHeader/messages.js
@@ -57,6 +57,11 @@ const messages = defineMessages({
defaultMessage: 'Switch to Programs',
description: 'Header link for switching to program page.',
},
+ exploreCourses: {
+ id: 'leanerDashboard.exploreCourses',
+ defaultMessage: 'Explore courses',
+ description: 'Header link for switching to course page.',
+ },
});
export default messages;
diff --git a/src/tracking/constants.js b/src/tracking/constants.js
index b561af4..32bbc5c 100644
--- a/src/tracking/constants.js
+++ b/src/tracking/constants.js
@@ -4,6 +4,7 @@ export const categories = StrictDict({
dashboard: 'dashboard',
upgrade: 'upgrade',
userEngagement: 'user-engagement',
+ searchButton: 'search_button',
});
export const events = StrictDict({
@@ -46,6 +47,12 @@ export const eventNames = StrictDict({
enterpriseDashboardModalOpened: `${learnerPortal}.opened`,
enterpriseDashboardModalCTAClicked: `${learnerPortal}.dashboard_cta.clicked`,
enterpriseDashboardModalClosed: `${learnerPortal}.closed`,
+ findCoursesClicked: 'edx.bi.dashboard.find_courses_button.clicked',
+});
+
+export const linkNames = StrictDict({
+ learnerHomeNavExplore: 'learner_home_nav_explore',
+ learnerHomeNavDropdownExplore: 'learner_home_nav_dropdown_explore',
});
export const appName = 'learner-home';
diff --git a/src/tracking/index.js b/src/tracking/index.js
index cccd169..30f5557 100644
--- a/src/tracking/index.js
+++ b/src/tracking/index.js
@@ -3,6 +3,7 @@ import engagement from './trackers/engagement';
import enterpriseDashboard from './trackers/enterpriseDashboard';
import entitlements from './trackers/entitlements';
import socialShare from './trackers/socialShare';
+import findCourses from './trackers/findCourses';
export default {
course,
@@ -10,4 +11,5 @@ export default {
enterpriseDashboard,
entitlements,
socialShare,
+ findCourses,
};
diff --git a/src/tracking/trackers/findCourses.js b/src/tracking/trackers/findCourses.js
new file mode 100644
index 0000000..495f32a
--- /dev/null
+++ b/src/tracking/trackers/findCourses.js
@@ -0,0 +1,16 @@
+import { createLinkTracker, createEventTracker } from 'data/services/segment/utils';
+import { categories, eventNames } from '../constants';
+
+export const findCoursesClicked = (href, args = {}) => createLinkTracker(
+ createEventTracker(eventNames.findCoursesClicked, {
+ pageName: 'learner_home',
+ linkType: 'button',
+ linkCategory: categories.searchButton,
+ ...args,
+ }),
+ href,
+);
+
+export default {
+ findCoursesClicked,
+};
diff --git a/src/tracking/trackers/findCourses.test.js b/src/tracking/trackers/findCourses.test.js
new file mode 100644
index 0000000..24b5719
--- /dev/null
+++ b/src/tracking/trackers/findCourses.test.js
@@ -0,0 +1,44 @@
+import { createLinkTracker, createEventTracker } from 'data/services/segment/utils';
+import { findCoursesClicked } from './findCourses';
+import { categories, eventNames } from '../constants';
+
+jest.mock('data/services/segment/utils', () => ({
+ createEventTracker: jest.fn((args) => ({ createEventTracker: args })),
+ createLinkTracker: jest.fn((args) => ({ createLinkTracker: args })),
+}));
+
+describe('find courses trackers', () => {
+ const url = 'http://example.com';
+ const defaultProps = {
+ pageName: 'learner_home',
+ linkType: 'button',
+ linkCategory: categories.searchButton,
+ };
+ beforeEach(() => {
+ createEventTracker.mockClear();
+ createLinkTracker.mockClear();
+ });
+ test('no args', () => {
+ findCoursesClicked(url);
+ expect(createEventTracker).toHaveBeenCalledWith(eventNames.findCoursesClicked, defaultProps);
+ expect(createLinkTracker).toHaveBeenCalledWith(
+ createEventTracker(eventNames.findCoursesClicked, defaultProps), url,
+ );
+ });
+
+ test('with args', () => {
+ const args = { linkName: 'foo' };
+ findCoursesClicked(url, args);
+ expect(createEventTracker).toHaveBeenCalledWith(eventNames.findCoursesClicked, {
+ ...defaultProps,
+ ...args,
+ });
+ expect(createLinkTracker).toHaveBeenCalledWith(
+ createEventTracker(eventNames.findCoursesClicked, {
+ ...defaultProps,
+ ...args,
+ }),
+ url,
+ );
+ });
+});
diff --git a/src/widgets/LookingForChallengeWidget/__snapshots__/index.test.jsx.snap b/src/widgets/LookingForChallengeWidget/__snapshots__/index.test.jsx.snap
index f13ad67..191f37b 100644
--- a/src/widgets/LookingForChallengeWidget/__snapshots__/index.test.jsx.snap
+++ b/src/widgets/LookingForChallengeWidget/__snapshots__/index.test.jsx.snap
@@ -19,6 +19,7 @@ exports[`LookingForChallengeWidget snapshots default 1`] = `
{
{formatMessage(messages.findCoursesButton, { arrow: arrowIcon })}
diff --git a/src/widgets/LookingForChallengeWidget/index.test.jsx b/src/widgets/LookingForChallengeWidget/index.test.jsx
index 6114679..94df1b8 100644
--- a/src/widgets/LookingForChallengeWidget/index.test.jsx
+++ b/src/widgets/LookingForChallengeWidget/index.test.jsx
@@ -11,7 +11,7 @@ jest.mock('data/redux', () => ({
}));
jest.mock('../RecommendationsPanel/track', () => ({
- findCoursesClicked: jest.fn().mockName('track.findCoursesClicked'),
+ findCoursesWidgetClicked: (href) => jest.fn().mockName(`track.findCoursesWidgetClicked('${href}')`),
}));
describe('LookingForChallengeWidget', () => {
diff --git a/src/widgets/RecommendationsPanel/LoadedView.jsx b/src/widgets/RecommendationsPanel/LoadedView.jsx
index 20f1c3a..e5e157a 100644
--- a/src/widgets/RecommendationsPanel/LoadedView.jsx
+++ b/src/widgets/RecommendationsPanel/LoadedView.jsx
@@ -39,7 +39,7 @@ export const LoadedView = ({
iconBefore={Search}
as="a"
href={courseSearchUrl}
- onClick={track.findCoursesClicked(courseSearchUrl)}
+ onClick={track.findCoursesWidgetClicked(courseSearchUrl)}
>
{formatMessage(messages.exploreCoursesButton)}
diff --git a/src/widgets/RecommendationsPanel/LoadedView.test.jsx b/src/widgets/RecommendationsPanel/LoadedView.test.jsx
index 2f5cb14..c2fdb46 100644
--- a/src/widgets/RecommendationsPanel/LoadedView.test.jsx
+++ b/src/widgets/RecommendationsPanel/LoadedView.test.jsx
@@ -14,7 +14,7 @@ jest.mock('data/redux', () => ({
},
}));
jest.mock('./track', () => ({
- findCoursesClicked: () => 'find-courses-clicked',
+ findCoursesWidgetClicked: (href) => jest.fn().mockName(`track.findCoursesWidgetClicked('${href}')`),
}));
describe('RecommendationsPanel LoadedView', () => {
diff --git a/src/widgets/RecommendationsPanel/__snapshots__/LoadedView.test.jsx.snap b/src/widgets/RecommendationsPanel/__snapshots__/LoadedView.test.jsx.snap
index d074753..08eaaa5 100644
--- a/src/widgets/RecommendationsPanel/__snapshots__/LoadedView.test.jsx.snap
+++ b/src/widgets/RecommendationsPanel/__snapshots__/LoadedView.test.jsx.snap
@@ -65,7 +65,7 @@ exports[`RecommendationsPanel LoadedView snapshot with personalize recommendatio