Compare commits

...

39 Commits

Author SHA1 Message Date
Jawayria
5d297a0d00 feat: Added package-lock file version check (#213) 2022-05-12 12:23:43 +05:00
Renovate Bot
1aa6e80274 chore(deps): update dependency @edx/paragon to v19.20.0 2022-05-02 13:43:13 +00:00
Renovate Bot
15778a5e4a chore(deps): update dependency @edx/frontend-build to v9.2.2 2022-05-02 10:38:49 +00:00
Renovate Bot
48c41a7757 chore(deps): update dependency redux to v4.2.0 2022-04-25 14:19:34 +00:00
Renovate Bot
28ee7518f4 chore(deps): update dependency @edx/paragon to v19.19.0 2022-04-25 11:43:12 +00:00
Carlos Muniz
c35df7ef60 feat: Add StudioHeader with optional AppMenu (#199)
* feat: Add StudioHeader with optional AppMenu

StudioHeader is a graft of Header with an additional optional AppMenu.
Some Frontend Apps use Menus in their custom headers to provide more
functionality in their apps. By adding this functionality in
StudioHeader, it will be easier for frontend apps in Studio to adopt
this component without it affecting the main Header component.

* test: Add tests for StudioHeader and AppMenu

* fix: Remove orderHistory

* fix: Remove Responsive components

* fix: Redefine User Menu for Studio

The userMenu in StudioHeader will be used more for Studio related items
such as Studio Home and Studio Maintenance. This requires new messages
and reestablishing the url destinations of these menu items.

* fix: Remove loggedOutItems

* fix: Remove AUTHN_MINIMAL_HEADER items

* fix: Remove unnecessary tests

Anonymous sessions do not exist in the Studio. And Studio is not Mobile
Ready. Tests of these kind are superfluous and have been removed.

* feat: Turn mainMenu into an optional prop

* test: Add test for optional mainMenu prop

* feat: Update snapshots

* fix: Remove ResponsiveContext

* fix: Remove href and update appMenu prop

Dropping the href because having a link that also works as a dropdown
can be mildly confusing. Changing menu (type, href, content ) triplet
to stick to the pattern; so we removed "menu". Also adding brackets around
the triplet. Lastly, updating test and snapshot.

Co-authored-by: Carlos Muniz <cmuniz@trcil.org>
2022-04-21 13:43:37 -04:00
Renovate Bot
a8d5a0b62a chore(deps): update dependency react-router-dom to v5.3.1 2022-04-18 15:48:35 +00:00
Renovate Bot
9ac38762eb chore(deps): update dependency react-redux to v7.2.8 2022-04-18 11:55:33 +00:00
Renovate Bot
72077302c0 chore(deps): update dependency jest to v27.5.1 2022-04-11 15:26:22 +00:00
Renovate Bot
f1a54ededf chore(deps): update dependency @testing-library/jest-dom to v5.16.4 2022-04-11 12:14:34 +00:00
Renovate Bot
709844a459 chore(deps): update dependency @edx/frontend-build to v9.1.4 2022-04-04 13:35:10 +00:00
Usama Sadiq
032c68edf2 Merge pull request #195 from openedx/jenkins/transifex-client-migration-541fe55
fix: transifex migration to new client
2022-04-04 14:10:03 +05:00
edX requirements bot
be8b6fba01 fix: transifex migration to new client 2022-03-17 08:56:54 -04:00
David Joy
541fe55d6e build: delete CODEOWNERS file
We no longer have a community-engineering team.
2022-03-04 10:42:58 -05:00
Jawayria
28a62cf263 Merge pull request #194 from openedx/jawayria/test-peer-dep
fix: update peer dep
2022-03-04 20:33:55 +05:00
Jawayria
6e7584c89c fix: update peer dep 2022-03-04 20:29:16 +05:00
Jawayria
49b03689a0 Merge pull request #193 from openedx/jawayria/update-deps
fix: Upgraded dependencies for Node 16
2022-03-04 12:50:50 +05:00
Jawayria
fdb00ce1f5 fix: Upgraded dependencies for Node 16 2022-03-03 19:55:31 +05:00
Renovate Bot
5d1d73a6b6 chore(deps): update dependency @edx/frontend-build to v9.1.1 2022-02-25 13:21:05 +00:00
Jawayria
b292ee39ad Merge pull request #181 from openedx/jawayria/node-16
feat: Added support for node v16
2022-02-25 17:09:30 +05:00
Sarina Canelake
c5f13022de Merge DEPR automation workflow
Add DEPR workflow automation
2022-02-24 15:22:08 -05:00
Jawayria
47a3962118 build: Added support for node v16 2022-02-24 21:29:25 +05:00
Sarina Canelake
b55d0d6bea build: add DEPR workflow automation 2022-02-23 14:38:13 -05:00
Renovate Bot
8cb19859aa chore(deps): update dependency jest to v27.5.0 2022-02-07 09:54:56 +00:00
Renovate Bot
bafa6452ca chore(deps): update dependency @testing-library/jest-dom to v5.16.2 2022-02-07 09:20:49 +00:00
edX Transifex Bot
3ab658ffa0 chore(i18n): update translations 2022-01-23 15:32:36 -05:00
Renovate Bot
72b6a2c2a0 chore(deps): update dependency prop-types to v15.8.1 2022-01-10 09:13:51 +00:00
Renovate Bot
a479556795 chore(deps): update dependency jest to v27.4.7 2022-01-10 08:55:54 +00:00
Renovate Bot
8f03fa84ac chore(deps): update dependency prop-types to v15.8.0 2022-01-03 10:24:10 +00:00
Renovate Bot
990d82be6a chore(deps): update dependency jest to v27.4.5 2022-01-03 10:05:52 +00:00
edX Transifex Bot
b90db977a0 chore(i18n): update translations 2022-01-02 15:31:58 -05:00
Renovate Bot
093452860e chore(deps): update dependency @testing-library/react to v10.4.9 2021-12-27 08:39:46 +00:00
Renovate Bot
8ac9a2dc3c chore(deps): update dependency @edx/frontend-platform to v1.14.9 2021-12-27 08:22:33 +00:00
David Joy
440eacbce4 fix: Causing a patch version bump so we can release the transifex fixes (#165) 2021-12-20 11:16:11 -05:00
Renovate Bot
725fa982c7 chore(deps): update dependency @testing-library/jest-dom to v5.16.1 2021-12-20 10:22:13 +00:00
Renovate Bot
fe41fbc0b1 chore(deps): update dependency @edx/frontend-platform to v1.14.4 2021-12-20 10:03:50 +00:00
edX Transifex Bot
0de0a3f07f chore(i18n): update translations 2021-12-19 15:31:34 -05:00
Diana Huang
b0009fef42 Merge pull request #159 from edx/diana/update-transifex-langs
chore: Update transifex languages.
2021-12-10 09:22:31 -05:00
Diana Huang
8bfae8bf2f chore: Update transifex languages.
Adding fr_CA to our transifex languages to
pull down the language files into the repo.

https://github.com/openedx/build-test-release-wg/issues/116
2021-12-10 09:14:54 -05:00
20 changed files with 35847 additions and 9207 deletions

View File

@@ -5,6 +5,7 @@ CSRF_TOKEN_API_PATH=/csrf/api/v1/token
ECOMMERCE_BASE_URL=http://localhost:18130 ECOMMERCE_BASE_URL=http://localhost:18130
LANGUAGE_PREFERENCE_COOKIE_NAME=openedx-language-preference LANGUAGE_PREFERENCE_COOKIE_NAME=openedx-language-preference
LMS_BASE_URL=http://localhost:18000 LMS_BASE_URL=http://localhost:18000
STUDIO_BASE_URL=http://localhost:18010
LOGIN_URL=http://localhost:18000/login LOGIN_URL=http://localhost:18000/login
LOGOUT_URL=http://localhost:18000/logout LOGOUT_URL=http://localhost:18000/logout
MARKETING_SITE_BASE_URL=http://localhost:18000 MARKETING_SITE_BASE_URL=http://localhost:18000

1
.github/CODEOWNERS vendored
View File

@@ -1 +0,0 @@
* @edx/community-engineering

View File

@@ -0,0 +1,19 @@
# Run the workflow that adds new tickets that are either:
# - labelled "DEPR"
# - title starts with "[DEPR]"
# - body starts with "Proposal Date" (this is the first template field)
# to the org-wide DEPR project board
name: Add newly created DEPR issues to the DEPR project board
on:
issues:
types: [opened]
jobs:
routeissue:
uses: openedx/.github/.github/workflows/add-depr-ticket-to-depr-board.yml@master
secrets:
GITHUB_APP_ID: ${{ secrets.GRAPHQL_AUTH_APP_ID }}
GITHUB_APP_PRIVATE_KEY: ${{ secrets.GRAPHQL_AUTH_APP_PEM }}
SLACK_BOT_TOKEN: ${{ secrets.SLACK_ISSUE_BOT_TOKEN }}

View File

@@ -1,8 +1,17 @@
name: Default CI name: Default CI
on: [push, pull_request] on:
push:
branches:
- 'master'
pull_request:
branches:
- '**'
jobs: jobs:
build: tests:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
matrix:
node: [12, 14, 16]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
@@ -11,7 +20,7 @@ jobs:
- name: Setup Nodejs - name: Setup Nodejs
uses: actions/setup-node@v2 uses: actions/setup-node@v2
with: with:
node-version: 12 node-version: ${{ matrix.node }}
- name: Install dependencies - name: Install dependencies
run: npm ci run: npm ci
- name: Validate package-lock.json changes - name: Validate package-lock.json changes

View File

@@ -0,0 +1,14 @@
#check package-lock file version
name: lockfileVersion check
on:
push:
branches:
- master
pull_request:
jobs:
version-check:
uses: openedx/.github/.github/workflows/lockfileversion-check.yml@master

View File

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

View File

@@ -1,5 +1,5 @@
transifex_resource = frontend-component-header transifex_resource = frontend-component-header
transifex_langs = "ar,fr,es_419,zh_CN" transifex_langs = "ar,fr,fr_CA,es_419,zh_CN"
transifex_utils = ./node_modules/.bin/transifex-utils.js transifex_utils = ./node_modules/.bin/transifex-utils.js
i18n = ./src/i18n i18n = ./src/i18n

View File

@@ -56,6 +56,7 @@ Examples
* `An example of component and messages usage. <https://github.com/edx/frontend-template-application/blob/3355bb3a96232390e9056f35b06ffa8f105ed7ca/src/index.jsx#L21>`_ * `An example of component and messages usage. <https://github.com/edx/frontend-template-application/blob/3355bb3a96232390e9056f35b06ffa8f105ed7ca/src/index.jsx#L21>`_
* `An example of SCSS file usage. <https://github.com/edx/frontend-template-application/blob/3cd5485bf387b8c479baf6b02bf59e3061dc3465/src/index.scss#L8>`_ * `An example of SCSS file usage. <https://github.com/edx/frontend-template-application/blob/3cd5485bf387b8c479baf6b02bf59e3061dc3465/src/index.scss#L8>`_
*********** ***********
Development Development
*********** ***********

44061
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -34,27 +34,27 @@
"homepage": "https://github.com/edx/frontend-component-header#readme", "homepage": "https://github.com/edx/frontend-component-header#readme",
"devDependencies": { "devDependencies": {
"@edx/brand": "npm:@edx/brand-openedx@1.1.0", "@edx/brand": "npm:@edx/brand-openedx@1.1.0",
"@edx/frontend-build": "5.6.14", "@edx/frontend-build": "9.2.2",
"@edx/frontend-platform": "1.14.1", "@edx/frontend-platform": "1.15.1",
"@edx/paragon": "12.8.0", "@edx/paragon": "19.20.0",
"codecov": "3.8.3", "codecov": "3.8.3",
"enzyme": "3.11.0", "enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.6", "enzyme-adapter-react-16": "1.15.6",
"husky": "7.0.4", "husky": "7.0.4",
"prop-types": "15.7.2", "prop-types": "15.8.1",
"react": "16.14.0", "react": "16.14.0",
"react-dom": "16.14.0", "react-dom": "16.14.0",
"react-redux": "7.2.6", "react-redux": "7.2.8",
"react-router-dom": "5.3.0", "react-router-dom": "5.3.1",
"react-test-renderer": "16.14.0", "react-test-renderer": "16.14.0",
"reactifex": "1.1.1", "reactifex": "1.1.1",
"redux": "4.1.2", "redux": "4.2.0",
"redux-saga": "1.1.3", "redux-saga": "1.1.3",
"@testing-library/dom": "7.31.2", "@testing-library/dom": "7.31.2",
"@testing-library/jest-dom": "5.15.1", "@testing-library/jest-dom": "5.16.4",
"jest": "27.3.1", "jest": "27.5.1",
"jest-chain": "1.1.5", "jest-chain": "1.1.5",
"@testing-library/react": "10.3.0" "@testing-library/react": "10.4.9"
}, },
"dependencies": { "dependencies": {
"babel-polyfill": "6.26.0", "babel-polyfill": "6.26.0",
@@ -68,7 +68,7 @@
}, },
"peerDependencies": { "peerDependencies": {
"@edx/frontend-platform": "^1.8.0", "@edx/frontend-platform": "^1.8.0",
"@edx/paragon": ">= ^7.0.0 < 13.0.0", "@edx/paragon": ">= 7.0.0 < 20.0.0",
"prop-types": "^15.5.10", "prop-types": "^15.5.10",
"react": "^16.9.0", "react": "^16.9.0",
"react-dom": "^16.9.0" "react-dom": "^16.9.0"

View File

@@ -54,6 +54,24 @@ class DesktopHeader extends React.Component {
}); });
} }
// 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() { renderUserMenu() {
const { const {
userMenu, userMenu,
@@ -102,6 +120,7 @@ class DesktopHeader extends React.Component {
logoDestination, logoDestination,
loggedIn, loggedIn,
intl, intl,
appMenu,
} = this.props; } = this.props;
const logoProps = { src: logo, alt: logoAltText, href: logoDestination }; const logoProps = { src: logo, alt: logoAltText, href: logoDestination };
const logoClasses = getConfig().AUTHN_MINIMAL_HEADER ? 'mw-100' : null; const logoClasses = getConfig().AUTHN_MINIMAL_HEADER ? 'mw-100' : null;
@@ -118,6 +137,14 @@ class DesktopHeader extends React.Component {
> >
{this.renderMainMenu()} {this.renderMainMenu()}
</nav> </nav>
{appMenu ? (
<nav
aria-label={intl.formatMessage(messages['header.label.app.nav'])}
className="nav app-nav"
>
{this.renderAppMenu()}
</nav>
) : null}
<nav <nav
aria-label={intl.formatMessage(messages['header.label.secondary.nav'])} aria-label={intl.formatMessage(messages['header.label.secondary.nav'])}
className="nav secondary-menu-container align-items-center ml-auto" className="nav secondary-menu-container align-items-center ml-auto"
@@ -155,6 +182,20 @@ DesktopHeader.propTypes = {
// i18n // i18n
intl: intlShape.isRequired, 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 = { DesktopHeader.defaultProps = {
@@ -167,6 +208,7 @@ DesktopHeader.defaultProps = {
avatar: null, avatar: null,
username: null, username: null,
loggedIn: false, loggedIn: false,
appMenu: null,
}; };
export default injectIntl(DesktopHeader); export default injectIntl(DesktopHeader);

View File

@@ -56,6 +56,16 @@ const messages = defineMessages({
defaultMessage: 'Sign Up', defaultMessage: 'Sign Up',
description: 'Link to registration', description: 'Link to registration',
}, },
'header.user.menu.studio.home': {
id: 'header.user.menu.studio.home',
defaultMessage: 'Studio Home',
description: 'Link to the Studio Home',
},
'header.user.menu.studio.maintenance': {
id: 'header.user.menu.studio.maintenance',
defaultMessage: 'Maintenance',
description: 'Link to the Studio Maintenance',
},
'header.label.account.nav': { 'header.label.account.nav': {
id: 'header.label.account.nav', id: 'header.label.account.nav',
defaultMessage: 'Account', defaultMessage: 'Account',
@@ -96,6 +106,11 @@ const messages = defineMessages({
defaultMessage: 'Skip to main content', defaultMessage: 'Skip to main content',
description: 'A link used by screen readers to allow users to skip to the main content of the page.', description: 'A link used by screen readers to allow users to skip to the main content of the page.',
}, },
'header.label.app.nav': {
id: 'header.label.app.nav',
defaultMessage: 'App',
description: 'The aria label for the app Nav',
},
}); });
export default messages; export default messages;

99
src/StudioHeader.jsx Normal file
View File

@@ -0,0 +1,99 @@
import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { AppContext } from '@edx/frontend-platform/react';
import {
APP_CONFIG_INITIALIZED,
ensureConfig,
mergeConfig,
subscribe,
} from '@edx/frontend-platform';
import DesktopHeader from './DesktopHeader';
import messages from './Header.messages';
ensureConfig([
'STUDIO_BASE_URL',
'LOGOUT_URL',
'LOGIN_URL',
'SITE_NAME',
'LOGO_URL',
'ORDER_HISTORY_URL',
], 'StudioHeader component');
subscribe(APP_CONFIG_INITIALIZED, () => {
mergeConfig({
AUTHN_MINIMAL_HEADER: !!process.env.AUTHN_MINIMAL_HEADER,
}, 'StudioHeader additional config');
});
function StudioHeader({ intl, mainMenu, appMenu }) {
const { authenticatedUser, config } = useContext(AppContext);
const userMenu = authenticatedUser === null ? [] : [
{
type: 'item',
href: `${config.STUDIO_BASE_URL}`,
content: intl.formatMessage(messages['header.user.menu.studio.home']),
},
{
type: 'item',
href: `${config.STUDIO_BASE_URL}/maintenance`,
content: intl.formatMessage(messages['header.user.menu.studio.maintenance']),
},
{
type: 'item',
href: config.LOGOUT_URL,
content: intl.formatMessage(messages['header.user.menu.logout']),
},
];
const props = {
logo: config.LOGO_URL,
logoAltText: config.SITE_NAME,
logoDestination: config.STUDIO_BASE_URL,
loggedIn: authenticatedUser !== null,
username: authenticatedUser !== null ? authenticatedUser.username : null,
avatar: authenticatedUser !== null ? authenticatedUser.avatar : null,
mainMenu,
userMenu,
appMenu,
loggedOutItems: [],
};
return <DesktopHeader {...props} />;
}
StudioHeader.propTypes = {
intl: intlShape.isRequired,
appMenu: PropTypes.shape(
{
content: PropTypes.string,
href: PropTypes.string,
menuItems: PropTypes.arrayOf(
PropTypes.shape({
type: PropTypes.string,
href: PropTypes.string,
content: PropTypes.string,
}),
),
},
),
mainMenu: PropTypes.arrayOf(
PropTypes.shape(
{
type: PropTypes.string,
href: PropTypes.string,
content: PropTypes.string,
},
),
),
};
StudioHeader.defaultProps = {
appMenu: null,
mainMenu: [],
};
export default injectIntl(StudioHeader);

135
src/StudioHeader.test.jsx Normal file
View File

@@ -0,0 +1,135 @@
import React from 'react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import TestRenderer from 'react-test-renderer';
import { AppContext } from '@edx/frontend-platform/react';
import { StudioHeader } from './index';
describe('<StudioHeader />', () => {
it('renders correctly', () => {
const component = (
<IntlProvider locale="en" messages={{}}>
<AppContext.Provider
value={{
authenticatedUser: {
userId: 'abc123',
username: 'edX',
roles: [],
administrator: false,
},
config: {
STUDIO_BASE_URL: process.env.STUDIO_BASE_URL,
SITE_NAME: process.env.SITE_NAME,
LOGIN_URL: process.env.LOGIN_URL,
LOGOUT_URL: process.env.LOGOUT_URL,
LOGO_URL: process.env.LOGO_URL,
},
}}
>
<StudioHeader />
</AppContext.Provider>
</IntlProvider>
);
const wrapper = TestRenderer.create(component);
expect(wrapper.toJSON()).toMatchSnapshot();
});
it('renders correctly with the optional app menu', () => {
const appMenu = {
content: 'App Menu',
menuItems: [
{
type: 'dropdown',
href: 'https://menu-href-url.org',
content: 'Content 1',
},
{
type: 'dropdown',
href: 'https://menu-href-url.org',
content: 'Content 2',
},
{
type: 'dropdown',
href: 'https://menu-href-url.org',
content: 'Content 3',
},
],
};
const component = (
<IntlProvider locale="en" messages={{}}>
<AppContext.Provider
value={{
authenticatedUser: {
userId: 'abc123',
username: 'edX',
roles: [],
administrator: false,
},
config: {
STUDIO_BASE_URL: process.env.STUDIO_BASE_URL,
SITE_NAME: process.env.SITE_NAME,
LOGIN_URL: process.env.LOGIN_URL,
LOGOUT_URL: process.env.LOGOUT_URL,
LOGO_URL: process.env.LOGO_URL,
},
}}
>
<StudioHeader appMenu={appMenu} />
</AppContext.Provider>
</IntlProvider>
);
const wrapper = TestRenderer.create(component);
expect(wrapper.toJSON()).toMatchSnapshot();
});
it('renders correctly with the optional main menu', () => {
const mainMenu = [
{
type: 'dropdown',
href: 'https://menu-href-url.org',
content: 'Content 1',
},
{
type: 'dropdown',
href: 'https://menu-href-url.org',
content: 'Content 2',
},
{
type: 'dropdown',
href: 'https://menu-href-url.org',
content: 'Content 3',
},
];
const component = (
<IntlProvider locale="en" messages={{}}>
<AppContext.Provider
value={{
authenticatedUser: {
userId: 'abc123',
username: 'edX',
roles: [],
administrator: false,
},
config: {
STUDIO_BASE_URL: process.env.STUDIO_BASE_URL,
SITE_NAME: process.env.SITE_NAME,
LOGIN_URL: process.env.LOGIN_URL,
LOGOUT_URL: process.env.LOGOUT_URL,
LOGO_URL: process.env.LOGO_URL,
},
}}
>
<StudioHeader mainMenu={mainMenu} />
</AppContext.Provider>
</IntlProvider>
);
const wrapper = TestRenderer.create(component);
expect(wrapper.toJSON()).toMatchSnapshot();
});
});

View File

@@ -0,0 +1,425 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<StudioHeader /> renders correctly 1`] = `
<header
className="site-header-desktop"
>
<a
className="nav-skip sr-only sr-only-focusable"
href="#main"
>
Skip to main content
</a>
<div
className="container-fluid null"
>
<div
className="nav-container position-relative d-flex align-items-center"
>
<img
alt="edX"
className="logo"
src="https://edx-cdn.org/v3/default/logo.svg"
/>
<nav
aria-label="Main"
className="nav main-nav"
/>
<nav
aria-label="Secondary"
className="nav secondary-menu-container align-items-center ml-auto"
>
<div
className="menu null"
onKeyDown={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
>
<button
aria-expanded={false}
aria-haspopup="menu"
aria-label="Account menu for edX"
className="menu-trigger btn btn-outline-primary d-inline-flex align-items-center pl-2 pr-3"
onClick={[Function]}
>
<span
className="avatar overflow-hidden d-inline-flex rounded-circle mr-2"
style={
Object {
"height": "1.5em",
"width": "1.5em",
}
}
>
<svg
aria-hidden={true}
focusable="false"
height="24px"
role="img"
style={
Object {
"height": "1.5em",
"width": "1.5em",
}
}
version="1.1"
viewBox="0 0 24 24"
width="24px"
>
<path
d="M4.10255106,18.1351061 C4.7170266,16.0581859 8.01891846,14.4720277 12,14.4720277 C15.9810815,14.4720277 19.2829734,16.0581859 19.8974489,18.1351061 C21.215206,16.4412566 22,14.3122775 22,12 C22,6.4771525 17.5228475,2 12,2 C6.4771525,2 2,6.4771525 2,12 C2,14.3122775 2.78479405,16.4412566 4.10255106,18.1351061 Z M12,24 C5.372583,24 0,18.627417 0,12 C0,5.372583 5.372583,0 12,0 C18.627417,0 24,5.372583 24,12 C24,18.627417 18.627417,24 12,24 Z M12,13 C9.790861,13 8,11.209139 8,9 C8,6.790861 9.790861,5 12,5 C14.209139,5 16,6.790861 16,9 C16,11.209139 14.209139,13 12,13 Z"
fill="currentColor"
/>
</svg>
</span>
edX
<svg
aria-hidden={true}
focusable="false"
height="16px"
role="img"
version="1.1"
viewBox="0 0 16 16"
width="16px"
>
<path
d="M7,4 L7,8 L11,8 L11,10 L5,10 L5,4 L7,4 Z"
fill="currentColor"
transform="translate(8.000000, 7.000000) rotate(-45.000000) translate(-8.000000, -7.000000) "
/>
</svg>
</button>
</div>
</nav>
</div>
</div>
</header>
`;
exports[`<StudioHeader /> renders correctly with the optional app menu 1`] = `
<header
className="site-header-desktop"
>
<a
className="nav-skip sr-only sr-only-focusable"
href="#main"
>
Skip to main content
</a>
<div
className="container-fluid null"
>
<div
className="nav-container position-relative d-flex align-items-center"
>
<img
alt="edX"
className="logo"
src="https://edx-cdn.org/v3/default/logo.svg"
/>
<nav
aria-label="Main"
className="nav main-nav"
/>
<nav
aria-label="App"
className="nav app-nav"
>
<div
className="menu null"
onKeyDown={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
>
<a
aria-expanded={false}
aria-haspopup="menu"
className="menu-trigger nav-link d-inline-flex align-items-center"
onClick={[Function]}
>
App Menu
<svg
aria-hidden={true}
focusable="false"
height="16px"
role="img"
version="1.1"
viewBox="0 0 16 16"
width="16px"
>
<path
d="M7,4 L7,8 L11,8 L11,10 L5,10 L5,4 L7,4 Z"
fill="currentColor"
transform="translate(8.000000, 7.000000) rotate(-45.000000) translate(-8.000000, -7.000000) "
/>
</svg>
</a>
</div>
</nav>
<nav
aria-label="Secondary"
className="nav secondary-menu-container align-items-center ml-auto"
>
<div
className="menu null"
onKeyDown={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
>
<button
aria-expanded={false}
aria-haspopup="menu"
aria-label="Account menu for edX"
className="menu-trigger btn btn-outline-primary d-inline-flex align-items-center pl-2 pr-3"
onClick={[Function]}
>
<span
className="avatar overflow-hidden d-inline-flex rounded-circle mr-2"
style={
Object {
"height": "1.5em",
"width": "1.5em",
}
}
>
<svg
aria-hidden={true}
focusable="false"
height="24px"
role="img"
style={
Object {
"height": "1.5em",
"width": "1.5em",
}
}
version="1.1"
viewBox="0 0 24 24"
width="24px"
>
<path
d="M4.10255106,18.1351061 C4.7170266,16.0581859 8.01891846,14.4720277 12,14.4720277 C15.9810815,14.4720277 19.2829734,16.0581859 19.8974489,18.1351061 C21.215206,16.4412566 22,14.3122775 22,12 C22,6.4771525 17.5228475,2 12,2 C6.4771525,2 2,6.4771525 2,12 C2,14.3122775 2.78479405,16.4412566 4.10255106,18.1351061 Z M12,24 C5.372583,24 0,18.627417 0,12 C0,5.372583 5.372583,0 12,0 C18.627417,0 24,5.372583 24,12 C24,18.627417 18.627417,24 12,24 Z M12,13 C9.790861,13 8,11.209139 8,9 C8,6.790861 9.790861,5 12,5 C14.209139,5 16,6.790861 16,9 C16,11.209139 14.209139,13 12,13 Z"
fill="currentColor"
/>
</svg>
</span>
edX
<svg
aria-hidden={true}
focusable="false"
height="16px"
role="img"
version="1.1"
viewBox="0 0 16 16"
width="16px"
>
<path
d="M7,4 L7,8 L11,8 L11,10 L5,10 L5,4 L7,4 Z"
fill="currentColor"
transform="translate(8.000000, 7.000000) rotate(-45.000000) translate(-8.000000, -7.000000) "
/>
</svg>
</button>
</div>
</nav>
</div>
</div>
</header>
`;
exports[`<StudioHeader /> renders correctly with the optional main menu 1`] = `
<header
className="site-header-desktop"
>
<a
className="nav-skip sr-only sr-only-focusable"
href="#main"
>
Skip to main content
</a>
<div
className="container-fluid null"
>
<div
className="nav-container position-relative d-flex align-items-center"
>
<img
alt="edX"
className="logo"
src="https://edx-cdn.org/v3/default/logo.svg"
/>
<nav
aria-label="Main"
className="nav main-nav"
>
<div
className="menu nav-item"
onKeyDown={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
>
<a
aria-expanded={false}
aria-haspopup="menu"
className="menu-trigger nav-link d-inline-flex align-items-center"
href="https://menu-href-url.org"
onClick={[Function]}
>
Content 1
<svg
aria-hidden={true}
focusable="false"
height="16px"
role="img"
version="1.1"
viewBox="0 0 16 16"
width="16px"
>
<path
d="M7,4 L7,8 L11,8 L11,10 L5,10 L5,4 L7,4 Z"
fill="currentColor"
transform="translate(8.000000, 7.000000) rotate(-45.000000) translate(-8.000000, -7.000000) "
/>
</svg>
</a>
</div>
<div
className="menu nav-item"
onKeyDown={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
>
<a
aria-expanded={false}
aria-haspopup="menu"
className="menu-trigger nav-link d-inline-flex align-items-center"
href="https://menu-href-url.org"
onClick={[Function]}
>
Content 2
<svg
aria-hidden={true}
focusable="false"
height="16px"
role="img"
version="1.1"
viewBox="0 0 16 16"
width="16px"
>
<path
d="M7,4 L7,8 L11,8 L11,10 L5,10 L5,4 L7,4 Z"
fill="currentColor"
transform="translate(8.000000, 7.000000) rotate(-45.000000) translate(-8.000000, -7.000000) "
/>
</svg>
</a>
</div>
<div
className="menu nav-item"
onKeyDown={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
>
<a
aria-expanded={false}
aria-haspopup="menu"
className="menu-trigger nav-link d-inline-flex align-items-center"
href="https://menu-href-url.org"
onClick={[Function]}
>
Content 3
<svg
aria-hidden={true}
focusable="false"
height="16px"
role="img"
version="1.1"
viewBox="0 0 16 16"
width="16px"
>
<path
d="M7,4 L7,8 L11,8 L11,10 L5,10 L5,4 L7,4 Z"
fill="currentColor"
transform="translate(8.000000, 7.000000) rotate(-45.000000) translate(-8.000000, -7.000000) "
/>
</svg>
</a>
</div>
</nav>
<nav
aria-label="Secondary"
className="nav secondary-menu-container align-items-center ml-auto"
>
<div
className="menu null"
onKeyDown={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
>
<button
aria-expanded={false}
aria-haspopup="menu"
aria-label="Account menu for edX"
className="menu-trigger btn btn-outline-primary d-inline-flex align-items-center pl-2 pr-3"
onClick={[Function]}
>
<span
className="avatar overflow-hidden d-inline-flex rounded-circle mr-2"
style={
Object {
"height": "1.5em",
"width": "1.5em",
}
}
>
<svg
aria-hidden={true}
focusable="false"
height="24px"
role="img"
style={
Object {
"height": "1.5em",
"width": "1.5em",
}
}
version="1.1"
viewBox="0 0 24 24"
width="24px"
>
<path
d="M4.10255106,18.1351061 C4.7170266,16.0581859 8.01891846,14.4720277 12,14.4720277 C15.9810815,14.4720277 19.2829734,16.0581859 19.8974489,18.1351061 C21.215206,16.4412566 22,14.3122775 22,12 C22,6.4771525 17.5228475,2 12,2 C6.4771525,2 2,6.4771525 2,12 C2,14.3122775 2.78479405,16.4412566 4.10255106,18.1351061 Z M12,24 C5.372583,24 0,18.627417 0,12 C0,5.372583 5.372583,0 12,0 C18.627417,0 24,5.372583 24,12 C24,18.627417 18.627417,24 12,24 Z M12,13 C9.790861,13 8,11.209139 8,9 C8,6.790861 9.790861,5 12,5 C14.209139,5 16,6.790861 16,9 C16,11.209139 14.209139,13 12,13 Z"
fill="currentColor"
/>
</svg>
</span>
edX
<svg
aria-hidden={true}
focusable="false"
height="16px"
role="img"
version="1.1"
viewBox="0 0 16 16"
width="16px"
>
<path
d="M7,4 L7,8 L11,8 L11,10 L5,10 L5,4 L7,4 Z"
fill="currentColor"
transform="translate(8.000000, 7.000000) rotate(-45.000000) translate(-8.000000, -7.000000) "
/>
</svg>
</button>
</div>
</nav>
</div>
</div>
</header>
`;

View File

@@ -1,30 +1,30 @@
{ {
"general.register.sentenceCase": "Register", "general.register.sentenceCase": "التسجيل",
"general.signIn.sentenceCase": "Sign in", "general.signIn.sentenceCase": "تسجيل الدخول",
"header.links.courses": "Courses", "header.links.courses": "مساقات",
"header.links.programs": "Programs", "header.links.programs": "برامج",
"header.links.content.search": "Discover New", "header.links.content.search": "استكشف الجديد",
"header.links.schools": "Schools & Partners", "header.links.schools": "المدارس والشركاء",
"header.user.menu.dashboard": "Dashboard", "header.user.menu.dashboard": "لوحة المعلومات",
"header.user.menu.profile": "Profile", "header.user.menu.profile": "الملف الشخصي",
"header.user.menu.account.settings": "Account", "header.user.menu.account.settings": "حساب",
"header.user.menu.order.history": "Order History", "header.user.menu.order.history": "سجل الطلبات",
"header.user.menu.logout": "Logout", "header.user.menu.logout": "تسجيل الخروج",
"header.user.menu.login": "Login", "header.user.menu.login": "تسجيل الدخول",
"header.user.menu.register": "Sign Up", "header.user.menu.register": "تسجيل ",
"header.label.account.nav": "Account", "header.label.account.nav": "حساب",
"header.label.account.menu": "Account Menu", "header.label.account.menu": "قائمة الحساب",
"header.label.account.menu.for": "Account menu for {username}", "header.label.account.menu.for": "قائمة الحساب للمستخدم {username}",
"header.label.main.nav": "Main", "header.label.main.nav": "الرئيسية",
"header.label.main.menu": "Main Menu", "header.label.main.menu": "القائمة الرئيسية",
"header.label.main.header": "Main", "header.label.main.header": "الرئيسية",
"header.label.secondary.nav": "Secondary", "header.label.secondary.nav": "فرعي",
"header.label.skip.nav": "Skip to main content", "header.label.skip.nav": "التخطي إلى المحتوى الرئيسي",
"header.menu.dashboard.label": "Dashboard", "header.menu.dashboard.label": "لوحة المعلومات",
"header.help.label": "Help", "header.help.label": "مساعدة",
"header.menu.profile.label": "Profile", "header.menu.profile.label": "الملف الشخصي",
"header.menu.account.label": "Account", "header.menu.account.label": "حساب",
"header.menu.orderHistory.label": "Order History", "header.menu.orderHistory.label": "سجل الطلبات",
"header.navigation.skipNavLink": "Skip to main content.", "header.navigation.skipNavLink": "التخطي إلى المحتوى الرئيسي",
"header.menu.signOut.label": "Sign Out" "header.menu.signOut.label": "تسجيل الخروج"
} }

View File

@@ -1,30 +1,30 @@
{ {
"general.register.sentenceCase": "Register", "general.register.sentenceCase": "Registrarse",
"general.signIn.sentenceCase": "Sign in", "general.signIn.sentenceCase": "Iniciar sesión",
"header.links.courses": "Courses", "header.links.courses": "Cursos",
"header.links.programs": "Programs", "header.links.programs": "Programas",
"header.links.content.search": "Discover New", "header.links.content.search": "Encontrar nuevo",
"header.links.schools": "Schools & Partners", "header.links.schools": "Escuelas y Socios",
"header.user.menu.dashboard": "Dashboard", "header.user.menu.dashboard": "Panel de Control",
"header.user.menu.profile": "Profile", "header.user.menu.profile": "Perfil",
"header.user.menu.account.settings": "Account", "header.user.menu.account.settings": "Cuenta",
"header.user.menu.order.history": "Order History", "header.user.menu.order.history": "Historial de órdenes",
"header.user.menu.logout": "Logout", "header.user.menu.logout": "Cerrar sesión",
"header.user.menu.login": "Login", "header.user.menu.login": "Login",
"header.user.menu.register": "Sign Up", "header.user.menu.register": "Registrarse",
"header.label.account.nav": "Account", "header.label.account.nav": "Cuenta",
"header.label.account.menu": "Account Menu", "header.label.account.menu": "Menú de la cuenta",
"header.label.account.menu.for": "Account menu for {username}", "header.label.account.menu.for": "Menú de la cuenta para {username}",
"header.label.main.nav": "Main", "header.label.main.nav": "Principal",
"header.label.main.menu": "Main Menu", "header.label.main.menu": "Menú Principal",
"header.label.main.header": "Main", "header.label.main.header": "Principal",
"header.label.secondary.nav": "Secondary", "header.label.secondary.nav": "Secondary",
"header.label.skip.nav": "Skip to main content", "header.label.skip.nav": "Ir al contenido principal",
"header.menu.dashboard.label": "Dashboard", "header.menu.dashboard.label": "Panel de Control",
"header.help.label": "Help", "header.help.label": "Ayuda",
"header.menu.profile.label": "Profile", "header.menu.profile.label": "Perfil",
"header.menu.account.label": "Account", "header.menu.account.label": "Cuenta",
"header.menu.orderHistory.label": "Order History", "header.menu.orderHistory.label": "Historial de órdenes",
"header.navigation.skipNavLink": "Skip to main content.", "header.navigation.skipNavLink": "Dirígete al contenido principal.",
"header.menu.signOut.label": "Sign Out" "header.menu.signOut.label": "Cerrar sesión"
} }

View File

@@ -1,30 +1,30 @@
{ {
"general.register.sentenceCase": "Register", "general.register.sentenceCase": "S'inscrire",
"general.signIn.sentenceCase": "Sign in", "general.signIn.sentenceCase": "Connectez-vous",
"header.links.courses": "Courses", "header.links.courses": "Cours",
"header.links.programs": "Programs", "header.links.programs": "Programmes",
"header.links.content.search": "Discover New", "header.links.content.search": "Explorer les cours",
"header.links.schools": "Schools & Partners", "header.links.schools": "Écoles et partenaires",
"header.user.menu.dashboard": "Dashboard", "header.user.menu.dashboard": "Tableau de bord",
"header.user.menu.profile": "Profile", "header.user.menu.profile": "Profil",
"header.user.menu.account.settings": "Account", "header.user.menu.account.settings": "Compte",
"header.user.menu.order.history": "Order History", "header.user.menu.order.history": "Historique des commandes",
"header.user.menu.logout": "Logout", "header.user.menu.logout": "Déconnexion",
"header.user.menu.login": "Login", "header.user.menu.login": "Connexion",
"header.user.menu.register": "Sign Up", "header.user.menu.register": "S'inscrire",
"header.label.account.nav": "Account", "header.label.account.nav": "Compte",
"header.label.account.menu": "Account Menu", "header.label.account.menu": "Menu du compte",
"header.label.account.menu.for": "Account menu for {username}", "header.label.account.menu.for": "Menu du compte pour {username}",
"header.label.main.nav": "Main", "header.label.main.nav": "Principal",
"header.label.main.menu": "Main Menu", "header.label.main.menu": "Menu Principal",
"header.label.main.header": "Main", "header.label.main.header": "Principal",
"header.label.secondary.nav": "Secondary", "header.label.secondary.nav": "Secondaire",
"header.label.skip.nav": "Skip to main content", "header.label.skip.nav": "Passer au contenu principal",
"header.menu.dashboard.label": "Dashboard", "header.menu.dashboard.label": "Tableau de bord",
"header.help.label": "Help", "header.help.label": "Aide",
"header.menu.profile.label": "Profile", "header.menu.profile.label": "Profil",
"header.menu.account.label": "Account", "header.menu.account.label": "Compte",
"header.menu.orderHistory.label": "Order History", "header.menu.orderHistory.label": "Historique des commandes",
"header.navigation.skipNavLink": "Skip to main content.", "header.navigation.skipNavLink": "Passer au contenu principal",
"header.menu.signOut.label": "Sign Out" "header.menu.signOut.label": "Se déconnecter"
} }

View File

@@ -0,0 +1,30 @@
{
"general.register.sentenceCase": "Inscription",
"general.signIn.sentenceCase": "Connexion",
"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.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.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"
}

View File

@@ -1,7 +1,8 @@
import Header from './Header'; import Header from './Header';
import LearningHeader from './learning-header/LearningHeader'; import LearningHeader from './learning-header/LearningHeader';
import messages from './i18n/index'; import messages from './i18n/index';
import StudioHeader from './StudioHeader';
export { LearningHeader, messages }; export { LearningHeader, messages, StudioHeader };
export default Header; export default Header;