Compare commits

...

197 Commits

Author SHA1 Message Date
Adolfo R. Brandes
2337a7105f 1.0.0-alpha.6 2026-03-04 10:58:29 -03:00
Adolfo R. Brandes
b9f2c5da43 feat!: compile to JS before publishing
Configure the package to compile TypeScript and copy SCSS files to dist/
before publishing, rather than publishing raw source files. This allows
us to use tsc-alias for @src imports.

Also use a more modern export map to decouple the internal file
structure from the package's API, and add a build step to CI.

BREAKING CHANGE: Consuming projects may need to update their imports or
SASS @use lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 16:02:42 -03:00
Javier Ontiveros
1a0a6e3179 feat: added code spliting on main module (#1627) 2026-02-12 16:15:08 -03:00
Adolfo R. Brandes
92208a0a7c 1.0.0-alpha.5 2026-02-09 20:21:28 -03:00
Adolfo R. Brandes
45535ee055 build: Add minimum node version warning
An issue was found when using Node version 24.9 with the latest
package-lock (see #123), one not reproducible with versions 24.12 and
above.  Add a warning that will be shown when running `npm ci`.
2026-01-15 09:49:57 -03:00
Adolfo R. Brandes
e53c4997bb fix: missing styles
The shell's SCSS must be explicitly loaded by site.config.dev.tsx.
2026-01-15 09:49:57 -03:00
Adolfo R. Brandes
f311539e12 fix: CI
App repos are no longer built.
2026-01-15 09:49:57 -03:00
Adolfo R. Brandes
c1070930bf fix: bump frontend-base
Bump frontend-base so we stop failing linting due to the nullish
coalescing rule we can't follow.
2026-01-15 09:49:57 -03:00
Adolfo R. Brandes
dad2887eed fix: linting errors 2026-01-15 09:49:57 -03:00
Adolfo R. Brandes
4f79099eca build: Upgrade to Node 24 2026-01-15 09:49:57 -03:00
Adolfo R. Brandes
49f42a8857 feat!: add design tokens support
BREAKING CHANGE: Pre-design-tokens theming is no longer supported.
2026-01-15 09:49:57 -03:00
Adolfo R. Brandes
2d6b401312 1.0.0-alpha.4 2025-08-20 13:12:29 -03:00
Adolfo R. Brandes
c602136798 chore: bump frontend-base and regenerate package-lock 2025-08-20 13:12:08 -03:00
Adolfo R. Brandes
9a48fe323b fix: work around inotify handle starvation
Bump frontend-base to avoid the inotify handle resource starvation.
2025-07-24 11:59:18 -03:00
Adolfo R. Brandes
967c52bde9 1.0.0-alpha.3 2025-06-29 13:20:08 +02:00
Adolfo R. Brandes
3252b593fd fix: bump frontend-base
Bump frontend-base to alpha.4 to fix a bug with the route role
redirection mechanism.
2025-06-29 13:19:33 +02:00
Adolfo R. Brandes
c98b9a1408 1.0.0-alpha.2 2025-06-29 13:11:02 +02:00
Adolfo R. Brandes
b6c659ccb8 feat: redirect to route role on successful login
Now we have a way to discover app URLs dynamically; do so for the
(default) redirect on login.
2025-06-29 13:09:17 +02:00
Adolfo R. Brandes
7efa279a29 1.0.0-alpha.1 2025-06-28 22:16:19 +02:00
Adolfo R. Brandes
f83f24af89 chore: bump frontend-base 2025-06-28 22:16:07 +02:00
Adolfo R. Brandes
b8116485b0 v1.0.0-alpha.0 2025-06-28 19:31:31 +02:00
Adolfo R. Brandes
762ff75fc4 Merge pull request #1515 from arbrandes/frontend-base-fixes
feat: Prepare for publication to NPM
2025-06-28 14:28:54 -03:00
Adolfo R. Brandes
095b156b95 chore: bump frontend-base 2025-06-28 19:27:26 +02:00
Adolfo R. Brandes
033e0fd7c5 feat: handle authentication roles 2025-06-28 19:18:34 +02:00
Adolfo R. Brandes
1ecdb0b6af chore: gitignore npm pack artifacts 2025-06-26 23:05:50 -03:00
Adolfo R. Brandes
18951cc4d0 chore: clean up npmignore 2025-06-26 23:05:50 -03:00
Adolfo R. Brandes
4dd5ddcc8b refactor: use appId from constants 2025-06-26 23:05:50 -03:00
Adolfo R. Brandes
6acbf64a71 chore: prepare for publication
Update package.json for publication as a "buildless" library.

(Also upgrade openedx-atlas.)
2025-06-26 19:52:56 -03:00
Adolfo R. Brandes
aea12a6a37 fix: remove catch-all route
Apps should avoid having a catch-all route, instead relying on the shell
to provide it.
2025-06-26 19:46:12 -03:00
Adolfo R. Brandes
3d778807f1 fix: update index.html
The only purpose of the included index.html is to serve the dev
environment, so modify it to make that clear.
2025-06-26 19:28:02 -03:00
Adolfo R. Brandes
014a990c22 docs: remove reference to devstack 2025-06-26 19:27:40 -03:00
Adolfo R. Brandes
7c8051a440 test: fix a couple of tests 2025-06-26 19:27:23 -03:00
Adolfo R. Brandes
8f8531a242 refactor: migrate to frontend-base
BREAKING CHANGE: refactors the MFE for frontend-base.
2025-06-24 15:30:07 -03:00
renovate[bot]
319c48f1c8 fix(deps): update dependency @openedx/paragon to v22.20.1 (#1496)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-12 17:38:03 +00:00
renovate[bot]
fbd73bfbfe chore(deps): update dependency jest to v30 (#1495)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-10 05:28:53 +00:00
renovate[bot]
27a63cf406 fix(deps): update dependency @edx/frontend-platform to v8.4.0 (#1494)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-09 16:33:27 +00:00
renovate[bot]
7ea351f6a0 fix(deps): update dependency core-js to v3.43.0 (#1493)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-09 07:34:11 +00:00
renovate[bot]
61e8c254d7 fix(deps): update dependency @edx/frontend-platform to v8.3.9 (#1492)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-06 19:27:33 +00:00
renovate[bot]
3a08e790c3 fix(deps): update dependency @openedx/paragon to v22.20.0 (#1491)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-04 18:02:08 +00:00
renovate[bot]
b4c5171886 fix(deps): update dependency @openedx/paragon to v22.18.2 (#1490)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-03 20:32:20 +00:00
renovate[bot]
7b83c416f8 fix(deps): update dependency @edx/frontend-platform to v8.3.8 (#1489)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-30 21:59:07 +00:00
renovate[bot]
a3c261bb13 fix(deps): update dependency @openedx/paragon to v22.18.1 (#1488)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-22 18:12:22 +00:00
renovate[bot]
98d03aa29f fix(deps): update dependency @openedx/paragon to v22.18.0 (#1487)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-21 22:11:58 +00:00
renovate[bot]
f5d5e2fd02 fix(deps): update react-router monorepo to v6.30.1 (#1486)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-20 20:32:18 +00:00
renovate[bot]
490bf27ed1 fix(deps): update dependency @edx/frontend-platform to v8.3.7 (#1484)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 13:30:11 +00:00
renovate[bot]
780acac2fd fix(deps): update dependency @edx/frontend-platform to v8.3.6 (#1482)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 11:17:03 +00:00
renovate[bot]
2ea763701d fix(deps): update dependency @edx/frontend-platform to v8.3.5 (#1481)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 11:51:58 +00:00
renovate[bot]
e2d9ba5857 chore(deps): update dependency babel-plugin-formatjs to v10.5.38 (#1480)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 07:15:18 +00:00
renovate[bot]
747d656f0a fix(deps): update dependency core-js to v3.42.0 (#1479)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 19:33:32 +00:00
renovate[bot]
8638ed5cf4 fix(deps): update dependency algoliasearch-helper to v3.25.0 (#1478)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 15:06:11 +00:00
renovate[bot]
ca2e7f554a chore(deps): update dependency @openedx/frontend-build to v14.6.0 (#1477)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 23:54:00 +00:00
Adolfo R. Brandes
0e94124d74 Merge pull request #1470 from regisb/regisb/no-husky
chore: remove husky 🪓🐶
2025-04-14 14:12:48 -03:00
Régis Behmo
af7edd8a3f chore: remove husky 🪓🐶
We remove husky, which is triggering pre-push git hooks, including
running "npm lint". This is causing failures when building Docker
images, because "npm clean-install --omit=dev" automatically triggers "npm
prepare", which attemps to run "husky". But husky is not listed in the
build dependencies, only in devDependencies. As a consequence, package
installation is failing with the following error:

        14.13 > @edx/frontend-app-ora-grading@0.0.1 prepare
        14.13 > husky install
        14.13
        14.15 sh: 1: husky: not found

Similar to: https://github.com/openedx/frontend-app-learning/pull/1622
2025-04-14 18:53:56 +02:00
renovate[bot]
9323f119c8 chore(deps): update dependency @openedx/frontend-build to v14.5.0 (#1474)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-11 18:08:35 +00:00
Brian Smith
38a1924c6a feat: upgrade to react 18 (#1466) 2025-04-04 10:17:53 -04:00
renovate[bot]
2d7303009f fix(deps): update dependency @edx/frontend-platform to v8.3.4 (#1471)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-02 18:46:51 +00:00
Brian Smith
dfcb94a831 fix: properly set background color for floating labels (#1468) 2025-04-01 12:51:38 -04:00
renovate[bot]
520dd6ed6b chore(deps): update dependency @openedx/frontend-build to v14.4.1 (#1464)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-28 14:49:39 +00:00
renovate[bot]
1b32dbfa19 fix(deps): update dependency @openedx/paragon to v22.16.2 (#1462)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-26 12:28:50 +00:00
renovate[bot]
f7d9bdb5b5 chore(deps): update dependency babel-plugin-formatjs to v10.5.37 (#1461)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-26 06:50:31 +00:00
sarina
063ec80cde docs: Add instructions on using Tutor for development 2025-03-25 14:40:55 -03:00
sarina
3cbb134c3a docs: Update migrated edx.rtd links to docs.openedx.org 2025-03-25 14:40:55 -03:00
Brian Smith
059a60d1c8 chore(deps): update @openedx dependencies to versions that support React 18 (#1458) 2025-03-25 12:22:43 -04:00
renovate[bot]
c88d701271 fix(deps): update dependency @openedx/paragon to v22.16.1 (#1460)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 22:21:52 +00:00
renovate[bot]
33b98b356b chore(deps): update dependency @openedx/frontend-build to v14.3.3 (#1459)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 20:18:14 +00:00
renovate[bot]
1f81699af4 fix(deps): update dependency algoliasearch-helper to v3.24.3 (#1457)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 13:55:06 +00:00
renovate[bot]
13aa77fc70 fix(deps): update dependency @edx/frontend-platform to v8.3.3 (#1456)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 07:13:09 +00:00
renovate[bot]
66531831b7 chore(deps): update dependency babel-plugin-formatjs to v10.5.36 (#1455)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 03:42:16 +00:00
renovate[bot]
846d3f0662 fix(deps): update dependency @edx/frontend-platform to v8.3.2 (#1454)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-21 19:54:09 +00:00
renovate[bot]
f78e84ee0a fix(deps): update dependency @edx/frontend-platform to v8.3.1 (#1449)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-07 23:16:01 +00:00
renovate[bot]
2d27da2391 fix(deps): update dependency @openedx/paragon to v22.16.0 (#1446)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-05 18:03:14 +00:00
renovate[bot]
78413be34a chore(deps): update dependency @openedx/frontend-build to v14.3.2 (#1444)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-05 01:30:17 +00:00
renovate[bot]
88866a39c1 fix(deps): update dependency algoliasearch-helper to v3.24.2 (#1442)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-04 16:02:35 +00:00
renovate[bot]
dc9699c033 fix(deps): update dependency @edx/frontend-platform to v8.3.0 (#1440)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-04 02:44:20 +00:00
renovate[bot]
00a0e27062 fix(deps): update dependency core-js to v3.41.0 (#1439)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 03:32:41 +00:00
renovate[bot]
6839afcf3c fix(deps): update react-router monorepo to v6.30.0 (#1435)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-27 18:41:40 +00:00
renovate[bot]
1cd9c58c1a fix(deps): update dependency @openedx/paragon to v22.15.3 (#1432)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-25 22:14:39 +00:00
renovate[bot]
5d481a93c7 fix(deps): update dependency @edx/frontend-platform to v8.2.1 (#1429)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-21 22:56:35 +00:00
renovate[bot]
438d1fcfa7 fix(deps): update dependency @edx/frontend-platform to v8.2.0 (#1428)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-21 03:16:30 +00:00
renovate[bot]
bc912ce139 chore(deps): update dependency @openedx/frontend-build to v14.3.1 (#1427)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-20 23:02:47 +00:00
renovate[bot]
ab1c2d5379 fix(deps): update dependency @openedx/paragon to v22.15.2 (#1426)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-20 15:27:23 +00:00
renovate[bot]
c109f6e771 chore(deps): update dependency babel-plugin-formatjs to v10.5.35 (#1421)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-10 01:03:12 +00:00
renovate[bot]
8976647190 fix(deps): update dependency @openedx/paragon to v22.15.1 (#1420)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-31 21:51:26 +00:00
renovate[bot]
cb051a83ad fix(deps): update dependency @openedx/paragon to v22.15.0 (#1419)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-31 17:40:38 +00:00
renovate[bot]
1b8aec5709 fix(deps): update react-router monorepo to v6.29.0 (#1417)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-30 17:54:09 +00:00
renovate[bot]
9a68e95fcc fix(deps): update dependency algoliasearch-helper to v3.24.1 (#1414)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-28 12:31:35 +00:00
renovate[bot]
c90980afb0 fix(deps): update dependency @openedx/paragon to v22.14.0 (#1413)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-22 22:06:09 +00:00
renovate[bot]
abb8ae5085 fix(deps): update dependency algoliasearch-helper to v3.23.1 (#1412)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-21 18:52:31 +00:00
renovate[bot]
8bb7462098 chore(deps): update dependency babel-plugin-formatjs to v10.5.34 (#1411)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-20 17:48:45 +00:00
renovate[bot]
b4a5397ba1 chore(deps): update dependency babel-plugin-formatjs to v10.5.33 (#1410)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-20 05:32:02 +00:00
Feanil Patel
a43c620dc4 Merge pull request #1406 from salman2013/salman/update-catalog-info-file
Update catalog-info file for release data
2025-01-17 10:42:49 -05:00
salman2013
93d11b8485 chore: Update catalog-info file for release data and remove openedx.yaml 2025-01-17 10:39:31 -05:00
renovate[bot]
68e13d4daf chore(deps): update dependency babel-plugin-formatjs to v10.5.31 (#1409)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-17 09:05:56 +00:00
renovate[bot]
f6617935e3 fix(deps): update react-router monorepo to v6.28.2 (#1408)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-16 18:07:00 +00:00
renovate[bot]
5f4591c046 chore(deps): update dependency @edx/browserslist-config to v1.5.0 (#1407)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-15 16:22:56 +00:00
renovate[bot]
ae52a8cb65 fix(deps): update dependency algoliasearch-helper to v3.23.0 (#1405)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-14 18:38:26 +00:00
renovate[bot]
b8df66ad23 fix(deps): update dependency core-js to v3.40.0 (#1404)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-07 20:46:54 +00:00
renovate[bot]
923776ab96 fix(deps): update dependency @edx/frontend-platform to v8.1.5 (#1403)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-06 12:10:02 +00:00
renovate[bot]
f170f5e3f0 chore(deps): update dependency babel-plugin-formatjs to v10.5.30 (#1402)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 18:14:00 +00:00
renovate[bot]
730875ceb2 fix(deps): update dependency @edx/frontend-platform to v8.1.4 (#1401)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-30 09:15:59 +00:00
renovate[bot]
812350d24a fix(deps): update react-router monorepo to v6.28.1 (#1399)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-20 21:25:00 +00:00
renovate[bot]
6879bacb89 fix(deps): update dependency @openedx/paragon to v22.13.0 (#1398)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-18 17:20:36 +00:00
renovate[bot]
9b2b0f2019 fix(deps): update font awesome to v6.7.2 (#1397)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-16 22:17:55 +00:00
renovate[bot]
87884f2d91 fix(deps): update dependency @openedx/paragon to v22.12.0 (#1395)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-16 01:22:07 +00:00
renovate[bot]
3e20fcae57 fix(deps): update dependency @openedx/paragon to v22.11.2 (#1391)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-10 01:57:22 +00:00
renovate[bot]
173896811d chore(deps): update dependency @edx/browserslist-config to v1.4.0 (#1394)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-09 23:47:31 +00:00
renovate[bot]
7af4a08bd9 fix(deps): update dependency algoliasearch-helper to v3.22.6 (#1393)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-09 18:57:08 +00:00
renovate[bot]
6c12b3b034 fix(deps): update dependency @edx/frontend-platform to v8.1.3 (#1392)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-09 15:21:14 +00:00
renovate[bot]
5304085cd8 chore(deps): update dependency babel-plugin-formatjs to v10.5.29 (#1389)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-09 09:02:19 +00:00
renovate[bot]
3cd9ae130c chore(deps): update dependency @openedx/frontend-build to v14.2.2 (#1390)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-09 05:41:46 +00:00
renovate[bot]
28ad2c2cf6 chore(deps): update dependency @openedx/frontend-build to v14.2.1 (#1388)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-09 00:46:21 +00:00
renovate[bot]
3e889df109 chore(deps): update dependency @edx/browserslist-config to v1.3.0 (#1386)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-06 02:36:06 +00:00
Eemaan Amir
52c6efc34d Merge pull request #1357 from openedx/renovate/universal-cookie-7.x
fix(deps): update dependency universal-cookie to v7
2024-11-27 17:14:02 +05:00
renovate[bot]
584a84a99c fix(deps): update dependency universal-cookie to v7 2024-11-27 09:07:41 +00:00
Eemaan Amir
7e4ab1c74c Merge pull request #1356 from openedx/renovate/reselect-5.x
fix(deps): update dependency reselect to v5
2024-11-27 14:07:16 +05:00
renovate[bot]
13d89cb3a0 fix(deps): update dependency reselect to v5 2024-11-22 06:55:30 +00:00
Eemaan Amir
5a1e2e6c97 Merge pull request #1147 from openedx/renovate/actions-checkout-4.x
chore(deps): update actions/checkout action to v4
2024-11-22 11:54:42 +05:00
renovate[bot]
6f1cf29a60 chore(deps): update actions/checkout action to v4 2024-11-21 10:15:17 +00:00
renovate[bot]
159f1ae30e fix(deps): update font awesome to v6.7.1 (#1374)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-21 08:56:48 +00:00
Eemaan Amir
e2e626552f Merge pull request #1314 from openedx/repo-tools/salman/add-dependabot-file-e2a206c
chore: enable github action auto update in dependabot.yml
2024-11-21 13:53:25 +05:00
edX requirements bot
308d7c62e4 chore: enable github action auto update in dependabot.yml 2024-11-19 19:18:17 +05:00
Eemaan Amir
0bc78da55d Merge pull request #1367 from openedx/renovate/codecov-codecov-action-5.x
chore(deps): update codecov/codecov-action action to v5
2024-11-19 18:28:46 +05:00
renovate[bot]
6527caea54 chore(deps): update codecov/codecov-action action to v5 2024-11-19 10:57:48 +00:00
Eemaan Amir
a52912e35b Merge pull request #1149 from openedx/renovate/husky-9.x
chore(deps): update dependency husky to v9
2024-11-19 15:57:32 +05:00
renovate[bot]
6479382b90 chore(deps): update dependency husky to v9 2024-11-19 00:06:24 +00:00
renovate[bot]
4ce36bb12c fix(deps): update font awesome to v6.7.0 (#1371)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-18 23:17:51 +00:00
renovate[bot]
4cc7723984 chore(deps): update dependency @openedx/frontend-build to v14.2.0 (#1370)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-18 20:24:00 +00:00
renovate[bot]
3c3d359d4e chore(deps): update dependency babel-plugin-formatjs to v10.5.26 (#1369)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-18 09:44:26 +00:00
renovate[bot]
cccbf3a9d1 chore(deps): update dependency babel-plugin-formatjs to v10.5.25 (#1368)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-18 06:28:06 +00:00
renovate[bot]
4a3fd2ee8e fix(deps): update dependency @openedx/paragon to v22.10.0 (#1365)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-13 02:40:50 +00:00
Eemaan Amir
48d7cb386a Merge pull request #1362 from openedx/renovate/algolia-instantsearch-monorepo
fix(deps): update dependency algoliasearch-helper to v3.22.5
2024-11-11 18:52:42 +05:00
renovate[bot]
bdf9cab869 fix(deps): update dependency algoliasearch-helper to v3.22.5 2024-11-11 12:41:03 +00:00
Eemaan Amir
be02dabf40 Merge pull request #1361 from openedx/revert-1313-renovate/algolia-instantsearch-monorepo
Revert "fix(deps): update dependency algoliasearch-helper to v3.22.5"
2024-11-11 17:39:58 +05:00
Eemaan Amir
c535fb9d24 Revert "fix(deps): update dependency algoliasearch-helper to v3.22.5"
This reverts commit 8ab8d09b97.
2024-11-11 17:32:28 +05:00
renovate[bot]
8ab8d09b97 fix(deps): update dependency algoliasearch-helper to v3.22.5 2024-11-11 16:45:38 +05:00
renovate[bot]
286c70d50f fix(deps): update react-router monorepo to v6.28.0 (#1355)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-08 12:00:01 +00:00
renovate[bot]
8939e5b91f chore(deps): update dependency babel-plugin-formatjs to v10.5.24 2024-11-06 10:42:36 +00:00
renovate[bot]
bc9f7b3bce fix(deps): update react-router monorepo to v6.27.0 2024-11-01 16:32:19 +00:00
renovate[bot]
fd0bcb9e5f fix(deps): update dependency core-js to v3.39.0 2024-11-01 13:58:08 +00:00
renovate[bot]
98e0167ef1 fix(deps): update dependency @openedx/paragon to v22.9.0 2024-11-01 11:23:30 +00:00
renovate[bot]
8091085f45 chore(deps): update dependency eslint-plugin-import to v2.31.0 2024-11-01 06:51:18 +00:00
renovate[bot]
cd5abd1d9c fix(deps): update dependency redux-mock-store to v1.5.5 2024-11-01 03:09:49 +00:00
renovate[bot]
2a88f435b9 fix(deps): update dependency @edx/frontend-platform to v8.1.2 2024-11-01 00:54:11 +00:00
renovate[bot]
fe1e9c5629 chore(deps): update dependency @openedx/frontend-build to v14.1.5 2024-10-31 21:45:56 +00:00
renovate[bot]
0e363ca724 chore(deps): update dependency babel-plugin-formatjs to v10.5.22 2024-10-31 19:54:28 +00:00
Bilal Qamar
c874638bd1 test: Remove support for Node 18 (#1312)
Co-authored-by: Brian Smith <112954497+brian-smith-tcril@users.noreply.github.com>
2024-10-31 15:51:22 -04:00
Brian Smith
e5c3b1ed41 Revert "fix(deps): update dependency @testing-library/react to v16" (#1339)
This reverts commit 8a27b8cc37.
2024-10-31 15:25:11 -04:00
renovate[bot]
8a27b8cc37 fix(deps): update dependency @testing-library/react to v16 2024-10-31 15:09:42 -04:00
renovate[bot]
046fbeab01 fix(deps): update dependency react-loading-skeleton to v3.5.0 2024-09-23 01:48:16 +00:00
renovate[bot]
27ea509989 fix(deps): update dependency @openedx/paragon to v22.8.1 2024-09-20 21:22:27 +00:00
renovate[bot]
27f0508e6e chore(deps): update dependency eslint-plugin-import to v2.30.0 2024-09-20 19:10:37 +00:00
renovate[bot]
c53fedf7a1 chore(deps): update dependency @openedx/frontend-build to v14.1.4 2024-09-20 17:06:05 +00:00
renovate[bot]
0f1a5e9aef fix(deps): update react-router monorepo to v6.26.2 2024-09-20 14:37:28 +00:00
Feanil Patel
6cb4b799b7 Merge pull request #1316 from openedx/feanil/ubuntu_upgrade
build: Switch to ubuntu-latest for builds
2024-09-20 10:32:28 -04:00
Feanil Patel
439b9161b5 build: Switch to ubuntu-latest for builds
This code does not have any dependencies that are specific to any specific
version of ubuntu.  So instead of testing on a specific version and then needing
to do work to keep the versions up-to-date, we switch to the ubuntu-latest
target which should be sufficient for testing purposes.

This work is being done as a part of https://github.com/openedx/platform-roadmap/issues/377

closes https://github.com/openedx/frontend-app-authn/issues/1299
2024-09-20 10:25:36 -04:00
sundasnoreen12
6ffa45f0c1 Merge pull request #1317 from openedx/sundas/INF-1551
docs: updated catalog-info file for authn MFE
2024-09-10 16:50:23 +05:00
sundasnoreen12
a03ba3e3b3 docs: updated catalog-info file for authn MFE 2024-09-10 13:36:13 +03:00
renovate[bot]
e2a206caa5 fix(deps): update dependency @edx/openedx-atlas to v0.6.2 2024-09-02 10:22:01 +00:00
Bilal Qamar
3a963da819 build: Upgrade to Node 20 (#1295)
* feat: updated node to v20

* refactor: updated package-lock

* refactor: updated package-lock & lockfile version check workflow

* refactor: updated package-lock along with ci & lockfile version check workflows

* refactor: updated lockfile version workflow
2024-09-02 15:18:31 +05:00
Blue
4a65f0a84c fix: change the totalRegisterationTime to snake case (#1301)
Description:
Convert the totalRegistrationTime to snake case
VAN-1816

Co-authored-by: Ahtesham Quraish <ahtesham.quraish@192.168.1.4>
2024-08-28 15:08:30 +05:00
renovate[bot]
9688bd3699 fix(deps): update react-router monorepo to v6.26.1 2024-08-23 06:35:23 +00:00
renovate[bot]
c123815a55 fix(deps): update dependency core-js to v3.38.1 2024-08-23 05:27:21 +00:00
renovate[bot]
182e669593 chore(deps): update dependency @openedx/frontend-build to v14.1.0 2024-08-23 01:23:22 +00:00
renovate[bot]
65533b8d58 fix(deps): update dependency algoliasearch-helper to v3.22.4 2024-08-22 22:43:06 +00:00
renovate[bot]
45185dba70 fix(deps): update dependency @edx/frontend-platform to v8.1.1 2024-08-22 18:38:57 +00:00
Bilal Qamar
444c4b4434 test: Add Node 20 to CI matrix (#1303) 2024-08-22 14:34:50 -04:00
renovate[bot]
d629d66bf2 fix(deps): update react-router monorepo to v6.25.1 2024-07-22 00:49:21 +00:00
renovate[bot]
9d46d68150 fix(deps): update font awesome to v6.6.0 2024-07-19 23:07:12 +00:00
renovate[bot]
a4ed6a362e fix(deps): update dependency @openedx/paragon to v22.7.0 2024-07-19 18:42:43 +00:00
renovate[bot]
a1a0d3cd96 fix(deps): update dependency algoliasearch-helper to v3.22.3 2024-07-19 15:43:53 +00:00
renovate[bot]
950c401e88 fix(deps): update dependency redux to v4.2.1 2024-07-19 12:37:44 -03:00
renovate[bot]
ce056c9ad2 fix(deps): update react-router monorepo to v6.24.1 2024-07-09 09:47:38 +00:00
renovate[bot]
3bd6e454d0 fix(deps): update dependency @edx/frontend-platform to v8.1.0 2024-07-09 06:59:28 +00:00
renovate[bot]
f52129a11e chore(deps): update dependency iframe-resizer to v4.4.4 2024-07-09 03:58:26 +00:00
renovate[bot]
ea01050163 fix(deps): update dependency algoliasearch-helper to v3.22.2 2024-07-09 00:27:00 +00:00
renovate[bot]
c1ec9b6e99 fix(deps): update dependency algoliasearch-helper to v3.22.1 2024-07-01 18:59:29 +00:00
renovate[bot]
2c509b00ac fix(deps): update dependency @openedx/paragon to v22.6.1 2024-07-01 17:39:58 +00:00
renovate[bot]
ef358fe741 fix(deps): update dependency @edx/frontend-platform to v8.0.4 2024-07-01 12:56:55 +00:00
renovate[bot]
56e0520d9c chore(deps): update dependency @openedx/frontend-build to v14.0.10 2024-07-01 11:26:22 +00:00
Bilal Qamar
1f7b7f5c41 chore: major version upgrades for frontend-platform & frontend-build (#1251) 2024-07-01 13:22:45 +02:00
renovate[bot]
471fa75155 fix(deps): update react-router monorepo to v6.23.1 2024-06-18 22:48:40 +00:00
renovate[bot]
c89d16e529 fix(deps): update dependency core-js to v3.37.1 2024-06-18 20:06:43 +00:00
renovate[bot]
fc02ab820a fix(deps): update dependency algoliasearch-helper to v3.22.0 2024-06-18 17:06:47 +00:00
renovate[bot]
ac23cdcc7a fix(deps): update dependency algoliasearch-helper to v3.21.0 2024-06-18 12:06:40 +00:00
renovate[bot]
02c4c5be29 fix(deps): update dependency @openedx/paragon to v22.6.0 2024-06-18 09:11:03 +00:00
renovate[bot]
3bd7d61e3a fix(deps): update dependency form-urlencoded to v6.1.5 2024-06-18 07:26:49 +00:00
renovate[bot]
32ebc69c0e fix(deps): update dependency @fortawesome/react-fontawesome to v0.2.2 2024-06-18 03:19:51 +00:00
renovate[bot]
c98c3b16c5 fix(deps): update dependency @edx/openedx-atlas to v0.6.1 2024-06-18 02:42:13 +00:00
renovate[bot]
287fe3adfe fix(deps): update dependency @edx/frontend-platform to v7.1.4 2024-06-17 22:30:03 +00:00
renovate[bot]
d4e7b7b371 chore(deps): update dependency iframe-resizer to v4.3.11 2024-06-17 19:04:24 +00:00
renovate[bot]
ad78f068e0 chore(deps): update dependency babel-plugin-formatjs to v10.5.16 2024-06-17 15:05:32 +00:00
Adolfo R. Brandes
d156de2e66 build: Update codecov and use token
Update codecov to the latest version and start using the org-wide token for uploads.

See https://github.com/openedx/wg-frontend/issues/179
2024-06-17 12:02:25 -03:00
Attiya Ishaque
99bca1bd9b fix: frontend validation on email field (#1249) 2024-06-12 14:15:56 +05:00
Blue
8efb22595c fix: add new entry for another US label (#1244)
Add new entry for for another US label which is United States
2024-05-03 10:27:32 +05:00
Syed Sajjad Hussain Shah
73e8913f90 feat: remove username from the registration from (#1201) (#1241)
Co-authored-by: Attiya Ishaque <atiya.ishaq@arbisoft.com>
2024-05-02 08:55:56 +05:00
Stanislav Lunyachek
3ddaf795f2 feat: Hide preloaders for third party auth providers if they are disabled 2024-04-19 10:55:48 +05:00
renovate[bot]
a18df02d37 fix(deps): update dependency algoliasearch-helper to v3.17.0 2024-04-11 09:20:07 +00:00
196 changed files with 12540 additions and 15799 deletions

42
.env
View File

@@ -1,42 +0,0 @@
NODE_ENV='production'
ACCESS_TOKEN_COOKIE_NAME=null
BASE_URL=null
CREDENTIALS_BASE_URL=null
CSRF_TOKEN_API_PATH=null
ECOMMERCE_BASE_URL=null
LANGUAGE_PREFERENCE_COOKIE_NAME=null
LMS_BASE_URL=null
LOGIN_URL=null
LOGOUT_URL=null
MARKETING_SITE_BASE_URL=null
ORDER_HISTORY_URL=null
REFRESH_ACCESS_TOKEN_ENDPOINT=null
SEGMENT_KEY=''
SITE_NAME=null
INFO_EMAIL=''
# ***** Cookies *****
USER_RETENTION_COOKIE_NAME=null
# ***** Links *****
LOGIN_ISSUE_SUPPORT_LINK=''
AUTHN_PROGRESSIVE_PROFILING_SUPPORT_LINK=null
POST_REGISTRATION_REDIRECT_URL=''
SEARCH_CATALOG_URL=''
# ***** Features flags *****
DISABLE_ENTERPRISE_LOGIN=''
ENABLE_DYNAMIC_REGISTRATION_FIELDS=''
ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN=''
ENABLE_POST_REGISTRATION_RECOMMENDATIONS=''
MARKETING_EMAILS_OPT_IN=''
SHOW_CONFIGURABLE_EDX_FIELDS=''
ENABLE_IMAGE_LAYOUT=''
# ***** Zendesk related keys *****
ZENDESK_KEY=''
ZENDESK_LOGO_URL=''
# ***** Base Container Images *****
BANNER_IMAGE_LARGE=''
BANNER_IMAGE_MEDIUM=''
BANNER_IMAGE_SMALL=''
BANNER_IMAGE_EXTRA_SMALL=''
# ***** Miscellaneous *****
APP_ID=''
MFE_CONFIG_API_URL=''

View File

@@ -1,4 +0,0 @@
# Copy these to the .env.private to enable edX specific functionality on local system
ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN='true'
MARKETING_EMAILS_OPT_IN='true'
SHOW_CONFIGURABLE_EDX_FIELDS='true'

View File

@@ -1,20 +0,0 @@
ACCESS_TOKEN_COOKIE_NAME='edx-jwt-cookie-header-payload'
BASE_URL='http://localhost:1995'
CREDENTIALS_BASE_URL='http://localhost:18150'
CSRF_TOKEN_API_PATH='/csrf/api/v1/token'
ECOMMERCE_BASE_URL='http://localhost:18130'
LANGUAGE_PREFERENCE_COOKIE_NAME='openedx-language-preference'
LMS_BASE_URL='http://localhost:18000'
LOGIN_URL='http://localhost:18000/login'
LOGOUT_URL='http://localhost:18000/logout'
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
MARKETING_SITE_BASE_URL='http://localhost:18000'
ORDER_HISTORY_URL='http://localhost:1996/orders'
REFRESH_ACCESS_TOKEN_ENDPOINT='http://localhost:18000/login_refresh'
SEGMENT_KEY=''
SITE_NAME='Your Platform Name Here'
APP_ID=''
MFE_CONFIG_API_URL=''

View File

@@ -1,6 +0,0 @@
coverage/*
dist/
docs
node_modules/
__mocks__/
__snapshots__/

View File

@@ -1,52 +0,0 @@
// eslint-disable-next-line import/no-extraneous-dependencies
const { createConfig } = require('@openedx/frontend-build');
module.exports = createConfig('eslint', {
rules: {
// Temporarily update the 'indent', 'template-curly-spacing' and
// 'no-multiple-empty-lines' rules since they are causing eslint
// to fail for no apparent reason since upgrading
// @openedx/frontend-build from v3 to v5:
// - TypeError: Cannot read property 'range' of null
indent: [
'error',
2,
{ ignoredNodes: ['TemplateLiteral', 'SwitchCase'] },
],
'template-curly-spacing': 'off',
'jsx-a11y/label-has-associated-control': ['error', {
labelComponents: [],
labelAttributes: [],
controlComponents: [],
assert: 'htmlFor',
depth: 25,
}],
'sort-imports': ['error', { ignoreCase: true, ignoreDeclarationSort: true }],
'import/order': [
'error',
{
groups: [
'builtin',
'external',
'internal',
['sibling', 'parent'],
'index',
],
pathGroups: [
{
pattern: '@(react|react-dom|react-redux)',
group: 'external',
position: 'before',
},
],
pathGroupsExcludedImportTypes: ['react'],
'newlines-between': 'always',
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
},
],
'function-paren-newline': 'off',
},
});

1
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1 @@
* @openedx/2U-infinity

7
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,7 @@
version: 2
updates:
# Adding new check for github-actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

View File

@@ -25,5 +25,5 @@ Include a link to the sandbox for design changes or screenshot for before and af
#### Post-merge Checklist
* [ ] Deploy the changes to prod after verifying on stage or ask **@openedx/2u-vanguards** to do it.
* [ ] Deploy the changes to prod after verifying on stage or ask **@openedx/2u-infinity** to do it.
* [ ] 🎉 🙌 Celebrate! Thanks for your contribution.

View File

@@ -10,7 +10,7 @@ on:
jobs:
autoupdate:
name: autoupdate
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- uses: docker://chinthakagodawita/autoupdate-action:v1
env:

View File

@@ -10,17 +10,15 @@ on:
jobs:
tests:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Nodejs Env
run: echo "NODE_VER=`cat .nvmrc`" >> $GITHUB_ENV
uses: actions/checkout@v4
- name: Setup Nodejs
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VER }}
node-version-file: '.nvmrc'
- name: Install Dependencies
run: npm ci
@@ -41,4 +39,7 @@ jobs:
run: npm run build
- name: Run Code Coverage
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true

View File

@@ -10,4 +10,4 @@ on:
jobs:
version-check:
uses: openedx/.github/.github/workflows/lockfile-check.yml@master
uses: openedx/.github/.github/workflows/lockfileversion-check-v3.yml@master

16
.gitignore vendored
View File

@@ -1,21 +1,15 @@
.DS_Store
.eslintcache
.idea
node_modules
npm-debug.log
coverage
module.config.js
.env.private
dist/
/*.tgz
### i18n ###
src/i18n/transifex_input.json
temp/babel-plugin-react-intl
### pyenv ###
.python-version
### Emacs ###
### Editors ###
.DS_Store
*~
/temp
/.vscode
src/i18n/messages

View File

@@ -1,11 +1,6 @@
.eslintignore
.eslintrc.json
.gitignore
docker-compose.yml
Dockerfile
Makefile
npm-debug.log
coverage
__mocks__
node_modules
public
*.test.js
*.test.jsx
*.test.ts
*.test.tsx

2
.nvmrc
View File

@@ -1 +1 @@
18
24

View File

@@ -1,2 +1,2 @@
# The following users are the owners of all frontend-app-authn files
* @openedx/2u-vanguards
* @openedx/2u-infinity

View File

@@ -13,6 +13,19 @@ precommit:
requirements:
npm ci
clean:
rm -rf dist
build: clean
tsc --project tsconfig.build.json
tsc-alias -p tsconfig.build.json
find src -type f -name '*.scss' -exec sh -c '\
for f in "$$@"; do \
d="dist/$${f#src/}"; \
mkdir -p "$$(dirname "$$d")"; \
cp "$$f" "$$d"; \
done' sh {} +
i18n.extract:
# Pulling display strings from .jsx files into .json files...
rm -rf $(transifex_temp)

View File

@@ -29,29 +29,15 @@ Getting Started
Installation
============
This MFE is bundled with `Devstack <https://github.com/openedx/devstack>`_, see the `Getting Started <https://github.com/openedx/devstack#getting-started>`_ section for setup instructions.
`Tutor`_ is currently recommended as a development environment for your new MFE. Please refer to the `relevant tutor-mfe documentation`_ to get started using it.
1. Install Devstack using the `Getting Started <https://github.com/openedx/devstack#getting-started>`_ instructions.
2. Start up LMS, if it's not already started.
4. Within this project (frontend-app-authn), install requirements and start the development server:
.. code-block::
npm install
npm start # The server will run on port 1999
5. Once the dev server is up, visit http://localhost:1999 to access the MFE
.. image:: ./docs/images/frontend-app-authn-localhost-preview.png
**Note:** Follow `Enable social auth locally <docs/how_tos/enable_social_auth.rst>`_ for enabling Social Sign-on Buttons (SSO) locally
.. _Tutor: https://github.com/overhangio/tutor
.. _relevant tutor-mfe documentation: https://github.com/overhangio/tutor-mfe?tab=readme-ov-file#mfe-development
Environment Variables/Setup Notes
=================================
This MFE is configured via environment variables supplied at build time. All micro-frontends have a shared set of required environment variables, as documented in the Open edX Developer Guide under `Required Environment Variables <https://edx.readthedocs.io/projects/edx-developer-docs/en/latest/developers_guide/micro_frontends_in_open_edx.html#required-environment-variables>`__.
This MFE is configured via environment variables supplied at build time. All micro-frontends have a shared set of required environment variables, as documented in the Open edX Developer Guide under `Required Environment Variables <https://github.com/overhangio/tutor-mfe?tab=readme-ov-file#mfe-development>`__.
The authentication micro-frontend also requires the following additional variable:
@@ -137,18 +123,14 @@ Furthermore, there are several edX-specific environment variables that enable in
- Enables support for opting in marketing emails that helps us getting user consent for sending marketing emails.
- ``true`` | ``''`` (empty strings are falsy)
* - ``SHOW_CONFIGURABLE_EDX_FIELDS``
- For edX, country and honor code fields are required by default. This flag enables edX specific required fields.
- ``true`` | ``''`` (empty strings are falsy)
For more information see the document: `Micro-frontend applications in Open
edX <https://edx.readthedocs.io/projects/edx-developer-docs/en/latest/developers_guide/micro_frontends_in_open_edx.html#required-environment-variables>`__.
edX <https://github.com/overhangio/tutor-mfe?tab=readme-ov-file#mfe-development>`__.
How To Contribute
=================
Contributions are very welcome, and strongly encouraged! We've
put together `some documentation that describes our contribution process <https://edx.readthedocs.org/projects/edx-developer-guide/en/latest/process/index.html>`_.
put together `some documentation that describes our contribution process <https://docs.openedx.org/en/latest/developers/references/developer_guide/process/index.html>`_.
Even though they were written with edx-platform in mind, the guidelines should be followed for Open edX code in general.
@@ -187,7 +169,7 @@ All community members are expected to follow the `Open edX Code of Conduct <http
People
======
The assigned maintainers for this component and other project details may be
found in `Backstage <https://backstage.openedx.org/catalog/default/group/2u-vanguards>`_. Backstage pulls this data from the ``catalog-info.yaml``
found in `Backstage <https://backstage.openedx.org/catalog/default/group/2u-infinity>`_. Backstage pulls this data from the ``catalog-info.yaml``
file in this repo.
Reporting Security Issues
@@ -219,4 +201,4 @@ Please see `LICENSE <https://github.com/openedx/frontend-app-authn/blob/master/L
:target: https://github.com/openedx/edx-developer-docs/actions/workflows/ci.yml
:alt: Continuous Integration
.. |semantic-release| image:: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg
:target: https://github.com/semantic-release/semantic-release
:target: https://github.com/semantic-release/semantic-release

5
app.d.ts vendored Normal file
View File

@@ -0,0 +1,5 @@
/// <reference types="@openedx/frontend-base" />
declare module 'site.config' {
export default SiteConfig;
}

3
babel.config.js Normal file
View File

@@ -0,0 +1,3 @@
const { createConfig } = require('@openedx/frontend-base/tools');
module.exports = createConfig('babel');

View File

@@ -12,7 +12,8 @@ metadata:
icon: 'Article'
annotations:
openedx.org/arch-interest-groups: ""
openedx.org/release: "master"
spec:
owner: group:2u-vanguards
owner: group:2u-infinity
type: 'service'
lifecycle: 'production'

View File

@@ -3,7 +3,7 @@ Enable Social Auth Locally
Please follow the steps below to enable social auth (SSO) locally.
1. Follow `Enabling Third Party Authentication <https://edx.readthedocs.io/projects/edx-installing-configuring-and-running/en/latest/configuration/tpa/index.html>`_ for backend configuration.
1. Follow `Enabling Third Party Authentication <https://docs.openedx.org/en/latest/site_ops/install_configure_run_guide/configuration/tpa/index.html>`_ for backend configuration.
2. Authn has a component for rendering Social Auth providers at frontend which goes through each provider.

22
eslint.config.js Normal file
View File

@@ -0,0 +1,22 @@
// @ts-check
const { createLintConfig } = require('@openedx/frontend-base/tools');
module.exports = createLintConfig(
{
files: [
'src/**/*',
'site.config.*',
],
},
{
ignores: [
'coverage/*',
'dist/*',
'docs/*',
'node_modules/*',
'**/__mocks__/*',
'**/__snapshots__/*',
],
},
);

View File

@@ -1,14 +1,15 @@
const { createConfig } = require('@openedx/frontend-build');
const { createConfig } = require('@openedx/frontend-base/tools');
module.exports = createConfig('jest', {
setupFiles: [
module.exports = createConfig('test', {
setupFilesAfterEnv: [
'<rootDir>/src/setupTest.js',
],
coveragePathIgnorePatterns: [
'src/setupTest.js',
'src/i18n',
'src/index.jsx',
'MainApp.jsx',
],
testEnvironment: 'jsdom',
moduleNameMapper: {
'\\.svg$': '<rootDir>/src/__mocks__/svg.js',
'\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/src/__mocks__/file.js',
},
});

View File

@@ -1,8 +0,0 @@
# This file describes this Open edX repo, as described in OEP-2:
# http://open-edx-proposals.readthedocs.io/en/latest/oeps/oep-0002.html#specification
nick: Authn MFE
oeps: {}
owner: openedx/2u-vanguards
openedx-release:
ref: master

22810
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,28 +1,40 @@
{
"name": "@edx/frontend-app-authn",
"version": "0.1.0",
"description": "Frontend application template",
"name": "@openedx/frontend-app-authn",
"version": "1.0.0-alpha.6",
"description": "Frontend authentication",
"engines": {
"node": "^24.12"
},
"repository": {
"type": "git",
"url": "git+https://github.com/openedx/frontend-app-authn.git"
},
"exports": {
".": "./dist/index.js",
"./app.scss": "./dist/app.scss"
},
"files": [
"/dist"
],
"browserslist": [
"extends @edx/browserslist-config"
],
"sideEffects": [
"*.css",
"*.scss"
],
"scripts": {
"build": "fedx-scripts webpack",
"i18n_extract": "fedx-scripts formatjs extract",
"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"
"build": "make build",
"clean": "make clean",
"dev": "PORT=1999 PUBLIC_PATH=/authn openedx dev",
"i18n_extract": "openedx formatjs extract",
"lint": "openedx lint .",
"lint:fix": "openedx lint --fix .",
"prepack": "npm run build",
"snapshot": "openedx test --updateSnapshot",
"test": "openedx test --coverage --passWithNoTests"
},
"husky": {
"hooks": {
"pre-commit": "npm run lint"
}
},
"author": "edX",
"author": "Open edX",
"license": "AGPL-3.0",
"homepage": "https://github.com/openedx/frontend-app-authn#readme",
"publishConfig": {
@@ -32,54 +44,47 @@
"url": "https://github.com/openedx/frontend-app-authn/issues"
},
"dependencies": {
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
"@edx/frontend-platform": "7.1.3",
"@edx/openedx-atlas": "^0.6.0",
"@fortawesome/fontawesome-svg-core": "6.5.2",
"@fortawesome/free-brands-svg-icons": "6.5.2",
"@fortawesome/free-solid-svg-icons": "6.5.2",
"@fortawesome/react-fontawesome": "0.2.0",
"@openedx/paragon": "^22.1.1",
"@optimizely/react-sdk": "^2.9.1",
"@redux-devtools/extension": "3.3.0",
"@testing-library/react": "^12.1.5",
"@testing-library/react-hooks": "^8.0.1",
"algoliasearch": "^4.14.3",
"algoliasearch-helper": "^3.14.0",
"classnames": "2.5.1",
"core-js": "3.36.1",
"fastest-levenshtein": "1.0.16",
"form-urlencoded": "6.1.4",
"prop-types": "15.8.1",
"query-string": "7.1.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-helmet": "6.1.0",
"react-loading-skeleton": "3.4.0",
"react-redux": "7.2.9",
"react-responsive": "8.2.0",
"react-router": "6.22.3",
"react-router-dom": "6.22.3",
"react-zendesk": "^0.1.13",
"redux": "4.2.0",
"redux-logger": "3.0.6",
"redux-mock-store": "1.5.4",
"redux-saga": "1.3.0",
"redux-thunk": "2.4.2",
"regenerator-runtime": "0.14.1",
"reselect": "4.1.8",
"universal-cookie": "4.0.4"
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.3",
"@edx/openedx-atlas": "^0.7.0",
"@fortawesome/fontawesome-svg-core": "^6.7.2",
"@fortawesome/free-brands-svg-icons": "^6.7.2",
"@fortawesome/free-solid-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "^0.2.2",
"@redux-devtools/extension": "^3.3.0",
"classnames": "^2.5.1",
"fastest-levenshtein": "^1.0.16",
"form-urlencoded": "^6.1.5",
"i18n-iso-countries": "^7.13.0",
"prop-types": "^15.8.1",
"query-string": "^7.1.3",
"react-helmet": "^6.1.0",
"react-loading-skeleton": "^3.5.0",
"react-responsive": "^8.2.0",
"redux-logger": "^3.0.6",
"redux-mock-store": "^1.5.5",
"redux-saga": "^1.3.0",
"redux-thunk": "^2.4.2",
"reselect": "^5.1.1",
"universal-cookie": "^8.0.1"
},
"devDependencies": {
"@edx/browserslist-config": "^1.1.1",
"@edx/reactifex": "1.1.0",
"@openedx/frontend-build": "13.1.4",
"babel-plugin-formatjs": "10.5.14",
"eslint-plugin-import": "2.29.1",
"glob": "7.2.3",
"history": "5.3.0",
"husky": "7.0.4",
"jest": "29.7.0",
"react-test-renderer": "^17.0.2"
"@edx/browserslist-config": "^1.5.0",
"@testing-library/react": "^16.3.0",
"babel-plugin-formatjs": "10.5.38",
"eslint-plugin-import": "2.31.0",
"jest": "^29.7.0",
"react-test-renderer": "^18.3.1",
"ts-jest": "^29.4.0",
"tsc-alias": "^1.8.16"
},
"peerDependencies": {
"@openedx/frontend-base": "^1.0.0-alpha.13",
"@openedx/paragon": "^23",
"react": "^18",
"react-dom": "^18",
"react-redux": "^8",
"react-router": "^6",
"react-router-dom": "^6",
"redux": "^4"
}
}

View File

@@ -1,24 +1,9 @@
<!doctype html>
<html lang="en-us">
<head>
<title><%= (process.env.SITE_NAME && process.env.SITE_NAME != 'null') ? 'Authentication | ' + process.env.SITE_NAME : 'Authentication' %></title>
<title>Authentication Development Site></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="<%=htmlWebpackPlugin.options.FAVICON_URL%>" type="image/x-icon"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.9/iframeResizer.contentWindow.min.js"
integrity="sha512-mdT/HQRzoRP4laVz49Mndx6rcCGA3IhuyhP3gaY0E9sZPkwbtDk9ttQIq9o8qGCf5VvJv1Xsy3k2yTjfUoczqw=="
crossorigin="anonymous"
referrerpolicy="no-referrer">
</script>
<% if (process.env.OPTIMIZELY_URL) { %>
<script
src="<%= process.env.OPTIMIZELY_URL %>"
></script>
<% } else if (process.env.OPTIMIZELY_PROJECT_ID) { %>
<script
src="<%= process.env.MARKETING_SITE_BASE_URL %>/optimizelyjs/<%= process.env.OPTIMIZELY_PROJECT_ID %>.js"
></script>
<% } %>
</head>
<body>
<div id="root"></div>

20
site.config.dev.tsx Normal file
View File

@@ -0,0 +1,20 @@
import { EnvironmentTypes, SiteConfig } from '@openedx/frontend-base';
import { authnApp } from './src';
import './src/app.scss';
const siteConfig: SiteConfig = {
siteId: 'authn-dev',
siteName: 'Authn Dev',
baseUrl: 'http://apps.local.openedx.io:8080',
lmsBaseUrl: 'http://local.openedx.io:8000',
loginUrl: 'http://local.openedx.io:8000/login',
logoutUrl: 'http://local.openedx.io:8000/logout',
environment: EnvironmentTypes.DEVELOPMENT,
basename: '/authn',
apps: [authnApp],
};
export default siteConfig;

50
site.config.test.tsx Normal file
View File

@@ -0,0 +1,50 @@
import { EnvironmentTypes, SiteConfig } from '@openedx/frontend-base';
import { appId } from './src/constants';
const siteConfig: SiteConfig = {
siteId: 'test-site',
siteName: 'Test Site',
baseUrl: 'http://localhost:1996',
lmsBaseUrl: 'http://localhost:8000',
loginUrl: 'http://localhost:8000/login',
logoutUrl: 'http://localhost:8000/logout',
environment: EnvironmentTypes.TEST,
apps: [{
appId,
config: {
ACTIVATION_EMAIL_SUPPORT_LINK: null,
ALLOW_PUBLIC_ACCOUNT_CREATION: false,
AUTHN_PROGRESSIVE_PROFILING_SUPPORT_LINK: null,
BANNER_IMAGE_EXTRA_SMALL: '',
BANNER_IMAGE_LARGE: '',
BANNER_IMAGE_MEDIUM: '',
BANNER_IMAGE_SMALL: '',
DISABLE_ENTERPRISE_LOGIN: true,
ENABLE_AUTO_GENERATED_USERNAME: false,
ENABLE_DYNAMIC_REGISTRATION_FIELDS: false,
ENABLE_IMAGE_LAYOUT: false,
ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN: false,
FAVICON_URL: 'https://edx-cdn.org/v3/default/favicon.ico',
INFO_EMAIL: '',
LOGIN_ISSUE_SUPPORT_LINK: null,
LOGO_TRADEMARK_URL: 'https://edx-cdn.org/v3/default/logo-trademark.svg',
LOGO_URL: 'https://edx-cdn.org/v3/default/logo.svg',
LOGO_WHITE_URL: 'https://edx-cdn.org/v3/default/logo-white.svg',
MARKETING_EMAILS_OPT_IN: '',
MARKETING_SITE_BASE_URL: 'http://localhost:18000',
PASSWORD_RESET_SUPPORT_LINK: null,
POST_REGISTRATION_REDIRECT_URL: '',
PRIVACY_POLICY: null,
SEARCH_CATALOG_URL: null,
SESSION_COOKIE_DOMAIN: 'local.openedx.io',
SHOW_REGISTRATION_LINKS: false,
TOS_AND_HONOR_CODE: null,
TOS_LINK: null,
USER_RETENTION_COOKIE_NAME: '',
},
}],
};
export default siteConfig;

23
src/Main.tsx Executable file
View File

@@ -0,0 +1,23 @@
import { Provider as ReduxProvider } from 'react-redux';
import { Outlet } from 'react-router-dom';
import { CurrentAppProvider } from '@openedx/frontend-base';
import { appId } from './constants';
import {
registerIcons,
} from './common-components';
import configureStore from './data/configureStore';
import './sass/_style.scss';
registerIcons();
const Main = () => (
<CurrentAppProvider appId={appId}>
<ReduxProvider store={configureStore()}>
<Outlet />
</ReduxProvider>
</CurrentAppProvider>
);
export default Main;

View File

@@ -1,63 +0,0 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { AppProvider } from '@edx/frontend-platform/react';
import { Helmet } from 'react-helmet';
import { Navigate, Route, Routes } from 'react-router-dom';
import {
EmbeddedRegistrationRoute, NotFoundPage, registerIcons, UnAuthOnlyRoute, Zendesk,
} from './common-components';
import configureStore from './data/configureStore';
import {
AUTHN_PROGRESSIVE_PROFILING,
LOGIN_PAGE,
PAGE_NOT_FOUND,
PASSWORD_RESET_CONFIRM,
RECOMMENDATIONS,
REGISTER_EMBEDDED_PAGE,
REGISTER_PAGE,
RESET_PAGE,
} from './data/constants';
import { updatePathWithQueryParams } from './data/utils';
import { ForgotPasswordPage } from './forgot-password';
import Logistration from './logistration/Logistration';
import { ProgressiveProfiling } from './progressive-profiling';
import { RecommendationsPage } from './recommendations';
import { RegistrationPage } from './register';
import { ResetPasswordPage } from './reset-password';
import './index.scss';
registerIcons();
const MainApp = () => (
<AppProvider store={configureStore()}>
<Helmet>
<link rel="shortcut icon" href={getConfig().FAVICON_URL} type="image/x-icon" />
</Helmet>
{getConfig().ZENDESK_KEY && <Zendesk />}
<Routes>
<Route path="/" element={<Navigate replace to={updatePathWithQueryParams(REGISTER_PAGE)} />} />
<Route
path={REGISTER_EMBEDDED_PAGE}
element={<EmbeddedRegistrationRoute><RegistrationPage /></EmbeddedRegistrationRoute>}
/>
<Route
path={LOGIN_PAGE}
element={
<UnAuthOnlyRoute><Logistration selectedPage={LOGIN_PAGE} /></UnAuthOnlyRoute>
}
/>
<Route path={REGISTER_PAGE} element={<UnAuthOnlyRoute><Logistration /></UnAuthOnlyRoute>} />
<Route path={RESET_PAGE} element={<UnAuthOnlyRoute><ForgotPasswordPage /></UnAuthOnlyRoute>} />
<Route path={PASSWORD_RESET_CONFIRM} element={<ResetPasswordPage />} />
<Route path={AUTHN_PROGRESSIVE_PROFILING} element={<ProgressiveProfiling />} />
<Route path={RECOMMENDATIONS} element={<RecommendationsPage />} />
<Route path={PAGE_NOT_FOUND} element={<NotFoundPage />} />
<Route path="*" element={<Navigate replace to={PAGE_NOT_FOUND} />} />
</Routes>
</AppProvider>
);
export default MainApp;

1
src/__mocks__/file.js Normal file
View File

@@ -0,0 +1 @@
module.exports = 'FileMock';

1
src/__mocks__/svg.js Normal file
View File

@@ -0,0 +1 @@
module.exports = 'SvgURL';

2
src/app.scss Executable file
View File

@@ -0,0 +1,2 @@
@use "@openedx/frontend-base/shell/app.scss";
@use "./sass/style";

43
src/app.ts Normal file
View File

@@ -0,0 +1,43 @@
import { App } from '@openedx/frontend-base';
import { appId } from './constants';
import routes from './routes';
import messages from './i18n';
const app: App = {
appId,
routes,
messages,
config: {
ACTIVATION_EMAIL_SUPPORT_LINK: null,
ALLOW_PUBLIC_ACCOUNT_CREATION: true,
AUTHN_PROGRESSIVE_PROFILING_SUPPORT_LINK: null,
BANNER_IMAGE_EXTRA_SMALL: '',
BANNER_IMAGE_LARGE: '',
BANNER_IMAGE_MEDIUM: '',
BANNER_IMAGE_SMALL: '',
DISABLE_ENTERPRISE_LOGIN: true,
ENABLE_AUTO_GENERATED_USERNAME: false,
ENABLE_DYNAMIC_REGISTRATION_FIELDS: false,
ENABLE_IMAGE_LAYOUT: false,
ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN: false,
FAVICON_URL: 'https://edx-cdn.org/v3/default/favicon.ico',
INFO_EMAIL: '',
LOGIN_ISSUE_SUPPORT_LINK: null,
LOGO_TRADEMARK_URL: 'https://edx-cdn.org/v3/default/logo-trademark.svg',
LOGO_URL: 'https://edx-cdn.org/v3/default/logo.svg',
LOGO_WHITE_URL: 'https://edx-cdn.org/v3/default/logo-white.svg',
MARKETING_EMAILS_OPT_IN: '',
MARKETING_SITE_BASE_URL: 'http://local.openedx.io',
PASSWORD_RESET_SUPPORT_LINK: null,
POST_REGISTRATION_REDIRECT_URL: '',
PRIVACY_POLICY: null,
SEARCH_CATALOG_URL: null,
SESSION_COOKIE_DOMAIN: 'local.openedx.io',
SHOW_REGISTRATION_LINKS: true,
TOS_AND_HONOR_CODE: null,
TOS_LINK: null,
USER_RETENTION_COOKIE_NAME: '',
},
};
export default app;

View File

@@ -1,6 +1,4 @@
import React from 'react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { IntlProvider } from '@openedx/frontend-base';
import { render, screen } from '@testing-library/react';
import { DefaultLargeLayout, DefaultMediumLayout, DefaultSmallLayout } from './index';

View File

@@ -1,7 +1,4 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useAppConfig, getSiteConfig, useIntl } from '@openedx/frontend-base';
import { Hyperlink, Image } from '@openedx/paragon';
import classNames from 'classnames';
@@ -13,20 +10,20 @@ const LargeLayout = () => {
return (
<div className="w-50 d-flex">
<div className="col-md-9 bg-primary-400">
<Hyperlink destination={getConfig().MARKETING_SITE_BASE_URL}>
<Image className="logo position-absolute" alt={getConfig().SITE_NAME} src={getConfig().LOGO_WHITE_URL} />
<Hyperlink destination={useAppConfig().MARKETING_SITE_BASE_URL}>
<Image className="logo position-absolute" alt={getSiteConfig().siteName} src={useAppConfig().LOGO_WHITE_URL} />
</Hyperlink>
<div className="min-vh-100 d-flex align-items-center">
<div className={classNames({ 'large-yellow-line mr-n4.5': getConfig().SITE_NAME === 'edX' })} />
<div className={classNames({ 'large-yellow-line mr-n4.5': getSiteConfig().siteName === 'edX' })} />
<h1
className={classNames(
'display-2 text-white mw-xs',
{ 'ml-6': getConfig().SITE_NAME !== 'edX' },
{ 'ml-6': getSiteConfig().siteName !== 'edX' },
)}
>
{formatMessage(messages['start.learning'])}
<div className="text-accent-a">
{formatMessage(messages['with.site.name'], { siteName: getConfig().SITE_NAME })}
{formatMessage(messages['with.site.name'], { siteName: getSiteConfig().siteName })}
</div>
</h1>
</div>

View File

@@ -1,7 +1,4 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useAppConfig, getSiteConfig, useIntl } from '@openedx/frontend-base';
import { Hyperlink, Image } from '@openedx/paragon';
import classNames from 'classnames';
@@ -15,22 +12,22 @@ const MediumLayout = () => {
<div className="w-100 medium-screen-top-stripe" />
<div className="w-100 p-0 mb-3 d-flex">
<div className="col-md-10 bg-primary-400">
<Hyperlink destination={getConfig().MARKETING_SITE_BASE_URL}>
<Image alt={getConfig().SITE_NAME} className="logo" src={getConfig().LOGO_WHITE_URL} />
<Hyperlink destination={useAppConfig().MARKETING_SITE_BASE_URL}>
<Image alt={getSiteConfig().siteName} className="logo" src={useAppConfig().LOGO_WHITE_URL} />
</Hyperlink>
<div className="d-flex align-items-center justify-content-center mb-4 ">
<div className={classNames({ 'mt-1 medium-yellow-line': getConfig().SITE_NAME === 'edX' })} />
<div className={classNames({ 'mt-1 medium-yellow-line': getSiteConfig().siteName === 'edX' })} />
<div>
<h1
className={classNames(
'display-1 text-white mt-5 mb-5 mr-2 main-heading',
{ 'ml-4.5': getConfig().SITE_NAME !== 'edX' },
{ 'ml-4.5': getSiteConfig().siteName !== 'edX' },
)}
>
<span>
{formatMessage(messages['start.learning'])}{' '}
<span className="text-accent-a d-inline-block">
{formatMessage(messages['with.site.name'], { siteName: getConfig().SITE_NAME })}
{formatMessage(messages['with.site.name'], { siteName: getSiteConfig().siteName })}
</span>
</span>
</h1>

View File

@@ -1,7 +1,4 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useAppConfig, getSiteConfig, useIntl } from '@openedx/frontend-base';
import { Hyperlink, Image } from '@openedx/paragon';
import classNames from 'classnames';
@@ -14,11 +11,11 @@ const SmallLayout = () => {
<span className="bg-primary-400 w-100">
<div className="col-md-12 small-screen-top-stripe" />
<div>
<Hyperlink destination={getConfig().MARKETING_SITE_BASE_URL}>
<Image className="logo-small" alt={getConfig().SITE_NAME} src={getConfig().LOGO_WHITE_URL} />
<Hyperlink destination={useAppConfig().MARKETING_SITE_BASE_URL}>
<Image className="logo-small" alt={getSiteConfig().siteName} src={useAppConfig().LOGO_WHITE_URL} />
</Hyperlink>
<div className="d-flex align-items-center m-3.5">
<div className={classNames({ 'small-yellow-line mr-n2.5': getConfig().SITE_NAME === 'edX' })} />
<div className={classNames({ 'small-yellow-line mr-n2.5': getSiteConfig().siteName === 'edX' })} />
<h1
className={classNames(
'text-white mt-3.5 mb-3.5',
@@ -27,7 +24,7 @@ const SmallLayout = () => {
<span>
{formatMessage(messages['start.learning'])}{' '}
<span className="text-accent-a d-inline-block">
{formatMessage(messages['with.site.name'], { siteName: getConfig().SITE_NAME })}
{formatMessage(messages['with.site.name'], { siteName: getSiteConfig().siteName })}
</span>
</span>
</h1>

View File

@@ -1,4 +1,4 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
import { defineMessages } from '@openedx/frontend-base';
const messages = defineMessages({
'start.learning': {

View File

@@ -1,7 +1,4 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useAppConfig, getSiteConfig, useIntl } from '@openedx/frontend-base';
import { Hyperlink, Image } from '@openedx/paragon';
import messages from './messages';
@@ -12,10 +9,10 @@ const ExtraSmallLayout = () => {
return (
<span
className="w-100 bg-primary-500 banner__image extra-small-layout"
style={{ backgroundImage: `url(${getConfig().BANNER_IMAGE_EXTRA_SMALL})` }}
style={{ backgroundImage: `url(${useAppConfig().BANNER_IMAGE_EXTRA_SMALL})` }}
>
<Hyperlink destination={getConfig().MARKETING_SITE_BASE_URL}>
<Image className="company-logo" alt={getConfig().SITE_NAME} src={getConfig().LOGO_WHITE_URL} />
<Hyperlink destination={useAppConfig().MARKETING_SITE_BASE_URL}>
<Image className="company-logo" alt={getSiteConfig().siteName} src={useAppConfig().LOGO_WHITE_URL} />
</Hyperlink>
<div className="ml-4.5 mr-1 pb-3.5 pt-3.5">
<h1 className="banner__heading">

View File

@@ -1,7 +1,4 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useAppConfig, getSiteConfig, useIntl } from '@openedx/frontend-base';
import { Hyperlink, Image } from '@openedx/paragon';
import './index.scss';
@@ -13,10 +10,10 @@ const LargeLayout = () => {
return (
<div
className="w-50 bg-primary-500 banner__image large-layout"
style={{ backgroundImage: `url(${getConfig().BANNER_IMAGE_LARGE})` }}
style={{ backgroundImage: `url(${useAppConfig().BANNER_IMAGE_LARGE})` }}
>
<Hyperlink destination={getConfig().MARKETING_SITE_BASE_URL}>
<Image className="company-logo position-absolute" alt={getConfig().SITE_NAME} src={getConfig().LOGO_WHITE_URL} />
<Hyperlink destination={useAppConfig().MARKETING_SITE_BASE_URL}>
<Image className="company-logo position-absolute" alt={getSiteConfig().siteName} src={useAppConfig().LOGO_WHITE_URL} />
</Hyperlink>
<div className="min-vh-100 p-5 d-flex align-items-end">
<h1 className="display-2 mw-sm mb-3 d-flex flex-column flex-shrink-0 justify-content-center">

View File

@@ -1,7 +1,4 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useAppConfig, getSiteConfig, useIntl } from '@openedx/frontend-base';
import { Hyperlink, Image } from '@openedx/paragon';
import './index.scss';
@@ -13,10 +10,10 @@ const MediumLayout = () => {
return (
<div
className="w-100 mb-3 bg-primary-500 banner__image medium-layout"
style={{ backgroundImage: `url(${getConfig().BANNER_IMAGE_MEDIUM})` }}
style={{ backgroundImage: `url(${useAppConfig().BANNER_IMAGE_MEDIUM})` }}
>
<Hyperlink destination={getConfig().MARKETING_SITE_BASE_URL}>
<Image className="company-logo" alt={getConfig().SITE_NAME} src={getConfig().LOGO_WHITE_URL} />
<Hyperlink destination={useAppConfig().MARKETING_SITE_BASE_URL}>
<Image className="company-logo" alt={getSiteConfig().siteName} src={useAppConfig().LOGO_WHITE_URL} />
</Hyperlink>
<div className="ml-5 pb-4 pt-4">
<h1 className="display-2 banner__heading">

View File

@@ -1,7 +1,4 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useAppConfig, getSiteConfig, useIntl } from '@openedx/frontend-base';
import { Hyperlink, Image } from '@openedx/paragon';
import messages from './messages';
@@ -12,10 +9,10 @@ const SmallLayout = () => {
return (
<span
className="w-100 bg-primary-500 banner__image small-layout"
style={{ backgroundImage: `url(${getConfig().BANNER_IMAGE_SMALL})` }}
style={{ backgroundImage: `url(${useAppConfig().BANNER_IMAGE_SMALL})` }}
>
<Hyperlink destination={getConfig().MARKETING_SITE_BASE_URL}>
<Image className="company-logo" alt={getConfig().SITE_NAME} src={getConfig().LOGO_WHITE_URL} />
<Hyperlink destination={useAppConfig().MARKETING_SITE_BASE_URL}>
<Image className="company-logo" alt={getSiteConfig().siteName} src={useAppConfig().LOGO_WHITE_URL} />
</Hyperlink>
<div className="ml-5 mr-1 pb-3.5 pt-3.5">
<h1 className="display-2">

View File

@@ -1,4 +1,4 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
import { defineMessages } from '@openedx/frontend-base';
const messages = defineMessages({
'your.career.turning.point': {

View File

@@ -1,7 +1,4 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useAppConfig, getSiteConfig, useIntl } from '@openedx/frontend-base';
import { Hyperlink, Image } from '@openedx/paragon';
import PropTypes from 'prop-types';
@@ -13,14 +10,14 @@ const LargeLayout = ({ fullName }) => {
return (
<div className="w-50 d-flex">
<div className="col-md-10 bg-light-200 p-0">
<Hyperlink destination={getConfig().MARKETING_SITE_BASE_URL}>
<Image className="logo position-absolute" alt={getConfig().SITE_NAME} src={getConfig().LOGO_URL} />
<Hyperlink destination={useAppConfig().MARKETING_SITE_BASE_URL}>
<Image className="logo position-absolute" alt={getSiteConfig().siteName} src={useAppConfig().LOGO_URL} />
</Hyperlink>
<div className="min-vh-100 d-flex align-items-center">
<div className="large-screen-left-container mr-n4.5 large-yellow-line mt-5" />
<div>
<h1 className="welcome-to-platform data-hj-suppress">
{formatMessage(messages['welcome.to.platform'], { siteName: getConfig().SITE_NAME, fullName })}
{formatMessage(messages['welcome.to.platform'], { siteName: getSiteConfig().siteName, fullName })}
</h1>
<h2 className="complete-your-profile">
{formatMessage(messages['complete.your.profile.1'])}

View File

@@ -1,7 +1,4 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useAppConfig, getSiteConfig, useIntl } from '@openedx/frontend-base';
import { Hyperlink, Image } from '@openedx/paragon';
import PropTypes from 'prop-types';
@@ -15,14 +12,14 @@ const MediumLayout = ({ fullName }) => {
<div className="w-100 medium-screen-top-stripe" />
<div className="w-100 p-0 mb-3 d-flex">
<div className="col-md-10 bg-light-200">
<Hyperlink destination={getConfig().MARKETING_SITE_BASE_URL}>
<Image className="logo" alt={getConfig().SITE_NAME} src={getConfig().LOGO_URL} />
<Hyperlink destination={useAppConfig().MARKETING_SITE_BASE_URL}>
<Image className="logo" alt={getSiteConfig().siteName} src={useAppConfig().LOGO_URL} />
</Hyperlink>
<div className="d-flex align-items-center justify-content-center mb-4 ml-5">
<div className="medium-yellow-line mt-5 mr-n2" />
<div>
<h1 className="h3 data-hj-suppress mw-320">
{formatMessage(messages['welcome.to.platform'], { siteName: getConfig().SITE_NAME, fullName })}
{formatMessage(messages['welcome.to.platform'], { siteName: getSiteConfig().siteName, fullName })}
</h1>
<h2 className="display-1">
{formatMessage(messages['complete.your.profile.1'])}

View File

@@ -1,7 +1,4 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useAppConfig, getSiteConfig, useIntl } from '@openedx/frontend-base';
import { Hyperlink, Image } from '@openedx/paragon';
import PropTypes from 'prop-types';
@@ -13,14 +10,14 @@ const SmallLayout = ({ fullName }) => {
return (
<div className="min-vw-100 bg-light-200">
<div className="col-md-12 small-screen-top-stripe" />
<Hyperlink destination={getConfig().MARKETING_SITE_BASE_URL}>
<Image className="logo-small" alt={getConfig().SITE_NAME} src={getConfig().LOGO_URL} />
<Hyperlink destination={useAppConfig().MARKETING_SITE_BASE_URL}>
<Image className="logo-small" alt={getSiteConfig().siteName} src={useAppConfig().LOGO_URL} />
</Hyperlink>
<div className="d-flex align-items-center m-3.5">
<div className="small-yellow-line mt-4.5" />
<div>
<h1 className="h5 data-hj-suppress">
{formatMessage(messages['welcome.to.platform'], { siteName: getConfig().SITE_NAME, fullName })}
{formatMessage(messages['welcome.to.platform'], { siteName: getSiteConfig().siteName, fullName })}
</h1>
<h2 className="h1">
{formatMessage(messages['complete.your.profile.1'])}

View File

@@ -1,4 +1,4 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
import { defineMessages } from '@openedx/frontend-base';
const messages = defineMessages({
'welcome.to.platform': {

View File

@@ -1,6 +1,4 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useAppConfig } from '@openedx/frontend-base';
import { breakpoints } from '@openedx/paragon';
import classNames from 'classnames';
import PropTypes from 'prop-types';
@@ -13,7 +11,7 @@ import {
import { AuthLargeLayout, AuthMediumLayout, AuthSmallLayout } from './components/welcome-page-layout';
const BaseContainer = ({ children, showWelcomeBanner, fullName }) => {
const enableImageLayout = getConfig().ENABLE_IMAGE_LAYOUT;
const enableImageLayout = useAppConfig().ENABLE_IMAGE_LAYOUT;
if (enableImageLayout) {
return (

View File

@@ -1,11 +1,9 @@
import React from 'react';
import { mergeConfig } from '@edx/frontend-platform';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { IntlProvider, mergeAppConfig } from '@openedx/frontend-base';
import { render } from '@testing-library/react';
import { Context as ResponsiveContext } from 'react-responsive';
import BaseContainer from '../index';
import { appId } from '../../constants';
const LargeScreen = {
wrappingComponent: ResponsiveContext.Provider,
@@ -28,7 +26,7 @@ describe('Base component tests', () => {
});
it('renders Image layout when ENABLE_IMAGE_LAYOUT configuration is enabled', () => {
mergeConfig({
mergeAppConfig(appId, {
ENABLE_IMAGE_LAYOUT: true,
});

View File

@@ -1,5 +1,3 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Navigate } from 'react-router-dom';

View File

@@ -1,8 +1,5 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useAppConfig, getSiteConfig, useIntl } from '@openedx/frontend-base';
import {
Button, Form,
Icon,
@@ -10,8 +7,8 @@ import {
import { Login } from '@openedx/paragon/icons';
import PropTypes from 'prop-types';
import messages from './messages';
import { LOGIN_PAGE, SUPPORTED_ICON_CLASSES } from '../data/constants';
import messages from './messages';
/**
* This component renders the Single sign-on (SSO) button only for the tpa provider passed
@@ -19,12 +16,12 @@ import { LOGIN_PAGE, SUPPORTED_ICON_CLASSES } from '../data/constants';
const EnterpriseSSO = (props) => {
const { formatMessage } = useIntl();
const tpaProvider = props.provider;
const hideRegistrationLink = getConfig().ALLOW_PUBLIC_ACCOUNT_CREATION === false
|| getConfig().SHOW_REGISTRATION_LINKS === false;
const hideRegistrationLink = useAppConfig().ALLOW_PUBLIC_ACCOUNT_CREATION === false
|| useAppConfig().SHOW_REGISTRATION_LINKS === false;
const handleSubmit = (e, url) => {
e.preventDefault();
window.location.href = getConfig().LMS_BASE_URL + url;
window.location.href = getSiteConfig().lmsBaseUrl + url;
};
const handleClick = (e) => {
@@ -50,7 +47,7 @@ const EnterpriseSSO = (props) => {
{tpaProvider.iconImage ? (
<div aria-hidden="true">
<img className="btn-tpa__image-icon" src={tpaProvider.iconImage} alt={`icon ${tpaProvider.name}`} />
<span className="pl-2" aria-hidden="true">{ tpaProvider.name }</span>
<span className="pl-2" aria-hidden="true">{tpaProvider.name}</span>
</div>
)
: (
@@ -62,7 +59,7 @@ const EnterpriseSSO = (props) => {
<Icon className="h-75" src={Login} />
)}
</div>
<span className="pl-2" aria-hidden="true">{ tpaProvider.name }</span>
<span className="pl-2" aria-hidden="true">{tpaProvider.name}</span>
</>
)}
</Button>

View File

@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import { useState } from 'react';
import {
Form, TransitionReplace,

View File

@@ -1,7 +1,4 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { getSiteConfig, useIntl } from '@openedx/frontend-base';
import { Button, Hyperlink, Icon } from '@openedx/paragon';
import { Institution } from '@openedx/paragon/icons';
import PropTypes from 'prop-types';
@@ -31,7 +28,7 @@ export const RenderInstitutionButton = props => {
* This component renders the page list of available institutions for login
* */
const InstitutionLogistration = props => {
const lmsBaseUrl = getConfig().LMS_BASE_URL;
const lmsBaseUrl = getSiteConfig().lmsBaseUrl;
const { formatMessage } = useIntl();
const {
secondaryProviders,

View File

@@ -1,6 +1,4 @@
import React from 'react';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import { FormattedMessage } from '@openedx/frontend-base';
const NotFoundPage = () => (
<div className="container-fluid d-flex py-5 justify-content-center align-items-start text-center">

View File

@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useIntl } from '@openedx/frontend-base';
import {
Form, Icon, IconButton, OverlayTrigger, Tooltip, useToggle,
} from '@openedx/paragon';
@@ -10,10 +10,10 @@ import {
} from '@openedx/paragon/icons';
import PropTypes from 'prop-types';
import messages from './messages';
import { LETTER_REGEX, NUMBER_REGEX } from '../data/constants';
import { clearRegistrationBackendError, fetchRealtimeValidations } from '../register/data/actions';
import { validatePasswordField } from '../register/data/utils';
import messages from './messages';
const PasswordField = (props) => {
const { formatMessage } = useIntl();

View File

@@ -1,9 +1,9 @@
import { getConfig } from '@edx/frontend-platform';
import { useAppConfig, getSiteConfig } from '@openedx/frontend-base';
import PropTypes from 'prop-types';
import { Navigate } from 'react-router-dom';
import {
AUTHN_PROGRESSIVE_PROFILING, RECOMMENDATIONS, REDIRECT,
AUTHN_PROGRESSIVE_PROFILING, REDIRECT,
} from '../data/constants';
import { setCookie } from '../data/utils';
@@ -15,7 +15,6 @@ const RedirectLogistration = (props) => {
redirectToProgressiveProfilingPage,
success,
optionalFields,
redirectToRecommendationsPage,
educationLevel,
userId,
registrationEmbedded,
@@ -29,7 +28,7 @@ const RedirectLogistration = (props) => {
// Note: For multiple enterprise use case, we need to make sure that user first visits the
// enterprise selection page and then complete the auth workflow
if (finishAuthUrl && !redirectUrl.includes(finishAuthUrl)) {
finalRedirectUrl = getConfig().LMS_BASE_URL + finishAuthUrl;
finalRedirectUrl = getSiteConfig().lmsBaseUrl + finishAuthUrl;
} else {
finalRedirectUrl = redirectUrl;
}
@@ -37,12 +36,12 @@ const RedirectLogistration = (props) => {
// Redirect to Progressive Profiling after successful registration
if (redirectToProgressiveProfilingPage) {
// TODO: Do we still need this cookie?
setCookie('van-504-returning-user', true);
setCookie('van-504-returning-user', true, useAppConfig().SESSION_COOKIE_DOMAIN);
if (registrationEmbedded) {
window.parent.postMessage({
action: REDIRECT,
redirectUrl: getConfig().POST_REGISTRATION_REDIRECT_URL,
redirectUrl: useAppConfig().POST_REGISTRATION_REDIRECT_URL,
}, host);
return null;
}
@@ -60,22 +59,6 @@ const RedirectLogistration = (props) => {
);
}
// Redirect to Recommendation page
if (redirectToRecommendationsPage) {
const registrationResult = { redirectUrl: finalRedirectUrl, success };
return (
<Navigate
to={RECOMMENDATIONS}
state={{
registrationResult,
educationLevel,
userId,
}}
replace
/>
);
}
window.location.href = finalRedirectUrl;
}
@@ -90,7 +73,6 @@ RedirectLogistration.defaultProps = {
redirectUrl: '',
redirectToProgressiveProfilingPage: false,
optionalFields: {},
redirectToRecommendationsPage: false,
userId: null,
registrationEmbedded: false,
host: '',
@@ -104,7 +86,6 @@ RedirectLogistration.propTypes = {
redirectUrl: PropTypes.string,
redirectToProgressiveProfilingPage: PropTypes.bool,
optionalFields: PropTypes.shape({}),
redirectToRecommendationsPage: PropTypes.bool,
userId: PropTypes.number,
registrationEmbedded: PropTypes.bool,
host: PropTypes.string,

View File

@@ -1,14 +1,11 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { getSiteConfig, useIntl } from '@openedx/frontend-base';
import { Icon } from '@openedx/paragon';
import { Login } from '@openedx/paragon/icons';
import PropTypes from 'prop-types';
import messages from './messages';
import { LOGIN_PAGE, SUPPORTED_ICON_CLASSES } from '../data/constants';
import messages from './messages';
const SocialAuthProviders = (props) => {
const { formatMessage } = useIntl();
@@ -18,7 +15,7 @@ const SocialAuthProviders = (props) => {
e.preventDefault();
const url = e.currentTarget.dataset.providerUrl;
window.location.href = getConfig().LMS_BASE_URL + url;
window.location.href = getSiteConfig().lmsBaseUrl + url;
}
const socialAuth = socialAuthProviders.map((provider, index) => (

View File

@@ -1,7 +1,4 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useAppConfig, getSiteConfig, useIntl } from '@openedx/frontend-base';
import {
Hyperlink, Icon,
} from '@openedx/paragon';
@@ -10,10 +7,10 @@ import classNames from 'classnames';
import PropTypes from 'prop-types';
import Skeleton from 'react-loading-skeleton';
import messages from './messages';
import {
ENTERPRISE_LOGIN_URL, LOGIN_PAGE, PENDING_STATE, REGISTER_PAGE,
} from '../data/constants';
import messages from './messages';
import {
RenderInstitutionButton,
@@ -35,8 +32,9 @@ const ThirdPartyAuth = (props) => {
} = props;
const isInstitutionAuthActive = !!secondaryProviders.length && !currentProvider;
const isSocialAuthActive = !!providers.length && !currentProvider;
const isEnterpriseLoginDisabled = getConfig().DISABLE_ENTERPRISE_LOGIN;
const enterpriseLoginURL = getConfig().LMS_BASE_URL + ENTERPRISE_LOGIN_URL;
const isEnterpriseLoginDisabled = useAppConfig().DISABLE_ENTERPRISE_LOGIN;
const enterpriseLoginURL = getSiteConfig().lmsBaseUrl + ENTERPRISE_LOGIN_URL;
const isThirdPartyAuthActive = isSocialAuthActive || (isEnterpriseLoginDisabled && isInstitutionAuthActive);
return (
<>
@@ -61,7 +59,7 @@ const ThirdPartyAuth = (props) => {
</Hyperlink>
)}
{thirdPartyAuthApiStatus === PENDING_STATE ? (
{thirdPartyAuthApiStatus === PENDING_STATE && isThirdPartyAuthActive ? (
<div className="mt-4">
<Skeleton className="tpa-skeleton" height={36} count={2} />
</div>

View File

@@ -1,17 +1,14 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { getSiteConfig, useIntl } from '@openedx/frontend-base';
import { Alert } from '@openedx/paragon';
import PropTypes from 'prop-types';
import messages from './messages';
import { LOGIN_PAGE, REGISTER_PAGE } from '../data/constants';
import messages from './messages';
const ThirdPartyAuthAlert = (props) => {
const { formatMessage } = useIntl();
const { currentProvider, referrer } = props;
const platformName = getConfig().SITE_NAME;
const platformName = getSiteConfig().siteName;
let message;
if (referrer === LOGIN_PAGE) {
@@ -30,7 +27,7 @@ const ThirdPartyAuthAlert = (props) => {
{referrer === REGISTER_PAGE ? (
<Alert.Heading>{formatMessage(messages['tpa.alert.heading'])}</Alert.Heading>
) : null}
<p>{ message }</p>
<p>{message}</p>
</Alert>
{referrer === REGISTER_PAGE ? (
<h4 className="mt-4 mb-4">{formatMessage(messages['registration.using.tpa.form.heading'])}</h4>

View File

@@ -1,7 +1,6 @@
import { useEffect, useState } from 'react';
import { getConfig } from '@edx/frontend-platform';
import { fetchAuthenticatedUser, getAuthenticatedUser } from '@edx/frontend-platform/auth';
import { fetchAuthenticatedUser, getAuthenticatedUser, getSiteConfig } from '@openedx/frontend-base';
import PropTypes from 'prop-types';
import {
@@ -25,7 +24,7 @@ const UnAuthOnlyRoute = ({ children }) => {
if (isReady) {
if (authUser && authUser.username) {
global.location.href = getConfig().LMS_BASE_URL.concat(DEFAULT_REDIRECT_URL);
global.location.href = getSiteConfig().lmsBaseUrl.concat(DEFAULT_REDIRECT_URL);
return null;
}

View File

@@ -1,61 +0,0 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import Zendesk from 'react-zendesk';
import messages from './messages';
import { REGISTER_EMBEDDED_PAGE } from '../data/constants';
const ZendeskHelp = () => {
const { formatMessage } = useIntl();
const setting = {
cookies: true,
webWidget: {
contactOptions: {
enabled: false,
},
chat: {
suppress: false,
departments: {
enabled: ['account settings', 'billing and payments', 'certificates', 'deadlines', 'errors and technical issues', 'other', 'proctoring'],
},
},
contactForm: {
ticketForms: [
{
id: 360003368814,
subject: false,
fields: [{ id: 'description', prefill: { '*': '' } }],
},
],
selectTicketForm: {
'*': formatMessage(messages.selectTicketForm),
},
attachments: true,
},
helpCenter: {
originalArticleButton: true,
},
answerBot: {
suppress: false,
contactOnlyAfterQuery: true,
title: { '*': formatMessage(messages.supportTitle) },
avatar: {
url: getConfig().ZENDESK_LOGO_URL,
name: { '*': formatMessage(messages.supportTitle) },
},
},
},
};
if (window.location.pathname === REGISTER_EMBEDDED_PAGE) {
return null;
}
return (
<Zendesk defer zendeskKey={getConfig().ZENDESK_KEY} {...setting} />
);
};
export default ZendeskHelp;

View File

@@ -1,6 +1,7 @@
import { logError } from '@edx/frontend-platform/logging';
import { logError } from '@openedx/frontend-base';
import { call, put, takeEvery } from 'redux-saga/effects';
import { setCountryFromThirdPartyAuthContext } from '../../register/data/actions';
import {
getThirdPartyAuthContextBegin,
getThirdPartyAuthContextFailure,
@@ -10,7 +11,6 @@ import {
import {
getThirdPartyAuthContext,
} from './service';
import { setCountryFromThirdPartyAuthContext } from '../../register/data/actions';
export function* fetchThirdPartyAuthContext(action) {
try {

View File

@@ -1,7 +1,5 @@
import { getConfig } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { getAuthenticatedHttpClient, getSiteConfig } from '@openedx/frontend-base';
// eslint-disable-next-line import/prefer-default-export
export async function getThirdPartyAuthContext(urlParams) {
const requestConfig = {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
@@ -11,15 +9,15 @@ export async function getThirdPartyAuthContext(urlParams) {
const { data } = await getAuthenticatedHttpClient()
.get(
`${getConfig().LMS_BASE_URL}/api/mfe_context`,
`${getSiteConfig().lmsBaseUrl}/api/mfe_context`,
requestConfig,
)
.catch((e) => {
throw (e);
});
return {
fieldDescriptions: data.registrationFields || {},
optionalFields: data.optionalFields || {},
thirdPartyAuthContext: data.contextData || {},
fieldDescriptions: data.registrationFields ?? {},
optionalFields: data.optionalFields ?? {},
thirdPartyAuthContext: data.contextData ?? {},
};
}

View File

@@ -1,12 +1,12 @@
import { runSaga } from 'redux-saga';
import { setCountryFromThirdPartyAuthContext } from '../../../register/data/actions';
import initializeMockLogging from '../../../setupTest';
import { initializeMockServices } from '../../../setupTest';
import * as actions from '../actions';
import { fetchThirdPartyAuthContext } from '../sagas';
import * as api from '../service';
const { loggingService } = initializeMockLogging();
const { loggingService } = initializeMockServices();
describe('fetchThirdPartyAuthContext', () => {
const params = {

View File

@@ -12,4 +12,3 @@ export { default as saga } from './data/sagas';
export { storeName } from './data/selectors';
export { default as FormGroup } from './FormGroup';
export { default as PasswordField } from './PasswordField';
export { default as Zendesk } from './Zendesk';

View File

@@ -1,4 +1,4 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
import { defineMessages } from '@openedx/frontend-base';
const messages = defineMessages({
// institution login strings
@@ -85,33 +85,23 @@ const messages = defineMessages({
'login.third.party.auth.account.not.linked': {
id: 'login.third.party.auth.account.not.linked',
defaultMessage: 'You have successfully signed into {currentProvider}, but your {currentProvider} '
+ 'account does not have a linked {platformName} account. To link your accounts, '
+ 'sign in now using your {platformName} password.',
+ 'account does not have a linked {platformName} account. To link your accounts, '
+ 'sign in now using your {platformName} password.',
description: 'Message that appears on login page if user has successfully authenticated with social '
+ 'auth but no associated platform account exists',
+ 'auth but no associated platform account exists',
},
'register.third.party.auth.account.not.linked': {
id: 'register.third.party.auth.account.not.linked',
defaultMessage: 'You\'ve successfully signed into {currentProvider}! We just need a little more information '
+ 'before you start learning with {platformName}.',
+ 'before you start learning with {platformName}.',
description: 'Message that appears on register page if user has successfully authenticated with TPA '
+ 'but no associated platform account exists',
+ 'but no associated platform account exists',
},
'registration.using.tpa.form.heading': {
id: 'registration.using.tpa.form.heading',
defaultMessage: 'Finish creating your account',
description: 'Heading that appears above form when user is trying to create account using social auth',
},
supportTitle: {
id: 'zendesk.supportTitle',
description: 'Title for the support button',
defaultMessage: 'edX Support',
},
selectTicketForm: {
id: 'zendesk.selectTicketForm',
description: 'Select ticket form',
defaultMessage: 'Please choose your request type:',
},
'registration.other.options.heading': {
id: 'registration.other.options.heading',
defaultMessage: 'Or register with:',

View File

@@ -1,22 +1,20 @@
/* eslint-disable import/no-import-module-exports */
/* eslint-disable react/function-component-definition */
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { getSiteConfig } from '@openedx/frontend-base';
import { render } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import { PAGE_NOT_FOUND, REGISTER_EMBEDDED_PAGE } from '../../data/constants';
import EmbeddedRegistrationRoute from '../EmbeddedRegistrationRoute';
import {
MemoryRouter, Route, BrowserRouter as Router, Routes,
} from 'react-router-dom';
import { PAGE_NOT_FOUND, REGISTER_EMBEDDED_PAGE } from '../../data/constants';
import EmbeddedRegistrationRoute from '../EmbeddedRegistrationRoute';
const RRD = require('react-router-dom');
// Just render plain div with its children
// eslint-disable-next-line react/prop-types
RRD.BrowserRouter = ({ children }) => <div>{ children }</div>;
RRD.BrowserRouter = ({ children }) => <div>{children}</div>;
module.exports = RRD;
const TestApp = () => (
@@ -61,7 +59,7 @@ describe('EmbeddedRegistrationRoute', () => {
it('should render embedded register page if host query param is available in the url (embedded)', async () => {
delete window.location;
window.location = {
href: getConfig().BASE_URL.concat(REGISTER_EMBEDDED_PAGE),
href: getSiteConfig().baseUrl.concat(REGISTER_EMBEDDED_PAGE),
search: '?host=http://localhost/host-websit',
};

View File

@@ -1,7 +1,6 @@
import React from 'react';
import { Provider } from 'react-redux';
import { injectIntl, IntlProvider } from '@edx/frontend-platform/i18n';
import { injectIntl, IntlProvider } from '@openedx/frontend-base';
import { fireEvent, render } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import { MemoryRouter } from 'react-router-dom';

View File

@@ -1,6 +1,4 @@
import React from 'react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { IntlProvider } from '@openedx/frontend-base';
import renderer from 'react-test-renderer';
import registerIcons from '../RegisterFaIcons';

View File

@@ -1,6 +1,4 @@
import React from 'react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { IntlProvider } from '@openedx/frontend-base';
import renderer from 'react-test-renderer';
import { REGISTER_PAGE } from '../../data/constants';

View File

@@ -1,19 +1,18 @@
/* eslint-disable import/no-import-module-exports */
/* eslint-disable react/function-component-definition */
import React from 'react';
import { fetchAuthenticatedUser, getAuthenticatedUser } from '@edx/frontend-platform/auth';
import { fetchAuthenticatedUser, getAuthenticatedUser } from '@openedx/frontend-base';
import { render } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import { UnAuthOnlyRoute } from '..';
import { REGISTER_PAGE } from '../../data/constants';
import {
MemoryRouter, Route, BrowserRouter as Router, Routes,
} from 'react-router-dom';
jest.mock('@edx/frontend-platform/auth', () => ({
import { UnAuthOnlyRoute } from '..';
import { REGISTER_PAGE } from '../../data/constants';
jest.mock('@openedx/frontend-base', () => ({
...jest.requireActual('@openedx/frontend-base'),
getAuthenticatedUser: jest.fn(),
fetchAuthenticatedUser: jest.fn(),
}));

View File

@@ -1,17 +0,0 @@
import { IntlProvider } from '@edx/frontend-platform/i18n';
import renderer from 'react-test-renderer';
import Zendesk from '../Zendesk';
jest.mock('react-zendesk', () => 'Zendesk');
describe('Zendesk Help', () => {
it('should match login page third party auth alert message snapshot', () => {
const tree = renderer.create(
<IntlProvider locale="en">
<Zendesk />
</IntlProvider>,
).toJSON();
expect(tree).toMatchSnapshot();
});
});

View File

@@ -66,14 +66,14 @@ exports[`SocialAuthProviders should match social auth provider with iconClass sn
data-prefix="fab"
focusable="false"
role="img"
style={Object {}}
style={{}}
viewBox="0 0 488 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M488 261.8C488 403.3 391.1 504 248 504 110.8 504 0 393.2 0 256S110.8 8 248 8c66.8 0 123 24.5 166.3 64.9l-67.5 64.9C258.5 52.6 94.3 116.6 94.3 256c0 86.5 69.1 156.6 153.7 156.6 98.2 0 135-70.4 140.8-106.9H248v-85.3h236.1c2.3 12.7 3.9 24.9 3.9 41.4z"
fill="currentColor"
style={Object {}}
style={{}}
/>
</svg>
</div>
@@ -93,7 +93,7 @@ exports[`SocialAuthProviders should match social auth provider with iconClass sn
`;
exports[`SocialAuthProviders should match social auth provider with iconImage snapshot 1`] = `
Array [
[
<button
className="btn-social btn-oa2-apple-id mr-3"
data-provider-url="/auth/login/apple-id/?auth_entry=login&next=/dashboard"

View File

@@ -13,7 +13,7 @@ exports[`ThirdPartyAuthAlert should match login page third party auth alert mess
className="alert-message-content"
>
<p>
You have successfully signed into Google, but your Google account does not have a linked Your Platform Name Here account. To link your accounts, sign in now using your Your Platform Name Here password.
You have successfully signed into Google, but your Google account does not have a linked Test Site account. To link your accounts, sign in now using your Test Site password.
</p>
</div>
</div>
@@ -21,7 +21,7 @@ exports[`ThirdPartyAuthAlert should match login page third party auth alert mess
`;
exports[`ThirdPartyAuthAlert should match register page third party auth alert message snapshot 1`] = `
Array [
[
<div
className="fade alert-content alert-success mt-n2 mb-5 alert show"
id="tpa-alert"
@@ -39,7 +39,7 @@ Array [
Almost done!
</div>
<p>
You've successfully signed into Google! We just need a little more information before you start learning with Your Platform Name Here.
You've successfully signed into Google! We just need a little more information before you start learning with Test Site.
</p>
</div>
</div>

View File

@@ -1,65 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Zendesk Help should match login page third party auth alert message snapshot 1`] = `
<Zendesk
cookies={true}
defer={true}
webWidget={
Object {
"answerBot": Object {
"avatar": Object {
"name": Object {
"*": "edX Support",
},
"url": undefined,
},
"contactOnlyAfterQuery": true,
"suppress": false,
"title": Object {
"*": "edX Support",
},
},
"chat": Object {
"departments": Object {
"enabled": Array [
"account settings",
"billing and payments",
"certificates",
"deadlines",
"errors and technical issues",
"other",
"proctoring",
],
},
"suppress": false,
},
"contactForm": Object {
"attachments": true,
"selectTicketForm": Object {
"*": "Please choose your request type:",
},
"ticketForms": Array [
Object {
"fields": Array [
Object {
"id": "description",
"prefill": Object {
"*": "",
},
},
],
"id": 360003368814,
"subject": false,
},
],
},
"contactOptions": Object {
"enabled": false,
},
"helpCenter": Object {
"originalArticleButton": true,
},
}
}
/>
`;

View File

@@ -1,39 +0,0 @@
const configuration = {
// Cookies related configs
SESSION_COOKIE_DOMAIN: process.env.SESSION_COOKIE_DOMAIN,
USER_RETENTION_COOKIE_NAME: process.env.USER_RETENTION_COOKIE_NAME || '',
// Features
DISABLE_ENTERPRISE_LOGIN: process.env.DISABLE_ENTERPRISE_LOGIN || '',
ENABLE_DYNAMIC_REGISTRATION_FIELDS: process.env.ENABLE_DYNAMIC_REGISTRATION_FIELDS || false,
ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN: process.env.ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN || false,
ENABLE_POST_REGISTRATION_RECOMMENDATIONS: process.env.ENABLE_POST_REGISTRATION_RECOMMENDATIONS || false,
MARKETING_EMAILS_OPT_IN: process.env.MARKETING_EMAILS_OPT_IN || '',
SHOW_CONFIGURABLE_EDX_FIELDS: process.env.SHOW_CONFIGURABLE_EDX_FIELDS || false,
SHOW_REGISTRATION_LINKS: process.env.SHOW_REGISTRATION_LINKS !== 'false',
ENABLE_IMAGE_LAYOUT: process.env.ENABLE_IMAGE_LAYOUT || false,
// Links
ACTIVATION_EMAIL_SUPPORT_LINK: process.env.ACTIVATION_EMAIL_SUPPORT_LINK || null,
AUTHN_PROGRESSIVE_PROFILING_SUPPORT_LINK: process.env.AUTHN_PROGRESSIVE_PROFILING_SUPPORT_LINK || null,
LOGIN_ISSUE_SUPPORT_LINK: process.env.LOGIN_ISSUE_SUPPORT_LINK || null,
PASSWORD_RESET_SUPPORT_LINK: process.env.PASSWORD_RESET_SUPPORT_LINK || null,
POST_REGISTRATION_REDIRECT_URL: process.env.POST_REGISTRATION_REDIRECT_URL || '',
PRIVACY_POLICY: process.env.PRIVACY_POLICY || null,
SEARCH_CATALOG_URL: process.env.SEARCH_CATALOG_URL || null,
TOS_AND_HONOR_CODE: process.env.TOS_AND_HONOR_CODE || null,
TOS_LINK: process.env.TOS_LINK || null,
// Base container images
BANNER_IMAGE_LARGE: process.env.BANNER_IMAGE_LARGE || '',
BANNER_IMAGE_MEDIUM: process.env.BANNER_IMAGE_MEDIUM || '',
BANNER_IMAGE_SMALL: process.env.BANNER_IMAGE_SMALL || '',
BANNER_IMAGE_EXTRA_SMALL: process.env.BANNER_IMAGE_EXTRA_SMALL || '',
// Recommendation constants
GENERAL_RECOMMENDATIONS: process.env.GENERAL_RECOMMENDATIONS || '[]',
// Miscellaneous
INFO_EMAIL: process.env.INFO_EMAIL || '',
ZENDESK_KEY: process.env.ZENDESK_KEY,
ZENDESK_LOGO_URL: process.env.ZENDESK_LOGO_URL,
ALGOLIA_APP_ID: process.env.ALGOLIA_APP_ID || '',
ALGOLIA_SEARCH_API_KEY: process.env.ALGOLIA_SEARCH_API_KEY || '',
};
export default configuration;

1
src/constants.ts Normal file
View File

@@ -0,0 +1 @@
export const appId = 'org.openedx.frontend.app.authn';

View File

@@ -1,20 +0,0 @@
import { getConfig } from '@edx/frontend-platform';
import algoliasearch from 'algoliasearch';
// initialize Algolia workers
const initializeSearchClient = () => algoliasearch(
getConfig().ALGOLIA_APP_ID,
getConfig().ALGOLIA_SEARCH_API_KEY,
);
const getLocationRestrictionFilter = (userCountry) => {
if (userCountry) {
return `NOT blocked_in:"${userCountry}" AND (allowed_in:"null" OR allowed_in:"${userCountry}")`;
}
return '';
};
export {
initializeSearchClient,
getLocationRestrictionFilter,
};

View File

@@ -1,4 +1,4 @@
import { getConfig } from '@edx/frontend-platform';
import { getSiteConfig } from '@openedx/frontend-base';
import { composeWithDevTools } from '@redux-devtools/extension';
import { applyMiddleware, compose, createStore } from 'redux';
import { createLogger } from 'redux-logger';
@@ -11,7 +11,7 @@ import rootSaga from './sagas';
const sagaMiddleware = createSagaMiddleware();
function composeMiddleware() {
if (getConfig().ENVIRONMENT === 'development') {
if (getSiteConfig().environment === 'development') {
const loggerMiddleware = createLogger({
collapsed: true,
});

View File

@@ -5,7 +5,6 @@ export const REGISTER_EMBEDDED_PAGE = '/register-embedded';
export const RESET_PAGE = '/reset';
export const AUTHN_PROGRESSIVE_PROFILING = '/welcome';
export const DEFAULT_REDIRECT_URL = '/dashboard';
export const RECOMMENDATIONS = '/recommendations';
export const PASSWORD_RESET_CONFIRM = '/password_reset_confirm/:token/';
export const PAGE_NOT_FOUND = '/notfound';
export const ENTERPRISE_LOGIN_URL = '/enterprise/login';
@@ -29,9 +28,9 @@ export const EMBEDDED = 'embedded';
export const LETTER_REGEX = /[a-zA-Z]/;
export const NUMBER_REGEX = /\d/;
export const VALID_EMAIL_REGEX = '(^[-!#$%&\'*+/=?^_`{}|~0-9A-Z]+(\\.[-!#$%&\'*+/=?^_`{}|~0-9A-Z]+)*'
+ '|^"([\\001-\\010\\013\\014\\016-\\037!#-\\[\\]-\\177]|\\\\[\\001-\\011\\013\\014\\016-\\177])*"'
+ ')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\\.)+)(?:[A-Z0-9-]{2,63})'
+ '|\\[(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\]$';
+ '|^"([\\001-\\010\\013\\014\\016-\\037!#-\\[\\]-\\177]|\\\\[\\001-\\011\\013\\014\\016-\\177])*"'
+ ')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\\.)+)(?:[A-Z0-9-]{2,63})'
+ '|\\[(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\]$';
// Query string parameters that can be passed to LMS to manage
// things like auto-enrollment upon login and registration.

59
src/data/countries.ts Normal file
View File

@@ -0,0 +1,59 @@
import { getPrimaryLanguageSubtag } from '@openedx/frontend-base';
import COUNTRIES, { langs as countryLangs } from 'i18n-iso-countries';
import arLocale from 'i18n-iso-countries/langs/ar.json';
import caLocale from 'i18n-iso-countries/langs/ca.json';
import enLocale from 'i18n-iso-countries/langs/en.json';
import esLocale from 'i18n-iso-countries/langs/es.json';
import frLocale from 'i18n-iso-countries/langs/fr.json';
import heLocale from 'i18n-iso-countries/langs/he.json';
import idLocale from 'i18n-iso-countries/langs/id.json';
import koLocale from 'i18n-iso-countries/langs/ko.json';
import plLocale from 'i18n-iso-countries/langs/pl.json';
import ptLocale from 'i18n-iso-countries/langs/pt.json';
import ruLocale from 'i18n-iso-countries/langs/ru.json';
import ukLocale from 'i18n-iso-countries/langs/uk.json';
import zhLocale from 'i18n-iso-countries/langs/zh.json';
COUNTRIES.registerLocale(arLocale);
COUNTRIES.registerLocale(enLocale);
COUNTRIES.registerLocale(esLocale);
COUNTRIES.registerLocale(frLocale);
COUNTRIES.registerLocale(zhLocale);
COUNTRIES.registerLocale(caLocale);
COUNTRIES.registerLocale(heLocale);
COUNTRIES.registerLocale(idLocale);
COUNTRIES.registerLocale(koLocale);
COUNTRIES.registerLocale(plLocale);
COUNTRIES.registerLocale(ptLocale);
COUNTRIES.registerLocale(ruLocale);
COUNTRIES.registerLocale(ukLocale);
/**
* Provides a lookup table of country IDs to country names for the current locale.
*
* @memberof module:I18n
*/
export function getCountryMessages(locale) {
const primaryLanguageSubtag = getPrimaryLanguageSubtag(locale);
const languageCode = countryLangs().includes(primaryLanguageSubtag) ? primaryLanguageSubtag : 'en';
return COUNTRIES.getNames(languageCode);
}
/**
* Provides a list of countries represented as objects of the following shape:
*
* {
* key, // The ID of the country
* name // The localized name of the country
* }
*
* TODO: ARCH-878: The list should be sorted alphabetically in the current locale.
* This is useful for populating dropdowns.
*
* @memberof module:I18n
*/
export function getCountryList(locale) {
const countryMessages = getCountryMessages(locale);
return Object.entries(countryMessages).map(([code, name]) => ({ code, name }));
}

View File

@@ -1,17 +0,0 @@
import {
createInstance,
} from '@optimizely/react-sdk';
const OPTIMIZELY_SDK_KEY = process.env.OPTIMIZELY_FULL_STACK_SDK_KEY;
const getOptimizelyInstance = () => {
if (OPTIMIZELY_SDK_KEY) {
return createInstance({
sdkKey: OPTIMIZELY_SDK_KEY,
});
}
return null;
};
export default getOptimizelyInstance();

View File

@@ -1,16 +0,0 @@
import { getLocationRestrictionFilter } from '../algolia';
describe('algoliaUtilsTests', () => {
it('test getLocationRestrictionFilter returns filter if country is passed', () => {
const countryCode = 'PK';
const filter = getLocationRestrictionFilter(countryCode);
const expectedFilter = `NOT blocked_in:"${countryCode}" AND (allowed_in:"null" OR allowed_in:"${countryCode}")`;
expect(filter).toEqual(expectedFilter);
});
it('test getLocationRestrictionFilter returns empty string if country is not passed', () => {
const countryCode = '';
const filter = getLocationRestrictionFilter(countryCode);
const expectedFilter = '';
expect(filter).toEqual(expectedFilter);
});
});

View File

@@ -1,13 +1,7 @@
import { getConfig } from '@edx/frontend-platform';
import Cookies from 'universal-cookie';
import { setCookie } from '../utils';
// Mock getConfig function
jest.mock('@edx/frontend-platform', () => ({
getConfig: jest.fn(),
}));
// Mock Cookies class
jest.mock('universal-cookie');
@@ -17,9 +11,7 @@ describe('setCookie function', () => {
});
it('should set a cookie with default options', () => {
getConfig.mockReturnValue({ SESSION_COOKIE_DOMAIN: 'example.com' });
setCookie('testCookie', 'testValue');
setCookie('testCookie', 'testValue', 'example.com');
expect(Cookies).toHaveBeenCalled();
expect(Cookies).toHaveBeenCalledWith();
@@ -30,10 +22,8 @@ describe('setCookie function', () => {
});
it('should set a cookie with specified expiry', () => {
getConfig.mockReturnValue({ SESSION_COOKIE_DOMAIN: 'example.com' });
const expiry = new Date('2023-12-31');
setCookie('testCookie', 'testValue', expiry);
setCookie('testCookie', 'testValue', 'example.com', expiry);
expect(Cookies).toHaveBeenCalled();
expect(Cookies).toHaveBeenCalledWith();
@@ -45,7 +35,7 @@ describe('setCookie function', () => {
});
it('should not set a cookie if cookieName is undefined', () => {
setCookie(undefined, 'testValue');
setCookie(undefined, 'testValue', 'example.com');
expect(Cookies).not.toHaveBeenCalled();
});

View File

@@ -1,10 +1,9 @@
import { getConfig } from '@edx/frontend-platform';
import Cookies from 'universal-cookie';
export default function setCookie(cookieName, cookieValue, cookieExpiry) {
export default function setCookie(cookieName, cookieValue, cookieDomain, cookieExpiry) {
if (cookieName) { // To avoid setting getting exception when setting cookie with undefined names.
const cookies = new Cookies();
const options = { domain: getConfig().SESSION_COOKIE_DOMAIN, path: '/' };
const options = { domain: cookieDomain, path: '/' };
if (cookieExpiry) {
options.expires = cookieExpiry;
}

View File

@@ -40,10 +40,8 @@ export const updatePathWithQueryParams = (path) => {
return path;
}
if (queryParams.indexOf('track=pwreset') > -1) {
queryParams = queryParams.replace(
'?track=pwreset&', '?',
).replace('?track=pwreset', '').replace('&track=pwreset', '').replace('?&', '?');
if (queryParams.includes('track=pwreset')) {
queryParams = queryParams.replace('?track=pwreset&', '?',).replace('?track=pwreset', '').replace('&track=pwreset', '').replace('?&', '?');
}
return `${path}${queryParams}`;
@@ -53,7 +51,7 @@ export const getAllPossibleQueryParams = (locationURl = null) => {
const urlParams = locationURl ? QueryString.parseUrl(locationURl).query : QueryString.parse(window.location.search);
const params = {};
Object.entries(urlParams).forEach(([key, value]) => {
if (AUTH_PARAMS.indexOf(key) > -1) {
if (AUTH_PARAMS.includes(key)) {
params[key] = value;
}
});

View File

@@ -10,7 +10,7 @@ import { breakpoints } from '@openedx/paragon';
const useMobileResponsive = (breakpoint) => {
const [isMobileWindow, setIsMobileWindow] = useState();
const checkForMobile = () => {
setIsMobileWindow(window.matchMedia(`(max-width: ${breakpoint || breakpoints.small.maxWidth}px)`).matches);
setIsMobileWindow(window.matchMedia(`(max-width: ${breakpoint ?? breakpoints.small.maxWidth}px)`).matches);
};
useEffect(() => {
checkForMobile();

View File

@@ -1,5 +1,3 @@
import React from 'react';
import { Form, Icon } from '@openedx/paragon';
import { ExpandMore } from '@openedx/paragon/icons';
import PropTypes from 'prop-types';

View File

@@ -1,6 +1,4 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { getSiteConfig } from '@openedx/frontend-base';
import { fireEvent, render } from '@testing-library/react';
import FieldRenderer from '../FieldRenderer';
@@ -45,7 +43,7 @@ describe('FieldRendererTests', () => {
name: 'yob-field',
};
const { container } = render(<FieldRenderer fieldData={fieldData} onChangeHandler={() => {}} />);
const { container } = render(<FieldRenderer fieldData={fieldData} onChangeHandler={() => { }} />);
expect(container.innerHTML).toEqual('');
});
@@ -86,7 +84,7 @@ describe('FieldRendererTests', () => {
it('should render checkbox field', () => {
const fieldData = {
type: 'checkbox',
label: `I agree that ${getConfig().SITE_NAME} may send me marketing messages.`,
label: `I agree that ${getSiteConfig().siteName} may send me marketing messages.`,
name: 'marketing-emails-opt-in-field',
};
@@ -105,7 +103,7 @@ describe('FieldRendererTests', () => {
type: 'unknown',
};
const { container } = render(<FieldRenderer fieldData={fieldData} onChangeHandler={() => {}} />);
const { container } = render(<FieldRenderer fieldData={fieldData} onChangeHandler={() => { }} />);
expect(container.innerHTML).toContain('');
});

View File

@@ -1,16 +1,13 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { FormattedMessage, useAppConfig, useIntl } from '@openedx/frontend-base';
import { Alert } from '@openedx/paragon';
import { CheckCircle, Error } from '@openedx/paragon/icons';
import PropTypes from 'prop-types';
import messages from './messages';
import {
COMPLETE_STATE, FORBIDDEN_STATE, FORM_SUBMISSION_ERROR, INTERNAL_SERVER_ERROR,
} from '../data/constants';
import { PASSWORD_RESET } from '../reset-password/data/constants';
import messages from './messages';
const ForgotPasswordAlert = (props) => {
const { formatMessage } = useIntl();
@@ -36,14 +33,14 @@ const ForgotPasswordAlert = (props) => {
values={{
email: <span className="data-hj-suppress">{email}</span>,
supportLink: (
<Alert.Link href={getConfig().PASSWORD_RESET_SUPPORT_LINK} target="_blank">
<Alert.Link href={useAppConfig().PASSWORD_RESET_SUPPORT_LINK} target="_blank">
{formatMessage(messages['confirmation.support.link'])}
</Alert.Link>
),
}}
/>
);
break;
break;
case INTERNAL_SERVER_ERROR:
message = formatMessage(messages['internal.server.error']);
break;

View File

@@ -1,9 +1,10 @@
import React, { useEffect, useState } from 'react';
import { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { getConfig } from '@edx/frontend-platform';
import { sendPageEvent, sendTrackEvent } from '@edx/frontend-platform/analytics';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
useAppConfig,
getSiteConfig, sendPageEvent, sendTrackEvent, useIntl
} from '@openedx/frontend-base';
import {
Form,
Hyperlink,
@@ -17,17 +18,17 @@ import PropTypes from 'prop-types';
import { Helmet } from 'react-helmet';
import { useNavigate } from 'react-router-dom';
import { forgotPassword, setForgotPasswordFormData } from './data/actions';
import { forgotPasswordResultSelector } from './data/selectors';
import ForgotPasswordAlert from './ForgotPasswordAlert';
import messages from './messages';
import BaseContainer from '../base-container';
import { FormGroup } from '../common-components';
import { DEFAULT_STATE, LOGIN_PAGE, VALID_EMAIL_REGEX } from '../data/constants';
import { updatePathWithQueryParams, windowScrollTo } from '../data/utils';
import { forgotPassword, setForgotPasswordFormData } from './data/actions';
import { forgotPasswordResultSelector } from './data/selectors';
import ForgotPasswordAlert from './ForgotPasswordAlert';
import messages from './messages';
const ForgotPasswordPage = (props) => {
const platformName = getConfig().SITE_NAME;
const platformName = getSiteConfig().siteName;
const emailRegex = new RegExp(VALID_EMAIL_REGEX, 'i');
const {
status, submitState, emailValidationError,
@@ -97,8 +98,11 @@ const ForgotPasswordPage = (props) => {
return (
<BaseContainer>
<Helmet>
<title>{formatMessage(messages['forgot.password.page.title'],
{ siteName: getConfig().SITE_NAME })}
<title>
{formatMessage(
messages['forgot.password.page.title'],
{ siteName: getSiteConfig().siteName }
)}
</title>
</Helmet>
<div>
@@ -139,12 +143,12 @@ const ForgotPasswordPage = (props) => {
onClick={handleSubmit}
onMouseDown={(e) => e.preventDefault()}
/>
{(getConfig().LOGIN_ISSUE_SUPPORT_LINK) && (
{(useAppConfig().LOGIN_ISSUE_SUPPORT_LINK) && (
<Hyperlink
id="forgot-password"
name="forgot-password"
className="ml-4 font-weight-500 text-body"
destination={getConfig().LOGIN_ISSUE_SUPPORT_LINK}
destination={useAppConfig().LOGIN_ISSUE_SUPPORT_LINK}
target="_blank"
showLaunchIcon={false}
>
@@ -154,7 +158,7 @@ const ForgotPasswordPage = (props) => {
<p className="mt-5.5 small text-gray-700">
{formatMessage(messages['additional.help.text'], { platformName })}
<span>
<Hyperlink isInline destination={`mailto:${getConfig().INFO_EMAIL}`}>{getConfig().INFO_EMAIL}</Hyperlink>
<Hyperlink isInline destination={`mailto:${useAppConfig().INFO_EMAIL}`}>{useAppConfig().INFO_EMAIL}</Hyperlink>
</span>
</p>
</Form>

View File

@@ -1,4 +1,4 @@
import { logError, logInfo } from '@edx/frontend-platform/logging';
import { logError, logInfo } from '@openedx/frontend-base';
import { call, put, takeEvery } from 'redux-saga/effects';
// Actions
@@ -20,7 +20,7 @@ export function* handleForgotPassword(action) {
yield put(forgotPasswordSuccess(action.payload.email));
} catch (e) {
if (e.response && e.response.status === 403) {
if (e.response?.status === 403) {
yield put(forgotPasswordForbidden());
logInfo(e);
} else {

View File

@@ -1,8 +1,6 @@
import { getConfig } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { getAuthenticatedHttpClient, getSiteConfig } from '@openedx/frontend-base';
import formurlencoded from 'form-urlencoded';
// eslint-disable-next-line import/prefer-default-export
export async function forgotPassword(email) {
const requestConfig = {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
@@ -11,7 +9,7 @@ export async function forgotPassword(email) {
const { data } = await getAuthenticatedHttpClient()
.post(
`${getConfig().LMS_BASE_URL}/account/password`,
`${getSiteConfig().lmsBaseUrl}/account/password`,
formurlencoded({ email }),
requestConfig,
)

View File

@@ -1,11 +1,11 @@
import { runSaga } from 'redux-saga';
import initializeMockLogging from '../../../setupTest';
import { initializeMockServices } from '../../../setupTest';
import * as actions from '../actions';
import { handleForgotPassword } from '../sagas';
import * as api from '../service';
const { loggingService } = initializeMockLogging();
const { loggingService } = initializeMockServices();
describe('handleForgotPassword', () => {
const params = {

View File

@@ -1,4 +1,4 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
import { defineMessages } from '@openedx/frontend-base';
const messages = defineMessages({
'forgot.password.page.title': {

View File

@@ -1,8 +1,8 @@
import React from 'react';
import { Provider } from 'react-redux';
import { mergeConfig } from '@edx/frontend-platform';
import { configure, injectIntl, IntlProvider } from '@edx/frontend-platform/i18n';
import {
configureI18n, injectIntl, IntlProvider, mergeAppConfig
} from '@openedx/frontend-base';
import {
fireEvent, render, screen,
} from '@testing-library/react';
@@ -11,16 +11,22 @@ import configureStore from 'redux-mock-store';
import { INTERNAL_SERVER_ERROR, LOGIN_PAGE } from '../../data/constants';
import { PASSWORD_RESET } from '../../reset-password/data/constants';
import { appId } from '../../constants';
import { setForgotPasswordFormData } from '../data/actions';
import ForgotPasswordPage from '../ForgotPasswordPage';
const mockedNavigator = jest.fn();
jest.mock('@edx/frontend-platform/analytics', () => ({
jest.mock('@openedx/frontend-base', () => ({
...jest.requireActual('@openedx/frontend-base'),
sendPageEvent: jest.fn(),
sendTrackEvent: jest.fn(),
getAuthenticatedUser: jest.fn(() => ({
userId: 3,
username: 'test-user',
})),
}));
jest.mock('@edx/frontend-platform/auth');
jest.mock('react-router-dom', () => ({
...(jest.requireActual('react-router-dom')),
useNavigate: () => mockedNavigator,
@@ -36,7 +42,7 @@ const initialState = {
};
describe('ForgotPasswordPage', () => {
mergeConfig({
mergeAppConfig(appId, {
LOGIN_ISSUE_SUPPORT_LINK: '',
INFO_EMAIL: '',
});
@@ -54,18 +60,8 @@ describe('ForgotPasswordPage', () => {
beforeEach(() => {
store = mockStore(initialState);
jest.mock('@edx/frontend-platform/auth', () => ({
getAuthenticatedUser: jest.fn(() => ({
userId: 3,
username: 'test-user',
})),
}));
configure({
loggingService: { logError: jest.fn() },
config: {
ENVIRONMENT: 'production',
LANGUAGE_PREFERENCE_COOKIE_NAME: 'yum',
},
configureI18n({
messages: { 'es-419': {}, de: {}, 'en-us': {} },
});
props = {
@@ -84,7 +80,7 @@ describe('ForgotPasswordPage', () => {
});
it('should display need other help signing in button', () => {
mergeConfig({
mergeAppConfig(appId, {
LOGIN_ISSUE_SUPPORT_LINK: '/support',
});
render(reduxWrapper(<IntlForgotPasswordPage {...props} />));
@@ -113,7 +109,7 @@ describe('ForgotPasswordPage', () => {
forgotPassword: { status: INTERNAL_SERVER_ERROR },
});
const expectedMessage = 'We were unable to contact you.'
+ 'An error has occurred. Try refreshing the page, or check your internet connection.';
+ 'An error has occurred. Try refreshing the page, or check your internet connection.';
const { container } = render(reduxWrapper(<IntlForgotPasswordPage {...props} />));
@@ -233,8 +229,8 @@ describe('ForgotPasswordPage', () => {
});
const successMessage = 'Check your emailWe sent an email to with instructions to reset your password. If you do not '
+ 'receive a password reset message after 1 minute, verify that you entered the correct email address,'
+ ' or check your spam folder. If you need further assistance, contact technical support.';
+ 'receive a password reset message after 1 minute, verify that you entered the correct email address,'
+ ' or check your spam folder. If you need further assistance, contact technical support.';
const { container } = render(reduxWrapper(<IntlForgotPasswordPage {...props} />));
const successElement = findByTextContent(container, successMessage);
@@ -251,8 +247,8 @@ describe('ForgotPasswordPage', () => {
},
});
const successMessage = 'Invalid password reset link'
+ 'This password reset link is invalid. It may have been used already. '
+ 'Enter your email below to receive a new link.';
+ 'This password reset link is invalid. It may have been used already. '
+ 'Enter your email below to receive a new link.';
const { container } = render(reduxWrapper(<IntlForgotPasswordPage {...props} />));
const successElement = findByTextContent(container, successMessage);

View File

@@ -1 +1,25 @@
export default [];
// Placeholder be overridden by `make pull_translations`
export default {
ar: {},
'zh-hk': {},
'zh-cn': {},
uk: {},
'tr-tr': {},
th: {},
te: {},
ru: {},
'pt-pt': {},
'pt-br': {},
'it-it': {},
id: {},
hi: {},
he: {},
'fr-ca': {},
fa: {},
'es-es': {},
'es-419': {},
el: {},
'de-de': {},
da: {},
bo: {},
};

View File

@@ -1,34 +0,0 @@
import 'core-js/stable';
import 'regenerator-runtime/runtime';
import React from 'react';
import ReactDOM from 'react-dom';
import {
APP_INIT_ERROR, APP_READY, initialize, mergeConfig, subscribe,
} from '@edx/frontend-platform';
import { ErrorPage } from '@edx/frontend-platform/react';
import configuration from './config';
import messages from './i18n';
import MainApp from './MainApp';
subscribe(APP_READY, () => {
ReactDOM.render(
<MainApp />,
document.getElementById('root'),
);
});
subscribe(APP_INIT_ERROR, (error) => {
ReactDOM.render(<ErrorPage message={error.message} />, document.getElementById('root'));
});
initialize({
handlers: {
config: () => {
mergeConfig(configuration);
},
},
messages,
});

Some files were not shown because too many files have changed in this diff Show More