Compare commits

...

47 Commits

Author SHA1 Message Date
Sarina Canelake
d529e00d7b Merge pull request #257 from openedx/tcril/fix-gh-org-url
Fix github url strings (org edx -> openedx)
2022-09-13 22:21:04 -04:00
renovate[bot]
e0cbbf7da1 chore(deps): update dependency @testing-library/dom to v8.17.1 2022-09-12 11:50:01 +00:00
Sarina Canelake
ba209fd050 fix: update path to .github workflows to read from openedx org 2022-09-10 18:07:21 -04:00
Sarina Canelake
ae7004e95d fix: fix github url strings (org edx -> openedx) 2022-09-07 09:02:25 -04:00
renovate[bot]
bf64a829cc chore(deps): update dependency @edx/frontend-platform to v2.6.2 2022-09-05 13:45:11 +00:00
renovate[bot]
1e1b06dfa5 chore(deps): update dependency @edx/frontend-platform to v2.6.1 2022-08-29 12:34:32 +00:00
renovate[bot]
469a93bd9c chore(deps): update dependency @testing-library/jest-dom to v5.16.5 2022-08-22 11:06:32 +00:00
Muhammad Abdullah Waheed
0645761f05 Merge pull request #250 from openedx/abdullahwaheed/run-build-in-ci
`npm run build` script in Github CI
2022-08-16 11:20:25 +05:00
renovate[bot]
20e9881546 chore(deps): update dependency @edx/frontend-platform to v2.5.2 2022-08-15 10:43:52 +00:00
Abdullah Waheed
42b347058f feat: added build script in github CI 2022-08-15 10:30:48 +05:00
renovate[bot]
b097535580 chore(deps): update dependency @edx/frontend-platform to v2.5.1 2022-08-08 12:39:35 +00:00
edx-semantic-release
d06929ca2b chore(i18n): update translations 2022-08-07 16:29:27 -04:00
renovate[bot]
0a9316c407 fix(deps): update dependency react-transition-group to v4.4.5 2022-08-02 00:28:16 +00:00
Kira Miller
d7704799fe Merge pull request #246 from openedx/kiram15/ENT-6064
chore: updating paragon dependecy
2022-08-01 15:18:47 -04:00
Kira
cc26f750e8 chore: updating paragon dependecy 2022-08-01 13:32:03 -04:00
renovate[bot]
8ac22515a6 chore(deps): update dependency @edx/frontend-platform to v2.5.0 2022-07-25 10:44:21 +00:00
renovate[bot]
b4a8d0afdc chore(deps): update dependency jest to v28.1.3 2022-07-18 12:07:45 +00:00
renovate[bot]
c131842139 chore(deps): update dependency @testing-library/dom to v8.16.0 2022-07-11 13:44:17 +00:00
renovate[bot]
acf5398b31 chore(deps): update dependency jest to v28 2022-07-04 12:55:37 +00:00
renovate[bot]
871e35d53a fix(deps): update dependency @fortawesome/react-fontawesome to ^0.2.0 2022-07-04 06:26:38 +00:00
connorhaugh
c8fb2ded56 Merge pull request #233 from openedx/feat--upgrade-frontend-build-
feat: upgrade frontend-build
2022-06-30 10:28:14 -04:00
connorhaugh
01ffe0b945 feat: upgrade frontend-build 2022-06-30 10:23:35 -04:00
connorhaugh
092c61dada Merge pull request #225 from openedx/renovate/edx-frontend-platform-2.x
chore(deps): update dependency @edx/frontend-platform to v2
2022-06-30 10:11:50 -04:00
renovate[bot]
cc43299932 chore(deps): update dependency @edx/frontend-platform to v2 2022-06-28 18:08:29 +00:00
renovate[bot]
9086b96313 chore(deps): update dependency @testing-library/dom to v8.14.0 2022-06-27 12:17:35 +00:00
renovate[bot]
86b9d4a061 chore(deps): update dependency @edx/paragon to v19.25.3 2022-06-20 12:10:31 +00:00
Renovate Bot
36fd9cb89a chore(deps): update dependency @testing-library/dom to v8 2022-06-13 14:57:57 +00:00
Renovate Bot
5aec913cd6 chore(deps): update dependency @edx/paragon to v19.25.1 2022-06-06 06:59:04 +00:00
Renovate Bot
5da9cc3ce4 chore(deps): update dependency @edx/paragon to v19.25.0 2022-05-30 10:10:04 +00:00
Renovate Bot
97e8c69345 chore(deps): update dependency @edx/paragon to v19.23.1 2022-05-23 13:08:03 +00:00
Renovate Bot
a410ec8ed6 chore(deps): update dependency react-router-dom to v5.3.3 2022-05-23 10:58:27 +00:00
Renovate Bot
7e197e2315 chore(deps): update dependency @edx/frontend-platform to v1.15.6 2022-05-16 19:03:38 +00:00
edX requirements bot
6373bc726f chore!: Dropped support for Node 12 (#216)
BREAKING CHANGE: Dropped support for Node 12
2022-05-16 20:57:50 +05:00
Renovate Bot
1ccf3214f0 chore(deps): update dependency @edx/paragon to v19.22.1 2022-05-16 10:16:14 +00:00
edx-semantic-release
137701d10c chore(i18n): update translations 2022-05-12 16:05:09 -04:00
Tim McCormack
37d39dba95 fix: Fix pull_translations by using correct CLI flag for language filter (#214)
Docs: https://developers.transifex.com/docs/using-the-client
2022-05-12 19:57:30 +00:00
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
20 changed files with 5630 additions and 3917 deletions

View File

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

View File

@@ -2,16 +2,16 @@ name: Default CI
on:
push:
branches:
- 'master'
- master
pull_request:
branches:
- '**'
- '**'
jobs:
tests:
runs-on: ubuntu-latest
strategy:
matrix:
node: [12, 14, 16]
node: [16]
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -29,6 +29,8 @@ jobs:
run: npm run lint
- name: Test
run: npm run test
- name: Build
run: npm run build
- name: i18n_extract
run: npm run i18n_extract
- name: Coverage

View File

@@ -7,4 +7,4 @@ on:
jobs:
commitlint:
uses: edx/.github/.github/workflows/commitlint.yml@master
uses: openedx/.github/.github/workflows/commitlint.yml@master

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

@@ -2,38 +2,38 @@ name: Release CI
on:
push:
branches:
- master
- master
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 12
- name: Install dependencies
run: npm ci
- name: Validate package-lock.json changes
run: make validate-no-uncommitted-package-lock-changes
- name: Lint
run: npm run lint
- name: Test
run: npm run test
- name: i18n_extract
run: npm run i18n_extract
- name: Coverage
uses: codecov/codecov-action@v2
- name: Build
run: npm run build
- name: Release
uses: cycjimmy/semantic-release-action@v2
with:
semantic_version: 16
env:
GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_NPM_TOKEN }}
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 16
- name: Install dependencies
run: npm ci
- name: Validate package-lock.json changes
run: make validate-no-uncommitted-package-lock-changes
- name: Lint
run: npm run lint
- name: Test
run: npm run test
- name: i18n_extract
run: npm run i18n_extract
- name: Coverage
uses: codecov/codecov-action@v2
- name: Build
run: npm run build
- name: Release
uses: cycjimmy/semantic-release-action@v2
with:
semantic_version: 16
env:
GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_NPM_TOKEN }}

