diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 53579ccb..20abc86c 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -33,11 +33,12 @@ "@eslint/js": "^9.33.0", "@types/react": "^19.1.10", "@types/react-dom": "^19.1.7", - "@vitejs/plugin-react": "^5.0.0", + "@vitejs/plugin-react-swc": "^4.2.3", "eslint": "^9.33.0", "eslint-plugin-react-hooks": "^7.0.0", "eslint-plugin-react-refresh": "^0.5.0", "globals": "^17.0.0", + "lightningcss": "^1.31.1", "sass-embedded": "^1.96.0", "vite": "^7.1.2" } @@ -72,7 +73,6 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -169,14 +169,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", "license": "MIT", @@ -230,34 +222,6 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/runtime": { "version": "7.28.4", "license": "MIT", @@ -365,7 +329,6 @@ "node_modules/@emotion/react": { "version": "11.14.0", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -403,7 +366,6 @@ "node_modules/@emotion/styled": { "version": "11.14.1", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -1026,6 +988,17 @@ "@floating-ui/utils": "^0.2.10" } }, + "node_modules/@floating-ui/dom": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.5.tgz", + "integrity": "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@floating-ui/core": "^1.7.4", + "@floating-ui/utils": "^0.2.10" + } + }, "node_modules/@floating-ui/utils": { "version": "0.2.10", "license": "MIT", @@ -1195,7 +1168,6 @@ "node_modules/@mui/material": { "version": "7.3.7", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.28.4", "@mui/core-downloads-tracker": "^7.3.7", @@ -1300,7 +1272,6 @@ "node_modules/@mui/system": { "version": "7.3.7", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.28.4", "@mui/private-theming": "^7.3.7", @@ -2085,12 +2056,237 @@ "win32" ] }, + "node_modules/@swc/core": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.11.tgz", + "integrity": "sha512-iLmLTodbYxU39HhMPaMUooPwO/zqJWvsqkrXv1ZI38rMb048p6N7qtAtTp37sw9NzSrvH6oli8EdDygo09IZ/w==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.25" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.15.11", + "@swc/core-darwin-x64": "1.15.11", + "@swc/core-linux-arm-gnueabihf": "1.15.11", + "@swc/core-linux-arm64-gnu": "1.15.11", + "@swc/core-linux-arm64-musl": "1.15.11", + "@swc/core-linux-x64-gnu": "1.15.11", + "@swc/core-linux-x64-musl": "1.15.11", + "@swc/core-win32-arm64-msvc": "1.15.11", + "@swc/core-win32-ia32-msvc": "1.15.11", + "@swc/core-win32-x64-msvc": "1.15.11" + }, + "peerDependencies": { + "@swc/helpers": ">=0.5.17" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.11.tgz", + "integrity": "sha512-QoIupRWVH8AF1TgxYyeA5nS18dtqMuxNwchjBIwJo3RdwLEFiJq6onOx9JAxHtuPwUkIVuU2Xbp+jCJ7Vzmgtg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.11.tgz", + "integrity": "sha512-S52Gu1QtPSfBYDiejlcfp9GlN+NjTZBRRNsz8PNwBgSE626/FUf2PcllVUix7jqkoMC+t0rS8t+2/aSWlMuQtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.11.tgz", + "integrity": "sha512-lXJs8oXo6Z4yCpimpQ8vPeCjkgoHu5NoMvmJZ8qxDyU99KVdg6KwU9H79vzrmB+HfH+dCZ7JGMqMF//f8Cfvdg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.11.tgz", + "integrity": "sha512-chRsz1K52/vj8Mfq/QOugVphlKPWlMh10V99qfH41hbGvwAU6xSPd681upO4bKiOr9+mRIZZW+EfJqY42ZzRyA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.11.tgz", + "integrity": "sha512-PYftgsTaGnfDK4m6/dty9ryK1FbLk+LosDJ/RJR2nkXGc8rd+WenXIlvHjWULiBVnS1RsjHHOXmTS4nDhe0v0w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.11.tgz", + "integrity": "sha512-DKtnJKIHiZdARyTKiX7zdRjiDS1KihkQWatQiCHMv+zc2sfwb4Glrodx2VLOX4rsa92NLR0Sw8WLcPEMFY1szQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.11.tgz", + "integrity": "sha512-mUjjntHj4+8WBaiDe5UwRNHuEzLjIWBTSGTw0JT9+C9/Yyuh4KQqlcEQ3ro6GkHmBGXBFpGIj/o5VMyRWfVfWw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.11.tgz", + "integrity": "sha512-ZkNNG5zL49YpaFzfl6fskNOSxtcZ5uOYmWBkY4wVAvgbSAQzLRVBp+xArGWh2oXlY/WgL99zQSGTv7RI5E6nzA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.11.tgz", + "integrity": "sha512-6XnzORkZCQzvTQ6cPrU7iaT9+i145oLwnin8JrfsLG41wl26+5cNQ2XV3zcbrnFEV6esjOceom9YO1w9mGJByw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.11.tgz", + "integrity": "sha512-IQ2n6af7XKLL6P1gIeZACskSxK8jWtoKpJWLZmdXTDj1MGzktUy4i+FvpdtxFmJWNavRWH1VmTr6kAubRDHeKw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@swc/types": { + "version": "0.1.25", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.25.tgz", + "integrity": "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, "node_modules/@tiptap/core": { "version": "3.19.0", "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.19.0.tgz", "integrity": "sha512-bpqELwPW+DG8gWiD8iiFtSl4vIBooG5uVJod92Qxn3rA9nFatyXRr4kNbMJmOZ66ezUvmCjXVe/5/G4i5cyzKA==", "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -2244,7 +2440,6 @@ "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.19.0.tgz", "integrity": "sha512-789zcnM4a8OWzvbD2DL31d0wbSm9BVeO/R7PLQwLIGysDI3qzrcclyZ8yhqOEVuvPitRRwYLq+mY14jz7kY4cw==", "license": "MIT", - "peer": true, "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-collab": "^1.3.1", @@ -2297,43 +2492,6 @@ "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } - }, "node_modules/@types/d3-array": { "version": "3.2.2", "license": "MIT" @@ -2422,7 +2580,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.13.tgz", "integrity": "sha512-KkiJeU6VbYbUOp5ITMIc7kBfqlYkKA5KhEHVrGMmUUMt7NeaZg65ojdPk+FtNrBAOXNVM5QM72jnADjM+XVRAQ==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -2430,7 +2587,6 @@ "node_modules/@types/react-dom": { "version": "19.2.3", "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -2446,32 +2602,27 @@ "version": "0.0.6", "license": "MIT" }, - "node_modules/@vitejs/plugin-react": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.3.tgz", - "integrity": "sha512-NVUnA6gQCl8jfoYqKqQU5Clv0aPw14KkZYCsX6T9Lfu9slI0LOU10OTwFHS/WmptsMMpshNd/1tuWsHQ2Uk+cg==", + "node_modules/@vitejs/plugin-react-swc": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-4.2.3.tgz", + "integrity": "sha512-QIluDil2prhY1gdA3GGwxZzTAmLdi8cQ2CcuMW4PB/Wu4e/1pzqrwhYWVd09LInCRlDUidQjd0B70QWbjWtLxA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.29.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-rc.2", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.18.0" + "@swc/core": "^1.15.11" }, "engines": { "node": "^20.19.0 || >=22.12.0" }, "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + "vite": "^4 || ^5 || ^6 || ^7" } }, "node_modules/acorn": { "version": "8.15.0", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2593,7 +2744,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -2966,7 +3116,6 @@ "version": "9.39.2", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -3493,6 +3642,277 @@ "node": ">= 0.8.0" } }, + "node_modules/lightningcss": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", + "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.31.1", + "lightningcss-darwin-arm64": "1.31.1", + "lightningcss-darwin-x64": "1.31.1", + "lightningcss-freebsd-x64": "1.31.1", + "lightningcss-linux-arm-gnueabihf": "1.31.1", + "lightningcss-linux-arm64-gnu": "1.31.1", + "lightningcss-linux-arm64-musl": "1.31.1", + "lightningcss-linux-x64-gnu": "1.31.1", + "lightningcss-linux-x64-musl": "1.31.1", + "lightningcss-win32-arm64-msvc": "1.31.1", + "lightningcss-win32-x64-msvc": "1.31.1" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz", + "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz", + "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz", + "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz", + "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz", + "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz", + "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz", + "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz", + "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz", + "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz", + "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz", + "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss/node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "license": "MIT" @@ -3753,7 +4173,6 @@ "version": "4.0.3", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -3899,7 +4318,6 @@ "node_modules/prosemirror-model": { "version": "1.25.4", "license": "MIT", - "peer": true, "dependencies": { "orderedmap": "^2.0.0" } @@ -3923,7 +4341,6 @@ "node_modules/prosemirror-state": { "version": "1.4.4", "license": "MIT", - "peer": true, "dependencies": { "prosemirror-model": "^1.0.0", "prosemirror-transform": "^1.0.0", @@ -3964,7 +4381,6 @@ "node_modules/prosemirror-view": { "version": "1.41.4", "license": "MIT", - "peer": true, "dependencies": { "prosemirror-model": "^1.20.0", "prosemirror-state": "^1.0.0", @@ -3989,7 +4405,6 @@ "node_modules/react": { "version": "19.2.4", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -3997,7 +4412,6 @@ "node_modules/react-dom": { "version": "19.2.4", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -4009,14 +4423,6 @@ "version": "19.2.3", "license": "MIT" }, - "node_modules/react-refresh": { - "version": "0.18.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/react-transition-group": { "version": "4.4.5", "license": "BSD-3-Clause", @@ -4705,7 +5111,6 @@ "version": "7.3.1", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -4823,7 +5228,6 @@ "version": "4.1.12", "dev": true, "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/frontend/package.json b/frontend/package.json index 798e1ae6..22b20439 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -35,11 +35,12 @@ "@eslint/js": "^9.33.0", "@types/react": "^19.1.10", "@types/react-dom": "^19.1.7", - "@vitejs/plugin-react": "^5.0.0", + "@vitejs/plugin-react-swc": "^4.2.3", "eslint": "^9.33.0", "eslint-plugin-react-hooks": "^7.0.0", "eslint-plugin-react-refresh": "^0.5.0", "globals": "^17.0.0", + "lightningcss": "^1.31.1", "sass-embedded": "^1.96.0", "vite": "^7.1.2" } diff --git a/frontend/platform/course/Course.jsx b/frontend/platform/course/Course.jsx index 151e904a..a1171343 100644 --- a/frontend/platform/course/Course.jsx +++ b/frontend/platform/course/Course.jsx @@ -7,15 +7,17 @@ import FilterListIcon from '@mui/icons-material/FilterList'; import DescriptionIcon from '@mui/icons-material/Description'; import BallotIcon from '@mui/icons-material/Ballot'; import { useState, useEffect } from 'react'; -import { Box, Grid, Button, Dialog, Typography } from '@mui/material' +import { Box, Grid, Button, Dialog, LinearProgress, Typography } from '@mui/material' import { useTheme } from '@mui/material/styles'; -import LessonForm from './components/LessonForm.jsx'; -import QuizForm from './components/QuizForm.jsx'; import ContentTable from './components/ContentTable.jsx'; -import DeleteContentForm from './components/DeleteContentForm.jsx'; import { PieChart } from '@mui/x-charts/PieChart' import { BarChart } from '@mui/x-charts/BarChart'; import { getCookie } from '../../src/utils.js'; +import { lazy, Suspense } from "react"; + +const QuizForm = lazy(() => import("./components/QuizForm.jsx")); +const LessonForm = lazy(() => import("./components/LessonForm.jsx")); +const DeleteContentForm = lazy(() => import("./components/DeleteContentForm.jsx")); function Course() { @@ -140,7 +142,7 @@ function Course() { if (content.type == 'lesson') { console.log("Opening lesson editor for content:", content); setDialogOpen(true); - setDialogContent(}>); + contentId={content.id} />); } else if (content.type == 'quiz') { console.log("Opening quiz editor for content:", content); setDialogOpen(true); - setDialogContent(}> setDialogOpen(false)} successCallback={resetDialog} courseId={course_id} @@ -166,7 +168,7 @@ function Course() { initialWaitingPeriod={content.waiting_period} initialStrategy={content.quiz.selection_strategy} initialDeadlineDays={content.quiz.deadline_days} - />); + />); } } if (event.type === 'content_reordered') { @@ -190,7 +192,7 @@ function Course() { .catch(error => console.error('Error reordering contents:', error)); } if (event.type === 'delete_content') { - setDialogContent( {setDialogOpen(false); setDialogMaxWidth('lg');}} />); + setDialogContent(}> {setDialogOpen(false); setDialogMaxWidth('lg');}} />); setDialogMaxWidth('sm'); setDialogOpen(true); } @@ -211,19 +213,19 @@ function Course() { {userRole !== 'viewer' && <> } tableEventHandler(event)} /> diff --git a/frontend/platform/courses/Courses.jsx b/frontend/platform/courses/Courses.jsx index f5916ece..2e78af41 100644 --- a/frontend/platform/courses/Courses.jsx +++ b/frontend/platform/courses/Courses.jsx @@ -1,17 +1,34 @@ import 'vite/modulepreload-polyfill' import { useState, useEffect } from 'react' -import { Grid, Box, Link, Button, IconButton, Dialog, Paper, Switch, TableContainer, Table, TableHead, TableRow,TableBody, TableCell } from '@mui/material' +import Grid from '@mui/material/Grid'; +import Box from '@mui/material/Box'; +import Link from '@mui/material/Link'; +import Button from '@mui/material/Button'; +import IconButton from '@mui/material/IconButton'; +import Dialog from '@mui/material/Dialog'; +import LinearProgress from '@mui/material/LinearProgress'; +import Paper from '@mui/material/Paper'; +import Switch from '@mui/material/Switch'; +import TableContainer from '@mui/material/TableContainer'; +import Table from '@mui/material/Table'; +import TableHead from '@mui/material/TableHead'; +import TableRow from '@mui/material/TableRow'; +import TableBody from '@mui/material/TableBody'; +import TableCell from '@mui/material/TableCell'; import Base from '../../src/components/Base.jsx' -import CourseForm from './components/CourseForm.jsx'; import FilterListIcon from '@mui/icons-material/FilterList'; import SchoolIcon from '@mui/icons-material/School'; import DeleteIcon from '@mui/icons-material/Delete'; import EditIcon from '@mui/icons-material/Edit'; import render from '../../src/render.jsx'; import { getCookie } from '../../src/utils.js'; -import EnableCourseSwitchPopup from './components/EnableCourseSwitchPopup.jsx'; -import DeleteCoursePopup from './components/DeleteCoursePopup.jsx'; import FilterForm from './components/FilterForm.jsx'; +import { lazy, Suspense } from "react"; + +const CourseForm = lazy(() => import("./components/CourseForm.jsx")); +const EnableCourseSwitchPopup = lazy(() => import("./components/EnableCourseSwitchPopup.jsx")); +const DeleteCoursePopup = lazy(() => import("./components/DeleteCoursePopup.jsx")); + function Courses() { @@ -62,7 +79,7 @@ function Courses() { console.log(`${action} course with ID:`, courseId); console.log('Event:', event.target.checked); setDialogContent( - setDialogOpen(false)} handleSuccess={updateCourseState}/> + }> setDialogOpen(false)} handleSuccess={updateCourseState}/> ); setDialogOpen(true); } @@ -78,7 +95,7 @@ function Courses() { }; const showEditCourseDialog = (course) => { - setDialogContent(}> { const index = courses.findIndex(item => item.id === course.id); courses[index] = data; @@ -92,7 +109,7 @@ function Courses() { activeOrganizationId={organizationId} createMode={false} courseId={course.id} - />); + />); setDialogOpen(true); } @@ -108,13 +125,13 @@ function Courses() { {userRole !== 'viewer' && } @@ -148,10 +165,10 @@ function Courses() { { showEditCourseDialog(course);}}> { - setDialogContent( setDialogOpen(false)} handleSuccess={() => { + setDialogContent(}> setDialogOpen(false)} handleSuccess={() => { const index = courses.findIndex(item => item.id === course.id); setCourses(courses.filter((_, i) => i !== index)); - }} />); + }} />); setDialogOpen(true); }}>} @@ -163,7 +180,7 @@ function Courses() { - + setQueryParameters(params)} /> diff --git a/frontend/platform/learners/Learners.jsx b/frontend/platform/learners/Learners.jsx index 7cac3130..aeff9dbc 100644 --- a/frontend/platform/learners/Learners.jsx +++ b/frontend/platform/learners/Learners.jsx @@ -13,39 +13,13 @@ import SchoolIcon from '@mui/icons-material/School'; import BackspaceIcon from '@mui/icons-material/Backspace'; import render from '../../src/render.jsx'; import { getCookie } from '../../src/utils.js'; +import { lazy, Suspense } from "react"; - -const apiBaseUrl = localStorage.getItem('apiBaseUrl'); +const EnrollentList = lazy(() => import("./components/EnrollmentList.jsx")); -function EnrolmentList({enrollments, selectHandler}) { - if (enrollments.length === 0) { - return {localeMessages["nor_enrollments_found"]} - } +const apiBaseUrl = localStorage.getItem('apiBaseUrl'); - return ( - -
- - - {localeMessages["course"]} - {localeMessages["status"]} - - - - {enrollments.map((enrollment) => ( - ({':hover': {backgroundColor: theme.palette.background.dark, cursor: 'pointer', borderBottomColor: 'secondary.light', borderBottomWidth: 2, borderBottomStyle: 'solid'}})} - onClick={() => selectHandler(enrollment.id)}> - {enrollment.course_title} - {localeMessages[enrollment.status]} - - ))} - -
-
- ) -} function Learners(initialQs="") { @@ -242,7 +216,7 @@ function Learners(initialQs="") { {learner.email} - {learner.state === 0 ? "" : learner.state === 1 ? : } + {learner.state === 0 ? "" : learner.state === 1 ? :
}>} diff --git a/frontend/platform/learners/components/EnrollmentList.jsx b/frontend/platform/learners/components/EnrollmentList.jsx new file mode 100644 index 00000000..298c582e --- /dev/null +++ b/frontend/platform/learners/components/EnrollmentList.jsx @@ -0,0 +1,32 @@ +import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Typography } from '@mui/material'; + +function EnrollentList({enrollments, selectHandler}) { + if (enrollments.length === 0) { + return {localeMessages["nor_enrollments_found"]} + } + + return ( + + + + + {localeMessages["course"]} + {localeMessages["status"]} + + + + {enrollments.map((enrollment) => ( + ({':hover': {backgroundColor: theme.palette.background.dark, cursor: 'pointer', borderBottomColor: 'secondary.light', borderBottomWidth: 2, borderBottomStyle: 'solid'}})} + onClick={() => selectHandler(enrollment.id)}> + {enrollment.course_title} + {localeMessages[enrollment.status]} + + ))} + +
+
+ ) +} + +export default EnrollentList; diff --git a/frontend/platform/organizations/Organizations.jsx b/frontend/platform/organizations/Organizations.jsx index 9fc1ddbf..ef028799 100644 --- a/frontend/platform/organizations/Organizations.jsx +++ b/frontend/platform/organizations/Organizations.jsx @@ -1,5 +1,19 @@ import Base from "../../src/components/Base"; -import { Alert, Box, Button, Dialog, Grid, IconButton, Paper, TableContainer, Table, TableHead, TableRow,TableBody, TableCell, Typography } from "@mui/material"; +import Alert from "@mui/material/Alert" +import Box from "@mui/material/Box" +import Button from "@mui/material/Button" +import Dialog from "@mui/material/Dialog" +import Grid from "@mui/material/Grid" +import IconButton from "@mui/material/IconButton" +import LinearProgress from "@mui/material/LinearProgress" +import Paper from "@mui/material/Paper" +import TableContainer from "@mui/material/TableContainer" +import Table from "@mui/material/Table" +import TableHead from "@mui/material/TableHead" +import TableRow from "@mui/material/TableRow" +import TableBody from "@mui/material/TableBody" +import TableCell from "@mui/material/TableCell" +import Typography from "@mui/material/Typography" import AddIcon from '@mui/icons-material/Add'; import PublicIcon from '@mui/icons-material/Public'; import DeleteIcon from '@mui/icons-material/Delete'; @@ -7,7 +21,9 @@ import EditIcon from '@mui/icons-material/Edit'; import { useState, useEffect, use } from "react"; import { getCookie } from "../../src/utils"; import render from "../../src/render"; -import OrganizationForm from "./components/OrganizationForm"; +import { lazy, Suspense } from "react"; + +const OrganizationForm = lazy(() => import("./components/OrganizationForm.jsx")); function Organizations() { const [dialogOpen, setDialogOpen] = useState(false); @@ -93,12 +109,12 @@ function Organizations() { @@ -117,7 +133,7 @@ function Organizations() { goToUrl(org.public_url)}> { - setDialogContent(}> setDialogOpen(false)} @@ -126,7 +142,7 @@ function Organizations() { initialDescription={org.description} initialLogoUrl={org.logo} organizationId={org.id} - />); + />); setDialogOpen(true); }}> deleteConfirmationDialog(org)}> diff --git a/frontend/vite.config.js b/frontend/vite.config.js index 5dac89a1..9a98b1e8 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -3,7 +3,7 @@ import { fileURLToPath } from 'url'; import { dirname, resolve } from 'path'; -import react from '@vitejs/plugin-react' +import react from '@vitejs/plugin-react-swc'; const __dirname = dirname(fileURLToPath(import.meta.url)); @@ -13,6 +13,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url)); // https://vite.dev/config/ export default defineConfig({ plugins: [react()], + css: { transformer: 'lightningcss' }, appType: 'mpa', base: "/static/", server: { @@ -38,8 +39,18 @@ export default defineConfig({ outDir: resolve(__dirname, '../dist'), emptyOutDir: true, sourcemap: true, + optimizeDeps: { + include: [ + 'react', + 'react-dom', + '@mui/material', + '@mui/icons-material', + '@mui/lab', + '@mui/x-charts', + '@emotion/react', + '@emotion/styled', + ], // Force pre-bundling + entries: ['./platform/courses/Courses.jsx', './platform/course/Course.jsx', './platform/organizations/Organizations.jsx', './platform/learners/Learners.jsx', './platform/settings_api_keys/SettingsApiKeys.jsx', './public/organization/Organization.jsx', './personalised/quiz_public/QuizPublic.jsx', './personalised/command_result/CommandResult.jsx'], }, - optimizeDeps: { - include: ['esm-dep > cjs-dep'], - }, + } })