Compare commits

..

149 Commits

Author SHA1 Message Date
renovate[bot]
01405eaff9 fix(deps): update dependency @edx/paragon to v20.30.1 2023-04-10 14:48:47 +00:00
renovate[bot]
59fa6e2a35 chore(deps): update dependency @edx/frontend-build to v12.8.6 2023-04-10 11:18:27 +00:00
Mashal Malik
9fc3a0e835 refactor: update peer dependency for react and react-dom (#326)
* refactor: remove react16 from peer dependency

* build: update lock file

* fix: fix lint issue

* refactor: add 17 support of react in peerDep
2023-04-05 16:47:15 +05:00
renovate[bot]
22e157adf6 fix(deps): update dependency @edx/paragon to v20.29.0 2023-04-03 12:46:02 +00:00
renovate[bot]
6b81f69eba chore(deps): update dependency @testing-library/dom to v9.2.0 2023-04-03 10:35:08 +00:00
Bilal Qamar
cefa84006c fix: reverted semantic release to v16 (#321) 2023-03-30 11:04:45 +05:00
Muhammad Abdullah Waheed
a54309dd63 fix: updated version of semantic-release-action (#322) 2023-03-29 23:33:58 +05:00
Bilal Qamar
aeb0fd2be7 feat: upgraded to node v18, added .nvmrc and updated workflows (#314)
* feat: upgraded to node v18, added .nvmrc and updated workflows

* refactor: upgraded frontend-build & frontend-platform, updated workflows

* refactor: moved platform from devDependencies
2023-03-29 16:44:29 +05:00
renovate[bot]
26eb2bb4c7 chore(deps): update dependency @edx/frontend-platform to v3.6.0 2023-03-27 10:18:25 +00:00
renovate[bot]
8083079954 chore(deps): update dependency @edx/frontend-build to v12.7.0 2023-03-27 10:15:17 +00:00
renovate[bot]
d4fc8489ea fix(deps): update dependency @edx/paragon to v20.28.5 2023-03-20 11:56:19 +00:00
renovate[bot]
4020a81bd4 chore(deps): update dependency redux-saga to v1.2.3 2023-03-20 11:53:34 +00:00
renovate[bot]
acf1adba80 chore(deps): update dependency jest to v29.5.0 2023-03-13 09:54:48 +00:00
renovate[bot]
a204ff8c03 chore(deps): update dependency @testing-library/dom to v9.0.1 2023-03-13 09:47:40 +00:00
Mashal Malik
e8ccc4b707 chore: Update transifex api from v2 to v3 (#310)
* chore: Update transifex api from v2 to v3

* refactor: remove duplicate line
2023-03-06 17:58:12 +05:00
renovate[bot]
4d86780c73 chore(deps): update dependency @testing-library/dom to v9 2023-02-27 11:44:52 +00:00
renovate[bot]
fdbb83f51e fix(deps): update font awesome to v6.3.0 2023-02-27 11:38:21 +00:00
Feanil Patel
f6e4664d37 Merge pull request #304 from openedx/repo_checks/ensure_workflows
Update standard workflow files.
2023-02-24 11:45:23 -05:00
Feanil Patel
65177fcdcc build: Updating a missing workflow file add-depr-ticket-to-depr-board.yml.
The .github/workflows/add-depr-ticket-to-depr-board.yml workflow is missing or needs an update to stay in
sync with the current standard for this workflow as defined in the
`.github` repo of the `openedx` GitHub org.
2023-02-23 13:57:40 -05:00
Feanil Patel
7601249fb6 build: Creating a missing workflow file add-remove-label-on-comment.yml.
The .github/workflows/add-remove-label-on-comment.yml workflow is missing or needs an update to stay in
sync with the current standard for this workflow as defined in the
`.github` repo of the `openedx` GitHub org.
2023-02-23 13:57:40 -05:00
Feanil Patel
c8ef3dad93 build: Creating a missing workflow file self-assign-issue.yml.
The .github/workflows/self-assign-issue.yml workflow is missing or needs an update to stay in
sync with the current standard for this workflow as defined in the
`.github` repo of the `openedx` GitHub org.
2023-02-23 13:57:39 -05:00
renovate[bot]
b02fe00c71 fix(deps): update dependency @edx/paragon to v20.28.4 2023-02-20 11:19:51 +00:00
renovate[bot]
4404aede33 chore(deps): update dependency jest to v29.4.3 2023-02-20 11:12:57 +00:00
renovate[bot]
1b0edb10c4 chore(deps): update dependency @testing-library/dom to v8.20.0 2023-02-13 12:12:41 +00:00
renovate[bot]
546adff45e chore(deps): update dependency @edx/brand to v1.2.0 2023-02-13 12:05:28 +00:00
renovate[bot]
94b14fd618 chore(deps): update dependency redux-saga to v1.2.2 2023-02-06 13:51:48 +00:00
renovate[bot]
5b8a9a587b chore(deps): update dependency redux to v4.2.1 2023-02-06 13:44:55 +00:00
renovate[bot]
2650cb59b3 chore(deps): update actions/setup-node action to v3 (#212)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-06 15:11:28 +05:00
renovate[bot]
bc2b13175a chore(deps): update dependency husky to v8 (#235)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-06 14:30:50 +05:00
renovate[bot]
85e8094833 fix(deps): update font awesome to v6 (#281)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-06 14:17:48 +05:00
dependabot[bot]
aff8dda3ee chore(deps): bump decode-uri-component from 0.2.0 to 0.2.2 (#287)
Bumps [decode-uri-component](https://github.com/SamVerschueren/decode-uri-component) from 0.2.0 to 0.2.2.
- [Release notes](https://github.com/SamVerschueren/decode-uri-component/releases)
- [Commits](https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.2)

---
updated-dependencies:
- dependency-name: decode-uri-component
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-01 17:15:00 +05:00
dependabot[bot]
51b505552d chore(deps): bump cookiejar from 2.1.3 to 2.1.4 (#296)
Bumps [cookiejar](https://github.com/bmeck/node-cookiejar) from 2.1.3 to 2.1.4.
- [Release notes](https://github.com/bmeck/node-cookiejar/releases)
- [Commits](https://github.com/bmeck/node-cookiejar/commits)

---
updated-dependencies:
- dependency-name: cookiejar
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-01 17:14:36 +05:00
dependabot[bot]
3648f1b6be build(deps): bump json5 from 1.0.1 to 1.0.2
Bumps [json5](https://github.com/json5/json5) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v1.0.1...v1.0.2)

---
updated-dependencies:
- dependency-name: json5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-30 14:12:31 +00:00
Bilal Qamar
c78b6964b9 chore: updated frontend-build version to v12.4.19 (#297) 2023-01-25 18:51:25 +05:00
renovate[bot]
664d05134b fix(deps): update dependency @edx/paragon to v20.27.0 2023-01-23 10:38:54 +00:00
renovate[bot]
b969522cd0 chore(deps): update dependency @edx/frontend-build to v12.4.16 2023-01-23 10:34:46 +00:00
renovate[bot]
0cd8210ea7 chore(deps): update dependency @testing-library/dom to v8.19.1 2023-01-16 10:17:13 +00:00
renovate[bot]
1c763c2102 chore(deps): update dependency @edx/frontend-build to v12.4.15 2023-01-09 09:27:54 +00:00
Mashal Malik
073003284a Moving code coverage from codecov package to CI (#289)
* fix: removed derpeciated package codecov

* fix: install edx/paragon 20.20.0 fixed version

* fix: specified paragron 20.20.0 version

Co-authored-by: Shahroz Ahmad <shahroz.ahmad@arbisoft.com>
2022-12-29 12:25:49 +05:00
Bilal Qamar
92fdf85c9a feat: paragon updated to v20 & frontend-build version updated
* feat: paragon updated to v20 & frontend-build version updated

* refactor: moved paragon from devDependencies to satisfy eslint rule

* refactor: updated snapshots
2022-12-09 15:57:09 +05:00
Sagirov Eugeniy
5ee8a8c75c feat: Account pages. Updated menu items urls. 2022-12-02 12:28:15 +00:00
Abdullah Waheed
536d67404f refactor: updated renovate config to auto update minor and patch versions of edx dependencies 2022-11-30 13:17:21 +00:00
Bilal Qamar
9d99bfcec6 refactor: updated snapshots 2022-11-25 16:53:50 +05:00
Bilal Qamar
3180c9d973 refactor: moved paragon from devDependencies to satisfy eslint rule 2022-11-25 16:48:29 +05:00
Bilal Qamar
1645274d9f feat: paragon updated to v20 & frontend-build version updated 2022-11-25 16:36:06 +05:00
Bilal Qamar
84e43cb038 refactor: bumped loader-utils 2022-11-25 16:26:11 +05:00
julianajlk
994b21c0c1 fix: Change frontend-platform peer dependency to v2 or v3 range 2022-11-14 20:19:37 +00:00
renovate[bot]
940b45ba7e chore(deps): update dependency jest to v29 2022-11-14 07:52:30 +00:00
dependabot[bot]
4efa0a07ae build(deps): bump loader-utils from 1.4.0 to 1.4.1 (#278)
Bumps [loader-utils](https://github.com/webpack/loader-utils) from 1.4.0 to 1.4.1.
- [Release notes](https://github.com/webpack/loader-utils/releases)
- [Changelog](https://github.com/webpack/loader-utils/blob/v1.4.1/CHANGELOG.md)
- [Commits](https://github.com/webpack/loader-utils/compare/v1.4.0...v1.4.1)

---
updated-dependencies:
- dependency-name: loader-utils
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-10 17:34:00 +05:00
renovate[bot]
2bd6879bda chore(deps): update actions/checkout action to v3 (#211)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-10 17:18:45 +05:00
Muhammad Abdullah Waheed
b479f0b376 Merge pull request #205 from openedx/dependabot/npm_and_yarn/async-2.6.4
build(deps): bump async from 2.6.3 to 2.6.4
2022-11-08 18:40:15 +05:00
Leangseu Kim
dfdcbc0a8d feat: upgrade frontend platform to version 3 2022-11-07 12:45:43 +00:00
renovate[bot]
c3b02a2946 chore(deps): update dependency enzyme-adapter-react-16 to v1.15.7 2022-11-07 09:36:45 +00:00
renovate[bot]
f6c1a8bcc1 chore(deps): update dependency redux-saga to v1.2.1 2022-10-31 07:42:11 +00:00
Bilal Qamar
6c02962e0d refactor: updated frontend-build & resolved eslint issues 2022-10-26 10:37:57 -03:00
renovate[bot]
acaf98f0b1 chore(deps): update dependency @testing-library/dom to v8.19.0 2022-10-24 08:15:34 +00:00
Adolfo R. Brandes
90351083aa Merge pull request #256 from openedx/abdullahwaheed/transifex-languages-list-update
Supported Transifex languages in Makefile
2022-10-20 16:15:57 -03:00
Adolfo R. Brandes
6f75684ad9 Merge pull request #271 from brian-smith-tcril/studio-header-component
refactor: make studio header more flexible
2022-10-20 14:24:44 -03:00
Brian Smith
a54f099d68 refactor: make studio header more flexible 2022-10-19 10:20:10 -04:00
Diana Huang
02d081dd26 Merge pull request #270 from openedx/diana/transifex-call
fix: Add transifex flag.
2022-10-17 16:28:12 -04:00
Diana Huang
468acc80f0 fix: Add transifex flag.
The Transifex cli started requiring the -t or --translations flag in the pull command in order to fetch translations.

https://github.com/edx/edx-arch-experiments/issues/77
2022-10-17 16:05:53 -04:00
renovate[bot]
90fdd13fbc chore(deps): update dependency react-router-dom to v5.3.4 2022-10-17 08:57:14 +00:00
renovate[bot]
faf1b8522a chore(deps): update dependency react-redux to v7.2.9 2022-10-10 09:15:51 +00:00
Jenkins
e8a28b09bc chore(i18n): update translations 2022-10-09 16:30:19 -04:00
renovate[bot]
c611df3f69 chore(deps): update dependency jest-chain to v1.1.6 2022-10-03 08:05:06 +00:00
Jenkins
ab371f1c3a chore(i18n): update translations 2022-10-02 16:30:36 -04:00
renovate[bot]
fb2002a004 chore(deps): update dependency @testing-library/dom to v8.18.1 2022-09-26 10:35:10 +00:00
renovate[bot]
f955ec4434 chore(deps): update dependency @testing-library/dom to v8.18.0 2022-09-19 09:59:12 +00:00
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
Abdullah Waheed
de9eb63b07 feat: added new translations in Makefile and updated all the translations 2022-09-06 20:05:09 +05: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
dependabot[bot]
64f55150b6 build(deps): bump async from 2.6.3 to 2.6.4
Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4.
- [Release notes](https://github.com/caolan/async/releases)
- [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md)
- [Commits](https://github.com/caolan/async/compare/v2.6.3...v2.6.4)

---
updated-dependencies:
- dependency-name: async
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-18 11:56:29 +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
53 changed files with 24841 additions and 20145 deletions

View File

@@ -1,10 +1,13 @@
ACCESS_TOKEN_COOKIE_NAME=edx-jwt-cookie-header-payload
ACCOUNT_PROFILE_URL=http://localhost:1995
ACCOUNT_SETTINGS_URL=http://localhost:1997
BASE_URL=localhost:8080
CREDENTIALS_BASE_URL=http://localhost:18150
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

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

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

@@ -0,0 +1,20 @@
# This workflow runs when a comment is made on the ticket
# If the comment starts with "label: " it tries to apply
# the label indicated in rest of comment.
# If the comment starts with "remove label: ", it tries
# to remove the indicated label.
# Note: Labels are allowed to have spaces and this script does
# not parse spaces (as often a space is legitimate), so the command
# "label: really long lots of words label" will apply the
# label "really long lots of words label"
name: Allows for the adding and removing of labels via comment
on:
issue_comment:
types: [created]
jobs:
add_remove_labels:
uses: openedx/.github/.github/workflows/add-remove-label-on-comment.yml@master

View File

@@ -1,17 +1,25 @@
name: Default CI
on: [push, pull_request]
on:
push:
branches:
- master
pull_request:
branches:
- '**'
jobs:
build:
tests:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Nodejs Env
run: echo "NODE_VER=`cat .nvmrc`" >> $GITHUB_ENV
- name: Setup Nodejs
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: 12
node-version: ${{ env.NODE_VER }}
- name: Install dependencies
run: npm ci
- name: Validate package-lock.json changes
@@ -20,7 +28,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

@@ -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,13 @@
#check package-lock file version
name: lockfileVersion check
on:
push:
branches:
- master
pull_request:
jobs:
version-check:
uses: openedx/.github/.github/workflows/lockfileversion-check-v3.yml@master

View File

@@ -2,38 +2,40 @@ 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@v3
with:
fetch-depth: 0
- name: Setup Nodejs Env
run: echo "NODE_VER=`cat .nvmrc`" >> $GITHUB_ENV
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VER }}
- 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@v3
with:
semantic_version: 16
env:
GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_NPM_TOKEN }}

12
.github/workflows/self-assign-issue.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
# This workflow runs when a comment is made on the ticket
# If the comment starts with "assign me" it assigns the author to the
# ticket (case insensitive)
name: Assign comment author to ticket if they say "assign me"
on:
issue_comment:
types: [created]
jobs:
self_assign_by_comment:
uses: openedx/.github/.github/workflows/self-assign-issue.yml@master

2
.gitignore vendored
View File

@@ -7,3 +7,5 @@ temp
src/i18n/transifex_input.json
module.config.js
.idea/
.vscode

1
.nvmrc Normal file
View File

@@ -0,0 +1 @@
18

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,11 +1,9 @@
transifex_resource = frontend-component-header
transifex_langs = "ar,fr,es_419,zh_CN"
export TRANSIFEX_RESOURCE = frontend-component-header
transifex_langs = "ar,fr,es_419,zh_CN,pt,it,de,uk,ru,hi,fr_CA"
transifex_utils = ./node_modules/.bin/transifex-utils.js
i18n = ./src/i18n
transifex_input = $(i18n)/transifex_input.json
tx_url1 = https://www.transifex.com/api/2/project/edx-platform/resource/$(transifex_resource)/translation/en/strings/
tx_url2 = https://www.transifex.com/api/2/project/edx-platform/resource/$(transifex_resource)/source/
# This directory must match .babelrc .
transifex_temp = ./temp/babel-plugin-react-intl
@@ -42,15 +40,15 @@ push_translations:
# Pushing strings to Transifex...
tx push -s
# Fetching hashes from Transifex...
./node_modules/reactifex/bash_scripts/get_hashed_strings.sh $(tx_url1)
./node_modules/@edx/reactifex/bash_scripts/get_hashed_strings_v3.sh
# Writing out comments to file...
$(transifex_utils) $(transifex_temp) --comments
$(transifex_utils) $(transifex_temp) --comments --v3-scripts-path
# Pushing comments to Transifex...
./node_modules/reactifex/bash_scripts/put_comments.sh $(tx_url2)
./node_modules/@edx/reactifex/bash_scripts/put_comments_v3.sh
# Pulls translations from Transifex.
pull_translations:
tx pull -f --mode reviewed --language=$(transifex_langs)
tx pull -t -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
=====================
@@ -26,6 +26,8 @@ Environment Variables
Defaults to "localhost" in development.
* ``LOGO_URL`` - The URL of the site's logo. This logo is displayed in the header.
* ``ORDER_HISTORY_URL`` - The URL of the order history page.
* ``ACCOUNT_PROFILE_URL`` - The URL of the account profile page.
* ``ACCOUNT_SETTINGS_URL`` - The URL of the account settings page.
* ``AUTHN_MINIMAL_HEADER`` - A boolean flag which hides the main menu, user menu, and logged-out
menu items when truthy. This is intended to be used in micro-frontends like
frontend-app-authentication in which these menus are considered distractions from the user's task.
@@ -53,8 +55,9 @@ 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>`_
***********
Development

43426
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -24,53 +24,51 @@
},
"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": "5.6.14",
"@edx/frontend-platform": "1.14.1",
"@edx/paragon": "12.8.0",
"codecov": "3.8.3",
"@edx/brand": "npm:@edx/brand-openedx@1.2.0",
"@edx/browserslist-config": "^1.1.1",
"@edx/frontend-build": "12.8.6",
"@edx/reactifex": "^2.1.1",
"@testing-library/dom": "9.2.0",
"@testing-library/jest-dom": "5.16.5",
"@testing-library/react": "10.4.9",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.6",
"husky": "7.0.4",
"prop-types": "15.7.2",
"enzyme-adapter-react-16": "1.15.7",
"husky": "8.0.3",
"jest": "29.5.0",
"jest-chain": "1.1.6",
"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.9",
"react-router-dom": "5.3.4",
"react-test-renderer": "16.14.0",
"reactifex": "1.1.1",
"redux": "4.1.2",
"redux-saga": "1.1.3",
"@testing-library/dom": "7.16.3",
"@testing-library/jest-dom": "5.15.1",
"jest": "27.3.1",
"jest-chain": "1.1.5",
"@testing-library/react": "10.3.0"
"redux": "4.2.1",
"redux-saga": "1.2.3"
},
"dependencies": {
"@edx/frontend-platform": "^4.0.1",
"@edx/paragon": "20.30.1",
"@fortawesome/fontawesome-svg-core": "6.3.0",
"@fortawesome/free-brands-svg-icons": "6.3.0",
"@fortawesome/free-regular-svg-icons": "6.3.0",
"@fortawesome/free-solid-svg-icons": "6.3.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"babel-polyfill": "6.26.0",
"react-responsive": "8.2.0",
"react-transition-group": "4.4.2",
"@fortawesome/fontawesome-svg-core": "1.2.36",
"@fortawesome/free-brands-svg-icons": "5.15.4",
"@fortawesome/free-regular-svg-icons": "5.15.4",
"@fortawesome/free-solid-svg-icons": "5.15.4",
"@fortawesome/react-fontawesome": "^0.1.14"
"react-transition-group": "4.4.5"
},
"peerDependencies": {
"@edx/frontend-platform": "^1.8.0",
"@edx/paragon": "^7.0.0",
"prop-types": "^15.5.10",
"react": "^16.9.0",
"react-dom": "^16.9.0"
"react": "^16.9.0 || ^17.0.0",
"react-dom": "^16.9.0 || ^17.0.0"
}
}

View File

@@ -22,6 +22,11 @@
"pin"
],
"automerge": true
},
{
"matchPackagePatterns": ["@edx"],
"matchUpdateTypes": ["minor", "patch"],
"automerge": true
}
],
"timezone": "America/New_York"

View File

@@ -3,12 +3,12 @@ import PropTypes from 'prop-types';
import { AvatarIcon } from './Icons';
function Avatar({
const Avatar = ({
size,
src,
alt,
className,
}) {
}) => {
const avatar = src ? (
<img className="d-block w-100 h-100" src={src} alt={alt} />
) : (
@@ -23,7 +23,7 @@ function Avatar({
{avatar}
</span>
);
}
};
Avatar.propTypes = {
src: PropTypes.string,

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

@@ -30,7 +30,7 @@ subscribe(APP_CONFIG_INITIALIZED, () => {
}, 'Header additional config');
});
function Header({ intl }) {
const Header = ({ intl }) => {
const { authenticatedUser, config } = useContext(AppContext);
const mainMenu = [
@@ -55,12 +55,12 @@ function Header({ intl }) {
},
{
type: 'item',
href: `${config.LMS_BASE_URL}/u/${authenticatedUser.username}`,
href: `${config.ACCOUNT_PROFILE_URL}/u/${authenticatedUser.username}`,
content: intl.formatMessage(messages['header.user.menu.profile']),
},
{
type: 'item',
href: `${config.LMS_BASE_URL}/account/settings`,
href: config.ACCOUNT_SETTINGS_URL,
content: intl.formatMessage(messages['header.user.menu.account.settings']),
},
{
@@ -110,7 +110,7 @@ function Header({ intl }) {
</Responsive>
</>
);
}
};
Header.propTypes = {
intl: intlShape.isRequired,

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;

View File

@@ -1,3 +1,4 @@
/* eslint-disable react/prop-types */
import React from 'react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import TestRenderer from 'react-test-renderer';
@@ -6,28 +7,31 @@ import { Context as ResponsiveContext } from 'react-responsive';
import Header from './index';
const HeaderComponent = ({ width, contextValue }) => (
<ResponsiveContext.Provider value={width}>
<IntlProvider locale="en" messages={{}}>
<AppContext.Provider
value={contextValue}
>
<Header />
</AppContext.Provider>
</IntlProvider>
</ResponsiveContext.Provider>
);
describe('<Header />', () => {
it('renders correctly for anonymous desktop', () => {
const component = (
<ResponsiveContext.Provider value={{ width: 1280 }}>
<IntlProvider locale="en" messages={{}}>
<AppContext.Provider
value={{
authenticatedUser: null,
config: {
LMS_BASE_URL: process.env.LMS_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,
},
}}
>
<Header />
</AppContext.Provider>
</IntlProvider>
</ResponsiveContext.Provider>
);
const contextValue = {
authenticatedUser: null,
config: {
LMS_BASE_URL: process.env.LMS_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,
},
};
const component = <HeaderComponent width={{ width: 1280 }} contextValue={contextValue} />;
const wrapper = TestRenderer.create(component);
@@ -35,31 +39,22 @@ describe('<Header />', () => {
});
it('renders correctly for authenticated desktop', () => {
const component = (
<ResponsiveContext.Provider value={{ width: 1280 }}>
<IntlProvider locale="en" messages={{}}>
<AppContext.Provider
value={{
authenticatedUser: {
userId: 'abc123',
username: 'edX',
roles: [],
administrator: false,
},
config: {
LMS_BASE_URL: process.env.LMS_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,
},
}}
>
<Header />
</AppContext.Provider>
</IntlProvider>
</ResponsiveContext.Provider>
);
const contextValue = {
authenticatedUser: {
userId: 'abc123',
username: 'edX',
roles: [],
administrator: false,
},
config: {
LMS_BASE_URL: process.env.LMS_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,
},
};
const component = <HeaderComponent width={{ width: 1280 }} contextValue={contextValue} />;
const wrapper = TestRenderer.create(component);
@@ -67,26 +62,17 @@ describe('<Header />', () => {
});
it('renders correctly for anonymous mobile', () => {
const component = (
<ResponsiveContext.Provider value={{ width: 500 }}>
<IntlProvider locale="en" messages={{}}>
<AppContext.Provider
value={{
authenticatedUser: null,
config: {
LMS_BASE_URL: process.env.LMS_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,
},
}}
>
<Header />
</AppContext.Provider>
</IntlProvider>
</ResponsiveContext.Provider>
);
const contextValue = {
authenticatedUser: null,
config: {
LMS_BASE_URL: process.env.LMS_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,
},
};
const component = <HeaderComponent width={{ width: 500 }} contextValue={contextValue} />;
const wrapper = TestRenderer.create(component);
@@ -94,31 +80,22 @@ describe('<Header />', () => {
});
it('renders correctly for authenticated mobile', () => {
const component = (
<ResponsiveContext.Provider value={{ width: 500 }}>
<IntlProvider locale="en" messages={{}}>
<AppContext.Provider
value={{
authenticatedUser: {
userId: 'abc123',
username: 'edX',
roles: [],
administrator: false,
},
config: {
LMS_BASE_URL: process.env.LMS_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,
},
}}
>
<Header />
</AppContext.Provider>
</IntlProvider>
</ResponsiveContext.Provider>
);
const contextValue = {
authenticatedUser: {
userId: 'abc123',
username: 'edX',
roles: [],
administrator: false,
},
config: {
LMS_BASE_URL: process.env.LMS_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,
},
};
const component = <HeaderComponent width={{ width: 500 }} contextValue={contextValue} />;
const wrapper = TestRenderer.create(component);

View File

@@ -1,6 +1,6 @@
import React from 'react';
export const MenuIcon = props => (
export const MenuIcon = (props) => (
<svg
width="24px"
height="24px"
@@ -14,7 +14,7 @@ export const MenuIcon = props => (
</svg>
);
export const AvatarIcon = props => (
export const AvatarIcon = (props) => (
<svg
width="24px"
height="24px"
@@ -29,7 +29,7 @@ export const AvatarIcon = props => (
</svg>
);
export const CaretIcon = props => (
export const CaretIcon = (props) => (
<svg
width="16px"
height="16px"

View File

@@ -1,29 +1,25 @@
import React from 'react';
import PropTypes from 'prop-types';
function Logo({ src, alt, ...attributes }) {
return (
<img src={src} alt={alt} {...attributes} />
);
}
const Logo = ({ src, alt, ...attributes }) => (
<img src={src} alt={alt} {...attributes} />
);
Logo.propTypes = {
src: PropTypes.string.isRequired,
alt: PropTypes.string.isRequired,
};
function LinkedLogo({
const LinkedLogo = ({
href,
src,
alt,
...attributes
}) {
return (
<a href={href} {...attributes}>
<img className="d-block" src={src} alt={alt} />
</a>
);
}
}) => (
<a href={href} {...attributes}>
<img className="d-block" src={src} alt={alt} />
</a>
);
LinkedLogo.propTypes = {
href: PropTypes.string.isRequired,

View File

@@ -2,12 +2,10 @@ import React from 'react';
import { CSSTransition } from 'react-transition-group';
import PropTypes from 'prop-types';
function MenuTrigger({ tag, className, ...attributes }) {
return React.createElement(tag, {
className: `menu-trigger ${className}`,
...attributes,
});
}
const MenuTrigger = ({ tag, className, ...attributes }) => React.createElement(tag, {
className: `menu-trigger ${className}`,
...attributes,
});
MenuTrigger.propTypes = {
tag: PropTypes.string,
className: PropTypes.string,
@@ -18,12 +16,10 @@ MenuTrigger.defaultProps = {
};
const MenuTriggerType = <MenuTrigger />.type;
function MenuContent({ tag, className, ...attributes }) {
return React.createElement(tag, {
className: ['menu-content', className].join(' '),
...attributes,
});
}
const MenuContent = ({ tag, className, ...attributes }) => React.createElement(tag, {
className: ['menu-content', className].join(' '),
...attributes,
});
MenuContent.propTypes = {
tag: PropTypes.string,
className: PropTypes.string,

200
src/StudioHeader.jsx Normal file
View File

@@ -0,0 +1,200 @@
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,
getConfig,
mergeConfig,
subscribe,
} from '@edx/frontend-platform';
import { ActionRow } from '@edx/paragon';
import { Menu, MenuTrigger, MenuContent } from './Menu';
import Avatar from './Avatar';
import { LinkedLogo, Logo } from './Logo';
import { CaretIcon } from './Icons';
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');
});
class StudioDesktopHeaderBase extends React.Component {
constructor(props) { // eslint-disable-line no-useless-constructor
super(props);
}
renderUserMenu() {
const {
userMenu,
avatar,
username,
intl,
} = this.props;
return (
<Menu transitionClassName="menu-dropdown" transitionTimeout={250}>
<MenuTrigger
tag="button"
aria-label={intl.formatMessage(messages['header.label.account.menu.for'], { username })}
className="btn btn-outline-primary d-inline-flex align-items-center pl-2 pr-3"
>
<Avatar size="1.5em" src={avatar} alt="" className="mr-2" />
{username} <CaretIcon role="img" aria-hidden focusable="false" />
</MenuTrigger>
<MenuContent className="mb-0 dropdown-menu show dropdown-menu-right pin-right shadow py-2">
{userMenu.map(({ type, href, content }) => (
<a className={`dropdown-${type}`} key={`${type}-${content}`} href={href}>{content}</a>
))}
</MenuContent>
</Menu>
);
}
renderLoggedOutItems() {
const { loggedOutItems } = this.props;
return loggedOutItems.map((item, i, arr) => (
<a
key={`${item.type}-${item.content}`}
className={i < arr.length - 1 ? 'btn mr-2 btn-link' : 'btn mr-2 btn-outline-primary'}
href={item.href}
>
{item.content}
</a>
));
}
render() {
const {
logo,
logoAltText,
logoDestination,
loggedIn,
intl,
actionRowContent,
} = this.props;
const logoProps = { src: logo, alt: logoAltText, href: logoDestination };
const logoClasses = getConfig().AUTHN_MINIMAL_HEADER ? 'mw-100' : null;
return (
<header className="site-header-desktop">
<a className="nav-skip sr-only sr-only-focusable" href="#main">{intl.formatMessage(messages['header.label.skip.nav'])}</a>
<div className={`container-fluid ${logoClasses}`}>
<div className="nav-container position-relative d-flex align-items-center">
{logoDestination === null ? <Logo className="logo" src={logo} alt={logoAltText} /> : <LinkedLogo className="logo" {...logoProps} />}
<ActionRow>
{actionRowContent}
<nav
aria-label={intl.formatMessage(messages['header.label.secondary.nav'])}
className="nav secondary-menu-container align-items-center ml-auto"
>
{loggedIn ? this.renderUserMenu() : this.renderLoggedOutItems()}
</nav>
</ActionRow>
</div>
</div>
</header>
);
}
}
StudioDesktopHeaderBase.propTypes = {
userMenu: PropTypes.arrayOf(PropTypes.shape({
type: PropTypes.oneOf(['item', 'menu']),
href: PropTypes.string,
content: PropTypes.string,
})),
loggedOutItems: PropTypes.arrayOf(PropTypes.shape({
type: PropTypes.oneOf(['item', 'menu']),
href: PropTypes.string,
content: PropTypes.string,
})),
logo: PropTypes.string,
logoAltText: PropTypes.string,
logoDestination: PropTypes.string,
avatar: PropTypes.string,
username: PropTypes.string,
loggedIn: PropTypes.bool,
actionRowContent: PropTypes.element,
// i18n
intl: intlShape.isRequired,
};
StudioDesktopHeaderBase.defaultProps = {
userMenu: [],
loggedOutItems: [],
logo: null,
logoAltText: null,
logoDestination: null,
avatar: null,
username: null,
loggedIn: false,
actionRowContent: null,
};
const StudioDesktopHeader = injectIntl(StudioDesktopHeaderBase);
const StudioHeader = ({ intl, actionRowContent }) => {
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,
actionRowContent,
userMenu,
loggedOutItems: [],
};
return <StudioDesktopHeader {...props} />;
};
StudioHeader.propTypes = {
intl: intlShape.isRequired,
actionRowContent: PropTypes.element,
};
StudioHeader.defaultProps = {
// eslint-disable-next-line react/jsx-no-useless-fragment
actionRowContent: <></>,
};
export default injectIntl(StudioHeader);

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

@@ -0,0 +1,108 @@
/* eslint-disable react/prop-types */
import React, { useMemo } from 'react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import TestRenderer from 'react-test-renderer';
import { Link } from 'react-router-dom';
import { AppContext } from '@edx/frontend-platform/react';
import {
ActionRow,
Button,
Dropdown,
} from '@edx/paragon';
import { StudioHeader } from './index';
const StudioHeaderComponent = ({ contextValue, appMenu = null, mainMenu = [] }) => (
<IntlProvider locale="en" messages={{}}>
<AppContext.Provider
value={contextValue}
>
<StudioHeader appMenu={appMenu} mainMenu={mainMenu} />
</AppContext.Provider>
</IntlProvider>
);
const StudioHeaderContext = ({ actionRowContent = null }) => {
const headerContextValue = useMemo(() => ({
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,
},
}), []);
return (
<IntlProvider locale="en" messages={{}}>
<AppContext.Provider
value={headerContextValue}
>
<StudioHeader actionRowContent={actionRowContent} />
</AppContext.Provider>
</IntlProvider>
);
};
describe('<StudioHeader />', () => {
it('renders correctly', () => {
const contextValue = {
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,
},
};
const component = <StudioHeaderComponent contextValue={contextValue} />;
const wrapper = TestRenderer.create(component);
expect(wrapper.toJSON()).toMatchSnapshot();
});
it('renders correctly with optional action row content', () => {
const actionRowContent = (
<>
<Dropdown>
<Dropdown.Toggle variant="outline-primary" id="library-header-menu-dropdown">
Settings
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item as={Link} to="#">Dropdown Item 1</Dropdown.Item>
<Dropdown.Item as={Link} to="#">Dropdown Item 2</Dropdown.Item>
<Dropdown.Item as={Link} to="#">Dropdown Item 3</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
<ActionRow.Spacer />
<Button
variant="tertiary"
href="#"
rel="noopener noreferrer"
target="_blank"
title="Help Button"
>Help
</Button>
</>
);
const component = <StudioHeaderContext actionRowContent={actionRowContent} />;
const wrapper = TestRenderer.create(component);
expect(wrapper.toJSON()).toMatchSnapshot();
});
});

View File

@@ -0,0 +1,226 @@
// 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"
/>
<div
className="pgn__action-row"
>
<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>
</div>
</header>
`;
exports[`<StudioHeader /> renders correctly with optional action row content 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"
/>
<div
className="pgn__action-row"
>
<div
className="pgn__dropdown pgn__dropdown-light dropdown"
data-testid="dropdown"
>
<button
aria-expanded={false}
aria-haspopup={true}
className="dropdown-toggle btn btn-outline-primary"
disabled={false}
id="library-header-menu-dropdown"
onClick={[Function]}
type="button"
>
Settings
</button>
</div>
<span
className="pgn__action-row-spacer"
/>
<a
className="btn btn-tertiary"
href="#"
onClick={[Function]}
onKeyDown={[Function]}
rel="noopener noreferrer"
role="button"
target="_blank"
title="Help Button"
>
Help
</a>
<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>
</div>
</header>
`;

View File

@@ -1,34 +1,28 @@
import arMessages from './messages/ar.json';
import caMessages from './messages/ca.json';
import heMessages from './messages/he.json';
import idMessages from './messages/id.json';
import plMessages from './messages/pl.json';
import ruMessages from './messages/ru.json';
import thMessages from './messages/th.json';
import ukMessages from './messages/uk.json';
// no need to import en messages-- they are in the defaultMessage field
import es419Messages from './messages/es_419.json';
import frMessages from './messages/fr.json';
import kokrMessages from './messages/ko_KR.json';
import ptbrMessages from './messages/pt_BR.json';
import es419Messages from './messages/es_419.json';
import zhcnMessages from './messages/zh_CN.json';
import ptMessages from './messages/pt.json';
import itMessages from './messages/it.json';
import ukMessages from './messages/uk.json';
import deMessages from './messages/de.json';
import ruMessages from './messages/ru.json';
import hiMessages from './messages/hi.json';
import frCAMessages from './messages/fr_CA.json';
// no need to import en messages-- they are in the defaultMessage field
const messages = {
ar: arMessages,
ca: caMessages,
he: heMessages,
id: idMessages,
pl: plMessages,
ru: ruMessages,
th: thMessages,
uk: ukMessages,
'es-419': es419Messages,
fr: frMessages,
'zh-cn': zhcnMessages,
'ko-kr': kokrMessages,
'pt-br': ptbrMessages,
pt: ptMessages,
it: itMessages,
de: deMessages,
hi: hiMessages,
'fr-ca': frCAMessages,
ru: ruMessages,
uk: ukMessages,
};
export default messages;

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": "صفحة الاستوديو الرئيسية",
"header.user.menu.studio.maintenance": "الصيانة",
"header.label.account.nav": "الحساب",
"header.label.account.menu": "قائمة الحساب",
"header.label.account.menu.for": "قائمة حساب المستخدم {username}",
"header.label.main.nav": "القا|مة الرئيسية",
"header.label.main.menu": "القائمة الرئيسية",
"header.label.main.header": "الرئيسية",
"header.label.secondary.nav": "القائمة الثانوية",
"header.label.skip.nav": "التخطي إلى المحتوى الرئيسي",
"header.label.app.nav": "تطبيق",
"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 +0,0 @@
{}

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

@@ -0,0 +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,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 +0,0 @@
{}

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

@@ -0,0 +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 +0,0 @@
{}

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

@@ -0,0 +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,2 +0,0 @@
{
}

View File

@@ -1 +0,0 @@
{}

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

@@ -0,0 +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,2 +0,0 @@
{
}

View File

@@ -1 +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 +0,0 @@
{}

View File

@@ -1 +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,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;

View File

@@ -7,25 +7,23 @@ import { Button } from '@edx/paragon';
import genericMessages from '../generic/messages';
function AnonymousUserMenu({ intl }) {
return (
<div>
<Button
className="mr-3"
variant="outline-primary"
href={`${getConfig().LMS_BASE_URL}/register?next=${encodeURIComponent(global.location.href)}`}
>
{intl.formatMessage(genericMessages.registerSentenceCase)}
</Button>
<Button
variant="primary"
href={`${getLoginRedirectUrl(global.location.href)}`}
>
{intl.formatMessage(genericMessages.signInSentenceCase)}
</Button>
</div>
);
}
const AnonymousUserMenu = ({ intl }) => (
<div>
<Button
className="mr-3"
variant="outline-primary"
href={`${getConfig().LMS_BASE_URL}/register?next=${encodeURIComponent(global.location.href)}`}
>
{intl.formatMessage(genericMessages.registerSentenceCase)}
</Button>
<Button
variant="primary"
href={`${getLoginRedirectUrl(global.location.href)}`}
>
{intl.formatMessage(genericMessages.signInSentenceCase)}
</Button>
</div>
);
AnonymousUserMenu.propTypes = {
intl: intlShape.isRequired,

View File

@@ -10,7 +10,7 @@ import { Dropdown } from '@edx/paragon';
import messages from './messages';
function AuthenticatedUserDropdown({ intl, username }) {
const AuthenticatedUserDropdown = ({ intl, username }) => {
const dashboardMenuItem = (
<Dropdown.Item href={`${getConfig().LMS_BASE_URL}/dashboard`}>
{intl.formatMessage(messages.dashboard)}
@@ -29,10 +29,10 @@ function AuthenticatedUserDropdown({ intl, username }) {
</Dropdown.Toggle>
<Dropdown.Menu className="dropdown-menu-right">
{dashboardMenuItem}
<Dropdown.Item href={`${getConfig().LMS_BASE_URL}/u/${username}`}>
<Dropdown.Item href={`${getConfig().ACCOUNT_PROFILE_URL}/u/${username}`}>
{intl.formatMessage(messages.profile)}
</Dropdown.Item>
<Dropdown.Item href={`${getConfig().LMS_BASE_URL}/account/settings`}>
<Dropdown.Item href={getConfig().ACCOUNT_SETTINGS_URL}>
{intl.formatMessage(messages.account)}
</Dropdown.Item>
{ getConfig().ORDER_HISTORY_URL && (
@@ -47,7 +47,7 @@ function AuthenticatedUserDropdown({ intl, username }) {
</Dropdown>
</>
);
}
};
AuthenticatedUserDropdown.propTypes = {
intl: intlShape.isRequired,

View File

@@ -8,18 +8,16 @@ import AnonymousUserMenu from './AnonymousUserMenu';
import AuthenticatedUserDropdown from './AuthenticatedUserDropdown';
import messages from './messages';
function LinkedLogo({
const LinkedLogo = ({
href,
src,
alt,
...attributes
}) {
return (
<a href={href} {...attributes}>
<img className="d-block" src={src} alt={alt} />
</a>
);
}
}) => (
<a href={href} {...attributes}>
<img className="d-block" src={src} alt={alt} />
</a>
);
LinkedLogo.propTypes = {
href: PropTypes.string.isRequired,
@@ -27,9 +25,9 @@ LinkedLogo.propTypes = {
alt: PropTypes.string.isRequired,
};
function LearningHeader({
const LearningHeader = ({
courseOrg, courseNumber, courseTitle, intl, showUserDropdown,
}) {
}) => {
const { authenticatedUser } = useContext(AppContext);
const headerLogo = (
@@ -61,7 +59,7 @@ function LearningHeader({
</div>
</header>
);
}
};
LearningHeader.propTypes = {
courseOrg: PropTypes.string,

View File

@@ -22,6 +22,8 @@ Enzyme.configure({ adapter: new Adapter() });
// These configuration values are usually set in webpack's EnvironmentPlugin however
// Jest does not use webpack so we need to set these so for testing
process.env.ACCESS_TOKEN_COOKIE_NAME = 'edx-jwt-cookie-header-payload';
process.env.ACCOUNT_PROFILE_URL = 'http://localhost:1995';
process.env.ACCOUNT_SETTINGS_URL = 'http://localhost:1997';
process.env.BASE_URL = 'localhost:1995';
process.env.CREDENTIALS_BASE_URL = 'http://localhost:18150';
process.env.CSRF_TOKEN_API_PATH = '/csrf/api/v1/token';
@@ -102,16 +104,14 @@ function render(
...renderOptions
} = {},
) {
function Wrapper({ children }) {
return (
const Wrapper = ({ children }) => (
// eslint-disable-next-line react/jsx-filename-extension
<IntlProvider locale="en">
<AppProvider store={store}>
{children}
</AppProvider>
</IntlProvider>
);
}
<IntlProvider locale="en">
<AppProvider store={store}>
{children}
</AppProvider>
</IntlProvider>
);
Wrapper.propTypes = {
children: PropTypes.node.isRequired,