View File

@@ -50,7 +50,7 @@ push_translations:
# Pulls translations from Transifex.
pull_translations:
tx pull -f --mode reviewed --language=$(transifex_langs)
tx pull -f --mode reviewed --languages=$(transifex_langs)
# This target is used by Travis.
validate-no-uncommitted-package-lock-changes:

View File

@@ -14,7 +14,7 @@ A generic header for Open edX micro-frontend applications.
Requirements
************
This component uses ``@edx/frontend-platform`` services such as i18n, analytics, configuration, and the ``AppContext`` React component, and expects that it has been loaded into a micro-frontend that has been properly initialized via ``@edx/frontend-platform``'s ``initialize`` function. `Please visit the frontend template application to see an example. <https://github.com/edx/frontend-template-application/blob/master/src/index.jsx>`_
This component uses ``@edx/frontend-platform`` services such as i18n, analytics, configuration, and the ``AppContext`` React component, and expects that it has been loaded into a micro-frontend that has been properly initialized via ``@edx/frontend-platform``'s ``initialize`` function. `Please visit the frontend template application to see an example. <https://github.com/openedx/frontend-template-application/blob/master/src/index.jsx>`_
Environment Variables
=====================
@@ -53,8 +53,8 @@ This library has the following exports:
Examples
========
* `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 component and messages usage. <https://github.com/openedx/frontend-template-application/blob/3355bb3a96232390e9056f35b06ffa8f105ed7ca/src/index.jsx#L21>`_
* `An example of SCSS file usage. <https://github.com/openedx/frontend-template-application/blob/3cd5485bf387b8c479baf6b02bf59e3061dc3465/src/index.scss#L8>`_
***********

