From 90a225a94b4f72f2848cc0ac85e8c8a8e9306946 Mon Sep 17 00:00:00 2001 From: Asad Iqbal Date: Fri, 29 Oct 2021 04:05:47 -0700 Subject: [PATCH] feat: Removed course header stuff --- package-lock.json | 15 +++ package.json | 1 + src/course-header/AnonymousUserMenu.jsx | 34 ------ .../AuthenticatedUserDropdown.jsx | 76 ------------- src/course-header/Header.jsx | 100 ------------------ src/course-header/Header.test.jsx | 29 ----- src/course-header/messages.js | 46 -------- .../goal-unsubscribe/GoalUnsubscribe.jsx | 2 +- .../CourseTabsNavigation.jsx | 0 .../CourseTabsNavigation.test.jsx | 0 src/{course-header => course-tabs}/index.js | 2 +- src/course-tabs/messages.js | 11 ++ src/courseware/CoursewareContainer.test.jsx | 2 +- src/generic/messages.js | 10 -- src/index.scss | 23 ---- src/tab-page/LoadedTabPage.jsx | 2 +- src/tab-page/LoadedTabPage.test.jsx | 2 +- src/tab-page/TabPage.jsx | 4 +- 18 files changed, 34 insertions(+), 325 deletions(-) delete mode 100644 src/course-header/AnonymousUserMenu.jsx delete mode 100644 src/course-header/AuthenticatedUserDropdown.jsx delete mode 100644 src/course-header/Header.jsx delete mode 100644 src/course-header/Header.test.jsx delete mode 100644 src/course-header/messages.js rename src/{course-header => course-tabs}/CourseTabsNavigation.jsx (100%) rename src/{course-header => course-tabs}/CourseTabsNavigation.test.jsx (100%) rename src/{course-header => course-tabs}/index.js (59%) create mode 100644 src/course-tabs/messages.js diff --git a/package-lock.json b/package-lock.json index 6f2bd3cc88..27f2317783 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3964,6 +3964,21 @@ } } }, + "@edx/frontend-component-header": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@edx/frontend-component-header/-/frontend-component-header-2.4.2.tgz", + "integrity": "sha512-xE1rnZ3eM1gEi/69pb1aGTAb+pcQa32c50EyBGrmmaaVemqby94g3MvMvTYO7jjJ5+coBSa9KEHBZ2XRadRknA==", + "requires": { + "@fortawesome/fontawesome-svg-core": "1.2.36", + "@fortawesome/free-brands-svg-icons": "5.15.4", + "@fortawesome/free-regular-svg-icons": "5.15.4", + "@fortawesome/free-solid-svg-icons": "5.15.4", + "@fortawesome/react-fontawesome": "^0.1.14", + "babel-polyfill": "6.26.0", + "react-responsive": "8.2.0", + "react-transition-group": "4.4.2" + } + }, "@edx/frontend-enterprise-utils": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@edx/frontend-enterprise-utils/-/frontend-enterprise-utils-1.1.1.tgz", diff --git a/package.json b/package.json index e744d798f0..b73ceae2de 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "@edx/frontend-lib-special-exams": "1.14.1", "@edx/frontend-platform": "1.14.3", "@edx/paragon": "16.19.0", + "@edx/frontend-component-header": "^2.4.2", "@fortawesome/fontawesome-svg-core": "1.2.36", "@fortawesome/free-brands-svg-icons": "5.15.4", "@fortawesome/free-regular-svg-icons": "5.15.4", diff --git a/src/course-header/AnonymousUserMenu.jsx b/src/course-header/AnonymousUserMenu.jsx deleted file mode 100644 index 75396086c2..0000000000 --- a/src/course-header/AnonymousUserMenu.jsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; - -import { getConfig } from '@edx/frontend-platform'; -import { getLoginRedirectUrl } from '@edx/frontend-platform/auth'; -import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; -import { Button } from '@edx/paragon'; - -import genericMessages from '../generic/messages'; - -function AnonymousUserMenu({ intl }) { - return ( -
- - -
- ); -} - -AnonymousUserMenu.propTypes = { - intl: intlShape.isRequired, -}; - -export default injectIntl(AnonymousUserMenu); diff --git a/src/course-header/AuthenticatedUserDropdown.jsx b/src/course-header/AuthenticatedUserDropdown.jsx deleted file mode 100644 index f5257b24d1..0000000000 --- a/src/course-header/AuthenticatedUserDropdown.jsx +++ /dev/null @@ -1,76 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faUserCircle } from '@fortawesome/free-solid-svg-icons'; - -import { getConfig } from '@edx/frontend-platform'; -import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; -import { Dropdown } from '@edx/paragon'; - -import messages from './messages'; - -function AuthenticatedUserDropdown({ enterpriseLearnerPortalLink, intl, username }) { - let dashboardMenuItem = ( - - {intl.formatMessage(messages.dashboard)} - - ); - if (enterpriseLearnerPortalLink && Object.keys(enterpriseLearnerPortalLink).length > 0) { - dashboardMenuItem = ( - - {enterpriseLearnerPortalLink.content} - - ); - } - return ( - <> - {intl.formatMessage(messages.help)} - - - - - {username} - - - - {dashboardMenuItem} - - {intl.formatMessage(messages.profile)} - - - {intl.formatMessage(messages.account)} - - {!enterpriseLearnerPortalLink && ( - // Users should only see Order History if they do not have an available - // learner portal, because an available learner portal currently means - // that they access content via Subscriptions, in which context an "order" - // is not relevant. - - {intl.formatMessage(messages.orderHistory)} - - )} - - {intl.formatMessage(messages.signOut)} - - - - - ); -} - -AuthenticatedUserDropdown.propTypes = { - intl: intlShape.isRequired, - username: PropTypes.string.isRequired, - enterpriseLearnerPortalLink: PropTypes.shape({ - type: PropTypes.string, - href: PropTypes.string, - content: PropTypes.string, - }), -}; - -AuthenticatedUserDropdown.defaultProps = { - enterpriseLearnerPortalLink: undefined, -}; - -export default injectIntl(AuthenticatedUserDropdown); diff --git a/src/course-header/Header.jsx b/src/course-header/Header.jsx deleted file mode 100644 index ab952fa7e3..0000000000 --- a/src/course-header/Header.jsx +++ /dev/null @@ -1,100 +0,0 @@ -import React, { useContext } from 'react'; -import PropTypes from 'prop-types'; -import { useEnterpriseConfig } from '@edx/frontend-enterprise-utils'; -import { getConfig } from '@edx/frontend-platform'; -import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; -import { AppContext } from '@edx/frontend-platform/react'; - -import AnonymousUserMenu from './AnonymousUserMenu'; -import AuthenticatedUserDropdown from './AuthenticatedUserDropdown'; - -import messages from './messages'; - -function LinkedLogo({ - href, - src, - alt, - ...attributes -}) { - return ( - - {alt} - - ); -} - -LinkedLogo.propTypes = { - href: PropTypes.string.isRequired, - src: PropTypes.string.isRequired, - alt: PropTypes.string.isRequired, -}; - -function Header({ - courseOrg, courseNumber, courseTitle, intl, showUserDropdown, -}) { - const { authenticatedUser } = useContext(AppContext); - - const { enterpriseLearnerPortalLink, enterpriseCustomerBrandingConfig } = useEnterpriseConfig( - authenticatedUser, - getConfig().ENTERPRISE_LEARNER_PORTAL_HOSTNAME, - getConfig().LMS_BASE_URL, - ); - - let headerLogo = ( - - ); - if (enterpriseCustomerBrandingConfig && Object.keys(enterpriseCustomerBrandingConfig).length > 0) { - headerLogo = ( - - ); - } - - return ( -
- {intl.formatMessage(messages.skipNavLink)} -
- {headerLogo} -
- {courseOrg} {courseNumber} - {courseTitle} -
- {showUserDropdown && authenticatedUser && ( - - )} - {showUserDropdown && !authenticatedUser && ( - - )} -
-
- ); -} - -Header.propTypes = { - courseOrg: PropTypes.string, - courseNumber: PropTypes.string, - courseTitle: PropTypes.string, - intl: intlShape.isRequired, - showUserDropdown: PropTypes.bool, -}; - -Header.defaultProps = { - courseOrg: null, - courseNumber: null, - courseTitle: null, - showUserDropdown: true, -}; - -export default injectIntl(Header); diff --git a/src/course-header/Header.test.jsx b/src/course-header/Header.test.jsx deleted file mode 100644 index 2889aa7abf..0000000000 --- a/src/course-header/Header.test.jsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react'; -import { - authenticatedUser, initializeMockApp, render, screen, -} from '../setupTest'; -import { Header } from './index'; - -describe('Header', () => { - beforeAll(async () => { - // We need to mock AuthService to implicitly use `getAuthenticatedUser` within `AppContext.Provider`. - await initializeMockApp(); - }); - - it('displays user button', () => { - render(
); - expect(screen.getByRole('button')).toHaveTextContent(authenticatedUser.username); - }); - - it('displays course data', () => { - const courseData = { - courseOrg: 'course-org', - courseNumber: 'course-number', - courseTitle: 'course-title', - }; - render(
); - - expect(screen.getByText(`${courseData.courseOrg} ${courseData.courseNumber}`)).toBeInTheDocument(); - expect(screen.getByText(courseData.courseTitle)).toBeInTheDocument(); - }); -}); diff --git a/src/course-header/messages.js b/src/course-header/messages.js deleted file mode 100644 index e35d61ac66..0000000000 --- a/src/course-header/messages.js +++ /dev/null @@ -1,46 +0,0 @@ -import { defineMessages } from '@edx/frontend-platform/i18n'; - -const messages = defineMessages({ - courseMaterial: { - id: 'learn.navigation.course.tabs.label', - defaultMessage: 'Course Material', - description: 'The accessible label for course tabs navigation', - }, - dashboard: { - id: 'header.menu.dashboard.label', - defaultMessage: 'Dashboard', - description: 'The text for the user menu Dashboard navigation link.', - }, - help: { - id: 'header.help.label', - defaultMessage: 'Help', - description: 'The text for the link to the Help Center', - }, - profile: { - id: 'header.menu.profile.label', - defaultMessage: 'Profile', - description: 'The text for the user menu Profile navigation link.', - }, - account: { - id: 'header.menu.account.label', - defaultMessage: 'Account', - description: 'The text for the user menu Account navigation link.', - }, - orderHistory: { - id: 'header.menu.orderHistory.label', - defaultMessage: 'Order History', - description: 'The text for the user menu Order History navigation link.', - }, - skipNavLink: { - id: 'header.navigation.skipNavLink', - defaultMessage: 'Skip to main content.', - description: 'A link used by screen readers to allow users to skip to the main content of the page.', - }, - signOut: { - id: 'header.menu.signOut.label', - defaultMessage: 'Sign Out', - description: 'The label for the user menu Sign Out action.', - }, -}); - -export default messages; diff --git a/src/course-home/goal-unsubscribe/GoalUnsubscribe.jsx b/src/course-home/goal-unsubscribe/GoalUnsubscribe.jsx index 895e4100b8..24fdddee7e 100644 --- a/src/course-home/goal-unsubscribe/GoalUnsubscribe.jsx +++ b/src/course-home/goal-unsubscribe/GoalUnsubscribe.jsx @@ -3,7 +3,7 @@ import { useParams } from 'react-router-dom'; import { sendTrackEvent } from '@edx/frontend-platform/analytics'; import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; -import { Header } from '../../course-header'; +import { LearningHeader as Header } from '@edx/frontend-component-header'; import PageLoading from '../../generic/PageLoading'; import { unsubscribeFromCourseGoal } from '../data/api'; diff --git a/src/course-header/CourseTabsNavigation.jsx b/src/course-tabs/CourseTabsNavigation.jsx similarity index 100% rename from src/course-header/CourseTabsNavigation.jsx rename to src/course-tabs/CourseTabsNavigation.jsx diff --git a/src/course-header/CourseTabsNavigation.test.jsx b/src/course-tabs/CourseTabsNavigation.test.jsx similarity index 100% rename from src/course-header/CourseTabsNavigation.test.jsx rename to src/course-tabs/CourseTabsNavigation.test.jsx diff --git a/src/course-header/index.js b/src/course-tabs/index.js similarity index 59% rename from src/course-header/index.js rename to src/course-tabs/index.js index 8839c6ce07..e2236ee726 100644 --- a/src/course-header/index.js +++ b/src/course-tabs/index.js @@ -1,2 +1,2 @@ -export { default as Header } from './Header'; +/* eslint-disable import/prefer-default-export */ export { default as CourseTabsNavigation } from './CourseTabsNavigation'; diff --git a/src/course-tabs/messages.js b/src/course-tabs/messages.js new file mode 100644 index 0000000000..e1230ab500 --- /dev/null +++ b/src/course-tabs/messages.js @@ -0,0 +1,11 @@ +import { defineMessages } from '@edx/frontend-platform/i18n'; + +const messages = defineMessages({ + courseMaterial: { + id: 'learn.navigation.course.tabs.label', + defaultMessage: 'Course Material', + description: 'The accessible label for course tabs navigation', + }, +}); + +export default messages; diff --git a/src/courseware/CoursewareContainer.test.jsx b/src/courseware/CoursewareContainer.test.jsx index 304fcd1c6d..737e1812e6 100644 --- a/src/courseware/CoursewareContainer.test.jsx +++ b/src/courseware/CoursewareContainer.test.jsx @@ -159,7 +159,7 @@ describe('CoursewareContainer', () => { const courseId = defaultCourseId; function assertLoadedHeader(container) { - const courseHeader = container.querySelector('.course-header'); + const courseHeader = container.querySelector('.learning-header'); // Ensure the course number and org appear - this proves we loaded course metadata properly. expect(courseHeader).toHaveTextContent(courseMetadata.number); expect(courseHeader).toHaveTextContent(courseMetadata.org); diff --git a/src/generic/messages.js b/src/generic/messages.js index ad435a0515..fdf916a395 100644 --- a/src/generic/messages.js +++ b/src/generic/messages.js @@ -11,16 +11,6 @@ const messages = defineMessages({ defaultMessage: 'register', description: 'Text in a link, prompting the user to create an account. Used in "learning.logistration.alert"', }, - registerSentenceCase: { - id: 'general.register.sentenceCase', - defaultMessage: 'Register', - description: 'Text in a button, prompting the user to register.', - }, - signInLowercase: { - id: 'learning.logistration.login', // ID left for historical purposes - defaultMessage: 'sign in', - description: 'Text in a link, prompting the user to log in. Used in "learning.logistration.alert"', - }, signInSentenceCase: { id: 'general.signIn.sentenceCase', defaultMessage: 'Sign in', diff --git a/src/index.scss b/src/index.scss index f764088b8f..498631b90f 100755 --- a/src/index.scss +++ b/src/index.scss @@ -36,29 +36,6 @@ } } -.course-header { - min-width: 0; - - .course-title-lockup { - min-width: 0; - - span { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - padding-bottom: 0.1rem; - } - } - - .user-dropdown { - .btn { - height: 3rem; - @media (max-width: -1 + map-get($grid-breakpoints, "sm")) { - padding: 0 0.5rem; - } - } - } -} .course-tabs-navigation { border-bottom: solid 1px #eaeaea; diff --git a/src/tab-page/LoadedTabPage.jsx b/src/tab-page/LoadedTabPage.jsx index 9ba67ac621..12a00f95dd 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 { CourseTabsNavigation } from '../course-header'; +import { CourseTabsNavigation } from '../course-tabs'; import { useModel } from '../generic/model-store'; import { AlertList } from '../generic/user-messages'; import StreakModal from '../shared/streak-celebration'; diff --git a/src/tab-page/LoadedTabPage.test.jsx b/src/tab-page/LoadedTabPage.test.jsx index cccbbe7ac0..0c15e9f40c 100644 --- a/src/tab-page/LoadedTabPage.test.jsx +++ b/src/tab-page/LoadedTabPage.test.jsx @@ -3,7 +3,7 @@ import { Factory } from 'rosie'; import { initializeTestStore, render, screen } from '../setupTest'; import LoadedTabPage from './LoadedTabPage'; -jest.mock('../course-header/CourseTabsNavigation', () => () =>
); +jest.mock('../course-tabs/CourseTabsNavigation', () => () =>
); jest.mock('../instructor-toolbar/InstructorToolbar', () => () =>
); jest.mock('../shared/streak-celebration/StreakCelebrationModal', () => () =>
); jest.mock('../product-tours/ProductTours', () => () =>
); diff --git a/src/tab-page/TabPage.jsx b/src/tab-page/TabPage.jsx index dcd7db8b93..0b89ee4070 100644 --- a/src/tab-page/TabPage.jsx +++ b/src/tab-page/TabPage.jsx @@ -6,9 +6,9 @@ import { Redirect } from 'react-router'; import Footer from '@edx/frontend-component-footer'; import { Toast } from '@edx/paragon'; -import { Header } from '../course-header'; -import { getAccessDeniedRedirectUrl } from '../shared/access'; +import { LearningHeader as Header } from '@edx/frontend-component-header'; import PageLoading from '../generic/PageLoading'; +import { getAccessDeniedRedirectUrl } from '../shared/access'; import { useModel } from '../generic/model-store'; import genericMessages from '../generic/messages';