Compare commits

..

242 Commits

Author SHA1 Message Date
Ihor Romaniuk
1a4174d2f2 fix: trim long text in form controls and username block (#887)
* fix: trim long text in form controls and username block
* fix: update snapshots
2023-11-08 13:57:45 -05:00
vladislavkeblysh
9461973574 feat: fixed displaying field and visibility forms (#865) 2023-11-08 13:46:31 -05:00
vladislavkeblysh
06e827bdb4 feat: Fixed displaying banner and certificates on mobile view (palm.master) (#861)
* feat: fixed displaing banner and certificates on mobile view

* feat: update snapshot
2023-10-16 13:06:59 -04:00
Eugene Dyudyunov
5e3508051c fix: error when trying to save 'other education' (#746)
When user selects "Other Education" and clicks save - error occurs.

It's caused by the wrong API call payload value `'o'`
Fix: use the `'other'` payload value instead (the valid one).
2023-07-03 10:21:51 -07:00
Maxwell Frank
8c779590a1 Merge pull request #788 from openedx/mfrank/palm-release-remove-skills
refactor: remove Skills Builder from Palm
2023-06-28 14:21:23 -04:00
Maxwell Frank
b533bf7046 refactor: remove Skills Builder 2023-06-27 15:55:49 +00:00
Bilal Qamar
2af0383847 feat: upgraded to node v18, added .nvmrc and updated workflows (#712)
* feat: upgraded to node v18, added .nvmrc and updated workflows

* build: updated frontend-build, frontend-platform, component-footer & component-header packages

* refactor: updated snapshots

* refactor: updated snapshots
2023-06-09 08:51:17 +02:00
Sagirov Eugeniy
57e3bd0125 chore: update frontend-platform version to v4.2.0 2023-05-02 17:14:27 -03:00
renovate[bot]
85d85007d2 fix(deps): update dependency @edx/frontend-component-footer to v11.7.1 2023-04-10 13:30:36 +00:00
renovate[bot]
9276fe25ad chore(deps): update dependency @edx/frontend-build to v12.8.6 2023-04-10 09:32:52 +00:00
Jenkins
9c2dd68752 chore(i18n): update translations 2023-04-02 16:40:41 -04:00
Maxwell Frank
e4a9045e89 feat: course recommendations for Skills Builder with fix 2023-03-30 15:34:43 -04:00
Maxwell Frank
c1bbbe488a feat: skills builder course recommendations 2023-03-30 19:26:29 +00:00
Maxwell Frank
45ab2f8175 Merge pull request #725 from openedx/revert-721-mfrank/course-recommendations
Revert "feat: course recommendations for Skills Builder"
2023-03-28 14:34:51 -04:00
Maxwell Frank
d9c7096fd7 Revert "feat: course recommendations for Skills Builder" 2023-03-28 14:05:18 -04:00
Maxwell Frank
c6825393c6 feat: course recommendations for Skills Builder
feat: course recommendations for Skills Builder
2023-03-28 09:37:59 -04:00
renovate[bot]
9354f11a99 fix(deps): update dependency @edx/frontend-component-header to v3.6.5 2023-03-28 12:04:23 +00:00
renovate[bot]
e7fc8f52fb chore(deps): update dependency @commitlint/cli to v17.5.1 2023-03-28 10:16:30 +00:00
Maxwell Frank
d8c8f5d7bd feat: course recommendations for Skills Builder 2023-03-27 19:28:46 +00:00
renovate[bot]
e5355e7ac8 chore(deps): update dependency @edx/frontend-build to v12.6.2 2023-03-24 09:14:55 +00:00
Maxwell Frank
99a80d3e66 Merge pull request #718 from openedx/mfrank/authenticated-page-route
fix: authenticated page route
2023-03-22 10:56:11 -04:00
Maxwell Frank
abf9860f62 fix: authenticated page route 2023-03-20 13:39:01 +00:00
renovate[bot]
ccc62a0e48 fix(deps): update dependency redux-saga to v1.2.3 2023-03-20 10:39:41 +00:00
renovate[bot]
650d3d469f fix(deps): update dependency @edx/paragon to v20.28.5 2023-03-20 08:06:56 +00:00
renovate[bot]
ab80fd7671 fix(deps): update dependency @edx/frontend-component-header to v3.6.4 2023-03-13 13:09:42 +00:00
Mashal Malik
f55b304732 refactor: remove unused tranisfex v2 url (#704) 2023-03-13 10:45:28 +05:00
Jenkins
65971820d4 chore(i18n): update translations 2023-03-12 16:40:39 -04:00
Maxwell Frank
7da386264b Merge pull request #706 from openedx/mfrank/retrieving-job-skills-data
APER-2187 Render jobs and related skills for Skills Builder
2023-03-08 14:03:46 -05:00
Maxwell Frank
b1fe21cded feat: SkillsBuilder jobs with related skills 2023-03-07 19:07:10 +00:00
Jenkins
40225d7db3 chore(i18n): update translations 2023-03-05 15:40:37 -05:00
Maxwell Frank
b4ba5276ae Merge pull request #702 from openedx/mfrank/adding-career-interests
feat: SkillsBuilder career interests selection
2023-02-28 14:55:57 -05:00
Maxwell Frank
ddff5364ce feat: SkillsBuilder career interests selection 2023-02-28 19:51:16 +00:00
David Joy
f57f5c4725 docs: update the maintaining group to openedx/2u-aperture (#703)
The @edx/arch-fed group no longer exists - this repo is maintained by the @openedx/2u-aperture team.
2023-02-28 13:46:03 -05:00
Feanil Patel
e6feef00eb Merge pull request #696 from openedx/repo_checks/ensure_workflows
Update standard workflow files.
2023-02-27 22:36:12 -05:00
Maxwell Frank
87487e37d7 Merge pull request #693 from openedx/mfrank/goals-and-job-select-v2
APER-2186: adding goal and job title selection
2023-02-27 09:16:06 -05:00
renovate[bot]
6b451a4437 fix(deps): update dependency @edx/frontend-component-footer to v11.6.3 2023-02-27 12:33:52 +00:00
renovate[bot]
b10b31860d chore(deps): update commitlint monorepo to v17.4.4 2023-02-27 09:29:59 +00:00
Jenkins
83e2b66c77 chore(i18n): update translations 2023-02-26 15:40:39 -05:00
dependabot[bot]
6fa5681e91 build(deps): bump cookiejar from 2.1.3 to 2.1.4 (#674)
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-24 13:07:48 -08:00
dependabot[bot]
e9e48e4eb0 build(deps): bump json5 from 1.0.1 to 1.0.2 (#661)
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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-24 13:03:26 -08:00
renovate[bot]
17b4933278 fix(deps): update dependency @edx/frontend-platform to v3 (#660)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-24 12:52:53 -08:00
Maxwell Frank
68dc8a1045 feat: first two questions of Skills Builder 2023-02-24 19:26:53 +00:00
Justin Hynes
21a3e9259d Merge pull request #695 from openedx/jhynes/aper-2262
feat: add utility function to retrieve product recommendations based on job skills
2023-02-24 09:06:26 -05:00
Justin Hynes
a6086fd4bf feat: add utility function to retrieve product recommendations based on job skills
[APER-2262]

- add a utility function to retrieve product recommendations based on skills from a job a learner is interested in
- add additional tests and coverage around new utility functions in `search.jsx`
2023-02-24 08:57:37 -05:00
edX requirements bot
0c427cf5e3 chore: update browserslist DB (#656) 2023-02-23 13:44:15 -08:00
Feanil Patel
75ea8bc207 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 14:01:50 -05:00
Feanil Patel
47c06c0f5d 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 14:01:49 -05:00
Feanil Patel
8e0ab6db4d 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 14:01:48 -05:00
Jenkins
20159f140e chore(i18n): update translations 2023-02-19 15:40:37 -05:00
Justin Hynes
2d05de92af Merge pull request #691 from openedx/jhynes/aper-2261_algolia-utility-functions
feat: Add utility functions for querying job related data from Algolia
2023-02-17 14:12:54 -05:00
Justin Hynes
10f93420f4 feat: Add utility functions for querying job related data from Algolia
[APER-2261]
* rename `hooks.jsx` to `search.jsx` as this is more of a collection of utilities for working with Algolia
* add a utiltiy function for returning job info (from our "job" Algolia index) based on a list of jobs a learner is interested in
* add a utility function for formatting job names based on the syntax Algolia expects
2023-02-17 14:08:11 -05:00
Maxwell Frank
a12f91f7a5 Merge pull request #685 from openedx/mfrank/building-out-reducer
feat: adding actions and reducer for Skills Builder
2023-02-15 13:34:06 -05:00
Maxwell Frank
8f42e6fbfb feat: adding actions and reducer 2023-02-15 17:09:12 +00:00
Justin Hynes
4ecdf583ea Merge pull request #690 from openedx/jhynes/aper-2261
feat: Add Algolia support to Profile MFE for Skills Builder
2023-02-15 11:37:46 -05:00
Justin Hynes
e75864b860 feat: Add Algolia support to Profile MFE
[APER-2261]

This PR adds Algolia support to the Profile MFE and the upcoming Skills Builder feature.

* Adds new dependency for the `algoliasearch` package
* Add new config to support Algolia
* Update MFE configuration so we can access the new configuration variables
* Add hook to initialize Algolia client and return job and product Algolia indexes (based on settings)
* Update SkillsBuilderModal to add test code that displays the results of querying Algolia
2023-02-15 09:56:52 -05:00
Jenkins
a697e3c543 chore(i18n): update translations 2023-02-12 15:40:35 -05:00
Jason Wesson
04607dba1d Feat: display Learning Goal in profile (#676)
* feat: add unit tests for LearningGoal component

* feat: add LearningGoals component to Profile

---------

Co-authored-by: Jason Wesson <jwesson@2u.com>
2023-02-08 13:54:47 -08:00
Justin Hynes
6a4c8d9138 Merge pull request #682 from openedx/jhynes/aper-2258
feat: add Skills Builder Header component, refactor to use ModalDialog
2023-02-06 14:45:31 -05:00
Justin Hynes
dbf716eef5 feat: add Skills Builder Header component, refactor to use ModalDialog
[APER-2258]

This PR adds the SkillsBuilderHeader component to the profile MFE.

There was also some additional refactoring work required to display the header in the modal. The FullscreenModal component is not flexible enough to allow custom header designs to be displayed (only text). We have to pivot to using the `ModalDialog` family of components instead.
2023-02-06 13:34:04 -05:00
renovate[bot]
5eaab4f07d fix(deps): update dependency redux to v4.2.1 2023-02-06 13:31:33 +00:00
renovate[bot]
a139c2f71d fix(deps): update dependency @edx/frontend-component-footer to v11.6.2 2023-02-06 11:47:01 +00:00
Maxwell Frank
9e34fdd68d Merge pull request #680 from openedx/mfrank/adding-skills-context
feat: added skills context
2023-02-01 13:31:52 -05:00
Justin Hynes
109c5d437d Merge pull request #681 from openedx/jhynes/aper-2240-cleanup
fix: remove LR MFE URL building logic
2023-01-31 13:48:51 -05:00
Justin Hynes
25d0ecb531 fix: remove learner record MFE URL building logic
[APER-2240]

The Profile MFE no longer needs to understand anything about the Learner Record MFE. The Credentials IDA now has logic to determine if a request should be redirected to the Learner Record MFE so we can remove these changes from the Profile MFE.
2023-01-30 14:00:13 -05:00
Maxwell Frank
767af3c40b feat: added skills context 2023-01-30 15:46:15 +00:00
renovate[bot]
6a05552969 fix(deps): update dependency core-js to v3.27.2 2023-01-30 15:02:41 +00:00
renovate[bot]
628914dce3 fix(deps): update dependency @edx/frontend-component-header to v3.6.1 2023-01-30 10:28:08 +00:00
Jenkins
be7e204c91 chore(i18n): update translations 2023-01-29 15:40:36 -05:00
Bilal Qamar
c1d4c36a65 chore: update dependency @edx/frontend-build to v12.4.19 (#675) 2023-01-26 12:20:35 +05:00
renovate[bot]
ce04a04c36 fix(deps): update dependency @edx/frontend-component-footer to v11.6.1 2023-01-23 14:58:40 +00:00
renovate[bot]
346c08e5d6 chore(deps): update dependency @edx/frontend-build to v12.4.16 2023-01-23 11:27:47 +00:00
Jenkins
fe61237464 chore(i18n): update translations 2023-01-22 15:40:35 -05:00
renovate[bot]
c89285f0e8 chore(deps): update dependency glob to v8.1.0 2023-01-16 15:28:14 +00:00
renovate[bot]
7523a1edb3 chore(deps): update commitlint monorepo to v17.4.2 2023-01-16 11:27:14 +00:00
Jenkins
9f1c16a599 chore(i18n): update translations 2023-01-15 15:40:34 -05:00
Maxwell Frank
fdcef0edc8 Merge pull request #664 from openedx/mfrank/adding-skills-route
feat: set up skills builder route
2023-01-11 13:53:03 -05:00
Maxwell Frank
1f056dfac7 feat: set up skills builder route 2023-01-11 18:45:06 +00:00
renovate[bot]
2814349f37 fix(deps): update dependency @edx/brand to v1.2.0 2023-01-09 11:50:01 +00:00
renovate[bot]
a4327a98e4 chore(deps): update commitlint monorepo to v17.4.0 2023-01-09 08:15:56 +00:00
renovate[bot]
50fe0ecb6f fix(deps): update dependency core-js to v3.27.1 2023-01-02 08:58:39 +00:00
renovate[bot]
8e011fdf7b fix(deps): update dependency core-js to v3.27.0 2022-12-26 08:57:37 +00:00
dependabot[bot]
a6a35f3762 build(deps): bump loader-utils from 1.4.0 to 1.4.2 (#655)
Bumps [loader-utils](https://github.com/webpack/loader-utils) from 1.4.0 to 1.4.2.
- [Release notes](https://github.com/webpack/loader-utils/releases)
- [Changelog](https://github.com/webpack/loader-utils/blob/v1.4.2/CHANGELOG.md)
- [Commits](https://github.com/webpack/loader-utils/compare/v1.4.0...v1.4.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-22 12:54:32 -08:00
renovate[bot]
259f4b2a5e chore(deps): update dependency @edx/frontend-build to v12.4.15 (#625)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-22 12:34:58 -08:00
Muhammad Abdullah Waheed
65a4091e78 Automate Browserlist DB Update (#615)
* feat: added cron github action to auto update brwoserlist DB periodically

* refactor: used a shared script to update broswerslist DB, create PR and automerge it
2022-12-22 12:06:26 -08:00
Jason Wesson
e5ee7894b0 refactor: updated frontend-build & resolved eslint issues (#654)
Co-authored-by: Bilal Qamar <59555732+BilalQamar95@users.noreply.github.com>
2022-12-22 12:00:53 -08:00
renovate[bot]
8f781ea867 chore(deps): update dependency glob to v8 (#622)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-20 13:16:24 -08:00
dependabot[bot]
7d208a91ac build(deps): bump loader-utils from 1.4.0 to 1.4.2 (#635)
Bumps [loader-utils](https://github.com/webpack/loader-utils) from 1.4.0 to 1.4.2.
- [Release notes](https://github.com/webpack/loader-utils/releases)
- [Changelog](https://github.com/webpack/loader-utils/blob/v1.4.2/CHANGELOG.md)
- [Commits](https://github.com/webpack/loader-utils/compare/v1.4.0...v1.4.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-20 13:07:00 -08:00
dependabot[bot]
80599a617f build(deps): bump minimatch and recursive-readdir (#642)
Bumps [minimatch](https://github.com/isaacs/minimatch) and [recursive-readdir](https://github.com/jergason/recursive-readdir). These dependencies needed to be updated together.

Updates `minimatch` from 3.0.4 to 3.1.2
- [Release notes](https://github.com/isaacs/minimatch/releases)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.2)

Updates `recursive-readdir` from 2.2.2 to 2.2.3
- [Release notes](https://github.com/jergason/recursive-readdir/releases)
- [Changelog](https://github.com/jergason/recursive-readdir/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jergason/recursive-readdir/commits/v2.2.3)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-type: indirect
- dependency-name: recursive-readdir
  dependency-type: indirect

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-20 12:59:41 -08:00
dependabot[bot]
652559b157 build(deps): bump decode-uri-component from 0.2.0 to 0.2.2 (#644)
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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-20 12:53:22 -08:00
renovate[bot]
5363663170 fix(deps): update dependency universal-cookie to v4 (#279)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-20 12:44:44 -08:00
renovate[bot]
b34041f090 fix(deps): update dependency core-js to v3.26.1 2022-12-19 10:22:55 +00:00
renovate[bot]
a82e3e9918 fix(deps): update dependency @edx/frontend-component-header to v3.6.0 2022-12-19 08:03:15 +00:00
mashal-m
6c15c2a0fd fix: remove is-es6 check 2022-12-15 12:43:57 +00:00
mashal-m
da5bf2f533 build: use shared browserslist configuration and upgrade paragon version 2022-12-15 12:43:57 +00:00
renovate[bot]
e507548d48 fix(deps): update dependency @edx/frontend-component-footer to v11.6.0 2022-12-12 11:18:25 +00:00
renovate[bot]
ff6c63c86b fix(deps): update dependency redux-saga to v1.2.2 2022-12-12 08:31:07 +00:00
renovate[bot]
6e24a48570 fix(deps): update dependency @edx/frontend-component-header to v3.5.0 2022-12-05 13:32:14 +00:00
renovate[bot]
42a0d27b47 fix(deps): update dependency @edx/frontend-component-footer to v11.5.2 2022-12-05 11:02:32 +00:00
edX requirements bot
6a79462567 fix: -t flag added in pull translation command (#639) 2022-11-30 16:43:21 +05:00
renovate[bot]
afe39e8b9e fix(deps): update dependency @edx/frontend-component-header to v3.4.1 2022-11-28 12:53:13 +00:00
renovate[bot]
38afcb8a5a fix(deps): update dependency @edx/frontend-component-footer to v11.5.1 2022-11-28 09:16:22 +00:00
renovate[bot]
5bf65de9e4 chore(deps): update commitlint monorepo to v17.3.0 2022-11-28 09:09:07 +00:00
renovate[bot]
28423c261d fix(deps): update dependency regenerator-runtime to v0.13.11 2022-11-21 09:04:15 +00:00
renovate[bot]
0986fd05ab chore(deps): update commitlint monorepo to v17.2.0 2022-11-14 08:32:19 +00:00
renovate[bot]
21adb70478 fix(deps): update dependency reselect to v4.1.7 2022-11-14 08:25:41 +00:00
renovate[bot]
daca35ffbe fix(deps): update dependency redux-thunk to v2.4.2 2022-11-07 10:07:44 +00:00
renovate[bot]
9fe9164bb2 chore(deps): update dependency enzyme-adapter-react-16 to v1.15.7 2022-11-07 07:58:45 +00:00
Jenkins
09e010443d chore(i18n): update translations 2022-10-30 16:40:23 -04:00
renovate[bot]
87377a1443 fix(deps): pin dependency react-helmet to 6.1.0 2022-10-24 08:47:44 +00:00
Jenkins
5f89049506 chore(i18n): update translations 2022-10-23 16:40:27 -04:00
Diana Olarte
4f00bc43b9 feat: allow runtieme configuration (#586)
Allows frontend-app-profile to be configured at
runtime using the LMS's new MFE Configuration API.

Part of https://github.com/openedx/frontend-wg/issues/103
2022-10-17 12:13:59 -04:00
renovate[bot]
f732fa7ffc fix(deps): update dependency regenerator-runtime to v0.13.10 2022-10-17 09:48:16 +00:00
renovate[bot]
963ff21423 fix(deps): update dependency redux-saga to v1.2.1 2022-10-10 12:57:02 +00:00
renovate[bot]
bb5a8004b9 fix(deps): update dependency core-js to v3.25.5 2022-10-10 10:01:03 +00:00
renovate[bot]
de81959252 chore(deps): update dependency @edx/frontend-build to v12.0.6 2022-10-10 06:41:00 +00:00
renovate[bot]
964dbe26b7 fix(deps): update dependency core-js to v3.25.4 2022-10-03 11:37:09 +00:00
renovate[bot]
be0865c8d4 fix(deps): update react-router monorepo to v5.3.4 2022-10-03 08:00:29 +00:00
Jenkins
b4afc24ef2 chore(i18n): update translations 2022-10-02 16:41:52 -04:00
renovate[bot]
392f01cecf fix(deps): update dependency react-redux to v7.2.9 2022-09-26 15:45:28 +00:00
renovate[bot]
cb504f2d57 fix(deps): update dependency classnames to v2.3.2 2022-09-26 11:50:55 +00:00
Jenkins
599b655ac4 chore(i18n): update translations 2022-09-25 16:39:48 -04:00
Thomas Tracy
e28bc0a62e Merge pull request #608 from openedx/renovate/major-commitlint-monorepo
chore(deps): update commitlint monorepo to v17 (major)
2022-09-23 10:38:27 -04:00
renovate[bot]
af46aa208f chore(deps): update commitlint monorepo to v17 2022-09-22 17:01:15 +00:00
renovate[bot]
2ad4d24262 chore(deps): update dependency @edx/frontend-build to v12.0.5 2022-09-22 16:57:54 +00:00
Thomas Tracy
d4c49fb34b Merge pull request #582 from openedx/renovate/redux-4.x
fix(deps): update dependency redux to v4.2.0
2022-09-21 15:41:36 -04:00
renovate[bot]
0034fcf79f fix(deps): update dependency redux to v4.2.0 2022-09-21 14:39:57 +00:00
Thomas Tracy
b3bb371d05 Merge pull request #588 from openedx/renovate/actions-checkout-3.x
chore(deps): update actions/checkout action to v3
2022-09-21 10:36:36 -04:00
renovate[bot]
1f5c4939e4 chore(deps): update actions/checkout action to v3 2022-09-21 14:21:21 +00:00
Thomas Tracy
349c4f799d Merge pull request #591 from openedx/renovate/actions-setup-node-3.x
chore(deps): update actions/setup-node action to v3
2022-09-21 10:14:47 -04:00
Thomas Tracy
1d3c09f7a5 Merge pull request #592 from openedx/renovate/codecov-codecov-action-3.x
chore(deps): update codecov/codecov-action action to v3
2022-09-21 10:14:21 -04:00
Thomas Tracy
777ba47a3c Merge pull request #581 from openedx/renovate/font-awesome
fix(deps): update dependency @fortawesome/react-fontawesome to v0.2.0
2022-09-21 10:13:21 -04:00
renovate[bot]
379bb8a9c4 chore(deps): update codecov/codecov-action action to v3 2022-09-20 20:18:43 +00:00
renovate[bot]
1e14092771 chore(deps): update actions/setup-node action to v3 2022-09-20 20:18:38 +00:00
renovate[bot]
066f447d38 fix(deps): update dependency @fortawesome/react-fontawesome to v0.2.0 2022-09-20 20:17:55 +00:00
Thomas Tracy
d7d6cd8ad4 Merge pull request #589 from openedx/bilalqamar95/frontend-build-upgrade
Upgraded frontend-build version to v12
2022-09-20 16:13:58 -04:00
Thomas Tracy
4a40868afa chore: rebuild package lock with updated reactifex 2022-09-20 16:09:57 -04:00
Bilal Qamar
22d0f8b688 refactor: updated tests to accommodate jsx-no-constructed-context-values rule 2022-09-20 16:08:15 -04:00
Bilal Qamar
95cffc73f1 refactor: pinned frontend-build version & ignored jsx-no-constructed-context-values for tests 2022-09-20 16:08:11 -04:00
Bilal Qamar
759428dd3e refactor: resolved eslint issues after master branch merge 2022-09-20 16:07:50 -04:00
Bilal Qamar
8bb7dd7430 refactor: updated frontend-build to 12.0.3 2022-09-20 16:07:46 -04:00
Bilal Qamar
3733497ecb refactor: resolved eslint issues 2022-09-20 16:06:40 -04:00
Bilal Qamar
1b5f8ee732 refactor: updated frontend-build to v12.0.2 2022-09-20 16:06:35 -04:00
Bilal Qamar
8fa5bf57b0 refactor: upgraded frontend-build version to v12 2022-09-20 16:05:54 -04:00
Thomas Tracy
011c4ef356 Merge pull request #599 from openedx/renovate/edx-reactifex-2.x
chore(deps): update dependency @edx/reactifex to v2
2022-09-20 14:24:51 -04:00
Thomas Tracy
43a58961f3 Merge pull request #604 from openedx/abdullahwaheed/transifex-languages-list-update
Supported Transifex languages in Makefile
2022-09-20 14:23:22 -04:00
Thomas Tracy
939c18c765 Merge pull request #602 from openedx/abdullahwaheed/renovate-bot-edx-packages-auto-update
Renovate config to automate @edx namespaced minor/patch version upgrades
2022-09-20 14:22:23 -04:00
Thomas Tracy
c68ef187ee Merge pull request #590 from openedx/dependabot/npm_and_yarn/terser-4.8.1
build(deps): bump terser from 4.8.0 to 4.8.1
2022-09-20 14:21:44 -04:00
Thomas Tracy
50289e3f52 Merge pull request #605 from openedx/tcril/fix-gh-org-url
Fix github url strings (org edx -> openedx)
2022-09-20 14:20:51 -04:00
renovate[bot]
188e29f6e9 chore(deps): update dependency @edx/reactifex to v2 2022-09-16 19:49:18 +00:00
Sarina Canelake
7d11b73997 fix: update path to .github workflows to read from openedx org 2022-09-14 09:42:46 -04:00
Sarina Canelake
f1b7c86f88 fix: fix github url strings (org edx -> openedx) 2022-09-14 09:42:46 -04:00
Abdullah Waheed
ab62a2d231 feat: added new translations in Makefile and updated all the translations 2022-09-06 15:11:57 +05:00
Abdullah Waheed
728fd3f232 refactor: updated renovate config to auto update minor and patch versions of edx dependencies 2022-08-23 15:01:30 +05:00
Muhammad Abdullah Waheed
7503e6c5cb Paragon form component deprecations (#596)
* refactor: removed ValidationFormGroup deprecations

* refactor: updated unit tests

* fix: linting issue

* refactor: added unit tests for some uncovered code
2022-08-18 10:41:50 +05:00
edx-semantic-release
8363307cb4 chore(i18n): update translations 2022-08-14 16:39:20 -04:00
Muhammad Abdullah Waheed
34a9caa0bb fix: Paragon StatusAlert deprecation (#574)
* refactor: migrated StatusAlert deprecated package to Alert in AgeMessage component

* refactor: migrated StatusAlert deprecated package to Alert for remaining components

* refactor: changed snapshot to unit test to fix ci issue

* fix: updated unit test scrip to make it consistent to timezone differences and fixed snapshot issue

* feat: added unit tests of SocialLinks component to fix ci issue and improve coverage

* refactor: used aria-labelledby in place of ID as suggested in PR

* fix: unnecessary removal of coverage from test script

* fix: typo
2022-08-11 08:20:50 -04:00
edx-semantic-release
392167e554 chore(i18n): update translations 2022-08-07 16:39:27 -04:00
renovate[bot]
a087f4e983 fix(deps): update dependency core-js to v3.24.1 2022-08-01 17:21:30 +00:00
dependabot[bot]
1ffd5275bc build(deps): bump terser from 4.8.0 to 4.8.1
Bumps [terser](https://github.com/terser/terser) from 4.8.0 to 4.8.1.
- [Release notes](https://github.com/terser/terser/releases)
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-20 14:25:27 +00:00
renovate[bot]
87374a045d fix(deps): update dependency core-js to v3.23.5 2022-07-18 10:23:13 +00:00
Thomas Tracy
fbe9d9bb1c Merge pull request #585 from openedx/revert-580-ttracy/cookie-policy-banner-test
Revert "feat: Add cookie banner to profile for testing"
2022-07-11 15:04:42 -04:00
Thomas Tracy
a0b49a7a1c Revert "feat: Add cookie banner to profile for testing" 2022-07-11 14:54:11 -04:00
renovate[bot]
a2215044f3 fix(deps): update react-router monorepo to v5.3.3 2022-07-11 11:09:11 +00:00
renovate[bot]
c6c4951890 fix(deps): update dependency core-js to v3.23.4 2022-07-11 11:02:12 +00:00
Jawayria
f603f433d4 Merge pull request #542 from openedx/jenkins/drop-node-12-c50b401
chore!: Dropped support for Node 12
2022-07-01 12:36:35 +05:00
Maman Khan
3195e199a1 Merge pull request #566 from openedx/maman/update-vulnerable-packages
Update dependencies node-forge & minimist
2022-06-29 13:26:23 +05:00
Maman Naveed Khan
fd5bc50a37 fix: snapshots timezone issue 2022-06-29 13:00:25 +05:00
Maman Naveed Khan
aedb698133 fix: sync package and package-lock 2022-06-29 12:52:26 +05:00
Maman Naveed Khan
a941e6f073 fix: package lock updated 2022-06-29 12:46:37 +05:00
Maman Naveed Khan
84ea38de77 fix: updated snapshots 2022-06-29 12:44:36 +05:00
Maman Naveed Khan
3460734ff7 Merge branch 'master' into maman/update-vulnerable-packages 2022-06-29 12:39:25 +05:00
Thomas Tracy
2e9c124ced Merge pull request #580 from openedx/ttracy/cookie-policy-banner-test
feat: Add cookie banner to profile for testing
2022-06-28 14:01:21 -04:00
tj-tracy
7b61520544 feat: Add cookie banner to profile for testing 2022-06-28 17:33:38 +00:00
renovate[bot]
077f8d5b84 fix(deps): update dependency prop-types to v15.8.1 2022-06-27 11:40:07 +00:00
renovate[bot]
a1606709b2 fix(deps): update dependency core-js to v3.23.3 2022-06-27 11:33:45 +00:00
renovate[bot]
d8b0ab3442 fix(deps): update dependency reselect to v4.1.6 2022-06-20 16:20:34 +00:00
renovate[bot]
694165312c fix(deps): update dependency @edx/paragon to v19.25.3 2022-06-20 12:49:19 +00:00
edx-semantic-release
2b0dff352d chore(i18n): update translations 2022-06-12 16:40:36 -04:00
Renovate Bot
23e61bdf72 fix(deps): update dependency core-js to v3.22.8 2022-06-06 15:31:37 +00:00
Renovate Bot
bbfcb61ef3 fix(deps): update dependency @edx/paragon to v19.25.1 2022-06-06 12:59:03 +00:00
edx-semantic-release
547ce30879 chore(i18n): update translations 2022-06-03 13:17:32 -04:00
maman
a4d0f276be fix: updated vulnerable packages in package lock 2022-06-03 16:06:00 +05:00
maman
8f36e976e7 Merge branch 'master' into maman/update-vulnerable-packages 2022-06-03 15:49:55 +05:00
Renovate Bot
fa602f566f fix(deps): update dependency core-js to v3.22.7 2022-05-30 12:34:11 +00:00
Renovate Bot
7842ec56d2 fix(deps): update dependency @edx/paragon to v19.25.0 2022-05-30 09:59:48 +00:00
Diana Catalina Olarte
1acc1d0262 fix: show site name instead edX 2022-05-23 14:36:49 +01:00
Renovate Bot
b69dc2d10a fix(deps): update dependency @edx/paragon to v19.23.1 2022-05-23 12:50:56 +00:00
Renovate Bot
4cb73e0851 fix(deps): update dependency @edx/frontend-component-header to v2.6.1 2022-05-23 10:52:32 +00:00
Renovate Bot
016e6bf184 fix(deps): update dependency @edx/frontend-component-footer to v10.3.0 2022-05-16 13:52:25 +00:00
Renovate Bot
e877d0d749 chore(deps): update dependency glob to v7.2.3 2022-05-16 10:41:58 +00:00
Renovate Bot
2e1cd607d5 fix(deps): update dependency @edx/paragon to v19.21.2 2022-05-11 00:32:40 +00:00
David Joy
e4033037f2 build: adding nvmrc, bumping paragon to latest (#557)
* build: adding nvmrc, bumping paragon to latest

Adding .nvmrc is a nicety. Bumping paragon to latest is necessary to ensure compatiblity with the edX override header (frontend-component-header-edx).

* test: snapshot needed updating to account for new data-testid

This is the result of upgrading to the latest paragon.  Presumably some test IDs were added.
2022-05-09 16:15:48 -04:00
Renovate Bot
9a730117fb fix(deps): update dependency @edx/frontend-component-header to v2.5.0 2022-05-09 12:16:45 +00:00
Jawayria
7a59c32660 Merge pull request #552 from openedx/jenkins/version-check-33ed66e
feat: Add package-lock file version check
2022-05-06 15:53:33 +05:00
Renovate Bot
bfcfe35530 chore(deps): update dependency @edx/reactifex to v1.1.0 2022-05-02 16:04:48 +00:00
Renovate Bot
cf9bd36eb4 chore(deps): update dependency @edx/frontend-build to v9.2.2 2022-05-02 12:49:29 +00:00
edX requirements bot
af34fc4079 feat: Add package-lock file version check 2022-04-29 08:45:54 -04:00
Renovate Bot
33ed66e916 fix(deps): update dependency react-redux to v7.2.8 2022-04-25 15:57:32 +00:00
Renovate Bot
4982e2768d fix(deps): update dependency @fortawesome/react-fontawesome to v0.1.18 2022-04-25 12:06:20 +00:00
Renovate Bot
26ba34e648 fix(deps): update dependency @edx/frontend-platform to v1.15.6 2022-04-18 18:46:39 +00:00
Renovate Bot
6e71b7281e fix(deps): update dependency @edx/frontend-component-header to v2.4.6 2022-04-18 14:24:03 +00:00
Renovate Bot
5f9675a8a7 fix(deps): update dependency @edx/frontend-component-footer to v10.2.4 2022-04-11 16:23:38 +00:00
Renovate Bot
95155df409 chore(deps): update dependency @edx/frontend-build to v9.1.4 2022-04-11 13:41:03 +00:00
Renovate Bot
ed97f0db72 chore(deps): update dependency node-forge [security] 2022-04-04 14:42:03 +00:00
Renovate Bot
abce0a5387 chore(deps): pin dependency @edx/reactifex to v 2022-04-04 14:40:51 +00:00
edX requirements bot
ba3388dee8 chore!: Dropped support for Node 12 2022-04-04 08:04:42 -04:00
Usama Sadiq
c50b401c14 Merge pull request #541 from openedx/usamasadiq/update-pull-translations-command
build: update transifex pull translations command
2022-04-04 16:22:46 +05:00
UsamaSadiq
0c50bce43d build: update transifex pull translations command 2022-04-04 14:47:17 +05:00
Usama Sadiq
e56914eb80 Merge pull request #535 from openedx/jenkins/transifex-client-migration-ead9180
fix: transifex migration to new client
2022-04-04 14:09:02 +05:00
edX requirements bot
918aa91e49 feat: Added support for node v16 (#530)
Co-authored-by: Mohammad Ahtasham ul Hassan <ahthassan74@gmail.com>
2022-03-25 14:51:14 +05:00
David Joy
87230613c5 build: Delete CODEOWNERS (#537) 2022-03-18 10:25:02 -04:00
Ali Adnan
e2dfde2432 Merge pull request #534 from openedx/aadnan/migrate-reactifex
feat: migrate translations to reactifex
2022-03-18 14:01:31 +05:00
edX requirements bot
75ea16103a fix: transifex migration to new client 2022-03-17 08:51:00 -04:00
aliadnan
f5a6c483e2 feat: migrate translations to reactifex 2022-03-17 17:43:51 +05:00
Sarina Canelake
ead91806e6 Merge DEPR automation workflow
Add DEPR workflow automation
2022-02-24 15:21:46 -05:00
Sarina Canelake
f5e46741d2 build: add DEPR workflow automation 2022-02-23 14:36:56 -05:00
Renovate Bot
9cc77ddc1b fix(deps): update dependency @fortawesome/react-fontawesome to v0.1.17 2022-01-31 08:21:25 +00:00
Renovate Bot
2e0549a859 fix(deps): update dependency core-js to v3.20.3 2022-01-17 09:51:23 +00:00
Renovate Bot
cb515e81fc fix(deps): update dependency @edx/frontend-platform to v1.14.9 2022-01-17 09:24:30 +00:00
Renovate Bot
f8520ca2dc fix(deps): update dependency @edx/frontend-component-header to v2.4.3 2021-12-27 09:49:05 +00:00
Renovate Bot
cce3146fed fix(deps): update dependency core-js to v3.20.0 2021-12-20 10:02:18 +00:00
Renovate Bot
1e48a55029 fix(deps): update dependency @edx/frontend-component-header to v2.4.2 2021-12-20 09:42:31 +00:00
Renovate Bot
9d4d6ee2a1 chore(deps): update dependency @edx/frontend-build to v8.2.0 2021-12-13 12:38:12 +00:00
Renovate Bot
b9e4fdaf64 fix(deps): update dependency @edx/frontend-platform to v1.14.4 2021-12-13 10:52:54 +00:00
Renovate Bot
7b14eeb42c fix(deps): update dependency core-js to v3.19.3 2021-12-06 09:10:22 +00:00
Renovate Bot
2b2a94f78c fix(deps): update dependency reselect to v4.1.5 2021-12-06 08:57:31 +00:00
Renovate Bot
5e94fa62ed fix(deps): update dependency redux-thunk to v2.4.1 2021-11-29 08:53:00 +00:00
Renovate Bot
f610c5bc70 fix(deps): update dependency @edx/frontend-platform to v1.14.1 2021-11-29 08:39:18 +00:00
Renovate Bot
5922947843 fix(deps): update dependency reselect to v4.1.4 2021-11-22 10:27:21 +00:00
Renovate Bot
02da9797b4 fix(deps): update dependency redux-thunk to v2.4.0 2021-11-22 10:13:32 +00:00
Renovate Bot
8cf5b82a78 fix(deps): update dependency core-js to v3.19.1 2021-11-15 12:54:15 +00:00
Renovate Bot
c265d57ea5 chore(deps): update dependency @edx/frontend-build to v8.1.6 2021-11-15 11:00:20 +00:00
edX Transifex Bot
1069f23239 chore(i18n): update translations 2021-11-15 01:40:52 +05:00
Renovate Bot
718400dcd1 fix(deps): update dependency @edx/frontend-platform to v1.14.0 2021-11-08 10:59:03 +00:00
Renovate Bot
59e112205d chore(deps): update dependency @edx/frontend-build to v8.1.3 2021-11-08 10:43:06 +00:00
Renovate Bot
7948812a78 fix(deps): update dependency redux to v4.1.2 2021-11-01 09:16:29 +00:00
Renovate Bot
3da88dd557 fix(deps): update dependency react-redux to v7.2.6 2021-11-01 09:06:12 +00:00
edX Transifex Bot
7181950081 chore(i18n): update translations 2021-11-01 01:40:48 +05:00
Waheed Ahmed
8fbedf008c Merge pull request #488 from edx/remove-age-banner
feat: add feature flag to toggle age banner
2021-10-25 17:13:18 +05:00
uzairr
ac912e5ffc feat: add feature flag to toggle age banner
Based on the requirement for COPPA,users under the age of 13 are
not be informed to update the age information.

Fixes: VAN-753
2021-10-25 17:10:03 +05:00
Renovate Bot
299cbbea6c fix(deps): update dependency @fortawesome/react-fontawesome to v0.1.16 2021-10-25 09:05:53 +00:00
Renovate Bot
3f904fe8f6 chore(deps): update dependency @edx/frontend-build to v8.0.6 2021-10-25 08:57:34 +00:00
80 changed files with 24538 additions and 15119 deletions

6
.env
View File

@@ -22,5 +22,7 @@ LOGO_URL=''
LOGO_TRADEMARK_URL=''
LOGO_WHITE_URL=''
FAVICON_URL=''
ENABLE_LEARNER_RECORD_MFE=''
LEARNER_RECORD_MFE_BASE_URL=''
COLLECT_YEAR_OF_BIRTH=true
APP_ID=''
MFE_CONFIG_API_URL=''
ENABLE_SKILLS_BUILDER_PROFILE=''

View File

@@ -23,5 +23,7 @@ LOGO_URL=https://edx-cdn.org/v3/default/logo.svg
LOGO_TRADEMARK_URL=https://edx-cdn.org/v3/default/logo-trademark.svg
LOGO_WHITE_URL=https://edx-cdn.org/v3/default/logo-white.svg
FAVICON_URL=https://edx-cdn.org/v3/default/favicon.ico
ENABLE_LEARNER_RECORD_MFE=''
LEARNER_RECORD_MFE_BASE_URL='http://localhost:1990'
COLLECT_YEAR_OF_BIRTH=true
APP_ID=''
MFE_CONFIG_API_URL=''
ENABLE_SKILLS_BUILDER_PROFILE=''

View File

@@ -18,4 +18,8 @@ LOGO_TRADEMARK_URL=https://edx-cdn.org/v3/default/logo-trademark.svg
LOGO_WHITE_URL=https://edx-cdn.org/v3/default/logo-white.svg
FAVICON_URL=https://edx-cdn.org/v3/default/favicon.ico
ENABLE_LEARNER_RECORD_MFE=''
ENABLE_SKILLS_BUILDER_PROFILE=''
LEARNER_RECORD_MFE_BASE_URL='http://localhost:1990'
COLLECT_YEAR_OF_BIRTH=true
APP_ID=''
MFE_CONFIG_API_URL=''

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,4 +1,3 @@
---
name: ci
on:
push:
@@ -6,27 +5,25 @@ on:
- master
pull_request:
jobs:
build:
tests:
runs-on: ubuntu-latest
strategy:
matrix:
node-version:
- 12
npm-test:
- i18n_extract
- is-es5
- lint
- test
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/checkout@v3
- name: Setup Nodejs Env
run: echo "NODE_VER=`cat .nvmrc`" >> $GITHUB_ENV
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm install -g npm@6
node-version: ${{ env.NODE_VER }}
- run: make requirements
- run: make test NPM_TESTS=build
- run: make test NPM_TESTS=${{ matrix.npm-test }}
- name: upload coverage
uses: codecov/codecov-action@v2
uses: codecov/codecov-action@v3
with:
fail_ci_if_error: false

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: Lockfile Version check
on:
push:
branches:
- master
pull_request:
jobs:
version-check:
uses: openedx/.github/.github/workflows/lockfileversion-check-v3.yml@master

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

View File

@@ -0,0 +1,12 @@
name: Update Browserslist DB
on:
schedule:
- cron: '0 0 * * 1'
workflow_dispatch:
jobs:
update-browserslist:
uses: openedx/.github/.github/workflows/update-browserslist-db.yml@master
secrets:
requirements_bot_github_token: ${{ secrets.requirements_bot_github_token }}

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-app-profile]
[o:open-edx:p:edx-platform:r:frontend-app-profile]
file_filter = src/i18n/messages/<lang>.json
source_file = src/i18n/transifex_input.json
source_lang = en
type = KEYVALUEJSON
type = KEYVALUEJSON

16
Makefile Executable file → Normal file
View File

@@ -1,16 +1,14 @@
export TRANSIFEX_RESOURCE = frontend-app-profile
transifex_resource = frontend-app-profile
transifex_langs = "ar,fr,es_419,zh_CN"
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
NPM_TESTS=build i18n_extract lint test is-es5
NPM_TESTS=build i18n_extract lint test
.PHONY: test
test: $(addprefix test.npm.,$(NPM_TESTS)) ## validate ci suite
@@ -45,15 +43,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

@@ -3,7 +3,7 @@
frontend-app-profile
====================
This is a micro-frontend application responsible for the display and updating of user profiles. Please tag **@edx/arch-fed** on any PRs or issues.
This is a micro-frontend application responsible for the display and updating of user profiles. Please tag **@openedx/2u-aperture** on any PRs or issues.
When a user views their own profile, they're given fields to edit their full name, location, primary spoken language, education, social links, and bio. Each field also has a dropdown to select the visibility of that field - i.e., whether it can be viewed by other learners.
@@ -17,7 +17,7 @@ Development
Start Devstack
^^^^^^^^^^^^^^
To use this application `devstack <https://github.com/edx/devstack>`__ must be running and you must be logged into it.
To use this application `devstack <https://github.com/openedx/devstack>`__ must be running and you must be logged into it.
- Start devstack
- Log in (http://localhost:18000/login)

28807
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,69 +6,71 @@
"license": "AGPL-3.0",
"repository": {
"type": "git",
"url": "git+https://github.com/edx/frontend-app-profile.git"
"url": "git+https://github.com/openedx/frontend-app-profile.git"
},
"scripts": {
"build": "fedx-scripts webpack",
"i18n_extract": "BABEL_ENV=i18n fedx-scripts babel src --quiet > /dev/null",
"is-es5": "es-check es5 ./dist/*.js",
"lint": "fedx-scripts eslint --ext .js --ext .jsx .",
"snapshot": "fedx-scripts jest --updateSnapshot",
"start": "fedx-scripts webpack-dev-server --progress",
"test": "fedx-scripts jest --coverage --passWithNoTests"
"test": "TZ=UTC fedx-scripts jest --coverage --passWithNoTests"
},
"bugs": {
"url": "https://github.com/edx/frontend-app-profile/issues"
"url": "https://github.com/openedx/frontend-app-profile/issues"
},
"homepage": "https://github.com/edx/frontend-app-profile#readme",
"homepage": "https://github.com/openedx/frontend-app-profile#readme",
"publishConfig": {
"access": "public"
},
"browserslist": [
"last 2 versions",
"ie 11"
"extends @edx/browserslist-config"
],
"dependencies": {
"@edx/brand": "npm:@edx/brand-openedx@1.1.0",
"@edx/frontend-component-footer": "10.1.6",
"@edx/frontend-component-header": "2.4.3",
"@edx/frontend-platform": "1.12.7",
"@edx/paragon": "16.6.1",
"@edx/brand": "npm:@edx/brand-openedx@1.2.0",
"@edx/frontend-component-footer": "12.0.0",
"@edx/frontend-component-header": "4.0.0",
"@edx/frontend-platform": "4.2.0",
"@edx/paragon": "^20.20.0",
"@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.15",
"classnames": "2.3.1",
"core-js": "3.18.2",
"@fortawesome/react-fontawesome": "0.2.0",
"classnames": "2.3.2",
"core-js": "3.27.2",
"history": "4.10.1",
"lodash.camelcase": "4.3.0",
"lodash.get": "4.4.2",
"lodash.pick": "4.4.0",
"lodash.snakecase": "4.1.1",
"prop-types": "15.7.2",
"prop-types": "15.8.1",
"react": "16.14.0",
"react-dom": "16.14.0",
"react-redux": "7.2.5",
"react-router": "5.2.1",
"react-router-dom": "5.3.0",
"redux": "4.1.1",
"react-helmet": "6.1.0",
"react-redux": "7.2.9",
"react-router": "5.3.4",
"react-router-dom": "5.3.4",
"redux": "4.2.1",
"redux-devtools-extension": "2.13.9",
"redux-logger": "3.0.6",
"redux-saga": "1.1.3",
"redux-thunk": "2.3.0",
"regenerator-runtime": "0.13.9",
"reselect": "4.0.0",
"universal-cookie": "3.1.0"
"redux-saga": "1.2.3",
"redux-thunk": "2.4.2",
"regenerator-runtime": "0.13.11",
"reselect": "4.1.7",
"universal-cookie": "4.0.4"
},
"devDependencies": {
"@commitlint/cli": "13.2.1",
"@commitlint/config-angular": "13.2.0",
"@edx/frontend-build": "9.0.5",
"@commitlint/cli": "17.5.1",
"@commitlint/config-angular": "17.4.4",
"@edx/browserslist-config": "^1.1.1",
"@edx/frontend-build": "12.8.6",
"@edx/reactifex": "2.1.1",
"@testing-library/react": "11.2.7",
"codecov": "3.8.3",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.6",
"es-check": "5.2.4",
"glob": "7.2.0",
"enzyme-adapter-react-16": "1.15.7",
"glob": "8.1.0",
"react-test-renderer": "16.14.0",
"reactifex": "1.1.1",
"redux-mock-store": "1.5.4"

View File

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

21
src/head/Head.jsx Normal file
View File

@@ -0,0 +1,21 @@
import React from 'react';
import { Helmet } from 'react-helmet';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform';
import messages from './messages';
const Head = ({ intl }) => (
<Helmet>
<title>
{intl.formatMessage(messages['profile.page.title'], { siteName: getConfig().SITE_NAME })}
</title>
<link rel="shortcut icon" href={getConfig().FAVICON_URL} type="image/x-icon" />
</Helmet>
);
Head.propTypes = {
intl: intlShape.isRequired,
};
export default injectIntl(Head);

17
src/head/Head.test.jsx Normal file
View File

@@ -0,0 +1,17 @@
import React from 'react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { Helmet } from 'react-helmet';
import { mount } from 'enzyme';
import { getConfig } from '@edx/frontend-platform';
import Head from './Head';
describe('Head', () => {
const props = {};
it('should match render title tag and favicon with the site configuration values', () => {
mount(<IntlProvider locale="en"><Head {...props} /></IntlProvider>);
const helmet = Helmet.peek();
expect(helmet.title).toEqual(`Profile | ${getConfig().SITE_NAME}`);
expect(helmet.linkTags[0].rel).toEqual('shortcut icon');
expect(helmet.linkTags[0].href).toEqual(getConfig().FAVICON_URL);
});
});

11
src/head/messages.js Normal file
View File

@@ -0,0 +1,11 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
'profile.page.title': {
id: 'profile.page.title',
defaultMessage: 'Profile | {siteName}',
description: 'Title tag',
},
});
export default messages;

View File

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

View File

@@ -1,51 +1,84 @@
{
"profile.age.headline": ا يمكن مشاركة ملفك الشخصي",
"profile.age.details": "لمشاركة ملفك الشخصي مع متعلمي edX الآخرين يجب التحقق من أن يكون عمرك أكثر من ١٣ سنة",
"profile.age.set.date": "اضبط تاريخ ميلاك",
"profile.datejoined.member.since": "عضو منذُ {year}",
"profile.bio.empty": "أضف نبذة قصيرة",
"profile.page.title": "الملف الشخصي | {siteName}",
"profile.age.details": "لمشاركة ملفك الشخصي مع بقية متعلمي {siteName}، يجب أن تؤكد أنك عمرك يفوق 13 عامًا.",
"profile.age.set.date": "ضيط تاريخ ميلادك",
"profile.datejoined.member.since": "عضو منذ {year}",
"profile.bio.empty": "إضافة نبذة قصيرة",
"profile.bio.about.me": "نبذة عنّي",
"profile.certificate.organization.label": "من",
"profile.certificate.completion.date.label": "مكتمل في",
"profile.no.certificates": م تحصل على أية شهادات حتى الآن.",
"profile.certificate.organization.label": "من طرف",
"profile.certificate.completion.date.label": "صدرت بتاريخ {date}",
"profile.no.certificates": يست لديك أي شهادات يعد.",
"profile.certificates.my.certificates": "شهاداتي",
"profile.certificates.view.certificate": "معاينة الشهادة",
"profile.certificates.types.verified": "شهادة موثقة",
"profile.certificates.types.professional": "شهادة مهنية",
"profile.certificates.types.unknown": "شهادة",
"profile.country.label": "الموقع",
"profile.country.empty": "أضف موقعًا",
"profile.education.empty": "أضف مؤهلًا تعليميًا",
"profile.country.empty": "إضافة الموقع",
"profile.education.empty": "إضافة المستوى التعليمي",
"profile.education.education": "المستوى التعليمي",
"profile.education.levels.p": "شهادة دكتوراه",
"profile.education.levels.m": "ماجستير أو شهادة مهنيّة",
"profile.education.levels.b": "درجة البكالوريوس",
"profile.education.levels.a": "درجة الزمالة",
"profile.education.levels.hs": "شهادة الثانوية العامة",
"profile.education.levels.jhs": "شهادة الثانوية الصغرى/الإعدادية/المرحلة المتوسّطة",
"profile.education.levels.el": "شهادة المدرسة الابتدائية",
"profile.education.levels.none": "لا يوجد تعليم رسمي",
"profile.education.levels.p": "دكتوراه",
"profile.education.levels.m": "ماجستير / ماستر أو شهادة مهنيّة",
"profile.education.levels.b": "بكالوريوس / ليسانس",
"profile.education.levels.a": "درجة الزمالة / دبلوم الدراسات الجامعية",
"profile.education.levels.hs": "الثانوية العامة / البكالوريا",
"profile.education.levels.jhs": "المدرسة الإعدادية / المتوسطة",
"profile.education.levels.el": "المدرسة الابتدائية / الأساسية",
"profile.education.levels.none": ون تعليم رسمي",
"profile.education.levels.o": "نوع آخر من التعليم",
"profile.editbutton.edit": حرير",
"profile.formcontrols.who.can.see": "من يمكنه مشاهدة هذا:",
"profile.editbutton.edit": عديل",
"profile.formcontrols.who.can.see": "من يستطيع رؤية هذا:",
"profile.formcontrols.button.cancel": "إلغاء",
"profile.formcontrols.button.save": "حفظ",
"profile.formcontrols.button.saving": "جاري الحفظ",
"profile.formcontrols.button.saving": "الحفظ جارٍ",
"profile.formcontrols.button.saved": "تم الحفظ",
"profile.visibility.who.just.me": "أنا فقط",
"profile.visibility.who.everyone": "جميع أعضاء edX",
"profile.visibility.who.everyone": "جميع من على {siteName}",
"profile.learningGoal.learningGoal": "Learning Goal",
"profile.learningGoal.options.start_career": "I want to start my career",
"profile.learningGoal.options.advance_career": "I want to advance my career",
"profile.learningGoal.options.learn_something_new": "I want to learn something new",
"profile.learningGoal.options.something_else": "Something else",
"profile.name.full.name": "الاسم الكامل",
"profile.name.details": "هذا هو الاسم الذي سيظهر في حسابك وفي شهاداتك",
"profile.name.empty": "إضافة اسم",
"profile.name.details": "هذا هو الاسم الذي يظهر في حسابك وفي شهاداتك",
"profile.name.empty": "إضافة الاسم",
"profile.preferredlanguage.empty": "إضافة اللغة",
"profile.preferredlanguage.label": "لغة التحدث الأم",
"profile.preferredlanguage.label": "لغة التحدّث الأساسية",
"profile.profileavatar.upload-button": "تحميل صورة",
"profile.profileavatar.remove.button": "حذف",
"profile.image.alt.attribute": "صورة عرض الملف الشخصي",
"profile.image.alt.attribute": "صورة الملف الشخصي",
"profile.profileavatar.change-button": "تغيير",
"profile.sociallinks.add": "إضافة {network}",
"profile.sociallinks.social.links": "روابط قنوات التواصل الاجتماعي",
"profile.notfound.message": "الصفحة التي تبحث عنها غير متوفرة أو هناك خطأ في نص الرابط. الرجاء التحقق من الرابط والمحاولة مجددا.",
"profile.sociallinks.social.links": "روابط التواصل الاجتماعي",
"profile.notfound.message": "الصفحة التي تبحث عنها غير متوفرة أو هناك خطأ في العنوان. رجاءً تحقق من العنوان و حاول مجدّدًا.",
"profile.viewMyRecords": "عرض سجلّاتي",
"profile.loading": "جاري تحميل الملف الشخصي ..."
"profile.loading": تم تحميل الملف الشخصي...",
"profile.username.description": "معلومات ملفك الشخصي تظهر لك فقط. وحده اسم المستخدم الخاص بك يظهر للآخرين على {siteName}.",
"skills.builder.header.title": "Skills Builder",
"skills.builder.header.subheading": "Let edX be your guide",
"go.back.button": "Go Back",
"next.step.button": "Next Step",
"exit.button": "Exit",
"select.preferences": "Select preferences",
"review.results": "Review results",
"skills.builder.description": "Find the right courses and programs that help you reach your goals.",
"learning.goal.prompt": "First, tell us what you want to achieve",
"select.learning.goal": "Select a goal",
"learning.goal.start_career": "I want to start my career",
"learning.goal.advance_career": "I want to advance my career",
"learning.goal.change_career": "I want to change careers",
"learning.goal.something.new": "I want to learn something new",
"learning.goal.something.else": "Something else",
"job.title.prompt": "Next, search and select your current job title",
"job.title.input.placeholder.text": "Search and select a job title",
"student.checkbox.prompt": "I'm a student",
"currently.looking.checkbox.prompt": "I'm currently looking for work",
"career.interest.prompt": "What careers are you interested in?",
"career.interest.input.placeholder.text": "Select up to 3 new job titles",
"career.interest.remove.button.alt.text": "Remove career interest: ",
"matches.found.success.alert": "We found skills and courses that match your preferences!",
"matches.not.found.danger.alert": "We were not able to retrieve recommendations at this time. Please try again later.",
"related.skills.heading": "Related Skills",
"related.skills.selectable.box.label.text": "Related skills:",
"product.recommendations.header.text": "{productType} recommendations for {jobName}"
}

View File

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

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

@@ -0,0 +1,84 @@
{
"profile.page.title": "Profile | {siteName}",
"profile.age.details": "To share your profile with other {siteName} learners, you must confirm that you are over the age of 13.",
"profile.age.set.date": "Set your date of birth",
"profile.datejoined.member.since": "Member since {year}",
"profile.bio.empty": "Add a short bio",
"profile.bio.about.me": "About Me",
"profile.certificate.organization.label": "From",
"profile.certificate.completion.date.label": "Completed on {date}",
"profile.no.certificates": "You don't have any certificates yet.",
"profile.certificates.my.certificates": "My Certificates",
"profile.certificates.view.certificate": "View Certificate",
"profile.certificates.types.verified": "Verified Certificate",
"profile.certificates.types.professional": "Professional Certificate",
"profile.certificates.types.unknown": "Certificate",
"profile.country.label": "Location",
"profile.country.empty": "Add location",
"profile.education.empty": "Add education",
"profile.education.education": "Education",
"profile.education.levels.p": "Doctorate",
"profile.education.levels.m": "Master's or professional degree",
"profile.education.levels.b": "Bachelor's Degree",
"profile.education.levels.a": "Associate's degree",
"profile.education.levels.hs": "Secondary/high school",
"profile.education.levels.jhs": "Junior secondary/junior high/middle school",
"profile.education.levels.el": "Elementary/primary school",
"profile.education.levels.none": "No formal education",
"profile.education.levels.o": "Other education",
"profile.editbutton.edit": "Edit",
"profile.formcontrols.who.can.see": "Who can see this:",
"profile.formcontrols.button.cancel": "Cancel",
"profile.formcontrols.button.save": "Save",
"profile.formcontrols.button.saving": "Saving",
"profile.formcontrols.button.saved": "Saved",
"profile.visibility.who.just.me": "Just me",
"profile.visibility.who.everyone": "Everyone on {siteName}",
"profile.learningGoal.learningGoal": "Learning Goal",
"profile.learningGoal.options.start_career": "I want to start my career",
"profile.learningGoal.options.advance_career": "I want to advance my career",
"profile.learningGoal.options.learn_something_new": "I want to learn something new",
"profile.learningGoal.options.something_else": "Something else",
"profile.name.full.name": "Full Name",
"profile.name.details": "This is the name that appears in your account and on your certificates.",
"profile.name.empty": "Add name",
"profile.preferredlanguage.empty": "Add language",
"profile.preferredlanguage.label": "Primary Language Spoken",
"profile.profileavatar.upload-button": "Upload Photo",
"profile.profileavatar.remove.button": "Remove",
"profile.image.alt.attribute": "profile avatar",
"profile.profileavatar.change-button": "Change",
"profile.sociallinks.add": "Add {network}",
"profile.sociallinks.social.links": "Social Links",
"profile.notfound.message": "The page you're looking for is unavailable or there's an error in the URL. Please check the URL and try again.",
"profile.viewMyRecords": "View My Records",
"profile.loading": "Profile loading...",
"profile.username.description": "Your profile information is only visible to you. Only your username is visible to others on {siteName}.",
"skills.builder.header.title": "Skills Builder",
"skills.builder.header.subheading": "Let edX be your guide",
"go.back.button": "Go Back",
"next.step.button": "Next Step",
"exit.button": "Exit",
"select.preferences": "Select preferences",
"review.results": "Review results",
"skills.builder.description": "Find the right courses and programs that help you reach your goals.",
"learning.goal.prompt": "First, tell us what you want to achieve",
"select.learning.goal": "Select a goal",
"learning.goal.start_career": "I want to start my career",
"learning.goal.advance_career": "I want to advance my career",
"learning.goal.change_career": "I want to change careers",
"learning.goal.something.new": "I want to learn something new",
"learning.goal.something.else": "Something else",
"job.title.prompt": "Next, search and select your current job title",
"job.title.input.placeholder.text": "Search and select a job title",
"student.checkbox.prompt": "I'm a student",
"currently.looking.checkbox.prompt": "I'm currently looking for work",
"career.interest.prompt": "What careers are you interested in?",
"career.interest.input.placeholder.text": "Select up to 3 new job titles",
"career.interest.remove.button.alt.text": "Remove career interest: ",
"matches.found.success.alert": "We found skills and courses that match your preferences!",
"matches.not.found.danger.alert": "We were not able to retrieve recommendations at this time. Please try again later.",
"related.skills.heading": "Related Skills",
"related.skills.selectable.box.label.text": "Related skills:",
"product.recommendations.header.text": "{productType} recommendations for {jobName}"
}

View File

@@ -1,6 +1,6 @@
{
"profile.age.headline": "Tu perfil no puede ser compartido.",
"profile.age.details": "Para compartir tu perfil con otros estudiantes de edX, debes confirmar que tienes más de 13 años.",
"profile.page.title": "Perfil | {siteName}",
"profile.age.details": "Para compartir el perfil con otros {siteName} estudiantes, debe confirmar que es mayor de 13 años.",
"profile.age.set.date": "Establece tu fecha de nacimiento",
"profile.datejoined.member.since": "Miembro desde {year}",
"profile.bio.empty": "Añade una breve biografía",
@@ -33,7 +33,12 @@
"profile.formcontrols.button.saving": "Guardando",
"profile.formcontrols.button.saved": "Guardado",
"profile.visibility.who.just.me": "Solo yo",
"profile.visibility.who.everyone": "Todos en edX",
"profile.visibility.who.everyone": "Todos en {siteName}",
"profile.learningGoal.learningGoal": "Objetivo de aprendizaje",
"profile.learningGoal.options.start_career": "quiero empezar mi carrera",
"profile.learningGoal.options.advance_career": "Quiero avanzar en mi carrera",
"profile.learningGoal.options.learn_something_new": "quiero aprender algo nuevo",
"profile.learningGoal.options.something_else": "Algo más",
"profile.name.full.name": "Nombre completo",
"profile.name.details": "Este es el nombre que aparecerá en tu cuenta y en tus certificados.",
"profile.name.empty": "Añade nombre",
@@ -47,5 +52,33 @@
"profile.sociallinks.social.links": "Enlaces De Redes Sociales",
"profile.notfound.message": "La página que estas buscando no está disponible o hay un error en la URL. Por favor, comprueba la URL y vuelve a intentarlo.",
"profile.viewMyRecords": "Ver mis registros",
"profile.loading": "Cargando perfil..."
"profile.loading": "Cargando perfil...",
"profile.username.description": "La información del perfil solo la visualiza usted. Solo el nombre de usuario es visible para los demás en {siteName}.",
"skills.builder.header.title": "Constructor de habilidades",
"skills.builder.header.subheading": "Dejanos ser tu guía",
"go.back.button": "Volver Atrás",
"next.step.button": "Próximo paso",
"exit.button": "Salida",
"select.preferences": "Seleccionar preferencias",
"review.results": "Revisar resultados",
"skills.builder.description": "Encontrar los cursos y programas adecuados que lo ayuden a alcanzar sus metas.",
"learning.goal.prompt": "Primero, contar qué quieres lograr",
"select.learning.goal": "Seleccionar una meta",
"learning.goal.start_career": "Quiero empezar mi carrera",
"learning.goal.advance_career": "Quiero avanzar en mi carrera",
"learning.goal.change_career": "Quiero cambiar de carrera",
"learning.goal.something.new": "Quiero aprender algo nuevo",
"learning.goal.something.else": "Algo más",
"job.title.prompt": "A continuación, busque y seleccione su título de trabajo actual",
"job.title.input.placeholder.text": "Search and select a job title",
"student.checkbox.prompt": "Soy un estudiante",
"currently.looking.checkbox.prompt": "Actualmente estoy buscando trabajo",
"career.interest.prompt": "¿Qué carreras te interesan?",
"career.interest.input.placeholder.text": "Select up to 3 new job titles",
"career.interest.remove.button.alt.text": "Eliminar interés profesional:",
"matches.found.success.alert": "We found skills and courses that match your preferences!",
"matches.not.found.danger.alert": "We were not able to retrieve recommendations at this time. Please try again later.",
"related.skills.heading": "Related Skills",
"related.skills.selectable.box.label.text": "Related skills:",
"product.recommendations.header.text": "{productType} recommendations for {jobName}"
}

View File

@@ -1,6 +1,6 @@
{
"profile.age.headline": "Votre profil ne peut pas être partagé.",
"profile.age.details": "Pour partager votre profil avec d'autres apprenants edX, vous devez confirmer que vous avez plus de 13 ans.",
"profile.page.title": "Profile | {siteName}",
"profile.age.details": "Pour partager votre profil avec d'autres étudiants {siteName}, vous devez confirmer que vous avez plus de 13 ans.",
"profile.age.set.date": "Définissez votre date de naissance",
"profile.datejoined.member.since": "Membre depuis {year}",
"profile.bio.empty": "Ajouter une courte biographie",
@@ -33,7 +33,12 @@
"profile.formcontrols.button.saving": "Enregistrement",
"profile.formcontrols.button.saved": "Enregistré",
"profile.visibility.who.just.me": "Juste moi",
"profile.visibility.who.everyone": "Tout le monde sur edX",
"profile.visibility.who.everyone": "Tout le monde sur {siteName}",
"profile.learningGoal.learningGoal": "Learning Goal",
"profile.learningGoal.options.start_career": "I want to start my career",
"profile.learningGoal.options.advance_career": "I want to advance my career",
"profile.learningGoal.options.learn_something_new": "I want to learn something new",
"profile.learningGoal.options.something_else": "Something else",
"profile.name.full.name": "Nom complet",
"profile.name.details": "C'est le nom qui apparaît dans votre compte et sur vos certificats.",
"profile.name.empty": "Ajouter un nom",
@@ -47,5 +52,33 @@
"profile.sociallinks.social.links": "Liens vers les réseaux sociaux",
"profile.notfound.message": "La page que vous recherchez n'est pas disponible ou il y a une erreur dans l'URL. Veuillez vérifier l'URL et réessayer.",
"profile.viewMyRecords": "Voir mes succès",
"profile.loading": "Chargement du profil...."
"profile.loading": "Chargement du profil....",
"profile.username.description": "Les informations de votre profil ne sont visibles que par vous. Seul votre nom d'utilisateur est visible par les autres sur {siteName}.",
"skills.builder.header.title": "Skills Builder",
"skills.builder.header.subheading": "Let edX be your guide",
"go.back.button": "Go Back",
"next.step.button": "Next Step",
"exit.button": "Exit",
"select.preferences": "Select preferences",
"review.results": "Review results",
"skills.builder.description": "Find the right courses and programs that help you reach your goals.",
"learning.goal.prompt": "First, tell us what you want to achieve",
"select.learning.goal": "Select a goal",
"learning.goal.start_career": "I want to start my career",
"learning.goal.advance_career": "I want to advance my career",
"learning.goal.change_career": "I want to change careers",
"learning.goal.something.new": "I want to learn something new",
"learning.goal.something.else": "Something else",
"job.title.prompt": "Next, search and select your current job title",
"job.title.input.placeholder.text": "Search and select a job title",
"student.checkbox.prompt": "I'm a student",
"currently.looking.checkbox.prompt": "I'm currently looking for work",
"career.interest.prompt": "What careers are you interested in?",
"career.interest.input.placeholder.text": "Select up to 3 new job titles",
"career.interest.remove.button.alt.text": "Remove career interest: ",
"matches.found.success.alert": "We found skills and courses that match your preferences!",
"matches.not.found.danger.alert": "We were not able to retrieve recommendations at this time. Please try again later.",
"related.skills.heading": "Related Skills",
"related.skills.selectable.box.label.text": "Related skills:",
"product.recommendations.header.text": "{productType} recommendations for {jobName}"
}

View File

@@ -0,0 +1,84 @@
{
"profile.page.title": "Profil | {siteName}",
"profile.age.details": "Pour partager votre profil avec d'autres apprenants {siteName}, vous devez confirmer que vous avez plus de 13 ans.",
"profile.age.set.date": "Entrez votre date de naissance",
"profile.datejoined.member.since": "Membre depuis {year}",
"profile.bio.empty": "Ajouter une courte biographie",
"profile.bio.about.me": "À propos de moi",
"profile.certificate.organization.label": "De",
"profile.certificate.completion.date.label": "Terminé le {date}",
"profile.no.certificates": "Vous n'avez pas encore d'attestation.",
"profile.certificates.my.certificates": "Mes Attestations",
"profile.certificates.view.certificate": "Voir votre attestation",
"profile.certificates.types.verified": "Attestation vérifiée",
"profile.certificates.types.professional": "Attestation professionnelle",
"profile.certificates.types.unknown": "Attestation",
"profile.country.label": "Adresse",
"profile.country.empty": "Ajouter un emplacement",
"profile.education.empty": "Ajouter formation",
"profile.education.education": "Formation",
"profile.education.levels.p": "Doctorat",
"profile.education.levels.m": "Maîtrise ou diplôme professionnel",
"profile.education.levels.b": "Diplôme de baccalauréat",
"profile.education.levels.a": "Diplôme d'associé",
"profile.education.levels.hs": "Lycée / enseignement secondaire",
"profile.education.levels.jhs": "Collège / enseignement secondaire inférieur",
"profile.education.levels.el": "Enseignement primaire",
"profile.education.levels.none": "Sans formation formelle",
"profile.education.levels.o": "Autre niveau de formation",
"profile.editbutton.edit": "Éditer",
"profile.formcontrols.who.can.see": "Qui peut voir ça :",
"profile.formcontrols.button.cancel": "Annuler",
"profile.formcontrols.button.save": "Sauvegarder",
"profile.formcontrols.button.saving": "Sauvegarde en cours",
"profile.formcontrols.button.saved": "Sauvegardé",
"profile.visibility.who.just.me": "Juste moi",
"profile.visibility.who.everyone": "Tout le monde sur {siteName}",
"profile.learningGoal.learningGoal": "Objectif d'apprentissage",
"profile.learningGoal.options.start_career": "Je veux commencer ma carrière",
"profile.learningGoal.options.advance_career": "Je veux faire progresser ma carrière",
"profile.learningGoal.options.learn_something_new": "Je veux apprendre quelque chose de nouveau",
"profile.learningGoal.options.something_else": "Autre chose",
"profile.name.full.name": "Nom complet",
"profile.name.details": "C'est le nom qui apparaît dans votre compte et sur vos attestations.",
"profile.name.empty": "Ajouter un nom",
"profile.preferredlanguage.empty": "Ajouter une langue",
"profile.preferredlanguage.label": "Langue principale parlée",
"profile.profileavatar.upload-button": "Téléverser une photo",
"profile.profileavatar.remove.button": "Supprimer",
"profile.image.alt.attribute": "avatar de profil",
"profile.profileavatar.change-button": "Modifier",
"profile.sociallinks.add": "Ajouter {network}",
"profile.sociallinks.social.links": "Liens vers les réseaux sociaux",
"profile.notfound.message": "La page que vous recherchez n'est pas disponible ou il y a une erreur dans l'URL. Veuillez vérifier l'URL et réessayer.",
"profile.viewMyRecords": "Afficher mes dossiers",
"profile.loading": "Chargement du profil...",
"profile.username.description": "Les informations de votre profil ne sont visibles que par vous. Seul votre nom d'utilisateur est visible par les autres sur {siteName}.",
"skills.builder.header.title": "Constructeur de compétences",
"skills.builder.header.subheading": "Laissez EDUlib être votre guide",
"go.back.button": "Retour",
"next.step.button": "Prochaine étape",
"exit.button": "Sortie",
"select.preferences": "Sélectionnez les préférences",
"review.results": "Examiner les résultats",
"skills.builder.description": "Trouvez les bons cours et programmes qui vous aideront à atteindre vos objectifs.",
"learning.goal.prompt": "Tout d&#39;abord, dites-nous ce que vous voulez réaliser",
"select.learning.goal": "Sélectionnez un objectif",
"learning.goal.start_career": "Je veux commencer ma carrière",
"learning.goal.advance_career": "Je veux faire progresser ma carrière",
"learning.goal.change_career": "Je veux changer de métier",
"learning.goal.something.new": "Je veux apprendre quelque chose de nouveau",
"learning.goal.something.else": "Autre chose",
"job.title.prompt": "Ensuite, recherchez et sélectionnez votre titre de poste actuel",
"job.title.input.placeholder.text": "Rechercher et sélectionner un intitulé de poste",
"student.checkbox.prompt": "Je suis étudiant.e",
"currently.looking.checkbox.prompt": "Je suis actuellement à la recherche d&#39;un emploi",
"career.interest.prompt": "Quels métiers vous intéressent ?",
"career.interest.input.placeholder.text": "Sélectionnez jusqu'à 3 nouveaux intitulés de poste",
"career.interest.remove.button.alt.text": "Supprimer l'intérêt professionnel :",
"matches.found.success.alert": "Nous avons trouvé des compétences et des cours qui correspondent à vos préférences !",
"matches.not.found.danger.alert": "Nous n'avons pas pu récupérer les recommandations pour le moment. Veuillez réessayer plus tard.",
"related.skills.heading": "Compétences connexes",
"related.skills.selectable.box.label.text": "Compétences connexes:",
"product.recommendations.header.text": "{productType} recommandations pour {jobName}"
}

View File

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

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

@@ -0,0 +1,84 @@
{
"profile.page.title": "Profile | {siteName}",
"profile.age.details": "To share your profile with other {siteName} learners, you must confirm that you are over the age of 13.",
"profile.age.set.date": "Set your date of birth",
"profile.datejoined.member.since": "Member since {year}",
"profile.bio.empty": "Add a short bio",
"profile.bio.about.me": "About Me",
"profile.certificate.organization.label": "From",
"profile.certificate.completion.date.label": "Completed on {date}",
"profile.no.certificates": "You don't have any certificates yet.",
"profile.certificates.my.certificates": "My Certificates",
"profile.certificates.view.certificate": "View Certificate",
"profile.certificates.types.verified": "Verified Certificate",
"profile.certificates.types.professional": "Professional Certificate",
"profile.certificates.types.unknown": "Certificate",
"profile.country.label": "Location",
"profile.country.empty": "Add location",
"profile.education.empty": "Add education",
"profile.education.education": "Education",
"profile.education.levels.p": "Doctorate",
"profile.education.levels.m": "Master's or professional degree",
"profile.education.levels.b": "Bachelor's Degree",
"profile.education.levels.a": "Associate's degree",
"profile.education.levels.hs": "Secondary/high school",
"profile.education.levels.jhs": "Junior secondary/junior high/middle school",
"profile.education.levels.el": "Elementary/primary school",
"profile.education.levels.none": "No formal education",
"profile.education.levels.o": "Other education",
"profile.editbutton.edit": "Edit",
"profile.formcontrols.who.can.see": "Who can see this:",
"profile.formcontrols.button.cancel": "Cancel",
"profile.formcontrols.button.save": "Save",
"profile.formcontrols.button.saving": "Saving",
"profile.formcontrols.button.saved": "Saved",
"profile.visibility.who.just.me": "Just me",
"profile.visibility.who.everyone": "Everyone on {siteName}",
"profile.learningGoal.learningGoal": "Learning Goal",
"profile.learningGoal.options.start_career": "I want to start my career",
"profile.learningGoal.options.advance_career": "I want to advance my career",
"profile.learningGoal.options.learn_something_new": "I want to learn something new",
"profile.learningGoal.options.something_else": "Something else",
"profile.name.full.name": "Full Name",
"profile.name.details": "This is the name that appears in your account and on your certificates.",
"profile.name.empty": "Add name",
"profile.preferredlanguage.empty": "Add language",
"profile.preferredlanguage.label": "Primary Language Spoken",
"profile.profileavatar.upload-button": "Upload Photo",
"profile.profileavatar.remove.button": "Remove",
"profile.image.alt.attribute": "profile avatar",
"profile.profileavatar.change-button": "Change",
"profile.sociallinks.add": "Add {network}",
"profile.sociallinks.social.links": "Social Links",
"profile.notfound.message": "The page you're looking for is unavailable or there's an error in the URL. Please check the URL and try again.",
"profile.viewMyRecords": "View My Records",
"profile.loading": "Profile loading...",
"profile.username.description": "Your profile information is only visible to you. Only your username is visible to others on {siteName}.",
"skills.builder.header.title": "Skills Builder",
"skills.builder.header.subheading": "Let edX be your guide",
"go.back.button": "Go Back",
"next.step.button": "Next Step",
"exit.button": "Exit",
"select.preferences": "Select preferences",
"review.results": "Review results",
"skills.builder.description": "Find the right courses and programs that help you reach your goals.",
"learning.goal.prompt": "First, tell us what you want to achieve",
"select.learning.goal": "Select a goal",
"learning.goal.start_career": "I want to start my career",
"learning.goal.advance_career": "I want to advance my career",
"learning.goal.change_career": "I want to change careers",
"learning.goal.something.new": "I want to learn something new",
"learning.goal.something.else": "Something else",
"job.title.prompt": "Next, search and select your current job title",
"job.title.input.placeholder.text": "Search and select a job title",
"student.checkbox.prompt": "I'm a student",
"currently.looking.checkbox.prompt": "I'm currently looking for work",
"career.interest.prompt": "What careers are you interested in?",
"career.interest.input.placeholder.text": "Select up to 3 new job titles",
"career.interest.remove.button.alt.text": "Remove career interest: ",
"matches.found.success.alert": "We found skills and courses that match your preferences!",
"matches.not.found.danger.alert": "We were not able to retrieve recommendations at this time. Please try again later.",
"related.skills.heading": "Related Skills",
"related.skills.selectable.box.label.text": "Related skills:",
"product.recommendations.header.text": "{productType} recommendations for {jobName}"
}

View File

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

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

@@ -0,0 +1,84 @@
{
"profile.page.title": "Profile | {siteName}",
"profile.age.details": "To share your profile with other {siteName} learners, you must confirm that you are over the age of 13.",
"profile.age.set.date": "Set your date of birth",
"profile.datejoined.member.since": "Member since {year}",
"profile.bio.empty": "Add a short bio",
"profile.bio.about.me": "About Me",
"profile.certificate.organization.label": "From",
"profile.certificate.completion.date.label": "Completed on {date}",
"profile.no.certificates": "You don't have any certificates yet.",
"profile.certificates.my.certificates": "My Certificates",
"profile.certificates.view.certificate": "View Certificate",
"profile.certificates.types.verified": "Verified Certificate",
"profile.certificates.types.professional": "Professional Certificate",
"profile.certificates.types.unknown": "Certificate",
"profile.country.label": "Location",
"profile.country.empty": "Add location",
"profile.education.empty": "Add education",
"profile.education.education": "Education",
"profile.education.levels.p": "Doctorate",
"profile.education.levels.m": "Master's or professional degree",
"profile.education.levels.b": "Bachelor's Degree",
"profile.education.levels.a": "Associate's degree",
"profile.education.levels.hs": "Secondary/high school",
"profile.education.levels.jhs": "Junior secondary/junior high/middle school",
"profile.education.levels.el": "Elementary/primary school",
"profile.education.levels.none": "No formal education",
"profile.education.levels.o": "Other education",
"profile.editbutton.edit": "Edit",
"profile.formcontrols.who.can.see": "Who can see this:",
"profile.formcontrols.button.cancel": "Cancel",
"profile.formcontrols.button.save": "Save",
"profile.formcontrols.button.saving": "Saving",
"profile.formcontrols.button.saved": "Saved",
"profile.visibility.who.just.me": "Just me",
"profile.visibility.who.everyone": "Everyone on {siteName}",
"profile.learningGoal.learningGoal": "Learning Goal",
"profile.learningGoal.options.start_career": "I want to start my career",
"profile.learningGoal.options.advance_career": "I want to advance my career",
"profile.learningGoal.options.learn_something_new": "I want to learn something new",
"profile.learningGoal.options.something_else": "Something else",
"profile.name.full.name": "Full Name",
"profile.name.details": "This is the name that appears in your account and on your certificates.",
"profile.name.empty": "Add name",
"profile.preferredlanguage.empty": "Add language",
"profile.preferredlanguage.label": "Primary Language Spoken",
"profile.profileavatar.upload-button": "Upload Photo",
"profile.profileavatar.remove.button": "Remove",
"profile.image.alt.attribute": "profile avatar",
"profile.profileavatar.change-button": "Change",
"profile.sociallinks.add": "Add {network}",
"profile.sociallinks.social.links": "Social Links",
"profile.notfound.message": "The page you're looking for is unavailable or there's an error in the URL. Please check the URL and try again.",
"profile.viewMyRecords": "View My Records",
"profile.loading": "Profile loading...",
"profile.username.description": "Your profile information is only visible to you. Only your username is visible to others on {siteName}.",
"skills.builder.header.title": "Skills Builder",
"skills.builder.header.subheading": "Let edX be your guide",
"go.back.button": "Go Back",
"next.step.button": "Next Step",
"exit.button": "Exit",
"select.preferences": "Select preferences",
"review.results": "Review results",
"skills.builder.description": "Find the right courses and programs that help you reach your goals.",
"learning.goal.prompt": "First, tell us what you want to achieve",
"select.learning.goal": "Select a goal",
"learning.goal.start_career": "I want to start my career",
"learning.goal.advance_career": "I want to advance my career",
"learning.goal.change_career": "I want to change careers",
"learning.goal.something.new": "I want to learn something new",
"learning.goal.something.else": "Something else",
"job.title.prompt": "Next, search and select your current job title",
"job.title.input.placeholder.text": "Search and select a job title",
"student.checkbox.prompt": "I'm a student",
"currently.looking.checkbox.prompt": "I'm currently looking for work",
"career.interest.prompt": "What careers are you interested in?",
"career.interest.input.placeholder.text": "Select up to 3 new job titles",
"career.interest.remove.button.alt.text": "Remove career interest: ",
"matches.found.success.alert": "We found skills and courses that match your preferences!",
"matches.not.found.danger.alert": "We were not able to retrieve recommendations at this time. Please try again later.",
"related.skills.heading": "Related Skills",
"related.skills.selectable.box.label.text": "Related skills:",
"product.recommendations.header.text": "{productType} recommendations for {jobName}"
}

View File

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

View File

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

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

@@ -0,0 +1,84 @@
{
"profile.page.title": "Profile | {siteName}",
"profile.age.details": "To share your profile with other {siteName} learners, you must confirm that you are over the age of 13.",
"profile.age.set.date": "Set your date of birth",
"profile.datejoined.member.since": "Member since {year}",
"profile.bio.empty": "Add a short bio",
"profile.bio.about.me": "About Me",
"profile.certificate.organization.label": "From",
"profile.certificate.completion.date.label": "Completed on {date}",
"profile.no.certificates": "You don't have any certificates yet.",
"profile.certificates.my.certificates": "My Certificates",
"profile.certificates.view.certificate": "View Certificate",
"profile.certificates.types.verified": "Verified Certificate",
"profile.certificates.types.professional": "Professional Certificate",
"profile.certificates.types.unknown": "Certificate",
"profile.country.label": "Location",
"profile.country.empty": "Add location",
"profile.education.empty": "Add education",
"profile.education.education": "Education",
"profile.education.levels.p": "Doctorate",
"profile.education.levels.m": "Master's or professional degree",
"profile.education.levels.b": "Bachelor's Degree",
"profile.education.levels.a": "Associate's degree",
"profile.education.levels.hs": "Secondary/high school",
"profile.education.levels.jhs": "Junior secondary/junior high/middle school",
"profile.education.levels.el": "Elementary/primary school",
"profile.education.levels.none": "No formal education",
"profile.education.levels.o": "Other education",
"profile.editbutton.edit": "Edit",
"profile.formcontrols.who.can.see": "Who can see this:",
"profile.formcontrols.button.cancel": "Cancel",
"profile.formcontrols.button.save": "Save",
"profile.formcontrols.button.saving": "Saving",
"profile.formcontrols.button.saved": "Saved",
"profile.visibility.who.just.me": "Just me",
"profile.visibility.who.everyone": "Everyone on {siteName}",
"profile.learningGoal.learningGoal": "Learning Goal",
"profile.learningGoal.options.start_career": "I want to start my career",
"profile.learningGoal.options.advance_career": "I want to advance my career",
"profile.learningGoal.options.learn_something_new": "I want to learn something new",
"profile.learningGoal.options.something_else": "Something else",
"profile.name.full.name": "Full Name",
"profile.name.details": "This is the name that appears in your account and on your certificates.",
"profile.name.empty": "Add name",
"profile.preferredlanguage.empty": "Add language",
"profile.preferredlanguage.label": "Primary Language Spoken",
"profile.profileavatar.upload-button": "Upload Photo",
"profile.profileavatar.remove.button": "Remove",
"profile.image.alt.attribute": "profile avatar",
"profile.profileavatar.change-button": "Change",
"profile.sociallinks.add": "Add {network}",
"profile.sociallinks.social.links": "Social Links",
"profile.notfound.message": "The page you're looking for is unavailable or there's an error in the URL. Please check the URL and try again.",
"profile.viewMyRecords": "View My Records",
"profile.loading": "Profile loading...",
"profile.username.description": "Your profile information is only visible to you. Only your username is visible to others on {siteName}.",
"skills.builder.header.title": "Skills Builder",
"skills.builder.header.subheading": "Let edX be your guide",
"go.back.button": "Go Back",
"next.step.button": "Next Step",
"exit.button": "Exit",
"select.preferences": "Select preferences",
"review.results": "Review results",
"skills.builder.description": "Find the right courses and programs that help you reach your goals.",
"learning.goal.prompt": "First, tell us what you want to achieve",
"select.learning.goal": "Select a goal",
"learning.goal.start_career": "I want to start my career",
"learning.goal.advance_career": "I want to advance my career",
"learning.goal.change_career": "I want to change careers",
"learning.goal.something.new": "I want to learn something new",
"learning.goal.something.else": "Something else",
"job.title.prompt": "Next, search and select your current job title",
"job.title.input.placeholder.text": "Search and select a job title",
"student.checkbox.prompt": "I'm a student",
"currently.looking.checkbox.prompt": "I'm currently looking for work",
"career.interest.prompt": "What careers are you interested in?",
"career.interest.input.placeholder.text": "Select up to 3 new job titles",
"career.interest.remove.button.alt.text": "Remove career interest: ",
"matches.found.success.alert": "We found skills and courses that match your preferences!",
"matches.not.found.danger.alert": "We were not able to retrieve recommendations at this time. Please try again later.",
"related.skills.heading": "Related Skills",
"related.skills.selectable.box.label.text": "Related skills:",
"product.recommendations.header.text": "{productType} recommendations for {jobName}"
}

View File

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

View File

@@ -1 +1,84 @@
{}
{
"profile.page.title": "Profile | {siteName}",
"profile.age.details": "To share your profile with other {siteName} learners, you must confirm that you are over the age of 13.",
"profile.age.set.date": "Set your date of birth",
"profile.datejoined.member.since": "Member since {year}",
"profile.bio.empty": "Add a short bio",
"profile.bio.about.me": "About Me",
"profile.certificate.organization.label": "From",
"profile.certificate.completion.date.label": "Completed on {date}",
"profile.no.certificates": "You don't have any certificates yet.",
"profile.certificates.my.certificates": "My Certificates",
"profile.certificates.view.certificate": "View Certificate",
"profile.certificates.types.verified": "Verified Certificate",
"profile.certificates.types.professional": "Professional Certificate",
"profile.certificates.types.unknown": "Certificate",
"profile.country.label": "Location",
"profile.country.empty": "Add location",
"profile.education.empty": "Add education",
"profile.education.education": "Education",
"profile.education.levels.p": "Doctorate",
"profile.education.levels.m": "Master's or professional degree",
"profile.education.levels.b": "Bachelor's Degree",
"profile.education.levels.a": "Associate's degree",
"profile.education.levels.hs": "Secondary/high school",
"profile.education.levels.jhs": "Junior secondary/junior high/middle school",
"profile.education.levels.el": "Elementary/primary school",
"profile.education.levels.none": "No formal education",
"profile.education.levels.o": "Other education",
"profile.editbutton.edit": "Edit",
"profile.formcontrols.who.can.see": "Who can see this:",
"profile.formcontrols.button.cancel": "Cancel",
"profile.formcontrols.button.save": "Save",
"profile.formcontrols.button.saving": "Saving",
"profile.formcontrols.button.saved": "Saved",
"profile.visibility.who.just.me": "Just me",
"profile.visibility.who.everyone": "Everyone on {siteName}",
"profile.learningGoal.learningGoal": "Learning Goal",
"profile.learningGoal.options.start_career": "I want to start my career",
"profile.learningGoal.options.advance_career": "I want to advance my career",
"profile.learningGoal.options.learn_something_new": "I want to learn something new",
"profile.learningGoal.options.something_else": "Something else",
"profile.name.full.name": "Full Name",
"profile.name.details": "This is the name that appears in your account and on your certificates.",
"profile.name.empty": "Add name",
"profile.preferredlanguage.empty": "Add language",
"profile.preferredlanguage.label": "Primary Language Spoken",
"profile.profileavatar.upload-button": "Upload Photo",
"profile.profileavatar.remove.button": "Remove",
"profile.image.alt.attribute": "profile avatar",
"profile.profileavatar.change-button": "Change",
"profile.sociallinks.add": "Add {network}",
"profile.sociallinks.social.links": "Social Links",
"profile.notfound.message": "The page you're looking for is unavailable or there's an error in the URL. Please check the URL and try again.",
"profile.viewMyRecords": "View My Records",
"profile.loading": "Profile loading...",
"profile.username.description": "Your profile information is only visible to you. Only your username is visible to others on {siteName}.",
"skills.builder.header.title": "Skills Builder",
"skills.builder.header.subheading": "Let edX be your guide",
"go.back.button": "Go Back",
"next.step.button": "Next Step",
"exit.button": "Exit",
"select.preferences": "Select preferences",
"review.results": "Review results",
"skills.builder.description": "Find the right courses and programs that help you reach your goals.",
"learning.goal.prompt": "First, tell us what you want to achieve",
"select.learning.goal": "Select a goal",
"learning.goal.start_career": "I want to start my career",
"learning.goal.advance_career": "I want to advance my career",
"learning.goal.change_career": "I want to change careers",
"learning.goal.something.new": "I want to learn something new",
"learning.goal.something.else": "Something else",
"job.title.prompt": "Next, search and select your current job title",
"job.title.input.placeholder.text": "Search and select a job title",
"student.checkbox.prompt": "I'm a student",
"currently.looking.checkbox.prompt": "I'm currently looking for work",
"career.interest.prompt": "What careers are you interested in?",
"career.interest.input.placeholder.text": "Select up to 3 new job titles",
"career.interest.remove.button.alt.text": "Remove career interest: ",
"matches.found.success.alert": "We found skills and courses that match your preferences!",
"matches.not.found.danger.alert": "We were not able to retrieve recommendations at this time. Please try again later.",
"related.skills.heading": "Related Skills",
"related.skills.selectable.box.label.text": "Related skills:",
"product.recommendations.header.text": "{productType} recommendations for {jobName}"
}

View File

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

View File

@@ -1 +1,84 @@
{}
{
"profile.page.title": "Profile | {siteName}",
"profile.age.details": "To share your profile with other {siteName} learners, you must confirm that you are over the age of 13.",
"profile.age.set.date": "Set your date of birth",
"profile.datejoined.member.since": "Member since {year}",
"profile.bio.empty": "Add a short bio",
"profile.bio.about.me": "About Me",
"profile.certificate.organization.label": "From",
"profile.certificate.completion.date.label": "Completed on {date}",
"profile.no.certificates": "You don't have any certificates yet.",
"profile.certificates.my.certificates": "My Certificates",
"profile.certificates.view.certificate": "View Certificate",
"profile.certificates.types.verified": "Verified Certificate",
"profile.certificates.types.professional": "Professional Certificate",
"profile.certificates.types.unknown": "Certificate",
"profile.country.label": "Location",
"profile.country.empty": "Add location",
"profile.education.empty": "Add education",
"profile.education.education": "Education",
"profile.education.levels.p": "Doctorate",
"profile.education.levels.m": "Master's or professional degree",
"profile.education.levels.b": "Bachelor's Degree",
"profile.education.levels.a": "Associate's degree",
"profile.education.levels.hs": "Secondary/high school",
"profile.education.levels.jhs": "Junior secondary/junior high/middle school",
"profile.education.levels.el": "Elementary/primary school",
"profile.education.levels.none": "No formal education",
"profile.education.levels.o": "Other education",
"profile.editbutton.edit": "Edit",
"profile.formcontrols.who.can.see": "Who can see this:",
"profile.formcontrols.button.cancel": "Cancel",
"profile.formcontrols.button.save": "Save",
"profile.formcontrols.button.saving": "Saving",
"profile.formcontrols.button.saved": "Saved",
"profile.visibility.who.just.me": "Just me",
"profile.visibility.who.everyone": "Everyone on {siteName}",
"profile.learningGoal.learningGoal": "Learning Goal",
"profile.learningGoal.options.start_career": "I want to start my career",
"profile.learningGoal.options.advance_career": "I want to advance my career",
"profile.learningGoal.options.learn_something_new": "I want to learn something new",
"profile.learningGoal.options.something_else": "Something else",
"profile.name.full.name": "Full Name",
"profile.name.details": "This is the name that appears in your account and on your certificates.",
"profile.name.empty": "Add name",
"profile.preferredlanguage.empty": "Add language",
"profile.preferredlanguage.label": "Primary Language Spoken",
"profile.profileavatar.upload-button": "Upload Photo",
"profile.profileavatar.remove.button": "Remove",
"profile.image.alt.attribute": "profile avatar",
"profile.profileavatar.change-button": "Change",
"profile.sociallinks.add": "Add {network}",
"profile.sociallinks.social.links": "Social Links",
"profile.notfound.message": "The page you're looking for is unavailable or there's an error in the URL. Please check the URL and try again.",
"profile.viewMyRecords": "View My Records",
"profile.loading": "Profile loading...",
"profile.username.description": "Your profile information is only visible to you. Only your username is visible to others on {siteName}.",
"skills.builder.header.title": "Skills Builder",
"skills.builder.header.subheading": "Let edX be your guide",
"go.back.button": "Go Back",
"next.step.button": "Next Step",
"exit.button": "Exit",
"select.preferences": "Select preferences",
"review.results": "Review results",
"skills.builder.description": "Find the right courses and programs that help you reach your goals.",
"learning.goal.prompt": "First, tell us what you want to achieve",
"select.learning.goal": "Select a goal",
"learning.goal.start_career": "I want to start my career",
"learning.goal.advance_career": "I want to advance my career",
"learning.goal.change_career": "I want to change careers",
"learning.goal.something.new": "I want to learn something new",
"learning.goal.something.else": "Something else",
"job.title.prompt": "Next, search and select your current job title",
"job.title.input.placeholder.text": "Search and select a job title",
"student.checkbox.prompt": "I'm a student",
"currently.looking.checkbox.prompt": "I'm currently looking for work",
"career.interest.prompt": "What careers are you interested in?",
"career.interest.input.placeholder.text": "Select up to 3 new job titles",
"career.interest.remove.button.alt.text": "Remove career interest: ",
"matches.found.success.alert": "We found skills and courses that match your preferences!",
"matches.not.found.danger.alert": "We were not able to retrieve recommendations at this time. Please try again later.",
"related.skills.heading": "Related Skills",
"related.skills.selectable.box.label.text": "Related skills:",
"product.recommendations.header.text": "{productType} recommendations for {jobName}"
}

View File

@@ -1,6 +1,6 @@
{
"profile.age.headline": "Your profile cannot be shared.",
"profile.age.details": "To share your profile with other edX learners, you must confirm that you are over the age of 13.",
"profile.page.title": "Profile | {siteName}",
"profile.age.details": "To share your profile with other {siteName} learners, you must confirm that you are over the age of 13.",
"profile.age.set.date": "Set your date of birth",
"profile.datejoined.member.since": "Member since {year}",
"profile.bio.empty": "Add a short bio",
@@ -33,7 +33,12 @@
"profile.formcontrols.button.saving": "Saving",
"profile.formcontrols.button.saved": "Saved",
"profile.visibility.who.just.me": "Just me",
"profile.visibility.who.everyone": "Everyone on edX",
"profile.visibility.who.everyone": "Everyone on {siteName}",
"profile.learningGoal.learningGoal": "Learning Goal",
"profile.learningGoal.options.start_career": "I want to start my career",
"profile.learningGoal.options.advance_career": "I want to advance my career",
"profile.learningGoal.options.learn_something_new": "I want to learn something new",
"profile.learningGoal.options.something_else": "Something else",
"profile.name.full.name": "Full Name",
"profile.name.details": "This is the name that appears in your account and on your certificates.",
"profile.name.empty": "Add name",
@@ -47,5 +52,33 @@
"profile.sociallinks.social.links": "Social Links",
"profile.notfound.message": "The page you're looking for is unavailable or there's an error in the URL. Please check the URL and try again.",
"profile.viewMyRecords": "View My Records",
"profile.loading": "Profile loading..."
"profile.loading": "Profile loading...",
"profile.username.description": "Your profile information is only visible to you. Only your username is visible to others on {siteName}.",
"skills.builder.header.title": "Skills Builder",
"skills.builder.header.subheading": "Let edX be your guide",
"go.back.button": "Go Back",
"next.step.button": "Next Step",
"exit.button": "Exit",
"select.preferences": "Select preferences",
"review.results": "Review results",
"skills.builder.description": "Find the right courses and programs that help you reach your goals.",
"learning.goal.prompt": "First, tell us what you want to achieve",
"select.learning.goal": "Select a goal",
"learning.goal.start_career": "I want to start my career",
"learning.goal.advance_career": "I want to advance my career",
"learning.goal.change_career": "I want to change careers",
"learning.goal.something.new": "I want to learn something new",
"learning.goal.something.else": "Something else",
"job.title.prompt": "Next, search and select your current job title",
"job.title.input.placeholder.text": "Search and select a job title",
"student.checkbox.prompt": "I'm a student",
"currently.looking.checkbox.prompt": "I'm currently looking for work",
"career.interest.prompt": "What careers are you interested in?",
"career.interest.input.placeholder.text": "Select up to 3 new job titles",
"career.interest.remove.button.alt.text": "Remove career interest: ",
"matches.found.success.alert": "We found skills and courses that match your preferences!",
"matches.not.found.danger.alert": "We were not able to retrieve recommendations at this time. Please try again later.",
"related.skills.heading": "Related Skills",
"related.skills.selectable.box.label.text": "Related skills:",
"product.recommendations.header.text": "{productType} recommendations for {jobName}"
}

View File

@@ -15,27 +15,25 @@ import {
import React from 'react';
import ReactDOM from 'react-dom';
import { Route, Switch } from 'react-router-dom';
import Header, { messages as headerMessages } from '@edx/frontend-component-header';
import Footer, { messages as footerMessages } from '@edx/frontend-component-footer';
import appMessages from './i18n';
import { ProfilePage, NotFoundPage } from './profile';
import configureStore from './data/configureStore';
import './index.scss';
import Head from './head/Head';
import AppRoutes from './routes/AppRoutes';
subscribe(APP_READY, () => {
ReactDOM.render(
<AppProvider store={configureStore()}>
<Head />
<Header />
<main>
<Switch>
<Route path="/u/:username" component={ProfilePage} />
<Route path="/notfound" component={NotFoundPage} />
<Route path="*" component={NotFoundPage} />
</Switch>
<AppRoutes />
</main>
<Footer />
</AppProvider>,
@@ -53,13 +51,12 @@ initialize({
headerMessages,
footerMessages,
],
requireAuthenticatedUser: true,
hydrateAuthenticatedUser: true,
handlers: {
config: () => {
mergeConfig({
ENABLE_LEARNER_RECORD_MFE: (process.env.ENABLE_LEARNER_RECORD_MFE || false),
LEARNER_RECORD_MFE_BASE_URL: process.env.LEARNER_RECORD_MFE_BASE_URL,
COLLECT_YEAR_OF_BIRTH: process.env.COLLECT_YEAR_OF_BIRTH,
ENABLE_SKILLS_BUILDER_PROFILE: process.env.ENABLE_SKILLS_BUILDER_PROFILE,
}, 'App loadConfig override handler');
},
},

View File

@@ -1,40 +1,36 @@
import React from 'react';
import PropTypes from 'prop-types';
import { StatusAlert } from '@edx/paragon';
import { Alert } from '@edx/paragon';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform';
function AgeMessage({ accountSettingsUrl }) {
return (
<StatusAlert
alertType="info"
dialog={(
<>
<FormattedMessage
id="profile.age.headline"
defaultMessage="Your profile cannot be shared."
description="error message"
tagName="h6"
/>
<FormattedMessage
id="profile.age.details"
defaultMessage="To share your profile with other edX learners, you must confirm that you are over the age of 13."
description="error message"
tagName="p"
/>
<a href={accountSettingsUrl}>
<FormattedMessage
id="profile.age.set.date"
defaultMessage="Set your date of birth"
description="label on a link to set birthday"
/>
</a>
</>
)}
dismissible={false}
open
const AgeMessage = ({ accountSettingsUrl }) => (
<Alert
variant="info"
dismissible={false}
show
>
<Alert.Heading id="profile.age.headline">
Your profile cannot be shared.
</Alert.Heading>
<FormattedMessage
id="profile.age.details"
defaultMessage="To share your profile with other {siteName} learners, you must confirm that you are over the age of 13."
description="Error message"
tagName="p"
values={{
siteName: getConfig().SITE_NAME,
}}
/>
);
}
<Alert.Link href={accountSettingsUrl}>
<FormattedMessage
id="profile.age.set.date"
defaultMessage="Set your date of birth"
description="Label on a link to set birthday"
/>
</Alert.Link>
</Alert>
);
AgeMessage.propTypes = {
accountSettingsUrl: PropTypes.string.isRequired,

View File

@@ -1,7 +1,5 @@
import React from 'react';
function Banner() {
return <div className="profile-page-bg-banner bg-primary d-none d-md-block p-relative" />;
}
const Banner = () => <div className="profile-page-bg-banner bg-primary d-md-block p-relative" />;
export default Banner;

View File

@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage, FormattedDate } from '@edx/frontend-platform/i18n';
function DateJoined({ date }) {
const DateJoined = ({ date }) => {
if (date == null) {
return null;
}
@@ -19,7 +19,7 @@ function DateJoined({ date }) {
/>
</p>
);
}
};
DateJoined.propTypes = {
date: PropTypes.string,

View File

@@ -1,16 +1,16 @@
import React from 'react';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
export default function NotFoundPage() {
return (
<div className="container-fluid d-flex py-5 justify-content-center align-items-start text-center">
<p className="my-0 py-5 text-muted" style={{ maxWidth: '32em' }}>
<FormattedMessage
id="profile.notfound.message"
defaultMessage="The page you're looking for is unavailable or there's an error in the URL. Please check the URL and try again."
description="error message when a page does not exist"
/>
</p>
</div>
);
}
const NotFoundPage = () => (
<div className="container-fluid d-flex py-5 justify-content-center align-items-start text-center">
<p className="my-0 py-5 text-muted" style={{ maxWidth: '32em' }}>
<FormattedMessage
id="profile.notfound.message"
defaultMessage="The page you're looking for is unavailable or there's an error in the URL. Please check the URL and try again."
description="error message when a page does not exist"
/>
</p>
</div>
);
export default NotFoundPage;

View File

@@ -6,7 +6,7 @@ import { sendTrackingLogEvent } from '@edx/frontend-platform/analytics';
import { ensureConfig, getConfig } from '@edx/frontend-platform';
import { AppContext } from '@edx/frontend-platform/react';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { StatusAlert, Hyperlink } from '@edx/paragon';
import { Alert, Hyperlink } from '@edx/paragon';
// Actions
import {
@@ -30,8 +30,10 @@ import Bio from './forms/Bio';
import Certificates from './forms/Certificates';
import AgeMessage from './AgeMessage';
import DateJoined from './DateJoined';
import UsernameDescription from './UsernameDescription';
import PageLoading from './PageLoading';
import Banner from './Banner';
import LearningGoal from './forms/LearningGoal';
// Selectors
import { profilePageSelector } from './data/selectors';
@@ -45,10 +47,10 @@ class ProfilePage extends React.Component {
constructor(props, context) {
super(props, context);
const recordsUrl = this.getRecordsUrl(context);
const credentialsBaseUrl = context.config.CREDENTIALS_BASE_URL;
this.state = {
viewMyRecordsUrl: recordsUrl,
viewMyRecordsUrl: credentialsBaseUrl ? `${credentialsBaseUrl}/records` : null,
accountSettingsUrl: `${context.config.LMS_BASE_URL}/account/settings`,
};
@@ -67,23 +69,6 @@ class ProfilePage extends React.Component {
});
}
getRecordsUrl(context) {
let recordsUrl = null;
if (getConfig().ENABLE_LEARNER_RECORD_MFE) {
recordsUrl = getConfig().LEARNER_RECORD_MFE_BASE_URL;
} else {
const credentialsBaseUrl = context.config.CREDENTIALS_BASE_URL;
recordsUrl = credentialsBaseUrl ? `${credentialsBaseUrl}/records` : null;
}
return recordsUrl;
}
isAuthenticatedUserProfile() {
return this.props.match.params.username === this.context.authenticatedUser.username;
}
handleSaveProfilePhoto(formData) {
this.props.saveProfilePhoto(this.context.authenticatedUser.username, formData);
}
@@ -108,6 +93,18 @@ class ProfilePage extends React.Component {
this.props.updateDraft(name, value);
}
isYOBDisabled() {
const { yearOfBirth } = this.props;
const currentYear = new Date().getFullYear();
const isAgeOrNotCompliant = !yearOfBirth || ((currentYear - yearOfBirth) < 13);
return isAgeOrNotCompliant && getConfig().COLLECT_YEAR_OF_BIRTH !== 'true';
}
isAuthenticatedUserProfile() {
return this.props.match.params.username === this.context.authenticatedUser.username;
}
// Inserted into the DOM in two places (for responsive layout)
renderViewMyRecordsButton() {
if (!(this.state.viewMyRecordsUrl && this.isAuthenticatedUserProfile())) {
@@ -126,13 +123,12 @@ class ProfilePage extends React.Component {
const { dateJoined } = this.props;
return (
<>
<span data-hj-suppress>
<h1 className="h2 mb-0 font-weight-bold">{this.props.match.params.username}</h1>
<DateJoined date={dateJoined} />
<hr className="d-none d-md-block" />
</span>
</>
<span data-hj-suppress>
<h1 className="h2 mb-0 font-weight-bold text-truncate">{this.props.match.params.username}</h1>
<DateJoined date={dateJoined} />
{this.isYOBDisabled() && <UsernameDescription />}
<hr className="d-none d-md-block" />
</span>
);
}
@@ -146,7 +142,9 @@ class ProfilePage extends React.Component {
return (
<div className="row">
<div className="col-md-4 col-lg-3">
<StatusAlert alertType="danger" dialog={photoUploadError.userMessage} dismissible={false} open />
<Alert variant="danger" dismissible={false} show>
{photoUploadError.userMessage}
</Alert>
</div>
</div>
);
@@ -174,8 +172,11 @@ class ProfilePage extends React.Component {
socialLinks,
draftSocialLinksByPlatform,
visibilitySocialLinks,
learningGoal,
visibilityLearningGoal,
languageProficiencies,
visibilityLanguageProficiencies,
courseCertificates,
visibilityCourseCertificates,
bio,
visibilityBio,
@@ -194,6 +195,17 @@ class ProfilePage extends React.Component {
changeHandler: this.handleChange,
};
const isBlockVisible = (blockInfo) => this.isAuthenticatedUserProfile()
|| (!this.isAuthenticatedUserProfile() && Boolean(blockInfo));
const isLanguageBlockVisible = isBlockVisible(languageProficiencies.length);
const isEducationBlockVisible = isBlockVisible(levelOfEducation);
const isSocialLinksBLockVisible = isBlockVisible(socialLinks.some((link) => link.socialLink !== null));
const isBioBlockVisible = isBlockVisible(bio);
const isCertificatesBlockVisible = isBlockVisible(courseCertificates.length);
const isNameBlockVisible = isBlockVisible(name);
const isLocationBlockVisible = isBlockVisible(country);
return (
<div className="container-fluid">
<div className="row align-items-center pt-4 mb-4 pt-md-0 mb-md-0">
@@ -210,7 +222,7 @@ class ProfilePage extends React.Component {
/>
</div>
</div>
<div className="col pl-0">
<div className="col">
<div className="d-md-none">
{this.renderHeadingLockup()}
</div>
@@ -228,51 +240,73 @@ class ProfilePage extends React.Component {
<div className="d-md-none mb-4">
{this.renderViewMyRecordsButton()}
</div>
<Name
name={name}
visibilityName={visibilityName}
formId="name"
{...commonFormProps}
/>
<Country
country={country}
visibilityCountry={visibilityCountry}
formId="country"
{...commonFormProps}
/>
<PreferredLanguage
languageProficiencies={languageProficiencies}
visibilityLanguageProficiencies={visibilityLanguageProficiencies}
formId="languageProficiencies"
{...commonFormProps}
/>
<Education
levelOfEducation={levelOfEducation}
visibilityLevelOfEducation={visibilityLevelOfEducation}
formId="levelOfEducation"
{...commonFormProps}
/>
<SocialLinks
socialLinks={socialLinks}
draftSocialLinksByPlatform={draftSocialLinksByPlatform}
visibilitySocialLinks={visibilitySocialLinks}
formId="socialLinks"
{...commonFormProps}
/>
{isNameBlockVisible && (
<Name
name={name}
visibilityName={visibilityName}
formId="name"
{...commonFormProps}
/>
)}
{isLocationBlockVisible && (
<Country
country={country}
visibilityCountry={visibilityCountry}
formId="country"
{...commonFormProps}
/>
)}
{isLanguageBlockVisible && (
<PreferredLanguage
languageProficiencies={languageProficiencies}
visibilityLanguageProficiencies={visibilityLanguageProficiencies}
formId="languageProficiencies"
{...commonFormProps}
/>
)}
{isEducationBlockVisible && (
<Education
levelOfEducation={levelOfEducation}
visibilityLevelOfEducation={visibilityLevelOfEducation}
formId="levelOfEducation"
{...commonFormProps}
/>
)}
{isSocialLinksBLockVisible && (
<SocialLinks
socialLinks={socialLinks}
draftSocialLinksByPlatform={draftSocialLinksByPlatform}
visibilitySocialLinks={visibilitySocialLinks}
formId="socialLinks"
{...commonFormProps}
/>
)}
</div>
<div className="pt-md-3 col-md-8 col-lg-7 offset-lg-1">
{this.renderAgeMessage()}
<Bio
bio={bio}
visibilityBio={visibilityBio}
formId="bio"
{...commonFormProps}
/>
<Certificates
visibilityCourseCertificates={visibilityCourseCertificates}
formId="certificates"
{...commonFormProps}
/>
{!this.isYOBDisabled() && this.renderAgeMessage()}
{isBioBlockVisible && (
<Bio
bio={bio}
visibilityBio={visibilityBio}
formId="bio"
{...commonFormProps}
/>
)}
{getConfig().ENABLE_SKILLS_BUILDER_PROFILE && (
<LearningGoal
learningGoal={learningGoal}
visibilityLearningGoal={visibilityLearningGoal}
formId="learningGoal"
{...commonFormProps}
/>
)}
{isCertificatesBlockVisible && (
<Certificates
visibilityCourseCertificates={visibilityCourseCertificates}
formId="certificates"
{...commonFormProps}
/>
)}
</div>
</div>
</div>
@@ -298,6 +332,7 @@ ProfilePage.propTypes = {
// Bio form data
bio: PropTypes.string,
yearOfBirth: PropTypes.number,
visibilityBio: PropTypes.string.isRequired,
// Certificates form data
@@ -335,6 +370,10 @@ ProfilePage.propTypes = {
})),
visibilitySocialLinks: PropTypes.string.isRequired,
// Learning Goal form data
learningGoal: PropTypes.string,
visibilityLearningGoal: PropTypes.string,
// Other data we need
profileImage: PropTypes.shape({
src: PropTypes.string,
@@ -373,15 +412,18 @@ ProfilePage.defaultProps = {
photoUploadError: {},
profileImage: {},
name: null,
yearOfBirth: null,
levelOfEducation: null,
country: null,
socialLinks: [],
draftSocialLinksByPlatform: {},
bio: null,
learningGoal: null,
languageProficiencies: [],
courseCertificates: null,
requiresParentalConsent: null,
dateJoined: null,
visibilityLearningGoal: null,
};
export default connect(

View File

@@ -5,6 +5,7 @@ import { AppContext } from '@edx/frontend-platform/react';
import { configure as configureI18n, IntlProvider } from '@edx/frontend-platform/i18n';
import { mount } from 'enzyme';
import React from 'react';
import PropTypes from 'prop-types';
import { Provider } from 'react-redux';
import renderer from 'react-test-renderer';
import configureMockStore from 'redux-mock-store';
@@ -15,10 +16,10 @@ import ProfilePage from './ProfilePage';
const mockStore = configureMockStore([thunk]);
const storeMocks = {
loadingApp: require('./__mocks__/loadingApp.mockStore.js'),
viewOwnProfile: require('./__mocks__/viewOwnProfile.mockStore.js'),
viewOtherProfile: require('./__mocks__/viewOtherProfile.mockStore.js'),
savingEditedBio: require('./__mocks__/savingEditedBio.mockStore.js'),
loadingApp: require('./__mocks__/loadingApp.mockStore'),
viewOwnProfile: require('./__mocks__/viewOwnProfile.mockStore'),
viewOtherProfile: require('./__mocks__/viewOtherProfile.mockStore'),
savingEditedBio: require('./__mocks__/savingEditedBio.mockStore'),
};
const requiredProfilePageProps = {
fetchUserAccount: () => {},
@@ -65,82 +66,170 @@ beforeEach(() => {
analytics.sendTrackingLogEvent.mockReset();
});
const ProfilePageWrapper = ({
contextValue, store, match, requiresParentalConsent,
}) => (
<AppContext.Provider
value={contextValue}
>
<IntlProvider locale="en">
<Provider store={store}>
<ProfilePage {...requiredProfilePageProps} match={match} requiresParentalConsent={requiresParentalConsent} />
</Provider>
</IntlProvider>
</AppContext.Provider>
);
ProfilePageWrapper.defaultProps = {
match: { params: { username: 'staff' } },
requiresParentalConsent: null,
};
ProfilePageWrapper.propTypes = {
contextValue: PropTypes.shape({}).isRequired,
store: PropTypes.shape({}).isRequired,
match: PropTypes.shape({}),
requiresParentalConsent: PropTypes.bool,
};
describe('<ProfilePage />', () => {
describe('Renders correctly in various states', () => {
it('app loading', () => {
const component = (
<AppContext.Provider
value={{
authenticatedUser: { userId: null, username: null, administrator: false },
config: getConfig(),
}}
>
<IntlProvider locale="en">
<Provider store={mockStore(storeMocks.loadingApp)}>
<ProfilePage {...requiredProfilePageProps} />
</Provider>
</IntlProvider>
</AppContext.Provider>
);
const contextValue = {
authenticatedUser: { userId: null, username: null, administrator: false },
config: getConfig(),
};
const component = <ProfilePageWrapper contextValue={contextValue} store={mockStore(storeMocks.loadingApp)} />;
const tree = renderer.create(component).toJSON();
expect(tree).toMatchSnapshot();
});
it('viewing own profile', () => {
const component = (
<AppContext.Provider
value={{
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config: getConfig(),
}}
>
<IntlProvider locale="en">
<Provider store={mockStore(storeMocks.viewOwnProfile)}>
<ProfilePage {...requiredProfilePageProps} />
</Provider>
</IntlProvider>
</AppContext.Provider>
);
const contextValue = {
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config: getConfig(),
};
const component = <ProfilePageWrapper contextValue={contextValue} store={mockStore(storeMocks.viewOwnProfile)} />;
const tree = renderer.create(component).toJSON();
expect(tree).toMatchSnapshot();
});
it('viewing other profile', () => {
it('viewing other profile with all fields', () => {
const contextValue = {
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config: getConfig(),
};
const component = (
<AppContext.Provider
value={{
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config: getConfig(),
}}
>
<IntlProvider locale="en">
<Provider store={mockStore(storeMocks.viewOtherProfile)}>
<ProfilePage
{...requiredProfilePageProps}
match={{ params: { username: 'verified' } }} // Override default match
/>
</Provider>
</IntlProvider>
</AppContext.Provider>
<ProfilePageWrapper
contextValue={contextValue}
store={mockStore({
...storeMocks.viewOtherProfile,
profilePage: {
...storeMocks.viewOtherProfile.profilePage,
account: {
...storeMocks.viewOtherProfile.profilePage.account,
name: 'user',
country: 'EN',
bio: 'bio',
courseCertificates: ['course certificates'],
levelOfEducation: 'some level',
languageProficiencies: ['some lang'],
socialLinks: ['twitter'],
timeZone: 'time zone',
accountPrivacy: 'all_users',
},
},
})}
match={{ params: { username: 'verified' } }} // Override default match
/>
);
const tree = renderer.create(component).toJSON();
expect(tree).toMatchSnapshot();
});
it('while saving an edited bio', () => {
const contextValue = {
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config: getConfig(),
};
const component = (
<AppContext.Provider
value={{
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config: getConfig(),
}}
>
<IntlProvider locale="en">
<Provider store={mockStore(storeMocks.savingEditedBio)}>
<ProfilePage {...requiredProfilePageProps} />
</Provider>
</IntlProvider>
</AppContext.Provider>
<ProfilePageWrapper
contextValue={contextValue}
store={mockStore(storeMocks.savingEditedBio)}
/>
);
const tree = renderer.create(component).toJSON();
expect(tree).toMatchSnapshot();
});
it('while saving an edited bio with error', () => {
const storeData = JSON.parse(JSON.stringify(storeMocks.savingEditedBio));
storeData.profilePage.errors.bio = { userMessage: 'bio error' };
const contextValue = {
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config: getConfig(),
};
const component = (
<ProfilePageWrapper
contextValue={contextValue}
store={mockStore(storeData)}
/>
);
const tree = renderer.create(component).toJSON();
expect(tree).toMatchSnapshot();
});
it('test country edit with error', () => {
const storeData = JSON.parse(JSON.stringify(storeMocks.savingEditedBio));
storeData.profilePage.errors.country = { userMessage: 'country error' };
storeData.profilePage.currentlyEditingField = 'country';
const contextValue = {
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config: getConfig(),
};
const component = (
<ProfilePageWrapper
contextValue={contextValue}
store={mockStore(storeData)}
/>
);
const tree = renderer.create(component).toJSON();
expect(tree).toMatchSnapshot();
});
it('test education edit with error', () => {
const storeData = JSON.parse(JSON.stringify(storeMocks.savingEditedBio));
storeData.profilePage.errors.levelOfEducation = { userMessage: 'education error' };
storeData.profilePage.currentlyEditingField = 'levelOfEducation';
const contextValue = {
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config: getConfig(),
};
const component = (
<ProfilePageWrapper
contextValue={contextValue}
store={mockStore(storeData)}
/>
);
const tree = renderer.create(component).toJSON();
expect(tree).toMatchSnapshot();
});
it('test preferreded language edit with error', () => {
const storeData = JSON.parse(JSON.stringify(storeMocks.savingEditedBio));
storeData.profilePage.errors.languageProficiencies = { userMessage: 'preferred language error' };
storeData.profilePage.currentlyEditingField = 'languageProficiencies';
const contextValue = {
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config: getConfig(),
};
const component = (
<ProfilePageWrapper
contextValue={contextValue}
store={mockStore(storeData)}
/>
);
const tree = renderer.create(component).toJSON();
expect(tree).toMatchSnapshot();
@@ -150,43 +239,66 @@ describe('<ProfilePage />', () => {
const config = getConfig();
config.CREDENTIALS_BASE_URL = '';
const contextValue = {
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config: getConfig(),
};
const component = (
<AppContext.Provider
value={{
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config,
}}
>
<IntlProvider locale="en">
<Provider store={mockStore(storeMocks.viewOwnProfile)}>
<ProfilePage {...requiredProfilePageProps} />
</Provider>
</IntlProvider>
</AppContext.Provider>
<ProfilePageWrapper
contextValue={contextValue}
store={mockStore(storeMocks.viewOwnProfile)}
/>
);
const tree = renderer.create(component).toJSON();
expect(tree).toMatchSnapshot();
});
it('test age message alert', () => {
const storeData = JSON.parse(JSON.stringify(storeMocks.viewOwnProfile));
storeData.userAccount.requiresParentalConsent = true;
storeData.profilePage.account.requiresParentalConsent = true;
const contextValue = {
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config: { ...getConfig(), COLLECT_YEAR_OF_BIRTH: true },
};
const component = (
<ProfilePageWrapper
contextValue={contextValue}
store={mockStore(storeData)}
requiresParentalConsent
/>
);
const wrapper = mount(component);
wrapper.update();
expect(wrapper.find('.alert-info').hasClass('show')).toBe(true);
});
it('test photo error alert', () => {
const storeData = JSON.parse(JSON.stringify(storeMocks.viewOwnProfile));
storeData.profilePage.errors.photo = { userMessage: 'error' };
const contextValue = {
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config: { ...getConfig(), COLLECT_YEAR_OF_BIRTH: true },
};
const component = <ProfilePageWrapper contextValue={contextValue} store={mockStore(storeData)} />;
const wrapper = mount(component);
wrapper.update();
expect(wrapper.find('.alert-danger').hasClass('show')).toBe(true);
});
});
describe('handles analytics', () => {
it('calls sendTrackingLogEvent when mounting', () => {
const contextValue = {
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config: getConfig(),
};
const component = (
<AppContext.Provider
value={{
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config: getConfig(),
}}
>
<IntlProvider locale="en">
<Provider store={mockStore(storeMocks.loadingApp)}>
<ProfilePage
{...requiredProfilePageProps}
match={{ params: { username: 'test-username' } }}
/>
</Provider>
</IntlProvider>
</AppContext.Provider>
<ProfilePageWrapper
contextValue={contextValue}
store={mockStore(storeMocks.loadingApp)}
match={{ params: { username: 'test-username' } }}
/>
);
const wrapper = mount(component);
wrapper.update();

View File

@@ -0,0 +1,23 @@
import React from 'react';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import { VisibilityOff } from '@edx/paragon/icons';
import { Icon } from '@edx/paragon';
import { getConfig } from '@edx/frontend-platform';
const UsernameDescription = () => (
<div className="d-flex align-items-center mt-3 mb-2rem">
<Icon src={VisibilityOff} className="icon-visibility-off" />
<div className="username-description">
<FormattedMessage
id="profile.username.description"
defaultMessage="Your profile information is only visible to you. Only your username is visible to others on {siteName}."
description="A description of the username field"
values={{
siteName: getConfig().SITE_NAME,
}}
/>
</div>
</div>
);
export default UsernameDescription;

View File

@@ -12,7 +12,8 @@ module.exports = {
imageUrlMedium: null,
imageUrlLarge: null
},
levelOfEducation: null
levelOfEducation: null,
learningGoal: null
},
profilePage: {
errors: {},

View File

@@ -42,7 +42,8 @@ module.exports = {
secondaryEmail: null,
timeZone: null,
gender: null,
accountPrivacy: 'custom'
accountPrivacy: 'custom',
learningGoal: null,
},
profilePage: {
errors: {},
@@ -91,7 +92,8 @@ module.exports = {
timeZone: null,
levelOfEducation: 'el',
gender: null,
accountPrivacy: 'custom'
accountPrivacy: 'custom',
learningGoal: null,
},
preferences: {
visibilityUserLocation: 'all_users',
@@ -104,7 +106,8 @@ module.exports = {
visibilityName: 'private',
visibilityLanguageProficiencies: 'all_users',
visibilityCountry: 'all_users',
accountPrivacy: 'custom'
accountPrivacy: 'custom',
visibilityLearningGoal: 'private',
},
courseCertificates: [
{

View File

@@ -42,7 +42,8 @@ module.exports = {
secondaryEmail: null,
timeZone: null,
gender: null,
accountPrivacy: 'custom'
accountPrivacy: 'custom',
learningGoal: 'advance_career',
},
profilePage: {
errors: {},
@@ -83,7 +84,8 @@ module.exports = {
preferences: {},
courseCertificates: [],
drafts: {},
isLoadingProfile: false
isLoadingProfile: false,
learningGoal: 'advance_career',
},
router: {
location: {

View File

@@ -42,7 +42,8 @@ module.exports = {
secondaryEmail: null,
timeZone: null,
gender: null,
accountPrivacy: 'custom'
accountPrivacy: 'custom',
learningGoal: 'advance_career'
},
profilePage: {
errors: {},
@@ -91,7 +92,8 @@ module.exports = {
timeZone: null,
levelOfEducation: 'el',
gender: null,
accountPrivacy: 'custom'
accountPrivacy: 'custom',
learningGoal: 'advance_career'
},
preferences: {
visibilityUserLocation: 'all_users',
@@ -104,7 +106,8 @@ module.exports = {
visibilityName: 'private',
visibilityLanguageProficiencies: 'all_users',
visibilityCountry: 'all_users',
accountPrivacy: 'custom'
accountPrivacy: 'custom',
visibilityLearningGoal: 'private',
},
courseCertificates: [
{

View File

@@ -5,7 +5,7 @@ exports[`<ProfilePage /> Renders correctly in various states app loading 1`] = `
className="profile-page"
>
<div
className="profile-page-bg-banner bg-primary d-none d-md-block p-relative"
className="profile-page-bg-banner bg-primary d-md-block p-relative"
/>
<div>
<div
@@ -31,196 +31,12 @@ exports[`<ProfilePage /> Renders correctly in various states app loading 1`] = `
</div>
`;
exports[`<ProfilePage /> Renders correctly in various states viewing other profile 1`] = `
exports[`<ProfilePage /> Renders correctly in various states test country edit with error 1`] = `
<div
className="profile-page"
>
<div
className="profile-page-bg-banner bg-primary d-none d-md-block p-relative"
/>
<div
className="container-fluid"
>
<div
className="row align-items-center pt-4 mb-4 pt-md-0 mb-md-0"
>
<div
className="col-auto col-md-4 col-lg-3"
>
<div
className="d-flex align-items-center d-md-block"
>
<div
className="profile-avatar-wrap position-relative"
>
<div
className="profile-avatar rounded-circle bg-light"
>
<IconMock
aria-hidden={true}
className="text-muted"
focusable="false"
role="img"
viewBox="0 0 24 24"
/>
</div>
<form
encType="multipart/form-data"
onSubmit={[Function]}
>
<input
accept=".jpg, .jpeg, .png"
className="d-none form-control-file"
id="photo-file"
name="file"
onChange={[Function]}
type="file"
/>
</form>
</div>
</div>
</div>
<div
className="col pl-0"
>
<div
className="d-md-none"
>
<span
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold"
>
verified
</h1>
<p
className="mb-0"
>
<span>
Member since
<span>
2017
</span>
</span>
</p>
<hr
className="d-none d-md-block"
/>
</span>
</div>
<div
className="d-none d-md-block float-right"
/>
</div>
</div>
<div
className="row"
>
<div
className="col-md-4 col-lg-4"
>
<div
className="d-none d-md-block mb-4"
>
<span
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold"
>
verified
</h1>
<p
className="mb-0"
>
<span>
Member since
<span>
2017
</span>
</span>
</p>
<hr
className="d-none d-md-block"
/>
</span>
</div>
<div
className="d-md-none mb-4"
/>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
/>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
/>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
/>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
/>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
/>
</div>
<div
className="pt-md-3 col-md-8 col-lg-7 offset-lg-1"
>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
/>
<div
className="pgn-transition-replace-group position-relative mb-4"
style={
Object {
"height": null,
}
}
/>
</div>
</div>
</div>
</div>
`;
exports[`<ProfilePage /> Renders correctly in various states viewing own profile 1`] = `
<div
className="profile-page"
>
<div
className="profile-page-bg-banner bg-primary d-none d-md-block p-relative"
className="profile-page-bg-banner bg-primary d-md-block p-relative"
/>
<div
className="container-fluid"
@@ -244,7 +60,8 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
className="profile-avatar-menu-container"
>
<div
className="dropdown"
className="pgn__dropdown pgn__dropdown-light dropdown"
data-testid="dropdown"
>
<button
aria-expanded={false}
@@ -287,7 +104,7 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
</div>
</div>
<div
className="col pl-0"
className="col"
>
<div
className="d-md-none"
@@ -296,19 +113,15 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold"
className="h2 mb-0 font-weight-bold text-truncate"
>
staff
</h1>
<p
className="mb-0"
>
<span>
Member since
<span>
2017
</span>
</span>
Member since
2017
</p>
<hr
className="d-none d-md-block"
@@ -319,17 +132,17 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
className="d-none d-md-block float-right"
>
<a
className="btn btn-primary"
className="pgn__hyperlink default-link standalone-link btn btn-primary"
href="http://localhost:18150/records"
onClick={[Function]}
rel="noopener"
rel="noopener noreferrer"
target="_blank"
>
View My Records
<span
className="d-inline-block align-text-top"
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
@@ -341,7 +154,6 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
>
<svg
aria-hidden={true}
aria-label=""
fill="none"
focusable={false}
height={24}
@@ -355,6 +167,11 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
@@ -374,19 +191,15 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold"
className="h2 mb-0 font-weight-bold text-truncate"
>
staff
</h1>
<p
className="mb-0"
>
<span>
Member since
<span>
2017
</span>
</span>
Member since
2017
</p>
<hr
className="d-none d-md-block"
@@ -397,17 +210,17 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
className="d-md-none mb-4"
>
<a
className="btn btn-primary"
className="pgn__hyperlink default-link standalone-link btn btn-primary"
href="http://localhost:18150/records"
onClick={[Function]}
rel="noopener"
rel="noopener noreferrer"
target="_blank"
>
View My Records
<span
className="d-inline-block align-text-top"
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
@@ -419,7 +232,6 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
>
<svg
aria-hidden={true}
aria-label=""
fill="none"
focusable={false}
height={24}
@@ -433,6 +245,11 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
@@ -548,78 +365,1409 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
}
>
<div
className="editable-item-header mb-2"
aria-labelledby="country-label"
role="dialog"
>
<h2
className="edit-section-header"
id={null}
<form
onSubmit={[Function]}
>
Location
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
<div
className="pgn__form-group"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
<label
className="edit-section-header"
htmlFor="country"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
Location
</label>
<select
className="form-control"
data-hj-suppress={true}
id="country"
name="country"
onChange={[Function]}
type="select"
value="ME"
>
<option
value=""
>
 
</option>
<option
value="AF"
>
Afghanistan
</option>
<option
value="AL"
>
Albania
</option>
<option
value="DZ"
>
Algeria
</option>
<option
value="AS"
>
American Samoa
</option>
<option
value="AD"
>
Andorra
</option>
<option
value="AO"
>
Angola
</option>
<option
value="AI"
>
Anguilla
</option>
<option
value="AQ"
>
Antarctica
</option>
<option
value="AG"
>
Antigua and Barbuda
</option>
<option
value="AR"
>
Argentina
</option>
<option
value="AM"
>
Armenia
</option>
<option
value="AW"
>
Aruba
</option>
<option
value="AU"
>
Australia
</option>
<option
value="AT"
>
Austria
</option>
<option
value="AZ"
>
Azerbaijan
</option>
<option
value="BS"
>
Bahamas
</option>
<option
value="BH"
>
Bahrain
</option>
<option
value="BD"
>
Bangladesh
</option>
<option
value="BB"
>
Barbados
</option>
<option
value="BY"
>
Belarus
</option>
<option
value="BE"
>
Belgium
</option>
<option
value="BZ"
>
Belize
</option>
<option
value="BJ"
>
Benin
</option>
<option
value="BM"
>
Bermuda
</option>
<option
value="BT"
>
Bhutan
</option>
<option
value="BO"
>
Bolivia
</option>
<option
value="BA"
>
Bosnia and Herzegovina
</option>
<option
value="BW"
>
Botswana
</option>
<option
value="BV"
>
Bouvet Island
</option>
<option
value="BR"
>
Brazil
</option>
<option
value="IO"
>
British Indian Ocean Territory
</option>
<option
value="BN"
>
Brunei Darussalam
</option>
<option
value="BG"
>
Bulgaria
</option>
<option
value="BF"
>
Burkina Faso
</option>
<option
value="BI"
>
Burundi
</option>
<option
value="KH"
>
Cambodia
</option>
<option
value="CM"
>
Cameroon
</option>
<option
value="CA"
>
Canada
</option>
<option
value="CV"
>
Cape Verde
</option>
<option
value="KY"
>
Cayman Islands
</option>
<option
value="CF"
>
Central African Republic
</option>
<option
value="TD"
>
Chad
</option>
<option
value="CL"
>
Chile
</option>
<option
value="CN"
>
China
</option>
<option
value="CX"
>
Christmas Island
</option>
<option
value="CC"
>
Cocos (Keeling) Islands
</option>
<option
value="CO"
>
Colombia
</option>
<option
value="KM"
>
Comoros
</option>
<option
value="CG"
>
Congo
</option>
<option
value="CD"
>
Congo, the Democratic Republic of the
</option>
<option
value="CK"
>
Cook Islands
</option>
<option
value="CR"
>
Costa Rica
</option>
<option
value="CI"
>
Cote D'Ivoire
</option>
<option
value="HR"
>
Croatia
</option>
<option
value="CU"
>
Cuba
</option>
<option
value="CY"
>
Cyprus
</option>
<option
value="CZ"
>
Czech Republic
</option>
<option
value="DK"
>
Denmark
</option>
<option
value="DJ"
>
Djibouti
</option>
<option
value="DM"
>
Dominica
</option>
<option
value="DO"
>
Dominican Republic
</option>
<option
value="EC"
>
Ecuador
</option>
<option
value="EG"
>
Egypt
</option>
<option
value="SV"
>
El Salvador
</option>
<option
value="GQ"
>
Equatorial Guinea
</option>
<option
value="ER"
>
Eritrea
</option>
<option
value="EE"
>
Estonia
</option>
<option
value="ET"
>
Ethiopia
</option>
<option
value="FK"
>
Falkland Islands (Malvinas)
</option>
<option
value="FO"
>
Faroe Islands
</option>
<option
value="FJ"
>
Fiji
</option>
<option
value="FI"
>
Finland
</option>
<option
value="FR"
>
France
</option>
<option
value="GF"
>
French Guiana
</option>
<option
value="PF"
>
French Polynesia
</option>
<option
value="TF"
>
French Southern Territories
</option>
<option
value="GA"
>
Gabon
</option>
<option
value="GM"
>
Gambia
</option>
<option
value="GE"
>
Georgia
</option>
<option
value="DE"
>
Germany
</option>
<option
value="GH"
>
Ghana
</option>
<option
value="GI"
>
Gibraltar
</option>
<option
value="GR"
>
Greece
</option>
<option
value="GL"
>
Greenland
</option>
<option
value="GD"
>
Grenada
</option>
<option
value="GP"
>
Guadeloupe
</option>
<option
value="GU"
>
Guam
</option>
<option
value="GT"
>
Guatemala
</option>
<option
value="GN"
>
Guinea
</option>
<option
value="GW"
>
Guinea-Bissau
</option>
<option
value="GY"
>
Guyana
</option>
<option
value="HT"
>
Haiti
</option>
<option
value="HM"
>
Heard Island and Mcdonald Islands
</option>
<option
value="VA"
>
Holy See (Vatican City State)
</option>
<option
value="HN"
>
Honduras
</option>
<option
value="HK"
>
Hong Kong
</option>
<option
value="HU"
>
Hungary
</option>
<option
value="IS"
>
Iceland
</option>
<option
value="IN"
>
India
</option>
<option
value="ID"
>
Indonesia
</option>
<option
value="IR"
>
Iran, Islamic Republic of
</option>
<option
value="IQ"
>
Iraq
</option>
<option
value="IE"
>
Ireland
</option>
<option
value="IL"
>
Israel
</option>
<option
value="IT"
>
Italy
</option>
<option
value="JM"
>
Jamaica
</option>
<option
value="JP"
>
Japan
</option>
<option
value="JO"
>
Jordan
</option>
<option
value="KZ"
>
Kazakhstan
</option>
<option
value="KE"
>
Kenya
</option>
<option
value="KI"
>
Kiribati
</option>
<option
value="KP"
>
North Korea
</option>
<option
value="KR"
>
South Korea
</option>
<option
value="KW"
>
Kuwait
</option>
<option
value="KG"
>
Kyrgyzstan
</option>
<option
value="LA"
>
Lao People's Democratic Republic
</option>
<option
value="LV"
>
Latvia
</option>
<option
value="LB"
>
Lebanon
</option>
<option
value="LS"
>
Lesotho
</option>
<option
value="LR"
>
Liberia
</option>
<option
value="LY"
>
Libya
</option>
<option
value="LI"
>
Liechtenstein
</option>
<option
value="LT"
>
Lithuania
</option>
<option
value="LU"
>
Luxembourg
</option>
<option
value="MO"
>
Macao
</option>
<option
value="MG"
>
Madagascar
</option>
<option
value="MW"
>
Malawi
</option>
<option
value="MY"
>
Malaysia
</option>
<option
value="MV"
>
Maldives
</option>
<option
value="ML"
>
Mali
</option>
<option
value="MT"
>
Malta
</option>
<option
value="MH"
>
Marshall Islands
</option>
<option
value="MQ"
>
Martinique
</option>
<option
value="MR"
>
Mauritania
</option>
<option
value="MU"
>
Mauritius
</option>
<option
value="YT"
>
Mayotte
</option>
<option
value="MX"
>
Mexico
</option>
<option
value="FM"
>
Micronesia, Federated States of
</option>
<option
value="MD"
>
Moldova, Republic of
</option>
<option
value="MC"
>
Monaco
</option>
<option
value="MN"
>
Mongolia
</option>
<option
value="MS"
>
Montserrat
</option>
<option
value="MA"
>
Morocco
</option>
<option
value="MZ"
>
Mozambique
</option>
<option
value="MM"
>
Myanmar
</option>
<option
value="NA"
>
Namibia
</option>
<option
value="NR"
>
Nauru
</option>
<option
value="NP"
>
Nepal
</option>
<option
value="NL"
>
Netherlands
</option>
<option
value="NC"
>
New Caledonia
</option>
<option
value="NZ"
>
New Zealand
</option>
<option
value="NI"
>
Nicaragua
</option>
<option
value="NE"
>
Niger
</option>
<option
value="NG"
>
Nigeria
</option>
<option
value="NU"
>
Niue
</option>
<option
value="NF"
>
Norfolk Island
</option>
<option
value="MK"
>
North Macedonia, Republic of
</option>
<option
value="MP"
>
Northern Mariana Islands
</option>
<option
value="NO"
>
Norway
</option>
<option
value="OM"
>
Oman
</option>
<option
value="PK"
>
Pakistan
</option>
<option
value="PW"
>
Palau
</option>
<option
value="PS"
>
Palestinian Territory, Occupied
</option>
<option
value="PA"
>
Panama
</option>
<option
value="PG"
>
Papua New Guinea
</option>
<option
value="PY"
>
Paraguay
</option>
<option
value="PE"
>
Peru
</option>
<option
value="PH"
>
Philippines
</option>
<option
value="PN"
>
Pitcairn
</option>
<option
value="PL"
>
Poland
</option>
<option
value="PT"
>
Portugal
</option>
<option
value="PR"
>
Puerto Rico
</option>
<option
value="QA"
>
Qatar
</option>
<option
value="RE"
>
Reunion
</option>
<option
value="RO"
>
Romania
</option>
<option
value="RU"
>
Russian Federation
</option>
<option
value="RW"
>
Rwanda
</option>
<option
value="SH"
>
Saint Helena
</option>
<option
value="KN"
>
Saint Kitts and Nevis
</option>
<option
value="LC"
>
Saint Lucia
</option>
<option
value="PM"
>
Saint Pierre and Miquelon
</option>
<option
value="VC"
>
Saint Vincent and the Grenadines
</option>
<option
value="WS"
>
Samoa
</option>
<option
value="SM"
>
San Marino
</option>
<option
value="ST"
>
Sao Tome and Principe
</option>
<option
value="SA"
>
Saudi Arabia
</option>
<option
value="SN"
>
Senegal
</option>
<option
value="SC"
>
Seychelles
</option>
<option
value="SL"
>
Sierra Leone
</option>
<option
value="SG"
>
Singapore
</option>
<option
value="SK"
>
Slovakia
</option>
<option
value="SI"
>
Slovenia
</option>
<option
value="SB"
>
Solomon Islands
</option>
<option
value="SO"
>
Somalia
</option>
<option
value="ZA"
>
South Africa
</option>
<option
value="GS"
>
South Georgia and the South Sandwich Islands
</option>
<option
value="ES"
>
Spain
</option>
<option
value="LK"
>
Sri Lanka
</option>
<option
value="SD"
>
Sudan
</option>
<option
value="SR"
>
Suriname
</option>
<option
value="SJ"
>
Svalbard and Jan Mayen
</option>
<option
value="SZ"
>
Swaziland
</option>
<option
value="SE"
>
Sweden
</option>
<option
value="CH"
>
Switzerland
</option>
<option
value="SY"
>
Syrian Arab Republic
</option>
<option
value="TW"
>
Taiwan
</option>
<option
value="TJ"
>
Tajikistan
</option>
<option
value="TZ"
>
Tanzania, United Republic of
</option>
<option
value="TH"
>
Thailand
</option>
<option
value="TL"
>
Timor-Leste
</option>
<option
value="TG"
>
Togo
</option>
<option
value="TK"
>
Tokelau
</option>
<option
value="TO"
>
Tonga
</option>
<option
value="TT"
>
Trinidad and Tobago
</option>
<option
value="TN"
>
Tunisia
</option>
<option
value="TR"
>
Turkey
</option>
<option
value="TM"
>
Turkmenistan
</option>
<option
value="TC"
>
Turks and Caicos Islands
</option>
<option
value="TV"
>
Tuvalu
</option>
<option
value="UG"
>
Uganda
</option>
<option
value="UA"
>
Ukraine
</option>
<option
value="AE"
>
United Arab Emirates
</option>
<option
value="GB"
>
United Kingdom
</option>
<option
value="US"
>
United States of America
</option>
<option
value="UM"
>
United States Minor Outlying Islands
</option>
<option
value="UY"
>
Uruguay
</option>
<option
value="UZ"
>
Uzbekistan
</option>
<option
value="VU"
>
Vanuatu
</option>
<option
value="VE"
>
Venezuela
</option>
<option
value="VN"
>
Viet Nam
</option>
<option
value="VG"
>
Virgin Islands, British
</option>
<option
value="VI"
>
Virgin Islands, U.S.
</option>
<option
value="WF"
>
Wallis and Futuna
</option>
<option
value="EH"
>
Western Sahara
</option>
<option
value="YE"
>
Yemen
</option>
<option
value="ZM"
>
Zambia
</option>
<option
value="ZW"
>
Zimbabwe
</option>
<option
value="AX"
>
Åland Islands
</option>
<option
value="BQ"
>
Bonaire, Sint Eustatius and Saba
</option>
<option
value="CW"
>
Curaçao
</option>
<option
value="GG"
>
Guernsey
</option>
<option
value="IM"
>
Isle of Man
</option>
<option
value="JE"
>
Jersey
</option>
<option
value="ME"
>
Montenegro
</option>
<option
value="BL"
>
Saint Barthélemy
</option>
<option
value="MF"
>
Saint Martin (French part)
</option>
<option
value="RS"
>
Serbia
</option>
<option
value="SX"
>
Sint Maarten (Dutch part)
</option>
<option
value="SS"
>
South Sudan
</option>
<option
value="XK"
>
Kosovo
</option>
</select>
<div
className="pgn__form-control-description pgn__form-text pgn__form-text-invalid"
id="country-2"
>
country error
</div>
</div>
<div
className="d-flex flex-row-reverse flex-wrap justify-content-end align-items-center"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
<div
className="form-group d-flex flex-wrap"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on edX
</span>
</p>
<label
className="col-form-label"
htmlFor="visibilityCountry"
>
Who can see this:
</label>
<span
className="d-flex align-items-center"
>
<span
className="d-inline-block ml-1 mr-2"
style={
Object {
"width": "1.5rem",
}
}
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
</span>
<select
className="d-inline-block form-control"
id="visibilityCountry"
name="visibilityCountry"
onChange={[Function]}
type="select"
value="all_users"
>
<option
value="private"
>
Just me
</option>
<option
value="all_users"
>
Everyone on localhost
</option>
</select>
</span>
</div>
<div
className="form-group flex-shrink-0 flex-grow-1"
>
<button
aria-disabled={false}
aria-live="assertive"
className="pgn__stateful-btn pgn__stateful-btn-state-pending btn btn-primary"
disabled={false}
onClick={[Function]}
type="submit"
>
<span
className="d-flex align-items-center justify-content-center"
>
<span
className="pgn__stateful-btn-icon"
>
<span
className="pgn__icon icon-spin"
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M22 12A10 10 0 116.122 3.91l1.176 1.618A8 8 0 1020 12h2z"
fill="currentColor"
/>
</svg>
</span>
</span>
<span>
Saving
</span>
</span>
</button>
<button
className="btn btn-link"
disabled={false}
onClick={[Function]}
type="button"
>
Cancel
</button>
</div>
</div>
</form>
</div>
<p
className="h5"
data-hj-suppress={true}
>
Montenegro
</p>
</div>
</div>
<div
@@ -700,7 +1848,7 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
/>
</svg>
Everyone on edX
Everyone on localhost
</span>
</p>
</div>
@@ -880,7 +2028,7 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
/>
</svg>
Everyone on edX
Everyone on localhost
</span>
</p>
</div>
@@ -1059,7 +2207,7 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
/>
</svg>
Everyone on edX
Everyone on localhost
</span>
</p>
</div>
@@ -1149,7 +2297,7 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
/>
</svg>
Everyone on edX
Everyone on localhost
</span>
</p>
</div>
@@ -1157,7 +2305,7 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
className="row align-items-stretch"
>
<div
className="col col-sm-6 d-flex align-items-stretch"
className="col-12 col-sm-6 d-flex align-items-stretch"
>
<div
className="card mb-4 certificate flex-grow-1"
@@ -1190,9 +2338,7 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
<p
className="small mb-0"
>
<span>
From
</span>
From
</p>
<p
className="h6 mb-4"
@@ -1205,26 +2351,22 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
<p
className="small mb-2"
>
<span>
Completed on
<span>
3/4/2019
</span>
</span>
Completed on
3/4/2019
</p>
<div>
<a
className="btn btn-outline-primary"
className="pgn__hyperlink default-link standalone-link btn btn-outline-primary"
href="http://www.example.com/"
onClick={[Function]}
rel="noopener"
rel="noopener noreferrer"
target="_blank"
>
View Certificate
<span
className="d-inline-block align-text-top"
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
@@ -1236,7 +2378,6 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
>
<svg
aria-hidden={true}
aria-label=""
fill="none"
focusable={false}
height={24}
@@ -1250,6 +2391,11 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
@@ -1266,12 +2412,12 @@ exports[`<ProfilePage /> Renders correctly in various states viewing own profile
</div>
`;
exports[`<ProfilePage /> Renders correctly in various states while saving an edited bio 1`] = `
exports[`<ProfilePage /> Renders correctly in various states test education edit with error 1`] = `
<div
className="profile-page"
>
<div
className="profile-page-bg-banner bg-primary d-none d-md-block p-relative"
className="profile-page-bg-banner bg-primary d-md-block p-relative"
/>
<div
className="container-fluid"
@@ -1295,7 +2441,8 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
className="profile-avatar-menu-container"
>
<div
className="dropdown"
className="pgn__dropdown pgn__dropdown-light dropdown"
data-testid="dropdown"
>
<button
aria-expanded={false}
@@ -1338,7 +2485,7 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
</div>
</div>
<div
className="col pl-0"
className="col"
>
<div
className="d-md-none"
@@ -1347,19 +2494,15 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold"
className="h2 mb-0 font-weight-bold text-truncate"
>
staff
</h1>
<p
className="mb-0"
>
<span>
Member since
<span>
2017
</span>
</span>
Member since
2017
</p>
<hr
className="d-none d-md-block"
@@ -1370,17 +2513,17 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
className="d-none d-md-block float-right"
>
<a
className="btn btn-primary"
className="pgn__hyperlink default-link standalone-link btn btn-primary"
href="http://localhost:18150/records"
onClick={[Function]}
rel="noopener"
rel="noopener noreferrer"
target="_blank"
>
View My Records
<span
className="d-inline-block align-text-top"
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
@@ -1392,7 +2535,6 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
>
<svg
aria-hidden={true}
aria-label=""
fill="none"
focusable={false}
height={24}
@@ -1406,6 +2548,11 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
@@ -1425,19 +2572,15 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold"
className="h2 mb-0 font-weight-bold text-truncate"
>
staff
</h1>
<p
className="mb-0"
>
<span>
Member since
<span>
2017
</span>
</span>
Member since
2017
</p>
<hr
className="d-none d-md-block"
@@ -1448,17 +2591,17 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
className="d-md-none mb-4"
>
<a
className="btn btn-primary"
className="pgn__hyperlink default-link standalone-link btn btn-primary"
href="http://localhost:18150/records"
onClick={[Function]}
rel="noopener"
rel="noopener noreferrer"
target="_blank"
>
View My Records
<span
className="d-inline-block align-text-top"
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
@@ -1470,7 +2613,6 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
>
<svg
aria-hidden={true}
aria-label=""
fill="none"
focusable={false}
height={24}
@@ -1484,6 +2626,11 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
@@ -1661,7 +2808,7 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
/>
</svg>
Everyone on edX
Everyone on localhost
</span>
</p>
</div>
@@ -1751,7 +2898,3569 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
/>
</svg>
Everyone on edX
Everyone on localhost
</span>
</p>
</div>
<p
className="h5"
data-hj-suppress={true}
>
Yoruba
</p>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
aria-labelledby="levelOfEducation-label"
role="dialog"
>
<form
onSubmit={[Function]}
>
<div
className="pgn__form-group"
>
<label
className="edit-section-header"
htmlFor="levelOfEducation"
>
Education
</label>
<select
className="form-control"
data-hj-suppress={true}
id="levelOfEducation"
name="levelOfEducation"
onChange={[Function]}
value="el"
>
<option
value=""
>
 
</option>
<option
value="p"
>
Doctorate
</option>
<option
value="m"
>
Master's or professional degree
</option>
<option
value="b"
>
Bachelor's Degree
</option>
<option
value="a"
>
Associate's degree
</option>
<option
value="hs"
>
Secondary/high school
</option>
<option
value="jhs"
>
Junior secondary/junior high/middle school
</option>
<option
value="el"
>
Elementary/primary school
</option>
<option
value="none"
>
No formal education
</option>
<option
value="other"
>
Other education
</option>
</select>
<div
className="pgn__form-control-description pgn__form-text pgn__form-text-invalid"
id="levelOfEducation-3"
>
education error
</div>
</div>
<div
className="d-flex flex-row-reverse flex-wrap justify-content-end align-items-center"
>
<div
className="form-group d-flex flex-wrap"
>
<label
className="col-form-label"
htmlFor="visibilityLevelOfEducation"
>
Who can see this:
</label>
<span
className="d-flex align-items-center"
>
<span
className="d-inline-block ml-1 mr-2"
style={
Object {
"width": "1.5rem",
}
}
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye-slash fa-w-20 "
data-icon="eye-slash"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 640 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M634 471L36 3.51A16 16 0 0 0 13.51 6l-10 12.49A16 16 0 0 0 6 41l598 467.49a16 16 0 0 0 22.49-2.49l10-12.49A16 16 0 0 0 634 471zM296.79 146.47l134.79 105.38C429.36 191.91 380.48 144 320 144a112.26 112.26 0 0 0-23.21 2.47zm46.42 219.07L208.42 260.16C210.65 320.09 259.53 368 320 368a113 113 0 0 0 23.21-2.46zM320 112c98.65 0 189.09 55 237.93 144a285.53 285.53 0 0 1-44 60.2l37.74 29.5a333.7 333.7 0 0 0 52.9-75.11 32.35 32.35 0 0 0 0-29.19C550.29 135.59 442.93 64 320 64c-36.7 0-71.71 7-104.63 18.81l46.41 36.29c18.94-4.3 38.34-7.1 58.22-7.1zm0 288c-98.65 0-189.08-55-237.93-144a285.47 285.47 0 0 1 44.05-60.19l-37.74-29.5a333.6 333.6 0 0 0-52.89 75.1 32.35 32.35 0 0 0 0 29.19C89.72 376.41 197.08 448 320 448c36.7 0 71.71-7.05 104.63-18.81l-46.41-36.28C359.28 397.2 339.89 400 320 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
</span>
<select
className="d-inline-block form-control"
id="visibilityLevelOfEducation"
name="visibilityLevelOfEducation"
onChange={[Function]}
type="select"
value="private"
>
<option
value="private"
>
Just me
</option>
<option
value="all_users"
>
Everyone on localhost
</option>
</select>
</span>
</div>
<div
className="form-group flex-shrink-0 flex-grow-1"
>
<button
aria-disabled={false}
aria-live="assertive"
className="pgn__stateful-btn pgn__stateful-btn-state-pending btn btn-primary"
disabled={false}
onClick={[Function]}
type="submit"
>
<span
className="d-flex align-items-center justify-content-center"
>
<span
className="pgn__stateful-btn-icon"
>
<span
className="pgn__icon icon-spin"
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M22 12A10 10 0 116.122 3.91l1.176 1.618A8 8 0 1020 12h2z"
fill="currentColor"
/>
</svg>
</span>
</span>
<span>
Saving
</span>
</span>
</button>
<button
className="btn btn-link"
disabled={false}
onClick={[Function]}
type="button"
>
Cancel
</button>
</div>
</div>
</form>
</div>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Social Links
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
<ul
className="list-unstyled"
>
<li
className="form-group"
>
<a
className="font-weight-bold"
href="https://www.twitter.com/ALOHA"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-twitter fa-w-16 mr-2"
data-icon="twitter"
data-prefix="fab"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"
fill="currentColor"
style={Object {}}
/>
</svg>
Twitter
</a>
</li>
<li
className="form-group"
>
<a
className="font-weight-bold"
href="https://www.facebook.com/aloha"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-facebook fa-w-16 mr-2"
data-icon="facebook"
data-prefix="fab"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M504 256C504 119 393 8 256 8S8 119 8 256c0 123.78 90.69 226.38 209.25 245V327.69h-63V256h63v-54.64c0-62.15 37-96.48 93.67-96.48 27.14 0 55.52 4.84 55.52 4.84v61h-31.28c-30.8 0-40.41 19.12-40.41 38.73V256h68.78l-11 71.69h-57.78V501C413.31 482.38 504 379.78 504 256z"
fill="currentColor"
style={Object {}}
/>
</svg>
Facebook
</a>
</li>
<li
className="form-group"
>
<div>
<button
className="pl-0 text-left btn btn-link"
onClick={[Function]}
onKeyDown={[Function]}
tabIndex={0}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-plus fa-w-14 fa-xs mr-2"
data-icon="plus"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z"
fill="currentColor"
style={Object {}}
/>
</svg>
Add
LinkedIn
</button>
</div>
</li>
</ul>
</div>
</div>
</div>
<div
className="pt-md-3 col-md-8 col-lg-7 offset-lg-1"
>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
About Me
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
<p
className="lead"
data-hj-suppress={true}
>
This is my bio
</p>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-4"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
My Certificates
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
<div
className="row align-items-stretch"
>
<div
className="col-12 col-sm-6 d-flex align-items-stretch"
>
<div
className="card mb-4 certificate flex-grow-1"
>
<div
className="certificate-type-illustration"
style={
Object {
"backgroundImage": "url(icon/mock/path)",
}
}
/>
<div
className="card-body d-flex flex-column"
>
<div
className="card-title"
>
<p
className="small mb-0"
>
Verified Certificate
</p>
<h4
className="certificate-title"
>
edX Demonstration Course
</h4>
</div>
<p
className="small mb-0"
>
From
</p>
<p
className="h6 mb-4"
>
edX
</p>
<div
className="flex-grow-1"
/>
<p
className="small mb-2"
>
Completed on
3/4/2019
</p>
<div>
<a
className="pgn__hyperlink default-link standalone-link btn btn-outline-primary"
href="http://www.example.com/"
onClick={[Function]}
rel="noopener noreferrer"
target="_blank"
>
View Certificate
<span
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
Object {
"height": "1em",
"width": "1em",
}
}
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`<ProfilePage /> Renders correctly in various states test preferreded language edit with error 1`] = `
<div
className="profile-page"
>
<div
className="profile-page-bg-banner bg-primary d-md-block p-relative"
/>
<div
className="container-fluid"
>
<div
className="row align-items-center pt-4 mb-4 pt-md-0 mb-md-0"
>
<div
className="col-auto col-md-4 col-lg-3"
>
<div
className="d-flex align-items-center d-md-block"
>
<div
className="profile-avatar-wrap position-relative"
>
<div
className="profile-avatar rounded-circle bg-light"
>
<div
className="profile-avatar-menu-container"
>
<div
className="pgn__dropdown pgn__dropdown-light dropdown"
data-testid="dropdown"
>
<button
aria-expanded={false}
aria-haspopup={true}
className="dropdown-toggle btn btn-primary"
disabled={false}
onClick={[Function]}
type="button"
>
Change
</button>
</div>
</div>
<img
alt="profile avatar"
className="w-100 h-100 d-block rounded-circle overflow-hidden"
data-hj-suppress={true}
src="http://localhost:18000/media/profile-images/d2a9bdc2ba165dcefc73265c54bf9a20_500.jpg?v=1552495012"
style={
Object {
"objectFit": "cover",
}
}
/>
</div>
<form
encType="multipart/form-data"
onSubmit={[Function]}
>
<input
accept=".jpg, .jpeg, .png"
className="d-none form-control-file"
id="photo-file"
name="file"
onChange={[Function]}
type="file"
/>
</form>
</div>
</div>
</div>
<div
className="col"
>
<div
className="d-md-none"
>
<span
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold text-truncate"
>
staff
</h1>
<p
className="mb-0"
>
Member since
2017
</p>
<hr
className="d-none d-md-block"
/>
</span>
</div>
<div
className="d-none d-md-block float-right"
>
<a
className="pgn__hyperlink default-link standalone-link btn btn-primary"
href="http://localhost:18150/records"
onClick={[Function]}
rel="noopener noreferrer"
target="_blank"
>
View My Records
<span
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
Object {
"height": "1em",
"width": "1em",
}
}
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
</div>
</div>
</div>
<div
className="row"
>
<div
className="col-md-4 col-lg-4"
>
<div
className="d-none d-md-block mb-4"
>
<span
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold text-truncate"
>
staff
</h1>
<p
className="mb-0"
>
Member since
2017
</p>
<hr
className="d-none d-md-block"
/>
</span>
</div>
<div
className="d-md-none mb-4"
>
<a
className="pgn__hyperlink default-link standalone-link btn btn-primary"
href="http://localhost:18150/records"
onClick={[Function]}
rel="noopener noreferrer"
target="_blank"
>
View My Records
<span
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
Object {
"height": "1em",
"width": "1em",
}
}
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Full Name
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye-slash fa-w-20 "
data-icon="eye-slash"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 640 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M634 471L36 3.51A16 16 0 0 0 13.51 6l-10 12.49A16 16 0 0 0 6 41l598 467.49a16 16 0 0 0 22.49-2.49l10-12.49A16 16 0 0 0 634 471zM296.79 146.47l134.79 105.38C429.36 191.91 380.48 144 320 144a112.26 112.26 0 0 0-23.21 2.47zm46.42 219.07L208.42 260.16C210.65 320.09 259.53 368 320 368a113 113 0 0 0 23.21-2.46zM320 112c98.65 0 189.09 55 237.93 144a285.53 285.53 0 0 1-44 60.2l37.74 29.5a333.7 333.7 0 0 0 52.9-75.11 32.35 32.35 0 0 0 0-29.19C550.29 135.59 442.93 64 320 64c-36.7 0-71.71 7-104.63 18.81l46.41 36.29c18.94-4.3 38.34-7.1 58.22-7.1zm0 288c-98.65 0-189.08-55-237.93-144a285.47 285.47 0 0 1 44.05-60.19l-37.74-29.5a333.6 333.6 0 0 0-52.89 75.1 32.35 32.35 0 0 0 0 29.19C89.72 376.41 197.08 448 320 448c36.7 0 71.71-7.05 104.63-18.81l-46.41-36.28C359.28 397.2 339.89 400 320 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Just me
</span>
</p>
</div>
<p
className="h5"
data-hj-suppress={true}
>
Lemon Seltzer
</p>
<small
className="form-text text-muted"
>
This is the name that appears in your account and on your certificates.
</small>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Location
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
<p
className="h5"
data-hj-suppress={true}
>
Montenegro
</p>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
aria-labelledby="languageProficiencies-label"
role="dialog"
>
<form
onSubmit={[Function]}
>
<div
className="pgn__form-group"
>
<label
className="edit-section-header"
htmlFor="languageProficiencies"
>
Primary Language Spoken
</label>
<select
className="form-control"
data-hj-suppress={true}
id="languageProficiencies"
name="languageProficiencies"
onChange={[Function]}
value="yo"
>
<option
value=""
>
 
</option>
<option
value="aa"
>
Afar
</option>
<option
value="ab"
>
Abkhazian
</option>
<option
value="ae"
>
Avestan
</option>
<option
value="af"
>
Afrikaans
</option>
<option
value="ak"
>
Akan
</option>
<option
value="am"
>
Amharic
</option>
<option
value="an"
>
Aragonese
</option>
<option
value="ar"
>
Arabic
</option>
<option
value="as"
>
Assamese
</option>
<option
value="av"
>
Avaric
</option>
<option
value="ay"
>
Aymara
</option>
<option
value="az"
>
Azerbaijani
</option>
<option
value="ba"
>
Bashkir
</option>
<option
value="be"
>
Belarusian
</option>
<option
value="bg"
>
Bulgarian
</option>
<option
value="bh"
>
Bihari languages
</option>
<option
value="bi"
>
Bislama
</option>
<option
value="bm"
>
Bambara
</option>
<option
value="bn"
>
Bengali
</option>
<option
value="bo"
>
Tibetan
</option>
<option
value="br"
>
Breton
</option>
<option
value="bs"
>
Bosnian
</option>
<option
value="ca"
>
Catalan
</option>
<option
value="ce"
>
Chechen
</option>
<option
value="ch"
>
Chamorro
</option>
<option
value="co"
>
Corsican
</option>
<option
value="cr"
>
Cree
</option>
<option
value="cs"
>
Czech
</option>
<option
value="cu"
>
Church Slavic
</option>
<option
value="cv"
>
Chuvash
</option>
<option
value="cy"
>
Welsh
</option>
<option
value="da"
>
Danish
</option>
<option
value="de"
>
German
</option>
<option
value="dv"
>
Maldivian
</option>
<option
value="dz"
>
Dzongkha
</option>
<option
value="ee"
>
Ewe
</option>
<option
value="el"
>
Greek (modern)
</option>
<option
value="en"
>
English
</option>
<option
value="eo"
>
Esperanto
</option>
<option
value="es"
>
Spanish
</option>
<option
value="et"
>
Estonian
</option>
<option
value="eu"
>
Basque
</option>
<option
value="fa"
>
Persian
</option>
<option
value="ff"
>
Fulah
</option>
<option
value="fi"
>
Finnish
</option>
<option
value="fj"
>
Fijian
</option>
<option
value="fo"
>
Faroese
</option>
<option
value="fr"
>
French
</option>
<option
value="fy"
>
Western Frisian
</option>
<option
value="ga"
>
Irish
</option>
<option
value="gd"
>
Gaelic
</option>
<option
value="gl"
>
Galician
</option>
<option
value="gn"
>
Guaraní
</option>
<option
value="gu"
>
Gujarati
</option>
<option
value="gv"
>
Manx
</option>
<option
value="ha"
>
Hausa
</option>
<option
value="he"
>
Hebrew (modern)
</option>
<option
value="hi"
>
Hindi
</option>
<option
value="ho"
>
Hiri Motu
</option>
<option
value="hr"
>
Croatian
</option>
<option
value="ht"
>
Haitian Creole
</option>
<option
value="hu"
>
Hungarian
</option>
<option
value="hy"
>
Armenian
</option>
<option
value="hz"
>
Herero
</option>
<option
value="ia"
>
Interlingua
</option>
<option
value="id"
>
Indonesian
</option>
<option
value="ie"
>
Interlingue
</option>
<option
value="ig"
>
Igbo
</option>
<option
value="ii"
>
Nuosu
</option>
<option
value="ik"
>
Inupiaq
</option>
<option
value="io"
>
Ido
</option>
<option
value="is"
>
Icelandic
</option>
<option
value="it"
>
Italian
</option>
<option
value="iu"
>
Inuktitut
</option>
<option
value="ja"
>
Japanese
</option>
<option
value="jv"
>
Javanese
</option>
<option
value="ka"
>
Georgian
</option>
<option
value="kg"
>
Kongo
</option>
<option
value="ki"
>
Kikuyu
</option>
<option
value="kj"
>
Kwanyama
</option>
<option
value="kk"
>
Kazakh
</option>
<option
value="kl"
>
Greenlandic
</option>
<option
value="km"
>
Central Khmer
</option>
<option
value="kn"
>
Kannada
</option>
<option
value="ko"
>
Korean
</option>
<option
value="kr"
>
Kanuri
</option>
<option
value="ks"
>
Kashmiri
</option>
<option
value="ku"
>
Kurdish
</option>
<option
value="kv"
>
Komi
</option>
<option
value="kw"
>
Cornish
</option>
<option
value="ky"
>
Kyrgyz
</option>
<option
value="la"
>
Latin
</option>
<option
value="lb"
>
Luxembourgish
</option>
<option
value="lg"
>
Ganda
</option>
<option
value="li"
>
Limburgish
</option>
<option
value="ln"
>
Lingala
</option>
<option
value="lo"
>
Lao
</option>
<option
value="lt"
>
Lithuanian
</option>
<option
value="lu"
>
Luba-Katanga
</option>
<option
value="lv"
>
Latvian
</option>
<option
value="mg"
>
Malagasy
</option>
<option
value="mh"
>
Marshallese
</option>
<option
value="mi"
>
Maori
</option>
<option
value="mk"
>
Macedonian
</option>
<option
value="ml"
>
Malayalam
</option>
<option
value="mn"
>
Mongolian
</option>
<option
value="mr"
>
Marathi
</option>
<option
value="ms"
>
Malay
</option>
<option
value="mt"
>
Maltese
</option>
<option
value="my"
>
Burmese
</option>
<option
value="na"
>
Nauru
</option>
<option
value="nb"
>
Bokmål
</option>
<option
value="nd"
>
North Ndebele
</option>
<option
value="ne"
>
Nepali
</option>
<option
value="ng"
>
Ndonga
</option>
<option
value="nl"
>
Dutch
</option>
<option
value="nn"
>
Norwegian Nynorsk
</option>
<option
value="no"
>
Norwegian
</option>
<option
value="nr"
>
South Ndebele
</option>
<option
value="nv"
>
Navajo
</option>
<option
value="ny"
>
Nyanja
</option>
<option
value="oc"
>
Occitan
</option>
<option
value="oj"
>
Ojibwa
</option>
<option
value="om"
>
Oromo
</option>
<option
value="or"
>
Oriya
</option>
<option
value="os"
>
Ossetian
</option>
<option
value="pa"
>
Punjabi
</option>
<option
value="pi"
>
Pali
</option>
<option
value="pl"
>
Polish
</option>
<option
value="ps"
>
Pashto
</option>
<option
value="pt"
>
Portuguese
</option>
<option
value="qu"
>
Quechua
</option>
<option
value="rm"
>
Romansh
</option>
<option
value="rn"
>
Rundi
</option>
<option
value="ro"
>
Romanian
</option>
<option
value="ru"
>
Russian
</option>
<option
value="rw"
>
Kinyarwanda
</option>
<option
value="sa"
>
Sanskrit
</option>
<option
value="sc"
>
Sardinian
</option>
<option
value="sd"
>
Sindhi
</option>
<option
value="se"
>
Northern Sami
</option>
<option
value="sg"
>
Sango
</option>
<option
value="si"
>
Sinhalese
</option>
<option
value="sk"
>
Slovak
</option>
<option
value="sl"
>
Slovenian
</option>
<option
value="sm"
>
Samoan
</option>
<option
value="sn"
>
Shona
</option>
<option
value="so"
>
Somali
</option>
<option
value="sq"
>
Albanian
</option>
<option
value="sr"
>
Serbian
</option>
<option
value="ss"
>
Swati
</option>
<option
value="st"
>
Southern Sotho
</option>
<option
value="su"
>
Sundanese
</option>
<option
value="sv"
>
Swedish
</option>
<option
value="sw"
>
Swahili
</option>
<option
value="ta"
>
Tamil
</option>
<option
value="te"
>
Telugu
</option>
<option
value="tg"
>
Tajik
</option>
<option
value="th"
>
Thai
</option>
<option
value="ti"
>
Tigrinya
</option>
<option
value="tk"
>
Turkmen
</option>
<option
value="tl"
>
Tagalog
</option>
<option
value="tn"
>
Tswana
</option>
<option
value="to"
>
Tonga
</option>
<option
value="tr"
>
Turkish
</option>
<option
value="ts"
>
Tsonga
</option>
<option
value="tt"
>
Tatar
</option>
<option
value="tw"
>
Twi
</option>
<option
value="ty"
>
Tahitian
</option>
<option
value="ug"
>
Uyghur
</option>
<option
value="uk"
>
Ukrainian
</option>
<option
value="ur"
>
Urdu
</option>
<option
value="uz"
>
Uzbek
</option>
<option
value="ve"
>
Venda
</option>
<option
value="vi"
>
Vietnamese
</option>
<option
value="vo"
>
Volapük
</option>
<option
value="wa"
>
Walloon
</option>
<option
value="wo"
>
Wolof
</option>
<option
value="xh"
>
Xhosa
</option>
<option
value="yi"
>
Yiddish
</option>
<option
value="yo"
>
Yoruba
</option>
<option
value="za"
>
Zhuang
</option>
<option
value="zh"
>
Chinese
</option>
<option
value="zu"
>
Zulu
</option>
</select>
<div
className="pgn__form-control-description pgn__form-text pgn__form-text-invalid"
id="languageProficiencies-4"
>
preferred language error
</div>
</div>
<div
className="d-flex flex-row-reverse flex-wrap justify-content-end align-items-center"
>
<div
className="form-group d-flex flex-wrap"
>
<label
className="col-form-label"
htmlFor="visibilityLanguageProficiencies"
>
Who can see this:
</label>
<span
className="d-flex align-items-center"
>
<span
className="d-inline-block ml-1 mr-2"
style={
Object {
"width": "1.5rem",
}
}
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
</span>
<select
className="d-inline-block form-control"
id="visibilityLanguageProficiencies"
name="visibilityLanguageProficiencies"
onChange={[Function]}
type="select"
value="all_users"
>
<option
value="private"
>
Just me
</option>
<option
value="all_users"
>
Everyone on localhost
</option>
</select>
</span>
</div>
<div
className="form-group flex-shrink-0 flex-grow-1"
>
<button
aria-disabled={false}
aria-live="assertive"
className="pgn__stateful-btn pgn__stateful-btn-state-pending btn btn-primary"
disabled={false}
onClick={[Function]}
type="submit"
>
<span
className="d-flex align-items-center justify-content-center"
>
<span
className="pgn__stateful-btn-icon"
>
<span
className="pgn__icon icon-spin"
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M22 12A10 10 0 116.122 3.91l1.176 1.618A8 8 0 1020 12h2z"
fill="currentColor"
/>
</svg>
</span>
</span>
<span>
Saving
</span>
</span>
</button>
<button
className="btn btn-link"
disabled={false}
onClick={[Function]}
type="button"
>
Cancel
</button>
</div>
</div>
</form>
</div>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Education
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye-slash fa-w-20 "
data-icon="eye-slash"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 640 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M634 471L36 3.51A16 16 0 0 0 13.51 6l-10 12.49A16 16 0 0 0 6 41l598 467.49a16 16 0 0 0 22.49-2.49l10-12.49A16 16 0 0 0 634 471zM296.79 146.47l134.79 105.38C429.36 191.91 380.48 144 320 144a112.26 112.26 0 0 0-23.21 2.47zm46.42 219.07L208.42 260.16C210.65 320.09 259.53 368 320 368a113 113 0 0 0 23.21-2.46zM320 112c98.65 0 189.09 55 237.93 144a285.53 285.53 0 0 1-44 60.2l37.74 29.5a333.7 333.7 0 0 0 52.9-75.11 32.35 32.35 0 0 0 0-29.19C550.29 135.59 442.93 64 320 64c-36.7 0-71.71 7-104.63 18.81l46.41 36.29c18.94-4.3 38.34-7.1 58.22-7.1zm0 288c-98.65 0-189.08-55-237.93-144a285.47 285.47 0 0 1 44.05-60.19l-37.74-29.5a333.6 333.6 0 0 0-52.89 75.1 32.35 32.35 0 0 0 0 29.19C89.72 376.41 197.08 448 320 448c36.7 0 71.71-7.05 104.63-18.81l-46.41-36.28C359.28 397.2 339.89 400 320 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Just me
</span>
</p>
</div>
<p
className="h5"
data-hj-suppress={true}
>
Elementary/primary school
</p>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Social Links
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
<ul
className="list-unstyled"
>
<li
className="form-group"
>
<a
className="font-weight-bold"
href="https://www.twitter.com/ALOHA"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-twitter fa-w-16 mr-2"
data-icon="twitter"
data-prefix="fab"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"
fill="currentColor"
style={Object {}}
/>
</svg>
Twitter
</a>
</li>
<li
className="form-group"
>
<a
className="font-weight-bold"
href="https://www.facebook.com/aloha"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-facebook fa-w-16 mr-2"
data-icon="facebook"
data-prefix="fab"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M504 256C504 119 393 8 256 8S8 119 8 256c0 123.78 90.69 226.38 209.25 245V327.69h-63V256h63v-54.64c0-62.15 37-96.48 93.67-96.48 27.14 0 55.52 4.84 55.52 4.84v61h-31.28c-30.8 0-40.41 19.12-40.41 38.73V256h68.78l-11 71.69h-57.78V501C413.31 482.38 504 379.78 504 256z"
fill="currentColor"
style={Object {}}
/>
</svg>
Facebook
</a>
</li>
<li
className="form-group"
>
<div>
<button
className="pl-0 text-left btn btn-link"
onClick={[Function]}
onKeyDown={[Function]}
tabIndex={0}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-plus fa-w-14 fa-xs mr-2"
data-icon="plus"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z"
fill="currentColor"
style={Object {}}
/>
</svg>
Add
LinkedIn
</button>
</div>
</li>
</ul>
</div>
</div>
</div>
<div
className="pt-md-3 col-md-8 col-lg-7 offset-lg-1"
>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
About Me
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
<p
className="lead"
data-hj-suppress={true}
>
This is my bio
</p>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-4"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
My Certificates
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
<div
className="row align-items-stretch"
>
<div
className="col-12 col-sm-6 d-flex align-items-stretch"
>
<div
className="card mb-4 certificate flex-grow-1"
>
<div
className="certificate-type-illustration"
style={
Object {
"backgroundImage": "url(icon/mock/path)",
}
}
/>
<div
className="card-body d-flex flex-column"
>
<div
className="card-title"
>
<p
className="small mb-0"
>
Verified Certificate
</p>
<h4
className="certificate-title"
>
edX Demonstration Course
</h4>
</div>
<p
className="small mb-0"
>
From
</p>
<p
className="h6 mb-4"
>
edX
</p>
<div
className="flex-grow-1"
/>
<p
className="small mb-2"
>
Completed on
3/4/2019
</p>
<div>
<a
className="pgn__hyperlink default-link standalone-link btn btn-outline-primary"
href="http://www.example.com/"
onClick={[Function]}
rel="noopener noreferrer"
target="_blank"
>
View Certificate
<span
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
Object {
"height": "1em",
"width": "1em",
}
}
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`<ProfilePage /> Renders correctly in various states viewing other profile with all fields 1`] = `
<div
className="profile-page"
>
<div
className="profile-page-bg-banner bg-primary d-md-block p-relative"
/>
<div
className="container-fluid"
>
<div
className="row align-items-center pt-4 mb-4 pt-md-0 mb-md-0"
>
<div
className="col-auto col-md-4 col-lg-3"
>
<div
className="d-flex align-items-center d-md-block"
>
<div
className="profile-avatar-wrap position-relative"
>
<div
className="profile-avatar rounded-circle bg-light"
>
<IconMock
aria-hidden={true}
className="text-muted"
focusable="false"
role="img"
viewBox="0 0 24 24"
/>
</div>
<form
encType="multipart/form-data"
onSubmit={[Function]}
>
<input
accept=".jpg, .jpeg, .png"
className="d-none form-control-file"
id="photo-file"
name="file"
onChange={[Function]}
type="file"
/>
</form>
</div>
</div>
</div>
<div
className="col"
>
<div
className="d-md-none"
>
<span
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold text-truncate"
>
verified
</h1>
<p
className="mb-0"
>
Member since
2017
</p>
<div
className="d-flex align-items-center mt-3 mb-2rem"
>
<span
className="pgn__icon icon-visibility-off"
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 6.5c2.76 0 5 2.24 5 5 0 .51-.1 1-.24 1.46l3.06 3.06c1.39-1.23 2.49-2.77 3.18-4.53C21.27 7.11 17 4 12 4c-1.27 0-2.49.2-3.64.57l2.17 2.17c.47-.14.96-.24 1.47-.24zM3.42 2.45L2.01 3.87l2.68 2.68A11.738 11.738 0 001 11.5C2.73 15.89 7 19 12 19c1.52 0 2.97-.3 4.31-.82l3.43 3.43 1.41-1.41L3.42 2.45zM12 16.5c-2.76 0-5-2.24-5-5 0-.77.18-1.5.49-2.14l1.57 1.57c-.03.18-.06.37-.06.57 0 1.66 1.34 3 3 3 .2 0 .38-.03.57-.07L14.14 16c-.65.32-1.37.5-2.14.5zm2.97-5.33a2.97 2.97 0 00-2.64-2.64l2.64 2.64z"
fill="currentColor"
/>
</svg>
</span>
<div
className="username-description"
>
Your profile information is only visible to you. Only your username is visible to others on localhost.
</div>
</div>
<hr
className="d-none d-md-block"
/>
</span>
</div>
<div
className="d-none d-md-block float-right"
/>
</div>
</div>
<div
className="row"
>
<div
className="col-md-4 col-lg-4"
>
<div
className="d-none d-md-block mb-4"
>
<span
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold text-truncate"
>
verified
</h1>
<p
className="mb-0"
>
Member since
2017
</p>
<div
className="d-flex align-items-center mt-3 mb-2rem"
>
<span
className="pgn__icon icon-visibility-off"
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 6.5c2.76 0 5 2.24 5 5 0 .51-.1 1-.24 1.46l3.06 3.06c1.39-1.23 2.49-2.77 3.18-4.53C21.27 7.11 17 4 12 4c-1.27 0-2.49.2-3.64.57l2.17 2.17c.47-.14.96-.24 1.47-.24zM3.42 2.45L2.01 3.87l2.68 2.68A11.738 11.738 0 001 11.5C2.73 15.89 7 19 12 19c1.52 0 2.97-.3 4.31-.82l3.43 3.43 1.41-1.41L3.42 2.45zM12 16.5c-2.76 0-5-2.24-5-5 0-.77.18-1.5.49-2.14l1.57 1.57c-.03.18-.06.37-.06.57 0 1.66 1.34 3 3 3 .2 0 .38-.03.57-.07L14.14 16c-.65.32-1.37.5-2.14.5zm2.97-5.33a2.97 2.97 0 00-2.64-2.64l2.64 2.64z"
fill="currentColor"
/>
</svg>
</span>
<div
className="username-description"
>
Your profile information is only visible to you. Only your username is visible to others on localhost.
</div>
</div>
<hr
className="d-none d-md-block"
/>
</span>
</div>
<div
className="d-md-none mb-4"
/>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Full Name
</h2>
</div>
<p
className="h5"
data-hj-suppress={true}
>
user
</p>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Location
</h2>
</div>
<p
className="h5"
data-hj-suppress={true}
/>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Primary Language Spoken
</h2>
</div>
<p
className="h5"
data-hj-suppress={true}
/>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Education
</h2>
</div>
<p
className="h5"
data-hj-suppress={true}
>
Other education
</p>
</div>
</div>
</div>
<div
className="pt-md-3 col-md-8 col-lg-7 offset-lg-1"
>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
About Me
</h2>
</div>
<p
className="lead"
data-hj-suppress={true}
>
bio
</p>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`<ProfilePage /> Renders correctly in various states viewing own profile 1`] = `
<div
className="profile-page"
>
<div
className="profile-page-bg-banner bg-primary d-md-block p-relative"
/>
<div
className="container-fluid"
>
<div
className="row align-items-center pt-4 mb-4 pt-md-0 mb-md-0"
>
<div
className="col-auto col-md-4 col-lg-3"
>
<div
className="d-flex align-items-center d-md-block"
>
<div
className="profile-avatar-wrap position-relative"
>
<div
className="profile-avatar rounded-circle bg-light"
>
<div
className="profile-avatar-menu-container"
>
<div
className="pgn__dropdown pgn__dropdown-light dropdown"
data-testid="dropdown"
>
<button
aria-expanded={false}
aria-haspopup={true}
className="dropdown-toggle btn btn-primary"
disabled={false}
onClick={[Function]}
type="button"
>
Change
</button>
</div>
</div>
<img
alt="profile avatar"
className="w-100 h-100 d-block rounded-circle overflow-hidden"
data-hj-suppress={true}
src="http://localhost:18000/media/profile-images/d2a9bdc2ba165dcefc73265c54bf9a20_500.jpg?v=1552495012"
style={
Object {
"objectFit": "cover",
}
}
/>
</div>
<form
encType="multipart/form-data"
onSubmit={[Function]}
>
<input
accept=".jpg, .jpeg, .png"
className="d-none form-control-file"
id="photo-file"
name="file"
onChange={[Function]}
type="file"
/>
</form>
</div>
</div>
</div>
<div
className="col"
>
<div
className="d-md-none"
>
<span
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold text-truncate"
>
staff
</h1>
<p
className="mb-0"
>
Member since
2017
</p>
<hr
className="d-none d-md-block"
/>
</span>
</div>
<div
className="d-none d-md-block float-right"
>
<a
className="pgn__hyperlink default-link standalone-link btn btn-primary"
href="http://localhost:18150/records"
onClick={[Function]}
rel="noopener noreferrer"
target="_blank"
>
View My Records
<span
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
Object {
"height": "1em",
"width": "1em",
}
}
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
</div>
</div>
</div>
<div
className="row"
>
<div
className="col-md-4 col-lg-4"
>
<div
className="d-none d-md-block mb-4"
>
<span
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold text-truncate"
>
staff
</h1>
<p
className="mb-0"
>
Member since
2017
</p>
<hr
className="d-none d-md-block"
/>
</span>
</div>
<div
className="d-md-none mb-4"
>
<a
className="pgn__hyperlink default-link standalone-link btn btn-primary"
href="http://localhost:18150/records"
onClick={[Function]}
rel="noopener noreferrer"
target="_blank"
>
View My Records
<span
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
Object {
"height": "1em",
"width": "1em",
}
}
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Full Name
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye-slash fa-w-20 "
data-icon="eye-slash"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 640 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M634 471L36 3.51A16 16 0 0 0 13.51 6l-10 12.49A16 16 0 0 0 6 41l598 467.49a16 16 0 0 0 22.49-2.49l10-12.49A16 16 0 0 0 634 471zM296.79 146.47l134.79 105.38C429.36 191.91 380.48 144 320 144a112.26 112.26 0 0 0-23.21 2.47zm46.42 219.07L208.42 260.16C210.65 320.09 259.53 368 320 368a113 113 0 0 0 23.21-2.46zM320 112c98.65 0 189.09 55 237.93 144a285.53 285.53 0 0 1-44 60.2l37.74 29.5a333.7 333.7 0 0 0 52.9-75.11 32.35 32.35 0 0 0 0-29.19C550.29 135.59 442.93 64 320 64c-36.7 0-71.71 7-104.63 18.81l46.41 36.29c18.94-4.3 38.34-7.1 58.22-7.1zm0 288c-98.65 0-189.08-55-237.93-144a285.47 285.47 0 0 1 44.05-60.19l-37.74-29.5a333.6 333.6 0 0 0-52.89 75.1 32.35 32.35 0 0 0 0 29.19C89.72 376.41 197.08 448 320 448c36.7 0 71.71-7.05 104.63-18.81l-46.41-36.28C359.28 397.2 339.89 400 320 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Just me
</span>
</p>
</div>
<p
className="h5"
data-hj-suppress={true}
>
Lemon Seltzer
</p>
<small
className="form-text text-muted"
>
This is the name that appears in your account and on your certificates.
</small>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Location
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
<p
className="h5"
data-hj-suppress={true}
>
Montenegro
</p>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Primary Language Spoken
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
@@ -1931,7 +6640,1057 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
/>
</svg>
Everyone on edX
Everyone on localhost
</span>
</p>
</div>
<ul
className="list-unstyled"
>
<li
className="form-group"
>
<a
className="font-weight-bold"
href="https://www.twitter.com/ALOHA"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-twitter fa-w-16 mr-2"
data-icon="twitter"
data-prefix="fab"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"
fill="currentColor"
style={Object {}}
/>
</svg>
Twitter
</a>
</li>
<li
className="form-group"
>
<a
className="font-weight-bold"
href="https://www.facebook.com/aloha"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-facebook fa-w-16 mr-2"
data-icon="facebook"
data-prefix="fab"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M504 256C504 119 393 8 256 8S8 119 8 256c0 123.78 90.69 226.38 209.25 245V327.69h-63V256h63v-54.64c0-62.15 37-96.48 93.67-96.48 27.14 0 55.52 4.84 55.52 4.84v61h-31.28c-30.8 0-40.41 19.12-40.41 38.73V256h68.78l-11 71.69h-57.78V501C413.31 482.38 504 379.78 504 256z"
fill="currentColor"
style={Object {}}
/>
</svg>
Facebook
</a>
</li>
<li
className="form-group"
>
<div>
<button
className="pl-0 text-left btn btn-link"
onClick={[Function]}
onKeyDown={[Function]}
tabIndex={0}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-plus fa-w-14 fa-xs mr-2"
data-icon="plus"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z"
fill="currentColor"
style={Object {}}
/>
</svg>
Add
LinkedIn
</button>
</div>
</li>
</ul>
</div>
</div>
</div>
<div
className="pt-md-3 col-md-8 col-lg-7 offset-lg-1"
>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
About Me
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
<p
className="lead"
data-hj-suppress={true}
>
This is my bio
</p>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-4"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
My Certificates
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
<div
className="row align-items-stretch"
>
<div
className="col-12 col-sm-6 d-flex align-items-stretch"
>
<div
className="card mb-4 certificate flex-grow-1"
>
<div
className="certificate-type-illustration"
style={
Object {
"backgroundImage": "url(icon/mock/path)",
}
}
/>
<div
className="card-body d-flex flex-column"
>
<div
className="card-title"
>
<p
className="small mb-0"
>
Verified Certificate
</p>
<h4
className="certificate-title"
>
edX Demonstration Course
</h4>
</div>
<p
className="small mb-0"
>
From
</p>
<p
className="h6 mb-4"
>
edX
</p>
<div
className="flex-grow-1"
/>
<p
className="small mb-2"
>
Completed on
3/4/2019
</p>
<div>
<a
className="pgn__hyperlink default-link standalone-link btn btn-outline-primary"
href="http://www.example.com/"
onClick={[Function]}
rel="noopener noreferrer"
target="_blank"
>
View Certificate
<span
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
Object {
"height": "1em",
"width": "1em",
}
}
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`<ProfilePage /> Renders correctly in various states while saving an edited bio 1`] = `
<div
className="profile-page"
>
<div
className="profile-page-bg-banner bg-primary d-md-block p-relative"
/>
<div
className="container-fluid"
>
<div
className="row align-items-center pt-4 mb-4 pt-md-0 mb-md-0"
>
<div
className="col-auto col-md-4 col-lg-3"
>
<div
className="d-flex align-items-center d-md-block"
>
<div
className="profile-avatar-wrap position-relative"
>
<div
className="profile-avatar rounded-circle bg-light"
>
<div
className="profile-avatar-menu-container"
>
<div
className="pgn__dropdown pgn__dropdown-light dropdown"
data-testid="dropdown"
>
<button
aria-expanded={false}
aria-haspopup={true}
className="dropdown-toggle btn btn-primary"
disabled={false}
onClick={[Function]}
type="button"
>
Change
</button>
</div>
</div>
<img
alt="profile avatar"
className="w-100 h-100 d-block rounded-circle overflow-hidden"
data-hj-suppress={true}
src="http://localhost:18000/media/profile-images/d2a9bdc2ba165dcefc73265c54bf9a20_500.jpg?v=1552495012"
style={
Object {
"objectFit": "cover",
}
}
/>
</div>
<form
encType="multipart/form-data"
onSubmit={[Function]}
>
<input
accept=".jpg, .jpeg, .png"
className="d-none form-control-file"
id="photo-file"
name="file"
onChange={[Function]}
type="file"
/>
</form>
</div>
</div>
</div>
<div
className="col"
>
<div
className="d-md-none"
>
<span
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold text-truncate"
>
staff
</h1>
<p
className="mb-0"
>
Member since
2017
</p>
<hr
className="d-none d-md-block"
/>
</span>
</div>
<div
className="d-none d-md-block float-right"
>
<a
className="pgn__hyperlink default-link standalone-link btn btn-primary"
href="http://localhost:18150/records"
onClick={[Function]}
rel="noopener noreferrer"
target="_blank"
>
View My Records
<span
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
Object {
"height": "1em",
"width": "1em",
}
}
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
</div>
</div>
</div>
<div
className="row"
>
<div
className="col-md-4 col-lg-4"
>
<div
className="d-none d-md-block mb-4"
>
<span
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold text-truncate"
>
staff
</h1>
<p
className="mb-0"
>
Member since
2017
</p>
<hr
className="d-none d-md-block"
/>
</span>
</div>
<div
className="d-md-none mb-4"
>
<a
className="pgn__hyperlink default-link standalone-link btn btn-primary"
href="http://localhost:18150/records"
onClick={[Function]}
rel="noopener noreferrer"
target="_blank"
>
View My Records
<span
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
Object {
"height": "1em",
"width": "1em",
}
}
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Full Name
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye-slash fa-w-20 "
data-icon="eye-slash"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 640 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M634 471L36 3.51A16 16 0 0 0 13.51 6l-10 12.49A16 16 0 0 0 6 41l598 467.49a16 16 0 0 0 22.49-2.49l10-12.49A16 16 0 0 0 634 471zM296.79 146.47l134.79 105.38C429.36 191.91 380.48 144 320 144a112.26 112.26 0 0 0-23.21 2.47zm46.42 219.07L208.42 260.16C210.65 320.09 259.53 368 320 368a113 113 0 0 0 23.21-2.46zM320 112c98.65 0 189.09 55 237.93 144a285.53 285.53 0 0 1-44 60.2l37.74 29.5a333.7 333.7 0 0 0 52.9-75.11 32.35 32.35 0 0 0 0-29.19C550.29 135.59 442.93 64 320 64c-36.7 0-71.71 7-104.63 18.81l46.41 36.29c18.94-4.3 38.34-7.1 58.22-7.1zm0 288c-98.65 0-189.08-55-237.93-144a285.47 285.47 0 0 1 44.05-60.19l-37.74-29.5a333.6 333.6 0 0 0-52.89 75.1 32.35 32.35 0 0 0 0 29.19C89.72 376.41 197.08 448 320 448c36.7 0 71.71-7.05 104.63-18.81l-46.41-36.28C359.28 397.2 339.89 400 320 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Just me
</span>
</p>
</div>
<p
className="h5"
data-hj-suppress={true}
>
Lemon Seltzer
</p>
<small
className="form-text text-muted"
>
This is the name that appears in your account and on your certificates.
</small>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Location
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
<p
className="h5"
data-hj-suppress={true}
>
Montenegro
</p>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Primary Language Spoken
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
<p
className="h5"
data-hj-suppress={true}
>
Yoruba
</p>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Education
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye-slash fa-w-20 "
data-icon="eye-slash"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 640 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M634 471L36 3.51A16 16 0 0 0 13.51 6l-10 12.49A16 16 0 0 0 6 41l598 467.49a16 16 0 0 0 22.49-2.49l10-12.49A16 16 0 0 0 634 471zM296.79 146.47l134.79 105.38C429.36 191.91 380.48 144 320 144a112.26 112.26 0 0 0-23.21 2.47zm46.42 219.07L208.42 260.16C210.65 320.09 259.53 368 320 368a113 113 0 0 0 23.21-2.46zM320 112c98.65 0 189.09 55 237.93 144a285.53 285.53 0 0 1-44 60.2l37.74 29.5a333.7 333.7 0 0 0 52.9-75.11 32.35 32.35 0 0 0 0-29.19C550.29 135.59 442.93 64 320 64c-36.7 0-71.71 7-104.63 18.81l46.41 36.29c18.94-4.3 38.34-7.1 58.22-7.1zm0 288c-98.65 0-189.08-55-237.93-144a285.47 285.47 0 0 1 44.05-60.19l-37.74-29.5a333.6 333.6 0 0 0-52.89 75.1 32.35 32.35 0 0 0 0 29.19C89.72 376.41 197.08 448 320 448c36.7 0 71.71-7.05 104.63-18.81l-46.41-36.28C359.28 397.2 339.89 400 320 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Just me
</span>
</p>
</div>
<p
className="h5"
data-hj-suppress={true}
>
Elementary/primary school
</p>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Social Links
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
@@ -2055,7 +7814,7 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
onSubmit={[Function]}
>
<div
className="form-group"
className="pgn__form-group"
>
<label
className="edit-section-header"
@@ -2064,7 +7823,6 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
About Me
</label>
<textarea
aria-describedby=""
className="form-control"
id="bio"
name="bio"
@@ -2114,7 +7872,7 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
</svg>
</span>
<select
className="d-inline-block w-auto form-control"
className="d-inline-block form-control"
id="visibilityBio"
name="visibilityBio"
onChange={[Function]}
@@ -2129,7 +7887,7 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
<option
value="all_users"
>
Everyone on edX
Everyone on localhost
</option>
</select>
</span>
@@ -2156,7 +7914,6 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
>
<svg
aria-hidden={true}
aria-label=""
fill="none"
focusable={false}
height={24}
@@ -2172,9 +7929,7 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
</svg>
</span>
</span>
<span
className=""
>
<span>
Saving
</span>
</span>
@@ -2271,7 +8026,7 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
/>
</svg>
Everyone on edX
Everyone on localhost
</span>
</p>
</div>
@@ -2279,7 +8034,7 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
className="row align-items-stretch"
>
<div
className="col col-sm-6 d-flex align-items-stretch"
className="col-12 col-sm-6 d-flex align-items-stretch"
>
<div
className="card mb-4 certificate flex-grow-1"
@@ -2312,9 +8067,7 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
<p
className="small mb-0"
>
<span>
From
</span>
From
</p>
<p
className="h6 mb-4"
@@ -2327,26 +8080,22 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
<p
className="small mb-2"
>
<span>
Completed on
<span>
3/4/2019
</span>
</span>
Completed on
3/4/2019
</p>
<div>
<a
className="btn btn-outline-primary"
className="pgn__hyperlink default-link standalone-link btn btn-outline-primary"
href="http://www.example.com/"
onClick={[Function]}
rel="noopener"
rel="noopener noreferrer"
target="_blank"
>
View Certificate
<span
className="d-inline-block align-text-top"
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
@@ -2358,7 +8107,6 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
>
<svg
aria-hidden={true}
aria-label=""
fill="none"
focusable={false}
height={24}
@@ -2372,6 +8120,11 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
@@ -2388,12 +8141,12 @@ exports[`<ProfilePage /> Renders correctly in various states while saving an edi
</div>
`;
exports[`<ProfilePage /> Renders correctly in various states without credentials service 1`] = `
exports[`<ProfilePage /> Renders correctly in various states while saving an edited bio with error 1`] = `
<div
className="profile-page"
>
<div
className="profile-page-bg-banner bg-primary d-none d-md-block p-relative"
className="profile-page-bg-banner bg-primary d-md-block p-relative"
/>
<div
className="container-fluid"
@@ -2417,7 +8170,8 @@ exports[`<ProfilePage /> Renders correctly in various states without credentials
className="profile-avatar-menu-container"
>
<div
className="dropdown"
className="pgn__dropdown pgn__dropdown-light dropdown"
data-testid="dropdown"
>
<button
aria-expanded={false}
@@ -2460,7 +8214,7 @@ exports[`<ProfilePage /> Renders correctly in various states without credentials
</div>
</div>
<div
className="col pl-0"
className="col"
>
<div
className="d-md-none"
@@ -2469,19 +8223,1138 @@ exports[`<ProfilePage /> Renders correctly in various states without credentials
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold"
className="h2 mb-0 font-weight-bold text-truncate"
>
staff
</h1>
<p
className="mb-0"
>
<span>
Member since
<span>
2017
Member since
2017
</p>
<hr
className="d-none d-md-block"
/>
</span>
</div>
<div
className="d-none d-md-block float-right"
>
<a
className="pgn__hyperlink default-link standalone-link btn btn-primary"
href="http://localhost:18150/records"
onClick={[Function]}
rel="noopener noreferrer"
target="_blank"
>
View My Records
<span
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
Object {
"height": "1em",
"width": "1em",
}
}
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
</div>
</div>
</div>
<div
className="row"
>
<div
className="col-md-4 col-lg-4"
>
<div
className="d-none d-md-block mb-4"
>
<span
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold text-truncate"
>
staff
</h1>
<p
className="mb-0"
>
Member since
2017
</p>
<hr
className="d-none d-md-block"
/>
</span>
</div>
<div
className="d-md-none mb-4"
>
<a
className="pgn__hyperlink default-link standalone-link btn btn-primary"
href="http://localhost:18150/records"
onClick={[Function]}
rel="noopener noreferrer"
target="_blank"
>
View My Records
<span
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
Object {
"height": "1em",
"width": "1em",
}
}
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Full Name
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye-slash fa-w-20 "
data-icon="eye-slash"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 640 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M634 471L36 3.51A16 16 0 0 0 13.51 6l-10 12.49A16 16 0 0 0 6 41l598 467.49a16 16 0 0 0 22.49-2.49l10-12.49A16 16 0 0 0 634 471zM296.79 146.47l134.79 105.38C429.36 191.91 380.48 144 320 144a112.26 112.26 0 0 0-23.21 2.47zm46.42 219.07L208.42 260.16C210.65 320.09 259.53 368 320 368a113 113 0 0 0 23.21-2.46zM320 112c98.65 0 189.09 55 237.93 144a285.53 285.53 0 0 1-44 60.2l37.74 29.5a333.7 333.7 0 0 0 52.9-75.11 32.35 32.35 0 0 0 0-29.19C550.29 135.59 442.93 64 320 64c-36.7 0-71.71 7-104.63 18.81l46.41 36.29c18.94-4.3 38.34-7.1 58.22-7.1zm0 288c-98.65 0-189.08-55-237.93-144a285.47 285.47 0 0 1 44.05-60.19l-37.74-29.5a333.6 333.6 0 0 0-52.89 75.1 32.35 32.35 0 0 0 0 29.19C89.72 376.41 197.08 448 320 448c36.7 0 71.71-7.05 104.63-18.81l-46.41-36.28C359.28 397.2 339.89 400 320 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Just me
</span>
</p>
</div>
<p
className="h5"
data-hj-suppress={true}
>
Lemon Seltzer
</p>
<small
className="form-text text-muted"
>
This is the name that appears in your account and on your certificates.
</small>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Location
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
<p
className="h5"
data-hj-suppress={true}
>
Montenegro
</p>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Primary Language Spoken
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
<p
className="h5"
data-hj-suppress={true}
>
Yoruba
</p>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Education
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye-slash fa-w-20 "
data-icon="eye-slash"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 640 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M634 471L36 3.51A16 16 0 0 0 13.51 6l-10 12.49A16 16 0 0 0 6 41l598 467.49a16 16 0 0 0 22.49-2.49l10-12.49A16 16 0 0 0 634 471zM296.79 146.47l134.79 105.38C429.36 191.91 380.48 144 320 144a112.26 112.26 0 0 0-23.21 2.47zm46.42 219.07L208.42 260.16C210.65 320.09 259.53 368 320 368a113 113 0 0 0 23.21-2.46zM320 112c98.65 0 189.09 55 237.93 144a285.53 285.53 0 0 1-44 60.2l37.74 29.5a333.7 333.7 0 0 0 52.9-75.11 32.35 32.35 0 0 0 0-29.19C550.29 135.59 442.93 64 320 64c-36.7 0-71.71 7-104.63 18.81l46.41 36.29c18.94-4.3 38.34-7.1 58.22-7.1zm0 288c-98.65 0-189.08-55-237.93-144a285.47 285.47 0 0 1 44.05-60.19l-37.74-29.5a333.6 333.6 0 0 0-52.89 75.1 32.35 32.35 0 0 0 0 29.19C89.72 376.41 197.08 448 320 448c36.7 0 71.71-7.05 104.63-18.81l-46.41-36.28C359.28 397.2 339.89 400 320 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Just me
</span>
</p>
</div>
<p
className="h5"
data-hj-suppress={true}
>
Elementary/primary school
</p>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Social Links
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
<ul
className="list-unstyled"
>
<li
className="form-group"
>
<a
className="font-weight-bold"
href="https://www.twitter.com/ALOHA"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-twitter fa-w-16 mr-2"
data-icon="twitter"
data-prefix="fab"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"
fill="currentColor"
style={Object {}}
/>
</svg>
Twitter
</a>
</li>
<li
className="form-group"
>
<a
className="font-weight-bold"
href="https://www.facebook.com/aloha"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-facebook fa-w-16 mr-2"
data-icon="facebook"
data-prefix="fab"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M504 256C504 119 393 8 256 8S8 119 8 256c0 123.78 90.69 226.38 209.25 245V327.69h-63V256h63v-54.64c0-62.15 37-96.48 93.67-96.48 27.14 0 55.52 4.84 55.52 4.84v61h-31.28c-30.8 0-40.41 19.12-40.41 38.73V256h68.78l-11 71.69h-57.78V501C413.31 482.38 504 379.78 504 256z"
fill="currentColor"
style={Object {}}
/>
</svg>
Facebook
</a>
</li>
<li
className="form-group"
>
<div>
<button
className="pl-0 text-left btn btn-link"
onClick={[Function]}
onKeyDown={[Function]}
tabIndex={0}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-plus fa-w-14 fa-xs mr-2"
data-icon="plus"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z"
fill="currentColor"
style={Object {}}
/>
</svg>
Add
LinkedIn
</button>
</div>
</li>
</ul>
</div>
</div>
</div>
<div
className="pt-md-3 col-md-8 col-lg-7 offset-lg-1"
>
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
aria-labelledby="bio-label"
role="dialog"
>
<form
onSubmit={[Function]}
>
<div
className="pgn__form-group"
>
<label
className="edit-section-header"
htmlFor="bio"
>
About Me
</label>
<textarea
className="form-control"
id="bio"
name="bio"
onChange={[Function]}
value="This is my bio"
/>
<div
className="pgn__form-control-description pgn__form-text pgn__form-text-invalid"
id="bio-1"
>
bio error
</div>
</div>
<div
className="d-flex flex-row-reverse flex-wrap justify-content-end align-items-center"
>
<div
className="form-group d-flex flex-wrap"
>
<label
className="col-form-label"
htmlFor="visibilityBio"
>
Who can see this:
</label>
<span
className="d-flex align-items-center"
>
<span
className="d-inline-block ml-1 mr-2"
style={
Object {
"width": "1.5rem",
}
}
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
</span>
<select
className="d-inline-block form-control"
id="visibilityBio"
name="visibilityBio"
onChange={[Function]}
type="select"
value="all_users"
>
<option
value="private"
>
Just me
</option>
<option
value="all_users"
>
Everyone on localhost
</option>
</select>
</span>
</div>
<div
className="form-group flex-shrink-0 flex-grow-1"
>
<button
aria-disabled={false}
aria-live="assertive"
className="pgn__stateful-btn pgn__stateful-btn-state-pending btn btn-primary"
disabled={false}
onClick={[Function]}
type="submit"
>
<span
className="d-flex align-items-center justify-content-center"
>
<span
className="pgn__stateful-btn-icon"
>
<span
className="pgn__icon icon-spin"
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M22 12A10 10 0 116.122 3.91l1.176 1.618A8 8 0 1020 12h2z"
fill="currentColor"
/>
</svg>
</span>
</span>
<span>
Saving
</span>
</span>
</button>
<button
className="btn btn-link"
disabled={false}
onClick={[Function]}
type="button"
>
Cancel
</button>
</div>
</div>
</form>
</div>
</div>
</div>
<div
className="pgn-transition-replace-group position-relative mb-4"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
My Certificates
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye fa-w-18 "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
<div
className="row align-items-stretch"
>
<div
className="col-12 col-sm-6 d-flex align-items-stretch"
>
<div
className="card mb-4 certificate flex-grow-1"
>
<div
className="certificate-type-illustration"
style={
Object {
"backgroundImage": "url(icon/mock/path)",
}
}
/>
<div
className="card-body d-flex flex-column"
>
<div
className="card-title"
>
<p
className="small mb-0"
>
Verified Certificate
</p>
<h4
className="certificate-title"
>
edX Demonstration Course
</h4>
</div>
<p
className="small mb-0"
>
From
</p>
<p
className="h6 mb-4"
>
edX
</p>
<div
className="flex-grow-1"
/>
<p
className="small mb-2"
>
Completed on
3/4/2019
</p>
<div>
<a
className="pgn__hyperlink default-link standalone-link btn btn-outline-primary"
href="http://www.example.com/"
onClick={[Function]}
rel="noopener noreferrer"
target="_blank"
>
View Certificate
<span
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
Object {
"height": "1em",
"width": "1em",
}
}
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`<ProfilePage /> Renders correctly in various states without credentials service 1`] = `
<div
className="profile-page"
>
<div
className="profile-page-bg-banner bg-primary d-md-block p-relative"
/>
<div
className="container-fluid"
>
<div
className="row align-items-center pt-4 mb-4 pt-md-0 mb-md-0"
>
<div
className="col-auto col-md-4 col-lg-3"
>
<div
className="d-flex align-items-center d-md-block"
>
<div
className="profile-avatar-wrap position-relative"
>
<div
className="profile-avatar rounded-circle bg-light"
>
<div
className="profile-avatar-menu-container"
>
<div
className="pgn__dropdown pgn__dropdown-light dropdown"
data-testid="dropdown"
>
<button
aria-expanded={false}
aria-haspopup={true}
className="dropdown-toggle btn btn-primary"
disabled={false}
onClick={[Function]}
type="button"
>
Change
</button>
</div>
</div>
<img
alt="profile avatar"
className="w-100 h-100 d-block rounded-circle overflow-hidden"
data-hj-suppress={true}
src="http://localhost:18000/media/profile-images/d2a9bdc2ba165dcefc73265c54bf9a20_500.jpg?v=1552495012"
style={
Object {
"objectFit": "cover",
}
}
/>
</div>
<form
encType="multipart/form-data"
onSubmit={[Function]}
>
<input
accept=".jpg, .jpeg, .png"
className="d-none form-control-file"
id="photo-file"
name="file"
onChange={[Function]}
type="file"
/>
</form>
</div>
</div>
</div>
<div
className="col"
>
<div
className="d-md-none"
>
<span
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold text-truncate"
>
staff
</h1>
<p
className="mb-0"
>
Member since
2017
</p>
<hr
className="d-none d-md-block"
@@ -2506,19 +9379,15 @@ exports[`<ProfilePage /> Renders correctly in various states without credentials
data-hj-suppress={true}
>
<h1
className="h2 mb-0 font-weight-bold"
className="h2 mb-0 font-weight-bold text-truncate"
>
staff
</h1>
<p
className="mb-0"
>
<span>
Member since
<span>
2017
</span>
</span>
Member since
2017
</p>
<hr
className="d-none d-md-block"
@@ -2701,7 +9570,7 @@ exports[`<ProfilePage /> Renders correctly in various states without credentials
/>
</svg>
Everyone on edX
Everyone on localhost
</span>
</p>
</div>
@@ -2791,7 +9660,7 @@ exports[`<ProfilePage /> Renders correctly in various states without credentials
/>
</svg>
Everyone on edX
Everyone on localhost
</span>
</p>
</div>
@@ -2971,7 +9840,7 @@ exports[`<ProfilePage /> Renders correctly in various states without credentials
/>
</svg>
Everyone on edX
Everyone on localhost
</span>
</p>
</div>
@@ -3150,7 +10019,7 @@ exports[`<ProfilePage /> Renders correctly in various states without credentials
/>
</svg>
Everyone on edX
Everyone on localhost
</span>
</p>
</div>
@@ -3240,7 +10109,7 @@ exports[`<ProfilePage /> Renders correctly in various states without credentials
/>
</svg>
Everyone on edX
Everyone on localhost
</span>
</p>
</div>
@@ -3248,7 +10117,7 @@ exports[`<ProfilePage /> Renders correctly in various states without credentials
className="row align-items-stretch"
>
<div
className="col col-sm-6 d-flex align-items-stretch"
className="col-12 col-sm-6 d-flex align-items-stretch"
>
<div
className="card mb-4 certificate flex-grow-1"
@@ -3281,9 +10150,7 @@ exports[`<ProfilePage /> Renders correctly in various states without credentials
<p
className="small mb-0"
>
<span>
From
</span>
From
</p>
<p
className="h6 mb-4"
@@ -3296,26 +10163,22 @@ exports[`<ProfilePage /> Renders correctly in various states without credentials
<p
className="small mb-2"
>
<span>
Completed on
<span>
3/4/2019
</span>
</span>
Completed on
3/4/2019
</p>
<div>
<a
className="btn btn-outline-primary"
className="pgn__hyperlink default-link standalone-link btn btn-outline-primary"
href="http://www.example.com/"
onClick={[Function]}
rel="noopener"
rel="noopener noreferrer"
target="_blank"
>
View Certificate
<span
className="d-inline-block align-text-top"
className="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
className="pgn__icon"
style={
@@ -3327,7 +10190,6 @@ exports[`<ProfilePage /> Renders correctly in various states without credentials
>
<svg
aria-hidden={true}
aria-label=""
fill="none"
focusable={false}
height={24}
@@ -3341,6 +10203,11 @@ exports[`<ProfilePage /> Renders correctly in various states without credentials
fill="currentColor"
/>
</svg>
<span
className="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>

View File

@@ -7,7 +7,7 @@ const EDUCATION_LEVELS = [
'jhs',
'el',
'none',
'o',
'other',
];
const SOCIAL = {

View File

@@ -0,0 +1,7 @@
const mockData = {
learningGoal: 'advance_career',
editMode: 'static',
visibilityLearningGoal: 'private',
};
export default mockData;

View File

@@ -24,7 +24,7 @@ export const initialState = {
isAuthenticatedUserProfile: false,
};
const profilePage = (state = initialState, action) => {
const profilePage = (state = initialState, action = {}) => {
switch (action.type) {
case FETCH_PROFILE.BEGIN:
return {

View File

@@ -66,6 +66,25 @@ export function* handleFetchProfile(action) {
} else {
[account, courseCertificates] = result;
}
// Set initial visibility values for account
// Set account_privacy as custom is necessary so that when viewing another user's profile,
// their full name is displayed and change visibility forms are worked correctly
if (isAuthenticatedUserProfile && result[0].accountPrivacy === 'all_users') {
yield call(ProfileApiService.patchPreferences, action.payload.username, {
account_privacy: 'custom',
'visibility.name': 'all_users',
'visibility.bio': 'all_users',
'visibility.course_certificates': 'all_users',
'visibility.country': 'all_users',
'visibility.date_joined': 'all_users',
'visibility.level_of_education': 'all_users',
'visibility.language_proficiencies': 'all_users',
'visibility.social_links': 'all_users',
'visibility.time_zone': 'all_users',
});
}
yield put(fetchProfileSuccess(
account,
preferences,

View File

@@ -35,9 +35,12 @@ export const editableFormModeSelector = createSelector(
// or is being hidden from us (for other users' profiles)
let propExists = account[formId] != null && account[formId].length > 0;
propExists = formId === 'certificates' ? certificates.length > 0 : propExists; // overwrite for certificates
// If this isn't the current user's profile or if
// If this isn't the current user's profile
if (!isAuthenticatedUserProfile) {
return 'static';
}
// the current user has no age set / under 13 ...
if (!isAuthenticatedUserProfile || account.requiresParentalConsent) {
if (account.requiresParentalConsent) {
// then there are only two options: static or nothing.
// We use 'null' as a return value because the consumers of
// getMode render nothing at all on a mode of null.
@@ -228,13 +231,13 @@ export const visibilitiesSelector = createSelector(
switch (accountPrivacy) {
case 'custom':
return {
visibilityBio: preferences.visibilityBio || 'private',
visibilityCourseCertificates: preferences.visibilityCourseCertificates || 'private',
visibilityCountry: preferences.visibilityCountry || 'private',
visibilityLevelOfEducation: preferences.visibilityLevelOfEducation || 'private',
visibilityLanguageProficiencies: preferences.visibilityLanguageProficiencies || 'private',
visibilityName: preferences.visibilityName || 'private',
visibilitySocialLinks: preferences.visibilitySocialLinks || 'private',
visibilityBio: preferences.visibilityBio || 'all_users',
visibilityCourseCertificates: preferences.visibilityCourseCertificates || 'all_users',
visibilityCountry: preferences.visibilityCountry || 'all_users',
visibilityLevelOfEducation: preferences.visibilityLevelOfEducation || 'all_users',
visibilityLanguageProficiencies: preferences.visibilityLanguageProficiencies || 'all_users',
visibilityName: preferences.visibilityName || 'all_users',
visibilitySocialLinks: preferences.visibilitySocialLinks || 'all_users',
};
case 'private':
return {
@@ -335,6 +338,7 @@ export const profilePageSelector = createSelector(
profileImage,
requiresParentalConsent: account.requiresParentalConsent,
dateJoined: account.dateJoined,
yearOfBirth: account.yearOfBirth,
// Bio form data
bio: formValues.bio,

View File

@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { ValidationFormGroup } from '@edx/paragon';
import { Form } from '@edx/paragon';
import messages from './Bio.messages';
@@ -56,10 +56,9 @@ class Bio extends React.Component {
editing: (
<div role="dialog" aria-labelledby={`${formId}-label`}>
<form onSubmit={this.handleSubmit}>
<ValidationFormGroup
for={formId}
invalid={error !== null}
invalidMessage={error}
<Form.Group
controlId={formId}
isInvalid={error !== null}
>
<label className="edit-section-header" htmlFor={formId}>
{intl.formatMessage(messages['profile.bio.about.me'])}
@@ -71,7 +70,12 @@ class Bio extends React.Component {
value={bio}
onChange={this.handleChange}
/>
</ValidationFormGroup>
{error !== null && (
<Form.Control.Feedback hasIcon={false}>
{error}
</Form.Control.Feedback>
)}
</Form.Group>
<FormControls
visibilityId="visibilityBio"
saveState={saveState}

View File

@@ -68,7 +68,7 @@ class Certificates extends React.Component {
})();
return (
<div key={`${modifiedDate}-${courseId}`} className="col col-sm-6 d-flex align-items-stretch">
<div key={`${modifiedDate}-${courseId}`} className="col-12 col-sm-6 d-flex align-items-stretch">
<div className="card mb-4 certificate flex-grow-1">
<div
className="certificate-type-illustration"

View File

@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { ValidationFormGroup } from '@edx/paragon';
import { Form } from '@edx/paragon';
import messages from './Country.messages';
@@ -67,10 +67,9 @@ class Country extends React.Component {
editing: (
<div role="dialog" aria-labelledby={`${formId}-label`}>
<form onSubmit={this.handleSubmit}>
<ValidationFormGroup
for={formId}
invalid={error !== null}
invalidMessage={error}
<Form.Group
controlId={formId}
isInvalid={error !== null}
>
<label className="edit-section-header" htmlFor={formId}>
{intl.formatMessage(messages['profile.country.label'])}
@@ -89,7 +88,12 @@ class Country extends React.Component {
<option key={code} value={code}>{name}</option>
))}
</select>
</ValidationFormGroup>
{error !== null && (
<Form.Control.Feedback hasIcon={false}>
{error}
</Form.Control.Feedback>
)}
</Form.Group>
<FormControls
visibilityId="visibilityCountry"
saveState={saveState}

View File

@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import get from 'lodash.get';
import { ValidationFormGroup } from '@edx/paragon';
import { Form } from '@edx/paragon';
import messages from './Education.messages';
@@ -63,10 +63,9 @@ class Education extends React.Component {
editing: (
<div role="dialog" aria-labelledby={`${formId}-label`}>
<form onSubmit={this.handleSubmit}>
<ValidationFormGroup
for={formId}
invalid={error !== null}
invalidMessage={error}
<Form.Group
controlId={formId}
isInvalid={error !== null}
>
<label className="edit-section-header" htmlFor={formId}>
{intl.formatMessage(messages['profile.education.education'])}
@@ -90,7 +89,12 @@ class Education extends React.Component {
</option>
))}
</select>
</ValidationFormGroup>
{error !== null && (
<Form.Control.Feedback hasIcon={false}>
{error}
</Form.Control.Feedback>
)}
</Form.Group>
<FormControls
visibilityId="visibilityLevelOfEducation"
saveState={saveState}

View File

@@ -0,0 +1,92 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import get from 'lodash.get';
// Mock Data
import mockData from '../data/mock_data';
import messages from './LearningGoal.messages';
// Components
import EditableItemHeader from './elements/EditableItemHeader';
import SwitchContent from './elements/SwitchContent';
// Selectors
import { editableFormSelector } from '../data/selectors';
const LearningGoal = (props) => {
let { learningGoal, editMode, visibilityLearningGoal } = props;
const { intl } = props;
if (!learningGoal) {
learningGoal = mockData.learningGoal;
}
if (!editMode || editMode === 'empty') { // editMode defaults to 'empty', not sure why yet
editMode = mockData.editMode;
}
if (!visibilityLearningGoal) {
visibilityLearningGoal = mockData.visibilityLearningGoal;
}
return (
<SwitchContent
className="mb-5"
expression={editMode}
cases={{
editable: (
<>
<EditableItemHeader
content={intl.formatMessage(messages['profile.learningGoal.learningGoal'])}
showVisibility={visibilityLearningGoal !== null}
visibility={visibilityLearningGoal}
/>
<p data-hj-suppress className="lead">
{intl.formatMessage(get(
messages,
`profile.learningGoal.options.${learningGoal}`,
messages['profile.learningGoal.options.something_else'],
))}
</p>
</>
),
static: (
<>
<EditableItemHeader content={intl.formatMessage(messages['profile.learningGoal.learningGoal'])} />
<p data-hj-suppress className="lead">
{intl.formatMessage(get(
messages,
`profile.learningGoal.options.${learningGoal}`,
messages['profile.learningGoal.options.something_else'],
))}
</p>
</>
),
}}
/>
);
};
LearningGoal.propTypes = {
// From Selector
learningGoal: PropTypes.oneOf(['advance_career', 'start_career', 'learn_something_new', 'something_else']),
visibilityLearningGoal: PropTypes.oneOf(['private', 'all_users']),
editMode: PropTypes.oneOf(['editable', 'static']),
// i18n
intl: intlShape.isRequired,
};
LearningGoal.defaultProps = {
editMode: 'static',
learningGoal: null,
visibilityLearningGoal: 'private',
};
export default connect(
editableFormSelector,
{},
)(injectIntl(LearningGoal));

View File

@@ -0,0 +1,31 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
'profile.learningGoal.learningGoal': {
id: 'profile.learningGoal.learningGoal',
defaultMessage: 'Learning Goal',
description: 'A section of a user profile that displays their current learning goal.',
},
'profile.learningGoal.options.start_career': {
id: 'profile.learningGoal.options.start_career',
defaultMessage: 'I want to start my career',
description: 'Selected by user if their goal is to start their career.',
},
'profile.learningGoal.options.advance_career': {
id: 'profile.learningGoal.options.advance_career',
defaultMessage: 'I want to advance my career',
description: 'Selected by user if their goal is to advance their career.',
},
'profile.learningGoal.options.learn_something_new': {
id: 'profile.learningGoal.options.learn_something_new',
defaultMessage: 'I want to learn something new',
description: 'Selected by user if their goal is to learn something new.',
},
'profile.learningGoal.options.something_else': {
id: 'profile.learningGoal.options.something_else',
defaultMessage: 'Something else',
description: 'Selected by user if their goal is not described by the other choices.',
},
});
export default messages;

View File

@@ -0,0 +1,122 @@
import PropTypes from 'prop-types';
import React, { useMemo } from 'react';
import { Provider } from 'react-redux';
import renderer from 'react-test-renderer';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { configure as configureI18n, IntlProvider } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform';
import { AppContext } from '@edx/frontend-platform/react';
import messages from '../../i18n';
import viewOwnProfileMockStore from '../__mocks__/viewOwnProfile.mockStore';
import savingEditedBioMockStore from '../__mocks__/savingEditedBio.mockStore';
import LearningGoal from './LearningGoal';
const mockStore = configureMockStore([thunk]);
// props to be passed down to LearningGoal component
const requiredLearningGoalProps = {
formId: 'learningGoal',
learningGoal: 'advance_career',
drafts: {},
visibilityLearningGoal: 'private',
editMode: 'static',
saveState: null,
error: null,
openHandler: jest.fn(),
};
configureI18n({
loggingService: { logError: jest.fn() },
config: {
ENVIRONMENT: 'production',
LANGUAGE_PREFERENCE_COOKIE_NAME: 'yum',
},
messages,
});
const LearningGoalWrapper = (props) => {
const contextValue = useMemo(() => ({
authenticatedUser: { userId: null, username: null, administrator: false },
config: getConfig(),
}), []);
return (
<AppContext.Provider
value={contextValue}
>
<IntlProvider locale="en">
<Provider store={props.store}>
<LearningGoal {...props} />
</Provider>
</IntlProvider>
</AppContext.Provider>
);
};
LearningGoalWrapper.defaultProps = {
store: mockStore(viewOwnProfileMockStore),
};
LearningGoalWrapper.propTypes = {
store: PropTypes.shape({}),
};
const LearningGoalWrapperWithStore = ({ store }) => {
const contextValue = useMemo(() => ({
authenticatedUser: { userId: null, username: null, administrator: false },
config: getConfig(),
}), []);
return (
<AppContext.Provider
value={contextValue}
>
<IntlProvider locale="en">
<Provider store={mockStore(store)}>
<LearningGoal {...requiredLearningGoalProps} formId="learningGoal" />
</Provider>
</IntlProvider>
</AppContext.Provider>
);
};
LearningGoalWrapperWithStore.defaultProps = {
store: mockStore(savingEditedBioMockStore),
};
LearningGoalWrapperWithStore.propTypes = {
store: PropTypes.shape({}),
};
describe('<LearningGoal />', () => {
describe('renders the current learning goal', () => {
it('renders "I want to advance my career"', () => {
const learningGoalRenderer = renderer.create(
<LearningGoalWrapper
{...requiredLearningGoalProps}
formId="learningGoal"
/>,
);
const learningGoalInstance = learningGoalRenderer.root;
expect(learningGoalInstance.findByProps({ className: 'lead' }).children).toEqual(['I want to advance my career']);
});
it('renders "Something else"', () => {
requiredLearningGoalProps.learningGoal = 'something_else';
const learningGoalRenderer = renderer.create(
<LearningGoalWrapper
{...requiredLearningGoalProps}
formId="learningGoal"
/>,
);
const learningGoalInstance = learningGoalRenderer.root;
expect(learningGoalInstance.findByProps({ className: 'lead' }).children).toEqual(['Something else']);
});
});
});

View File

@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { ValidationFormGroup } from '@edx/paragon';
import { Form } from '@edx/paragon';
import messages from './PreferredLanguage.messages';
@@ -77,10 +77,9 @@ class PreferredLanguage extends React.Component {
editing: (
<div role="dialog" aria-labelledby={`${formId}-label`}>
<form onSubmit={this.handleSubmit}>
<ValidationFormGroup
for={formId}
invalid={error !== null}
invalidMessage={error}
<Form.Group
controlId={formId}
isInvalid={error !== null}
>
<label className="edit-section-header" htmlFor={formId}>
{intl.formatMessage(messages['profile.preferredlanguage.label'])}
@@ -98,7 +97,12 @@ class PreferredLanguage extends React.Component {
<option key={code} value={code}>{name}</option>
))}
</select>
</ValidationFormGroup>
{error !== null && (
<Form.Control.Feedback hasIcon={false}>
{error}
</Form.Control.Feedback>
)}
</Form.Group>
<FormControls
visibilityId="visibilityLanguageProficiencies"
saveState={saveState}

View File

@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { StatusAlert } from '@edx/paragon';
import { Alert } from '@edx/paragon';
import { connect } from 'react-redux';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faTwitter, faFacebook, faLinkedin } from '@fortawesome/free-brands-svg-icons';
@@ -65,19 +65,6 @@ class SocialLinks extends React.Component {
}
}
mergeWithDrafts(newSocialLink) {
const knownPlatforms = ['twitter', 'facebook', 'linkedin'];
const updated = [];
knownPlatforms.forEach((platform) => {
if (newSocialLink.platform === platform) {
updated.push(newSocialLink);
} else if (this.props.draftSocialLinksByPlatform[platform] !== undefined) {
updated.push(this.props.draftSocialLinksByPlatform[platform]);
}
});
return updated;
}
handleSubmit(e) {
e.preventDefault();
this.props.submitHandler(this.props.formId);
@@ -91,6 +78,19 @@ class SocialLinks extends React.Component {
this.props.openHandler(this.props.formId);
}
mergeWithDrafts(newSocialLink) {
const knownPlatforms = ['twitter', 'facebook', 'linkedin'];
const updated = [];
knownPlatforms.forEach((platform) => {
if (newSocialLink.platform === platform) {
updated.push(newSocialLink);
} else if (this.props.draftSocialLinksByPlatform[platform] !== undefined) {
updated.push(this.props.draftSocialLinksByPlatform[platform]);
}
});
return updated;
}
render() {
const {
socialLinks, visibilitySocialLinks, editMode, saveState, error, intl,
@@ -158,14 +158,19 @@ class SocialLinks extends React.Component {
),
editing: (
<div role="dialog" aria-labelledby="social-links-label">
<form onSubmit={this.handleSubmit}>
<form aria-labelledby="editing-form" onSubmit={this.handleSubmit}>
<EditableItemHeader
headingId="social-links-label"
content={intl.formatMessage(messages['profile.sociallinks.social.links'])}
/>
{/* TODO: Replace this alert with per-field errors. Needs API update. */}
<div id="social-error-feedback">
{error !== null ? <StatusAlert alertType="danger" dialog={error} dismissible={false} open /> : null}
{error !== null
? (
<Alert variant="danger" dismissible={false} show>
{error}
</Alert>
) : null}
</div>
<ul className="list-unstyled">
{socialLinks.map(({ platform, socialLink }) => (
@@ -239,14 +244,12 @@ export default connect(
{},
)(injectIntl(SocialLinks));
function SocialLink({ url, name, platform }) {
return (
<a href={url} className="font-weight-bold">
<FontAwesomeIcon className="mr-2" icon={platformDisplayInfo[platform].icon} />
{name}
</a>
);
}
const SocialLink = ({ url, name, platform }) => (
<a href={url} className="font-weight-bold">
<FontAwesomeIcon className="mr-2" icon={platformDisplayInfo[platform].icon} />
{name}
</a>
);
SocialLink.propTypes = {
url: PropTypes.string.isRequired,
@@ -254,9 +257,9 @@ SocialLink.propTypes = {
name: PropTypes.string.isRequired,
};
function EditableListItem({
const EditableListItem = ({
url, platform, onClickEmptyContent, name,
}) {
}) => {
const linkDisplay = url ? (
<SocialLink name={name} url={url} platform={platform} />
) : (
@@ -264,7 +267,7 @@ function EditableListItem({
);
return <li className="form-group">{linkDisplay}</li>;
}
};
EditableListItem.propTypes = {
url: PropTypes.string,
@@ -277,24 +280,22 @@ EditableListItem.defaultProps = {
onClickEmptyContent: null,
};
function EditingListItem({
const EditingListItem = ({
platform, name, value, onChange, error,
}) {
return (
<li className="form-group">
<label htmlFor={`social-${platform}`}>{name}</label>
<input
className={classNames('form-control', { 'is-invalid': Boolean(error) })}
type="text"
id={`social-${platform}`}
name={platform}
value={value || ''}
onChange={onChange}
aria-describedby="social-error-feedback"
/>
</li>
);
}
}) => (
<li className="form-group">
<label htmlFor={`social-${platform}`}>{name}</label>
<input
className={classNames('form-control', { 'is-invalid': Boolean(error) })}
type="text"
id={`social-${platform}`}
name={platform}
value={value || ''}
onChange={onChange}
aria-describedby="social-error-feedback"
/>
</li>
);
EditingListItem.propTypes = {
platform: PropTypes.string.isRequired,
@@ -309,35 +310,31 @@ EditingListItem.defaultProps = {
error: null,
};
function EmptyListItem({ onClick, name }) {
return (
<li className="mb-4">
<EmptyContent onClick={onClick}>
<FormattedMessage
id="profile.sociallinks.add"
defaultMessage="Add {network}"
values={{
network: name,
}}
description="{network} is the name of a social network such as Facebook or Twitter"
/>
</EmptyContent>
</li>
);
}
const EmptyListItem = ({ onClick, name }) => (
<li className="mb-4">
<EmptyContent onClick={onClick}>
<FormattedMessage
id="profile.sociallinks.add"
defaultMessage="Add {network}"
values={{
network: name,
}}
description="{network} is the name of a social network such as Facebook or Twitter"
/>
</EmptyContent>
</li>
);
EmptyListItem.propTypes = {
name: PropTypes.string.isRequired,
onClick: PropTypes.func.isRequired,
};
function StaticListItem({ name, url, platform }) {
return (
<li className="mb-2">
<SocialLink name={name} url={url} platform={platform} />
</li>
);
}
const StaticListItem = ({ name, url, platform }) => (
<li className="mb-2">
<SocialLink name={name} url={url} platform={platform} />
</li>
);
StaticListItem.propTypes = {
name: PropTypes.string.isRequired,

View File

@@ -0,0 +1,169 @@
import { mount } from 'enzyme';
import PropTypes from 'prop-types';
import React, { useMemo } from 'react';
import { Provider } from 'react-redux';
import renderer from 'react-test-renderer';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { configure as configureI18n, IntlProvider } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform';
import { AppContext } from '@edx/frontend-platform/react';
import SocialLinks from './SocialLinks';
import * as savingEditedBio from '../__mocks__/savingEditedBio.mockStore';
import messages from '../../i18n';
const mockStore = configureMockStore([thunk]);
const defaultProps = {
formId: 'socialLinks',
socialLinks: [
{
platform: 'facebook',
socialLink: 'https://www.facebook.com/aloha',
},
{
platform: 'twitter',
socialLink: 'https://www.twitter.com/ALOHA',
},
],
drafts: {},
visibilitySocialLinks: 'private',
editMode: 'static',
saveState: null,
error: null,
changeHandler: jest.fn(),
submitHandler: jest.fn(),
closeHandler: jest.fn(),
openHandler: jest.fn(),
};
configureI18n({
loggingService: { logError: jest.fn() },
config: {
ENVIRONMENT: 'production',
LANGUAGE_PREFERENCE_COOKIE_NAME: 'yum',
},
messages,
});
const SocialLinksWrapper = (props) => {
const contextValue = useMemo(() => ({
authenticatedUser: { userId: null, username: null, administrator: false },
config: getConfig(),
}), []);
return (
<AppContext.Provider
value={contextValue}
>
<IntlProvider locale="en">
<Provider store={props.store}>
<SocialLinks {...props} />
</Provider>
</IntlProvider>
</AppContext.Provider>
);
};
SocialLinksWrapper.defaultProps = {
store: mockStore(savingEditedBio),
};
SocialLinksWrapper.propTypes = {
store: PropTypes.shape({}),
};
const SocialLinksWrapperWithStore = ({ store }) => {
const contextValue = useMemo(() => ({
authenticatedUser: { userId: null, username: null, administrator: false },
config: getConfig(),
}), []);
return (
<AppContext.Provider
value={contextValue}
>
<IntlProvider locale="en">
<Provider store={mockStore(store)}>
<SocialLinks {...defaultProps} formId="bio" />
</Provider>
</IntlProvider>
</AppContext.Provider>
);
};
SocialLinksWrapperWithStore.defaultProps = {
store: mockStore(savingEditedBio),
};
SocialLinksWrapperWithStore.propTypes = {
store: PropTypes.shape({}),
};
describe('<SocialLinks />', () => {
['certificates', 'bio', 'goals', 'socialLinks'].forEach(editMode => (
it(`calls social links with edit mode ${editMode}`, () => {
const component = <SocialLinksWrapper {...defaultProps} formId={editMode} />;
const tree = renderer.create(component).toJSON();
expect(tree).toMatchSnapshot();
})
));
it('calls social links with editing', () => {
const changeHandler = jest.fn();
const submitHandler = jest.fn();
const closeHandler = jest.fn();
const component = (
<SocialLinksWrapper
{...defaultProps}
formId="bio"
changeHandler={changeHandler}
submitHandler={submitHandler}
closeHandler={closeHandler}
/>
);
const wrapper = mount(component);
const socialLink = wrapper.find(SocialLinks);
const { platform } = defaultProps.socialLinks[0];
const inputField = socialLink.find(`#social-${platform}`);
inputField.simulate('change', { target: { value: 'test', name: platform } });
expect(changeHandler).toHaveBeenCalledTimes(1);
expect(socialLink.find('#visibilitySocialLinks select').props().value).toBe('private');
const event = { target: { value: 'all_users', name: 'visibilitySocialLinks' } };
socialLink.find('#visibilitySocialLinks select').simulate('change', event);
expect(changeHandler).toHaveBeenCalledTimes(2);
socialLink.find('[aria-labelledby="editing-form"]').simulate('submit');
expect(submitHandler).toHaveBeenCalledTimes(1);
socialLink.find('[aria-labelledby="editing-form"]').find('Button .btn-link').simulate('click');
expect(closeHandler).toHaveBeenCalledTimes(1);
});
it('calls social links with static', () => {
const openHandler = jest.fn();
const component = (
<SocialLinksWrapper
{...defaultProps}
formId="goals"
openHandler={openHandler}
/>
);
const wrapper = mount(component);
const socialLink = wrapper.find(SocialLinks);
socialLink.find('EmptyContent button').first().simulate('click');
expect(openHandler).toHaveBeenCalledTimes(1);
});
it('calls social links with error', () => {
const newStore = JSON.parse(JSON.stringify(savingEditedBio));
newStore.profilePage.errors.bio = { userMessage: 'error' };
const component = <SocialLinksWrapperWithStore store={newStore} />;
const wrapper = mount(component);
const socialLink = wrapper.find(SocialLinks);
expect(socialLink.find('.alert-danger').exists()).toBe(true);
});
});

View File

@@ -0,0 +1,586 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<SocialLinks /> calls social links with edit mode bio 1`] = `
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
aria-labelledby="social-links-label"
role="dialog"
>
<form
aria-labelledby="editing-form"
onSubmit={[Function]}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id="social-links-label"
>
Social Links
</h2>
</div>
<div
id="social-error-feedback"
/>
<ul
className="list-unstyled"
>
<li
className="form-group"
>
<label
htmlFor="social-facebook"
>
Facebook
</label>
<input
aria-describedby="social-error-feedback"
className="form-control"
id="social-facebook"
name="facebook"
onChange={[Function]}
type="text"
value="https://www.facebook.com/aloha"
/>
</li>
<li
className="form-group"
>
<label
htmlFor="social-twitter"
>
Twitter
</label>
<input
aria-describedby="social-error-feedback"
className="form-control"
id="social-twitter"
name="twitter"
onChange={[Function]}
type="text"
value="https://www.twitter.com/ALOHA"
/>
</li>
</ul>
<div
className="d-flex flex-row-reverse flex-wrap justify-content-end align-items-center"
>
<div
className="form-group d-flex flex-wrap"
>
<label
className="col-form-label"
htmlFor="visibilitySocialLinks"
>
Who can see this:
</label>
<span
className="d-flex align-items-center"
>
<span
className="d-inline-block ml-1 mr-2"
style={
Object {
"width": "1.5rem",
}
}
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye-slash fa-w-20 "
data-icon="eye-slash"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 640 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M634 471L36 3.51A16 16 0 0 0 13.51 6l-10 12.49A16 16 0 0 0 6 41l598 467.49a16 16 0 0 0 22.49-2.49l10-12.49A16 16 0 0 0 634 471zM296.79 146.47l134.79 105.38C429.36 191.91 380.48 144 320 144a112.26 112.26 0 0 0-23.21 2.47zm46.42 219.07L208.42 260.16C210.65 320.09 259.53 368 320 368a113 113 0 0 0 23.21-2.46zM320 112c98.65 0 189.09 55 237.93 144a285.53 285.53 0 0 1-44 60.2l37.74 29.5a333.7 333.7 0 0 0 52.9-75.11 32.35 32.35 0 0 0 0-29.19C550.29 135.59 442.93 64 320 64c-36.7 0-71.71 7-104.63 18.81l46.41 36.29c18.94-4.3 38.34-7.1 58.22-7.1zm0 288c-98.65 0-189.08-55-237.93-144a285.47 285.47 0 0 1 44.05-60.19l-37.74-29.5a333.6 333.6 0 0 0-52.89 75.1 32.35 32.35 0 0 0 0 29.19C89.72 376.41 197.08 448 320 448c36.7 0 71.71-7.05 104.63-18.81l-46.41-36.28C359.28 397.2 339.89 400 320 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
</span>
<select
className="d-inline-block form-control"
id="visibilitySocialLinks"
name="visibilitySocialLinks"
onChange={[Function]}
type="select"
value="private"
>
<option
value="private"
>
Just me
</option>
<option
value="all_users"
>
Everyone on localhost
</option>
</select>
</span>
</div>
<div
className="form-group flex-shrink-0 flex-grow-1"
>
<button
aria-disabled={false}
aria-live="assertive"
className="pgn__stateful-btn pgn__stateful-btn-state-pending btn btn-primary"
disabled={false}
onClick={[Function]}
type="submit"
>
<span
className="d-flex align-items-center justify-content-center"
>
<span
className="pgn__stateful-btn-icon"
>
<span
className="pgn__icon icon-spin"
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M22 12A10 10 0 116.122 3.91l1.176 1.618A8 8 0 1020 12h2z"
fill="currentColor"
/>
</svg>
</span>
</span>
<span>
Saving
</span>
</span>
</button>
<button
className="btn btn-link"
disabled={false}
onClick={[Function]}
type="button"
>
Cancel
</button>
</div>
</div>
</form>
</div>
</div>
</div>
`;
exports[`<SocialLinks /> calls social links with edit mode certificates 1`] = `
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Social Links
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye-slash fa-w-20 "
data-icon="eye-slash"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 640 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M634 471L36 3.51A16 16 0 0 0 13.51 6l-10 12.49A16 16 0 0 0 6 41l598 467.49a16 16 0 0 0 22.49-2.49l10-12.49A16 16 0 0 0 634 471zM296.79 146.47l134.79 105.38C429.36 191.91 380.48 144 320 144a112.26 112.26 0 0 0-23.21 2.47zm46.42 219.07L208.42 260.16C210.65 320.09 259.53 368 320 368a113 113 0 0 0 23.21-2.46zM320 112c98.65 0 189.09 55 237.93 144a285.53 285.53 0 0 1-44 60.2l37.74 29.5a333.7 333.7 0 0 0 52.9-75.11 32.35 32.35 0 0 0 0-29.19C550.29 135.59 442.93 64 320 64c-36.7 0-71.71 7-104.63 18.81l46.41 36.29c18.94-4.3 38.34-7.1 58.22-7.1zm0 288c-98.65 0-189.08-55-237.93-144a285.47 285.47 0 0 1 44.05-60.19l-37.74-29.5a333.6 333.6 0 0 0-52.89 75.1 32.35 32.35 0 0 0 0 29.19C89.72 376.41 197.08 448 320 448c36.7 0 71.71-7.05 104.63-18.81l-46.41-36.28C359.28 397.2 339.89 400 320 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Just me
</span>
</p>
</div>
<ul
className="list-unstyled"
>
<li
className="form-group"
>
<a
className="font-weight-bold"
href="https://www.facebook.com/aloha"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-facebook fa-w-16 mr-2"
data-icon="facebook"
data-prefix="fab"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M504 256C504 119 393 8 256 8S8 119 8 256c0 123.78 90.69 226.38 209.25 245V327.69h-63V256h63v-54.64c0-62.15 37-96.48 93.67-96.48 27.14 0 55.52 4.84 55.52 4.84v61h-31.28c-30.8 0-40.41 19.12-40.41 38.73V256h68.78l-11 71.69h-57.78V501C413.31 482.38 504 379.78 504 256z"
fill="currentColor"
style={Object {}}
/>
</svg>
Facebook
</a>
</li>
<li
className="form-group"
>
<a
className="font-weight-bold"
href="https://www.twitter.com/ALOHA"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-twitter fa-w-16 mr-2"
data-icon="twitter"
data-prefix="fab"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"
fill="currentColor"
style={Object {}}
/>
</svg>
Twitter
</a>
</li>
</ul>
</div>
</div>
`;
exports[`<SocialLinks /> calls social links with edit mode goals 1`] = `
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Social Links
</h2>
</div>
<ul
className="list-unstyled"
>
<li
className="mb-4"
>
<div>
<button
className="pl-0 text-left btn btn-link"
onClick={[Function]}
onKeyDown={[Function]}
tabIndex={0}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-plus fa-w-14 fa-xs mr-2"
data-icon="plus"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z"
fill="currentColor"
style={Object {}}
/>
</svg>
Add Facebook
</button>
</div>
</li>
<li
className="mb-4"
>
<div>
<button
className="pl-0 text-left btn btn-link"
onClick={[Function]}
onKeyDown={[Function]}
tabIndex={0}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-plus fa-w-14 fa-xs mr-2"
data-icon="plus"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z"
fill="currentColor"
style={Object {}}
/>
</svg>
Add Twitter
</button>
</div>
</li>
</ul>
</div>
</div>
`;
exports[`<SocialLinks /> calls social links with edit mode socialLinks 1`] = `
<div
className="pgn-transition-replace-group position-relative mb-5"
style={
Object {
"height": null,
}
}
>
<div
style={
Object {
"padding": ".1px 0",
}
}
>
<div
className="editable-item-header mb-2"
>
<h2
className="edit-section-header"
id={null}
>
Social Links
<button
className="float-right px-0 btn btn-link btn-sm"
disabled={false}
onClick={[Function]}
style={
Object {
"marginTop": "-.35rem",
}
}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-pencil-alt fa-w-16 mr-1"
data-icon="pencil-alt"
data-prefix="fas"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"
fill="currentColor"
style={Object {}}
/>
</svg>
Edit
</button>
</h2>
<p
className="mb-0"
>
<span
className="ml-auto small text-muted"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-eye-slash fa-w-20 "
data-icon="eye-slash"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 640 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M634 471L36 3.51A16 16 0 0 0 13.51 6l-10 12.49A16 16 0 0 0 6 41l598 467.49a16 16 0 0 0 22.49-2.49l10-12.49A16 16 0 0 0 634 471zM296.79 146.47l134.79 105.38C429.36 191.91 380.48 144 320 144a112.26 112.26 0 0 0-23.21 2.47zm46.42 219.07L208.42 260.16C210.65 320.09 259.53 368 320 368a113 113 0 0 0 23.21-2.46zM320 112c98.65 0 189.09 55 237.93 144a285.53 285.53 0 0 1-44 60.2l37.74 29.5a333.7 333.7 0 0 0 52.9-75.11 32.35 32.35 0 0 0 0-29.19C550.29 135.59 442.93 64 320 64c-36.7 0-71.71 7-104.63 18.81l46.41 36.29c18.94-4.3 38.34-7.1 58.22-7.1zm0 288c-98.65 0-189.08-55-237.93-144a285.47 285.47 0 0 1 44.05-60.19l-37.74-29.5a333.6 333.6 0 0 0-52.89 75.1 32.35 32.35 0 0 0 0 29.19C89.72 376.41 197.08 448 320 448c36.7 0 71.71-7.05 104.63-18.81l-46.41-36.28C359.28 397.2 339.89 400 320 400z"
fill="currentColor"
style={Object {}}
/>
</svg>
Just me
</span>
</p>
</div>
<ul
className="list-unstyled"
>
<li
className="form-group"
>
<a
className="font-weight-bold"
href="https://www.facebook.com/aloha"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-facebook fa-w-16 mr-2"
data-icon="facebook"
data-prefix="fab"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M504 256C504 119 393 8 256 8S8 119 8 256c0 123.78 90.69 226.38 209.25 245V327.69h-63V256h63v-54.64c0-62.15 37-96.48 93.67-96.48 27.14 0 55.52 4.84 55.52 4.84v61h-31.28c-30.8 0-40.41 19.12-40.41 38.73V256h68.78l-11 71.69h-57.78V501C413.31 482.38 504 379.78 504 256z"
fill="currentColor"
style={Object {}}
/>
</svg>
Facebook
</a>
</li>
<li
className="form-group"
>
<a
className="font-weight-bold"
href="https://www.twitter.com/ALOHA"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-twitter fa-w-16 mr-2"
data-icon="twitter"
data-prefix="fab"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"
fill="currentColor"
style={Object {}}
/>
</svg>
Twitter
</a>
</li>
</ul>
</div>
</div>
`;

View File

@@ -7,22 +7,20 @@ import { Button } from '@edx/paragon';
import messages from './EditButton.messages';
function EditButton({
const EditButton = ({
onClick, className, style, intl,
}) {
return (
<Button
variant="link"
size="sm"
className={className}
onClick={onClick}
style={style}
>
<FontAwesomeIcon className="mr-1" icon={faPencilAlt} />
{intl.formatMessage(messages['profile.editbutton.edit'])}
</Button>
);
}
}) => (
<Button
variant="link"
size="sm"
className={className}
onClick={onClick}
style={style}
>
<FontAwesomeIcon className="mr-1" icon={faPencilAlt} />
{intl.formatMessage(messages['profile.editbutton.edit'])}
</Button>
);
export default injectIntl(EditButton);

View File

@@ -4,26 +4,22 @@ import PropTypes from 'prop-types';
import EditButton from './EditButton';
import { Visibility } from './Visibility';
function EditableItemHeader({
const EditableItemHeader = ({
content,
showVisibility,
visibility,
showEditButton,
onClickEdit,
headingId,
}) {
return (
<>
<div className="editable-item-header mb-2">
<h2 className="edit-section-header" id={headingId}>
{content}
{showEditButton ? <EditButton style={{ marginTop: '-.35rem' }} className="float-right px-0" onClick={onClickEdit} /> : null}
</h2>
{showVisibility ? <p className="mb-0"><Visibility to={visibility} /></p> : null}
</div>
</>
);
}
}) => (
<div className="editable-item-header mb-2">
<h2 className="edit-section-header" id={headingId}>
{content}
{showEditButton ? <EditButton style={{ marginTop: '-.35rem' }} className="float-right px-0" onClick={onClickEdit} /> : null}
</h2>
{showVisibility ? <p className="mb-0"><Visibility to={visibility} /></p> : null}
</div>
);
export default EditableItemHeader;

View File

@@ -3,24 +3,22 @@ import PropTypes from 'prop-types';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faPlus } from '@fortawesome/free-solid-svg-icons';
function EmptyContent({ children, onClick, showPlusIcon }) {
return (
<div>
{onClick ? (
<button
type="button"
className="pl-0 text-left btn btn-link"
onClick={onClick}
onKeyDown={(e) => { if (e.key === 'Enter') { onClick(); } }}
tabIndex={0}
>
{showPlusIcon ? <FontAwesomeIcon size="xs" className="mr-2" icon={faPlus} /> : null}
{children}
</button>
) : children}
</div>
);
}
const EmptyContent = ({ children, onClick, showPlusIcon }) => (
<div>
{onClick ? (
<button
type="button"
className="pl-0 text-left btn btn-link"
onClick={onClick}
onKeyDown={(e) => { if (e.key === 'Enter') { onClick(); } }}
tabIndex={0}
>
{showPlusIcon ? <FontAwesomeIcon size="xs" className="mr-2" icon={faPlus} /> : null}
{children}
</button>
) : children}
</div>
);
export default EmptyContent;

View File

@@ -7,9 +7,9 @@ import messages from './FormControls.messages';
import { VisibilitySelect } from './Visibility';
function FormControls({
const FormControls = ({
cancelHandler, changeHandler, visibility, visibilityId, saveState, intl,
}) {
}) => {
// Eliminate error/failed state for save button
const buttonState = saveState === 'error' ? null : saveState;
@@ -57,7 +57,7 @@ function FormControls({
</div>
</div>
);
}
};
export default injectIntl(FormControls);

View File

@@ -22,7 +22,7 @@ const onChildExit = (htmlNode) => {
}
};
function SwitchContent({ expression, cases, className }) {
const SwitchContent = ({ expression, cases, className }) => {
const getContent = (caseKey) => {
if (cases[caseKey]) {
if (typeof cases[caseKey] === 'string') {
@@ -48,7 +48,7 @@ function SwitchContent({ expression, cases, className }) {
{getContent(expression)}
</TransitionReplace>
);
}
};
SwitchContent.propTypes = {
expression: PropTypes.string,

View File

@@ -1,23 +1,24 @@
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faEyeSlash, faEye } from '@fortawesome/free-regular-svg-icons';
import messages from './Visibility.messages';
function Visibility({ to, intl }) {
const Visibility = ({ to, intl }) => {
const icon = to === 'private' ? faEyeSlash : faEye;
const label = to === 'private'
? intl.formatMessage(messages['profile.visibility.who.just.me'])
: intl.formatMessage(messages['profile.visibility.who.everyone']);
: intl.formatMessage(messages['profile.visibility.who.everyone'], { siteName: getConfig().SITE_NAME });
return (
<span className="ml-auto small text-muted">
<FontAwesomeIcon icon={icon} /> {label}
</span>
);
}
};
Visibility.propTypes = {
to: PropTypes.oneOf(['private', 'all_users']),
@@ -29,7 +30,7 @@ Visibility.defaultProps = {
to: 'private',
};
function VisibilitySelect({ intl, className, ...props }) {
const VisibilitySelect = ({ intl, className, ...props }) => {
const { value } = props;
const icon = value === 'private' ? faEyeSlash : faEye;
@@ -38,17 +39,17 @@ function VisibilitySelect({ intl, className, ...props }) {
<span className="d-inline-block ml-1 mr-2" style={{ width: '1.5rem' }}>
<FontAwesomeIcon icon={icon} />
</span>
<select className="d-inline-block w-auto form-control" {...props}>
<select className="d-inline-block form-control" {...props}>
<option key="private" value="private">
{intl.formatMessage(messages['profile.visibility.who.just.me'])}
</option>
<option key="all_users" value="all_users">
{intl.formatMessage(messages['profile.visibility.who.everyone'])}
{intl.formatMessage(messages['profile.visibility.who.everyone'], { siteName: getConfig().SITE_NAME })}
</option>
</select>
</span>
);
}
};
VisibilitySelect.propTypes = {
id: PropTypes.string,

View File

@@ -8,7 +8,7 @@ const messages = defineMessages({
},
'profile.visibility.who.everyone': {
id: 'profile.visibility.who.everyone',
defaultMessage: 'Everyone on edX',
defaultMessage: 'Everyone on {siteName}',
description: 'What users can see this area?',
},
});

View File

@@ -23,6 +23,28 @@
background-size: auto 85%;
}
.username-description {
width: auto;
position: absolute;
left: 1.5rem;
top: 5.25rem;
color: $gray-500;
line-height: 0.9rem;
font-size: 0.8rem;
font-style: normal;
font-weight: 400;
margin-left: 0.9rem;
}
.mb-2rem {
margin-bottom: 2rem;
}
.icon-visibility-off {
height: 1rem;
color: $gray-500;
}
.profile-page {
.edit-section-header {
@extend .h6;

17
src/routes/AppRoutes.jsx Normal file
View File

@@ -0,0 +1,17 @@
import React from 'react';
import {
AuthenticatedPageRoute,
PageRoute,
} from '@edx/frontend-platform/react';
import { Switch } from 'react-router-dom';
import { ProfilePage, NotFoundPage } from '../profile';
const AppRoutes = () => (
<Switch>
<AuthenticatedPageRoute path="/u/:username" component={ProfilePage} />
<PageRoute path="/notfound" component={NotFoundPage} />
<PageRoute path="*" component={NotFoundPage} />
</Switch>
);
export default AppRoutes;

View File

@@ -0,0 +1,73 @@
import React from 'react';
import { AppContext } from '@edx/frontend-platform/react';
import { getConfig } from '@edx/frontend-platform';
import { Router } from 'react-router';
import { render, screen } from '@testing-library/react';
import { createMemoryHistory } from 'history';
import { getLoginRedirectUrl } from '@edx/frontend-platform/auth';
import AppRoutes from './AppRoutes';
jest.mock('@edx/frontend-platform/analytics');
jest.mock('@edx/frontend-platform/auth', () => ({
getLoginRedirectUrl: jest.fn(),
}));
jest.mock('../profile', () => ({
ProfilePage: () => (<div>Profile page</div>),
NotFoundPage: () => (<div>Not found page</div>),
}));
const RoutesWithProvider = (context, history) => (
<AppContext.Provider value={context}>
<Router history={history}>
<AppRoutes />
</Router>
</AppContext.Provider>
);
const unauthenticatedUser = {
authenticatedUser: null,
config: getConfig(),
};
describe('routes', () => {
let history;
beforeEach(() => {
history = createMemoryHistory();
});
test('Profile page should redirect for unauthenticated users', () => {
history.push('/u/edx');
render(
RoutesWithProvider(unauthenticatedUser, history),
);
expect(getLoginRedirectUrl).toHaveBeenCalled();
});
test('Profile page should be accessible for authenticated users', () => {
history.push('/u/edx');
render(
RoutesWithProvider(
{
authenticatedUser: {
username: 'edx',
email: 'edx@example.com',
},
config: getConfig(),
},
history,
),
);
expect(screen.getByText('Profile page')).toBeTruthy();
});
test('should show NotFound page for a bad route', () => {
history.push('/nonMatchingRoute');
render(
RoutesWithProvider(unauthenticatedUser, history),
);
expect(screen.getByText('Not found page')).toBeTruthy();
});
});