diff --git a/.gitignore b/.gitignore index 5f4d4c56..c68a920f 100755 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ .DS_Store .eslintcache -env.config.js +env.config.* node_modules npm-debug.log coverage @@ -26,3 +26,4 @@ module.config.js ### transifex ### src/i18n/transifex_input.json temp +src/i18n/messages \ No newline at end of file diff --git a/.tx/config b/.tx/config deleted file mode 100644 index 09a69859..00000000 --- a/.tx/config +++ /dev/null @@ -1,9 +0,0 @@ -[main] -host = https://www.transifex.com - -[o:open-edx:p:edx-platform:r:frontend-app-learner-dashboard] -file_filter = src/i18n/messages/.json -source_file = src/i18n/transifex_input.json -source_lang = en -type = KEYVALUEJSON - diff --git a/Makefile b/Makefile index 2a631422..e4db73fe 100755 --- a/Makefile +++ b/Makefile @@ -1,8 +1,6 @@ npm-install-%: ## install specified % npm package npm install $* --save-dev git add package.json -export TRANSIFEX_RESOURCE = frontend-app-learner-dashboard -transifex_langs = "ar,fr,fr_CA,es_419,pt_BR,zh_CN" intl_imports = ./node_modules/.bin/intl-imports.js transifex_utils = ./node_modules/.bin/transifex-utils.js @@ -42,23 +40,6 @@ detect_changed_source_translations: # Checking for changed translations... git diff --exit-code $(i18n) -# Pushes translations to Transifex. You must run make extract_translations first. -push_translations: - # Pushing strings to Transifex... - tx push -s - # Fetching hashes from Transifex... - ./node_modules/@edx/reactifex/bash_scripts/get_hashed_strings_v3.sh - # Writing out comments to file... - $(transifex_utils) $(transifex_temp) --comments --v3-scripts-path - # Pushing comments to Transifex... - ./node_modules/@edx/reactifex/bash_scripts/put_comments_v3.sh - -ifeq ($(OPENEDX_ATLAS_PULL),) -# Pulls translations from Transifex. -pull_translations: - tx pull -t -f --mode reviewed --languages=$(transifex_langs) -else -# Experimental: OEP-58 Pulls translations using atlas pull_translations: rm -rf src/i18n/messages mkdir src/i18n/messages @@ -70,7 +51,6 @@ pull_translations: translations/frontend-app-learner-dashboard/src/i18n/messages:frontend-app-learner-dashboard $(intl_imports) frontend-platform paragon frontend-component-footer frontend-app-learner-dashboard -endif # This target is used by CI. validate-no-uncommitted-package-lock-changes: diff --git a/package-lock.json b/package-lock.json index 1ac1dd79..91de9b9e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "@fortawesome/free-brands-svg-icons": "^5.15.4", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.15", + "@openedx/frontend-plugin-framework": "1.0.2", "@openedx/paragon": "^21.11.3", "@optimizely/react-sdk": "^2.9.2", "@redux-beacon/segment": "^1.1.0", @@ -39,6 +40,7 @@ "jest-when": "^3.6.0", "lodash": "^4.17.21", "moment": "^2.29.4", + "patch-package": "^8.0.0", "prop-types": "15.7.2", "query-string": "7.0.1", "react": "^17.0.2", @@ -2168,6 +2170,101 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/@edx/frontend-component-header": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@edx/frontend-component-header/-/frontend-component-header-5.0.2.tgz", + "integrity": "sha512-73fNNc1X/tevb3/hw7+s22T+nPGlW1yXA7zsT9eRzdH7rBxONfp0Jz7yEdeBvTax9a96PaOht45DA6GX9eG4KA==", + "dependencies": { + "@fortawesome/fontawesome-svg-core": "6.5.1", + "@fortawesome/free-brands-svg-icons": "6.5.1", + "@fortawesome/free-regular-svg-icons": "6.5.1", + "@fortawesome/free-solid-svg-icons": "6.5.1", + "@fortawesome/react-fontawesome": "^0.2.0", + "axios-mock-adapter": "1.22.0", + "babel-polyfill": "6.26.0", + "react-responsive": "8.2.0", + "react-transition-group": "4.4.5" + }, + "peerDependencies": { + "@edx/frontend-platform": "^7.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.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.1.tgz", + "integrity": "sha512-GkWzv+L6d2bI5f/Vk6ikJ9xtl7dfXtoRu3YGE6nq0p/FFqA1ebMOAWg3XgRyb0I6LYyYkiAo+3/KrwuBp8xG7A==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@edx/frontend-component-header/node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.1.tgz", + "integrity": "sha512-MfRCYlQPXoLlpem+egxjfkEuP9UQswTrlCOsknus/NcMoblTH2g0jPrapbcIb04KGA7E2GZxbAccGZfWoYgsrQ==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@edx/frontend-component-header/node_modules/@fortawesome/free-brands-svg-icons": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.5.1.tgz", + "integrity": "sha512-093l7DAkx0aEtBq66Sf19MgoZewv1zeY9/4C7vSKPO4qMwEsW/2VYTUTpBtLwfb9T2R73tXaRDPmE4UqLCYHfg==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@edx/frontend-component-header/node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.1.tgz", + "integrity": "sha512-S1PPfU3mIJa59biTtXJz1oI0+KAXW6bkAb31XKhxdxtuXDiUIFsih4JR1v5BbxY7hVHsD1RKq+jRkVRaf773NQ==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@edx/frontend-component-header/node_modules/@fortawesome/react-fontawesome": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", + "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.3" + } + }, + "node_modules/@edx/frontend-component-header/node_modules/@fortawesome/react-fontawesome/node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/@edx/frontend-component-header/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "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", @@ -6478,6 +6575,222 @@ "node": ">=8" } }, + "node_modules/@openedx/frontend-plugin-framework": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@openedx/frontend-plugin-framework/-/frontend-plugin-framework-1.0.2.tgz", + "integrity": "sha512-9KVFtVp14foXuZVzIN7EyXMha9fhbu4SwXBle81HFzuHEpm46+qxtiIOktH6b4TYh74SMzuSphgP30MCHr1P8Q==", + "dependencies": { + "@edx/brand": "npm:@openedx/brand-openedx@^1.2.2", + "@edx/frontend-component-footer": "13.0.3", + "@edx/frontend-component-header": "5.0.2", + "@edx/frontend-platform": "^7.1.0", + "@fortawesome/fontawesome-svg-core": "1.2.36", + "@fortawesome/free-brands-svg-icons": "5.15.4", + "@fortawesome/free-regular-svg-icons": "5.15.4", + "@fortawesome/free-solid-svg-icons": "5.15.4", + "@fortawesome/react-fontawesome": "0.2.0", + "@openedx/paragon": "^21.0.0", + "classnames": "^2.3.2", + "core-js": "3.36.0", + "prop-types": "15.8.1", + "react": "17.0.2", + "react-dom": "17.0.2", + "react-error-boundary": "^4.0.11", + "react-redux": "7.2.9", + "react-router": "6.22.2", + "react-router-dom": "6.22.2", + "redux": "4.2.1", + "regenerator-runtime": "0.14.1" + } + }, + "node_modules/@openedx/frontend-plugin-framework/node_modules/@edx/frontend-component-footer": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/@edx/frontend-component-footer/-/frontend-component-footer-13.0.3.tgz", + "integrity": "sha512-09vX6qC7AcDwG02qhBzKr4x58hpe9FXZrA9ui2cJnsG53pKaNL+wvOSRtDUBNexCf+y/iPg+8RgR+4alkzhZhw==", + "dependencies": { + "@fortawesome/fontawesome-svg-core": "6.5.1", + "@fortawesome/free-brands-svg-icons": "6.5.1", + "@fortawesome/free-regular-svg-icons": "6.5.1", + "@fortawesome/free-solid-svg-icons": "6.5.1", + "@fortawesome/react-fontawesome": "0.2.0", + "lodash": "^4.17.21" + }, + "peerDependencies": { + "@edx/frontend-platform": "^7.0.0", + "@openedx/paragon": ">= 21.11.3 < 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/@openedx/frontend-plugin-framework/node_modules/@edx/frontend-component-footer/node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.1.tgz", + "integrity": "sha512-GkWzv+L6d2bI5f/Vk6ikJ9xtl7dfXtoRu3YGE6nq0p/FFqA1ebMOAWg3XgRyb0I6LYyYkiAo+3/KrwuBp8xG7A==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@openedx/frontend-plugin-framework/node_modules/@edx/frontend-component-footer/node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.1.tgz", + "integrity": "sha512-MfRCYlQPXoLlpem+egxjfkEuP9UQswTrlCOsknus/NcMoblTH2g0jPrapbcIb04KGA7E2GZxbAccGZfWoYgsrQ==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@openedx/frontend-plugin-framework/node_modules/@edx/frontend-component-footer/node_modules/@fortawesome/free-brands-svg-icons": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.5.1.tgz", + "integrity": "sha512-093l7DAkx0aEtBq66Sf19MgoZewv1zeY9/4C7vSKPO4qMwEsW/2VYTUTpBtLwfb9T2R73tXaRDPmE4UqLCYHfg==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@openedx/frontend-plugin-framework/node_modules/@edx/frontend-component-footer/node_modules/@fortawesome/free-regular-svg-icons": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.1.tgz", + "integrity": "sha512-m6ShXn+wvqEU69wSP84coxLbNl7sGVZb+Ca+XZq6k30SzuP3X4TfPqtycgUh9ASwlNh5OfQCd8pDIWxl+O+LlQ==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@openedx/frontend-plugin-framework/node_modules/@edx/frontend-component-footer/node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.1.tgz", + "integrity": "sha512-S1PPfU3mIJa59biTtXJz1oI0+KAXW6bkAb31XKhxdxtuXDiUIFsih4JR1v5BbxY7hVHsD1RKq+jRkVRaf773NQ==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@openedx/frontend-plugin-framework/node_modules/@fortawesome/free-regular-svg-icons": { + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.4.tgz", + "integrity": "sha512-9VNNnU3CXHy9XednJ3wzQp6SwNwT3XaM26oS4Rp391GsxVYA+0oDR2J194YCIWf7jNRCYKjUCOduxdceLrx+xw==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "^0.2.36" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@openedx/frontend-plugin-framework/node_modules/@fortawesome/react-fontawesome": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", + "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.3" + } + }, + "node_modules/@openedx/frontend-plugin-framework/node_modules/@remix-run/router": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.2.tgz", + "integrity": "sha512-+Rnav+CaoTE5QJc4Jcwh5toUpnVLKYbpU6Ys0zqbakqbaLQHeglLVHPfxOiQqdNmUy5C2lXz5dwC6tQNX2JW2Q==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@openedx/frontend-plugin-framework/node_modules/core-js": { + "version": "3.36.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.36.0.tgz", + "integrity": "sha512-mt7+TUBbTFg5+GngsAxeKBTl5/VS0guFeJacYge9OmHb+m058UwwIm41SE9T4Den7ClatV57B6TYTuJ0CX1MAw==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/@openedx/frontend-plugin-framework/node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/@openedx/frontend-plugin-framework/node_modules/react-error-boundary": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.13.tgz", + "integrity": "sha512-b6PwbdSv8XeOSYvjt8LpgpKrZ0yGdtZokYwkwV2wlcZbxgopHX/hgPl5VgpnoVOWd868n1hktM8Qm4b+02MiLQ==", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, + "node_modules/@openedx/frontend-plugin-framework/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/@openedx/frontend-plugin-framework/node_modules/react-router": { + "version": "6.22.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.2.tgz", + "integrity": "sha512-YD3Dzprzpcq+tBMHBS822tCjnWD3iIZbTeSXMY9LPSG541EfoBGyZ3bS25KEnaZjLcmQpw2AVLkFyfgXY8uvcw==", + "dependencies": { + "@remix-run/router": "1.15.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/@openedx/frontend-plugin-framework/node_modules/react-router-dom": { + "version": "6.22.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.2.tgz", + "integrity": "sha512-WgqxD2qySEIBPZ3w0sHH+PUAiamDeszls9tzqMPBDA1YYVucTBXLU7+gtRfcSnhe92A3glPnvSxK2dhNoAVOIQ==", + "dependencies": { + "@remix-run/router": "1.15.2", + "react-router": "6.22.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/@openedx/frontend-plugin-framework/node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "node_modules/@openedx/frontend-plugin-framework/node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, "node_modules/@openedx/paragon": { "version": "21.12.3", "resolved": "https://registry.npmjs.org/@openedx/paragon/-/paragon-21.12.3.tgz", @@ -8451,6 +8764,11 @@ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==" + }, "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", @@ -9027,10 +9345,9 @@ } }, "node_modules/axios-mock-adapter": { - "version": "1.21.5", - "resolved": "https://registry.npmjs.org/axios-mock-adapter/-/axios-mock-adapter-1.21.5.tgz", - "integrity": "sha512-5NI1V/VK+8+JeTF8niqOowuysA4b8mGzdlMN/QnTnoXbYh4HZSNiopsDclN2g/m85+G++IrEtUdZaQ3GnaMsSA==", - "dev": true, + "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==", "dependencies": { "fast-deep-equal": "^3.1.3", "is-buffer": "^2.0.5" @@ -13659,6 +13976,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "dependencies": { + "micromatch": "^4.0.2" + } + }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -15556,7 +15881,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", @@ -20730,6 +21054,14 @@ "node": ">=0.10.0" } }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -24832,7 +25164,6 @@ "version": "7.4.2", "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "dev": true, "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" @@ -25148,6 +25479,154 @@ "node": ">=0.10.0" } }, + "node_modules/patch-package": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz", + "integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==", + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^4.1.2", + "ci-info": "^3.7.0", + "cross-spawn": "^7.0.3", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^9.0.0", + "json-stable-stringify": "^1.0.2", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.6", + "open": "^7.4.2", + "rimraf": "^2.6.3", + "semver": "^7.5.3", + "slash": "^2.0.0", + "tmp": "^0.0.33", + "yaml": "^2.2.2" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "node": ">=14", + "npm": ">5" + } + }, + "node_modules/patch-package/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==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/patch-package/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/patch-package/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" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/patch-package/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==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/patch-package/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==" + }, + "node_modules/patch-package/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/patch-package/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/patch-package/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/patch-package/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==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/patch-package/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/patch-package/node_modules/yaml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", diff --git a/package.json b/package.json index 1d8623dc..6705b2f6 100755 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@edx/frontend-platform": "7.1.0", "@edx/openedx-atlas": "^0.6.0", "@edx/react-unit-test-utils": "2.0.0", + "@openedx/frontend-plugin-framework": "1.0.2", "@fortawesome/fontawesome-svg-core": "^1.2.36", "@fortawesome/free-brands-svg-icons": "^5.15.4", "@fortawesome/free-solid-svg-icons": "^5.15.4", @@ -56,6 +57,7 @@ "jest-when": "^3.6.0", "lodash": "^4.17.21", "moment": "^2.29.4", + "patch-package": "^8.0.0", "prop-types": "15.7.2", "query-string": "7.0.1", "react": "^17.0.2", diff --git a/patches/@openedx+frontend-build+13.0.28.patch b/patches/@openedx+frontend-build+13.0.28.patch new file mode 100644 index 00000000..679f8732 --- /dev/null +++ b/patches/@openedx+frontend-build+13.0.28.patch @@ -0,0 +1,58 @@ +diff --git a/node_modules/@openedx/frontend-build/config/jest.config.js b/node_modules/@openedx/frontend-build/config/jest.config.js +index ac5f730..ddce396 100644 +--- a/node_modules/@openedx/frontend-build/config/jest.config.js ++++ b/node_modules/@openedx/frontend-build/config/jest.config.js +@@ -3,11 +3,16 @@ const fs = require('fs'); + + const presets = require('../lib/presets'); + ++// This assigns the envConfigPath filepath based on whether env.config exists, otherwise it uses the fallback filepath. ++ + let envConfigPath = path.resolve(__dirname, './jest/fallback.env.config.js'); +-const appEnvConfigPath = path.resolve(process.cwd(), './env.config.js'); ++const appEnvConfigPathJs = path.resolve(process.cwd(), './env.config.js'); ++const appEnvConfigPathJsx = path.resolve(process.cwd(), './env.config.jsx'); + +-if (fs.existsSync(appEnvConfigPath)) { +- envConfigPath = appEnvConfigPath; ++if (fs.existsSync(appEnvConfigPathJs)) { ++ envConfigPath = appEnvConfigPathJs; ++} else if (fs.existsSync(appEnvConfigPathJsx)) { ++ envConfigPath = appEnvConfigPathJsx; + } + + module.exports = { +diff --git a/node_modules/@openedx/frontend-build/config/webpack.prod.config.js b/node_modules/@openedx/frontend-build/config/webpack.prod.config.js +index 2879dd9..dd819bc 100644 +--- a/node_modules/@openedx/frontend-build/config/webpack.prod.config.js ++++ b/node_modules/@openedx/frontend-build/config/webpack.prod.config.js +@@ -11,6 +11,7 @@ const dotenv = require('dotenv'); + const NewRelicSourceMapPlugin = require('@edx/new-relic-source-map-webpack-plugin'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const MiniCssExtractPlugin = require('mini-css-extract-plugin'); ++const fs = require('fs'); + const path = require('path'); + const PostCssAutoprefixerPlugin = require('autoprefixer'); + const PostCssRTLCSS = require('postcss-rtlcss'); +@@ -23,6 +24,21 @@ const HtmlWebpackNewRelicPlugin = require('../lib/plugins/html-webpack-new-relic + const commonConfig = require('./webpack.common.config'); + const presets = require('../lib/presets'); + ++/** This condition confirms whether the configuration for the MFE has switched to a JS-based configuration ++ * as previously implemented in frontend-build and frontend-platform. If the environment variable exists, then ++ * an env.config.js file will be created at the root directory and its env variables can be accessed with getConfig(). ++ * ++ * https://github.com/openedx/frontend-build/blob/master/docs/0002-js-environment-config.md ++ * https://github.com/openedx/frontend-platform/blob/master/docs/decisions/0007-javascript-file-configuration.rst ++ */ ++ ++const envConfigPath = process.env.JS_CONFIG_FILEPATH; ++ ++if (envConfigPath) { ++ const envConfigFilename = envConfigPath.slice(envConfigPath.indexOf('env.config')); ++ fs.copyFileSync(envConfigPath, envConfigFilename); ++} ++ + // Add process env vars. Currently used only for setting the PUBLIC_PATH. + dotenv.config({ + path: path.resolve(process.cwd(), '.env'), diff --git a/src/containers/CourseFilterControls/ActiveCourseFilters.jsx b/src/containers/CourseFilterControls/ActiveCourseFilters.jsx index e4fad874..a121c749 100644 --- a/src/containers/CourseFilterControls/ActiveCourseFilters.jsx +++ b/src/containers/CourseFilterControls/ActiveCourseFilters.jsx @@ -4,16 +4,17 @@ import { useIntl } from '@edx/frontend-platform/i18n'; import { Button, Chip } from '@openedx/paragon'; import { CloseSmall } from '@openedx/paragon/icons'; +import { reduxHooks } from 'hooks'; import messages from './messages'; import './index.scss'; export const ActiveCourseFilters = ({ filters, - setFilters, handleRemoveFilter, }) => { const { formatMessage } = useIntl(); + const clearFilters = reduxHooks.useClearFilters(); return (
{filters.map(filter => ( @@ -25,7 +26,7 @@ export const ActiveCourseFilters = ({ {formatMessage(messages[filter])} ))} -
@@ -33,10 +34,6 @@ export const ActiveCourseFilters = ({ }; ActiveCourseFilters.propTypes = { filters: PropTypes.arrayOf(PropTypes.string).isRequired, - setFilters: PropTypes.shape({ - remove: PropTypes.func, - clear: PropTypes.func, - }).isRequired, handleRemoveFilter: PropTypes.func.isRequired, }; diff --git a/src/containers/CourseFilterControls/ActiveCourseFilters.test.jsx b/src/containers/CourseFilterControls/ActiveCourseFilters.test.jsx index e920613c..faf74d44 100644 --- a/src/containers/CourseFilterControls/ActiveCourseFilters.test.jsx +++ b/src/containers/CourseFilterControls/ActiveCourseFilters.test.jsx @@ -6,10 +6,6 @@ import ActiveCourseFilters from './ActiveCourseFilters'; describe('ActiveCourseFilters', () => { const props = { filters: Object.values(FilterKeys), - setFilters: { - remove: jest.fn().mockName('setFilters.remove'), - clear: jest.fn().mockName('setFilters.clear'), - }, handleRemoveFilter: jest.fn().mockName('handleRemoveFilter'), }; describe('snapshot', () => { diff --git a/src/containers/CourseFilterControls/CourseFilterControls.jsx b/src/containers/CourseFilterControls/CourseFilterControls.jsx index 46b72a90..4dd98186 100644 --- a/src/containers/CourseFilterControls/CourseFilterControls.jsx +++ b/src/containers/CourseFilterControls/CourseFilterControls.jsx @@ -27,7 +27,6 @@ export const CourseFilterControls = ({ sortBy, setSortBy, filters, - setFilters, }) => { const { formatMessage } = useIntl(); const hasCourses = reduxHooks.useHasCourses(); @@ -41,7 +40,6 @@ export const CourseFilterControls = ({ handleSortChange, } = useCourseFilterControlsData({ filters, - setFilters, setSortBy, }); const { width } = useWindowSize(); @@ -112,10 +110,6 @@ CourseFilterControls.propTypes = { sortBy: PropTypes.string.isRequired, setSortBy: PropTypes.func.isRequired, filters: PropTypes.arrayOf(PropTypes.string).isRequired, - setFilters: PropTypes.shape({ - add: PropTypes.func.isRequired, - remove: PropTypes.func.isRequired, - }).isRequired, }; export default CourseFilterControls; diff --git a/src/containers/CourseFilterControls/CourseFilterControls.test.jsx b/src/containers/CourseFilterControls/CourseFilterControls.test.jsx index 2526bdaa..7daee4e5 100644 --- a/src/containers/CourseFilterControls/CourseFilterControls.test.jsx +++ b/src/containers/CourseFilterControls/CourseFilterControls.test.jsx @@ -23,10 +23,6 @@ describe('CourseFilterControls', () => { sortBy: 'test-sort-by', setSortBy: jest.fn().mockName('setSortBy'), filters: ['test-filter'], - setFilters: { - add: jest.fn().mockName('setFilters.add'), - remove: jest.fn().mockName('setFilters.remove'), - }, }; useCourseFilterControlsData.mockReturnValue({ diff --git a/src/containers/CourseFilterControls/__snapshots__/ActiveCourseFilters.test.jsx.snap b/src/containers/CourseFilterControls/__snapshots__/ActiveCourseFilters.test.jsx.snap index ec20355d..9a9cf832 100644 --- a/src/containers/CourseFilterControls/__snapshots__/ActiveCourseFilters.test.jsx.snap +++ b/src/containers/CourseFilterControls/__snapshots__/ActiveCourseFilters.test.jsx.snap @@ -30,7 +30,7 @@ exports[`ActiveCourseFilters snapshot renders 1`] = ` Upgraded