8688
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -24,19 +24,19 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/edx/frontend-component-header.git"
"url": "git+https://github.com/openedx/frontend-component-header.git"
},
"author": "edX",
"license": "AGPL-3.0",
"bugs": {
"url": "https://github.com/edx/frontend-component-header/issues"
"url": "https://github.com/openedx/frontend-component-header/issues"
},
"homepage": "https://github.com/edx/frontend-component-header#readme",
"homepage": "https://github.com/openedx/frontend-component-header#readme",
"devDependencies": {
"@edx/brand": "npm:@edx/brand-openedx@1.1.0",
"@edx/frontend-build": "9.1.1",
"@edx/frontend-platform": "1.15.1",
"@edx/paragon": "19.6.0",
"@edx/frontend-build": "11.0.2",
"@edx/frontend-platform": "2.6.2",
"@edx/paragon": "19.25.3",
"codecov": "3.8.3",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.6",
@@ -44,31 +44,31 @@
"prop-types": "15.8.1",
"react": "16.14.0",
"react-dom": "16.14.0",
"react-redux": "7.2.6",
"react-router-dom": "5.3.0",
"react-redux": "7.2.8",
"react-router-dom": "5.3.3",
"react-test-renderer": "16.14.0",
"reactifex": "1.1.1",
"redux": "4.1.2",
"redux": "4.2.0",
"redux-saga": "1.1.3",
"@testing-library/dom": "7.31.2",
"@testing-library/jest-dom": "5.16.2",
"jest": "27.5.0",
"@testing-library/dom": "8.17.1",
"@testing-library/jest-dom": "5.16.5",
"jest": "28.1.3",
"jest-chain": "1.1.5",
"@testing-library/react": "10.4.9"
},
"dependencies": {
"babel-polyfill": "6.26.0",
"react-responsive": "8.2.0",
"react-transition-group": "4.4.2",
"react-transition-group": "4.4.5",
"@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"
"@fortawesome/react-fontawesome": "^0.2.0"
},
"peerDependencies": {
"@edx/frontend-platform": "^1.8.0",
"@edx/paragon": ">= 7.0.0 < 20.0.0",
"@edx/frontend-platform": "^2.0.0",
"@edx/paragon": ">= 7.0.0 < 21.0.0",
"prop-types": "^15.5.10",
"react": "^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() {
const {
userMenu,
@@ -102,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;
@@ -118,6 +137,14 @@ 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"
@@ -155,6 +182,20 @@ 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 = {
@@ -167,6 +208,7 @@ DesktopHeader.defaultProps = {
avatar: null,
username: null,
loggedIn: false,
appMenu: null,
};
export default injectIntl(DesktopHeader);

View File

@@ -56,6 +56,16 @@ const messages = defineMessages({
defaultMessage: 'Sign Up',
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': {
id: 'header.label.account.nav',
defaultMessage: 'Account',
@@ -96,6 +106,11 @@ const messages = defineMessages({
defaultMessage: 'Skip to main content',
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;

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

@@ -12,6 +12,8 @@
"header.user.menu.logout": "تسجيل الخروج",
"header.user.menu.login": "تسجيل الدخول",
"header.user.menu.register": "تسجيل ",
"header.user.menu.studio.home": "Studio Home",
"header.user.menu.studio.maintenance": "Maintenance",
"header.label.account.nav": "حساب",
"header.label.account.menu": "قائمة الحساب",
"header.label.account.menu.for": "قائمة الحساب للمستخدم {username}",
@@ -20,6 +22,7 @@
"header.label.main.header": "الرئيسية",
"header.label.secondary.nav": "فرعي",
"header.label.skip.nav": "التخطي إلى المحتوى الرئيسي",
"header.label.app.nav": "App",
"header.menu.dashboard.label": "لوحة المعلومات",
"header.help.label": "مساعدة",
"header.menu.profile.label": "الملف الشخصي",

View File

@@ -12,6 +12,8 @@
"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}",
@@ -20,6 +22,7 @@
"header.label.main.header": "Principal",
"header.label.secondary.nav": "Secondary",
"header.label.skip.nav": "Ir al contenido principal",
"header.label.app.nav": "Aplicación",
"header.menu.dashboard.label": "Panel de Control",
"header.help.label": "Ayuda",
"header.menu.profile.label": "Perfil",

View File

@@ -12,6 +12,8 @@
"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}",
@@ -20,6 +22,7 @@
"header.label.main.header": "Principal",
"header.label.secondary.nav": "Secondaire",
"header.label.skip.nav": "Passer au contenu principal",
"header.label.app.nav": "Application",
"header.menu.dashboard.label": "Tableau de bord",
"header.help.label": "Aide",
"header.menu.profile.label": "Profil",

View File

@@ -12,6 +12,8 @@
"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}",
@@ -20,6 +22,7 @@
"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",
"header.menu.dashboard.label": "Tableau de bord",
"header.help.label": "Aide",
"header.menu.profile.label": "Profil",

View File

@@ -12,6 +12,8 @@
"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}",
@@ -20,6 +22,7 @@
"header.label.main.header": "Main",
"header.label.secondary.nav": "Secondary",
"header.label.skip.nav": "Skip to main content",
"header.label.app.nav": "App",
"header.menu.dashboard.label": "Dashboard",
"header.help.label": "Help",
"header.menu.profile.label": "Profile",

View File

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