From 2d4db5683353155ba046bb0d4fc79a10c24695ea Mon Sep 17 00:00:00 2001 From: Ahtesham Quraish Date: Thu, 25 Apr 2024 15:37:27 +0500 Subject: [PATCH] fix: replace the header with openedx header Description: Replace the header with openedx header van-1914 --- package-lock.json | 85 ++++++++++- package.json | 1 + src/App.scss | 1 + .../CollapsedHeader/CollapseMenuBody.jsx | 104 ------------- .../CollapsedHeader/CollapseMenuBody.test.jsx | 48 ------ .../CollapseMenuBody.test.jsx.snap | 105 ------------- .../__snapshots__/index.test.jsx.snap | 48 ------ .../CollapsedHeader/index.jsx | 47 ------ .../CollapsedHeader/index.test.jsx | 38 ----- .../AuthenticatedUserDropdown.jsx | 78 ---------- .../AuthenticatedUserDropdown.test.jsx | 81 ---------- .../AuthenticatedUserDropdown.test.jsx.snap | 139 ------------------ .../__snapshots__/index.test.jsx.snap | 52 ------- .../ExpandedHeader/index.jsx | 76 ---------- .../ExpandedHeader/index.test.jsx | 41 ------ .../LearnerDashboardMenu.jsx | 75 ++++++++++ .../__snapshots__/index.test.jsx.snap | 68 ++++++++- .../LearnerDashboardHeader/hooks.js | 11 ++ .../LearnerDashboardHeader/hooks.test.js | 12 ++ .../LearnerDashboardHeader/index.jsx | 42 ++++-- .../LearnerDashboardHeader/index.test.jsx | 25 +++- 21 files changed, 299 insertions(+), 878 deletions(-) delete mode 100644 src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.jsx delete mode 100644 src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.test.jsx delete mode 100644 src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/CollapseMenuBody.test.jsx.snap delete mode 100644 src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/index.test.jsx.snap delete mode 100644 src/containers/LearnerDashboardHeader/CollapsedHeader/index.jsx delete mode 100644 src/containers/LearnerDashboardHeader/CollapsedHeader/index.test.jsx delete mode 100644 src/containers/LearnerDashboardHeader/ExpandedHeader/AuthenticatedUserDropdown.jsx delete mode 100644 src/containers/LearnerDashboardHeader/ExpandedHeader/AuthenticatedUserDropdown.test.jsx delete mode 100644 src/containers/LearnerDashboardHeader/ExpandedHeader/__snapshots__/AuthenticatedUserDropdown.test.jsx.snap delete mode 100644 src/containers/LearnerDashboardHeader/ExpandedHeader/__snapshots__/index.test.jsx.snap delete mode 100644 src/containers/LearnerDashboardHeader/ExpandedHeader/index.jsx delete mode 100644 src/containers/LearnerDashboardHeader/ExpandedHeader/index.test.jsx create mode 100644 src/containers/LearnerDashboardHeader/LearnerDashboardMenu.jsx diff --git a/package-lock.json b/package-lock.json index a73e86c78..15f74d193 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@edx/brand": "npm:@openedx/brand-openedx@^1.2.2", "@edx/browserslist-config": "^1.1.0", + "@edx/frontend-component-header": "^5.3.1", "@edx/frontend-enterprise-hotjar": "3.0.0", "@edx/frontend-platform": "8.1.1", "@edx/openedx-atlas": "^0.6.0", @@ -2242,9 +2243,9 @@ } }, "node_modules/@edx/frontend-component-footer": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@edx/frontend-component-footer/-/frontend-component-footer-14.0.0.tgz", - "integrity": "sha512-3Riz6ippBnPz1oq6gZgFBx27bJkNL+rwwKrv0uCuHV/5MscS1aYeKx1ZAMuUsxkKcGX6uhyU6PwM6agvnhKfNQ==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@edx/frontend-component-footer/-/frontend-component-footer-13.1.0.tgz", + "integrity": "sha512-Rtv8dfQmL75El8kF8dG9nYF1Cqj2AbWPLVLE4b0XTvipfx2RMeDKpgAO5XLAzTt0h+5fmiMCGhVEv3Y70Xu5pQ==", "peer": true, "dependencies": { "@fortawesome/fontawesome-svg-core": "6.5.2", @@ -2326,6 +2327,82 @@ "react": ">=16.3" } }, + "node_modules/@edx/frontend-component-header": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/@edx/frontend-component-header/-/frontend-component-header-5.3.4.tgz", + "integrity": "sha512-niuaXu0+qWPHud9Bs1pqmNXvZc9jpf8WS270/2YEH5owokd+BiDwQ6MWkvS9qbuQIVGPGTSZFFTttUKmQO5O0A==", + "dependencies": { + "@fortawesome/fontawesome-svg-core": "6.6.0", + "@fortawesome/free-brands-svg-icons": "6.6.0", + "@fortawesome/free-regular-svg-icons": "6.6.0", + "@fortawesome/free-solid-svg-icons": "6.6.0", + "@fortawesome/react-fontawesome": "^0.2.0", + "axios-mock-adapter": "1.22.0", + "babel-polyfill": "6.26.0", + "jest-environment-jsdom": "^29.7.0", + "react-responsive": "8.2.0", + "react-transition-group": "4.4.5" + }, + "peerDependencies": { + "@edx/frontend-platform": "^7.0.0 || ^8.0.0", + "@openedx/paragon": ">= 21.5.7 < 23.0.0", + "prop-types": "^15.5.10", + "react": "^16.9.0 || ^17.0.0", + "react-dom": "^16.9.0 || ^17.0.0" + } + }, + "node_modules/@edx/frontend-component-header/node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.6.0.tgz", + "integrity": "sha512-xyX0X9mc0kyz9plIyryrRbl7ngsA9jz77mCZJsUkLl+ZKs0KWObgaEBoSgQiYWAsSmjz/yjl0F++Got0Mdp4Rw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@edx/frontend-component-header/node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.6.0.tgz", + "integrity": "sha512-KHwPkCk6oRT4HADE7smhfsKudt9N/9lm6EJ5BVg0tD1yPA5hht837fB87F8pn15D8JfTqQOjhKTktwmLMiD7Kg==", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@edx/frontend-component-header/node_modules/@fortawesome/free-brands-svg-icons": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.6.0.tgz", + "integrity": "sha512-1MPD8lMNW/earme4OQi1IFHtmHUwAKgghXlNwWi9GO7QkTfD+IIaYpIai4m2YJEzqfEji3jFHX1DZI5pbY/biQ==", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@edx/frontend-component-header/node_modules/@fortawesome/free-regular-svg-icons": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.6.0.tgz", + "integrity": "sha512-Yv9hDzL4aI73BEwSEh20clrY8q/uLxawaQ98lekBx6t9dQKDHcDzzV1p2YtBGTtolYtNqcWdniOnhzB+JPnQEQ==", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@edx/frontend-component-header/node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.6.0.tgz", + "integrity": "sha512-IYv/2skhEDFc2WGUcqvFJkeK39Q+HyPf5GHUrT/l2pKbtgEIv1al1TKd6qStR5OIwQdN1GZP54ci3y4mroJWjA==", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.6.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@edx/frontend-enterprise-hotjar": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@edx/frontend-enterprise-hotjar/-/frontend-enterprise-hotjar-3.0.0.tgz", @@ -7004,7 +7081,6 @@ "version": "1.22.0", "resolved": "https://registry.npmjs.org/axios-mock-adapter/-/axios-mock-adapter-1.22.0.tgz", "integrity": "sha512-dmI0KbkyAhntUR05YY96qg2H6gg0XMl2+qTW0xmYg6Up+BFBAJYRLROMXRdDEL06/Wqwa0TJThAYvFtSFdRCZw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", "is-buffer": "^2.0.5" @@ -13314,7 +13390,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, "funding": [ { "type": "github", diff --git a/package.json b/package.json index 2604b58b3..2f9084cee 100755 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "dependencies": { "@edx/brand": "npm:@openedx/brand-openedx@^1.2.2", "@edx/browserslist-config": "^1.1.0", + "@edx/frontend-component-header": "^5.3.1", "@edx/frontend-enterprise-hotjar": "3.0.0", "@edx/frontend-platform": "8.1.1", "@edx/openedx-atlas": "^0.6.0", diff --git a/src/App.scss b/src/App.scss index eed6b145a..2292f72e7 100755 --- a/src/App.scss +++ b/src/App.scss @@ -9,6 +9,7 @@ $fa-font-path: "~font-awesome/fonts"; $input-focus-box-shadow: $input-box-shadow; // hack to get upgrade to paragon 4.0.0 to work +@import "~@edx/frontend-component-header/dist/index"; @import "~@edx/frontend-component-footer/dist/_footer"; .text-ellipsis { diff --git a/src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.jsx b/src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.jsx deleted file mode 100644 index 82de5aaf5..000000000 --- a/src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.jsx +++ /dev/null @@ -1,104 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -import { getConfig } from '@edx/frontend-platform'; -import { useIntl } from '@edx/frontend-platform/i18n'; -import { AppContext } from '@edx/frontend-platform/react'; -import { Button, Badge } from '@openedx/paragon'; - -import urls from 'data/services/lms/urls'; -import { reduxHooks } from 'hooks'; - -import { findCoursesNavDropdownClicked } from '../hooks'; -import messages from '../messages'; - -export const CollapseMenuBody = ({ isOpen }) => { - const { formatMessage } = useIntl(); - const { authenticatedUser } = React.useContext(AppContext); - - const dashboard = reduxHooks.useEnterpriseDashboardData(); - const { courseSearchUrl } = reduxHooks.usePlatformSettingsData(); - - const exploreCoursesClick = findCoursesNavDropdownClicked( - urls.baseAppUrl(courseSearchUrl), - ); - - if (!isOpen) { - return null; - } - - return ( -
- - - - - {authenticatedUser && ( - <> - {!!dashboard && ( - - )} - {!dashboard && getConfig().CAREER_LINK_URL && ( - - )} - - - {getConfig().ORDER_HISTORY_URL && ( - - )} - - - )} -
- ); -}; - -CollapseMenuBody.propTypes = { - isOpen: PropTypes.bool.isRequired, -}; - -export default CollapseMenuBody; diff --git a/src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.test.jsx b/src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.test.jsx deleted file mode 100644 index 2af8ae7e6..000000000 --- a/src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.test.jsx +++ /dev/null @@ -1,48 +0,0 @@ -import { shallow } from '@edx/react-unit-test-utils'; -import { AppContext } from '@edx/frontend-platform/react'; - -import CollapseMenuBody from './CollapseMenuBody'; - -jest.mock('@edx/frontend-platform/react', () => ({ - AppContext: { - authenticatedUser: { - username: 'username', - }, - }, -})); - -jest.mock('hooks', () => ({ - reduxHooks: { - useEnterpriseDashboardData: () => ({ - url: 'url', - }), - usePlatformSettingsData: () => ({ - courseSearchUrl: '/courseSearchUrl', - }), - }, -})); - -jest.mock('../hooks', () => ({ - findCoursesNavDropdownClicked: (url) => jest.fn().mockName(`findCoursesNavDropdownClicked("${url}")`), -})); - -describe('CollapseMenuBody', () => { - test('render', () => { - const wrapper = shallow(); - expect(wrapper.snapshot).toMatchSnapshot(); - }); - - test('render empty if not open', () => { - const wrapper = shallow(); - expect(wrapper.snapshot).toMatchSnapshot(); - expect(wrapper.isEmptyRender()).toBe(true); - }); - - test('render unauthenticated', () => { - const { authenticatedUser } = AppContext; - AppContext.authenticatedUser = null; - const wrapper = shallow(); - expect(wrapper.snapshot).toMatchSnapshot(); - AppContext.authenticatedUser = authenticatedUser; - }); -}); diff --git a/src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/CollapseMenuBody.test.jsx.snap b/src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/CollapseMenuBody.test.jsx.snap deleted file mode 100644 index c8cc4de83..000000000 --- a/src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/CollapseMenuBody.test.jsx.snap +++ /dev/null @@ -1,105 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CollapseMenuBody render 1`] = ` -
- - - - - - - - - - -
-`; - -exports[`CollapseMenuBody render empty if not open 1`] = `null`; - -exports[`CollapseMenuBody render unauthenticated 1`] = ` -
- - - - -
-`; diff --git a/src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/index.test.jsx.snap b/src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/index.test.jsx.snap deleted file mode 100644 index 2a1dc7bc4..000000000 --- a/src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/index.test.jsx.snap +++ /dev/null @@ -1,48 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CollapsedHeader render nothing if not collapsed 1`] = `false`; - -exports[`CollapsedHeader renders 1`] = ` - -
- - -
- -
-`; - -exports[`CollapsedHeader renders with isOpen true 1`] = ` - -
- - -
- -
-`; diff --git a/src/containers/LearnerDashboardHeader/CollapsedHeader/index.jsx b/src/containers/LearnerDashboardHeader/CollapsedHeader/index.jsx deleted file mode 100644 index 5cf9762bc..000000000 --- a/src/containers/LearnerDashboardHeader/CollapsedHeader/index.jsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from 'react'; - -import { useIntl } from '@edx/frontend-platform/i18n'; -import { MenuIcon, Close } from '@openedx/paragon/icons'; -import { IconButton, Icon } from '@openedx/paragon'; - -import { useLearnerDashboardHeaderData, useIsCollapsed } from '../hooks'; - -import CollapseMenuBody from './CollapseMenuBody'; -import BrandLogo from '../BrandLogo'; - -import messages from '../messages'; - -export const CollapsedHeader = () => { - const { formatMessage } = useIntl(); - const isCollapsed = useIsCollapsed(); - const { isOpen, toggleIsOpen } = useLearnerDashboardHeaderData(); - - return ( - isCollapsed && ( - <> -
- - -
- - - ) - ); -}; - -CollapsedHeader.propTypes = {}; - -export default CollapsedHeader; diff --git a/src/containers/LearnerDashboardHeader/CollapsedHeader/index.test.jsx b/src/containers/LearnerDashboardHeader/CollapsedHeader/index.test.jsx deleted file mode 100644 index c21e98ccd..000000000 --- a/src/containers/LearnerDashboardHeader/CollapsedHeader/index.test.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import { shallow } from '@edx/react-unit-test-utils'; - -import CollapsedHeader from '.'; - -import { useLearnerDashboardHeaderData, useIsCollapsed } from '../hooks'; - -jest.mock('../BrandLogo', () => jest.fn(() => 'BrandLogo')); -jest.mock('./CollapseMenuBody', () => jest.fn(() => 'CollapseMenuBody')); - -jest.mock('../hooks', () => ({ - useIsCollapsed: jest.fn(() => true), - useLearnerDashboardHeaderData: jest.fn(() => ({ - isOpen: false, - toggleIsOpen: jest.fn().mockName('toggleIsOpen'), - })), -})); - -describe('CollapsedHeader', () => { - it('renders', () => { - const wrapper = shallow(); - expect(wrapper.snapshot).toMatchSnapshot(); - }); - - it('render nothing if not collapsed', () => { - useIsCollapsed.mockReturnValueOnce(false); - const wrapper = shallow(); - expect(wrapper.snapshot).toMatchSnapshot(); - }); - - it('renders with isOpen true', () => { - useLearnerDashboardHeaderData.mockReturnValueOnce({ - isOpen: true, - toggleIsOpen: jest.fn().mockName('toggleIsOpen'), - }); - const wrapper = shallow(); - expect(wrapper.snapshot).toMatchSnapshot(); - }); -}); diff --git a/src/containers/LearnerDashboardHeader/ExpandedHeader/AuthenticatedUserDropdown.jsx b/src/containers/LearnerDashboardHeader/ExpandedHeader/AuthenticatedUserDropdown.jsx deleted file mode 100644 index e0751bb38..000000000 --- a/src/containers/LearnerDashboardHeader/ExpandedHeader/AuthenticatedUserDropdown.jsx +++ /dev/null @@ -1,78 +0,0 @@ -import React from 'react'; - -import { getConfig } from '@edx/frontend-platform'; -import { useIntl } from '@edx/frontend-platform/i18n'; -import { AppContext } from '@edx/frontend-platform/react'; -import { AvatarButton, Dropdown, Badge } from '@openedx/paragon'; - -import { reduxHooks } from 'hooks'; - -import messages from '../messages'; - -export const AuthenticatedUserDropdown = () => { - const { formatMessage } = useIntl(); - const { authenticatedUser } = React.useContext(AppContext); - const dashboard = reduxHooks.useEnterpriseDashboardData(); - - return ( - authenticatedUser && ( - - - - {authenticatedUser.username} - - - - { getConfig().ENABLE_EDX_PERSONAL_DASHBOARD && ( - <> - {formatMessage(messages.dashboardSwitch)} - - {formatMessage(messages.dashboardPersonal)} - - {!!dashboard && ( - - {dashboard.label} {formatMessage(messages.dashboard)} - - )} - - - )} - - {!dashboard && getConfig().CAREER_LINK_URL && ( - - {formatMessage(messages.career)} - - {formatMessage(messages.newAlert)} - - - )} - - {formatMessage(messages.profile)} - - - {formatMessage(messages.account)} - - {getConfig().ORDER_HISTORY_URL && ( - - {formatMessage(messages.orderHistory)} - - )} - - - {formatMessage(messages.signOut)} - - - - ) - ); -}; - -AuthenticatedUserDropdown.propTypes = {}; - -export default AuthenticatedUserDropdown; diff --git a/src/containers/LearnerDashboardHeader/ExpandedHeader/AuthenticatedUserDropdown.test.jsx b/src/containers/LearnerDashboardHeader/ExpandedHeader/AuthenticatedUserDropdown.test.jsx deleted file mode 100644 index e7452d355..000000000 --- a/src/containers/LearnerDashboardHeader/ExpandedHeader/AuthenticatedUserDropdown.test.jsx +++ /dev/null @@ -1,81 +0,0 @@ -import { shallow } from '@edx/react-unit-test-utils'; - -import { reduxHooks } from 'hooks'; -import { getConfig } from '@edx/frontend-platform'; -import { AppContext } from '@edx/frontend-platform/react'; -import { AuthenticatedUserDropdown } from './AuthenticatedUserDropdown'; -import { useIsCollapsed } from '../hooks'; - -jest.mock('@edx/frontend-platform', () => ({ - getConfig: jest.fn(), -})); - -jest.mock('@edx/frontend-platform/react', () => ({ - AppContext: { - authenticatedUser: { - profileImage: 'profileImage', - username: 'username', - }, - }, -})); -const COURSE_SEARCH_URL = 'test-course-search-url'; - -jest.mock('hooks', () => ({ - reduxHooks: { - useEnterpriseDashboardData: jest.fn(), - usePlatformSettingsData: jest.fn(() => ({ - courseSearchUrl: COURSE_SEARCH_URL, - })), - }, -})); -jest.mock('../hooks', () => ({ - useIsCollapsed: jest.fn(), - findCoursesNavDropdownClicked: (href) => jest.fn().mockName(`findCoursesNavDropdownClicked('${href}')`), -})); - -jest.mock('data/services/lms/urls', () => ({ - baseAppUrl: (url) => (url), - programsUrl: 'http://localhost:18000/dashboard/programs', -})); - -const config = { - ACCOUNT_PROFILE_URL: 'http://account-profile-url.test', - ACCOUNT_SETTINGS_URL: 'http://account-settings-url.test', - LOGOUT_URL: 'http://logout-url.test', - ORDER_HISTORY_URL: 'http://order-history-url.test', - SUPPORT_URL: 'http://localhost:18000/support', - CAREER_LINK_URL: 'http://localhost:18000/career', - LMS_BASE_URL: 'http:/localhost:18000', - ENABLE_EDX_PERSONAL_DASHBOARD: true, -}; -getConfig.mockReturnValue(config); - -describe('AuthenticatedUserDropdown', () => { - const defaultDashboardData = { - label: 'label', - url: 'url', - }; - - describe('snapshots', () => { - test('no auth render empty', () => { - const { authenticatedUser } = AppContext; - AppContext.authenticatedUser = null; - const wrapper = shallow(); - expect(wrapper.snapshot).toMatchSnapshot(); - expect(wrapper.isEmptyRender()).toBe(true); - AppContext.authenticatedUser = authenticatedUser; - }); - test('with enterprise dashboard', () => { - reduxHooks.useEnterpriseDashboardData.mockReturnValueOnce(defaultDashboardData); - useIsCollapsed.mockReturnValueOnce(true); - const wrapper = shallow(); - expect(wrapper.snapshot).toMatchSnapshot(); - }); - test('without enterprise dashboard and expanded', () => { - reduxHooks.useEnterpriseDashboardData.mockReturnValueOnce(null); - useIsCollapsed.mockReturnValueOnce(false); - const wrapper = shallow(); - expect(wrapper.snapshot).toMatchSnapshot(); - }); - }); -}); diff --git a/src/containers/LearnerDashboardHeader/ExpandedHeader/__snapshots__/AuthenticatedUserDropdown.test.jsx.snap b/src/containers/LearnerDashboardHeader/ExpandedHeader/__snapshots__/AuthenticatedUserDropdown.test.jsx.snap deleted file mode 100644 index eafdef3ce..000000000 --- a/src/containers/LearnerDashboardHeader/ExpandedHeader/__snapshots__/AuthenticatedUserDropdown.test.jsx.snap +++ /dev/null @@ -1,139 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AuthenticatedUserDropdown snapshots no auth render empty 1`] = `null`; - -exports[`AuthenticatedUserDropdown snapshots with enterprise dashboard 1`] = ` - - - - username - - - - - - SWITCH DASHBOARD - - - Personal - - - label - - Dashboard - - - - - Profile - - - Account - - - Order History - - - - Sign Out - - - -`; - -exports[`AuthenticatedUserDropdown snapshots without enterprise dashboard and expanded 1`] = ` - - - - username - - - - - - SWITCH DASHBOARD - - - Personal - - - - - Career - - New - - - - Profile - - - Account - - - Order History - - - - Sign Out - - - -`; diff --git a/src/containers/LearnerDashboardHeader/ExpandedHeader/__snapshots__/index.test.jsx.snap b/src/containers/LearnerDashboardHeader/ExpandedHeader/__snapshots__/index.test.jsx.snap deleted file mode 100644 index 44e08f166..000000000 --- a/src/containers/LearnerDashboardHeader/ExpandedHeader/__snapshots__/index.test.jsx.snap +++ /dev/null @@ -1,52 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ExpandedHeader render 1`] = ` -
-
- - - - - - -
- -
-`; - -exports[`ExpandedHeader render empty if collapsed 1`] = `null`; diff --git a/src/containers/LearnerDashboardHeader/ExpandedHeader/index.jsx b/src/containers/LearnerDashboardHeader/ExpandedHeader/index.jsx deleted file mode 100644 index f257cbc57..000000000 --- a/src/containers/LearnerDashboardHeader/ExpandedHeader/index.jsx +++ /dev/null @@ -1,76 +0,0 @@ -import React from 'react'; - -import { getConfig } from '@edx/frontend-platform'; -import { useIntl } from '@edx/frontend-platform/i18n'; -import { Button } from '@openedx/paragon'; - -import urls from 'data/services/lms/urls'; -import { reduxHooks } from 'hooks'; - -import AuthenticatedUserDropdown from './AuthenticatedUserDropdown'; -import { useIsCollapsed, findCoursesNavClicked } from '../hooks'; -import messages from '../messages'; -import BrandLogo from '../BrandLogo'; - -export const ExpandedHeader = () => { - const { formatMessage } = useIntl(); - const { courseSearchUrl } = reduxHooks.usePlatformSettingsData(); - const isCollapsed = useIsCollapsed(); - - const exploreCoursesClick = findCoursesNavClicked( - urls.baseAppUrl(courseSearchUrl), - ); - - if (isCollapsed) { - return null; - } - - return ( -
-
- - - - - - - -
- - -
- ); -}; - -ExpandedHeader.propTypes = {}; - -export default ExpandedHeader; diff --git a/src/containers/LearnerDashboardHeader/ExpandedHeader/index.test.jsx b/src/containers/LearnerDashboardHeader/ExpandedHeader/index.test.jsx deleted file mode 100644 index 3b96a1dbf..000000000 --- a/src/containers/LearnerDashboardHeader/ExpandedHeader/index.test.jsx +++ /dev/null @@ -1,41 +0,0 @@ -import { shallow } from '@edx/react-unit-test-utils'; - -import ExpandedHeader from '.'; - -import { useIsCollapsed } from '../hooks'; - -jest.mock('data/services/lms/urls', () => ({ - programsUrl: () => 'programsUrl', - baseAppUrl: url => (`http://localhost:18000${url}`), -})); - -jest.mock('hooks', () => ({ - reduxHooks: { - usePlatformSettingsData: () => ({ - courseSearchUrl: '/courseSearchUrl', - }), - }, -})); - -jest.mock('../hooks', () => ({ - useIsCollapsed: jest.fn(), - findCoursesNavClicked: (url) => jest.fn().mockName(`findCoursesNavClicked("${url}")`), -})); - -jest.mock('./AuthenticatedUserDropdown', () => 'AuthenticatedUserDropdown'); -jest.mock('../BrandLogo', () => 'BrandLogo'); - -describe('ExpandedHeader', () => { - test('render', () => { - useIsCollapsed.mockReturnValueOnce(false); - const wrapper = shallow(); - expect(wrapper.snapshot).toMatchSnapshot(); - }); - - test('render empty if collapsed', () => { - useIsCollapsed.mockReturnValueOnce(true); - const wrapper = shallow(); - expect(wrapper.snapshot).toMatchSnapshot(); - expect(wrapper.isEmptyRender()).toBe(true); - }); -}); diff --git a/src/containers/LearnerDashboardHeader/LearnerDashboardMenu.jsx b/src/containers/LearnerDashboardHeader/LearnerDashboardMenu.jsx new file mode 100644 index 000000000..9dcecc3a1 --- /dev/null +++ b/src/containers/LearnerDashboardHeader/LearnerDashboardMenu.jsx @@ -0,0 +1,75 @@ +import { getConfig } from '@edx/frontend-platform'; + +import urls from 'data/services/lms/urls'; + +import messages from './messages'; + +const getLearnerHeaderMenu = ( + formatMessage, + courseSearchUrl, + authenticatedUser, + exploreCoursesClick, +) => ({ + mainMenu: [ + { + type: 'item', + href: '/', + content: formatMessage(messages.course), + isActive: true, + }, + { + type: 'item', + href: `${urls.programsUrl()}`, + content: formatMessage(messages.program), + }, + { + type: 'item', + href: `${urls.baseAppUrl(courseSearchUrl)}`, + content: formatMessage(messages.discoverNew), + onClick: (e) => { + exploreCoursesClick(e); + }, + }, + ], + secondaryMenu: [ + { + type: 'item', + href: `${getConfig().SUPPORT_URL}`, + content: formatMessage(messages.help), + }, + ], + userMenu: [ + { + heading: '', + items: [ + { + type: 'item', + href: `${getConfig().ACCOUNT_PROFILE_URL}/u/${authenticatedUser?.username}`, + content: formatMessage(messages.profile), + }, + { + type: 'item', + href: `${getConfig().ACCOUNT_SETTINGS_URL}`, + content: formatMessage(messages.account), + }, + ...(getConfig().ORDER_HISTORY_URL ? [{ + type: 'item', + href: getConfig().ORDER_HISTORY_URL, + content: formatMessage(messages.orderHistory), + }] : []), + ], + }, + { + heading: '', + items: [ + { + type: 'item', + href: `${getConfig().LOGOUT_URL}`, + content: formatMessage(messages.signOut), + }, + ], + }, + ], +}); + +export default getLearnerHeaderMenu; diff --git a/src/containers/LearnerDashboardHeader/__snapshots__/index.test.jsx.snap b/src/containers/LearnerDashboardHeader/__snapshots__/index.test.jsx.snap index 87ec64c7d..a1f0a9e71 100644 --- a/src/containers/LearnerDashboardHeader/__snapshots__/index.test.jsx.snap +++ b/src/containers/LearnerDashboardHeader/__snapshots__/index.test.jsx.snap @@ -3,8 +3,72 @@ exports[`LearnerDashboardHeader render 1`] = ` - - +
`; diff --git a/src/containers/LearnerDashboardHeader/hooks.js b/src/containers/LearnerDashboardHeader/hooks.js index 7eee8437d..115322c1d 100644 --- a/src/containers/LearnerDashboardHeader/hooks.js +++ b/src/containers/LearnerDashboardHeader/hooks.js @@ -1,9 +1,12 @@ import React from 'react'; import { useWindowSize, breakpoints } from '@openedx/paragon'; +import { useIntl } from '@edx/frontend-platform/i18n'; import track from 'tracking'; import { StrictDict } from 'utils'; import { linkNames } from 'tracking/constants'; +import getLearnerHeaderMenu from './LearnerDashboardMenu'; + import * as module from './hooks'; export const state = StrictDict({ @@ -24,6 +27,13 @@ export const findCoursesNavDropdownClicked = (href) => track.findCourses.findCou linkName: linkNames.learnerHomeNavDropdownExplore, }); +export const useLearnerDashboardHeaderMenu = ({ + courseSearchUrl, authenticatedUser, exploreCoursesClick, +}) => { + const { formatMessage } = useIntl(); + return getLearnerHeaderMenu(formatMessage, courseSearchUrl, authenticatedUser, exploreCoursesClick); +}; + export const useLearnerDashboardHeaderData = () => { const [isOpen, setIsOpen] = module.state.isOpen(false); const toggleIsOpen = () => setIsOpen(!isOpen); @@ -39,4 +49,5 @@ export default { findCoursesNavClicked, findCoursesNavDropdownClicked, useLearnerDashboardHeaderData, + useLearnerDashboardHeaderMenu, }; diff --git a/src/containers/LearnerDashboardHeader/hooks.test.js b/src/containers/LearnerDashboardHeader/hooks.test.js index 72349f6e2..c9bac080a 100644 --- a/src/containers/LearnerDashboardHeader/hooks.test.js +++ b/src/containers/LearnerDashboardHeader/hooks.test.js @@ -13,6 +13,7 @@ const { findCoursesNavClicked, findCoursesNavDropdownClicked, useLearnerDashboardHeaderData, + useLearnerDashboardHeaderMenu, } = hooks; jest.mock('tracking', () => ({ @@ -48,6 +49,17 @@ describe('LearnerDashboardHeader hooks', () => { }); }); + describe('getLearnerDashboardHeaderMenu', () => { + test('calls header menu data hook', () => { + const courseSearchUrl = '/courses'; + const authenticatedUser = { + username: 'test', + }; + const learnerHomeHeaderMenu = useLearnerDashboardHeaderMenu({ courseSearchUrl, authenticatedUser }); + expect(learnerHomeHeaderMenu.mainMenu.length).toBe(3); + }); + }); + describe('findCoursesNavDropdownClicked', () => { test('calls tracking with dropdown link name', () => { findCoursesNavDropdownClicked(url); diff --git a/src/containers/LearnerDashboardHeader/index.jsx b/src/containers/LearnerDashboardHeader/index.jsx index dfa8dbfb0..2cd167658 100644 --- a/src/containers/LearnerDashboardHeader/index.jsx +++ b/src/containers/LearnerDashboardHeader/index.jsx @@ -1,21 +1,43 @@ import React from 'react'; import MasqueradeBar from 'containers/MasqueradeBar'; +import { AppContext } from '@edx/frontend-platform/react'; +import Header from '@edx/frontend-component-header'; +import { reduxHooks } from 'hooks'; +import urls from 'data/services/lms/urls'; + import ConfirmEmailBanner from './ConfirmEmailBanner'; -import CollapsedHeader from './CollapsedHeader'; -import ExpandedHeader from './ExpandedHeader'; +import { useLearnerDashboardHeaderMenu, findCoursesNavClicked } from './hooks'; import './index.scss'; -export const LearnerDashboardHeader = () => ( - <> - - - - - -); +export const LearnerDashboardHeader = () => { + const { authenticatedUser } = React.useContext(AppContext); + const { courseSearchUrl } = reduxHooks.usePlatformSettingsData(); + + const exploreCoursesClick = () => { + findCoursesNavClicked(urls.baseAppUrl(courseSearchUrl)); + }; + + const learnerHomeHeaderMenu = useLearnerDashboardHeaderMenu({ + courseSearchUrl, + authenticatedUser, + exploreCoursesClick, + }); + + return ( + <> + +
+ + + ); +}; LearnerDashboardHeader.propTypes = {}; diff --git a/src/containers/LearnerDashboardHeader/index.test.jsx b/src/containers/LearnerDashboardHeader/index.test.jsx index a7335565e..e07fbda42 100644 --- a/src/containers/LearnerDashboardHeader/index.test.jsx +++ b/src/containers/LearnerDashboardHeader/index.test.jsx @@ -1,18 +1,35 @@ +import { mergeConfig } from '@edx/frontend-platform'; import { shallow } from '@edx/react-unit-test-utils'; +import Header from '@edx/frontend-component-header'; + +import urls from 'data/services/lms/urls'; import LearnerDashboardHeader from '.'; +import { findCoursesNavClicked } from './hooks'; +jest.mock('hooks', () => ({ + reduxHooks: { + usePlatformSettingsData: jest.fn(() => ({ + courseSearchUrl: '/course-search-url', + })), + }, +})); +jest.mock('./hooks', () => ({ + ...jest.requireActual('./hooks'), + findCoursesNavClicked: jest.fn(), +})); jest.mock('containers/MasqueradeBar', () => 'MasqueradeBar'); -jest.mock('./CollapsedHeader', () => 'CollapsedHeader'); jest.mock('./ConfirmEmailBanner', () => 'ConfirmEmailBanner'); -jest.mock('./ExpandedHeader', () => 'ExpandedHeader'); +jest.mock('@edx/frontend-component-header', () => 'Header'); describe('LearnerDashboardHeader', () => { test('render', () => { + mergeConfig({ ORDER_HISTORY_URL: 'test-url' }); const wrapper = shallow(); expect(wrapper.snapshot).toMatchSnapshot(); expect(wrapper.instance.findByType('ConfirmEmailBanner')).toHaveLength(1); expect(wrapper.instance.findByType('MasqueradeBar')).toHaveLength(1); - expect(wrapper.instance.findByType('CollapsedHeader')).toHaveLength(1); - expect(wrapper.instance.findByType('ExpandedHeader')).toHaveLength(1); + expect(wrapper.instance.findByType(Header)).toHaveLength(1); + wrapper.instance.findByType(Header)[0].props.mainMenuItems[2].onClick(); + expect(findCoursesNavClicked).toHaveBeenCalledWith(urls.baseAppUrl('/course-search-url')); }); });