Compare commits
147 Commits
remove-com
...
teak-desig
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e999ebbc2 | ||
|
|
0e94124d74 | ||
|
|
af7edd8a3f | ||
|
|
9323f119c8 | ||
|
|
38a1924c6a | ||
|
|
2d7303009f | ||
|
|
dfcb94a831 | ||
|
|
520dd6ed6b | ||
|
|
1b32dbfa19 | ||
|
|
f7d9bdb5b5 | ||
|
|
063ec80cde | ||
|
|
3cbb134c3a | ||
|
|
059a60d1c8 | ||
|
|
c88d701271 | ||
|
|
33b98b356b | ||
|
|
1f81699af4 | ||
|
|
13aa77fc70 | ||
|
|
66531831b7 | ||
|
|
846d3f0662 | ||
|
|
f78e84ee0a | ||
|
|
2d27da2391 | ||
|
|
78413be34a | ||
|
|
88866a39c1 | ||
|
|
dc9699c033 | ||
|
|
00a0e27062 | ||
|
|
6839afcf3c | ||
|
|
1cd9c58c1a | ||
|
|
5d481a93c7 | ||
|
|
438d1fcfa7 | ||
|
|
bc912ce139 | ||
|
|
ab1c2d5379 | ||
|
|
c109f6e771 | ||
|
|
8976647190 | ||
|
|
cb051a83ad | ||
|
|
1b8aec5709 | ||
|
|
9a68e95fcc | ||
|
|
c90980afb0 | ||
|
|
abb8ae5085 | ||
|
|
8bb7462098 | ||
|
|
b4a5397ba1 | ||
|
|
a43c620dc4 | ||
|
|
93d11b8485 | ||
|
|
68e13d4daf | ||
|
|
f6617935e3 | ||
|
|
5f4591c046 | ||
|
|
ae52a8cb65 | ||
|
|
b8df66ad23 | ||
|
|
923776ab96 | ||
|
|
f170f5e3f0 | ||
|
|
730875ceb2 | ||
|
|
812350d24a | ||
|
|
6879bacb89 | ||
|
|
9b2b0f2019 | ||
|
|
87884f2d91 | ||
|
|
3e20fcae57 | ||
|
|
173896811d | ||
|
|
7af4a08bd9 | ||
|
|
6c12b3b034 | ||
|
|
5304085cd8 | ||
|
|
3cd9ae130c | ||
|
|
28ad2c2cf6 | ||
|
|
3e889df109 | ||
|
|
52c6efc34d | ||
|
|
584a84a99c | ||
|
|
7e4ab1c74c | ||
|
|
13d89cb3a0 | ||
|
|
5a1e2e6c97 | ||
|
|
6f1cf29a60 | ||
|
|
159f1ae30e | ||
|
|
e2e626552f | ||
|
|
308d7c62e4 | ||
|
|
0bc78da55d | ||
|
|
6527caea54 | ||
|
|
a52912e35b | ||
|
|
6479382b90 | ||
|
|
4ce36bb12c | ||
|
|
4cc7723984 | ||
|
|
3c3d359d4e | ||
|
|
cccbf3a9d1 | ||
|
|
4a3fd2ee8e | ||
|
|
48d7cb386a | ||
|
|
bdf9cab869 | ||
|
|
be02dabf40 | ||
|
|
c535fb9d24 | ||
|
|
8ab8d09b97 | ||
|
|
286c70d50f | ||
|
|
8939e5b91f | ||
|
|
bc9f7b3bce | ||
|
|
fd0bcb9e5f | ||
|
|
98e0167ef1 | ||
|
|
8091085f45 | ||
|
|
cd5abd1d9c | ||
|
|
2a88f435b9 | ||
|
|
fe1e9c5629 | ||
|
|
0e363ca724 | ||
|
|
c874638bd1 | ||
|
|
e5c3b1ed41 | ||
|
|
8a27b8cc37 | ||
|
|
046fbeab01 | ||
|
|
27ea509989 | ||
|
|
27f0508e6e | ||
|
|
c53fedf7a1 | ||
|
|
0f1a5e9aef | ||
|
|
6cb4b799b7 | ||
|
|
439b9161b5 | ||
|
|
6ffa45f0c1 | ||
|
|
a03ba3e3b3 | ||
|
|
e2a206caa5 | ||
|
|
3a963da819 | ||
|
|
4a65f0a84c | ||
|
|
9688bd3699 | ||
|
|
c123815a55 | ||
|
|
182e669593 | ||
|
|
65533b8d58 | ||
|
|
45185dba70 | ||
|
|
444c4b4434 | ||
|
|
d629d66bf2 | ||
|
|
9d46d68150 | ||
|
|
a4ed6a362e | ||
|
|
a1a0d3cd96 | ||
|
|
950c401e88 | ||
|
|
ce056c9ad2 | ||
|
|
3bd6e454d0 | ||
|
|
f52129a11e | ||
|
|
ea01050163 | ||
|
|
c1ec9b6e99 | ||
|
|
2c509b00ac | ||
|
|
ef358fe741 | ||
|
|
56e0520d9c | ||
|
|
1f7b7f5c41 | ||
|
|
471fa75155 | ||
|
|
c89d16e529 | ||
|
|
fc02ab820a | ||
|
|
ac23cdcc7a | ||
|
|
02c4c5be29 | ||
|
|
3bd7d61e3a | ||
|
|
32ebc69c0e | ||
|
|
c98c3b16c5 | ||
|
|
287fe3adfe | ||
|
|
d4e7b7b371 | ||
|
|
ad78f068e0 | ||
|
|
d156de2e66 | ||
|
|
99bca1bd9b | ||
|
|
8efb22595c | ||
|
|
73e8913f90 | ||
|
|
3ddaf795f2 | ||
|
|
a18df02d37 |
3
.env
3
.env
@@ -23,6 +23,7 @@ POST_REGISTRATION_REDIRECT_URL=''
|
||||
SEARCH_CATALOG_URL=''
|
||||
# ***** Features flags *****
|
||||
DISABLE_ENTERPRISE_LOGIN=''
|
||||
ENABLE_AUTO_GENERATED_USERNAME=''
|
||||
ENABLE_DYNAMIC_REGISTRATION_FIELDS=''
|
||||
ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN=''
|
||||
ENABLE_POST_REGISTRATION_RECOMMENDATIONS=''
|
||||
@@ -40,3 +41,5 @@ BANNER_IMAGE_EXTRA_SMALL=''
|
||||
# ***** Miscellaneous *****
|
||||
APP_ID=''
|
||||
MFE_CONFIG_API_URL=''
|
||||
# Fallback in local style files
|
||||
PARAGON_THEME_URLS={}
|
||||
|
||||
@@ -41,3 +41,5 @@ APP_ID=''
|
||||
MFE_CONFIG_API_URL=''
|
||||
ZENDESK_KEY=''
|
||||
ZENDESK_LOGO_URL=''
|
||||
# Fallback in local style files
|
||||
PARAGON_THEME_URLS={}
|
||||
|
||||
@@ -18,3 +18,4 @@ SEGMENT_KEY=''
|
||||
SITE_NAME='Your Platform Name Here'
|
||||
APP_ID=''
|
||||
MFE_CONFIG_API_URL=''
|
||||
PARAGON_THEME_URLS={}
|
||||
|
||||
1
.github/CODEOWNERS
vendored
Normal file
1
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* @openedx/2U-infinity
|
||||
7
.github/dependabot.yml
vendored
Normal file
7
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
version: 2
|
||||
updates:
|
||||
# Adding new check for github-actions
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
15
.github/workflows/ci.yml
vendored
15
.github/workflows/ci.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/lockfileversion-check.yml
vendored
2
.github/workflows/lockfileversion-check.yml
vendored
@@ -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
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# The following users are the owners of all frontend-app-authn files
|
||||
* @openedx/2u-vanguards
|
||||
* @openedx/2u-infinity
|
||||
|
||||
16
README.rst
16
README.rst
@@ -29,7 +29,13 @@ 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.
|
||||
|
||||
.. _Tutor: https://github.com/overhangio/tutor
|
||||
.. _relevant tutor-mfe documentation: https://github.com/overhangio/tutor-mfe?tab=readme-ov-file#mfe-development
|
||||
|
||||
Devstack (Deprecated) instructions
|
||||
==================================
|
||||
|
||||
1. Install Devstack using the `Getting Started <https://github.com/openedx/devstack#getting-started>`_ instructions.
|
||||
|
||||
@@ -51,7 +57,7 @@ This MFE is bundled with `Devstack <https://github.com/openedx/devstack>`_, see
|
||||
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:
|
||||
|
||||
@@ -142,13 +148,13 @@ Furthermore, there are several edX-specific environment variables that enable in
|
||||
- ``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 +193,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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
31176
package-lock.json
generated
31176
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
58
package.json
58
package.json
@@ -13,15 +13,12 @@
|
||||
"build": "fedx-scripts webpack",
|
||||
"i18n_extract": "fedx-scripts formatjs extract",
|
||||
"lint": "fedx-scripts eslint --ext .js --ext .jsx .",
|
||||
"lint:fix": "fedx-scripts eslint --fix --ext .js --ext .jsx .",
|
||||
"snapshot": "fedx-scripts jest --updateSnapshot",
|
||||
"start": "fedx-scripts webpack-dev-server --progress",
|
||||
"dev": "PUBLIC_PATH=/authn/ MFE_CONFIG_API_URL='http://localhost:8000/api/mfe_config/v1' fedx-scripts webpack-dev-server --progress --host apps.local.openedx.io",
|
||||
"test": "fedx-scripts jest --coverage --passWithNoTests"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "npm run lint"
|
||||
}
|
||||
},
|
||||
"author": "edX",
|
||||
"license": "AGPL-3.0",
|
||||
"homepage": "https://github.com/openedx/frontend-app-authn#readme",
|
||||
@@ -33,53 +30,52 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
|
||||
"@edx/frontend-platform": "7.1.3",
|
||||
"@edx/frontend-platform": "^8.3.1",
|
||||
"@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",
|
||||
"@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",
|
||||
"@openedx/paragon": "^23.4.2",
|
||||
"@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",
|
||||
"@testing-library/react": "^16.2.0",
|
||||
"algoliasearch": "^4.14.3",
|
||||
"algoliasearch-helper": "^3.14.0",
|
||||
"algoliasearch-helper": "^3.26.0",
|
||||
"classnames": "2.5.1",
|
||||
"core-js": "3.36.1",
|
||||
"core-js": "3.43.0",
|
||||
"fastest-levenshtein": "1.0.16",
|
||||
"form-urlencoded": "6.1.4",
|
||||
"form-urlencoded": "6.1.5",
|
||||
"prop-types": "15.8.1",
|
||||
"query-string": "7.1.3",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-helmet": "6.1.0",
|
||||
"react-loading-skeleton": "3.4.0",
|
||||
"react-loading-skeleton": "3.5.0",
|
||||
"react-redux": "7.2.9",
|
||||
"react-responsive": "8.2.0",
|
||||
"react-router": "6.22.3",
|
||||
"react-router-dom": "6.22.3",
|
||||
"react-router": "6.30.1",
|
||||
"react-router-dom": "6.30.1",
|
||||
"react-zendesk": "^0.1.13",
|
||||
"redux": "4.2.0",
|
||||
"redux": "4.2.1",
|
||||
"redux-logger": "3.0.6",
|
||||
"redux-mock-store": "1.5.4",
|
||||
"redux-mock-store": "1.5.5",
|
||||
"redux-saga": "1.3.0",
|
||||
"redux-thunk": "2.4.2",
|
||||
"regenerator-runtime": "0.14.1",
|
||||
"reselect": "4.1.8",
|
||||
"universal-cookie": "4.0.4"
|
||||
"reselect": "5.1.1",
|
||||
"universal-cookie": "7.2.2"
|
||||
},
|
||||
"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",
|
||||
"@openedx/frontend-build": "^14.6.1",
|
||||
"babel-plugin-formatjs": "10.5.39",
|
||||
"eslint-plugin-import": "2.31.0",
|
||||
"glob": "7.2.3",
|
||||
"history": "5.3.0",
|
||||
"husky": "7.0.4",
|
||||
"jest": "29.7.0",
|
||||
"react-test-renderer": "^17.0.2"
|
||||
"jest": "30.0.0",
|
||||
"react-test-renderer": "^18.3.1",
|
||||
"ts-jest": "^29.4.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<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=="
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.4.4/iframeResizer.contentWindow.min.js"
|
||||
integrity="sha512-IWwZFBvHzN41wNI6etRLLuLrDDj/6AwJcPt7cmKJAzluYTIHHQ1PF8wh0rSy05jxEvvjflVvH2MxeV6riyEEXg=="
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer">
|
||||
</script>
|
||||
|
||||
@@ -37,6 +37,7 @@ const ThirdPartyAuth = (props) => {
|
||||
const isSocialAuthActive = !!providers.length && !currentProvider;
|
||||
const isEnterpriseLoginDisabled = getConfig().DISABLE_ENTERPRISE_LOGIN;
|
||||
const enterpriseLoginURL = getConfig().LMS_BASE_URL + ENTERPRISE_LOGIN_URL;
|
||||
const isThirdPartyAuthActive = isSocialAuthActive || (isEnterpriseLoginDisabled && isInstitutionAuthActive);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -61,7 +62,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>
|
||||
|
||||
@@ -5,14 +5,13 @@ import React from 'react';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
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
|
||||
|
||||
@@ -5,14 +5,13 @@ import React from 'react';
|
||||
import { fetchAuthenticatedUser, getAuthenticatedUser } from '@edx/frontend-platform/auth';
|
||||
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';
|
||||
|
||||
import { UnAuthOnlyRoute } from '..';
|
||||
import { REGISTER_PAGE } from '../../data/constants';
|
||||
|
||||
jest.mock('@edx/frontend-platform/auth', () => ({
|
||||
getAuthenticatedUser: jest.fn(),
|
||||
fetchAuthenticatedUser: jest.fn(),
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -5,23 +5,23 @@ exports[`Zendesk Help should match login page third party auth alert message sna
|
||||
cookies={true}
|
||||
defer={true}
|
||||
webWidget={
|
||||
Object {
|
||||
"answerBot": Object {
|
||||
"avatar": Object {
|
||||
"name": Object {
|
||||
{
|
||||
"answerBot": {
|
||||
"avatar": {
|
||||
"name": {
|
||||
"*": "edX Support",
|
||||
},
|
||||
"url": undefined,
|
||||
},
|
||||
"contactOnlyAfterQuery": true,
|
||||
"suppress": false,
|
||||
"title": Object {
|
||||
"title": {
|
||||
"*": "edX Support",
|
||||
},
|
||||
},
|
||||
"chat": Object {
|
||||
"departments": Object {
|
||||
"enabled": Array [
|
||||
"chat": {
|
||||
"departments": {
|
||||
"enabled": [
|
||||
"account settings",
|
||||
"billing and payments",
|
||||
"certificates",
|
||||
@@ -33,17 +33,17 @@ exports[`Zendesk Help should match login page third party auth alert message sna
|
||||
},
|
||||
"suppress": false,
|
||||
},
|
||||
"contactForm": Object {
|
||||
"contactForm": {
|
||||
"attachments": true,
|
||||
"selectTicketForm": Object {
|
||||
"selectTicketForm": {
|
||||
"*": "Please choose your request type:",
|
||||
},
|
||||
"ticketForms": Array [
|
||||
Object {
|
||||
"fields": Array [
|
||||
Object {
|
||||
"ticketForms": [
|
||||
{
|
||||
"fields": [
|
||||
{
|
||||
"id": "description",
|
||||
"prefill": Object {
|
||||
"prefill": {
|
||||
"*": "",
|
||||
},
|
||||
},
|
||||
@@ -53,10 +53,10 @@ exports[`Zendesk Help should match login page third party auth alert message sna
|
||||
},
|
||||
],
|
||||
},
|
||||
"contactOptions": Object {
|
||||
"contactOptions": {
|
||||
"enabled": false,
|
||||
},
|
||||
"helpCenter": Object {
|
||||
"helpCenter": {
|
||||
"originalArticleButton": true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ const configuration = {
|
||||
USER_RETENTION_COOKIE_NAME: process.env.USER_RETENTION_COOKIE_NAME || '',
|
||||
// Features
|
||||
DISABLE_ENTERPRISE_LOGIN: process.env.DISABLE_ENTERPRISE_LOGIN || '',
|
||||
ENABLE_AUTO_GENERATED_USERNAME: process.env.ENABLE_AUTO_GENERATED_USERNAME || false,
|
||||
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,
|
||||
|
||||
@@ -1,27 +1,36 @@
|
||||
import 'core-js/stable';
|
||||
import 'regenerator-runtime/runtime';
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import React, { StrictMode } from 'react';
|
||||
|
||||
import {
|
||||
APP_INIT_ERROR, APP_READY, initialize, mergeConfig, subscribe,
|
||||
} from '@edx/frontend-platform';
|
||||
import { ErrorPage } from '@edx/frontend-platform/react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import configuration from './config';
|
||||
import messages from './i18n';
|
||||
import MainApp from './MainApp';
|
||||
|
||||
subscribe(APP_READY, () => {
|
||||
ReactDOM.render(
|
||||
<MainApp />,
|
||||
document.getElementById('root'),
|
||||
const root = createRoot(document.getElementById('root'));
|
||||
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<MainApp />
|
||||
</StrictMode>,
|
||||
);
|
||||
});
|
||||
|
||||
subscribe(APP_INIT_ERROR, (error) => {
|
||||
ReactDOM.render(<ErrorPage message={error.message} />, document.getElementById('root'));
|
||||
const root = createRoot(document.getElementById('root'));
|
||||
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<ErrorPage message={error.message} />
|
||||
</StrictMode>,
|
||||
);
|
||||
});
|
||||
|
||||
initialize({
|
||||
|
||||
@@ -1,6 +1,2 @@
|
||||
@import "~@edx/brand/paragon/fonts";
|
||||
@import "~@edx/brand/paragon/variables";
|
||||
@import "~@openedx/paragon/scss/core/core";
|
||||
@import "~@edx/brand/paragon/overrides";
|
||||
|
||||
@use "@openedx/paragon/styles/css/core/custom-media-breakpoints" as paragonCustomMediaBreakpoints;
|
||||
@import "sass/style";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import algoliasearchHelper from 'algoliasearch-helper';
|
||||
|
||||
import mockedRecommendedProducts from './mockedData';
|
||||
|
||||
@@ -97,7 +97,7 @@ const CountryField = (props) => {
|
||||
};
|
||||
|
||||
const getCountryList = () => countryList.map((country) => (
|
||||
<FormAutosuggestOption key={country[COUNTRY_CODE_KEY]} id={country[COUNTRY_CODE_KEY]}>
|
||||
<FormAutosuggestOption key={country[COUNTRY_DISPLAY_KEY]} id={country[COUNTRY_CODE_KEY]}>
|
||||
{country[COUNTRY_DISPLAY_KEY]}
|
||||
</FormAutosuggestOption>
|
||||
));
|
||||
|
||||
@@ -60,6 +60,7 @@ const RegistrationPage = (props) => {
|
||||
showConfigurableEdxFields: getConfig().SHOW_CONFIGURABLE_EDX_FIELDS,
|
||||
showConfigurableRegistrationFields: getConfig().ENABLE_DYNAMIC_REGISTRATION_FIELDS,
|
||||
showMarketingEmailOptInCheckbox: getConfig().MARKETING_EMAILS_OPT_IN,
|
||||
autoGeneratedUsernameEnabled: getConfig().ENABLE_AUTO_GENERATED_USERNAME,
|
||||
};
|
||||
const {
|
||||
handleInstitutionLogin,
|
||||
@@ -215,6 +216,9 @@ const RegistrationPage = (props) => {
|
||||
delete payload.password;
|
||||
payload.social_auth_provider = currentProvider;
|
||||
}
|
||||
if (flags.autoGeneratedUsernameEnabled) {
|
||||
delete payload.username;
|
||||
}
|
||||
|
||||
// Validating form data before submitting
|
||||
const { isValid, fieldErrors, emailSuggestion } = isFormValid(
|
||||
@@ -324,16 +328,18 @@ const RegistrationPage = (props) => {
|
||||
helpText={[formatMessage(messages['help.text.email'])]}
|
||||
floatingLabel={formatMessage(messages['registration.email.label'])}
|
||||
/>
|
||||
<UsernameField
|
||||
name="username"
|
||||
spellCheck="false"
|
||||
value={formFields.username}
|
||||
handleChange={handleOnChange}
|
||||
handleErrorChange={handleErrorChange}
|
||||
errorMessage={errors.username}
|
||||
helpText={[formatMessage(messages['help.text.username.1']), formatMessage(messages['help.text.username.2'])]}
|
||||
floatingLabel={formatMessage(messages['registration.username.label'])}
|
||||
/>
|
||||
{!flags.autoGeneratedUsernameEnabled && (
|
||||
<UsernameField
|
||||
name="username"
|
||||
spellCheck="false"
|
||||
value={formFields.username}
|
||||
handleChange={handleOnChange}
|
||||
handleErrorChange={handleErrorChange}
|
||||
errorMessage={errors.username}
|
||||
helpText={[formatMessage(messages['help.text.username.1']), formatMessage(messages['help.text.username.2'])]}
|
||||
floatingLabel={formatMessage(messages['registration.username.label'])}
|
||||
/>
|
||||
)}
|
||||
{!currentProvider && (
|
||||
<PasswordField
|
||||
name="password"
|
||||
|
||||
@@ -134,9 +134,16 @@ describe('RegistrationPage', () => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
const populateRequiredFields = (getByLabelText, payload, isThirdPartyAuth = false) => {
|
||||
const populateRequiredFields = (
|
||||
getByLabelText,
|
||||
payload,
|
||||
isThirdPartyAuth = false,
|
||||
autoGeneratedUsernameEnabled = false,
|
||||
) => {
|
||||
fireEvent.change(getByLabelText('Full name'), { target: { value: payload.name, name: 'name' } });
|
||||
fireEvent.change(getByLabelText('Public username'), { target: { value: payload.username, name: 'username' } });
|
||||
if (!autoGeneratedUsernameEnabled) {
|
||||
fireEvent.change(getByLabelText('Public username'), { target: { value: payload.username, name: 'username' } });
|
||||
}
|
||||
fireEvent.change(getByLabelText('Email'), { target: { value: payload.email, name: 'email' } });
|
||||
|
||||
fireEvent.change(getByLabelText('Country/Region'), { target: { value: payload.country, name: 'country' } });
|
||||
@@ -176,7 +183,7 @@ describe('RegistrationPage', () => {
|
||||
password: 'password1',
|
||||
country: 'Pakistan',
|
||||
honor_code: true,
|
||||
totalRegistrationTime: 0,
|
||||
total_registration_time: 0,
|
||||
next: '/course/demo-course-url',
|
||||
};
|
||||
|
||||
@@ -199,7 +206,7 @@ describe('RegistrationPage', () => {
|
||||
country: 'Pakistan',
|
||||
honor_code: true,
|
||||
social_auth_provider: 'Apple',
|
||||
totalRegistrationTime: 0,
|
||||
total_registration_time: 0,
|
||||
};
|
||||
|
||||
store = mockStore({
|
||||
@@ -232,7 +239,7 @@ describe('RegistrationPage', () => {
|
||||
password: 'password1',
|
||||
country: 'Ukraine',
|
||||
honor_code: true,
|
||||
totalRegistrationTime: 0,
|
||||
total_registration_time: 0,
|
||||
};
|
||||
|
||||
store.dispatch = jest.fn(store.dispatch);
|
||||
@@ -257,7 +264,7 @@ describe('RegistrationPage', () => {
|
||||
password: 'password1',
|
||||
country: 'Ukraine',
|
||||
honor_code: true,
|
||||
totalRegistrationTime: 0,
|
||||
total_registration_time: 0,
|
||||
};
|
||||
|
||||
store.dispatch = jest.fn(store.dispatch);
|
||||
@@ -283,7 +290,7 @@ describe('RegistrationPage', () => {
|
||||
password: 'password1',
|
||||
country: 'Pakistan',
|
||||
honor_code: true,
|
||||
totalRegistrationTime: 0,
|
||||
total_registration_time: 0,
|
||||
marketing_emails_opt_in: true,
|
||||
};
|
||||
|
||||
@@ -299,6 +306,44 @@ describe('RegistrationPage', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should submit form without UsernameField when autoGeneratedUsernameEnabled is true', () => {
|
||||
mergeConfig({
|
||||
ENABLE_AUTO_GENERATED_USERNAME: true,
|
||||
});
|
||||
jest.spyOn(global.Date, 'now').mockImplementation(() => 0);
|
||||
const payload = {
|
||||
name: 'John Doe',
|
||||
email: 'john.doe@gmail.com',
|
||||
password: 'password1',
|
||||
country: 'Pakistan',
|
||||
honor_code: true,
|
||||
total_registration_time: 0,
|
||||
};
|
||||
|
||||
store.dispatch = jest.fn(store.dispatch);
|
||||
const { getByLabelText, container } = render(routerWrapper(reduxWrapper(<IntlRegistrationPage {...props} />)));
|
||||
populateRequiredFields(getByLabelText, payload, false, true);
|
||||
const button = container.querySelector('button.btn-brand');
|
||||
fireEvent.click(button);
|
||||
expect(store.dispatch).toHaveBeenCalledWith(registerNewUser({ ...payload, country: 'PK' }));
|
||||
mergeConfig({
|
||||
ENABLE_AUTO_GENERATED_USERNAME: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not display UsernameField when ENABLE_AUTO_GENERATED_USERNAME is true', () => {
|
||||
mergeConfig({
|
||||
ENABLE_AUTO_GENERATED_USERNAME: true,
|
||||
});
|
||||
|
||||
const { queryByLabelText } = render(routerWrapper(reduxWrapper(<IntlRegistrationPage {...props} />)));
|
||||
expect(queryByLabelText('Username')).toBeNull();
|
||||
|
||||
mergeConfig({
|
||||
ENABLE_AUTO_GENERATED_USERNAME: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not dispatch registerNewUser on empty form Submission', () => {
|
||||
store.dispatch = jest.fn(store.dispatch);
|
||||
|
||||
@@ -837,7 +882,7 @@ describe('RegistrationPage', () => {
|
||||
email: 'john.doe@example.com',
|
||||
country: 'PK',
|
||||
social_auth_provider: 'Apple',
|
||||
totalRegistrationTime: 0,
|
||||
total_registration_time: 0,
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -33,7 +33,11 @@ const ConfigurableRegistrationForm = (props) => {
|
||||
autoSubmitRegistrationForm,
|
||||
} = props;
|
||||
|
||||
const countryList = useMemo(() => getCountryList(getLocale()), []);
|
||||
/** The reason for adding the entry 'United States' is that Chrome browser aut-fill the form with the 'Unites
|
||||
States' instead of 'United States of America' which does not exist in country dropdown list and gets the user
|
||||
confused and unable to create an account. So we added the United States entry in the dropdown list.
|
||||
*/
|
||||
const countryList = useMemo(() => getCountryList(getLocale()).concat([{ code: 'US', name: 'United States' }]), []);
|
||||
|
||||
let showTermsOfServiceAndHonorCode = false;
|
||||
let showCountryField = false;
|
||||
|
||||
@@ -245,7 +245,7 @@ describe('ConfigurableRegistrationForm', () => {
|
||||
country: 'Pakistan',
|
||||
honor_code: true,
|
||||
profession: 'Engineer',
|
||||
totalRegistrationTime: 0,
|
||||
total_registration_time: 0,
|
||||
};
|
||||
|
||||
store.dispatch = jest.fn(store.dispatch);
|
||||
@@ -356,7 +356,7 @@ describe('ConfigurableRegistrationForm', () => {
|
||||
password: 'password1',
|
||||
country: 'Ukraine',
|
||||
honor_code: true,
|
||||
totalRegistrationTime: 0,
|
||||
total_registration_time: 0,
|
||||
};
|
||||
|
||||
store = mockStore({
|
||||
|
||||
77
src/register/data/tests/utils.test.js
Normal file
77
src/register/data/tests/utils.test.js
Normal file
@@ -0,0 +1,77 @@
|
||||
import { isFormValid } from '../utils';
|
||||
|
||||
describe('Payload validation', () => {
|
||||
let formatMessage;
|
||||
let configurableFormFields;
|
||||
let fieldDescriptions;
|
||||
|
||||
beforeEach(() => {
|
||||
formatMessage = jest.fn(msg => msg);
|
||||
configurableFormFields = {
|
||||
confirm_email: true,
|
||||
};
|
||||
fieldDescriptions = {};
|
||||
});
|
||||
|
||||
test('validates name field correctly', () => {
|
||||
const payload = { name: ' ' };
|
||||
const errors = {};
|
||||
const { isValid, fieldErrors } = isFormValid(
|
||||
payload,
|
||||
errors,
|
||||
configurableFormFields,
|
||||
fieldDescriptions,
|
||||
formatMessage);
|
||||
|
||||
expect(fieldErrors.name).toBeDefined();
|
||||
expect(isValid).toBe(false);
|
||||
});
|
||||
|
||||
test('validates email field correctly', () => {
|
||||
const payload = { email: 'invalid-email' };
|
||||
const errors = {};
|
||||
const { isValid, fieldErrors } = isFormValid(
|
||||
payload, errors, configurableFormFields, fieldDescriptions, formatMessage);
|
||||
|
||||
expect(fieldErrors.email).toBeDefined();
|
||||
expect(isValid).toBe(false);
|
||||
});
|
||||
|
||||
test('validates username field correctly', () => {
|
||||
const payload = { username: 'invalid username' };
|
||||
const errors = {};
|
||||
const { isValid, fieldErrors } = isFormValid(
|
||||
payload, errors, configurableFormFields, fieldDescriptions, formatMessage);
|
||||
|
||||
expect(fieldErrors.username).toBeDefined();
|
||||
expect(isValid).toBe(false);
|
||||
});
|
||||
|
||||
test('validates password field correctly', () => {
|
||||
const payload = { password: 'short' };
|
||||
const errors = {};
|
||||
const { isValid, fieldErrors } = isFormValid(
|
||||
payload, errors, configurableFormFields, fieldDescriptions, formatMessage);
|
||||
|
||||
expect(fieldErrors.password).toBeDefined();
|
||||
expect(isValid).toBe(false);
|
||||
});
|
||||
|
||||
test('validates multiple fields correctly', () => {
|
||||
const payload = {
|
||||
name: 'InvalidName!',
|
||||
email: 'invalid-email',
|
||||
username: 'invalid username',
|
||||
password: 'short',
|
||||
};
|
||||
const errors = {};
|
||||
const { isValid, fieldErrors } = isFormValid(
|
||||
payload, errors, configurableFormFields, fieldDescriptions, formatMessage);
|
||||
|
||||
expect(fieldErrors.name).toBeDefined();
|
||||
expect(fieldErrors.email).toBeDefined();
|
||||
expect(fieldErrors.username).toBeDefined();
|
||||
expect(fieldErrors.password).toBeDefined();
|
||||
expect(isValid).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -43,30 +43,39 @@ export const isFormValid = (
|
||||
Object.keys(payload).forEach(key => {
|
||||
switch (key) {
|
||||
case 'name':
|
||||
fieldErrors.name = validateName(payload.name, formatMessage);
|
||||
if (!fieldErrors.name) {
|
||||
fieldErrors.name = validateName(payload.name, formatMessage);
|
||||
}
|
||||
if (fieldErrors.name) { isValid = false; }
|
||||
break;
|
||||
case 'email': {
|
||||
const {
|
||||
fieldError, confirmEmailError, suggestion,
|
||||
} = validateEmail(payload.email, configurableFormFields?.confirm_email, formatMessage);
|
||||
if (fieldError) {
|
||||
fieldErrors.email = fieldError;
|
||||
isValid = false;
|
||||
if (!fieldErrors.email) {
|
||||
const {
|
||||
fieldError, confirmEmailError, suggestion,
|
||||
} = validateEmail(payload.email, configurableFormFields?.confirm_email, formatMessage);
|
||||
if (fieldError) {
|
||||
fieldErrors.email = fieldError;
|
||||
isValid = false;
|
||||
}
|
||||
if (confirmEmailError) {
|
||||
fieldErrors.confirm_email = confirmEmailError;
|
||||
isValid = false;
|
||||
}
|
||||
emailSuggestion = suggestion;
|
||||
}
|
||||
if (confirmEmailError) {
|
||||
fieldErrors.confirm_email = confirmEmailError;
|
||||
isValid = false;
|
||||
}
|
||||
emailSuggestion = suggestion;
|
||||
if (fieldErrors.email) { isValid = false; }
|
||||
break;
|
||||
}
|
||||
case 'username':
|
||||
fieldErrors.username = validateUsername(payload.username, formatMessage);
|
||||
if (!fieldErrors.username) {
|
||||
fieldErrors.username = validateUsername(payload.username, formatMessage);
|
||||
}
|
||||
if (fieldErrors.username) { isValid = false; }
|
||||
break;
|
||||
case 'password':
|
||||
fieldErrors.password = validatePasswordField(payload.password, formatMessage);
|
||||
if (!fieldErrors.password) {
|
||||
fieldErrors.password = validatePasswordField(payload.password, formatMessage);
|
||||
}
|
||||
if (fieldErrors.password) { isValid = false; }
|
||||
break;
|
||||
default:
|
||||
@@ -125,8 +134,8 @@ export const prepareRegistrationPayload = (
|
||||
delete payload.marketingEmailsOptIn;
|
||||
}
|
||||
|
||||
payload = snakeCaseObject(payload);
|
||||
payload.totalRegistrationTime = totalRegistrationTime;
|
||||
payload = snakeCaseObject(payload);
|
||||
|
||||
// add query params to the payload
|
||||
payload = { ...payload, ...queryParams };
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
.layout {
|
||||
display: flex;
|
||||
|
||||
@include media-breakpoint-down('lg') {
|
||||
@media (--pgn-size-breakpoint-max-width-lg) {
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up('xl') {
|
||||
@media (--pgn-size-breakpoint-min-width-xl) {
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
@include media-breakpoint-up('xl') {
|
||||
@media (--pgn-size-breakpoint-min-width-xl) {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 50vw;
|
||||
@@ -47,7 +47,7 @@
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
|
||||
@include media-breakpoint-down('xl') {
|
||||
@media (--pgn-size-breakpoint-max-width-xl) {
|
||||
font-size: 3.75rem;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 700;
|
||||
|
||||
@include media-breakpoint-down('xl') {
|
||||
@media (-pgn-size-breakpoint-max-width-xl) {
|
||||
font-size: 1.375rem;
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
@@ -72,7 +72,7 @@
|
||||
}
|
||||
|
||||
.large-screen-left-container {
|
||||
@include media-breakpoint-down('xl') {
|
||||
@media (-pgn-size-breakpoint-max-width-xl) {
|
||||
flex: 0 0 25%;
|
||||
max-width: 25%;
|
||||
}
|
||||
@@ -87,43 +87,43 @@
|
||||
height: 0.25rem;
|
||||
background-image: linear-gradient(
|
||||
102.02deg,
|
||||
$brand-700,
|
||||
$brand-700 20%,
|
||||
$brand 20%,
|
||||
var(--pgn-color-brand-700),
|
||||
var(--pgn-color-brand-700) 20%,
|
||||
var(--pgn-color-brand-base) 20%,
|
||||
);
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
@include media-breakpoint-only('md') {
|
||||
@media (--pgn-size-breakpoint-min-width-md) and (--pgn-size-breakpoint-max-width-md) {
|
||||
.medium-screen-top-stripe {
|
||||
display: flex;
|
||||
height: 0.5rem;
|
||||
background-image: linear-gradient(
|
||||
102.02deg,
|
||||
$brand-700,
|
||||
$brand-700 10%,
|
||||
$brand 10%,
|
||||
$brand 90%,
|
||||
$primary-700 90%,
|
||||
$primary-700 100%,
|
||||
var(--pgn-color-brand-700),
|
||||
var(--pgn-color-brand-700) 10%,
|
||||
var(--pgn-color-brand-base) 10%,
|
||||
var(--pgn-color-brand-base) 90%,
|
||||
var(--pgn-color-primary-700) 90%,
|
||||
var(--pgn-color-primary-700) 100%,
|
||||
);
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-only('lg') {
|
||||
@media (--pgn-size-breakpoint-min-width-lg) and (--pgn-size-breakpoint-max-width-lg){
|
||||
.medium-screen-top-stripe {
|
||||
display: flex;
|
||||
height: 0.5rem;
|
||||
background-image: linear-gradient(
|
||||
102.02deg,
|
||||
$brand-700 10%,
|
||||
$brand 10%,
|
||||
$brand 65%,
|
||||
$primary-700 65%,
|
||||
$primary-700 75%,
|
||||
$accent-a 75%,
|
||||
$accent-a 75%
|
||||
var(--pgn-color-brand-700) 10%,
|
||||
var(--pgn-color-brand-base) 10%,
|
||||
var(--pgn-color-brand-base) 65%,
|
||||
var(--pgn-color-primary-700) 65%,
|
||||
var(--pgn-color-primary-700) 75%,
|
||||
var(--pgn-color-accent-a) 75%,
|
||||
var(--pgn-color-accent-a) 75%
|
||||
);
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
@@ -131,20 +131,20 @@
|
||||
|
||||
.extra-large-screen-top-stripe { display: none; }
|
||||
|
||||
@include media-breakpoint-up('xl') {
|
||||
@media (--pgn-size-breakpoint-min-width-xl) {
|
||||
.extra-large-screen-top-stripe {
|
||||
display: flex;
|
||||
height: 0.5rem;
|
||||
background-image: linear-gradient(
|
||||
102.02deg,
|
||||
$brand-700 10%,
|
||||
$brand 10%,
|
||||
$brand 45%,
|
||||
$primary-700 45%,
|
||||
$primary-700 55%,
|
||||
$accent-a 55%,
|
||||
$accent-a 75%,
|
||||
$info-200 75%,
|
||||
var(--pgn-color-brand-700) 10%,
|
||||
var(--pgn-color-brand-base) 10%,
|
||||
var(--pgn-color-brand-base) 45%,
|
||||
var(--pgn-color-primary-700) 45%,
|
||||
var(--pgn-color-primary-700) 55%,
|
||||
var(--pgn-color-accent-a) 55%,
|
||||
var(--pgn-color-accent-a) 75%,
|
||||
var(--pgn-color-info-200) 75%,
|
||||
);
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
@@ -152,24 +152,24 @@
|
||||
|
||||
.large-screen-svg-light,
|
||||
.large-screen-svg-primary {
|
||||
fill: $light-200;
|
||||
fill: var(--pgn-color-light-200);
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.large-screen-svg-primary {
|
||||
fill: $primary-400;
|
||||
fill: var(--pgn-color-primary-400);
|
||||
}
|
||||
|
||||
.medium-screen-svg-light,
|
||||
.medium-screen-svg-primary {
|
||||
fill: $light-200;
|
||||
fill: var(--pgn-color-light-200);
|
||||
overflow: inherit;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.medium-screen-svg-primary {
|
||||
fill: $primary-400;
|
||||
fill: var(--pgn-color-primary-400);
|
||||
}
|
||||
|
||||
[dir=rtl]{
|
||||
@@ -184,20 +184,20 @@
|
||||
.small-yellow-line {
|
||||
width: 80px;
|
||||
height: 0;
|
||||
border: 2px solid $accent-b;
|
||||
border: 2px solid var(--pgn-color-accent-b);
|
||||
transform: rotate(102.02deg);
|
||||
}
|
||||
|
||||
.medium-yellow-line {
|
||||
width: 120px;
|
||||
height: 0;
|
||||
border: 3px solid $accent-b;
|
||||
border: 3px solid var(--pgn-color-accent-b);
|
||||
transform: rotate(102.02deg);
|
||||
}
|
||||
|
||||
.large-yellow-line {
|
||||
width: 240px;
|
||||
height: 0;
|
||||
border: 3px solid $accent-b;
|
||||
border: 3px solid var(--pgn-color-accent-b);
|
||||
transform: rotate(102.02deg);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 700;
|
||||
|
||||
@include media-breakpoint-down('md') {
|
||||
@media (--pgn-size-breakpoint-max-width-md) {
|
||||
line-height: 1.5rem;
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
@@ -64,52 +64,52 @@ $header-height: 104px;
|
||||
}
|
||||
|
||||
&.light {
|
||||
background-color: $white;
|
||||
background-color: var(--pgn-color-white);
|
||||
|
||||
.title {
|
||||
color: $black;
|
||||
color: var(--pgn-color-black);
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: $gray-700;
|
||||
color: var(--pgn-color-gray-700);
|
||||
}
|
||||
|
||||
.badge {
|
||||
background-color: $light-500;
|
||||
color: $black;
|
||||
background-color: var(--pgn-color-light-500);
|
||||
color: var(--pgn-color-black);
|
||||
}
|
||||
|
||||
.footer-content {
|
||||
color: $gray-700;
|
||||
color: var(--pgn-color-gray-700);
|
||||
}
|
||||
}
|
||||
|
||||
&.dark {
|
||||
background-color: $primary-500;
|
||||
background-color: var(--pgn-color-primary-500);
|
||||
|
||||
.pgn__card-header-title-md {
|
||||
color: $white;
|
||||
color: var(--pgn-color-white);
|
||||
}
|
||||
|
||||
.pgn__card-header-subtitle-md {
|
||||
color: $light-200;
|
||||
color: var(--pgn-color-light-200);
|
||||
}
|
||||
|
||||
.title {
|
||||
color: $white;
|
||||
color: var(--pgn-color-white);
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: $light-200;
|
||||
color: var(--pgn-color-light-200);
|
||||
}
|
||||
|
||||
.badge {
|
||||
background-color: $dark-200;
|
||||
color: $white;
|
||||
background-color: var(--pgn-color-dark-200);
|
||||
color: var(--pgn-color-white);
|
||||
}
|
||||
|
||||
.footer-content {
|
||||
color: $light-200;
|
||||
color: var(--pgn-color-light-200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ $card-gap: 24px;
|
||||
.recommendations-container__card-list {
|
||||
gap: $card-gap $card-gap;
|
||||
|
||||
@include media-breakpoint-down(sm) {
|
||||
@media (-pgn-size-breakpoint-max-width-sm) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
@@ -11,15 +11,15 @@ $card-gap: 24px;
|
||||
flex: 0 1 100%;
|
||||
cursor: pointer;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
@media (--pgn-size-breakpoint-min-width-sm) {
|
||||
flex: 0 1 calc(50% - #{$card-gap - 12});
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
@media (--pgn-size-breakpoint-min-width-md) {
|
||||
flex: 0 1 calc(33.333% - #{$card-gap - 8});
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
@media (--pgn-size-breakpoint-min-width-lg) {
|
||||
flex: 0 1 calc(25% - #{$card-gap - 6});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,21 +23,21 @@
|
||||
}
|
||||
|
||||
.alert-link {
|
||||
color: $primary !important;
|
||||
color: var(--pgn-color-primary-base) !important;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
color: $info-700 !important;
|
||||
color: var(--pgn-color-info-700) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.email-suggestion-alert-warning {
|
||||
color: $info-500 !important;
|
||||
color: var(--pgn-color-info-500) !important;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
color: $info-700 !important;
|
||||
color: var(--pgn-color-info-700) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
line-height: 24px;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
color: $primary-700;
|
||||
color: var(--pgn-color-primary-700);
|
||||
}
|
||||
|
||||
.username-suggestion--label {
|
||||
@@ -99,7 +99,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: map-get($grid-breakpoints, "sm")) {
|
||||
@media (--pgn-size-breakpoint-max-width-sm) {
|
||||
.username-scroll-suggested--form-field {
|
||||
width: 15rem;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ $elevation-level-2-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.main-content {
|
||||
@extend .pt-4;
|
||||
padding-top: calc(var(--pgn-spacing-spacer-base) * 1.5) !important;
|
||||
min-width: 464px !important;
|
||||
}
|
||||
|
||||
@@ -80,15 +80,15 @@ $elevation-level-2-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.15);
|
||||
.alert-link {
|
||||
font-weight: normal;
|
||||
text-decoration: underline;
|
||||
color: $info-300 !important;
|
||||
color: var(--pgn-color-info-300) !important;
|
||||
|
||||
&:hover {
|
||||
color: $info-500 !important;
|
||||
color: var(--pgn-color-info-500) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.form-control {
|
||||
background-color: $white !important;
|
||||
background-color: var(--pgn-color-white) !important;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5;
|
||||
height: 2.75rem;
|
||||
@@ -103,11 +103,11 @@ $elevation-level-2-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.15);
|
||||
margin-bottom: 1rem;
|
||||
font-size: 14px;
|
||||
|
||||
background-color: $white;
|
||||
border: 1px solid $primary;
|
||||
background-color: var(--pgn-color-white);
|
||||
border: 1px solid var(--pgn-color-primary-base);
|
||||
width: 224px;
|
||||
height: 36px;
|
||||
color: $primary;
|
||||
color: var(--pgn-color-primary-base);
|
||||
|
||||
.btn-tpa__image-icon{
|
||||
background-color: transparent;
|
||||
@@ -132,8 +132,8 @@ $elevation-level-2-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.btn-tpa__font-container {
|
||||
background-color: $primary;
|
||||
color: $white;
|
||||
background-color: var(--pgn-color-primary-base);
|
||||
color: var(--pgn-color-white);
|
||||
font-size: 11px;
|
||||
|
||||
margin-left: -6px;
|
||||
@@ -143,7 +143,7 @@ $elevation-level-2-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.btn-oa2-facebook {
|
||||
color: $white;
|
||||
color: var(--pgn-color-white);
|
||||
border-color: $facebook-blue;
|
||||
background-color: $facebook-blue;
|
||||
|
||||
@@ -151,12 +151,12 @@ $elevation-level-2-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.15);
|
||||
&:focus {
|
||||
background-color: $facebook-focus-blue;
|
||||
border: 1px solid $facebook-focus-blue;
|
||||
color: $white;
|
||||
color: var(--pgn-color-white);
|
||||
}
|
||||
}
|
||||
|
||||
.btn-oa2-google-oauth2 {
|
||||
color: $white;
|
||||
color: var(--pgn-color-white);
|
||||
border-color: $google-blue;
|
||||
background-color: $google-blue;
|
||||
|
||||
@@ -171,12 +171,12 @@ $elevation-level-2-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.15);
|
||||
&:focus {
|
||||
background-color: $google-focus-blue;
|
||||
border: 1px solid $google-focus-blue;
|
||||
color: $white;
|
||||
color: var(--pgn-color-white);
|
||||
}
|
||||
}
|
||||
|
||||
.btn-oa2-apple-id {
|
||||
color: $white;
|
||||
color: var(--pgn-color-white);
|
||||
border-color: $apple-black;
|
||||
background-color: $apple-black;
|
||||
font-size: 16px;
|
||||
@@ -190,12 +190,12 @@ $elevation-level-2-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.15);
|
||||
&:focus {
|
||||
background-color: $apple-focus-black;
|
||||
border: 1px solid $apple-focus-black;
|
||||
color: $white;
|
||||
color: var(--pgn-color-white);
|
||||
}
|
||||
}
|
||||
|
||||
.btn-oa2-azuread-oauth2 {
|
||||
color: $white;
|
||||
color: var(--pgn-color-white);
|
||||
border-color: $microsoft-black;
|
||||
background-color: $microsoft-black;
|
||||
|
||||
@@ -203,7 +203,7 @@ $elevation-level-2-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.15);
|
||||
&:focus {
|
||||
background-color: $microsoft-focus-black;
|
||||
border: 1px solid $microsoft-focus-black;
|
||||
color: $white;
|
||||
color: var(--pgn-color-white);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,9 +214,8 @@ $elevation-level-2-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.institute-icon {
|
||||
@extend .mr-1;
|
||||
@extend .text-gray;
|
||||
|
||||
margin: calc(var(--pgn-spacing-spacer-base) * 0.25) !important;
|
||||
color: var(--pgn-color-gray-base) !important;
|
||||
display: inline-block;
|
||||
margin-bottom: 0.25rem;
|
||||
height: 18px;
|
||||
@@ -232,7 +231,7 @@ $elevation-level-2-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.invalid-feedback {
|
||||
color: $red;
|
||||
color: var(--pgn-color-red);
|
||||
}
|
||||
|
||||
.full-vertical-height {
|
||||
@@ -290,22 +289,22 @@ select.form-control {
|
||||
|
||||
#password-requirement-left {
|
||||
opacity: 1;
|
||||
@extend .x-small;
|
||||
font-size: var(--pgn-typography-font-size-xs) !important;
|
||||
filter: drop-shadow($elevation-level-2-shadow) drop-shadow($elevation-level-2-shadow) !important;
|
||||
right: 0.2rem !important;
|
||||
.tooltip-inner {
|
||||
background: $white;
|
||||
background: var(--pgn-color-white);
|
||||
display: block;
|
||||
color: $gray-500;
|
||||
color: var(--pgn-color-gray-500);
|
||||
}
|
||||
.arrow::before {
|
||||
border-left-color: $white;
|
||||
border-left-color: var(--pgn-color-white);
|
||||
}
|
||||
}
|
||||
|
||||
#password-requirement-top {
|
||||
@extend .x-small;
|
||||
filter: drop-shadow($elevation-level-2-shadow) drop-shadow($elevation-level-2-shadow) !important;
|
||||
font-size: var(--pgn-typography-font-size-xs) !important;
|
||||
filter: drop-shadow(var(--pgn-elevation-box-shadow-level-2)) drop-shadow(var(--pgn-elevation-box-shadow-level-2)) !important;
|
||||
opacity: 1;
|
||||
width: 90%;
|
||||
bottom: 10px !important;
|
||||
@@ -314,30 +313,30 @@ select.form-control {
|
||||
|
||||
.tooltip-inner {
|
||||
min-width: 464px !important;
|
||||
background: $white;
|
||||
background: var(--pgn-color-white);
|
||||
display: block;
|
||||
color: $gray-500;
|
||||
color: var(--pgn-color-gray-500);
|
||||
}
|
||||
.arrow::before {
|
||||
border-top-color: $white;
|
||||
border-top-color: var(--pgn-color-white);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.yellow-border {
|
||||
border: 2px solid $accent-b;
|
||||
border: 2px solid var(--pgn-color-accent-b);
|
||||
}
|
||||
|
||||
.institutions__heading {
|
||||
color: $primary-700;
|
||||
color: var(--pgn-color-primary-700);
|
||||
}
|
||||
|
||||
.logistration-button {
|
||||
color: $gray-700;
|
||||
color: var(--pgn-color-gray-700);
|
||||
}
|
||||
|
||||
.logistration-button:hover{
|
||||
color: $gray-700;
|
||||
color: var(--pgn-color-gray-700);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -352,7 +351,7 @@ select.form-control {
|
||||
width: 2.3rem;
|
||||
}
|
||||
.has-floating-label {
|
||||
color: $gray-500;
|
||||
color: var(--pgn-color-gray-500);
|
||||
}
|
||||
|
||||
.pgn__form-control-floating-label .pgn__form-control-floating-label-content {
|
||||
@@ -366,7 +365,7 @@ select.form-control {
|
||||
|
||||
.form-group__form-field .form-control:focus ~ .pgn__form-control-floating-label .pgn__form-control-floating-label-content {
|
||||
font-size: 16px;
|
||||
color: $primary-700;
|
||||
color: var(--pgn-color-primary-700);
|
||||
}
|
||||
|
||||
.form-group__form-field .form-control:not([value='']):not(:focus) ~
|
||||
@@ -444,14 +443,14 @@ select.form-control {
|
||||
}
|
||||
|
||||
.table-striped tbody tr:nth-of-type(odd) {
|
||||
background-color: $light-200;
|
||||
background-color: var(--pgn-color-light-200);
|
||||
}
|
||||
|
||||
.institutions--provider-link {
|
||||
font-weight: normal;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5rem;
|
||||
color: $primary-700
|
||||
color: var(--pgn-color-primary-700)
|
||||
}
|
||||
|
||||
.pgn__form-control-decorator-trailing {
|
||||
|
||||
Reference in New Issue
Block a user