Compare commits

..

76 Commits

Author SHA1 Message Date
Bilal Qamar
25054162ec Merge branch 'master' of https://github.com/openedx/frontend-component-header into maman/codecov-update 2022-08-30 12:25:17 +05: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
maman
90f1ada9f3 fix: removed derpeciated package codecov 2022-06-20 09:03:39 +05: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
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
Bianca Severino
abe0bbbf51 Merge pull request #158 from edx/bseverino/paragon-dependency
fix: update peer dependency of paragon
2021-12-09 11:55:20 -05:00
Bianca Severino
c6e971ef1d fix: update peer dependency of paragon 2021-12-09 11:48:34 -05:00
edX Transifex Bot
2f0a07b7eb chore(i18n): update translations 2021-12-08 22:22:31 +05:00
renovate[bot]
56593df3bd chore(deps): update dependency @testing-library/dom to v7.31.2 (#155)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-12-06 10:45:58 +00:00
22 changed files with 38596 additions and 10231 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

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
on: [push, pull_request]
on:
push:
branches:
- master
pull_request:
branches:
- '**'
jobs:
build:
tests:
runs-on: ubuntu-latest
strategy:
matrix:
node: [16]
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -11,7 +20,7 @@ jobs:
- name: Setup Nodejs
uses: actions/setup-node@v2
with:
node-version: 12
node-version: ${{ matrix.node }}
- name: Install dependencies
run: npm ci
- name: Validate package-lock.json changes
@@ -20,7 +29,9 @@ 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
uses: codecov/codecov-action@v2
uses: codecov/codecov-action@v3

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@v3
- 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

@@ -1,8 +1,9 @@
[main]
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
source_file = src/i18n/transifex_input.json
source_lang = en
type = KEYVALUEJSON
type = KEYVALUEJSON

View File

@@ -1,5 +1,5 @@
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
i18n = ./src/i18n
@@ -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

@@ -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 SCSS file usage. <https://github.com/edx/frontend-template-application/blob/3cd5485bf387b8c479baf6b02bf59e3061dc3465/src/index.scss#L8>`_
***********
Development
***********

47787
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -34,41 +34,43 @@
"homepage": "https://github.com/edx/frontend-component-header#readme",
"devDependencies": {
"@edx/brand": "npm:@edx/brand-openedx@1.1.0",
"@edx/frontend-build": "5.6.14",
"@edx/frontend-platform": "1.14.1",
"@edx/paragon": "12.8.0",
"@edx/frontend-build": "11.0.2",
"@edx/frontend-platform": "2.6.1",
"@edx/paragon": "19.25.3",
"codecov": "3.8.3",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.6",
"husky": "7.0.4",
"prop-types": "15.7.2",
"jest": "27.5.1",
"jest-chain": "1.1.5",
"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.16.3",
"@testing-library/jest-dom": "5.15.1",
"jest": "27.3.1",
"@testing-library/dom": "8.16.0",
"@testing-library/jest-dom": "5.16.5",
"jest": "28.1.3",
"jest-chain": "1.1.5",
"@testing-library/react": "10.3.0"
"@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",
"@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

@@ -1,2 +1,33 @@
{
}
"general.register.sentenceCase": "التسجيل",
"general.signIn.sentenceCase": "تسجيل الدخول",
"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": "Studio Home",
"header.user.menu.studio.maintenance": "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": "App",
"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": "تسجيل الخروج"
}

View File

@@ -1,2 +1,33 @@
{
}
"general.register.sentenceCase": "Registrarse",
"general.signIn.sentenceCase": "Iniciar sesión",
"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",
"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"
}

View File

@@ -1,2 +1,33 @@
{
}
"general.register.sentenceCase": "S'inscrire",
"general.signIn.sentenceCase": "Connectez-vous",
"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",
"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

@@ -0,0 +1,33 @@
{
"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.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",
"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,2 +1,33 @@
{
}
"general.register.sentenceCase": "Register",
"general.signIn.sentenceCase": "Sign in",
"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",
"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"
}

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;