Compare commits

...

71 Commits

Author SHA1 Message Date
Brian Smith
9516ee0e92 feat: import FooterSlot from component package instead of slot package (#1198) 2025-04-24 12:11:20 -04:00
renovate[bot]
29fd7176c8 fix(deps): update dependency @edx/frontend-component-header to v6.4.0 (#1201)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-23 20:18:38 +00:00
renovate[bot]
16ddd7abba fix(deps): update dependency @edx/openedx-atlas to ^0.7.0 (#1200)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-21 05:46:19 +00:00
renovate[bot]
577ef6ab0b fix(deps): update dependency @edx/frontend-component-footer to v14.6.0 (#1199)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-21 05:46:13 +00:00
renovate[bot]
8268fa4eab fix(deps): update dependency @edx/frontend-component-header to v6.3.0 (#1197)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-14 06:11:54 +00:00
renovate[bot]
5665f8a0d6 fix(deps): update dependency @edx/frontend-component-footer to v14.4.0 (#1196)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-14 06:11:46 +00:00
renovate[bot]
4b7a3207e0 fix(deps): update dependency @edx/frontend-platform to v8.3.4 (#1195)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-07 07:51:52 +00:00
Hunia Fatima
3db0289aab feat: upgrade react to v18 (#1190) 2025-04-04 11:16:23 -04:00
renovate[bot]
85d3eca9e4 fix(deps): update react-router monorepo to v6.30.0 (#1192)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 06:47:19 +00:00
renovate[bot]
f7fd2959ac chore(deps): update dependency @openedx/frontend-build to v14.4.1 (#1191)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 06:47:09 +00:00
Brian Smith
8652206aa4 chore(deps): update @openedx dependencies to versions that support React 18 (#1189) 2025-03-27 16:17:12 -04:00
renovate[bot]
7a5e03967d fix(deps): update dependency core-js to v3.41.0 (#1188)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 06:30:58 +00:00
renovate[bot]
da19dfaadc fix(deps): update dependency @edx/frontend-platform to v8.3.3 (#1187)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 06:30:34 +00:00
renovate[bot]
60d960276d fix(deps): update dependency @edx/frontend-platform to v8.3.1 (#1178)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-18 11:02:27 +00:00
Awais Ansari
c8a6f9fbd8 test: updated profile test cases (#1182) 2025-03-18 15:58:48 +05:00
renovate[bot]
2ef5a7baff chore(deps): update commitlint monorepo to v19.8.0 (#1177)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 01:35:10 -04:00
renovate[bot]
d59c641b3d chore(deps): update dependency @openedx/frontend-build to v14.3.2 (#1176)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 01:34:58 -04:00
renovate[bot]
4ea80a2a09 chore(deps): update dependency @openedx/frontend-build to v14.3.1 (#1175)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 01:52:17 -05:00
renovate[bot]
45fe50f7f7 fix(deps): update dependency @openedx/paragon to v22.15.3 (#1174)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 01:51:54 -05:00
renovate[bot]
933a177c78 fix(deps): update dependency @openedx/paragon to v22.15.2 (#1170)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 06:10:14 +00:00
renovate[bot]
14fff570a4 fix(deps): update dependency @edx/frontend-component-header to v5.8.3 (#1169)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 01:09:59 -05:00
sundasnoreen12
3d0f3806e1 Merge pull request #1168 from openedx/revert-1166-sundas/INF-1779
Revert "feat: addd countries changes for embargo"
2025-02-22 15:47:48 +05:00
sundasnoreen12
b597e2cc14 Revert "feat: addd countries changes for embargo" 2025-02-22 15:44:11 +05:00
sundasnoreen12
22dc85470a Merge pull request #1166 from openedx/sundas/INF-1779
feat: addd countries changes for embargo
2025-02-22 15:10:21 +05:00
sundasnoreen12
9a26dc7088 refactor: refactored test file 2025-02-20 16:55:53 +05:00
sundasnoreen12
770a248d8c refactor: fixed review suggestions 2025-02-19 16:14:48 +05:00
sundasnoreen12
70cb1803b4 refactor: added constant 2025-02-17 21:09:11 +05:00
sundasnoreen12
e9aa787ade test: fixed test case 2025-02-17 18:29:21 +05:00
sundasnoreen12
01e2f1af79 test: fixed test cases 2025-02-17 18:10:57 +05:00
sundasnoreen12
1e67d51394 feat: addd countries changes for embargo 2025-02-17 13:18:02 +05:00
renovate[bot]
95936419c2 fix(deps): update react-router monorepo to v6.29.0 (#1162)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-10 08:50:22 +00:00
renovate[bot]
00ada93994 fix(deps): update font awesome to v6.7.2 (#1161)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-10 03:50:09 -05:00
renovate[bot]
c57a924cc3 fix(deps): update dependency core-js to v3.40.0 (#1160)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-10 05:36:00 +00:00
renovate[bot]
dc2f03dfad fix(deps): update dependency @openedx/paragon to v22.15.1 (#1159)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-10 00:35:51 -05:00
renovate[bot]
5c7a521705 chore(deps): update dependency @edx/browserslist-config to v1.5.0 (#1158)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 05:11:55 +00:00
renovate[bot]
074374b2af chore(deps): update commitlint monorepo to v19.7.1 (#1157)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 00:11:44 -05:00
renovate[bot]
0a3aad38dc fix(deps): update dependency @edx/frontend-platform to v8.1.5 (#1156)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-27 05:10:58 +00:00
renovate[bot]
1730b5a2c4 chore(deps): update dependency glob to v11.0.1 (#1155)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-27 00:10:45 -05:00
Deborah Kaplan
12269c2c8e Merge pull request #1154 from salman2013/salman/update-catalog-info-file
Add catalog-info.yaml file for release data
2025-01-14 11:06:08 -05:00
salman2013
630dbefb7e chore: Update catalog-info file and remove openedx.yaml 2025-01-14 15:04:47 +05:00
renovate[bot]
00c8697c59 chore(deps): update dependency @commitlint/config-angular to v19.7.0 (#1153)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-06 02:23:40 -05:00
renovate[bot]
8df3d06598 fix(deps): update dependency @edx/frontend-platform to v8.1.4 (#1152)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-06 07:23:31 +00:00
renovate[bot]
f6ed6ee1f5 fix(deps): update dependency @openedx/paragon to v22.13.0 (#1151)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-30 06:41:46 +00:00
renovate[bot]
7e8d22ec6a chore(deps): update dependency @edx/browserslist-config to v1.4.0 (#1150)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-30 01:41:34 -05:00
renovate[bot]
d0595e679d fix(deps): update react-router monorepo to v6.28.1 (#1149)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-23 03:37:53 -05:00
renovate[bot]
4c7e713b6e fix(deps): update dependency @edx/frontend-platform to v8.1.3 (#1148)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-23 08:37:41 +00:00
renovate[bot]
bc0683281f fix(deps): update dependency @edx/frontend-component-header to v5.8.2 (#1147)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-16 06:47:58 +00:00
renovate[bot]
b954345b38 chore(deps): update dependency @commitlint/cli to v19.6.1 (#1146)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-16 06:47:46 +00:00
renovate[bot]
ca4f78bd1c chore(deps): update dependency @edx/browserslist-config to v1.3.0 (#1143)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-09 06:42:17 +00:00
renovate[bot]
3dc8b156fe chore(deps): update dependency @openedx/frontend-build to v14.2.2 (#1142)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-09 01:41:56 -05:00
renovate[bot]
a818cd4dc4 fix(deps): update dependency @edx/frontend-component-header to v5.8.1 (#1141)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-02 08:30:04 +00:00
renovate[bot]
2e9dcd165e fix(deps): update dependency @openedx/frontend-slot-footer to v1.0.7 (#1140)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-02 03:29:49 -05:00
sundasnoreen12
53a52b8f06 Merge pull request #1139 from openedx/sundasMasterBranch-INF-1594
feat: fixed loading issue for wrong username
2024-11-26 19:59:05 +05:00
sundasnoreen12
c66facee92 feat: fixed loading issue for wrong username 2024-11-26 16:32:50 +05:00
renovate[bot]
3270e27c94 chore(deps): update dependency @openedx/frontend-build to v14.2.0 (#1136)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-25 03:33:45 -05:00
renovate[bot]
01cd125d4f chore(deps): update commitlint monorepo to v19.6.0 (#1135)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-25 08:33:31 +00:00
renovate[bot]
5fcef4edf4 fix(deps): update dependency @openedx/paragon to v22.10.0 (#1128)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-18 06:25:48 +00:00
renovate[bot]
d33c79a525 fix(deps): update dependency @edx/frontend-component-header to v5.7.2 (#1127)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-18 01:25:22 -05:00
renovate[bot]
d36c61d44e fix(deps): update react-router monorepo to v6.28.0 (#1126)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-11 07:10:19 +00:00
renovate[bot]
aed6081d37 fix(deps): update dependency core-js to v3.39.0 (#1125)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-11 07:09:23 +00:00
renovate[bot]
66a4eef910 fix(deps): update dependency @openedx/frontend-slot-footer to v1.0.6 (#1124)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-11 06:43:51 +00:00
renovate[bot]
6da6fedc57 fix(deps): update dependency @edx/frontend-component-header to v5.7.1 (#1123)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-11 06:43:30 +00:00
edX requirements bot
a7e095f3bf chore: update browserslist DB (#1091)
Co-authored-by: jsnwesson <62807795+jsnwesson@users.noreply.github.com>
2024-11-11 07:16:51 +05:00
Muhammad Adeel Tajamul
9a393d8e43 Merge pull request #1105 from openedx/renovate/glob-11.x
chore(deps): update dependency glob to v11
2024-11-11 07:16:06 +05:00
renovate[bot]
1a5c4f2404 chore(deps): update dependency glob to v11 2024-11-07 05:13:12 +00:00
Muhammad Adeel Tajamul
13aaca03fd Merge pull request #1118 from openedx/renovate/reselect-5.x
fix(deps): update dependency reselect to v5
2024-11-07 10:12:13 +05:00
renovate[bot]
422aff1915 fix(deps): update dependency reselect to v5 2024-11-04 09:21:34 +00:00
renovate[bot]
cac4e42364 fix(deps): update dependency @edx/frontend-component-header to v5.7.0 2024-11-04 06:01:48 +00:00
renovate[bot]
c6d39884c8 chore(deps): update dependency @testing-library/jest-dom to v6.6.3 2024-11-04 06:01:26 +00:00
Bilal Qamar
4bb3678d4c test: Remove support for Node 18 (#1075) 2024-10-31 14:46:22 -04:00
renovate[bot]
5c2951de40 chore(deps): update dependency redux-mock-store to v1.5.5 2024-10-28 04:53:32 +00:00
15 changed files with 4583 additions and 2767 deletions

View File

@@ -13,12 +13,11 @@ jobs:
- i18n_extract
- lint
- test
node: [18, 20]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
node-version-file: '.nvmrc'
- run: make requirements
- run: make test NPM_TESTS=build
- run: make test NPM_TESTS=${{ matrix.npm-test }}

View File

@@ -17,6 +17,7 @@ metadata:
openedx.org/arch-interest-groups: ""
# This can be multiple comma-separated projects.
openedx.org/add-to-projects: "openedx:23"
openedx.org/release: "master"
spec:
owner: group:2u-infinity
type: 'service'

View File

@@ -1,6 +0,0 @@
# This file describes this Open edX repo, as described in OEP-2:
# https://open-edx-proposals.readthedocs.io/en/latest/oep-0002-bp-repo-metadata.html#specification
nick: prof
oeps: {}
openedx-release: {ref: master}

6499
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,7 @@
"lint": "fedx-scripts eslint --ext .js --ext .jsx .",
"snapshot": "fedx-scripts jest --updateSnapshot",
"start": "fedx-scripts webpack-dev-server --progress",
"dev": "PUBLIC_PATH=/profile/ MFE_CONFIG_API_URL='http://localhost:8000/api/mfe_config/v1' fedx-scripts webpack-dev-server --progress --host apps.local.openedx.io",
"test": "TZ=UTC fedx-scripts jest --coverage --passWithNoTests",
"stubs": "pact-stub-service ./src/pacts/frontend-app-profile-edx-platform.json --port 18000"
},
@@ -29,50 +30,50 @@
],
"dependencies": {
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
"@edx/frontend-component-header": "^5.6.0",
"@edx/frontend-platform": "8.1.2",
"@edx/openedx-atlas": "^0.6.0",
"@fortawesome/fontawesome-svg-core": "6.6.0",
"@fortawesome/free-brands-svg-icons": "6.6.0",
"@fortawesome/free-regular-svg-icons": "6.6.0",
"@fortawesome/free-solid-svg-icons": "6.6.0",
"@edx/frontend-component-footer": "^14.6.0",
"@edx/frontend-component-header": "^6.2.0",
"@edx/frontend-platform": "^8.3.1",
"@edx/openedx-atlas": "^0.7.0",
"@fortawesome/fontawesome-svg-core": "6.7.2",
"@fortawesome/free-brands-svg-icons": "6.7.2",
"@fortawesome/free-regular-svg-icons": "6.7.2",
"@fortawesome/free-solid-svg-icons": "6.7.2",
"@fortawesome/react-fontawesome": "0.2.2",
"@openedx/frontend-slot-footer": "^1.0.2",
"@openedx/paragon": "^22.2.2",
"@openedx/paragon": "^22.17.0",
"@pact-foundation/pact": "^11.0.2",
"@redux-devtools/extension": "3.3.0",
"classnames": "2.5.1",
"core-js": "3.38.1",
"core-js": "3.41.0",
"history": "5.3.0",
"lodash.camelcase": "4.3.0",
"lodash.get": "4.4.2",
"lodash.pick": "4.4.0",
"lodash.snakecase": "4.1.1",
"prop-types": "15.8.1",
"react": "17.0.2",
"react-dom": "17.0.2",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-helmet": "6.1.0",
"react-redux": "7.2.9",
"react-router": "6.27.0",
"react-router-dom": "6.27.0",
"react-router": "6.30.0",
"react-router-dom": "6.30.0",
"redux": "4.2.1",
"redux-logger": "3.0.6",
"redux-saga": "1.3.0",
"redux-thunk": "2.4.2",
"regenerator-runtime": "0.14.1",
"reselect": "4.1.8",
"reselect": "5.1.1",
"universal-cookie": "4.0.4"
},
"devDependencies": {
"@commitlint/cli": "19.5.0",
"@commitlint/config-angular": "19.5.0",
"@commitlint/cli": "19.8.0",
"@commitlint/config-angular": "19.8.0",
"@edx/browserslist-config": "^1.1.1",
"@edx/reactifex": "2.2.0",
"@openedx/frontend-build": "14.1.5",
"@testing-library/jest-dom": "6.6.2",
"@testing-library/react": "12.1.5",
"glob": "10.4.5",
"@openedx/frontend-build": "^14.3.3",
"@testing-library/jest-dom": "6.6.3",
"@testing-library/react": "14.3.1",
"glob": "11.0.1",
"reactifex": "1.1.1",
"redux-mock-store": "1.5.4"
"redux-mock-store": "1.5.5"
}
}

View File

@@ -13,11 +13,12 @@ import {
ErrorPage,
} from '@edx/frontend-platform/react';
import React from 'react';
import ReactDOM from 'react-dom';
import React, { StrictMode } from 'react';
// eslint-disable-next-line import/no-unresolved
import { createRoot } from 'react-dom/client';
import Header from '@edx/frontend-component-header';
import FooterSlot from '@openedx/frontend-slot-footer';
import { FooterSlot } from '@edx/frontend-component-footer';
import messages from './i18n';
import configureStore from './data/configureStore';
@@ -27,22 +28,24 @@ import Head from './head/Head';
import AppRoutes from './routes/AppRoutes';
const rootNode = createRoot(document.getElementById('root'));
subscribe(APP_READY, () => {
ReactDOM.render(
<AppProvider store={configureStore()}>
<Head />
<Header />
<main id="main">
<AppRoutes />
</main>
<FooterSlot />
</AppProvider>,
document.getElementById('root'),
rootNode.render(
<StrictMode>
<AppProvider store={configureStore()}>
<Head />
<Header />
<main id="main">
<AppRoutes />
</main>
<FooterSlot />
</AppProvider>
</StrictMode>,
);
});
subscribe(APP_INIT_ERROR, (error) => {
ReactDOM.render(<ErrorPage message={error.message} />, document.getElementById('root'));
rootNode.render(<ErrorPage message={error.message} />);
});
initialize({

View File

@@ -1,12 +1,15 @@
# Footer Slot
### Slot ID: `footer_slot`
### Slot ID: `org.openedx.frontend.layout.footer.v1`
### Slot ID Aliases
* `footer_slot`
## Description
This slot is used to replace/modify/hide the footer.
The implementation of the `FooterSlot` component lives in [the `frontend-slot-footer` repository](https://github.com/openedx/frontend-slot-footer/).
The implementation of the `FooterSlot` component lives in [the `frontend-component-footer` repository](https://github.com/openedx/frontend-component-footer/).
## Example
@@ -23,7 +26,7 @@ import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-frame
const config = {
pluginSlots: {
footer_slot: {
'org.openedx.frontend.layout.footer.v1': {
plugins: [
{
// Hide the default footer

View File

@@ -1,3 +1,3 @@
# `frontend-app-profile` Plugin Slots
* [`footer_slot`](./FooterSlot/)
* [`org.openedx.frontend.layout.footer.v1`](./FooterSlot/)

View File

@@ -183,12 +183,19 @@ class ProfilePage extends React.Component {
visibilityBio,
requiresParentalConsent,
isLoadingProfile,
username,
saveState,
navigate,
} = this.props;
if (isLoadingProfile) {
return <PageLoading srMessage={this.props.intl.formatMessage(messages['profile.loading'])} />;
}
if (!username && saveState === 'error' && navigate) {
navigate('/notfound');
}
const commonFormProps = {
openHandler: this.handleOpen,
closeHandler: this.handleClose,
@@ -330,6 +337,7 @@ ProfilePage.propTypes = {
// Account data
requiresParentalConsent: PropTypes.bool,
dateJoined: PropTypes.string,
username: PropTypes.string,
// Bio form data
bio: PropTypes.string,
@@ -395,6 +403,7 @@ ProfilePage.propTypes = {
openForm: PropTypes.func.isRequired,
closeForm: PropTypes.func.isRequired,
updateDraft: PropTypes.func.isRequired,
navigate: PropTypes.func.isRequired,
// Router
params: PropTypes.shape({
@@ -407,6 +416,7 @@ ProfilePage.propTypes = {
ProfilePage.defaultProps = {
saveState: null,
username: '',
savePhotoState: null,
photoUploadError: {},
profileImage: {},

View File

@@ -9,6 +9,7 @@ import PropTypes from 'prop-types';
import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { BrowserRouter, useNavigate } from 'react-router-dom';
import messages from '../i18n';
import ProfilePage from './ProfilePage';
@@ -16,6 +17,7 @@ import ProfilePage from './ProfilePage';
const mockStore = configureMockStore([thunk]);
const storeMocks = {
loadingApp: require('./__mocks__/loadingApp.mockStore'),
invalidUser: require('./__mocks__/invalidUser.mockStore'),
viewOwnProfile: require('./__mocks__/viewOwnProfile.mockStore'),
viewOtherProfile: require('./__mocks__/viewOtherProfile.mockStore'),
savingEditedBio: require('./__mocks__/savingEditedBio.mockStore'),
@@ -65,6 +67,23 @@ beforeEach(() => {
analytics.sendTrackingLogEvent.mockReset();
});
const ProfileWrapper = ({ params, requiresParentalConsent }) => {
const navigate = useNavigate();
return (
<ProfilePage
{...requiredProfilePageProps}
params={params}
requiresParentalConsent={requiresParentalConsent}
navigate={navigate}
/>
);
};
ProfileWrapper.propTypes = {
params: PropTypes.shape({}).isRequired,
requiresParentalConsent: PropTypes.bool.isRequired,
};
const ProfilePageWrapper = ({
contextValue, store, params, requiresParentalConsent,
}) => (
@@ -73,7 +92,12 @@ const ProfilePageWrapper = ({
>
<IntlProvider locale="en">
<Provider store={store}>
<ProfilePage {...requiredProfilePageProps} params={params} requiresParentalConsent={requiresParentalConsent} />
<BrowserRouter>
<ProfileWrapper
params={params}
requiresParentalConsent={requiresParentalConsent}
/>
</BrowserRouter>
</Provider>
</IntlProvider>
</AppContext.Provider>
@@ -103,6 +127,16 @@ describe('<ProfilePage />', () => {
expect(tree).toMatchSnapshot();
});
it('successfully redirected to not found page.', () => {
const contextValue = {
authenticatedUser: { userId: 123, username: 'staff', administrator: true },
config: getConfig(),
};
const component = <ProfilePageWrapper contextValue={contextValue} store={mockStore(storeMocks.invalidUser)} />;
const { container: tree } = render(component);
expect(tree).toMatchSnapshot();
});
it('viewing own profile', () => {
const contextValue = {
authenticatedUser: { userId: 123, username: 'staff', administrator: true },

View File

@@ -0,0 +1,41 @@
module.exports = {
userAccount: {
loading: false,
error: null,
username: 'staff',
email: null,
bio: null,
name: null,
country: null,
socialLinks: null,
profileImage: {
imageUrlMedium: null,
imageUrlLarge: null
},
levelOfEducation: null,
learningGoal: null
},
profilePage: {
errors: {},
saveState: 'error',
savePhotoState: null,
currentlyEditingField: null,
account: {
username: '',
socialLinks: []
},
preferences: {},
courseCertificates: [],
drafts: {},
isLoadingProfile: false,
isAuthenticatedUserProfile: true,
},
router: {
location: {
pathname: '/u/staffTest',
search: '',
hash: ''
},
action: 'POP'
}
};

View File

@@ -29,6 +29,641 @@ exports[`<ProfilePage /> Renders correctly in various states app loading 1`] = `
</div>
`;
exports[`<ProfilePage /> Renders correctly in various states successfully redirected to not found page. 1`] = `
<div>
<div
class="profile-page"
>
<div
class="profile-page-bg-banner bg-primary d-md-block p-relative"
/>
<div
class="container-fluid"
>
<div
class="row align-items-center pt-4 mb-4 pt-md-0 mb-md-0"
>
<div
class="col-auto col-md-4 col-lg-3"
>
<div
class="d-flex align-items-center d-md-block"
>
<div
class="profile-avatar-wrap position-relative"
>
<div
class="profile-avatar rounded-circle bg-light"
>
<div
class="profile-avatar-menu-container"
>
<button
class="text-white btn-block btn btn-link btn-sm"
type="button"
>
Upload Photo
</button>
</div>
<div
aria-hidden="true"
class="text-muted"
data-testid="IconMock"
focusable="false"
role="img"
viewbox="0 0 24 24"
/>
</div>
<form
enctype="multipart/form-data"
>
<input
accept=".jpg, .jpeg, .png"
class="d-none form-control-file"
id="photo-file"
name="file"
type="file"
/>
</form>
</div>
</div>
</div>
<div
class="col"
>
<div
class="d-md-none"
>
<span
data-hj-suppress="true"
>
<h1
class="h2 mb-0 font-weight-bold text-truncate"
>
staff
</h1>
<div
class="d-flex align-items-center mt-3 mb-2rem"
>
<span
class="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.45 2.01 3.87l2.68 2.68A11.738 11.738 0 0 0 1 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 0 0-2.64-2.64l2.64 2.64Z"
fill="currentColor"
/>
</svg>
</span>
<div
class="username-description"
>
Your profile information is only visible to you. Only your username is visible to others on localhost.
</div>
</div>
<hr
class="d-none d-md-block"
/>
</span>
</div>
<div
class="d-none d-md-block float-right"
>
<a
class="pgn__hyperlink default-link standalone-link btn btn-primary"
href="http://localhost:18150/records"
rel="noopener noreferrer"
target="_blank"
>
View My Records
<span
class="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
class="pgn__icon"
data-testid="hyperlink-icon"
style="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
class="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
</div>
</div>
</div>
<div
class="row"
>
<div
class="col-md-4 col-lg-4"
>
<div
class="d-none d-md-block mb-4"
>
<span
data-hj-suppress="true"
>
<h1
class="h2 mb-0 font-weight-bold text-truncate"
>
staff
</h1>
<div
class="d-flex align-items-center mt-3 mb-2rem"
>
<span
class="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.45 2.01 3.87l2.68 2.68A11.738 11.738 0 0 0 1 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 0 0-2.64-2.64l2.64 2.64Z"
fill="currentColor"
/>
</svg>
</span>
<div
class="username-description"
>
Your profile information is only visible to you. Only your username is visible to others on localhost.
</div>
</div>
<hr
class="d-none d-md-block"
/>
</span>
</div>
<div
class="d-md-none mb-4"
>
<a
class="pgn__hyperlink default-link standalone-link btn btn-primary"
href="http://localhost:18150/records"
rel="noopener noreferrer"
target="_blank"
>
View My Records
<span
class="pgn__hyperlink__external-icon"
title="Opens in a new tab"
>
<span
class="pgn__icon"
data-testid="hyperlink-icon"
style="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
class="sr-only"
>
in a new tab
</span>
</span>
</span>
</a>
</div>
<div
class="pgn-transition-replace-group position-relative mb-5"
>
<div
style="padding: .1px 0px;"
>
<div
class="editable-item-header mb-2"
>
<h2
class="edit-section-header"
>
Full Name
</h2>
</div>
<div>
<button
class="pl-0 text-left btn btn-link"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-plus fa-xs mr-2"
data-icon="plus"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z"
fill="currentColor"
/>
</svg>
Add name
</button>
</div>
<small
class="form-text text-muted"
>
This is the name that appears in your account and on your certificates.
</small>
</div>
</div>
<div
class="pgn-transition-replace-group position-relative mb-5"
>
<div
style="padding: .1px 0px;"
>
<div
class="editable-item-header mb-2"
>
<h2
class="edit-section-header"
>
Location
</h2>
</div>
<div>
<button
class="pl-0 text-left btn btn-link"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-plus fa-xs mr-2"
data-icon="plus"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z"
fill="currentColor"
/>
</svg>
Add location
</button>
</div>
</div>
</div>
<div
class="pgn-transition-replace-group position-relative mb-5"
>
<div
style="padding: .1px 0px;"
>
<div
class="editable-item-header mb-2"
>
<h2
class="edit-section-header"
>
Primary Language Spoken
</h2>
</div>
<div>
<button
class="pl-0 text-left btn btn-link"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-plus fa-xs mr-2"
data-icon="plus"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z"
fill="currentColor"
/>
</svg>
Add language
</button>
</div>
</div>
</div>
<div
class="pgn-transition-replace-group position-relative mb-5"
>
<div
style="padding: .1px 0px;"
>
<div
class="editable-item-header mb-2"
>
<h2
class="edit-section-header"
>
Education
</h2>
</div>
<div>
<button
class="pl-0 text-left btn btn-link"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-plus fa-xs mr-2"
data-icon="plus"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z"
fill="currentColor"
/>
</svg>
Add education
</button>
</div>
</div>
</div>
<div
class="pgn-transition-replace-group position-relative mb-5"
>
<div
style="padding: .1px 0px;"
>
<div
class="editable-item-header mb-2"
>
<h2
class="edit-section-header"
>
Social Links
</h2>
</div>
<ul
class="list-unstyled"
>
<li
class="mb-4"
>
<div>
<button
class="pl-0 text-left btn btn-link"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-plus fa-xs mr-2"
data-icon="plus"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z"
fill="currentColor"
/>
</svg>
Add Twitter
</button>
</div>
</li>
<li
class="mb-4"
>
<div>
<button
class="pl-0 text-left btn btn-link"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-plus fa-xs mr-2"
data-icon="plus"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z"
fill="currentColor"
/>
</svg>
Add Facebook
</button>
</div>
</li>
<li
class="mb-4"
>
<div>
<button
class="pl-0 text-left btn btn-link"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-plus fa-xs mr-2"
data-icon="plus"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z"
fill="currentColor"
/>
</svg>
Add LinkedIn
</button>
</div>
</li>
</ul>
</div>
</div>
</div>
<div
class="pt-md-3 col-md-8 col-lg-7 offset-lg-1"
>
<div
class="pgn-transition-replace-group position-relative mb-5"
>
<div
style="padding: .1px 0px;"
>
<div
class="editable-item-header mb-2"
>
<h2
class="edit-section-header"
>
About Me
</h2>
</div>
<div>
<button
class="pl-0 text-left btn btn-link"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-plus fa-xs mr-2"
data-icon="plus"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z"
fill="currentColor"
/>
</svg>
Add a short bio
</button>
</div>
</div>
</div>
<div
class="pgn-transition-replace-group position-relative mb-4"
>
<div
style="padding: .1px 0px;"
>
<div
class="editable-item-header mb-2"
>
<h2
class="edit-section-header"
>
My Certificates
<button
class="float-right px-0 btn btn-link btn-sm"
style="margin-top: -.35rem;"
type="button"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-pencil mr-1"
data-icon="pencil"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M410.3 231l11.3-11.3-33.9-33.9-62.1-62.1L291.7 89.8l-11.3 11.3-22.6 22.6L58.6 322.9c-10.4 10.4-18 23.3-22.2 37.4L1 480.7c-2.5 8.4-.2 17.5 6.1 23.7s15.3 8.5 23.7 6.1l120.3-35.4c14.1-4.2 27-11.8 37.4-22.2L387.7 253.7 410.3 231zM160 399.4l-9.1 22.7c-4 3.1-8.5 5.4-13.3 6.9L59.4 452l23-78.1c1.4-4.9 3.8-9.4 6.9-13.3l22.7-9.1 0 32c0 8.8 7.2 16 16 16l32 0zM362.7 18.7L348.3 33.2 325.7 55.8 314.3 67.1l33.9 33.9 62.1 62.1 33.9 33.9 11.3-11.3 22.6-22.6 14.5-14.5c25-25 25-65.5 0-90.5L453.3 18.7c-25-25-65.5-25-90.5 0zm-47.4 168l-144 144c-6.2 6.2-16.4 6.2-22.6 0s-6.2-16.4 0-22.6l144-144c6.2-6.2 16.4-6.2 22.6 0s6.2 16.4 0 22.6z"
fill="currentColor"
/>
</svg>
Edit
</button>
</h2>
<p
class="mb-0"
>
<span
class="ml-auto small text-muted"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-eye "
data-icon="eye"
data-prefix="far"
focusable="false"
role="img"
viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M288 80c-65.2 0-118.8 29.6-159.9 67.7C89.6 183.5 63 226 49.4 256c13.6 30 40.2 72.5 78.6 108.3C169.2 402.4 222.8 432 288 432s118.8-29.6 159.9-67.7C486.4 328.5 513 286 526.6 256c-13.6-30-40.2-72.5-78.6-108.3C406.8 109.6 353.2 80 288 80zM95.4 112.6C142.5 68.8 207.2 32 288 32s145.5 36.8 192.6 80.6c46.8 43.5 78.1 95.4 93 131.1c3.3 7.9 3.3 16.7 0 24.6c-14.9 35.7-46.2 87.7-93 131.1C433.5 443.2 368.8 480 288 480s-145.5-36.8-192.6-80.6C48.6 356 17.3 304 2.5 268.3c-3.3-7.9-3.3-16.7 0-24.6C17.3 208 48.6 156 95.4 112.6zM288 336c44.2 0 80-35.8 80-80s-35.8-80-80-80c-.7 0-1.3 0-2 0c1.3 5.1 2 10.5 2 16c0 35.3-28.7 64-64 64c-5.5 0-10.9-.7-16-2c0 .7 0 1.3 0 2c0 44.2 35.8 80 80 80zm0-208a128 128 0 1 1 0 256 128 128 0 1 1 0-256z"
fill="currentColor"
/>
</svg>
Everyone on localhost
</span>
</p>
</div>
You don't have any certificates yet.
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`<ProfilePage /> Renders correctly in various states test country edit with error 1`] = `
<div>
<div
@@ -5133,9 +5768,10 @@ exports[`<ProfilePage /> Renders correctly in various states viewing other profi
<div
class="profile-avatar rounded-circle bg-light"
>
<iconmock
<div
aria-hidden="true"
class="text-muted"
data-testid="IconMock"
focusable="false"
role="img"
viewbox="0 0 24 24"

View File

@@ -63,12 +63,14 @@ const profilePage = (state = initialState, action = {}) => {
return {
...state,
saveState: 'error',
isLoadingProfile: false,
errors: { ...state.errors, ...action.payload.errors },
};
case SAVE_PROFILE.RESET:
return {
...state,
saveState: null,
isLoadingProfile: false,
errors: {},
};

View File

@@ -1,4 +1,3 @@
import { history } from '@edx/frontend-platform';
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
import pick from 'lodash.pick';
import {
@@ -95,7 +94,11 @@ export function* handleFetchProfile(action) {
yield put(fetchProfileReset());
} catch (e) {
if (e.response.status === 404) {
history.push('/notfound');
if (e.processedData && e.processedData.fieldErrors) {
yield put(saveProfileFailure(e.processedData.fieldErrors));
} else {
yield put(saveProfileFailure(e.customAttributes));
}
} else {
throw e;
}

View File

@@ -3,15 +3,19 @@ import {
AuthenticatedPageRoute,
PageWrap,
} from '@edx/frontend-platform/react';
import { Routes, Route } from 'react-router-dom';
import { Routes, Route, useNavigate } from 'react-router-dom';
import { ProfilePage, NotFoundPage } from '../profile';
const AppRoutes = () => (
<Routes>
<Route path="/u/:username" element={<AuthenticatedPageRoute><ProfilePage /></AuthenticatedPageRoute>} />
<Route path="/notfound" element={<PageWrap><NotFoundPage /></PageWrap>} />
<Route path="*" element={<PageWrap><NotFoundPage /></PageWrap>} />
</Routes>
);
const AppRoutes = () => {
const navigate = useNavigate();
return (
<Routes>
<Route path="/u/:username" element={<AuthenticatedPageRoute><ProfilePage navigate={navigate} /></AuthenticatedPageRoute>} />
<Route path="/notfound" element={<PageWrap><NotFoundPage /></PageWrap>} />
<Route path="*" element={<PageWrap><NotFoundPage /></PageWrap>} />
</Routes>
);
};
export default AppRoutes;