diff --git a/package-lock.json b/package-lock.json
index 4926a8f9c..a0a3f295c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,7 @@
"dependencies": {
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
"@edx/browserslist-config": "^1.1.0",
+ "@edx/frontend-component-header": "^5.3.1",
"@edx/frontend-enterprise-hotjar": "3.0.0",
"@edx/frontend-platform": "^7.1.4",
"@edx/openedx-atlas": "^0.6.0",
@@ -2136,19 +2137,6 @@
"node": ">=6"
}
},
- "node_modules/@edx/frontend-component-footer/node_modules/@fortawesome/free-regular-svg-icons": {
- "version": "6.5.2",
- "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.2.tgz",
- "integrity": "sha512-iabw/f5f8Uy2nTRtJ13XZTS1O5+t+anvlamJ3zJGLEVE2pKsAWhPv2lq01uQlfgCX7VaveT3EVs515cCN9jRbw==",
- "hasInstallScript": true,
- "peer": true,
- "dependencies": {
- "@fortawesome/fontawesome-common-types": "6.5.2"
- },
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/@edx/frontend-component-footer/node_modules/@fortawesome/free-solid-svg-icons": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz",
@@ -2815,6 +2803,491 @@
"node": ">=12"
}
},
+ "node_modules/@edx/frontend-component-header": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/@edx/frontend-component-header/-/frontend-component-header-5.3.1.tgz",
+ "integrity": "sha512-hhraVbtmdaXSgaZZJOuEPeQNi5YXJwOfmoCdLsmh6WiTdGG5BusiFoF4SRyKKiTZuayhPFKGFFC8D0AwRxmKhg==",
+ "license": "AGPL-3.0",
+ "dependencies": {
+ "@fortawesome/fontawesome-svg-core": "6.5.2",
+ "@fortawesome/free-brands-svg-icons": "6.5.2",
+ "@fortawesome/free-regular-svg-icons": "6.5.2",
+ "@fortawesome/free-solid-svg-icons": "6.5.2",
+ "@fortawesome/react-fontawesome": "^0.2.0",
+ "axios-mock-adapter": "1.22.0",
+ "babel-polyfill": "6.26.0",
+ "jest-environment-jsdom": "^29.7.0",
+ "react-responsive": "8.2.0",
+ "react-transition-group": "4.4.5"
+ },
+ "peerDependencies": {
+ "@edx/frontend-platform": "^7.0.0 || ^8.0.0",
+ "@openedx/paragon": ">= 21.5.7 < 23.0.0",
+ "prop-types": "^15.5.10",
+ "react": "^16.9.0 || ^17.0.0",
+ "react-dom": "^16.9.0 || ^17.0.0"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/@fortawesome/fontawesome-common-types": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz",
+ "integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/@fortawesome/fontawesome-svg-core": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.2.tgz",
+ "integrity": "sha512-5CdaCBGl8Rh9ohNdxeeTMxIj8oc3KNBgIeLMvJosBMdslK/UnEB8rzyDRrbKdL1kDweqBPo4GT9wvnakHWucZw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "6.5.2"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/@fortawesome/free-brands-svg-icons": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.5.2.tgz",
+ "integrity": "sha512-zi5FNYdmKLnEc0jc0uuHH17kz/hfYTg4Uei0wMGzcoCL/4d3WM3u1VMc0iGGa31HuhV5i7ZK8ZlTCQrHqRHSGQ==",
+ "hasInstallScript": true,
+ "license": "(CC-BY-4.0 AND MIT)",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "6.5.2"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/@fortawesome/free-solid-svg-icons": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz",
+ "integrity": "sha512-QWFZYXFE7O1Gr1dTIp+D6UcFUF0qElOnZptpi7PBUMylJh+vFmIedVe1Ir6RM1t2tEQLLSV1k7bR4o92M+uqlw==",
+ "hasInstallScript": true,
+ "license": "(CC-BY-4.0 AND MIT)",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "6.5.2"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/@tootallnate/once": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
+ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/acorn-globals": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz",
+ "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.1.0",
+ "acorn-walk": "^8.0.2"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/acorn-walk": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
+ "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.11.0"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/cssom": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz",
+ "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==",
+ "license": "MIT"
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/data-urls": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz",
+ "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==",
+ "license": "MIT",
+ "dependencies": {
+ "abab": "^2.0.6",
+ "whatwg-mimetype": "^3.0.0",
+ "whatwg-url": "^11.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/domexception": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz",
+ "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==",
+ "deprecated": "Use your platform's native DOMException instead",
+ "license": "MIT",
+ "dependencies": {
+ "webidl-conversions": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/html-encoding-sniffer": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
+ "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==",
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-encoding": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/http-proxy-agent": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
+ "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
+ "license": "MIT",
+ "dependencies": {
+ "@tootallnate/once": "2",
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/jest-environment-jsdom": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz",
+ "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/jsdom": "^20.0.0",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jsdom": "^20.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "canvas": "^2.5.0"
+ },
+ "peerDependenciesMeta": {
+ "canvas": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/jsdom": {
+ "version": "20.0.3",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz",
+ "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==",
+ "license": "MIT",
+ "dependencies": {
+ "abab": "^2.0.6",
+ "acorn": "^8.8.1",
+ "acorn-globals": "^7.0.0",
+ "cssom": "^0.5.0",
+ "cssstyle": "^2.3.0",
+ "data-urls": "^3.0.2",
+ "decimal.js": "^10.4.2",
+ "domexception": "^4.0.0",
+ "escodegen": "^2.0.0",
+ "form-data": "^4.0.0",
+ "html-encoding-sniffer": "^3.0.0",
+ "http-proxy-agent": "^5.0.0",
+ "https-proxy-agent": "^5.0.1",
+ "is-potential-custom-element-name": "^1.0.1",
+ "nwsapi": "^2.2.2",
+ "parse5": "^7.1.1",
+ "saxes": "^6.0.0",
+ "symbol-tree": "^3.2.4",
+ "tough-cookie": "^4.1.2",
+ "w3c-xmlserializer": "^4.0.0",
+ "webidl-conversions": "^7.0.0",
+ "whatwg-encoding": "^2.0.0",
+ "whatwg-mimetype": "^3.0.0",
+ "whatwg-url": "^11.0.0",
+ "ws": "^8.11.0",
+ "xml-name-validator": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "canvas": "^2.5.0"
+ },
+ "peerDependenciesMeta": {
+ "canvas": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/parse5": {
+ "version": "7.2.1",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz",
+ "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==",
+ "license": "MIT",
+ "dependencies": {
+ "entities": "^4.5.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/saxes": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
+ "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
+ "license": "ISC",
+ "dependencies": {
+ "xmlchars": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=v12.22.7"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/tr46": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
+ "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
+ "license": "MIT",
+ "dependencies": {
+ "punycode": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/w3c-xmlserializer": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
+ "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==",
+ "license": "MIT",
+ "dependencies": {
+ "xml-name-validator": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/webidl-conversions": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/whatwg-encoding": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
+ "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==",
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "0.6.3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/whatwg-mimetype": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz",
+ "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/whatwg-url": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
+ "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "^3.0.0",
+ "webidl-conversions": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/ws": {
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz",
+ "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@edx/frontend-component-header/node_modules/xml-name-validator": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
+ "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/@edx/frontend-enterprise-hotjar": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@edx/frontend-enterprise-hotjar/-/frontend-enterprise-hotjar-3.0.0.tgz",
@@ -3712,6 +4185,29 @@
"node": ">=6"
}
},
+ "node_modules/@fortawesome/free-regular-svg-icons": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.2.tgz",
+ "integrity": "sha512-iabw/f5f8Uy2nTRtJ13XZTS1O5+t+anvlamJ3zJGLEVE2pKsAWhPv2lq01uQlfgCX7VaveT3EVs515cCN9jRbw==",
+ "hasInstallScript": true,
+ "license": "(CC-BY-4.0 AND MIT)",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "6.5.2"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/free-regular-svg-icons/node_modules/@fortawesome/fontawesome-common-types": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz",
+ "integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@fortawesome/free-solid-svg-icons": {
"version": "5.15.4",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz",
@@ -8736,7 +9232,6 @@
"version": "20.0.1",
"resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz",
"integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==",
- "peer": true,
"dependencies": {
"@types/node": "*",
"@types/tough-cookie": "*",
@@ -8747,7 +9242,6 @@
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
"integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
- "peer": true,
"dependencies": {
"entities": "^4.4.0"
},
@@ -8929,8 +9423,7 @@
"node_modules/@types/tough-cookie": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
- "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
- "peer": true
+ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="
},
"node_modules/@types/warning": {
"version": "3.0.0",
@@ -9380,9 +9873,10 @@
}
},
"node_modules/acorn": {
- "version": "8.10.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
- "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
+ "version": "8.14.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
+ "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
+ "license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
@@ -9975,7 +10469,6 @@
"version": "1.22.0",
"resolved": "https://registry.npmjs.org/axios-mock-adapter/-/axios-mock-adapter-1.22.0.tgz",
"integrity": "sha512-dmI0KbkyAhntUR05YY96qg2H6gg0XMl2+qTW0xmYg6Up+BFBAJYRLROMXRdDEL06/Wqwa0TJThAYvFtSFdRCZw==",
- "dev": true,
"dependencies": {
"fast-deep-equal": "^3.1.3",
"is-buffer": "^2.0.5"
@@ -16786,7 +17279,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
"integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
- "dev": true,
"funding": [
{
"type": "github",
diff --git a/package.json b/package.json
index 6c4004783..a52ef237d 100755
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
"dependencies": {
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
"@edx/browserslist-config": "^1.1.0",
+ "@edx/frontend-component-header": "^5.3.1",
"@edx/frontend-enterprise-hotjar": "3.0.0",
"@edx/frontend-platform": "^7.1.4",
"@edx/openedx-atlas": "^0.6.0",
diff --git a/src/App.scss b/src/App.scss
index eed6b145a..9092d14c0 100755
--- a/src/App.scss
+++ b/src/App.scss
@@ -9,6 +9,7 @@ $fa-font-path: "~font-awesome/fonts";
$input-focus-box-shadow: $input-box-shadow; // hack to get upgrade to paragon 4.0.0 to work
+@import "~@edx/frontend-component-header/dist/index";
@import "~@edx/frontend-component-footer/dist/_footer";
.text-ellipsis {
@@ -36,19 +37,6 @@ $input-focus-box-shadow: $input-box-shadow; // hack to get upgrade to paragon 4.
header {
flex: 0 0 auto;
-
- .logo {
- display: block;
- box-sizing: content-box;
- position: relative;
- top: 0.1em;
- height: 1.75rem;
- margin-right: 1rem;
- img {
- display: block;
- height: 100%;
- }
- }
}
footer {
diff --git a/src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.jsx b/src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.jsx
deleted file mode 100644
index 82de5aaf5..000000000
--- a/src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.jsx
+++ /dev/null
@@ -1,104 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-
-import { getConfig } from '@edx/frontend-platform';
-import { useIntl } from '@edx/frontend-platform/i18n';
-import { AppContext } from '@edx/frontend-platform/react';
-import { Button, Badge } from '@openedx/paragon';
-
-import urls from 'data/services/lms/urls';
-import { reduxHooks } from 'hooks';
-
-import { findCoursesNavDropdownClicked } from '../hooks';
-import messages from '../messages';
-
-export const CollapseMenuBody = ({ isOpen }) => {
- const { formatMessage } = useIntl();
- const { authenticatedUser } = React.useContext(AppContext);
-
- const dashboard = reduxHooks.useEnterpriseDashboardData();
- const { courseSearchUrl } = reduxHooks.usePlatformSettingsData();
-
- const exploreCoursesClick = findCoursesNavDropdownClicked(
- urls.baseAppUrl(courseSearchUrl),
- );
-
- if (!isOpen) {
- return null;
- }
-
- return (
-
-
-
-
-
- {authenticatedUser && (
- <>
- {!!dashboard && (
-
- )}
- {!dashboard && getConfig().CAREER_LINK_URL && (
-
- )}
-
-
- {getConfig().ORDER_HISTORY_URL && (
-
- )}
-
- >
- )}
-
- );
-};
-
-CollapseMenuBody.propTypes = {
- isOpen: PropTypes.bool.isRequired,
-};
-
-export default CollapseMenuBody;
diff --git a/src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.test.jsx b/src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.test.jsx
deleted file mode 100644
index 2af8ae7e6..000000000
--- a/src/containers/LearnerDashboardHeader/CollapsedHeader/CollapseMenuBody.test.jsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import { shallow } from '@edx/react-unit-test-utils';
-import { AppContext } from '@edx/frontend-platform/react';
-
-import CollapseMenuBody from './CollapseMenuBody';
-
-jest.mock('@edx/frontend-platform/react', () => ({
- AppContext: {
- authenticatedUser: {
- username: 'username',
- },
- },
-}));
-
-jest.mock('hooks', () => ({
- reduxHooks: {
- useEnterpriseDashboardData: () => ({
- url: 'url',
- }),
- usePlatformSettingsData: () => ({
- courseSearchUrl: '/courseSearchUrl',
- }),
- },
-}));
-
-jest.mock('../hooks', () => ({
- findCoursesNavDropdownClicked: (url) => jest.fn().mockName(`findCoursesNavDropdownClicked("${url}")`),
-}));
-
-describe('CollapseMenuBody', () => {
- test('render', () => {
- const wrapper = shallow();
- expect(wrapper.snapshot).toMatchSnapshot();
- });
-
- test('render empty if not open', () => {
- const wrapper = shallow();
- expect(wrapper.snapshot).toMatchSnapshot();
- expect(wrapper.isEmptyRender()).toBe(true);
- });
-
- test('render unauthenticated', () => {
- const { authenticatedUser } = AppContext;
- AppContext.authenticatedUser = null;
- const wrapper = shallow();
- expect(wrapper.snapshot).toMatchSnapshot();
- AppContext.authenticatedUser = authenticatedUser;
- });
-});
diff --git a/src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/CollapseMenuBody.test.jsx.snap b/src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/CollapseMenuBody.test.jsx.snap
deleted file mode 100644
index c8cc4de83..000000000
--- a/src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/CollapseMenuBody.test.jsx.snap
+++ /dev/null
@@ -1,105 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`CollapseMenuBody render 1`] = `
-
-
-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`CollapseMenuBody render empty if not open 1`] = `null`;
-
-exports[`CollapseMenuBody render unauthenticated 1`] = `
-
-
-
-
-
-
-`;
diff --git a/src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/index.test.jsx.snap b/src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/index.test.jsx.snap
deleted file mode 100644
index 2a1dc7bc4..000000000
--- a/src/containers/LearnerDashboardHeader/CollapsedHeader/__snapshots__/index.test.jsx.snap
+++ /dev/null
@@ -1,48 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`CollapsedHeader render nothing if not collapsed 1`] = `false`;
-
-exports[`CollapsedHeader renders 1`] = `
-
-
-
-
-`;
-
-exports[`CollapsedHeader renders with isOpen true 1`] = `
-
-
-
-
-`;
diff --git a/src/containers/LearnerDashboardHeader/CollapsedHeader/index.jsx b/src/containers/LearnerDashboardHeader/CollapsedHeader/index.jsx
deleted file mode 100644
index 5cf9762bc..000000000
--- a/src/containers/LearnerDashboardHeader/CollapsedHeader/index.jsx
+++ /dev/null
@@ -1,47 +0,0 @@
-import React from 'react';
-
-import { useIntl } from '@edx/frontend-platform/i18n';
-import { MenuIcon, Close } from '@openedx/paragon/icons';
-import { IconButton, Icon } from '@openedx/paragon';
-
-import { useLearnerDashboardHeaderData, useIsCollapsed } from '../hooks';
-
-import CollapseMenuBody from './CollapseMenuBody';
-import BrandLogo from '../BrandLogo';
-
-import messages from '../messages';
-
-export const CollapsedHeader = () => {
- const { formatMessage } = useIntl();
- const isCollapsed = useIsCollapsed();
- const { isOpen, toggleIsOpen } = useLearnerDashboardHeaderData();
-
- return (
- isCollapsed && (
- <>
-
-
- >
- )
- );
-};
-
-CollapsedHeader.propTypes = {};
-
-export default CollapsedHeader;
diff --git a/src/containers/LearnerDashboardHeader/CollapsedHeader/index.test.jsx b/src/containers/LearnerDashboardHeader/CollapsedHeader/index.test.jsx
deleted file mode 100644
index c21e98ccd..000000000
--- a/src/containers/LearnerDashboardHeader/CollapsedHeader/index.test.jsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import { shallow } from '@edx/react-unit-test-utils';
-
-import CollapsedHeader from '.';
-
-import { useLearnerDashboardHeaderData, useIsCollapsed } from '../hooks';
-
-jest.mock('../BrandLogo', () => jest.fn(() => 'BrandLogo'));
-jest.mock('./CollapseMenuBody', () => jest.fn(() => 'CollapseMenuBody'));
-
-jest.mock('../hooks', () => ({
- useIsCollapsed: jest.fn(() => true),
- useLearnerDashboardHeaderData: jest.fn(() => ({
- isOpen: false,
- toggleIsOpen: jest.fn().mockName('toggleIsOpen'),
- })),
-}));
-
-describe('CollapsedHeader', () => {
- it('renders', () => {
- const wrapper = shallow();
- expect(wrapper.snapshot).toMatchSnapshot();
- });
-
- it('render nothing if not collapsed', () => {
- useIsCollapsed.mockReturnValueOnce(false);
- const wrapper = shallow();
- expect(wrapper.snapshot).toMatchSnapshot();
- });
-
- it('renders with isOpen true', () => {
- useLearnerDashboardHeaderData.mockReturnValueOnce({
- isOpen: true,
- toggleIsOpen: jest.fn().mockName('toggleIsOpen'),
- });
- const wrapper = shallow();
- expect(wrapper.snapshot).toMatchSnapshot();
- });
-});
diff --git a/src/containers/LearnerDashboardHeader/ExpandedHeader/AuthenticatedUserDropdown.jsx b/src/containers/LearnerDashboardHeader/ExpandedHeader/AuthenticatedUserDropdown.jsx
deleted file mode 100644
index e0751bb38..000000000
--- a/src/containers/LearnerDashboardHeader/ExpandedHeader/AuthenticatedUserDropdown.jsx
+++ /dev/null
@@ -1,78 +0,0 @@
-import React from 'react';
-
-import { getConfig } from '@edx/frontend-platform';
-import { useIntl } from '@edx/frontend-platform/i18n';
-import { AppContext } from '@edx/frontend-platform/react';
-import { AvatarButton, Dropdown, Badge } from '@openedx/paragon';
-
-import { reduxHooks } from 'hooks';
-
-import messages from '../messages';
-
-export const AuthenticatedUserDropdown = () => {
- const { formatMessage } = useIntl();
- const { authenticatedUser } = React.useContext(AppContext);
- const dashboard = reduxHooks.useEnterpriseDashboardData();
-
- return (
- authenticatedUser && (
-
-
-
- {authenticatedUser.username}
-
-
-
- { getConfig().ENABLE_EDX_PERSONAL_DASHBOARD && (
- <>
- {formatMessage(messages.dashboardSwitch)}
-
- {formatMessage(messages.dashboardPersonal)}
-
- {!!dashboard && (
-
- {dashboard.label} {formatMessage(messages.dashboard)}
-
- )}
-
- >
- )}
-
- {!dashboard && getConfig().CAREER_LINK_URL && (
-
- {formatMessage(messages.career)}
-
- {formatMessage(messages.newAlert)}
-
-
- )}
-
- {formatMessage(messages.profile)}
-
-
- {formatMessage(messages.account)}
-
- {getConfig().ORDER_HISTORY_URL && (
-
- {formatMessage(messages.orderHistory)}
-
- )}
-
-
- {formatMessage(messages.signOut)}
-
-
-
- )
- );
-};
-
-AuthenticatedUserDropdown.propTypes = {};
-
-export default AuthenticatedUserDropdown;
diff --git a/src/containers/LearnerDashboardHeader/ExpandedHeader/AuthenticatedUserDropdown.test.jsx b/src/containers/LearnerDashboardHeader/ExpandedHeader/AuthenticatedUserDropdown.test.jsx
deleted file mode 100644
index e7452d355..000000000
--- a/src/containers/LearnerDashboardHeader/ExpandedHeader/AuthenticatedUserDropdown.test.jsx
+++ /dev/null
@@ -1,81 +0,0 @@
-import { shallow } from '@edx/react-unit-test-utils';
-
-import { reduxHooks } from 'hooks';
-import { getConfig } from '@edx/frontend-platform';
-import { AppContext } from '@edx/frontend-platform/react';
-import { AuthenticatedUserDropdown } from './AuthenticatedUserDropdown';
-import { useIsCollapsed } from '../hooks';
-
-jest.mock('@edx/frontend-platform', () => ({
- getConfig: jest.fn(),
-}));
-
-jest.mock('@edx/frontend-platform/react', () => ({
- AppContext: {
- authenticatedUser: {
- profileImage: 'profileImage',
- username: 'username',
- },
- },
-}));
-const COURSE_SEARCH_URL = 'test-course-search-url';
-
-jest.mock('hooks', () => ({
- reduxHooks: {
- useEnterpriseDashboardData: jest.fn(),
- usePlatformSettingsData: jest.fn(() => ({
- courseSearchUrl: COURSE_SEARCH_URL,
- })),
- },
-}));
-jest.mock('../hooks', () => ({
- useIsCollapsed: jest.fn(),
- findCoursesNavDropdownClicked: (href) => jest.fn().mockName(`findCoursesNavDropdownClicked('${href}')`),
-}));
-
-jest.mock('data/services/lms/urls', () => ({
- baseAppUrl: (url) => (url),
- programsUrl: 'http://localhost:18000/dashboard/programs',
-}));
-
-const config = {
- ACCOUNT_PROFILE_URL: 'http://account-profile-url.test',
- ACCOUNT_SETTINGS_URL: 'http://account-settings-url.test',
- LOGOUT_URL: 'http://logout-url.test',
- ORDER_HISTORY_URL: 'http://order-history-url.test',
- SUPPORT_URL: 'http://localhost:18000/support',
- CAREER_LINK_URL: 'http://localhost:18000/career',
- LMS_BASE_URL: 'http:/localhost:18000',
- ENABLE_EDX_PERSONAL_DASHBOARD: true,
-};
-getConfig.mockReturnValue(config);
-
-describe('AuthenticatedUserDropdown', () => {
- const defaultDashboardData = {
- label: 'label',
- url: 'url',
- };
-
- describe('snapshots', () => {
- test('no auth render empty', () => {
- const { authenticatedUser } = AppContext;
- AppContext.authenticatedUser = null;
- const wrapper = shallow();
- expect(wrapper.snapshot).toMatchSnapshot();
- expect(wrapper.isEmptyRender()).toBe(true);
- AppContext.authenticatedUser = authenticatedUser;
- });
- test('with enterprise dashboard', () => {
- reduxHooks.useEnterpriseDashboardData.mockReturnValueOnce(defaultDashboardData);
- useIsCollapsed.mockReturnValueOnce(true);
- const wrapper = shallow();
- expect(wrapper.snapshot).toMatchSnapshot();
- });
- test('without enterprise dashboard and expanded', () => {
- reduxHooks.useEnterpriseDashboardData.mockReturnValueOnce(null);
- useIsCollapsed.mockReturnValueOnce(false);
- const wrapper = shallow();
- expect(wrapper.snapshot).toMatchSnapshot();
- });
- });
-});
diff --git a/src/containers/LearnerDashboardHeader/ExpandedHeader/__snapshots__/AuthenticatedUserDropdown.test.jsx.snap b/src/containers/LearnerDashboardHeader/ExpandedHeader/__snapshots__/AuthenticatedUserDropdown.test.jsx.snap
deleted file mode 100644
index eafdef3ce..000000000
--- a/src/containers/LearnerDashboardHeader/ExpandedHeader/__snapshots__/AuthenticatedUserDropdown.test.jsx.snap
+++ /dev/null
@@ -1,139 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`AuthenticatedUserDropdown snapshots no auth render empty 1`] = `null`;
-
-exports[`AuthenticatedUserDropdown snapshots with enterprise dashboard 1`] = `
-
-
-
- username
-
-
-
-
-
- SWITCH DASHBOARD
-
-
- Personal
-
-
- label
-
- Dashboard
-
-
-
-
- Profile
-
-
- Account
-
-
- Order History
-
-
-
- Sign Out
-
-
-
-`;
-
-exports[`AuthenticatedUserDropdown snapshots without enterprise dashboard and expanded 1`] = `
-
-
-
- username
-
-
-
-
-
- SWITCH DASHBOARD
-
-
- Personal
-
-
-
-
- Career
-
- New
-
-
-
- Profile
-
-
- Account
-
-
- Order History
-
-
-
- Sign Out
-
-
-
-`;
diff --git a/src/containers/LearnerDashboardHeader/ExpandedHeader/__snapshots__/index.test.jsx.snap b/src/containers/LearnerDashboardHeader/ExpandedHeader/__snapshots__/index.test.jsx.snap
deleted file mode 100644
index 44e08f166..000000000
--- a/src/containers/LearnerDashboardHeader/ExpandedHeader/__snapshots__/index.test.jsx.snap
+++ /dev/null
@@ -1,52 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`ExpandedHeader render 1`] = `
-
-`;
-
-exports[`ExpandedHeader render empty if collapsed 1`] = `null`;
diff --git a/src/containers/LearnerDashboardHeader/ExpandedHeader/index.jsx b/src/containers/LearnerDashboardHeader/ExpandedHeader/index.jsx
deleted file mode 100644
index f257cbc57..000000000
--- a/src/containers/LearnerDashboardHeader/ExpandedHeader/index.jsx
+++ /dev/null
@@ -1,76 +0,0 @@
-import React from 'react';
-
-import { getConfig } from '@edx/frontend-platform';
-import { useIntl } from '@edx/frontend-platform/i18n';
-import { Button } from '@openedx/paragon';
-
-import urls from 'data/services/lms/urls';
-import { reduxHooks } from 'hooks';
-
-import AuthenticatedUserDropdown from './AuthenticatedUserDropdown';
-import { useIsCollapsed, findCoursesNavClicked } from '../hooks';
-import messages from '../messages';
-import BrandLogo from '../BrandLogo';
-
-export const ExpandedHeader = () => {
- const { formatMessage } = useIntl();
- const { courseSearchUrl } = reduxHooks.usePlatformSettingsData();
- const isCollapsed = useIsCollapsed();
-
- const exploreCoursesClick = findCoursesNavClicked(
- urls.baseAppUrl(courseSearchUrl),
- );
-
- if (isCollapsed) {
- return null;
- }
-
- return (
-
- );
-};
-
-ExpandedHeader.propTypes = {};
-
-export default ExpandedHeader;
diff --git a/src/containers/LearnerDashboardHeader/ExpandedHeader/index.test.jsx b/src/containers/LearnerDashboardHeader/ExpandedHeader/index.test.jsx
deleted file mode 100644
index 3b96a1dbf..000000000
--- a/src/containers/LearnerDashboardHeader/ExpandedHeader/index.test.jsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import { shallow } from '@edx/react-unit-test-utils';
-
-import ExpandedHeader from '.';
-
-import { useIsCollapsed } from '../hooks';
-
-jest.mock('data/services/lms/urls', () => ({
- programsUrl: () => 'programsUrl',
- baseAppUrl: url => (`http://localhost:18000${url}`),
-}));
-
-jest.mock('hooks', () => ({
- reduxHooks: {
- usePlatformSettingsData: () => ({
- courseSearchUrl: '/courseSearchUrl',
- }),
- },
-}));
-
-jest.mock('../hooks', () => ({
- useIsCollapsed: jest.fn(),
- findCoursesNavClicked: (url) => jest.fn().mockName(`findCoursesNavClicked("${url}")`),
-}));
-
-jest.mock('./AuthenticatedUserDropdown', () => 'AuthenticatedUserDropdown');
-jest.mock('../BrandLogo', () => 'BrandLogo');
-
-describe('ExpandedHeader', () => {
- test('render', () => {
- useIsCollapsed.mockReturnValueOnce(false);
- const wrapper = shallow();
- expect(wrapper.snapshot).toMatchSnapshot();
- });
-
- test('render empty if collapsed', () => {
- useIsCollapsed.mockReturnValueOnce(true);
- const wrapper = shallow();
- expect(wrapper.snapshot).toMatchSnapshot();
- expect(wrapper.isEmptyRender()).toBe(true);
- });
-});
diff --git a/src/containers/LearnerDashboardHeader/LearnerDashboardMenu.jsx b/src/containers/LearnerDashboardHeader/LearnerDashboardMenu.jsx
new file mode 100644
index 000000000..9dcecc3a1
--- /dev/null
+++ b/src/containers/LearnerDashboardHeader/LearnerDashboardMenu.jsx
@@ -0,0 +1,75 @@
+import { getConfig } from '@edx/frontend-platform';
+
+import urls from 'data/services/lms/urls';
+
+import messages from './messages';
+
+const getLearnerHeaderMenu = (
+ formatMessage,
+ courseSearchUrl,
+ authenticatedUser,
+ exploreCoursesClick,
+) => ({
+ mainMenu: [
+ {
+ type: 'item',
+ href: '/',
+ content: formatMessage(messages.course),
+ isActive: true,
+ },
+ {
+ type: 'item',
+ href: `${urls.programsUrl()}`,
+ content: formatMessage(messages.program),
+ },
+ {
+ type: 'item',
+ href: `${urls.baseAppUrl(courseSearchUrl)}`,
+ content: formatMessage(messages.discoverNew),
+ onClick: (e) => {
+ exploreCoursesClick(e);
+ },
+ },
+ ],
+ secondaryMenu: [
+ {
+ type: 'item',
+ href: `${getConfig().SUPPORT_URL}`,
+ content: formatMessage(messages.help),
+ },
+ ],
+ userMenu: [
+ {
+ heading: '',
+ items: [
+ {
+ type: 'item',
+ href: `${getConfig().ACCOUNT_PROFILE_URL}/u/${authenticatedUser?.username}`,
+ content: formatMessage(messages.profile),
+ },
+ {
+ type: 'item',
+ href: `${getConfig().ACCOUNT_SETTINGS_URL}`,
+ content: formatMessage(messages.account),
+ },
+ ...(getConfig().ORDER_HISTORY_URL ? [{
+ type: 'item',
+ href: getConfig().ORDER_HISTORY_URL,
+ content: formatMessage(messages.orderHistory),
+ }] : []),
+ ],
+ },
+ {
+ heading: '',
+ items: [
+ {
+ type: 'item',
+ href: `${getConfig().LOGOUT_URL}`,
+ content: formatMessage(messages.signOut),
+ },
+ ],
+ },
+ ],
+});
+
+export default getLearnerHeaderMenu;
diff --git a/src/containers/LearnerDashboardHeader/__snapshots__/index.test.jsx.snap b/src/containers/LearnerDashboardHeader/__snapshots__/index.test.jsx.snap
index 87ec64c7d..2b7fed432 100644
--- a/src/containers/LearnerDashboardHeader/__snapshots__/index.test.jsx.snap
+++ b/src/containers/LearnerDashboardHeader/__snapshots__/index.test.jsx.snap
@@ -3,8 +3,72 @@
exports[`LearnerDashboardHeader render 1`] = `
-
-
+
`;
diff --git a/src/containers/LearnerDashboardHeader/hooks.js b/src/containers/LearnerDashboardHeader/hooks.js
index 7eee8437d..115322c1d 100644
--- a/src/containers/LearnerDashboardHeader/hooks.js
+++ b/src/containers/LearnerDashboardHeader/hooks.js
@@ -1,9 +1,12 @@
import React from 'react';
import { useWindowSize, breakpoints } from '@openedx/paragon';
+import { useIntl } from '@edx/frontend-platform/i18n';
import track from 'tracking';
import { StrictDict } from 'utils';
import { linkNames } from 'tracking/constants';
+import getLearnerHeaderMenu from './LearnerDashboardMenu';
+
import * as module from './hooks';
export const state = StrictDict({
@@ -24,6 +27,13 @@ export const findCoursesNavDropdownClicked = (href) => track.findCourses.findCou
linkName: linkNames.learnerHomeNavDropdownExplore,
});
+export const useLearnerDashboardHeaderMenu = ({
+ courseSearchUrl, authenticatedUser, exploreCoursesClick,
+}) => {
+ const { formatMessage } = useIntl();
+ return getLearnerHeaderMenu(formatMessage, courseSearchUrl, authenticatedUser, exploreCoursesClick);
+};
+
export const useLearnerDashboardHeaderData = () => {
const [isOpen, setIsOpen] = module.state.isOpen(false);
const toggleIsOpen = () => setIsOpen(!isOpen);
@@ -39,4 +49,5 @@ export default {
findCoursesNavClicked,
findCoursesNavDropdownClicked,
useLearnerDashboardHeaderData,
+ useLearnerDashboardHeaderMenu,
};
diff --git a/src/containers/LearnerDashboardHeader/hooks.test.js b/src/containers/LearnerDashboardHeader/hooks.test.js
index 72349f6e2..c9bac080a 100644
--- a/src/containers/LearnerDashboardHeader/hooks.test.js
+++ b/src/containers/LearnerDashboardHeader/hooks.test.js
@@ -13,6 +13,7 @@ const {
findCoursesNavClicked,
findCoursesNavDropdownClicked,
useLearnerDashboardHeaderData,
+ useLearnerDashboardHeaderMenu,
} = hooks;
jest.mock('tracking', () => ({
@@ -48,6 +49,17 @@ describe('LearnerDashboardHeader hooks', () => {
});
});
+ describe('getLearnerDashboardHeaderMenu', () => {
+ test('calls header menu data hook', () => {
+ const courseSearchUrl = '/courses';
+ const authenticatedUser = {
+ username: 'test',
+ };
+ const learnerHomeHeaderMenu = useLearnerDashboardHeaderMenu({ courseSearchUrl, authenticatedUser });
+ expect(learnerHomeHeaderMenu.mainMenu.length).toBe(3);
+ });
+ });
+
describe('findCoursesNavDropdownClicked', () => {
test('calls tracking with dropdown link name', () => {
findCoursesNavDropdownClicked(url);
diff --git a/src/containers/LearnerDashboardHeader/index.jsx b/src/containers/LearnerDashboardHeader/index.jsx
index dfa8dbfb0..84f79e5fb 100644
--- a/src/containers/LearnerDashboardHeader/index.jsx
+++ b/src/containers/LearnerDashboardHeader/index.jsx
@@ -1,21 +1,41 @@
import React from 'react';
import MasqueradeBar from 'containers/MasqueradeBar';
+import { AppContext } from '@edx/frontend-platform/react';
+import Header from '@edx/frontend-component-header';
+import { reduxHooks } from 'hooks';
+import urls from 'data/services/lms/urls';
+
import ConfirmEmailBanner from './ConfirmEmailBanner';
-import CollapsedHeader from './CollapsedHeader';
-import ExpandedHeader from './ExpandedHeader';
+import { useLearnerDashboardHeaderMenu, findCoursesNavClicked } from './hooks';
+
+export const LearnerDashboardHeader = () => {
+ const { authenticatedUser } = React.useContext(AppContext);
+ const { courseSearchUrl } = reduxHooks.usePlatformSettingsData();
+
+ const exploreCoursesClick = () => {
+ findCoursesNavClicked(urls.baseAppUrl(courseSearchUrl));
+ };
-import './index.scss';
+ const learnerHomeHeaderMenu = useLearnerDashboardHeaderMenu({
+ courseSearchUrl,
+ authenticatedUser,
+ exploreCoursesClick,
+ });
-export const LearnerDashboardHeader = () => (
- <>
-
-
-
-
- >
-);
+ return (
+ <>
+
+
+
+ >
+ );
+};
LearnerDashboardHeader.propTypes = {};
diff --git a/src/containers/LearnerDashboardHeader/index.scss b/src/containers/LearnerDashboardHeader/index.scss
deleted file mode 100644
index d8bd8da1b..000000000
--- a/src/containers/LearnerDashboardHeader/index.scss
+++ /dev/null
@@ -1,38 +0,0 @@
-.dropdown-menu-collapse {
- width: 100vw;
- position: absolute;
- left: 0;
-}
-
-.learner-variant-header {
- a {
- // needed to make the link not resize the header
- border-bottom: 2px solid transparent;
- }
- .course-link {
- border-bottom: 2px solid !important;
- }
-
- .course-link:hover {
- border-bottom: inherit !important;
- }
-}
-
-.nav-small-menu {
- > * {
- justify-content: flex-start !important;
-
- border-radius: 0 !important;
- border-top: 1px solid #ddd !important;
-
- &::after {
- content: '\00BB';
- padding-left: 10px;
- }
- }
-}
-
-.logo {
- // copy from legacy dashboard
- height: 40px;
-}
diff --git a/src/containers/LearnerDashboardHeader/index.test.jsx b/src/containers/LearnerDashboardHeader/index.test.jsx
index a7335565e..79b7549ef 100644
--- a/src/containers/LearnerDashboardHeader/index.test.jsx
+++ b/src/containers/LearnerDashboardHeader/index.test.jsx
@@ -1,18 +1,36 @@
+import { mergeConfig } from '@edx/frontend-platform';
import { shallow } from '@edx/react-unit-test-utils';
+import Header from '@edx/frontend-component-header';
+
+import urls from 'data/services/lms/urls';
import LearnerDashboardHeader from '.';
+import { findCoursesNavClicked } from './hooks';
+
+jest.mock('hooks', () => ({
+ reduxHooks: {
+ usePlatformSettingsData: jest.fn(() => ({
+ courseSearchUrl: '/course-search-url',
+ })),
+ },
+}));
+jest.mock('./hooks', () => ({
+ ...jest.requireActual('./hooks'),
+ findCoursesNavClicked: jest.fn(),
+}));
jest.mock('containers/MasqueradeBar', () => 'MasqueradeBar');
-jest.mock('./CollapsedHeader', () => 'CollapsedHeader');
jest.mock('./ConfirmEmailBanner', () => 'ConfirmEmailBanner');
-jest.mock('./ExpandedHeader', () => 'ExpandedHeader');
+jest.mock('@edx/frontend-component-header', () => 'Header');
describe('LearnerDashboardHeader', () => {
test('render', () => {
+ mergeConfig({ ORDER_HISTORY_URL: 'test-url' });
const wrapper = shallow();
expect(wrapper.snapshot).toMatchSnapshot();
expect(wrapper.instance.findByType('ConfirmEmailBanner')).toHaveLength(1);
expect(wrapper.instance.findByType('MasqueradeBar')).toHaveLength(1);
- expect(wrapper.instance.findByType('CollapsedHeader')).toHaveLength(1);
- expect(wrapper.instance.findByType('ExpandedHeader')).toHaveLength(1);
+ expect(wrapper.instance.findByType(Header)).toHaveLength(1);
+ wrapper.instance.findByType(Header)[0].props.mainMenuItems[2].onClick();
+ expect(findCoursesNavClicked).toHaveBeenCalledWith(urls.baseAppUrl('/course-search-url'));
});
});
diff --git a/src/containers/LearnerDashboardHeader/messages.js b/src/containers/LearnerDashboardHeader/messages.js
index 08c71cd78..bed227f95 100644
--- a/src/containers/LearnerDashboardHeader/messages.js
+++ b/src/containers/LearnerDashboardHeader/messages.js
@@ -1,21 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
- dashboard: {
- id: 'learnerVariantDashboard.menu.dashboard.label',
- defaultMessage: 'Dashboard',
- description: 'The text for the user menu Dashboard navigation link.',
- },
- dashboardPersonal: {
- id: 'learnerVariantDashboard.menu.dashboardPersonal.label',
- defaultMessage: 'Personal',
- description: 'Link to personal dashboard in user menu',
- },
- dashboardSwitch: {
- id: 'learnerVariantDashboard.menu.dashboardSwitch.label',
- defaultMessage: 'SWITCH DASHBOARD',
- description: 'Switch Dashboard header in the user menu',
- },
help: {
id: 'learnerVariantDashboard.help.label',
defaultMessage: 'Help',
@@ -26,11 +11,6 @@ const messages = defineMessages({
defaultMessage: 'Profile',
description: 'The text for the user menu Profile navigation link.',
},
- viewPrograms: {
- id: 'learnerVariantDashboard.menu.viewPrograms.label',
- defaultMessage: 'View Programs',
- description: 'The text for the user menu View Programs navigation link.',
- },
account: {
id: 'learnerVariantDashboard.menu.account.label',
defaultMessage: 'Account',
@@ -66,26 +46,6 @@ const messages = defineMessages({
defaultMessage: 'edX, Inc. Dashboard',
description: 'Alt text for the edX logo.',
},
- collapseMenuOpenAltText: {
- id: 'learnerVariantDashboard.collapseMenuOpenAltText',
- defaultMessage: 'Menu',
- description: 'Alt text for the collapse menu icon when the menu is open.',
- },
- collapseMenuClosedAltText: {
- id: 'learnerVariantDashboard.collapseMenuClosedAltText',
- defaultMessage: 'Close',
- description: 'Alt text for the collapse menu icon when the menu is closed.',
- },
- career: {
- id: 'leanerDashboard.menu.career.label',
- defaultMessage: 'Career',
- description: 'The text for the user menu Career navigation link.',
- },
- newAlert: {
- id: 'header.menu.new.label',
- defaultMessage: 'New',
- description: 'The text announcing that an item in the user menu is New',
- },
});
export default messages;