Compare commits

..

3 Commits

Author SHA1 Message Date
mashal-m
bba751ba88 build: update lock file 2023-11-29 18:13:10 +05:00
mashal-m
0e65c7b32c Merge branch 'master' of https://github.com/openedx/frontend-component-header into mashal-m/url-test 2023-11-29 17:15:29 +05:00
mashal-m
4c21d5874d refactor: add profile url in config 2023-11-29 17:08:23 +05:00
45 changed files with 8603 additions and 3828 deletions

View File

@@ -1,4 +1,4 @@
// eslint-disable-next-line import/no-extraneous-dependencies
const { createConfig } = require('@openedx/frontend-build');
const { createConfig } = require('@edx/frontend-build');
module.exports = createConfig('eslint');

View File

@@ -3,7 +3,6 @@ on:
push:
branches:
- master
- alpha
jobs:
release:
name: Release

1
.gitignore vendored
View File

@@ -9,4 +9,3 @@ module.config.js
.idea/
.vscode
src/i18n/messages

View File

@@ -1,8 +1,5 @@
{
"branches": [
"master",
{name: "alpha", prerelease: true}
],
"branch": "master",
"tagFormat": "v${version}",
"verifyConditions": [
"@semantic-release/npm",

9
.tx/config Normal file
View File

@@ -0,0 +1,9 @@
[main]
host = https://www.transifex.com
[o:open-edx:p:edx-platform:r:frontend-component-header]
file_filter = src/i18n/messages/<lang>.json
source_file = src/i18n/transifex_input.json
source_lang = en
type = KEYVALUEJSON

View File

@@ -1,3 +1,6 @@
export TRANSIFEX_RESOURCE = frontend-component-header
transifex_langs = "ar,fr,es_419,zh_CN,pt,it,de,uk,ru,hi,fr_CA"
transifex_utils = ./node_modules/.bin/transifex-utils.js
i18n = ./src/i18n
transifex_input = $(i18n)/transifex_input.json
@@ -32,6 +35,21 @@ detect_changed_source_translations:
# Checking for changed translations...
git diff --exit-code $(i18n)
# Pushes translations to Transifex. You must run make extract_translations first.
push_translations:
# Pushing strings to Transifex...
tx push -s
# Fetching hashes from Transifex...
./node_modules/@edx/reactifex/bash_scripts/get_hashed_strings_v3.sh
# Writing out comments to file...
$(transifex_utils) $(transifex_temp) --comments --v3-scripts-path
# Pushing comments to Transifex...
./node_modules/@edx/reactifex/bash_scripts/put_comments_v3.sh
# Pulls translations from Transifex.
pull_translations:
tx pull -t -f --mode reviewed --languages=$(transifex_langs)
# This target is used by Travis.
validate-no-uncommitted-package-lock-changes:
# Checking for package-lock.json changes...

View File

@@ -1,3 +1,3 @@
const { createConfig } = require('@openedx/frontend-build');
const { createConfig } = require('@edx/frontend-build');
module.exports = createConfig('babel-preserve-modules');

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

View File

@@ -1,111 +0,0 @@
.. title:: Custom Header Component Documentation
Custom Header Component
=======================
Overview
--------
The ``Header`` component is used to display a header with a provided ``mainMenuItems``,
``secondaryMenuItems``, and ``userMenuItems`` props. If props are provided, the component will use them; otherwise,
if any of the props ``(mainMenuItems, secondaryMenuItems, userMenuItems)`` are not provided, default
items will be displayed. This component provides flexibility in customization, making it suitable for a wide
range of applications.
Props Details
-------------
The `Header` component accepts the following **optional** props for customization:
``mainMenuItems``
*****************
The main menu items is a list of menu items objects. On desktop screens, these items are displayed on the left side next to the logo icon.
On mobile screens, the main menu is displayed as a dropdown menu triggered by a hamburger icon. The main menu dropdown appears below the logo when opened.
Example:
::
[
{ type: 'item', href: '/courses', content: 'Courses', isActive: true },
{ type: 'item', href: '/programs', content: 'Programs' },
{ type: 'item', href: '/discover', content: 'Discover New', disabled, true },
{
type: 'submenu',
content: 'Sub Menu Item',
submenuContent: (
<>
<div className="mb-1"><a rel="noopener" href="#">Submenu item 1</a></div>
<div className="mb-1"><a rel="noopener" href="#">Submenu item 2</a></div>
</>
),
},
]
**Submenu Implementation**
To implement a submenu, set the type to ``submenu`` and provide a ``submenuContent`` property.
The submenuContent should be a React component (as shown in above example) that can be rendered.
**Note:**
- The ``type`` should be ``item`` or ``submenu``. If type is ``submenu``, it should contain ``submenuContent`` instead of ``href``.
- If any item is to be disabled, we can pass optional ``disabled: true`` in that item object and
- If any item is to be active, we can pass optional ``isActive: true`` in that item object
secondaryMenuItems
******************
The secondary menu items has same structure as ``mainMenuItems``. On desktop screen, these items are displayed on the right of header just before the userMenu avatar and on mobile screen,
these items are displayed below the mainMenu items in dropdown.
Example:
::
[
{ type: 'item', href: '/help', content: 'Help' },
]
userMenuItems
*************
The user menu items is list of objects. On desktop screens, these items are displayed as a dropdown menu on the most right side of the header. The dropdown is opened by clicking on the avatar icon, which is typically located at the far right of the header.
On mobile screens, the user menu is also displayed as a dropdown menu, appearing under the avatar icon.
Each object represents a group in the user menu. Each object contains the ``heading`` and
list of menu items to be displayed in that group. Heading is optional and will be displayed only if passed. There can
be multiple groups. For a normal user menu, a single group can be passed with empty heading.
Example:
::
[
{
heading: '',
items: [
{ type: 'item', href: '/profile', content: 'Profile' },
{ type: 'item', href: '/logout', content: 'Logout' }
]
},
]
Screenshots
***********
Desktop:
.. image:: ./images/desktop_header.png
Mobile:
.. image:: ./images/mobile_main_menu.png
.. image:: ./images/mobile_user_menu.png
Some Important Notes
--------------------
- Intl formatted strings should be passed in content attribute.
- Only menu items in the main menu can be disabled.
- Menu items in the main menu and user menu can have ``isActive`` prop.

View File

@@ -1,6 +1,6 @@
@import "@edx/brand/paragon/fonts";
@import "@edx/brand/paragon/variables";
@import "@openedx/paragon/scss/core/core";
@import "@edx/paragon/scss/core/core";
@import "@edx/brand/paragon/overrides";
@import "@edx/frontend-component-header/index";

View File

@@ -1,4 +1,4 @@
const { createConfig } = require('@openedx/frontend-build');
const { createConfig } = require('@edx/frontend-build');
module.exports = createConfig('jest', {
setupFilesAfterEnv: [

11432
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -35,13 +35,14 @@
"devDependencies": {
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
"@edx/browserslist-config": "^1.1.1",
"@edx/frontend-platform": "8.0.3",
"@edx/frontend-build": "13.0.8",
"@edx/frontend-platform": "6.1.0",
"@edx/reactifex": "^2.1.1",
"@openedx/frontend-build": "14.0.3",
"@openedx/paragon": "22.3.1",
"@testing-library/dom": "10.0.0",
"@testing-library/dom": "9.3.3",
"@testing-library/jest-dom": "5.17.0",
"@testing-library/react": "10.4.9",
"@wojtekmaj/enzyme-adapter-react-17": "0.8.0",
"enzyme": "3.11.0",
"husky": "8.0.3",
"jest": "29.7.0",
"jest-chain": "1.1.6",
@@ -49,26 +50,25 @@
"react": "17.0.2",
"react-dom": "17.0.2",
"react-redux": "7.2.9",
"react-router-dom": "6.23.1",
"react-router-dom": "6.20.0",
"react-test-renderer": "17.0.2",
"redux": "4.2.1",
"redux-saga": "1.3.0"
"redux-saga": "1.2.3"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "6.5.2",
"@fortawesome/free-brands-svg-icons": "6.5.2",
"@fortawesome/free-regular-svg-icons": "6.5.2",
"@fortawesome/free-solid-svg-icons": "6.5.2",
"@edx/paragon": "21.5.6",
"@fortawesome/fontawesome-svg-core": "6.4.2",
"@fortawesome/free-brands-svg-icons": "6.4.2",
"@fortawesome/free-regular-svg-icons": "6.4.2",
"@fortawesome/free-solid-svg-icons": "6.4.2",
"@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",
"@edx/frontend-platform": "^4.0.0 || ^5.0.0 || ^6.0.0",
"prop-types": "^15.5.10",
"react": "^16.9.0 || ^17.0.0",
"react-dom": "^16.9.0 || ^17.0.0"

View File

@@ -19,39 +19,31 @@ class DesktopHeader extends React.Component {
super(props);
}
renderMenu(menu) {
renderMainMenu() {
const { mainMenu } = this.props;
// Nodes are accepted as a prop
if (!Array.isArray(menu)) {
return menu;
if (!Array.isArray(mainMenu)) {
return mainMenu;
}
return menu.map((menuItem) => {
return mainMenu.map((menuItem) => {
const {
type,
href,
content,
submenuContent,
disabled,
isActive,
onClick,
} = menuItem;
if (type === 'item') {
return (
<a
key={`${type}-${content}`}
className={`nav-link${disabled ? ' disabled' : ''}${isActive ? ' active' : ''}`}
href={href}
onClick={onClick || null}
>
{content}
</a>
<a key={`${type}-${content}`} className="nav-link" href={href}>{content}</a>
);
}
return (
<Menu key={`${type}-${content}`} tag="div" className="nav-item" respondToPointerEvents>
<MenuTrigger onClick={onClick || null} tag="a" className="nav-link d-inline-flex align-items-center" href={href}>
<MenuTrigger tag="a" className="nav-link d-inline-flex align-items-center" href={href}>
{content} <CaretIcon role="img" aria-hidden focusable="false" />
</MenuTrigger>
<MenuContent className="pin-left pin-right shadow py-2">
@@ -62,14 +54,22 @@ class DesktopHeader extends React.Component {
});
}
renderMainMenu() {
const { mainMenu } = this.props;
return this.renderMenu(mainMenu);
}
renderSecondaryMenu() {
const { secondaryMenu } = this.props;
return this.renderMenu(secondaryMenu);
// Renders an optional App Menu for
renderAppMenu() {
const { appMenu } = this.props;
const { content: appMenuContent, menuItems } = appMenu;
return (
<Menu transitionClassName="menu-dropdown" transitionTimeout={250}>
<MenuTrigger tag="a" className="nav-link d-inline-flex align-items-center">
{appMenuContent} <CaretIcon role="img" aria-hidden focusable="false" />
</MenuTrigger>
<MenuContent className="mb-0 dropdown-menu show dropdown-menu-right pin-right shadow py-2">
{menuItems.map(({ type, href, content }) => (
<a className={`dropdown-${type}`} key={`${type}-${content}`} href={href}>{content}</a>
))}
</MenuContent>
</Menu>
);
}
renderUserMenu() {
@@ -91,24 +91,8 @@ class DesktopHeader extends React.Component {
{username} <CaretIcon role="img" aria-hidden focusable="false" />
</MenuTrigger>
<MenuContent className="mb-0 dropdown-menu show dropdown-menu-right pin-right shadow py-2">
{userMenu.map((group, index) => (
// eslint-disable-next-line react/jsx-no-comment-textnodes,react/no-array-index-key
<React.Fragment key={index}>
{group.heading && <div className="dropdown-header" role="heading" aria-level="1">{group.heading}</div>}
{group.items.map(({
type, content, href, disabled, isActive, onClick,
}) => (
<a
className={`dropdown-${type}${isActive ? ' active' : ''}${disabled ? ' disabled' : ''}`}
key={`${type}-${content}`}
href={href}
onClick={onClick || null}
>
{content}
</a>
))}
{index < userMenu.length - 1 && <div className="dropdown-divider" role="separator" />}
</React.Fragment>
{userMenu.map(({ type, href, content }) => (
<a className={`dropdown-${type}`} key={`${type}-${content}`} href={href}>{content}</a>
))}
</MenuContent>
</Menu>
@@ -136,6 +120,7 @@ class DesktopHeader extends React.Component {
logoDestination,
loggedIn,
intl,
appMenu,
} = this.props;
const logoProps = { src: logo, alt: logoAltText, href: logoDestination };
const logoClasses = getConfig().AUTHN_MINIMAL_HEADER ? 'mw-100' : null;
@@ -152,17 +137,19 @@ class DesktopHeader extends React.Component {
>
{this.renderMainMenu()}
</nav>
{appMenu ? (
<nav
aria-label={intl.formatMessage(messages['header.label.app.nav'])}
className="nav app-nav"
>
{this.renderAppMenu()}
</nav>
) : null}
<nav
aria-label={intl.formatMessage(messages['header.label.secondary.nav'])}
className="nav secondary-menu-container align-items-center ml-auto"
>
{loggedIn
? (
<>
{this.renderSecondaryMenu()}
{this.renderUserMenu()}
</>
) : this.renderLoggedOutItems()}
{loggedIn ? this.renderUserMenu() : this.renderLoggedOutItems()}
</nav>
</div>
</div>
@@ -176,19 +163,10 @@ DesktopHeader.propTypes = {
PropTypes.node,
PropTypes.array,
]),
secondaryMenu: PropTypes.oneOfType([
PropTypes.node,
PropTypes.array,
]),
userMenu: PropTypes.arrayOf(PropTypes.shape({
heading: PropTypes.string,
items: PropTypes.arrayOf(PropTypes.shape({
type: PropTypes.oneOf(['item', 'menu']),
href: PropTypes.string,
content: PropTypes.string,
isActive: PropTypes.bool,
onClick: PropTypes.func,
})),
type: PropTypes.oneOf(['item', 'menu']),
href: PropTypes.string,
content: PropTypes.string,
})),
loggedOutItems: PropTypes.arrayOf(PropTypes.shape({
type: PropTypes.oneOf(['item', 'menu']),
@@ -204,11 +182,24 @@ DesktopHeader.propTypes = {
// i18n
intl: intlShape.isRequired,
// appMenu
appMenu: PropTypes.shape(
{
content: PropTypes.string,
menuItems: PropTypes.arrayOf(
PropTypes.shape({
type: PropTypes.string,
href: PropTypes.string,
content: PropTypes.string,
}),
),
},
),
};
DesktopHeader.defaultProps = {
mainMenu: [],
secondaryMenu: [],
userMenu: [],
loggedOutItems: [],
logo: null,
@@ -217,6 +208,7 @@ DesktopHeader.defaultProps = {
avatar: null,
username: null,
loggedIn: false,
appMenu: null,
};
export default injectIntl(DesktopHeader);

View File

@@ -10,7 +10,6 @@ import {
subscribe,
} from '@edx/frontend-platform';
import PropTypes from 'prop-types';
import DesktopHeader from './DesktopHeader';
import MobileHeader from './MobileHeader';
@@ -23,6 +22,7 @@ ensureConfig([
'SITE_NAME',
'LOGO_URL',
'ORDER_HISTORY_URL',
'ACCOUNT_PROFILE_URL',
], 'Header component');
subscribe(APP_CONFIG_INITIALIZED, () => {
@@ -31,68 +31,50 @@ subscribe(APP_CONFIG_INITIALIZED, () => {
}, 'Header additional config');
});
/**
* Header component for the application.
* Displays a header with the provided main menu, secondary menu, and user menu when the user is authenticated.
* If any of the props (mainMenuItems, secondaryMenuItems, userMenuItems) are not provided, default
* items are displayed.
* For more details on how to use this component, please refer to this document:
* https://github.com/openedx/frontend-component-header/blob/master/docs/using_custom_header.rst
*
* @param {list} mainMenuItems - The list of main menu items to display.
* See the documentation for the structure of main menu item.
* @param {list} secondaryMenuItems - The list of secondary menu items to display.
* See the documentation for the structure of secondary menu item.
* @param {list} userMenuItems - The list of user menu items to display.
* See the documentation for the structure of user menu item.
*/
const Header = ({
intl, mainMenuItems, secondaryMenuItems, userMenuItems,
}) => {
const Header = ({ intl }) => {
const { authenticatedUser, config } = useContext(AppContext);
const defaultMainMenu = [
const mainMenu = [
{
type: 'item',
href: `${config.LMS_BASE_URL}/dashboard`,
content: intl.formatMessage(messages['header.links.courses']),
},
];
const defaultUserMenu = authenticatedUser === null ? [] : [{
heading: '',
items: [
{
type: 'item',
href: `${config.LMS_BASE_URL}/dashboard`,
content: intl.formatMessage(messages['header.user.menu.dashboard']),
},
{
type: 'item',
href: `${config.ACCOUNT_PROFILE_URL}/u/${authenticatedUser.username}`,
content: intl.formatMessage(messages['header.user.menu.profile']),
},
{
type: 'item',
href: config.ACCOUNT_SETTINGS_URL,
content: intl.formatMessage(messages['header.user.menu.account.settings']),
},
// Users should only see Order History if have a ORDER_HISTORY_URL define in the environment.
...(config.ORDER_HISTORY_URL ? [{
type: 'item',
href: config.ORDER_HISTORY_URL,
content: intl.formatMessage(messages['header.user.menu.order.history']),
}] : []),
{
type: 'item',
href: config.LOGOUT_URL,
content: intl.formatMessage(messages['header.user.menu.logout']),
},
],
}];
const mainMenu = mainMenuItems || defaultMainMenu;
const secondaryMenu = secondaryMenuItems || [];
const userMenu = authenticatedUser === null ? [] : userMenuItems || defaultUserMenu;
const orderHistoryItem = {
type: 'item',
href: config.ORDER_HISTORY_URL,
content: intl.formatMessage(messages['header.user.menu.order.history']),
};
const userMenu = authenticatedUser === null ? [] : [
{
type: 'item',
href: `${config.LMS_BASE_URL}/dashboard`,
content: intl.formatMessage(messages['header.user.menu.dashboard']),
},
{
type: 'item',
href: `${config.ACCOUNT_PROFILE_URL}/u/${authenticatedUser.username}`,
content: intl.formatMessage(messages['header.user.menu.profile']),
},
{
type: 'item',
href: config.ACCOUNT_SETTINGS_URL,
content: intl.formatMessage(messages['header.user.menu.account.settings']),
},
{
type: 'item',
href: config.LOGOUT_URL,
content: intl.formatMessage(messages['header.user.menu.logout']),
},
];
// Users should only see Order History if have a ORDER_HISTORY_URL define in the environment.
if (config.ORDER_HISTORY_URL) {
userMenu.splice(-1, 0, orderHistoryItem);
}
const loggedOutItems = [
{
@@ -115,14 +97,13 @@ const Header = ({
username: authenticatedUser !== null ? authenticatedUser.username : null,
avatar: authenticatedUser !== null ? authenticatedUser.avatar : null,
mainMenu: getConfig().AUTHN_MINIMAL_HEADER ? [] : mainMenu,
secondaryMenu: getConfig().AUTHN_MINIMAL_HEADER ? [] : secondaryMenu,
userMenu: getConfig().AUTHN_MINIMAL_HEADER ? [] : userMenu,
loggedOutItems: getConfig().AUTHN_MINIMAL_HEADER ? [] : loggedOutItems,
};
return (
<>
<Responsive maxWidth={769}>
<Responsive maxWidth={768}>
<MobileHeader {...props} />
</Responsive>
<Responsive minWidth={769}>
@@ -132,31 +113,8 @@ const Header = ({
);
};
Header.defaultProps = {
mainMenuItems: null,
secondaryMenuItems: null,
userMenuItems: null,
};
Header.propTypes = {
intl: intlShape.isRequired,
mainMenuItems: PropTypes.oneOfType([
PropTypes.node,
PropTypes.array,
]),
secondaryMenuItems: PropTypes.oneOfType([
PropTypes.node,
PropTypes.array,
]),
userMenuItems: PropTypes.arrayOf(PropTypes.shape({
heading: PropTypes.string,
items: PropTypes.arrayOf(PropTypes.shape({
type: PropTypes.oneOf(['item', 'menu']),
href: PropTypes.string,
content: PropTypes.string,
isActive: PropTypes.bool,
})),
})),
};
export default injectIntl(Header);

View File

@@ -19,31 +19,25 @@ class MobileHeader extends React.Component {
super(props);
}
renderMenu(menu) {
renderMainMenu() {
const { mainMenu } = this.props;
// Nodes are accepted as a prop
if (!Array.isArray(menu)) {
return menu;
if (!Array.isArray(mainMenu)) {
return mainMenu;
}
return menu.map((menuItem) => {
return mainMenu.map((menuItem) => {
const {
type,
href,
content,
submenuContent,
disabled,
isActive,
onClick,
} = menuItem;
if (type === 'item') {
return (
<a
key={`${type}-${content}`}
className={`nav-link${disabled ? ' disabled' : ''}${isActive ? ' active' : ''}`}
href={href}
onClick={onClick || null}
>
<a key={`${type}-${content}`} className="nav-link" href={href}>
{content}
</a>
);
@@ -51,7 +45,7 @@ class MobileHeader extends React.Component {
return (
<Menu key={`${type}-${content}`} tag="div" className="nav-item">
<MenuTrigger onClick={onClick || null} tag="a" role="button" tabIndex="0" className="nav-link">
<MenuTrigger tag="a" role="button" tabIndex="0" className="nav-link">
{content}
</MenuTrigger>
<MenuContent className="position-static pin-left pin-right py-2">
@@ -62,33 +56,13 @@ class MobileHeader extends React.Component {
});
}
renderMainMenu() {
const { mainMenu } = this.props;
return this.renderMenu(mainMenu);
}
renderSecondaryMenu() {
const { secondaryMenu } = this.props;
return this.renderMenu(secondaryMenu);
}
renderUserMenuItems() {
const { userMenu } = this.props;
return userMenu.map((group) => (
group.items.map(({
type, content, href, disabled, isActive, onClick,
}) => (
<li className="nav-item" key={`${type}-${content}`}>
<a
className={`nav-link${isActive ? ' active' : ''}${disabled ? ' disabled' : ''}`}
href={href}
onClick={onClick || null}
>
{content}
</a>
</li>
))
return userMenu.map(({ type, href, content }) => (
<li className="nav-item" key={`${type}-${content}`}>
<a className="nav-link" href={href}>{content}</a>
</li>
));
}
@@ -149,7 +123,6 @@ class MobileHeader extends React.Component {
className="nav flex-column pin-left pin-right border-top shadow py-2"
>
{this.renderMainMenu()}
{this.renderSecondaryMenu()}
</MenuContent>
</Menu>
</div>
@@ -184,19 +157,11 @@ MobileHeader.propTypes = {
PropTypes.node,
PropTypes.array,
]),
secondaryMenu: PropTypes.oneOfType([
PropTypes.node,
PropTypes.array,
]),
userMenu: PropTypes.arrayOf(PropTypes.shape({
heading: PropTypes.string,
items: PropTypes.arrayOf(PropTypes.shape({
type: PropTypes.oneOf(['item', 'menu']),
href: PropTypes.string,
content: PropTypes.string,
isActive: PropTypes.bool,
onClick: PropTypes.func,
})),
type: PropTypes.oneOf(['item', 'menu']),
href: PropTypes.string,
content: PropTypes.string,
})),
loggedOutItems: PropTypes.arrayOf(PropTypes.shape({
type: PropTypes.oneOf(['item', 'menu']),
@@ -217,7 +182,6 @@ MobileHeader.propTypes = {
MobileHeader.defaultProps = {
mainMenu: [],
secondaryMenu: [],
userMenu: [],
loggedOutItems: [],
logo: null,

View File

@@ -33,7 +33,6 @@ exports[`<Header /> renders correctly for anonymous desktop 1`] = `
<a
className="nav-link"
href="http://localhost:18000/dashboard"
onClick={null}
>
Courses
</a>
@@ -94,7 +93,7 @@ exports[`<Header /> renders correctly for anonymous mobile 1`] = `
height="24px"
role="img"
style={
{
Object {
"height": "1.5rem",
"width": "1.5rem",
}
@@ -164,7 +163,7 @@ exports[`<Header /> renders correctly for anonymous mobile 1`] = `
<span
className="avatar overflow-hidden d-inline-flex rounded-circle null"
style={
{
Object {
"height": "1.5rem",
"width": "1.5rem",
}
@@ -176,7 +175,7 @@ exports[`<Header /> renders correctly for anonymous mobile 1`] = `
height="24px"
role="img"
style={
{
Object {
"height": "1.5rem",
"width": "1.5rem",
}
@@ -230,7 +229,6 @@ exports[`<Header /> renders correctly for authenticated desktop 1`] = `
<a
className="nav-link"
href="http://localhost:18000/dashboard"
onClick={null}
>
Courses
</a>
@@ -255,7 +253,7 @@ exports[`<Header /> renders correctly for authenticated desktop 1`] = `
<span
className="avatar overflow-hidden d-inline-flex rounded-circle mr-2"
style={
{
Object {
"height": "1.5em",
"width": "1.5em",
}
@@ -267,7 +265,7 @@ exports[`<Header /> renders correctly for authenticated desktop 1`] = `
height="24px"
role="img"
style={
{
Object {
"height": "1.5em",
"width": "1.5em",
}
@@ -341,7 +339,7 @@ exports[`<Header /> renders correctly for authenticated mobile 1`] = `
height="24px"
role="img"
style={
{
Object {
"height": "1.5rem",
"width": "1.5rem",
}
@@ -411,7 +409,7 @@ exports[`<Header /> renders correctly for authenticated mobile 1`] = `
<span
className="avatar overflow-hidden d-inline-flex rounded-circle null"
style={
{
Object {
"height": "1.5rem",
"width": "1.5rem",
}
@@ -423,7 +421,7 @@ exports[`<Header /> renders correctly for authenticated mobile 1`] = `
height="24px"
role="img"
style={
{
Object {
"height": "1.5rem",
"width": "1.5rem",
}

View File

@@ -1 +1,28 @@
export default {};
import arMessages from './messages/ar.json';
import frMessages from './messages/fr.json';
import es419Messages from './messages/es_419.json';
import zhcnMessages from './messages/zh_CN.json';
import ptMessages from './messages/pt.json';
import itMessages from './messages/it.json';
import ukMessages from './messages/uk.json';
import deMessages from './messages/de.json';
import ruMessages from './messages/ru.json';
import hiMessages from './messages/hi.json';
import frCAMessages from './messages/fr_CA.json';
// no need to import en messages-- they are in the defaultMessage field
const messages = {
ar: arMessages,
'es-419': es419Messages,
fr: frMessages,
'zh-cn': zhcnMessages,
pt: ptMessages,
it: itMessages,
de: deMessages,
hi: hiMessages,
'fr-ca': frCAMessages,
ru: ruMessages,
uk: ukMessages,
};
export default messages;

36
src/i18n/messages/ar.json Normal file
View File

@@ -0,0 +1,36 @@
{
"header.links.courses": "المساقات",
"header.links.programs": "البرامج",
"header.links.content.search": "اكتشف الجديد",
"header.links.schools": "المدارس و الشركاء",
"header.user.menu.dashboard": "لوحة المعلومات",
"header.user.menu.profile": "الملف الشخصي",
"header.user.menu.account.settings": "الحساب",
"header.user.menu.order.history": "سجل الطلبيات",
"header.user.menu.logout": "تسجيل الخروج",
"header.user.menu.login": "تسجيل الدخول",
"header.user.menu.register": "التسجيل",
"header.user.menu.studio.home": "صفحة الاستوديو الرئيسية",
"header.user.menu.studio.maintenance": "الصيانة",
"header.label.account.nav": "الحساب",
"header.label.account.menu": "قائمة الحساب",
"header.label.account.menu.for": "قائمة حساب المستخدم {username}",
"header.label.main.nav": "القا|مة الرئيسية",
"header.label.main.menu": "القائمة الرئيسية",
"header.label.main.header": "الرئيسية",
"header.label.secondary.nav": "القائمة الثانوية",
"header.label.skip.nav": "التخطي إلى المحتوى الرئيسي",
"header.label.app.nav": "تطبيق",
"general.register.sentenceCase": "التسجيل",
"general.signIn.sentenceCase": "تسجيل الدخول",
"header.menu.dashboard.label": "لوحة المعلومات",
"header.help.label": "المساعدة",
"header.menu.profile.label": "الملف الشخصي",
"header.menu.account.label": "الحساب",
"header.menu.orderHistory.label": "سجل الطلبيات",
"header.navigation.skipNavLink": "التخطي إلى المحتوى الرئيسي",
"header.menu.signOut.label": "تسجيل الخروج",
"header.user.menu.studio": "Studio Home",
"header.user.menu.maintenance": "Maintenance",
"header.label.courseOutline": "Back to course outline in Studio"
}

36
src/i18n/messages/de.json Normal file
View File

@@ -0,0 +1,36 @@
{
"header.links.courses": "Courses",
"header.links.programs": "Programs",
"header.links.content.search": "Discover New",
"header.links.schools": "Schools & Partners",
"header.user.menu.dashboard": "Dashboard",
"header.user.menu.profile": "Profile",
"header.user.menu.account.settings": "Account",
"header.user.menu.order.history": "Order History",
"header.user.menu.logout": "Logout",
"header.user.menu.login": "Login",
"header.user.menu.register": "Sign Up",
"header.user.menu.studio.home": "Studio Home",
"header.user.menu.studio.maintenance": "Maintenance",
"header.label.account.nav": "Account",
"header.label.account.menu": "Account Menu",
"header.label.account.menu.for": "Account menu for {username}",
"header.label.main.nav": "Main",
"header.label.main.menu": "Main Menu",
"header.label.main.header": "Main",
"header.label.secondary.nav": "Secondary",
"header.label.skip.nav": "Skip to main content",
"header.label.app.nav": "App",
"general.register.sentenceCase": "Register",
"general.signIn.sentenceCase": "Sign in",
"header.menu.dashboard.label": "Dashboard",
"header.help.label": "Help",
"header.menu.profile.label": "Profile",
"header.menu.account.label": "Account",
"header.menu.orderHistory.label": "Order History",
"header.navigation.skipNavLink": "Skip to main content.",
"header.menu.signOut.label": "Sign Out",
"header.user.menu.studio": "Studio Home",
"header.user.menu.maintenance": "Maintenance",
"header.label.courseOutline": "Back to course outline in Studio"
}

View File

@@ -0,0 +1,36 @@
{
"header.links.courses": "Cursos",
"header.links.programs": "Programas",
"header.links.content.search": "Encontrar nuevo",
"header.links.schools": "Escuelas y Socios",
"header.user.menu.dashboard": "Panel de Control",
"header.user.menu.profile": "Perfil",
"header.user.menu.account.settings": "Cuenta",
"header.user.menu.order.history": "Historial de órdenes",
"header.user.menu.logout": "Cerrar sesión",
"header.user.menu.login": "Login",
"header.user.menu.register": "Registrarse",
"header.user.menu.studio.home": "Inicio Studio",
"header.user.menu.studio.maintenance": "Mantenimiento",
"header.label.account.nav": "Cuenta",
"header.label.account.menu": "Menú de la cuenta",
"header.label.account.menu.for": "Menú de la cuenta para {username}",
"header.label.main.nav": "Principal",
"header.label.main.menu": "Menú Principal",
"header.label.main.header": "Principal",
"header.label.secondary.nav": "Secondary",
"header.label.skip.nav": "Ir al contenido principal",
"header.label.app.nav": "Aplicación",
"general.register.sentenceCase": "Registrarse",
"general.signIn.sentenceCase": "Iniciar sesión",
"header.menu.dashboard.label": "Panel de Control",
"header.help.label": "Ayuda",
"header.menu.profile.label": "Perfil",
"header.menu.account.label": "Cuenta",
"header.menu.orderHistory.label": "Historial de órdenes",
"header.navigation.skipNavLink": "Dirígete al contenido principal.",
"header.menu.signOut.label": "Cerrar sesión",
"header.user.menu.studio": "Inicio Studio",
"header.user.menu.maintenance": "Mantenimiento",
"header.label.courseOutline": "Volver al esquema del curso en Studio"
}

36
src/i18n/messages/fr.json Normal file
View File

@@ -0,0 +1,36 @@
{
"header.links.courses": "Cours",
"header.links.programs": "Programmes",
"header.links.content.search": "Explorer les cours",
"header.links.schools": "Écoles et partenaires",
"header.user.menu.dashboard": "Tableau de bord",
"header.user.menu.profile": "Profil",
"header.user.menu.account.settings": "Compte",
"header.user.menu.order.history": "Historique des commandes",
"header.user.menu.logout": "Déconnexion",
"header.user.menu.login": "Connexion",
"header.user.menu.register": "S'inscrire",
"header.user.menu.studio.home": "Accueil Studio",
"header.user.menu.studio.maintenance": "Maintenance",
"header.label.account.nav": "Compte",
"header.label.account.menu": "Menu du compte",
"header.label.account.menu.for": "Menu du compte pour {username}",
"header.label.main.nav": "Principal",
"header.label.main.menu": "Menu Principal",
"header.label.main.header": "Principal",
"header.label.secondary.nav": "Secondaire",
"header.label.skip.nav": "Passer au contenu principal",
"header.label.app.nav": "Application",
"general.register.sentenceCase": "S'inscrire",
"general.signIn.sentenceCase": "Connectez-vous",
"header.menu.dashboard.label": "Tableau de bord",
"header.help.label": "Aide",
"header.menu.profile.label": "Profil",
"header.menu.account.label": "Compte",
"header.menu.orderHistory.label": "Historique des commandes",
"header.navigation.skipNavLink": "Passer au contenu principal",
"header.menu.signOut.label": "Se déconnecter",
"header.user.menu.studio": "Studio Home",
"header.user.menu.maintenance": "Maintenance",
"header.label.courseOutline": "Back to course outline in Studio"
}

View File

@@ -0,0 +1,36 @@
{
"header.links.courses": "Cours",
"header.links.programs": "Programmes",
"header.links.content.search": "Découvrir les nouveautés",
"header.links.schools": "Écoles et Partenaires",
"header.user.menu.dashboard": "Tableau de bord",
"header.user.menu.profile": "Profil",
"header.user.menu.account.settings": "Compte",
"header.user.menu.order.history": "Historique des commandes",
"header.user.menu.logout": "Déconnexion",
"header.user.menu.login": "Connexion",
"header.user.menu.register": "S'inscrire",
"header.user.menu.studio.home": "Accueil Studio",
"header.user.menu.studio.maintenance": "Entretien",
"header.label.account.nav": "Compte",
"header.label.account.menu": "Menu de compte",
"header.label.account.menu.for": "Menu de compte pour {username}",
"header.label.main.nav": "Principal",
"header.label.main.menu": "Menu principal",
"header.label.main.header": "Principal",
"header.label.secondary.nav": "Secondaire",
"header.label.skip.nav": "Passer au contenu de cette vue",
"header.label.app.nav": "Application",
"general.register.sentenceCase": "Inscription",
"general.signIn.sentenceCase": "Connexion",
"header.menu.dashboard.label": "Tableau de bord",
"header.help.label": "Aide",
"header.menu.profile.label": "Profil",
"header.menu.account.label": "Compte",
"header.menu.orderHistory.label": "Historique des commandes",
"header.navigation.skipNavLink": "Passer au contenu principal.",
"header.menu.signOut.label": "Se déconnecter",
"header.user.menu.studio": "Accueil Studio",
"header.user.menu.maintenance": "Entretien",
"header.label.courseOutline": "Retour au plan de cours dans Studio"
}

36
src/i18n/messages/hi.json Normal file
View File

@@ -0,0 +1,36 @@
{
"header.links.courses": "Courses",
"header.links.programs": "Programs",
"header.links.content.search": "Discover New",
"header.links.schools": "Schools & Partners",
"header.user.menu.dashboard": "Dashboard",
"header.user.menu.profile": "Profile",
"header.user.menu.account.settings": "Account",
"header.user.menu.order.history": "Order History",
"header.user.menu.logout": "Logout",
"header.user.menu.login": "Login",
"header.user.menu.register": "Sign Up",
"header.user.menu.studio.home": "Studio Home",
"header.user.menu.studio.maintenance": "Maintenance",
"header.label.account.nav": "Account",
"header.label.account.menu": "Account Menu",
"header.label.account.menu.for": "Account menu for {username}",
"header.label.main.nav": "Main",
"header.label.main.menu": "Main Menu",
"header.label.main.header": "Main",
"header.label.secondary.nav": "Secondary",
"header.label.skip.nav": "Skip to main content",
"header.label.app.nav": "App",
"general.register.sentenceCase": "Register",
"general.signIn.sentenceCase": "Sign in",
"header.menu.dashboard.label": "Dashboard",
"header.help.label": "Help",
"header.menu.profile.label": "Profile",
"header.menu.account.label": "Account",
"header.menu.orderHistory.label": "Order History",
"header.navigation.skipNavLink": "Skip to main content.",
"header.menu.signOut.label": "Sign Out",
"header.user.menu.studio": "Studio Home",
"header.user.menu.maintenance": "Maintenance",
"header.label.courseOutline": "Back to course outline in Studio"
}

36
src/i18n/messages/it.json Normal file
View File

@@ -0,0 +1,36 @@
{
"header.links.courses": "Courses",
"header.links.programs": "Programs",
"header.links.content.search": "Discover New",
"header.links.schools": "Schools & Partners",
"header.user.menu.dashboard": "Dashboard",
"header.user.menu.profile": "Profile",
"header.user.menu.account.settings": "Account",
"header.user.menu.order.history": "Order History",
"header.user.menu.logout": "Logout",
"header.user.menu.login": "Login",
"header.user.menu.register": "Sign Up",
"header.user.menu.studio.home": "Studio Home",
"header.user.menu.studio.maintenance": "Maintenance",
"header.label.account.nav": "Account",
"header.label.account.menu": "Account Menu",
"header.label.account.menu.for": "Account menu for {username}",
"header.label.main.nav": "Main",
"header.label.main.menu": "Main Menu",
"header.label.main.header": "Main",
"header.label.secondary.nav": "Secondary",
"header.label.skip.nav": "Skip to main content",
"header.label.app.nav": "App",
"general.register.sentenceCase": "Register",
"general.signIn.sentenceCase": "Sign in",
"header.menu.dashboard.label": "Dashboard",
"header.help.label": "Help",
"header.menu.profile.label": "Profile",
"header.menu.account.label": "Account",
"header.menu.orderHistory.label": "Order History",
"header.navigation.skipNavLink": "Skip to main content.",
"header.menu.signOut.label": "Sign Out",
"header.user.menu.studio": "Studio Home",
"header.user.menu.maintenance": "Maintenance",
"header.label.courseOutline": "Back to course outline in Studio"
}

36
src/i18n/messages/pt.json Normal file
View File

@@ -0,0 +1,36 @@
{
"header.links.courses": "Courses",
"header.links.programs": "Programs",
"header.links.content.search": "Discover New",
"header.links.schools": "Schools & Partners",
"header.user.menu.dashboard": "Dashboard",
"header.user.menu.profile": "Profile",
"header.user.menu.account.settings": "Account",
"header.user.menu.order.history": "Order History",
"header.user.menu.logout": "Logout",
"header.user.menu.login": "Login",
"header.user.menu.register": "Sign Up",
"header.user.menu.studio.home": "Studio Home",
"header.user.menu.studio.maintenance": "Maintenance",
"header.label.account.nav": "Account",
"header.label.account.menu": "Account Menu",
"header.label.account.menu.for": "Account menu for {username}",
"header.label.main.nav": "Main",
"header.label.main.menu": "Main Menu",
"header.label.main.header": "Main",
"header.label.secondary.nav": "Secondary",
"header.label.skip.nav": "Skip to main content",
"header.label.app.nav": "App",
"general.register.sentenceCase": "Register",
"general.signIn.sentenceCase": "Sign in",
"header.menu.dashboard.label": "Dashboard",
"header.help.label": "Help",
"header.menu.profile.label": "Profile",
"header.menu.account.label": "Account",
"header.menu.orderHistory.label": "Order History",
"header.navigation.skipNavLink": "Skip to main content.",
"header.menu.signOut.label": "Sign Out",
"header.user.menu.studio": "Studio Home",
"header.user.menu.maintenance": "Maintenance",
"header.label.courseOutline": "Back to course outline in Studio"
}

36
src/i18n/messages/ru.json Normal file
View File

@@ -0,0 +1,36 @@
{
"header.links.courses": "Courses",
"header.links.programs": "Programs",
"header.links.content.search": "Discover New",
"header.links.schools": "Schools & Partners",
"header.user.menu.dashboard": "Dashboard",
"header.user.menu.profile": "Profile",
"header.user.menu.account.settings": "Account",
"header.user.menu.order.history": "Order History",
"header.user.menu.logout": "Logout",
"header.user.menu.login": "Login",
"header.user.menu.register": "Sign Up",
"header.user.menu.studio.home": "Studio Home",
"header.user.menu.studio.maintenance": "Maintenance",
"header.label.account.nav": "Account",
"header.label.account.menu": "Account Menu",
"header.label.account.menu.for": "Account menu for {username}",
"header.label.main.nav": "Main",
"header.label.main.menu": "Main Menu",
"header.label.main.header": "Main",
"header.label.secondary.nav": "Secondary",
"header.label.skip.nav": "Skip to main content",
"header.label.app.nav": "App",
"general.register.sentenceCase": "Register",
"general.signIn.sentenceCase": "Sign in",
"header.menu.dashboard.label": "Dashboard",
"header.help.label": "Help",
"header.menu.profile.label": "Profile",
"header.menu.account.label": "Account",
"header.menu.orderHistory.label": "Order History",
"header.navigation.skipNavLink": "Skip to main content.",
"header.menu.signOut.label": "Sign Out",
"header.user.menu.studio": "Studio Home",
"header.user.menu.maintenance": "Maintenance",
"header.label.courseOutline": "Back to course outline in Studio"
}

36
src/i18n/messages/uk.json Normal file
View File

@@ -0,0 +1,36 @@
{
"header.links.courses": "Курси",
"header.links.programs": "Програми",
"header.links.content.search": "Discover New",
"header.links.schools": "Schools & Partners",
"header.user.menu.dashboard": "Dashboard",
"header.user.menu.profile": "Profile",
"header.user.menu.account.settings": "Account",
"header.user.menu.order.history": "Order History",
"header.user.menu.logout": "Logout",
"header.user.menu.login": "Login",
"header.user.menu.register": "Sign Up",
"header.user.menu.studio.home": "Studio Home",
"header.user.menu.studio.maintenance": "Maintenance",
"header.label.account.nav": "Account",
"header.label.account.menu": "Меню облікового запису",
"header.label.account.menu.for": "Меню облікового запису для {username}",
"header.label.main.nav": "Main",
"header.label.main.menu": "Main Menu",
"header.label.main.header": "Main",
"header.label.secondary.nav": "Secondary",
"header.label.skip.nav": "Перейти до головного змісту",
"header.label.app.nav": "App",
"general.register.sentenceCase": "Register",
"general.signIn.sentenceCase": "Увійти",
"header.menu.dashboard.label": "Dashboard",
"header.help.label": "Help",
"header.menu.profile.label": "Profile",
"header.menu.account.label": "Account",
"header.menu.orderHistory.label": "Order History",
"header.navigation.skipNavLink": "Перейти до головного змісту.",
"header.menu.signOut.label": "Sign Out",
"header.user.menu.studio": "Studio Home",
"header.user.menu.maintenance": "Maintenance",
"header.label.courseOutline": "Back to course outline in Studio"
}

View File

@@ -0,0 +1,36 @@
{
"header.links.courses": "Courses",
"header.links.programs": "Programs",
"header.links.content.search": "Discover New",
"header.links.schools": "Schools & Partners",
"header.user.menu.dashboard": "Dashboard",
"header.user.menu.profile": "Profile",
"header.user.menu.account.settings": "Account",
"header.user.menu.order.history": "Order History",
"header.user.menu.logout": "Logout",
"header.user.menu.login": "Login",
"header.user.menu.register": "Sign Up",
"header.user.menu.studio.home": "Studio Home",
"header.user.menu.studio.maintenance": "Maintenance",
"header.label.account.nav": "Account",
"header.label.account.menu": "Account Menu",
"header.label.account.menu.for": "Account menu for {username}",
"header.label.main.nav": "Main",
"header.label.main.menu": "Main Menu",
"header.label.main.header": "Main",
"header.label.secondary.nav": "Secondary",
"header.label.skip.nav": "Skip to main content",
"header.label.app.nav": "App",
"general.register.sentenceCase": "Register",
"general.signIn.sentenceCase": "Sign in",
"header.menu.dashboard.label": "Dashboard",
"header.help.label": "Help",
"header.menu.profile.label": "Profile",
"header.menu.account.label": "Account",
"header.menu.orderHistory.label": "Order History",
"header.navigation.skipNavLink": "Skip to main content.",
"header.menu.signOut.label": "Sign Out",
"header.user.menu.studio": "Studio Home",
"header.user.menu.maintenance": "Maintenance",
"header.label.courseOutline": "Back to course outline in Studio"
}

View File

@@ -88,15 +88,6 @@ $white: #fff;
height: 100%;
}
}
.secondary-menu-container {
.nav-link:hover,
.nav-link:focus,
.nav-link.active,
.expanded .nav-link {
background: $component-active-bg;
color: $component-active-color;
}
}
.main-nav {
.nav-link {
padding: 1.125rem 1rem;

View File

@@ -3,7 +3,7 @@ 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 '@openedx/paragon';
import { Button } from '@edx/paragon';
import genericMessages from '../generic/messages';

View File

@@ -5,7 +5,7 @@ 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 '@openedx/paragon';
import { Dropdown } from '@edx/paragon';
import messages from './messages';

View File

@@ -1,7 +1,9 @@
/* eslint-disable import/no-extraneous-dependencies */
import Enzyme from 'enzyme';
import React from 'react';
import PropTypes from 'prop-types';
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
import '@testing-library/jest-dom';
import '@testing-library/jest-dom/extend-expect';
import 'babel-polyfill';
@@ -15,6 +17,8 @@ import { IntlProvider } from 'react-intl';
import AppProvider from '@edx/frontend-platform/react/AppProvider';
import appMessages from './i18n';
Enzyme.configure({ adapter: new Adapter() });
// These configuration values are usually set in webpack's EnvironmentPlugin however
// Jest does not use webpack so we need to set these so for testing
process.env.ACCESS_TOKEN_COOKIE_NAME = 'edx-jwt-cookie-header-payload';

View File

@@ -4,7 +4,7 @@ import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import {
OverlayTrigger,
Tooltip,
} from '@openedx/paragon';
} from '@edx/paragon';
import messages from './messages';
const CourseLockUp = ({

View File

@@ -1,22 +1,18 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
ActionRow,
Button,
Container,
Icon,
IconButton,
Nav,
Row,
} from '@openedx/paragon';
import { Close, MenuIcon, Search } from '@openedx/paragon/icons';
} from '@edx/paragon';
import { Close, MenuIcon } from '@edx/paragon/icons';
import CourseLockUp from './CourseLockUp';
import UserMenu from './UserMenu';
import BrandNav from './BrandNav';
import NavDropdownMenu from './NavDropdownMenu';
import messages from './messages';
const HeaderBody = ({
logo,
@@ -36,10 +32,7 @@ const HeaderBody = ({
isHiddenMainMenu,
mainMenuDropdowns,
outlineLink,
searchButtonAction,
}) => {
const intl = useIntl();
const renderBrandNav = (
<BrandNav
{...{
@@ -103,16 +96,6 @@ const HeaderBody = ({
</>
)}
<ActionRow.Spacer />
{searchButtonAction && (
<Nav>
<IconButton
src={Search}
iconAs={Icon}
onClick={searchButtonAction}
aria-label={intl.formatMessage(messages['header.label.search.nav'])}
/>
</Nav>
)}
<Nav>
<UserMenu
{...{
@@ -154,7 +137,6 @@ HeaderBody.propTypes = {
})),
})),
outlineLink: PropTypes.string,
searchButtonAction: PropTypes.func,
};
HeaderBody.defaultProps = {
@@ -173,7 +155,6 @@ HeaderBody.defaultProps = {
isHiddenMainMenu: false,
mainMenuDropdowns: [],
outlineLink: null,
searchButtonAction: null,
};
export default HeaderBody;

View File

@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { useToggle, ModalPopup } from '@openedx/paragon';
import { useToggle, ModalPopup } from '@edx/paragon';
import HeaderBody from './HeaderBody';
import MobileMenu from './MobileMenu';

View File

@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Collapsible } from '@openedx/paragon';
import { Collapsible } from '@edx/paragon';
const MobileMenu = ({
mainMenuDropdowns,

View File

@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import {
Dropdown,
DropdownButton,
} from '@openedx/paragon';
} from '@edx/paragon';
const NavDropdownMenu = ({
id,

View File

@@ -16,7 +16,7 @@ ensureConfig([
], 'Studio Header component');
const StudioHeader = ({
number, org, title, isHiddenMainMenu, mainMenuDropdowns, outlineLink, searchButtonAction,
number, org, title, isHiddenMainMenu, mainMenuDropdowns, outlineLink,
}) => {
const { authenticatedUser, config } = useContext(AppContext);
const props = {
@@ -33,7 +33,6 @@ const StudioHeader = ({
isHiddenMainMenu,
mainMenuDropdowns,
outlineLink,
searchButtonAction,
};
return (
@@ -63,7 +62,6 @@ StudioHeader.propTypes = {
})),
})),
outlineLink: PropTypes.string,
searchButtonAction: PropTypes.func,
};
StudioHeader.defaultProps = {
@@ -72,7 +70,6 @@ StudioHeader.defaultProps = {
isHiddenMainMenu: false,
mainMenuDropdowns: [],
outlineLink: null,
searchButtonAction: null,
};
export default StudioHeader;

View File

@@ -69,7 +69,6 @@ const props = {
},
],
outlineLink: 'tEsTLInK',
searchButtonAction: null,
};
describe('Header', () => {
@@ -139,20 +138,6 @@ describe('Header', () => {
expect(desktopMenu).toBeNull();
});
it('should show search button', async () => {
const testProps = { ...props, searchButtonAction: () => undefined };
const { getByRole } = render(<RootWrapper {...testProps} />);
const searchButton = getByRole('button', { name: 'Search content' });
expect(searchButton).toBeVisible();
});
it('should not show search button', async () => {
const testProps = { ...props, searchButtonAction: null };
const { queryByRole } = render(<RootWrapper {...testProps} />);
expect(queryByRole('button', { name: 'Search content' })).not.toBeInTheDocument();
});
});
describe('mobile', () => {

View File

@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import {
Avatar,
} from '@openedx/paragon';
} from '@edx/paragon';
import NavDropdownMenu from './NavDropdownMenu';
import getUserMenuItems from './utils';

View File

@@ -51,11 +51,6 @@ const messages = defineMessages({
defaultMessage: 'Back to course outline in Studio',
description: 'The aria label for the link back to the Studio Course Outline',
},
'header.label.search.nav': {
id: 'header.label.search.nav',
defaultMessage: 'Search content',
description: 'The aria label for the search content button nav',
},
});
export default messages;

View File

@@ -1,5 +1,5 @@
const path = require('path');
const { createConfig } = require('@openedx/frontend-build');
const { createConfig } = require('@edx/frontend-build');
module.exports = createConfig('webpack-dev', {
entry: path.resolve(__dirname, 'example'),