diff --git a/.gitignore b/.gitignore index 9acb018ead..0d2b1b95ec 100644 --- a/.gitignore +++ b/.gitignore @@ -222,7 +222,7 @@ jspm_packages # Project-specific # --------------------------------------------------------------------------- / -# Create React App +# Create React Root # --- # dependencies @@ -249,7 +249,7 @@ node_modules .env.production.local -# App specific +# Root specific env-config.js tests/cypress/videos tests/cypress/screenshots diff --git a/package-lock.json b/package-lock.json index a5716da6e2..ced8c711b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,9 @@ "@meemoo/admin-core-ui": "4.5.26", "@meemoo/react-components": "4.3.2", "@popperjs/core": "2.11.6", + "@react-router/dev": "^7.9.1", + "@react-router/node": "^7.9.1", + "@react-router/serve": "^7.9.1", "@studiohyperdrive/pagination": "1.0.0", "@tanstack/react-query": "4.36.1", "@uidotdev/usehooks": "^2.4.1", @@ -32,10 +35,10 @@ "i18next-xhr-backend": "3.2.2", "immer": "9.0.12", "isomorphic-dompurify": "2.16.0", + "jotai": "2.14.0", "lodash-es": "4.17.21", "marked": "4.0.15", "node-fetch": "2.7.0", - "oaf-react-router": "2.1.1", "query-string": "7.1.1", "raf": "3.4.1", "react": "18.2.0", @@ -53,23 +56,18 @@ "react-perfect-scrollbar": "1.5.8", "react-popper": "2.3.0", "react-range": "1.8.14", - "react-redux": "8.1.2", - "react-router": "5.3.4", - "react-router-dom": "5.3.4", + "react-router": "^7.9.1", "react-select": "5.7.4", "react-table": "7.7.0", "react-to-string": "0.1.1", "react-toastify": "5.5.0", "react-zendesk": "0.1.13", - "redux": "4.2.1", - "redux-devtools-extension": "2.13.9", - "redux-thunk": "2.4.2", "rollup-plugin-sourcemaps": "^0.6.3", "source-map-explorer": "2.5.3", "to-camel-case": "1.0.0", "to-slug-case": "1.0.0", "ts-retry-promise": "0.8.1", - "use-query-params": "1.2.3", + "use-query-params": "2.2.1", "yup": "1.4.0" }, "devDependencies": { @@ -105,14 +103,12 @@ "@types/react-dom": "18.2.7", "@types/react-helmet": "6.1.6", "@types/react-modal": "3.16.0", - "@types/react-redux": "6.0.22", - "@types/react-router-dom": "5.3.3", "@types/to-camel-case": "^1.0.2", "@types/to-slug-case": "^1.0.2", "@types/uuid": "10.0.0", "@typescript-eslint/eslint-plugin": "5.62.0", "@typescript-eslint/parser": "5.62.0", - "@vitejs/plugin-react": "4.0.4", + "@vitejs/plugin-react": "^5.0.3", "bump-package-versions": "^1.0.7", "cross-env": "7.0.3", "dependency-cruiser": "^16.10.2", @@ -134,7 +130,6 @@ "lint-staged": "13.3.0", "lodash": "4.17.21", "prettier": "3.0.3", - "redux-mock-store": "1.5.4", "replace-in-file": "6.3.5", "rollup-plugin-sourcemaps": "0.6.3", "sass": "1.68.0", @@ -142,11 +137,11 @@ "ts-node": "10.9.1", "typescript": "5.1.6", "uuid": "10.0.0", - "vite": "4.5.5", - "vite-plugin-css-injected-by-js": "3.3.0", - "vite-plugin-svgr": "3.2.0", - "vite-svg-loader": "4.0.0", - "vite-tsconfig-paths": "4.2.1" + "vite": "6.3.6", + "vite-plugin-css-injected-by-js": "3.5.2", + "vite-plugin-svgr": "4.5.0", + "vite-svg-loader": "5.1.0", + "vite-tsconfig-paths": "5.1.4" }, "optionalDependencies": { "@esbuild/darwin-arm64": "^0.20.1", @@ -162,18 +157,6 @@ "node": ">=0.10.0" } }, - "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@ardatan/relay-compiler": { "version": "12.0.0", "dev": true, @@ -377,39 +360,44 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "license": "MIT", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "dev": true, + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", + "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.5", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.5", - "@babel/parser": "^7.23.5", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.5", - "@babel/types": "^7.23.5", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -425,38 +413,42 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.5", - "dev": true, + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.23.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "dev": true, + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.27.3" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "dev": true, + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -465,18 +457,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.23.5", - "dev": true, + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.3.tgz", + "integrity": "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.3", "semver": "^6.3.1" }, "engines": { @@ -506,48 +497,50 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "dev": true, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "license": "MIT", - "dependencies": { - "@babel/types": "^7.22.5" - }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "dev": true, + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", + "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", "license": "MIT", "dependencies": { - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "license": "MIT", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "dev": true, + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" }, "engines": { "node": ">=6.9.0" @@ -557,33 +550,35 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "dev": true, + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", - "dev": true, + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.20", - "dev": true, + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", - "@babel/helper-optimise-call-expression": "^7.22.5" + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -592,23 +587,14 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "dev": true, + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -626,56 +612,53 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "dev": true, + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.23.5", - "dev": true, + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", "license": "MIT", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.5", - "@babel/types": "^7.23.5" + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.23.4", + "node_modules/@babel/parser": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@babel/types": "^7.28.4" }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.5", - "dev": true, - "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -805,11 +788,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.23.3", - "dev": true, + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -905,12 +889,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "dev": true, + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1086,13 +1070,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.23.3", - "dev": true, + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", + "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1177,11 +1161,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.23.3", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1191,11 +1177,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.23.3", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1247,6 +1235,44 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz", + "integrity": "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.1.tgz", + "integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/runtime": { "version": "7.23.5", "license": "MIT", @@ -1258,45 +1284,45 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", - "dev": true, + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.5", - "dev": true, + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", + "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.5", - "@babel/types": "^7.23.5", - "debug": "^4.1.0", - "globals": "^11.1.0" + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { - "version": "7.23.5", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1921,6 +1947,70 @@ "version": "0.3.1", "license": "MIT" }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", + "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", + "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", + "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", + "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/darwin-arm64": { "version": "0.20.1", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.1.tgz", @@ -1936,87 +2026,391 @@ "node": ">=12" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz", - "integrity": "sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", + "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ - "linux" + "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.1.tgz", - "integrity": "sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", + "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", + "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ - "win32" + "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "dev": true, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", + "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=18" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "dev": true, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", + "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", + "cpu": [ + "arm64" + ], "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "dev": true, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", + "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", + "cpu": [ + "ia32" + ], "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "dev": true, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", + "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", + "cpu": [ + "loong64" + ], "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", + "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", + "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", + "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", + "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz", + "integrity": "sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", + "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", + "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", + "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", + "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", + "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", + "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", + "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", + "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.1.tgz", + "integrity": "sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" }, @@ -2268,18 +2662,6 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", "dev": true }, - "node_modules/@graphql-codegen/cli/node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", - "dev": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/@graphql-codegen/client-preset": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/@graphql-codegen/client-preset/-/client-preset-4.3.3.tgz", @@ -4788,42 +5170,42 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "dev": true, + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "dev": true, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "license": "MIT", - "engines": { - "node": ">=6.0.0" + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "dev": true, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "dev": true, + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "dev": true, + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -4911,6 +5293,12 @@ "react-table": "7.7.0" } }, + "node_modules/@mjackson/node-fetch-server": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@mjackson/node-fetch-server/-/node-fetch-server-0.2.0.tgz", + "integrity": "sha512-EMlH1e30yzmTpGLQjlFmaDAjyOeZhng1/XCd7DExR8PNAnG/G1tyruZxEoUe11ClnwGhGrtsdnyyUx1frSzjng==", + "license": "MIT" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "dev": true, @@ -4943,11 +5331,212 @@ "node": ">= 8" } }, - "node_modules/@one-ini/wasm": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", - "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==" - }, + "node_modules/@npmcli/git": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz", + "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==", + "license": "ISC", + "dependencies": { + "@npmcli/promise-spawn": "^6.0.0", + "lru-cache": "^7.4.4", + "npm-pick-manifest": "^8.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/@npmcli/git/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/git/node_modules/which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha512-lRCEGdHZomFsURroh522YvA/2cVb9oPIJrjHanCJZkiasz1BzcnLr3tBJhlV7S86MBJBuAQ33is2D60YitZL2Q==", + "license": "ISC", + "dependencies": { + "@npmcli/git": "^4.1.0", + "glob": "^10.2.2", + "hosted-git-info": "^6.1.1", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "proc-log": "^3.0.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/package-json/node_modules/hosted-git-info": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.3.tgz", + "integrity": "sha512-HVJyzUrLIL1c0QmviVh5E8VGyUS7xCFPS6yydaVd1UegW+ibV/CohqTH9MkOLDp5o+rb82DMo77PTuc9F/8GKw==", + "license": "ISC", + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/json-parse-even-better-errors": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", + "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", + "license": "MIT", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/@npmcli/package-json/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/package-json/node_modules/normalize-package-data": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", + "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^6.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/promise-spawn": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", + "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", + "license": "ISC", + "dependencies": { + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==" + }, "node_modules/@peculiar/asn1-schema": { "version": "2.3.13", "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.13.tgz", @@ -5008,81 +5597,611 @@ "node": ">=14" } }, - "node_modules/@pkgr/utils": { - "version": "2.4.2", - "dev": true, + "node_modules/@pkgr/utils": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "fast-glob": "^3.3.0", + "is-glob": "^4.0.3", + "open": "^9.1.0", + "picocolors": "^1.0.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@pkgr/utils/node_modules/open": { + "version": "9.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^4.0.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@pkgr/utils/node_modules/tslib": { + "version": "2.6.2", + "dev": true, + "license": "0BSD" + }, + "node_modules/@popperjs/core": { + "version": "2.11.6", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@react-router/dev": { + "version": "7.9.1", + "resolved": "https://registry.npmjs.org/@react-router/dev/-/dev-7.9.1.tgz", + "integrity": "sha512-fW/qubsdHq1nsufHPLpXa6hiNvXXV9JBtWqRlJ02OOhFeaWERZw4rGoHjG1DCg8/QTTadgbzplmP97ZnzWPkcA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.7", + "@babel/generator": "^7.27.5", + "@babel/parser": "^7.27.7", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/preset-typescript": "^7.27.1", + "@babel/traverse": "^7.27.7", + "@babel/types": "^7.27.7", + "@npmcli/package-json": "^4.0.1", + "@react-router/node": "7.9.1", + "arg": "^5.0.1", + "babel-dead-code-elimination": "^1.0.6", + "chokidar": "^4.0.0", + "dedent": "^1.5.3", + "es-module-lexer": "^1.3.1", + "exit-hook": "2.2.1", + "isbot": "^5.1.11", + "jsesc": "3.0.2", + "lodash": "^4.17.21", + "pathe": "^1.1.2", + "picocolors": "^1.1.1", + "prettier": "^3.6.2", + "react-refresh": "^0.14.0", + "semver": "^7.3.7", + "set-cookie-parser": "^2.6.0", + "tinyglobby": "^0.2.14", + "valibot": "^0.41.0", + "vite-node": "^3.2.2" + }, + "bin": { + "react-router": "bin.js" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@react-router/serve": "^7.9.1", + "@vitejs/plugin-rsc": "*", + "react-router": "^7.9.1", + "typescript": "^5.1.0", + "vite": "^5.1.0 || ^6.0.0 || ^7.0.0", + "wrangler": "^3.28.2 || ^4.0.0" + }, + "peerDependenciesMeta": { + "@react-router/serve": { + "optional": true + }, + "@vitejs/plugin-rsc": { + "optional": true + }, + "typescript": { + "optional": true + }, + "wrangler": { + "optional": true + } + } + }, + "node_modules/@react-router/dev/node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/@react-router/dev/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@react-router/dev/node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-router/dev/node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/@react-router/dev/node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@react-router/dev/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@react-router/dev/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-router/express": { + "version": "7.9.1", + "resolved": "https://registry.npmjs.org/@react-router/express/-/express-7.9.1.tgz", + "integrity": "sha512-d1sfsD3AJXZj+C5k3jAmxAD3vJXGfoh3lNmtSwxp0NdZFHI54zPC5S9o80cy3P8p6Gc7XzSEQJYk9k7fAM/AIw==", + "license": "MIT", + "dependencies": { + "@react-router/node": "7.9.1" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "express": "^4.17.1 || ^5", + "react-router": "7.9.1", + "typescript": "^5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@react-router/node": { + "version": "7.9.1", + "resolved": "https://registry.npmjs.org/@react-router/node/-/node-7.9.1.tgz", + "integrity": "sha512-XfyVLM+sDUDB1frGNr7iqaKNglrPwBiUp8+sFdL4///bngy49pUb2RuEtn2J2Cy5yjL+IlKbjJFrsmfimLBmeg==", + "license": "MIT", + "dependencies": { + "@mjackson/node-fetch-server": "^0.2.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react-router": "7.9.1", + "typescript": "^5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@react-router/serve": { + "version": "7.9.1", + "resolved": "https://registry.npmjs.org/@react-router/serve/-/serve-7.9.1.tgz", + "integrity": "sha512-yVBSb5KsNCdkSoOk186/M5GJtcIvKE32Ax9LhXySVpM+suCSjucI+p2TXDOJIYsBqr2aKcBl/bNBm5sIJxG/HA==", + "license": "MIT", + "dependencies": { + "@react-router/express": "7.9.1", + "@react-router/node": "7.9.1", + "compression": "^1.7.4", + "express": "^4.19.2", + "get-port": "5.1.1", + "morgan": "^1.10.0", + "source-map-support": "^0.5.21" + }, + "bin": { + "react-router-serve": "bin.js" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react-router": "7.9.1" + } + }, + "node_modules/@react-router/serve/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/@repeaterjs/repeater": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.6.tgz", + "integrity": "sha512-Javneu5lsuhwNCryN+pXH93VPQ8g0dBX7wItHFgYiwQmzE1sVdg5tWHiOgHywzL2W21XQopa7IwIEnNbmeUJYA==", + "dev": true + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.35.tgz", + "integrity": "sha512-slYrCpoxJUqzFDDNlvrOYRazQUNRvWPjXA17dAOISY3rDMxX6k8K4cj2H+hEYMHF81HO3uNd5rHVigAWRM5dSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.0.tgz", + "integrity": "sha512-VxDYCDqOaR7NXzAtvRx7G1u54d2kEHopb28YH/pKzY6y0qmogP3gG7CSiWsq9WvDFxOQMpNEyjVAHZFXfH3o/A==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.0.tgz", + "integrity": "sha512-pqDirm8koABIKvzL59YI9W9DWbRlTX7RWhN+auR8HXJxo89m4mjqbah7nJZjeKNTNYopqL+yGg+0mhCpf3xZtQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.0.tgz", + "integrity": "sha512-YCdWlY/8ltN6H78HnMsRHYlPiKvqKagBP1r+D7SSylxX+HnsgXGCmLiV3Y4nSyY9hW8qr8U9LDUx/Lo7M6MfmQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.0.tgz", + "integrity": "sha512-z4nw6y1j+OOSGzuVbSWdIp1IUks9qNw4dc7z7lWuWDKojY38VMWBlEN7F9jk5UXOkUcp97vA1N213DF+Lz8BRg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.0.tgz", + "integrity": "sha512-Q/dv9Yvyr5rKlK8WQJZVrp5g2SOYeZUs9u/t2f9cQ2E0gJjYB/BWoedXfUT0EcDJefi2zzVfhcOj8drWCzTviw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.0.tgz", + "integrity": "sha512-kdBsLs4Uile/fbjZVvCRcKB4q64R+1mUq0Yd7oU1CMm1Av336ajIFqNFovByipciuUQjBCPMxwJhCgfG2re3rg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.0.tgz", + "integrity": "sha512-aL6hRwu0k7MTUESgkg7QHY6CoqPgr6gdQXRJI1/VbFlUMwsSzPGSR7sG5d+MCbYnJmJwThc2ol3nixj1fvI/zQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.0.tgz", + "integrity": "sha512-BTs0M5s1EJejgIBJhCeiFo7GZZ2IXWkFGcyZhxX4+8usnIo5Mti57108vjXFIQmmJaRyDwmV59Tw64Ap1dkwMw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.0.tgz", + "integrity": "sha512-uj672IVOU9m08DBGvoPKPi/J8jlVgjh12C9GmjjBxCTQc3XtVmRkRKyeHSmIKQpvJ7fIm1EJieBUcnGSzDVFyw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.0.tgz", + "integrity": "sha512-/+IVbeDMDCtB/HP/wiWsSzduD10SEGzIZX2945KSgZRNi4TSkjHqRJtNTVtVb8IRwhJ65ssI56krlLik+zFWkw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.0.tgz", + "integrity": "sha512-U1vVzvSWtSMWKKrGoROPBXMh3Vwn93TA9V35PldokHGqiUbF6erSzox/5qrSMKp6SzakvyjcPiVF8yB1xKr9Pg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.0.tgz", + "integrity": "sha512-X/4WfuBAdQRH8cK3DYl8zC00XEE6aM472W+QCycpQJeLWVnHfkv7RyBFVaTqNUMsTgIX8ihMjCvFF9OUgeABzw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.0.tgz", + "integrity": "sha512-xIRYc58HfWDBZoLmWfWXg2Sq8VCa2iJ32B7mqfWnkx5mekekl0tMe7FHpY8I72RXEcUkaWawRvl3qA55og+cwQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.0.tgz", + "integrity": "sha512-mbsoUey05WJIOz8U1WzNdf+6UMYGwE3fZZnQqsM22FZ3wh1N887HT6jAOjXs6CNEK3Ntu2OBsyQDXfIjouI4dw==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.0.tgz", + "integrity": "sha512-qP6aP970bucEi5KKKR4AuPFd8aTx9EF6BvutvYxmZuWLJHmnq4LvBfp0U+yFDMGwJ+AIJEH5sIP+SNypauMWzg==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.0.tgz", + "integrity": "sha512-nmSVN+F2i1yKZ7rJNKO3G7ZzmxJgoQBQZ/6c4MuS553Grmr7WqR7LLDcYG53Z2m9409z3JLt4sCOhLdbKQ3HmA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.0.tgz", + "integrity": "sha512-2d0qRo33G6TfQVjaMR71P+yJVGODrt5V6+T0BDYH4EMfGgdC/2HWDVjSSFw888GSzAZUwuska3+zxNUCDco6rQ==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "fast-glob": "^3.3.0", - "is-glob": "^4.0.3", - "open": "^9.1.0", - "picocolors": "^1.0.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@pkgr/utils/node_modules/open": { - "version": "9.1.0", - "dev": true, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.0.tgz", + "integrity": "sha512-A1JalX4MOaFAAyGgpO7XP5khquv/7xKzLIyLmhNrbiCxWpMlnsTYr8dnsWM7sEeotNmxvSOEL7F65j0HXFcFsw==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "default-browser": "^4.0.0", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "optional": true, + "os": [ + "openharmony" + ] }, - "node_modules/@pkgr/utils/node_modules/tslib": { - "version": "2.6.2", - "dev": true, - "license": "0BSD" + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.0.tgz", + "integrity": "sha512-YQugafP/rH0eOOHGjmNgDURrpYHrIX0yuojOI8bwCyXwxC9ZdTd3vYkmddPX0oHONLXu9Rb1dDmT0VNpjkzGGw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@popperjs/core": { - "version": "2.11.6", + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.0.tgz", + "integrity": "sha512-zYdUYhi3Qe2fndujBqL5FjAFzvNeLxtIqfzNEVKD1I7C37/chv1VxhscWSQHTNfjPCrBFQMnynwA3kpZpZ8w4A==", + "cpu": [ + "ia32" + ], "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@repeaterjs/repeater": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.6.tgz", - "integrity": "sha512-Javneu5lsuhwNCryN+pXH93VPQ8g0dBX7wItHFgYiwQmzE1sVdg5tWHiOgHywzL2W21XQopa7IwIEnNbmeUJYA==", - "dev": true + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.0.tgz", + "integrity": "sha512-fGk03kQylNaCOQ96HDMeT7E2n91EqvCDd3RwvT5k+xNdFCeMGnj5b5hEgTGrQuyidqSsD3zJDQ21QIaxXqTBJw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@rollup/pluginutils": { - "version": "5.1.0", - "dev": true, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.0.tgz", + "integrity": "sha512-6iKDCVSIUQ8jPMoIV0OytRKniaYyy5EbY/RRydmLW8ZR3cEBhxbWl5ro0rkUNe0ef6sScvhbY79HrjRm8i3vDQ==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } + "optional": true, + "os": [ + "win32" + ] }, "node_modules/@sinclair/typebox": { "version": "0.27.8", @@ -5114,7 +6233,9 @@ } }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { - "version": "7.0.0", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", "dev": true, "license": "MIT", "engines": { @@ -5129,7 +6250,9 @@ } }, "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { - "version": "7.0.0", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", "dev": true, "license": "MIT", "engines": { @@ -5144,7 +6267,9 @@ } }, "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "7.0.0", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", "dev": true, "license": "MIT", "engines": { @@ -5159,7 +6284,9 @@ } }, "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "7.0.0", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", "dev": true, "license": "MIT", "engines": { @@ -5174,7 +6301,9 @@ } }, "node_modules/@svgr/babel-plugin-svg-dynamic-title": { - "version": "7.0.0", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", "dev": true, "license": "MIT", "engines": { @@ -5189,7 +6318,9 @@ } }, "node_modules/@svgr/babel-plugin-svg-em-dimensions": { - "version": "7.0.0", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", "dev": true, "license": "MIT", "engines": { @@ -5204,7 +6335,9 @@ } }, "node_modules/@svgr/babel-plugin-transform-react-native-svg": { - "version": "7.0.0", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", "dev": true, "license": "MIT", "engines": { @@ -5219,7 +6352,9 @@ } }, "node_modules/@svgr/babel-plugin-transform-svg-component": { - "version": "7.0.0", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", "dev": true, "license": "MIT", "engines": { @@ -5234,18 +6369,20 @@ } }, "node_modules/@svgr/babel-preset": { - "version": "7.0.0", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", "dev": true, "license": "MIT", "dependencies": { - "@svgr/babel-plugin-add-jsx-attribute": "^7.0.0", - "@svgr/babel-plugin-remove-jsx-attribute": "^7.0.0", - "@svgr/babel-plugin-remove-jsx-empty-expression": "^7.0.0", - "@svgr/babel-plugin-replace-jsx-attribute-value": "^7.0.0", - "@svgr/babel-plugin-svg-dynamic-title": "^7.0.0", - "@svgr/babel-plugin-svg-em-dimensions": "^7.0.0", - "@svgr/babel-plugin-transform-react-native-svg": "^7.0.0", - "@svgr/babel-plugin-transform-svg-component": "^7.0.0" + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" }, "engines": { "node": ">=14" @@ -5259,14 +6396,17 @@ } }, "node_modules/@svgr/core": { - "version": "7.0.0", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.21.3", - "@svgr/babel-preset": "^7.0.0", + "@svgr/babel-preset": "8.1.0", "camelcase": "^6.2.0", - "cosmiconfig": "^8.1.3" + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" }, "engines": { "node": ">=14" @@ -5278,6 +6418,8 @@ }, "node_modules/@svgr/core/node_modules/camelcase": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "license": "MIT", "engines": { @@ -5288,7 +6430,9 @@ } }, "node_modules/@svgr/hast-util-to-babel-ast": { - "version": "7.0.0", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -5304,13 +6448,15 @@ } }, "node_modules/@svgr/plugin-jsx": { - "version": "7.0.0", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.21.3", - "@svgr/babel-preset": "^7.0.0", - "@svgr/hast-util-to-babel-ast": "^7.0.0", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", "svg-parser": "^2.0.4" }, "engines": { @@ -5319,6 +6465,9 @@ "funding": { "type": "github", "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" } }, "node_modules/@tanstack/query-core": { @@ -5397,7 +6546,6 @@ "version": "7.20.5", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -5410,7 +6558,6 @@ "version": "7.6.7", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/types": "^7.0.0" } @@ -5419,7 +6566,6 @@ "version": "7.4.4", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" @@ -5429,7 +6575,6 @@ "version": "7.20.4", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/types": "^7.20.7" } @@ -5467,8 +6612,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "dev": true, + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, "node_modules/@types/file-saver": { @@ -5504,14 +6650,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/hoist-non-react-statics": { - "version": "3.3.5", - "license": "MIT", - "dependencies": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" - } - }, "node_modules/@types/i18next-xhr-backend": { "version": "1.4.2", "dev": true, @@ -5673,7 +6811,7 @@ }, "node_modules/@types/react-dom": { "version": "18.2.7", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@types/react": "*" @@ -5695,34 +6833,6 @@ "@types/react": "*" } }, - "node_modules/@types/react-redux": { - "version": "6.0.22", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/react": "*", - "redux": "^4.0.0" - } - }, - "node_modules/@types/react-router": { - "version": "5.1.20", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*" - } - }, - "node_modules/@types/react-router-dom": { - "version": "5.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router": "*" - } - }, "node_modules/@types/react-transition-group": { "version": "4.4.10", "license": "MIT", @@ -5768,10 +6878,6 @@ "version": "2.0.7", "license": "MIT" }, - "node_modules/@types/use-sync-external-store": { - "version": "0.0.3", - "license": "MIT" - }, "node_modules/@types/uuid": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", @@ -6118,111 +7224,143 @@ "integrity": "sha512-A838SvJuZ8l1eEpVhibnlU0nZYhvQROdkNYN2zS2N/c0NEaEOm8aGmBc0n3M/z+PCFxgqFzqvkGFhdVj58H7sg==" }, "node_modules/@vitejs/plugin-react": { - "version": "4.0.4", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.0.3.tgz", + "integrity": "sha512-PFVHhosKkofGH0Yzrw1BipSedTH68BFF8ZWy1kfUpCtJcouXXY0+racG8sExw7hw0HoX36813ga5o3LTWZ4FUg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.22.9", - "@babel/plugin-transform-react-jsx-self": "^7.22.5", - "@babel/plugin-transform-react-jsx-source": "^7.22.5", - "react-refresh": "^0.14.0" + "@babel/core": "^7.28.4", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.35", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^20.19.0 || >=22.12.0" }, "peerDependencies": { - "vite": "^4.2.0" + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "node_modules/@vue/compiler-core": { - "version": "3.3.10", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.21.tgz", + "integrity": "sha512-8i+LZ0vf6ZgII5Z9XmUvrCyEzocvWT+TeR2VBUVlzIH6Tyv57E20mPZ1bCS+tbejgUgmjrEh7q/0F0bibskAmw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@babel/parser": "^7.23.5", - "@vue/shared": "3.3.10", + "@babel/parser": "^7.28.3", + "@vue/shared": "3.5.21", + "entities": "^4.5.0", "estree-walker": "^2.0.2", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.3.10", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.21.tgz", + "integrity": "sha512-jNtbu/u97wiyEBJlJ9kmdw7tAr5Vy0Aj5CgQmo+6pxWNQhXZDPsRr1UWPN4v3Zf82s2H3kF51IbzZ4jMWAgPlQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@vue/compiler-core": "3.3.10", - "@vue/shared": "3.3.10" + "@vue/compiler-core": "3.5.21", + "@vue/shared": "3.5.21" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.3.10", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.21.tgz", + "integrity": "sha512-SXlyk6I5eUGBd2v8Ie7tF6ADHE9kCR6mBEuPyH1nUZ0h6Xx6nZI29i12sJKQmzbDyr2tUHMhhTt51Z6blbkTTQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@babel/parser": "^7.23.5", - "@vue/compiler-core": "3.3.10", - "@vue/compiler-dom": "3.3.10", - "@vue/compiler-ssr": "3.3.10", - "@vue/reactivity-transform": "3.3.10", - "@vue/shared": "3.3.10", + "@babel/parser": "^7.28.3", + "@vue/compiler-core": "3.5.21", + "@vue/compiler-dom": "3.5.21", + "@vue/compiler-ssr": "3.5.21", + "@vue/shared": "3.5.21", "estree-walker": "^2.0.2", - "magic-string": "^0.30.5", - "postcss": "^8.4.32", - "source-map-js": "^1.0.2" + "magic-string": "^0.30.18", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" } }, - "node_modules/@vue/compiler-sfc/node_modules/postcss": { - "version": "8.4.32", + "node_modules/@vue/compiler-ssr": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.21.tgz", + "integrity": "sha512-vKQ5olH5edFZdf5ZrlEgSO1j1DMA4u23TVK5XR1uMhvwnYvVdDF0nHXJUblL/GvzlShQbjhZZ2uvYmDlAbgo9w==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", + "peer": true, "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" + "@vue/compiler-dom": "3.5.21", + "@vue/shared": "3.5.21" } }, - "node_modules/@vue/compiler-ssr": { - "version": "3.3.10", + "node_modules/@vue/reactivity": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.21.tgz", + "integrity": "sha512-3ah7sa+Cwr9iiYEERt9JfZKPw4A2UlbY8RbbnH2mGCE8NwHkhmlZt2VsH0oDA3P08X3jJd29ohBDtX+TbD9AsA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@vue/compiler-dom": "3.3.10", - "@vue/shared": "3.3.10" + "@vue/shared": "3.5.21" } }, - "node_modules/@vue/reactivity-transform": { - "version": "3.3.10", + "node_modules/@vue/runtime-core": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.21.tgz", + "integrity": "sha512-+DplQlRS4MXfIf9gfD1BOJpk5RSyGgGXD/R+cumhe8jdjUcq/qlxDawQlSI8hCKupBlvM+3eS1se5xW+SuNAwA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@babel/parser": "^7.23.5", - "@vue/compiler-core": "3.3.10", - "@vue/shared": "3.3.10", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.5" + "@vue/reactivity": "3.5.21", + "@vue/shared": "3.5.21" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.21.tgz", + "integrity": "sha512-3M2DZsOFwM5qI15wrMmNF5RJe1+ARijt2HM3TbzBbPSuBHOQpoidE+Pa+XEaVN+czbHf81ETRoG1ltztP2em8w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@vue/reactivity": "3.5.21", + "@vue/runtime-core": "3.5.21", + "@vue/shared": "3.5.21", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.21.tgz", + "integrity": "sha512-qr8AqgD3DJPJcGvLcJKQo2tAc8OnXRcfxhOJCPF+fcfn5bBGz7VCcO7t+qETOPxpWK1mgysXvVT/j+xWaHeMWA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@vue/compiler-ssr": "3.5.21", + "@vue/shared": "3.5.21" + }, + "peerDependencies": { + "vue": "3.5.21" } }, "node_modules/@vue/shared": { - "version": "3.3.10", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.21.tgz", + "integrity": "sha512-+2k1EQpnYuVuu3N7atWyG3/xoFWIVJZq4Mz8XNOdScFI0etES75fbny/oU4lKWk/577P1zmg0ioYvpGEDZ3DLw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@whatwg-node/events": { "version": "0.0.3", @@ -6268,6 +7406,28 @@ "dev": true, "license": "ISC" }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.14.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", @@ -6396,6 +7556,7 @@ }, "node_modules/ansi-styles": { "version": "3.2.1", + "dev": true, "license": "MIT", "dependencies": { "color-convert": "^1.9.0" @@ -6406,7 +7567,7 @@ }, "node_modules/anymatch": { "version": "3.1.3", - "dev": true, + "devOptional": true, "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", @@ -6446,6 +7607,12 @@ "node": ">=0.10.0" } }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, "node_modules/array-ify": { "version": "1.0.0", "dev": true, @@ -6666,6 +7833,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/babel-dead-code-elimination": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/babel-dead-code-elimination/-/babel-dead-code-elimination-1.0.10.tgz", + "integrity": "sha512-DV5bdJZTzZ0zn0DC24v3jD7Mnidh6xhKa4GfKCbq3sfW8kaWhDdZjP3i81geA8T33tdYqWKw4D3fVv0CwEgKVA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.7", + "@babel/parser": "^7.23.6", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "dev": true, @@ -6831,6 +8010,15 @@ "node": ">=10" } }, + "node_modules/babel-plugin-macros/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/babel-plugin-syntax-trailing-function-commas": { "version": "7.0.0-beta.0", "dev": true, @@ -6935,6 +8123,33 @@ ], "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.6.tgz", + "integrity": "sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/big-integer": { "version": "1.6.52", "dev": true, @@ -6945,7 +8160,7 @@ }, "node_modules/binary-extensions": { "version": "2.2.0", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=8" @@ -6961,6 +8176,60 @@ "readable-stream": "^3.4.0" } }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/boolbase": { "version": "1.0.0", "license": "ISC" @@ -6988,7 +8257,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, + "devOptional": true, "dependencies": { "fill-range": "^7.1.1" }, @@ -7065,8 +8334,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.2", - "dev": true, + "version": "4.26.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.2.tgz", + "integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==", "funding": [ { "type": "opencollective", @@ -7083,10 +8353,11 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "baseline-browser-mapping": "^2.8.3", + "caniuse-lite": "^1.0.30001741", + "electron-to-chromium": "^1.5.218", + "node-releases": "^2.0.21", + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -7149,9 +8420,7 @@ }, "node_modules/buffer-from": { "version": "1.1.2", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/bump-package-versions": { "version": "1.0.7", @@ -7193,6 +8462,24 @@ "node": ">=10.16.0" } }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/call-bind": { "version": "1.0.5", "dev": true, @@ -7206,6 +8493,35 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "license": "MIT", @@ -7247,9 +8563,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001712", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001712.tgz", - "integrity": "sha512-MBqPpGYYdQ7/hfKiet9SCI+nmN5/hp4ZzveOJubl5DTAMa5oggjAuoi0Z4onBpKPFI2ePGnQuQIzF3VxDjDJig==", + "version": "1.0.30001743", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001743.tgz", + "integrity": "sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==", "funding": [ { "type": "opencollective", @@ -7285,6 +8601,7 @@ }, "node_modules/chalk": { "version": "2.4.2", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", @@ -7381,7 +8698,7 @@ }, "node_modules/chokidar": { "version": "3.5.3", - "dev": true, + "devOptional": true, "funding": [ { "type": "individual", @@ -7574,6 +8891,7 @@ }, "node_modules/color-convert": { "version": "1.9.3", + "dev": true, "license": "MIT", "dependencies": { "color-name": "1.1.3" @@ -7581,6 +8899,7 @@ }, "node_modules/color-name": { "version": "1.1.3", + "dev": true, "license": "MIT" }, "node_modules/colorette": { @@ -7623,6 +8942,51 @@ "dot-prop": "^5.1.0" } }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "license": "MIT" @@ -7646,6 +9010,27 @@ "upper-case": "^2.0.2" } }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/conventional-changelog-angular": { "version": "6.0.0", "dev": true, @@ -7687,7 +9072,21 @@ }, "node_modules/convert-source-map": { "version": "2.0.0", - "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, "node_modules/copy-to-clipboard": { @@ -7980,7 +9379,9 @@ "dev": true }, "node_modules/csstype": { - "version": "3.1.2", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, "node_modules/d": { @@ -8151,10 +9552,10 @@ } }, "node_modules/dedent": { - "version": "1.5.1", - "dev": true, + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", + "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", "license": "MIT", - "peer": true, "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, @@ -8368,6 +9769,15 @@ "node": ">=0.4.0" } }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/dependency-cruiser": { "version": "16.10.2", "resolved": "https://registry.npmjs.org/dependency-cruiser/-/dependency-cruiser-16.10.2.tgz", @@ -8464,6 +9874,16 @@ "node": ">= 0.6.0" } }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, "node_modules/detect-indent": { "version": "6.1.0", "dev": true, @@ -8776,6 +10196,20 @@ "node": ">=4" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/duplexer": { "version": "0.1.2", "license": "MIT" @@ -8842,6 +10276,12 @@ "node": ">=10" } }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, "node_modules/ejs": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", @@ -8857,8 +10297,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.607", - "dev": true, + "version": "1.5.222", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.222.tgz", + "integrity": "sha512-gA7psSwSwQRE60CEoLz6JBCQPIxNeuzB2nL8vE03GK/OHxlvykbLyeiumQy1iH5C2f3YbRAZpGCMT12a/9ih9w==", "license": "ISC" }, "node_modules/emittery": { @@ -8877,6 +10318,15 @@ "version": "8.0.0", "license": "MIT" }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/encoding": { "version": "0.1.13", "license": "MIT", @@ -8971,6 +10421,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT" + }, "node_modules/error-ex": { "version": "1.3.2", "license": "MIT", @@ -9035,6 +10491,24 @@ "dev": true, "license": "MIT" }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-iterator-helpers": { "version": "1.0.15", "dev": true, @@ -9056,6 +10530,24 @@ "safe-array-concat": "^1.0.1" } }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { "version": "2.0.2", "dev": true, @@ -9146,90 +10638,98 @@ } }, "node_modules/esbuild": { - "version": "0.18.20", - "dev": true, + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz", + "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", "hasInstallScript": true, "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" + "@esbuild/aix-ppc64": "0.25.10", + "@esbuild/android-arm": "0.25.10", + "@esbuild/android-arm64": "0.25.10", + "@esbuild/android-x64": "0.25.10", + "@esbuild/darwin-arm64": "0.25.10", + "@esbuild/darwin-x64": "0.25.10", + "@esbuild/freebsd-arm64": "0.25.10", + "@esbuild/freebsd-x64": "0.25.10", + "@esbuild/linux-arm": "0.25.10", + "@esbuild/linux-arm64": "0.25.10", + "@esbuild/linux-ia32": "0.25.10", + "@esbuild/linux-loong64": "0.25.10", + "@esbuild/linux-mips64el": "0.25.10", + "@esbuild/linux-ppc64": "0.25.10", + "@esbuild/linux-riscv64": "0.25.10", + "@esbuild/linux-s390x": "0.25.10", + "@esbuild/linux-x64": "0.25.10", + "@esbuild/netbsd-arm64": "0.25.10", + "@esbuild/netbsd-x64": "0.25.10", + "@esbuild/openbsd-arm64": "0.25.10", + "@esbuild/openbsd-x64": "0.25.10", + "@esbuild/openharmony-arm64": "0.25.10", + "@esbuild/sunos-x64": "0.25.10", + "@esbuild/win32-arm64": "0.25.10", + "@esbuild/win32-ia32": "0.25.10", + "@esbuild/win32-x64": "0.25.10" } }, "node_modules/esbuild/node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", + "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/esbuild/node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", + "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", "cpu": [ "x64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/esbuild/node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", + "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", "cpu": [ "x64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/escalade": { - "version": "3.1.1", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "license": "MIT", "engines": { "node": ">=6" @@ -9241,6 +10741,7 @@ }, "node_modules/escape-string-regexp": { "version": "1.0.5", + "dev": true, "license": "MIT", "engines": { "node": ">=0.8.0" @@ -9770,6 +11271,8 @@ }, "node_modules/estree-walker": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true, "license": "MIT" }, @@ -9781,6 +11284,15 @@ "node": ">=0.10.0" } }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", @@ -9830,6 +11342,18 @@ "node": ">= 0.8.0" } }, + "node_modules/exit-hook": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", + "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/expect": { "version": "29.7.0", "dev": true, @@ -9845,6 +11369,91 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/express/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/ext": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", @@ -10059,21 +11668,54 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, + "devOptional": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/filter-obj": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/filter-obj": { - "version": "1.1.0", + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "ms": "2.0.0" } }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/find-root": { "version": "1.1.0", "license": "MIT" @@ -10157,6 +11799,24 @@ "node": ">= 6" } }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fs-extra": { "version": "11.2.0", "dev": true, @@ -10178,7 +11838,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -10222,7 +11881,6 @@ }, "node_modules/gensync": { "version": "1.0.0-beta.2", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -10236,14 +11894,24 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "dev": true, + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -10258,6 +11926,31 @@ "node": ">=8.0.0" } }, + "node_modules/get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "6.0.1", "dev": true, @@ -10322,7 +12015,7 @@ }, "node_modules/glob-parent": { "version": "5.1.2", - "dev": true, + "devOptional": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -10415,11 +12108,12 @@ "license": "MIT" }, "node_modules/gopd": { - "version": "1.0.1", - "dev": true, + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -10620,6 +12314,7 @@ }, "node_modules/has-flag": { "version": "3.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -10648,8 +12343,9 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "dev": true, + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -10673,7 +12369,9 @@ } }, "node_modules/hasown": { - "version": "2.0.0", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -10819,6 +12517,22 @@ "entities": "^4.4.0" } }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/http-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", @@ -10913,7 +12627,6 @@ }, "node_modules/iconv-lite": { "version": "0.4.24", - "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" @@ -11166,6 +12879,15 @@ "loose-envify": "^1.0.0" } }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/is-absolute": { "version": "1.0.0", "dev": true, @@ -11222,7 +12944,7 @@ }, "node_modules/is-binary-path": { "version": "2.1.0", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" @@ -11296,7 +13018,7 @@ }, "node_modules/is-extglob": { "version": "2.1.1", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11345,7 +13067,7 @@ }, "node_modules/is-glob": { "version": "4.0.3", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -11458,7 +13180,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.12.0" } @@ -11710,6 +13432,15 @@ "dev": true, "license": "MIT" }, + "node_modules/isbot": { + "version": "5.1.30", + "resolved": "https://registry.npmjs.org/isbot/-/isbot-5.1.30.tgz", + "integrity": "sha512-3wVJEonAns1OETX83uWsk5IAne2S5zfDcntD2hbtU23LelSqNXzXs9zKjMPOLMzroCgIjCfjYAEHrd2D6FOkiA==", + "license": "Unlicense", + "engines": { + "node": ">=18" + } + }, "node_modules/isexe": { "version": "2.0.0", "license": "ISC" @@ -13751,7 +15482,7 @@ "version": "1.21.6", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", - "dev": true, + "devOptional": true, "bin": { "jiti": "bin/jiti.js" } @@ -13765,6 +15496,35 @@ "url": "https://github.com/sponsors/panva" } }, + "node_modules/jotai": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/jotai/-/jotai-2.14.0.tgz", + "integrity": "sha512-JQkNkTnqjk1BlSUjHfXi+pGG/573bVN104gp6CymhrWDseZGDReTNniWrLhJ+zXbM6pH+82+UNJ2vwYQUkQMWQ==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0", + "@babel/template": ">=7.0.0", + "@types/react": ">=17.0.0", + "react": ">=17.0.0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@babel/template": { + "optional": true + }, + "@types/react": { + "optional": true + }, + "react": { + "optional": true + } + } + }, "node_modules/js-beautify": { "version": "1.15.4", "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz", @@ -13990,14 +15750,15 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "dev": true, + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-buffer": { @@ -14033,7 +15794,6 @@ }, "node_modules/json5": { "version": "2.2.3", - "dev": true, "license": "MIT", "bin": { "json5": "lib/cli.js" @@ -14906,7 +16666,6 @@ }, "node_modules/lru-cache": { "version": "5.1.1", - "dev": true, "license": "ISC", "dependencies": { "yallist": "^3.0.2" @@ -14922,14 +16681,14 @@ } }, "node_modules/magic-string": { - "version": "0.30.5", + "version": "0.30.19", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", + "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - }, - "engines": { - "node": ">=12" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/make-dir": { @@ -15029,11 +16788,29 @@ "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==", "peer": true }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mdn-data": { "version": "2.0.30", "dev": true, "license": "CC0-1.0" }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/memoize": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/memoize/-/memoize-10.1.0.tgz", @@ -15108,6 +16885,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "dev": true, @@ -15138,6 +16924,15 @@ } } }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/micromatch": { "version": "4.0.5", "dev": true, @@ -15150,6 +16945,18 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/mime-db": { "version": "1.52.0", "license": "MIT", @@ -15249,6 +17056,49 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/morgan": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz", + "integrity": "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==", + "license": "MIT", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.1.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/ms": { "version": "2.1.2", "license": "MIT" @@ -15259,8 +17109,9 @@ "license": "ISC" }, "node_modules/nanoid": { - "version": "3.3.7", - "dev": true, + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "funding": [ { "type": "github", @@ -15311,6 +17162,15 @@ "dev": true, "license": "MIT" }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/next-tick": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", @@ -15350,8 +17210,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.14", - "dev": true, + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", + "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", "license": "MIT" }, "node_modules/nopt": { @@ -15412,17 +17273,125 @@ }, "node_modules/normalize-path": { "version": "3.0.0", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/npm-install-checks": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", + "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", + "license": "BSD-2-Clause", + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-install-checks/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/npm-normalize-package-bin": { "version": "1.0.1", "dev": true, "license": "ISC" }, + "node_modules/npm-package-arg": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", + "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", + "license": "ISC", + "dependencies": { + "hosted-git-info": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg/node_modules/hosted-git-info": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.3.tgz", + "integrity": "sha512-HVJyzUrLIL1c0QmviVh5E8VGyUS7xCFPS6yydaVd1UegW+ibV/CohqTH9MkOLDp5o+rb82DMo77PTuc9F/8GKw==", + "license": "ISC", + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/npm-package-arg/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-pick-manifest": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.2.tgz", + "integrity": "sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==", + "license": "ISC", + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^10.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-pick-manifest/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "dev": true, @@ -15455,32 +17424,6 @@ "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", "license": "MIT" }, - "node_modules/oaf-react-router": { - "version": "2.1.1", - "license": "MIT", - "dependencies": { - "oaf-routing": "^3.0.0" - }, - "peerDependencies": { - "history": "^4.9.0" - } - }, - "node_modules/oaf-routing": { - "version": "3.0.1", - "license": "MIT", - "dependencies": { - "oaf-side-effects": "^2.0.0", - "unique-selector": "^0.4.1" - } - }, - "node_modules/oaf-routing/node_modules/unique-selector": { - "version": "0.4.1", - "license": "MIT" - }, - "node_modules/oaf-side-effects": { - "version": "2.1.0", - "license": "MIT" - }, "node_modules/object-assign": { "version": "4.1.1", "license": "MIT", @@ -15489,9 +17432,13 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", - "dev": true, + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -15604,6 +17551,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "license": "ISC", @@ -15890,6 +17858,15 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/pascal-case": { "version": "3.1.2", "dev": true, @@ -15974,15 +17951,9 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" }, "node_modules/path-to-regexp": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", - "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/path-to-regexp/node_modules/isarray": { - "version": "0.0.1", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "license": "MIT" }, "node_modules/path-type": { @@ -15992,6 +17963,12 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "license": "MIT" + }, "node_modules/perfect-scrollbar": { "version": "1.5.5", "license": "MIT" @@ -16004,12 +17981,11 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -16110,6 +18086,34 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "dev": true, @@ -16181,6 +18185,15 @@ "node": ">=6" } }, + "node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/promise": { "version": "7.3.1", "license": "MIT", @@ -16188,6 +18201,25 @@ "asap": "~2.0.3" } }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "license": "ISC" + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/prompts": { "version": "2.4.2", "dev": true, @@ -16223,6 +18255,19 @@ "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -16359,6 +18404,30 @@ "node": ">=0.12" } }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/react": { "version": "18.2.0", "license": "MIT", @@ -16629,49 +18698,10 @@ "react-dom": "^16.8.0-0 || ^17.0.0-0 || ^18.0.0-0" } }, - "node_modules/react-redux": { - "version": "8.1.2", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.12.1", - "@types/hoist-non-react-statics": "^3.3.1", - "@types/use-sync-external-store": "^0.0.3", - "hoist-non-react-statics": "^3.3.2", - "react-is": "^18.0.0", - "use-sync-external-store": "^1.0.0" - }, - "peerDependencies": { - "@types/react": "^16.8 || ^17.0 || ^18.0", - "@types/react-dom": "^16.8 || ^17.0 || ^18.0", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0", - "react-native": ">=0.59", - "redux": "^4 || ^5.0.0-beta.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - }, - "redux": { - "optional": true - } - } - }, - "node_modules/react-redux/node_modules/react-is": { - "version": "18.2.0", - "license": "MIT" - }, "node_modules/react-refresh": { - "version": "0.14.0", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", "dev": true, "license": "MIT", "engines": { @@ -16679,43 +18709,44 @@ } }, "node_modules/react-router": { - "version": "5.3.4", + "version": "7.9.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.1.tgz", + "integrity": "sha512-pfAByjcTpX55mqSDGwGnY9vDCpxqBLASg0BMNAuMmpSGESo/TaOUG6BllhAtAkCGx8Rnohik/XtaqiYUJtgW2g==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.2", - "react-is": "^16.6.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" }, "peerDependencies": { - "react": ">=15" + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } } }, "node_modules/react-router-dom": { - "version": "5.3.4", + "version": "7.9.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.9.1.tgz", + "integrity": "sha512-U9WBQssBE9B1vmRjo9qTM7YRzfZ3lUxESIZnsf4VjR/lXYz9MHjvOxHzr/aUm4efpktbVOrF09rL/y4VHa8RMw==", "license": "MIT", + "peer": true, "dependencies": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-router": "5.3.4", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "react-router": "7.9.1" + }, + "engines": { + "node": ">=20.0.0" }, "peerDependencies": { - "react": ">=15" + "react": ">=18", + "react-dom": ">=18" } }, - "node_modules/react-router/node_modules/react-is": { - "version": "16.13.1", - "license": "MIT" - }, "node_modules/react-select": { "version": "5.7.4", "license": "MIT", @@ -17015,7 +19046,7 @@ }, "node_modules/readdirp": { "version": "3.6.0", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "picomatch": "^2.2.1" @@ -17049,35 +19080,6 @@ "node": ">=8" } }, - "node_modules/redux": { - "version": "4.2.1", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.9.2" - } - }, - "node_modules/redux-devtools-extension": { - "version": "2.13.9", - "license": "MIT", - "peerDependencies": { - "redux": "^3.1.0 || ^4.0.0" - } - }, - "node_modules/redux-mock-store": { - "version": "1.5.4", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash.isplainobject": "^4.0.6" - } - }, - "node_modules/redux-thunk": { - "version": "2.4.2", - "license": "MIT", - "peerDependencies": { - "redux": "^4" - } - }, "node_modules/reflect.getprototypeof": { "version": "1.0.4", "dev": true, @@ -17341,6 +19343,15 @@ "node": ">=0.12" } }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/reusify": { "version": "1.0.4", "dev": true, @@ -17517,7 +19528,6 @@ }, "node_modules/safe-buffer": { "version": "5.2.1", - "dev": true, "funding": [ { "type": "github", @@ -17563,7 +19573,7 @@ }, "node_modules/sass": { "version": "1.68.0", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -17579,7 +19589,7 @@ }, "node_modules/sass/node_modules/immutable": { "version": "4.3.4", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/saxes": { @@ -17616,12 +19626,65 @@ }, "node_modules/semver": { "version": "6.3.1", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" } }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/sentence-case": { "version": "3.0.4", "dev": true, @@ -17633,10 +19696,24 @@ } }, "node_modules/serialize-query-params": { - "version": "1.3.6", - "license": "ISC", - "peerDependencies": { - "query-string": ">=5.1.1" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/serialize-query-params/-/serialize-query-params-2.0.2.tgz", + "integrity": "sha512-1chMo1dST4pFA9RDXAtF0Rbjaut4is7bzFbI1Z26IuMub68pNCILku85aYmeFhvnY//BXUPUhoRMjYcsT93J/Q==", + "license": "ISC" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" } }, "node_modules/set-blocking": { @@ -17644,6 +19721,12 @@ "dev": true, "license": "ISC" }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, "node_modules/set-function-length": { "version": "1.1.1", "dev": true, @@ -17675,39 +19758,104 @@ "version": "1.0.5", "license": "MIT" }, - "node_modules/shebang-command": { - "version": "2.0.0", + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "license": "MIT", "dependencies": { - "shebang-regex": "^3.0.0" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/shell-quote": { - "version": "1.8.1", - "dev": true, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/side-channel": { - "version": "1.0.4", - "dev": true, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -17798,7 +19946,6 @@ }, "node_modules/source-map": { "version": "0.6.1", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -17939,8 +20086,9 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "dev": true, + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -17977,7 +20125,6 @@ }, "node_modules/spdx-correct": { "version": "3.2.0", - "dev": true, "license": "Apache-2.0", "dependencies": { "spdx-expression-parse": "^3.0.0", @@ -17986,12 +20133,10 @@ }, "node_modules/spdx-exceptions": { "version": "2.3.0", - "dev": true, "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", - "dev": true, "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", @@ -18000,7 +20145,6 @@ }, "node_modules/spdx-license-ids": { "version": "3.0.16", - "dev": true, "license": "CC0-1.0" }, "node_modules/spdx-ranges": { @@ -18066,6 +20210,15 @@ "node": ">=8" } }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -18271,6 +20424,7 @@ }, "node_modules/supports-color": { "version": "5.5.0", + "dev": true, "license": "MIT", "dependencies": { "has-flag": "^3.0.0" @@ -18291,6 +20445,8 @@ }, "node_modules/svg-parser": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", "dev": true, "license": "MIT" }, @@ -18469,6 +20625,51 @@ "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", "peer": true }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/title-case": { "version": "3.0.3", "dev": true, @@ -18530,13 +20731,6 @@ "to-space-case": "^1.0.0" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-no-case": { "version": "1.0.2", "license": "MIT" @@ -18545,7 +20739,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, + "devOptional": true, "dependencies": { "is-number": "^7.0.0" }, @@ -18571,6 +20765,15 @@ "version": "1.0.6", "license": "MIT" }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, "node_modules/toposort": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", @@ -18769,17 +20972,19 @@ } }, "node_modules/tsconfck": { - "version": "2.1.2", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz", + "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==", "dev": true, "license": "MIT", "bin": { "tsconfck": "bin/tsconfck.js" }, "engines": { - "node": "^14.13.1 || ^16 || >=18" + "node": "^18 || >=20" }, "peerDependencies": { - "typescript": "^4.3.5 || ^5.0.0" + "typescript": "^5.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -18994,6 +21199,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.0", "dev": true, @@ -19057,7 +21275,7 @@ }, "node_modules/typescript": { "version": "5.1.6", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -19143,6 +21361,15 @@ "node": ">=0.10.0" } }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/untildify": { "version": "4.0.0", "dev": true, @@ -19152,8 +21379,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "dev": true, + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "funding": [ { "type": "opencollective", @@ -19170,8 +21398,8 @@ ], "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -19233,15 +21461,26 @@ } }, "node_modules/use-query-params": { - "version": "1.2.3", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/use-query-params/-/use-query-params-2.2.1.tgz", + "integrity": "sha512-i6alcyLB8w9i3ZK3caNftdb+UnbfBRNPDnc89CNQWkGRmDrm/gfydHvMBfVsQJRq3NoHOM2dt/ceBWG2397v1Q==", "license": "ISC", "dependencies": { - "serialize-query-params": "^1.3.5" + "serialize-query-params": "^2.0.2" }, "peerDependencies": { - "query-string": ">=5.1.1", + "@reach/router": "^1.2.1", "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "react-dom": ">=16.8.0", + "react-router-dom": ">=5" + }, + "peerDependenciesMeta": { + "@reach/router": { + "optional": true + }, + "react-router-dom": { + "optional": true + } } }, "node_modules/use-sync-external-store": { @@ -19261,6 +21500,15 @@ "dev": true, "license": "MIT" }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/uuid": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", @@ -19294,15 +21542,37 @@ "node": ">=10.12.0" } }, + "node_modules/valibot": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/valibot/-/valibot-0.41.0.tgz", + "integrity": "sha512-igDBb8CTYr8YTQlOKgaN9nSS0Be7z+WRuaeYqGf3Cjz3aKmSnqEmYnkfVjzIuumGqfHpa3fLIvMEAfhrpqN8ng==", + "license": "MIT", + "peerDependencies": { + "typescript": ">=5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", - "dev": true, "license": "Apache-2.0", "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, + "node_modules/validate-npm-package-name": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/value-equal": { "version": "1.0.1", "license": "MIT" @@ -19316,41 +21586,60 @@ "node": ">=12" } }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/vite": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.5.tgz", - "integrity": "sha512-ifW3Lb2sMdX+WU91s3R0FyQlAyLxOzCSCP37ujw0+r5POeHPwe6udWVIElKQq8gk3t7b8rkmvqC6IHBpCff4GQ==", - "dev": true, + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.6.tgz", + "integrity": "sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA==", + "license": "MIT", "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.27", - "rollup": "^3.27.1" + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" }, "optionalDependencies": { - "fsevents": "~2.3.2" + "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": ">= 14", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", + "sass-embedded": "*", "stylus": "*", "sugarss": "*", - "terser": "^5.4.0" + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, + "jiti": { + "optional": true + }, "less": { "optional": true }, @@ -19360,6 +21649,9 @@ "sass": { "optional": true }, + "sass-embedded": { + "optional": true + }, "stylus": { "optional": true }, @@ -19368,11 +21660,70 @@ }, "terser": { "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite-node/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true } } }, + "node_modules/vite-node/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/vite-node/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" + }, "node_modules/vite-plugin-css-injected-by-js": { - "version": "3.3.0", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-3.5.2.tgz", + "integrity": "sha512-2MpU/Y+SCZyWUB6ua3HbJCrgnF0KACAsmzOQt1UvRVJCGF6S8xdA3ZUhWcWdM9ivG4I5az8PnQmwwrkC2CAQrQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -19380,35 +21731,43 @@ } }, "node_modules/vite-plugin-svgr": { - "version": "3.2.0", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.5.0.tgz", + "integrity": "sha512-W+uoSpmVkSmNOGPSsDCWVW/DDAyv+9fap9AZXBvWiQqrboJ08j2vh0tFxTD/LjwqwAd3yYSVJgm54S/1GhbdnA==", "dev": true, "license": "MIT", "dependencies": { - "@rollup/pluginutils": "^5.0.2", - "@svgr/core": "^7.0.0", - "@svgr/plugin-jsx": "^7.0.0" + "@rollup/pluginutils": "^5.2.0", + "@svgr/core": "^8.1.0", + "@svgr/plugin-jsx": "^8.1.0" }, "peerDependencies": { - "vite": "^2.6.0 || 3 || 4" + "vite": ">=2.6.0" } }, "node_modules/vite-svg-loader": { - "version": "4.0.0", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/vite-svg-loader/-/vite-svg-loader-5.1.0.tgz", + "integrity": "sha512-M/wqwtOEjgb956/+m5ZrYT/Iq6Hax0OakWbokj8+9PXOnB7b/4AxESHieEtnNEy7ZpjsjYW1/5nK8fATQMmRxw==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-sfc": "^3.2.20", "svgo": "^3.0.2" + }, + "peerDependencies": { + "vue": ">=3.2.13" } }, "node_modules/vite-tsconfig-paths": { - "version": "4.2.1", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.1.4.tgz", + "integrity": "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==", "dev": true, "license": "MIT", "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", - "tsconfck": "^2.1.0" + "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" @@ -19419,45 +21778,73 @@ } } }, - "node_modules/vite/node_modules/postcss": { - "version": "8.4.32", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "license": "MIT", - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/vite/node_modules/rollup": { - "version": "3.29.4", - "dev": true, + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.0.tgz", + "integrity": "sha512-+IuescNkTJQgX7AkIDtITipZdIGcWF0pnVvZTWStiazUmcGA2ag8dfg0urest2XlXUi9kuhfQ+qmdc5Stc3z7g==", "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=14.18.0", + "node": ">=18.0.0", "npm": ">=8.0.0" }, "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.52.0", + "@rollup/rollup-android-arm64": "4.52.0", + "@rollup/rollup-darwin-arm64": "4.52.0", + "@rollup/rollup-darwin-x64": "4.52.0", + "@rollup/rollup-freebsd-arm64": "4.52.0", + "@rollup/rollup-freebsd-x64": "4.52.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.0", + "@rollup/rollup-linux-arm-musleabihf": "4.52.0", + "@rollup/rollup-linux-arm64-gnu": "4.52.0", + "@rollup/rollup-linux-arm64-musl": "4.52.0", + "@rollup/rollup-linux-loong64-gnu": "4.52.0", + "@rollup/rollup-linux-ppc64-gnu": "4.52.0", + "@rollup/rollup-linux-riscv64-gnu": "4.52.0", + "@rollup/rollup-linux-riscv64-musl": "4.52.0", + "@rollup/rollup-linux-s390x-gnu": "4.52.0", + "@rollup/rollup-linux-x64-gnu": "4.52.0", + "@rollup/rollup-linux-x64-musl": "4.52.0", + "@rollup/rollup-openharmony-arm64": "4.52.0", + "@rollup/rollup-win32-arm64-msvc": "4.52.0", + "@rollup/rollup-win32-ia32-msvc": "4.52.0", + "@rollup/rollup-win32-x64-gnu": "4.52.0", + "@rollup/rollup-win32-x64-msvc": "4.52.0", "fsevents": "~2.3.2" } }, @@ -19468,6 +21855,29 @@ "node": ">=0.10.0" } }, + "node_modules/vue": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.21.tgz", + "integrity": "sha512-xxf9rum9KtOdwdRkiApWL+9hZEMWE90FHh8yS1+KJAiWYh+iGWV1FquPjoO9VUHQ+VIhsCXNNyZ5Sf4++RVZBA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@vue/compiler-dom": "3.5.21", + "@vue/compiler-sfc": "3.5.21", + "@vue/runtime-dom": "3.5.21", + "@vue/server-renderer": "3.5.21", + "@vue/shared": "3.5.21" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", @@ -19836,14 +22246,19 @@ }, "node_modules/yallist": { "version": "3.1.1", - "dev": true, "license": "ISC" }, "node_modules/yaml": { - "version": "1.10.2", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "devOptional": true, "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, "engines": { - "node": ">= 6" + "node": ">= 14.6" } }, "node_modules/yaml-ast-parser": { diff --git a/package.json b/package.json index 54f53b310b..5ec17797d8 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,9 @@ "@meemoo/admin-core-ui": "4.5.26", "@meemoo/react-components": "4.3.2", "@popperjs/core": "2.11.6", + "@react-router/dev": "^7.9.1", + "@react-router/node": "^7.9.1", + "@react-router/serve": "^7.9.1", "@studiohyperdrive/pagination": "1.0.0", "@tanstack/react-query": "4.36.1", "@uidotdev/usehooks": "^2.4.1", @@ -62,10 +65,10 @@ "i18next-xhr-backend": "3.2.2", "immer": "9.0.12", "isomorphic-dompurify": "2.16.0", + "jotai": "2.14.0", "lodash-es": "4.17.21", "marked": "4.0.15", "node-fetch": "2.7.0", - "oaf-react-router": "2.1.1", "query-string": "7.1.1", "raf": "3.4.1", "react": "18.2.0", @@ -83,23 +86,18 @@ "react-perfect-scrollbar": "1.5.8", "react-popper": "2.3.0", "react-range": "1.8.14", - "react-redux": "8.1.2", - "react-router": "5.3.4", - "react-router-dom": "5.3.4", + "react-router": "^7.9.1", "react-select": "5.7.4", "react-table": "7.7.0", "react-to-string": "0.1.1", "react-toastify": "5.5.0", "react-zendesk": "0.1.13", - "redux": "4.2.1", - "redux-devtools-extension": "2.13.9", - "redux-thunk": "2.4.2", "rollup-plugin-sourcemaps": "^0.6.3", "source-map-explorer": "2.5.3", "to-camel-case": "1.0.0", "to-slug-case": "1.0.0", "ts-retry-promise": "0.8.1", - "use-query-params": "1.2.3", + "use-query-params": "2.2.1", "yup": "1.4.0" }, "devDependencies": { @@ -135,14 +133,12 @@ "@types/react-dom": "18.2.7", "@types/react-helmet": "6.1.6", "@types/react-modal": "3.16.0", - "@types/react-redux": "6.0.22", - "@types/react-router-dom": "5.3.3", "@types/to-camel-case": "^1.0.2", "@types/to-slug-case": "^1.0.2", "@types/uuid": "10.0.0", "@typescript-eslint/eslint-plugin": "5.62.0", "@typescript-eslint/parser": "5.62.0", - "@vitejs/plugin-react": "4.0.4", + "@vitejs/plugin-react": "^5.0.3", "bump-package-versions": "^1.0.7", "cross-env": "7.0.3", "dependency-cruiser": "^16.10.2", @@ -164,7 +160,6 @@ "lint-staged": "13.3.0", "lodash": "4.17.21", "prettier": "3.0.3", - "redux-mock-store": "1.5.4", "replace-in-file": "6.3.5", "rollup-plugin-sourcemaps": "0.6.3", "sass": "1.68.0", @@ -172,11 +167,11 @@ "ts-node": "10.9.1", "typescript": "5.1.6", "uuid": "10.0.0", - "vite": "4.5.5", - "vite-plugin-css-injected-by-js": "3.3.0", - "vite-plugin-svgr": "3.2.0", - "vite-svg-loader": "4.0.0", - "vite-tsconfig-paths": "4.2.1" + "vite": "6.3.6", + "vite-plugin-css-injected-by-js": "3.5.2", + "vite-plugin-svgr": "4.5.0", + "vite-svg-loader": "5.1.0", + "vite-tsconfig-paths": "5.1.4" }, "optionalDependencies": { "@esbuild/darwin-arm64": "^0.20.1", @@ -188,7 +183,10 @@ "react-dom": "18.2.0", "@types/react": "18.2.22", "@types/react-dom": "18.2.7", - "typescript": "5.1.6" + "typescript": "5.1.6", + "react-router": "^7.9.1", + "react-router-dom": "^7.9.1", + "use-query-params": "2.2.1" }, "browserslist": { "production": [ diff --git a/src/App.routes.ts b/src/App.routes.ts new file mode 100644 index 0000000000..3a29608bac --- /dev/null +++ b/src/App.routes.ts @@ -0,0 +1,542 @@ +import { PermissionName } from '@viaa/avo2-types'; +import { type MiddlewareFunction, redirect, type RouteObject } from 'react-router'; + +import { AppWithAdminCoreConfig } from './App'; +import { Admin } from './admin/Admin'; +import { AdminRedirect } from './admin/AdminRedirect'; +import { ASSIGNMENTS_PATH } from './admin/assignments/assignments.const'; +import { AssignmentMarcomOverview } from './admin/assignments/views/AssignmentsMarcomOverview'; +import { AssignmentOverviewAdmin } from './admin/assignments/views/AssignmentsOverviewAdmin'; +import { COLLECTIONS_OR_BUNDLES_PATH } from './admin/collectionsOrBundles/collections-or-bundles.const'; +import { CollectionOrBundleActualisationOverview } from './admin/collectionsOrBundles/views/CollectionOrBundleActualisationOverview'; +import { CollectionOrBundleMarcomOverview } from './admin/collectionsOrBundles/views/CollectionOrBundleMarcomOverview'; +import { CollectionOrBundleQualityCheckOverview } from './admin/collectionsOrBundles/views/CollectionOrBundleQualityCheckOverview'; +import { CollectionsOrBundlesOverview } from './admin/collectionsOrBundles/views/CollectionsOrBundlesOverview'; +import { CONTENT_PAGE_PATH } from './admin/content-page/content-page.consts'; +import ContentPageDetailPage from './admin/content-page/views/ContentPageDetailPage'; +import ContentPageEditPage from './admin/content-page/views/ContentPageEditPage'; +import { ContentPageOverviewPage } from './admin/content-page/views/ContentPageOverviewPage'; +import { CONTENT_PAGE_LABEL_PATH } from './admin/content-page-labels/content-page-label.const'; +import ContentPageLabelDetailPage from './admin/content-page-labels/views/ContentPageLabelDetailPage'; +import ContentPageLabelEditPage from './admin/content-page-labels/views/ContentPageLabelEditPage'; +import ContentPageLabelOverviewPage from './admin/content-page-labels/views/ContentPageLabelOverviewPage'; +import { Dashboard } from './admin/dashboard/views/Dashboard'; +import { INTERACTIVE_TOUR_PATH } from './admin/interactive-tour/interactive-tour.const'; +import { InteractiveTourDetail } from './admin/interactive-tour/views/InteractiveTourDetail'; +import { InteractiveTourEdit } from './admin/interactive-tour/views/InteractiveTourEdit'; +import { InteractiveTourOverview } from './admin/interactive-tour/views/InteractiveTourOverview'; +import { ITEMS_PATH } from './admin/items/items.const'; +import { ItemDetail } from './admin/items/views/ItemDetail'; +import { ItemsOverview } from './admin/items/views/ItemsOverview'; +import { PublishItemsOverview } from './admin/items/views/PublishItemsOverview'; +import { MaintenanceAlertsOverviewPage } from './admin/maintenance-alerts-overview/MaintenanceAlertsOverviewPage'; +import { NAVIGATIONS_PATH } from './admin/navigations/navigations.const'; +import { + NavigationBarDetail, + NavigationBarOverview, + NavigationItemEdit, +} from './admin/navigations/views'; +import { PUPIL_COLLECTIONS_PATH } from './admin/pupil-collection/pupil-collection.const'; +import { PupilCollectionsOverview } from './admin/pupil-collection/views/PupilCollectionsOverview'; +import { TRANSLATIONS_PATH } from './admin/translations/translations.const'; +import TranslationsOverviewPage from './admin/translations/views/TranslationsOverviewPage'; +import { USER_GROUP_PATH } from './admin/user-groups/user-group.const'; +import UserGroupOverviewPage from './admin/user-groups/views/UserGroupOverviewPage'; +import { USER_PATH } from './admin/users/user.const'; +import UserDetailPage from './admin/users/views/UserDetailPage'; +import { UserEditPage } from './admin/users/views/UserEditPage'; +import { UserOverviewPage } from './admin/users/views/UserOverviewPage'; +import { AssignmentDetailSwitcher } from './assignment/views/AssignmentDetailSwitcher'; +import { AssignmentEdit } from './assignment/views/AssignmentEdit'; +import { AssignmentPupilCollectionDetail } from './assignment/views/AssignmentPupilCollectionDetail'; +import { AssignmentResponseAdminEdit } from './assignment/views/AssignmentResponseEdit/AssignmentResponseAdminEdit'; +import { LinkYourAccount } from './authentication/views/LinkYourAccount'; +import { Login } from './authentication/views/Login'; +import { Logout } from './authentication/views/Logout'; +import { RegisterOrLogin } from './authentication/views/RegisterOrLogin'; +import { AcceptConditions } from './authentication/views/registration-flow/l8-accept-conditions'; +import { StudentTeacher } from './authentication/views/registration-flow/r10-student-teacher'; +import { RegisterStamboek } from './authentication/views/registration-flow/r3-stamboek'; +import { ManualRegistration } from './authentication/views/registration-flow/r4-manual-registration'; +import { BundleDetail } from './bundle/views/BundleDetail'; +import { BundleEdit } from './bundle/views/BundleEdit'; +import { CollectionDetail } from './collection/views/CollectionDetail'; +import { CollectionEdit } from './collection/views/CollectionEdit'; +import { APP_PATH } from './constants'; +import { CookiePolicy } from './cookie-policy/views'; +import DynamicRouteResolver from './dynamic-route-resolver/views/DynamicRouteResolver'; +import { EmbedCodeDetail } from './embed-code/views/EmbedCodeDetail'; +import { ErrorView } from './error/views/ErrorView'; +import { LoggedInHome } from './home/views/LoggedInHome'; +import { LoggedOutHome } from './home/views/LoggedOutHome'; +import { ItemDetailRoute } from './item/views/ItemDetailRoute'; +import { QuickLaneDetail } from './quick-lane/views/QuickLaneDetail'; +import { Search } from './search/views/Search'; +import { CompleteProfileStep } from './settings/components/CompleteProfileStep'; +import { Email } from './settings/components/Email/Email'; +import { Profile } from './settings/components/Profile'; +import { Settings } from './settings/views/Settings'; +import { FullPageSpinner } from './shared/components/FullPageSpinner/FullPageSpinner'; +import { ROUTE_PARTS } from './shared/constants'; +import { + checkLoginLoaderAsync, + hasAllPermissionsLoader, + hasAnyPermissionLoader, + hasPermissionLoader, + isLoggedInLoader, + routeLoaders, +} from './shared/helpers/routing/route-loaders'; +import { EducationalAuthorItemRequestForm } from './user-item-request-form/views/EducationalAuthorItemRequestForm'; +import { EducationalAuthorItemRequestFormConfirm } from './user-item-request-form/views/EducationalAuthorItemRequestFormConfirm'; +import { UserItemRequestForm } from './user-item-request-form/views/UserItemRequestForm'; +import { UserItemRequestFormConfirm } from './user-item-request-form/views/UserItemRequestFormConfirm'; +import { Workspace } from './workspace/views/Workspace'; +import { WorkspaceAssignmentRedirect } from './workspace/views/WorkspaceAssignmentRedirect'; + +async function logRoutesMiddleware({ request }: Parameters[0]) { + console.log(`Starting navigation: ${request.url}`); +} + +export const getAppRoutes = (): RouteObject[] => [ + { + path: '/', + middleware: [logRoutesMiddleware], + loader: checkLoginLoaderAsync(), + children: [ + //////////////////////////////////////////////////////////////////////////////////////// + // ADMIN ROUTES + //////////////////////////////////////////////////////////////////////////////////////// + { + path: `/${ROUTE_PARTS.beheer}`, + loader: () => { + console.log('Redirecting to /admin'); + return redirect(`/${ROUTE_PARTS.admin}`); + }, + Component: FullPageSpinner, + }, + { + path: `/${ROUTE_PARTS.admin}`, + Component: Admin, + children: getAdminRoutes(), + }, + //////////////////////////////////////////////////////////////////////////////////////// + // CLIENT ROUTES + //////////////////////////////////////////////////////////////////////////////////////// + { + path: '/', + Component: AppWithAdminCoreConfig, + children: [ + //////////////////////////////////////////////////////////////////////////////////////// + // UNAUTHENTICATED + //////////////////////////////////////////////////////////////////////////////////////// + ...getUnauthenticatedClientRoutes(), + + //////////////////////////////////////////////////////////////////////////////////////// + // AUTHENTICATED ROUTES + //////////////////////////////////////////////////////////////////////////////////////// + { + loader: isLoggedInLoader(), + children: getAuthenticatedClientRoutes(), + }, + + //////////////////////////////////////////////////////////////////////////////////////// + // DYNAMIC ROUTES (CONTENT PAGES) AND 404 HANDLING + //////////////////////////////////////////////////////////////////////////////////////// + // This route needs to be the last one, since it handles all remaining routes + { Component: DynamicRouteResolver, path: APP_PATH.ALL_ROUTES.route }, + ], + }, + ], + }, +]; + +//////////////////////////////////////////////////////////////////////////////////////// +// UNAUTHENTICATED +//////////////////////////////////////////////////////////////////////////////////////// +function getUnauthenticatedClientRoutes(): RouteObject[] { + return [ + { index: true, Component: LoggedOutHome }, + { path: APP_PATH.LOGIN.route, Component: Login }, + { path: APP_PATH.LOGOUT.route, Component: Logout }, + { path: APP_PATH.STAMBOEK.route, Component: RegisterStamboek }, + { path: APP_PATH.MANUAL_ACCESS_REQUEST.route, Component: ManualRegistration }, + { path: APP_PATH.STUDENT_TEACHER.route, Component: StudentTeacher }, + { path: APP_PATH.REGISTER_OR_LOGIN.route, Component: RegisterOrLogin }, + { path: APP_PATH.LINK_YOUR_ACCOUNT.route, Component: LinkYourAccount }, + { path: APP_PATH.ACCEPT_CONDITIONS.route, Component: AcceptConditions }, + { path: APP_PATH.COMPLETE_PROFILE.route, Component: CompleteProfileStep }, + { path: APP_PATH.ERROR.route, Component: ErrorView }, + { path: APP_PATH.COOKIE_POLICY.route, Component: CookiePolicy }, + { path: APP_PATH.EMAIL_PREFERENCES_LOGGED_OUT.route, Component: Email }, + ]; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// AUTHENTICATED ROUTES +//////////////////////////////////////////////////////////////////////////////////////// +function getAuthenticatedClientRoutes(): RouteObject[] { + return [ + { + path: APP_PATH.LOGGED_IN_HOME.route, + Component: LoggedInHome, + }, + { + path: `/${ROUTE_PARTS.beheer}`, + Component: AdminRedirect, + }, + { + path: APP_PATH.SEARCH.route, + loader: isLoggedInLoader(), + Component: Search, + }, + { + path: APP_PATH.ITEM_DETAIL.route, + Component: ItemDetailRoute, + }, + { + path: APP_PATH.COLLECTION_DETAIL.route, + Component: CollectionDetail, + }, + { + path: APP_PATH.COLLECTION_EDIT.route, + Component: CollectionEdit, + }, + { + path: APP_PATH.COLLECTION_EDIT_TAB.route, + Component: CollectionEdit, + }, + { + path: APP_PATH.BUNDLE_DETAIL.route, + Component: BundleDetail, + }, + { + path: APP_PATH.BUNDLE_EDIT.route, + loader: isLoggedInLoader(), + Component: BundleEdit, + }, + { + path: APP_PATH.BUNDLE_EDIT_TAB.route, + Component: BundleEdit, + }, + { + path: APP_PATH.ASSIGNMENT_CREATE.route, + Component: AssignmentEdit, + }, + { + path: APP_PATH.ASSIGNMENT_DETAIL.route, + Component: AssignmentDetailSwitcher, + }, + { + path: APP_PATH.ASSIGNMENT_EDIT.route, + Component: AssignmentEdit, + }, + { + path: APP_PATH.ASSIGNMENT_EDIT_TAB.route, + Component: AssignmentEdit, + }, + { + path: APP_PATH.ASSIGNMENT_RESPONSE_CREATE.route, + Component: AssignmentDetailSwitcher, + }, + { + path: APP_PATH.ASSIGNMENT_RESPONSE_EDIT.route, + Component: AssignmentDetailSwitcher, + }, + // view pupil collection response as teacher/ad{min + { + path: APP_PATH.ASSIGNMENT_PUPIL_COLLECTION_DETAIL.route, + Component: AssignmentPupilCollectionDetail, + }, + // edit pupil collection response as admin + { + path: APP_PATH.ASSIGNMENT_PUPIL_COLLECTION_ADMIN_EDIT.route, + Component: AssignmentResponseAdminEdit, + }, + { + path: APP_PATH.WORKSPACE.route, + loader: isLoggedInLoader(), + Component: Workspace, + }, + { + path: `${APP_PATH.WORKSPACE.route}${APP_PATH.ASSIGNMENT_DETAIL.route}`, + loader: (props) => { + const assignmentId = props.params?.assignmentId; + return redirect(`/${ROUTE_PARTS.assignments}/${assignmentId}${location.search}`); + }, + Component: WorkspaceAssignmentRedirect, + }, + { + path: APP_PATH.WORKSPACE_TAB.route, + Component: Workspace, + }, + { + path: APP_PATH.SETTINGS.route, + loader: isLoggedInLoader(), + Component: Settings, + }, + { + path: APP_PATH.SETTINGS_TAB.route, + loader: isLoggedInLoader(), + Component: Settings, + }, + { + path: APP_PATH.COMPLETE_PROFILE.route, + Component: Profile, + }, + { + path: APP_PATH.USER_ITEM_REQUEST_FORM.route, + Component: UserItemRequestForm, + }, + { + path: APP_PATH.USER_ITEM_REQUEST_FORM_CONFIRM.route, + Component: UserItemRequestFormConfirm, + }, + { + path: APP_PATH.EDUCATIONAL_USER_ITEM_REQUEST_FORM.route, + Component: EducationalAuthorItemRequestForm, + }, + { + path: APP_PATH.EDUCATIONAL_USER_ITEM_REQUEST_FORM_CONFIRM.route, + Component: EducationalAuthorItemRequestFormConfirm, + }, + { + path: APP_PATH.QUICK_LANE.route, + Component: QuickLaneDetail, + }, + { path: APP_PATH.EMBED.route, Component: EmbedCodeDetail }, + ]; +} + +function getAdminRoutes(): RouteObject[] { + return [ + { + Component: Dashboard, + index: true, + }, + { + Component: AssignmentOverviewAdmin, + loader: hasPermissionLoader(PermissionName.VIEW_ANY_ASSIGNMENTS), + path: ASSIGNMENTS_PATH.ASSIGNMENTS_OVERVIEW, + }, + { + Component: AssignmentMarcomOverview, + loader: hasPermissionLoader(PermissionName.VIEW_ANY_ASSIGNMENTS), + path: ASSIGNMENTS_PATH.ASSIGNMENTS_MARCOM_OVERVIEW, + }, + { + Component: CollectionsOrBundlesOverview, + loader: routeLoaders( + (permissions) => + permissions.includes(PermissionName.VIEW_COLLECTIONS_OVERVIEW) && + (permissions.includes(PermissionName.VIEW_ANY_PUBLISHED_COLLECTIONS) || + permissions.includes(PermissionName.VIEW_ANY_UNPUBLISHED_COLLECTIONS)) + ), + path: COLLECTIONS_OR_BUNDLES_PATH.COLLECTIONS_OVERVIEW, + }, + { + Component: CollectionOrBundleActualisationOverview, + loader: hasAllPermissionsLoader( + PermissionName.VIEW_COLLECTIONS_OVERVIEW, + PermissionName.VIEW_COLLECTION_EDITORIAL_OVERVIEWS + ), + path: COLLECTIONS_OR_BUNDLES_PATH.COLLECTION_ACTUALISATION_OVERVIEW, + }, + { + Component: CollectionOrBundleQualityCheckOverview, + loader: hasAllPermissionsLoader( + PermissionName.VIEW_COLLECTIONS_OVERVIEW, + PermissionName.VIEW_COLLECTION_EDITORIAL_OVERVIEWS + ), + path: COLLECTIONS_OR_BUNDLES_PATH.COLLECTION_QUALITYCHECK_OVERVIEW, + }, + { + Component: CollectionOrBundleMarcomOverview, + loader: hasAllPermissionsLoader( + PermissionName.VIEW_COLLECTIONS_OVERVIEW, + PermissionName.VIEW_COLLECTION_EDITORIAL_OVERVIEWS + ), + path: COLLECTIONS_OR_BUNDLES_PATH.COLLECTION_MARCOM_OVERVIEW, + }, + { + Component: CollectionsOrBundlesOverview, + loader: routeLoaders( + (permissions) => + permissions.includes(PermissionName.VIEW_BUNDLES_OVERVIEW) && + (permissions.includes(PermissionName.VIEW_ANY_PUBLISHED_BUNDLES) || + permissions.includes(PermissionName.VIEW_ANY_UNPUBLISHED_BUNDLES)) + ), + path: COLLECTIONS_OR_BUNDLES_PATH.BUNDLES_OVERVIEW, + }, + { + Component: CollectionOrBundleActualisationOverview, + loader: hasAllPermissionsLoader( + PermissionName.VIEW_BUNDLES_OVERVIEW, + PermissionName.VIEW_BUNDLE_EDITORIAL_OVERVIEWS + ), + path: COLLECTIONS_OR_BUNDLES_PATH.BUNDLE_ACTUALISATION_OVERVIEW, + }, + { + Component: CollectionOrBundleQualityCheckOverview, + loader: hasAllPermissionsLoader( + PermissionName.VIEW_BUNDLES_OVERVIEW, + PermissionName.VIEW_BUNDLE_EDITORIAL_OVERVIEWS + ), + path: COLLECTIONS_OR_BUNDLES_PATH.BUNDLE_QUALITYCHECK_OVERVIEW, + }, + { + Component: CollectionOrBundleMarcomOverview, + loader: hasAllPermissionsLoader( + PermissionName.VIEW_BUNDLES_OVERVIEW, + PermissionName.VIEW_BUNDLE_EDITORIAL_OVERVIEWS + ), + path: COLLECTIONS_OR_BUNDLES_PATH.BUNDLE_MARCOM_OVERVIEW, + }, + { + Component: ContentPageOverviewPage, + loader: hasAnyPermissionLoader( + PermissionName.EDIT_OWN_CONTENT_PAGES, + PermissionName.EDIT_ANY_CONTENT_PAGES + ), + path: CONTENT_PAGE_PATH.CONTENT_PAGE_OVERVIEW, + }, + { + Component: ContentPageEditPage, + loader: hasAnyPermissionLoader( + PermissionName.EDIT_OWN_CONTENT_PAGES, + PermissionName.EDIT_ANY_CONTENT_PAGES + ), + path: CONTENT_PAGE_PATH.CONTENT_PAGE_CREATE, + }, + { + Component: ContentPageDetailPage, + loader: hasAnyPermissionLoader( + PermissionName.EDIT_OWN_CONTENT_PAGES, + PermissionName.EDIT_ANY_CONTENT_PAGES + ), + path: CONTENT_PAGE_PATH.CONTENT_PAGE_DETAIL, + }, + { + Component: ContentPageEditPage, + loader: hasAnyPermissionLoader( + PermissionName.EDIT_OWN_CONTENT_PAGES, + PermissionName.EDIT_ANY_CONTENT_PAGES + ), + path: CONTENT_PAGE_PATH.CONTENT_PAGE_EDIT, + }, + { + Component: ContentPageLabelOverviewPage, + loader: hasPermissionLoader(PermissionName.EDIT_CONTENT_PAGE_LABELS), + path: CONTENT_PAGE_LABEL_PATH.CONTENT_PAGE_LABEL_OVERVIEW, + }, + { + Component: ContentPageLabelEditPage, + loader: hasPermissionLoader(PermissionName.EDIT_CONTENT_PAGE_LABELS), + path: CONTENT_PAGE_LABEL_PATH.CONTENT_PAGE_LABEL_CREATE, + }, + { + Component: ContentPageLabelEditPage, + loader: hasPermissionLoader(PermissionName.EDIT_CONTENT_PAGE_LABELS), + path: CONTENT_PAGE_LABEL_PATH.CONTENT_PAGE_LABEL_EDIT, + }, + { + Component: ContentPageLabelDetailPage, + loader: hasPermissionLoader(PermissionName.EDIT_CONTENT_PAGE_LABELS), + path: CONTENT_PAGE_LABEL_PATH.CONTENT_PAGE_LABEL_DETAIL, + }, + { + Component: InteractiveTourOverview, + loader: hasPermissionLoader(PermissionName.EDIT_INTERACTIVE_TOURS), + path: INTERACTIVE_TOUR_PATH.INTERACTIVE_TOUR_OVERVIEW, + }, + { + Component: InteractiveTourEdit, + loader: hasPermissionLoader(PermissionName.EDIT_INTERACTIVE_TOURS), + path: INTERACTIVE_TOUR_PATH.INTERACTIVE_TOUR_CREATE, + }, + { + Component: InteractiveTourEdit, + loader: hasPermissionLoader(PermissionName.EDIT_INTERACTIVE_TOURS), + path: INTERACTIVE_TOUR_PATH.INTERACTIVE_TOUR_EDIT, + }, + { + Component: InteractiveTourDetail, + loader: hasPermissionLoader(PermissionName.EDIT_INTERACTIVE_TOURS), + path: INTERACTIVE_TOUR_PATH.INTERACTIVE_TOUR_DETAIL, + }, + { + Component: ItemsOverview, + loader: hasPermissionLoader(PermissionName.VIEW_ITEMS_OVERVIEW), + path: ITEMS_PATH.ITEMS_OVERVIEW, + }, + { + Component: ItemDetail, + loader: hasPermissionLoader(PermissionName.VIEW_ITEMS_OVERVIEW), + path: ITEMS_PATH.ITEM_DETAIL, + }, + { + Component: PublishItemsOverview, + loader: hasPermissionLoader(PermissionName.PUBLISH_ITEMS), + path: ITEMS_PATH.PUBLISH_ITEMS_OVERVIEW, + }, + { + Component: NavigationBarOverview, + loader: hasPermissionLoader(PermissionName.EDIT_NAVIGATION_BARS), + path: NAVIGATIONS_PATH.NAVIGATIONS_OVERVIEW, + }, + { + Component: NavigationItemEdit, + loader: hasPermissionLoader(PermissionName.EDIT_NAVIGATION_BARS), + path: NAVIGATIONS_PATH.NAVIGATIONS_CREATE, + }, + { + Component: NavigationBarDetail, + loader: hasPermissionLoader(PermissionName.EDIT_NAVIGATION_BARS), + path: NAVIGATIONS_PATH.NAVIGATIONS_DETAIL, + }, + { + Component: NavigationItemEdit, + loader: hasPermissionLoader(PermissionName.EDIT_NAVIGATION_BARS), + path: NAVIGATIONS_PATH.NAVIGATIONS_ITEM_CREATE, + }, + { + Component: NavigationItemEdit, + loader: hasPermissionLoader(PermissionName.EDIT_NAVIGATION_BARS), + path: NAVIGATIONS_PATH.NAVIGATIONS_ITEM_EDIT, + }, + { + Component: PupilCollectionsOverview, + loader: hasPermissionLoader(PermissionName.VIEW_ANY_PUPIL_COLLECTIONS), + path: PUPIL_COLLECTIONS_PATH.ASSIGNMENT_PUPIL_COLLECTIONS_OVERVIEW, + }, + { + Component: TranslationsOverviewPage, + loader: hasPermissionLoader(PermissionName.EDIT_TRANSLATIONS), + path: TRANSLATIONS_PATH.TRANSLATIONS, + }, + { + Component: UserGroupOverviewPage, + loader: hasPermissionLoader(PermissionName.EDIT_USER_GROUPS), + path: USER_GROUP_PATH.USER_GROUP_OVERVIEW, + }, + { + Component: UserOverviewPage, + loader: hasPermissionLoader(PermissionName.VIEW_USERS), + path: USER_PATH.USER_OVERVIEW, + }, + { + Component: UserDetailPage, + loader: hasPermissionLoader(PermissionName.VIEW_USERS), + path: USER_PATH.USER_DETAIL, + }, + { + Component: UserEditPage, + loader: hasPermissionLoader(PermissionName.VIEW_USERS), + path: USER_PATH.USER_EDIT, + }, + { + Component: MaintenanceAlertsOverviewPage, + loader: hasPermissionLoader(PermissionName.VIEW_ANY_MAINTENANCE_ALERTS), + path: `/${ROUTE_PARTS.admin}/${ROUTE_PARTS.alerts}`, + }, + ]; +} diff --git a/src/App.tsx b/src/App.tsx index a28cad29ca..92533d3655 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,83 +1,58 @@ -import { QueryCache, QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { type Avo, PermissionName } from '@viaa/avo2-types'; import { clsx } from 'clsx'; -import { createBrowserHistory } from 'history'; +import { useAtom, useAtomValue, useSetAtom } from 'jotai'; import { isEqual, noop, uniq } from 'lodash-es'; -import { wrapHistory } from 'oaf-react-router'; -import React, { type FC, type ReactNode, useCallback, useEffect, useState } from 'react'; -import { connect, Provider } from 'react-redux'; -import { - Route, - type RouteComponentProps, - BrowserRouter as Router, - useLocation, - withRouter, -} from 'react-router-dom'; +import React, { type FC, useCallback, useEffect, useState } from 'react'; +import { Outlet, useNavigate } from 'react-router'; +import { useLocation } from 'react-router-dom'; import { Slide, ToastContainer } from 'react-toastify'; -import { compose, type Dispatch } from 'redux'; import { QueryParamProvider } from 'use-query-params'; -import Admin from './admin/Admin'; +import { Admin } from './admin/Admin'; import { ADMIN_PATH } from './admin/admin.const'; import { withAdminCoreConfig } from './admin/shared/hoc/with-admin-core-config'; import { SpecialUserGroupId } from './admin/user-groups/user-group.const'; -import { SecuredRoute } from './authentication/components'; +import { commonUserAtom } from './authentication/authentication.store'; +import { SecuredRoute } from './authentication/components/SecuredRoute'; import { PermissionService } from './authentication/helpers/permission-service'; import { APP_PATH } from './constants'; -import { renderRoutes } from './routes'; -import ACMIDMNudgeModal from './shared/components/ACMIDMNudgeModal/ACMIDMNudgeModal'; +import { ACMIDMNudgeModal } from './shared/components/ACMIDMNudgeModal/ACMIDMNudgeModal'; import { ConfirmModal } from './shared/components/ConfirmModal/ConfirmModal'; -import Footer from './shared/components/Footer/Footer'; +import { Footer } from './shared/components/Footer/Footer'; import { LoadingErrorLoadedComponent, type LoadingInfo, } from './shared/components/LoadingErrorLoadedComponent/LoadingErrorLoadedComponent'; -import Navigation from './shared/components/Navigation/Navigation'; -import ZendeskWrapper from './shared/components/ZendeskWrapper/ZendeskWrapper'; +import { Navigation } from './shared/components/Navigation/Navigation'; +import { ZendeskWrapper } from './shared/components/ZendeskWrapper/ZendeskWrapper'; import { ROUTE_PARTS } from './shared/constants'; import { CustomError } from './shared/helpers/custom-error'; -import withUser, { type UserProps } from './shared/hocs/withUser'; import { usePageLoaded } from './shared/hooks/usePageLoaded'; -import useTranslation from './shared/hooks/useTranslation'; +import { useTranslation } from './shared/hooks/useTranslation'; import { ToastService } from './shared/services/toast-service'; +import { embedFlowAtom, historyLocationsAtom } from './shared/store/ui.store'; import { waitForTranslations } from './shared/translations/i18n'; -import store, { type AppState } from './store'; -import { setEmbedFlowAction, setHistoryLocationsAction } from './store/actions'; -import { selectHistoryLocations } from './store/selectors'; import 'react-datepicker/dist/react-datepicker.css'; // TODO: lazy-load import './App.scss'; import './styles/main.scss'; +import { ReactRouter7Adapter } from './shared/helpers/routing/react-router-v7-adapter-for-use-query-params'; -const history = createBrowserHistory(); -wrapHistory(history, { - smoothScroll: false, - shouldHandleAction: ( - previousLocation: RouteComponentProps['location'], - nextLocation: RouteComponentProps['location'] - ) => { - // We don't want to set focus when only the hash changes - return ( - previousLocation.pathname !== nextLocation.pathname || - previousLocation.search !== nextLocation.search - ); - }, -}); - -const App: FC< - RouteComponentProps & - UserProps & { - historyLocations: string[]; - setHistoryLocations: (locations: string[]) => void; - setEmbedFlow: (embedFlow: string) => void; - } -> = ({ setEmbedFlow, ...props }) => { - const { tHtml } = useTranslation(); +const App: FC = () => { + const { tText, tHtml } = useTranslation(); const location = useLocation(); - const isAdminRoute = new RegExp(`^/${ROUTE_PARTS.admin}`, 'g').test(props.location.pathname); + const navigate = useNavigate(); + + const commonUser = useAtomValue(commonUserAtom); + const [historyLocations, setHistoryLocations] = useAtom(historyLocationsAtom); + const setEmbedFlow = useSetAtom(embedFlowAtom); + + const [isUnsavedChangesModalOpen, setIsUnsavedChangesModalOpen] = useState(false); + + const isAdminRoute = new RegExp(`^/${ROUTE_PARTS.admin}`, 'g').test(location.pathname); const isPupilUser = [SpecialUserGroupId.PupilSecondary, SpecialUserGroupId.PupilElementary] .map(String) - .includes(String(props.commonUser?.userGroup?.id)); + .includes(String(commonUser?.userGroup?.id)); const [loadingInfo, setLoadingInfo] = useState({ state: 'loading' }); @@ -90,7 +65,7 @@ const App: FC< document.querySelector(decodedHash)?.scrollIntoView({ behavior: 'smooth' }); } }, []); - usePageLoaded(handlePageLoaded, !!props.location.hash); + usePageLoaded(handlePageLoaded, !!location.hash); /** * Wait for translations to be loaded before rendering the app @@ -127,25 +102,25 @@ const App: FC< if (hasLinked) { ToastService.success(tHtml('app___je-account-is-gekoppeld')); url.searchParams.delete(linked); - history.replace(url.toString().replace(url.origin, '')); + navigate(url.toString().replace(url.origin, ''), { replace: true }); } } - }, [loadingInfo, tHtml]); + }, [loadingInfo, tHtml, navigate]); /** * Keep track of route changes and track the 3 last visited pages for tracking events * Store them in the redux store */ useEffect(() => { - const existingHistoryLocations = props.historyLocations; + const existingHistoryLocations = historyLocations; const newHistoryLocations = uniq([...existingHistoryLocations, location.pathname]).slice( -3 ); if (!isEqual(existingHistoryLocations, newHistoryLocations)) { - props.setHistoryLocations(newHistoryLocations); + setHistoryLocations(newHistoryLocations); } handlePageLoaded(); - }, [location, props, handlePageLoaded]); + }, [location, historyLocations, setHistoryLocations, handlePageLoaded]); /** * Check if this window was opened from somewhere else and get the embed-flow query param @@ -156,13 +131,8 @@ const App: FC< const embedFlow = url.searchParams.get('embed-flow') || ''; const isOpenedByOtherPage = !!window.opener; - if (isOpenedByOtherPage && !!embedFlow && props.commonUser) { - if ( - PermissionService.hasPerm( - props.commonUser, - PermissionName.EMBED_ITEMS_ON_OTHER_SITES - ) - ) { + if (isOpenedByOtherPage && !!embedFlow && commonUser) { + if (PermissionService.hasPerm(commonUser, PermissionName.EMBED_ITEMS_ON_OTHER_SITES)) { setEmbedFlow(embedFlow); } else { ToastService.info(tHtml('app___je-hebt-geen-toegang-tot-de-embed-functionaliteit')); @@ -172,11 +142,11 @@ const App: FC< "Embed flow query param is present, but the page wasn't opened from another page, so window.opener is undefined. Cannot start the embed flow" ); } - }, [setEmbedFlow, props.commonUser]); + }, [setEmbedFlow, commonUser, tHtml]); // Render const renderApp = () => { - const isLoginRoute = props.location.pathname === APP_PATH.LOGIN.route; + const isLoginRoute = location.pathname === APP_PATH.LOGIN.route; return (
{isAdminRoute ? ( - + ) : ( <> - {!isLoginRoute && } - {renderRoutes()} - {!isLoginRoute &&
} + {!isLoginRoute && } + + {!isLoginRoute &&
} )} @@ -210,86 +180,41 @@ const App: FC< return ( <> - + {/* Use query params*/} + + <> + + { + setIsUnsavedChangesModalOpen(false); + (confirmUnsavedChangesCallback || noop)(true); + confirmUnsavedChangesCallback = null; + }} + onClose={() => { + setIsUnsavedChangesModalOpen(false); + (confirmUnsavedChangesCallback || noop)(false); + confirmUnsavedChangesCallback = null; + }} + cancelLabel={tText('app___blijven')} + confirmLabel={tText('app___verlaten')} + title={tHtml('app___wijzigingen-opslaan')} + body={tHtml( + 'app___er-zijn-nog-niet-opgeslagen-wijzigingen-weet-u-zeker-dat-u-de-pagina-wil-verlaten' + )} + confirmButtonType="primary" + /> + + ); }; -const mapStateToProps = (state: AppState) => ({ - historyLocations: selectHistoryLocations(state), -}); - -const mapDispatchToProps = (dispatch: Dispatch) => ({ - setHistoryLocations: (locations: string[]) => - dispatch(setHistoryLocationsAction(locations) as any), - setEmbedFlow: (embedFlow: string) => dispatch(setEmbedFlowAction(embedFlow) as any), -}); - -const AppWithRouter = compose( - connect(mapStateToProps, mapDispatchToProps), - withRouter, - withUser, - withAdminCoreConfig -)(App) as FC; +export const AppWithAdminCoreConfig = withAdminCoreConfig(App) as FC; let confirmUnsavedChangesCallback: ((navigateAway: boolean) => void) | null; - -const queryClient = new QueryClient({ - queryCache: new QueryCache({ - onError: (error, query) => { - if (query.meta?.errorMessage) { - console.error(error); - ToastService.danger(query.meta.errorMessage as ReactNode | string); - } - }, - }), -}); - -const Root: FC = () => { - const { tText, tHtml } = useTranslation(); - const [isUnsavedChangesModalOpen, setIsUnsavedChangesModalOpen] = useState(false); - - return ( - - - { - setIsUnsavedChangesModalOpen(true); - confirmUnsavedChangesCallback = callback; - }} - > - - - { - setIsUnsavedChangesModalOpen(false); - (confirmUnsavedChangesCallback || noop)(true); - confirmUnsavedChangesCallback = null; - }} - onClose={() => { - setIsUnsavedChangesModalOpen(false); - (confirmUnsavedChangesCallback || noop)(false); - confirmUnsavedChangesCallback = null; - }} - cancelLabel={tText('app___blijven')} - confirmLabel={tText('app___verlaten')} - title={tHtml('app___wijzigingen-opslaan')} - body={tHtml( - 'app___er-zijn-nog-niet-opgeslagen-wijzigingen-weet-u-zeker-dat-u-de-pagina-wil-verlaten' - )} - confirmButtonType="primary" - /> - - - - - ); -}; - -export default Root; diff --git a/src/admin/Admin.tsx b/src/admin/Admin.tsx index a35018503e..413930045e 100644 --- a/src/admin/Admin.tsx +++ b/src/admin/Admin.tsx @@ -1,25 +1,27 @@ import { Flex, IconName } from '@viaa/avo2-components'; -import { type Avo, PermissionName } from '@viaa/avo2-types'; +import { PermissionName } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import React, { type FC, useEffect, useState } from 'react'; import { HorizontalPageSplit } from 'react-page-split'; +import { Outlet } from 'react-router'; +import { commonUserAtom } from '../authentication/authentication.store'; import { PermissionService } from '../authentication/helpers/permission-service'; import { LoadingErrorLoadedComponent, type LoadingInfo, } from '../shared/components/LoadingErrorLoadedComponent/LoadingErrorLoadedComponent'; import { CustomError } from '../shared/helpers/custom-error'; -import withUser from '../shared/hocs/withUser'; -import useTranslation from '../shared/hooks/useTranslation'; +import { useTranslation } from '../shared/hooks/useTranslation'; import { ToastService } from '../shared/services/toast-service'; import { type NavigationItemInfo } from '../shared/types'; import { ADMIN_PATH, GET_NAV_ITEMS } from './admin.const'; -import { renderAdminRoutes } from './admin.routes'; -import { Sidebar } from './shared/components'; +import { Sidebar } from './shared/components/Sidebar/Sidebar'; -const Admin: FC<{ commonUser: Avo.User.CommonUser }> = ({ commonUser }) => { +export const Admin: FC = () => { const { tText, tHtml } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); const [loadingInfo, setLoadingInfo] = useState({ state: 'loading' }); const [userPermissions, setUserPermissions] = useState(null); @@ -72,7 +74,7 @@ const Admin: FC<{ commonUser: Avo.User.CommonUser }> = ({ commonUser }) => { className="o-app--admin__sidebar" /> - {renderAdminRoutes(userPermissions)} + ); @@ -86,5 +88,3 @@ const Admin: FC<{ commonUser: Avo.User.CommonUser }> = ({ commonUser }) => { /> ); }; - -export default withUser(Admin) as FC; diff --git a/src/admin/AdminRedirect.tsx b/src/admin/AdminRedirect.tsx index 3eee40a7c6..1a31f1f4ae 100644 --- a/src/admin/AdminRedirect.tsx +++ b/src/admin/AdminRedirect.tsx @@ -1,9 +1,17 @@ +import { Flex, Spinner } from '@viaa/avo2-components'; import React, { type FC } from 'react'; -import { Redirect } from 'react-router'; -import { type RouteComponentProps, withRouter } from 'react-router-dom'; +import { type ClientLoaderFunctionArgs, redirect } from 'react-router'; -const AdminRedirect: FC = ({ location }) => { - return ; -}; +export async function clientLoader({ request }: ClientLoaderFunctionArgs) { + throw redirect(request.url.replace(/^\/beheer/g, '/admin')); +} + +clientLoader.hydrate = true as const; -export default withRouter(AdminRedirect) as unknown as FC; +export const AdminRedirect: FC = () => { + return ( + + + + ); +}; diff --git a/src/admin/admin.routes.tsx b/src/admin/admin.routes.tsx deleted file mode 100644 index 92fd725729..0000000000 --- a/src/admin/admin.routes.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { PermissionName } from '@viaa/avo2-types'; -import { every, some } from 'lodash-es'; -import React, { type ReactNode } from 'react'; -import { Switch } from 'react-router'; - -import { renderErrorRoutes } from '../error/error.routes'; - -import { renderAdminAssignmentRoutes } from './assignments/assignment.routes'; -import { renderCollectionOrBundleRoutes } from './collectionsOrBundles/collections-or-bundles.routes'; -import { renderAdminContentPageRoutes } from './content-page/content-page.routes'; -import { renderAdminContentPageLabelRoutes } from './content-page-labels/content-page-label.routes'; -import { renderAdminDashboardRoutes } from './dashboard/dashboard.routes'; -import { renderInteractiveTourRoutes } from './interactive-tour/interactive-tour.routes'; -import { renderItemRoutes, renderPublishItemRoutes } from './items/items.routes'; -import { renderAdminNavigationRoutes } from './navigations/navigations.routes'; -import { renderAdminPupilCollectionRoutes } from './pupil-collection/pupil-collection.routes'; -import { renderAdminTranslationsRoutes } from './translations/translations.routes'; -import { renderUrlRedirectRoutes } from './url-redirects/url-redirects.routes'; -import { renderAdminUserGroupRoutes } from './user-groups/user-group.routes'; -import { renderAdminUserRoutes } from './users/user.routes'; - -export const renderAdminRoutes = (userPermissions: string[]): ReactNode => { - const renderWithPermissions = ( - renderFunc: (userPermissions: string[]) => ReactNode[], - permissions: string[], - booleanOperator: 'AND' | 'OR' = 'OR' - ): ReactNode[] => { - if (booleanOperator === 'OR') { - // OR - // If at least one of the permissions is met, render the routes - if (some(permissions, (permission) => userPermissions.includes(permission))) { - return renderFunc(userPermissions); - } - } else { - // AND - // All permissions have to be met - if (every(permissions, (permission) => userPermissions.includes(permission))) { - return renderFunc(userPermissions); - } - } - return []; - }; - - return ( - - {renderAdminDashboardRoutes()} - {renderWithPermissions(renderAdminUserRoutes, [PermissionName.VIEW_USERS])} - {renderWithPermissions(renderAdminUserGroupRoutes, [PermissionName.EDIT_USER_GROUPS])} - {renderWithPermissions(renderAdminNavigationRoutes, [ - PermissionName.EDIT_NAVIGATION_BARS, - ])} - {renderWithPermissions( - renderAdminContentPageRoutes, - [PermissionName.EDIT_OWN_CONTENT_PAGES, PermissionName.EDIT_ANY_CONTENT_PAGES], - 'OR' - )} - {renderWithPermissions(renderAdminContentPageLabelRoutes, [ - PermissionName.EDIT_CONTENT_PAGE_LABELS, - ])} - {renderWithPermissions(renderItemRoutes, [PermissionName.VIEW_ITEMS_OVERVIEW])} - {renderWithPermissions(renderPublishItemRoutes, [PermissionName.PUBLISH_ITEMS])} - {renderWithPermissions( - renderCollectionOrBundleRoutes, - [PermissionName.VIEW_COLLECTIONS_OVERVIEW, PermissionName.VIEW_BUNDLES_OVERVIEW], - 'OR' - )} - {renderWithPermissions(renderAdminAssignmentRoutes, [ - PermissionName.VIEW_ANY_ASSIGNMENTS, - ])} - {renderWithPermissions(renderAdminPupilCollectionRoutes, [ - PermissionName.VIEW_ANY_PUPIL_COLLECTIONS, - ])} - {renderWithPermissions(renderInteractiveTourRoutes, [ - PermissionName.EDIT_INTERACTIVE_TOURS, - ])} - {renderWithPermissions(renderUrlRedirectRoutes, [PermissionName.EDIT_REDIRECTS])} - {renderWithPermissions(renderAdminTranslationsRoutes, [ - PermissionName.EDIT_TRANSLATIONS, - ])} - {/* Default routes */} - {renderErrorRoutes()} - - ); -}; diff --git a/src/admin/assignments/assignment.routes.tsx b/src/admin/assignments/assignment.routes.tsx deleted file mode 100644 index 439b382e3e..0000000000 --- a/src/admin/assignments/assignment.routes.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React, { type ReactNode } from 'react'; - -import { SecuredRoute } from '../../authentication/components'; - -import { ASSIGNMENTS_PATH } from './assignments.const'; -import AssignmentMarcomOverview from './views/AssignmentsMarcomOverview'; -import AssignmentOverviewAdmin from './views/AssignmentsOverviewAdmin'; - -export const renderAdminAssignmentRoutes = (): ReactNode[] => [ - , - , -]; diff --git a/src/admin/assignments/views/AssignmentsMarcomOverview.tsx b/src/admin/assignments/views/AssignmentsMarcomOverview.tsx index 49baf33b89..d6ed28b3ae 100644 --- a/src/admin/assignments/views/AssignmentsMarcomOverview.tsx +++ b/src/admin/assignments/views/AssignmentsMarcomOverview.tsx @@ -1,26 +1,27 @@ import { ExportAllToCsvModal, FilterTable, getFilters } from '@meemoo/admin-core-ui/dist/admin.mjs'; import { Container, Flex, Spinner } from '@viaa/avo2-components'; import { type Avo } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import React, { type FC, type ReactNode, useEffect, useMemo, useState } from 'react'; import { Helmet } from 'react-helmet'; import { type AssignmentTableColumns } from '../../../assignment/assignment.types'; +import { commonUserAtom } from '../../../authentication/authentication.store'; import { GET_MARCOM_CHANNEL_NAME_OPTIONS, GET_MARCOM_CHANNEL_TYPE_OPTIONS, } from '../../../collection/collection.const'; import { GENERATE_SITE_TITLE } from '../../../constants'; -import { ErrorView } from '../../../error/views'; +import { ErrorView } from '../../../error/views/ErrorView'; import { OrderDirection } from '../../../search/search.const'; import { type CheckboxOption } from '../../../shared/components/CheckboxDropdownModal/CheckboxDropdownModal'; import { CustomError } from '../../../shared/helpers/custom-error'; import { tableColumnListToCsvColumnList } from '../../../shared/helpers/table-column-list-to-csv-column-list'; -import withUser, { type UserProps } from '../../../shared/hocs/withUser'; import { useCompaniesWithUsers } from '../../../shared/hooks/useCompanies'; import { useLomEducationLevelsAndDegrees } from '../../../shared/hooks/useLomEducationLevelsAndDegrees'; import { useLomSubjects } from '../../../shared/hooks/useLomSubjects'; import { useQualityLabels } from '../../../shared/hooks/useQualityLabels'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { ToastService } from '../../../shared/services/toast-service'; import { NULL_FILTER } from '../../shared/helpers/filters'; import { AdminLayout } from '../../shared/layouts/AdminLayout/AdminLayout'; @@ -39,8 +40,9 @@ import { } from '../helpers/render-assignment-columns'; import { useGetAssignmentsWithMarcomForAdminOverview } from '../hooks/useGetAssignmentsWithMarcomForAdminOverview'; -const AssignmentMarcomOverview: FC = ({ commonUser }) => { +export const AssignmentMarcomOverview: FC = () => { const { tText, tHtml } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); const [tableState, setTableState] = useState>({}); const { data: assignmentsWithMarcom, isLoading: isLoadingAssignments } = @@ -243,6 +245,7 @@ const AssignmentMarcomOverview: FC = ({ commonUser }) => { return ( + {/* AssignmentsMarcomOverview */} @@ -377,5 +380,3 @@ const AssignmentMarcomOverview: FC = ({ commonUser }) => { ); }; - -export default withUser(AssignmentMarcomOverview) as FC; diff --git a/src/admin/assignments/views/AssignmentsOverviewAdmin.tsx b/src/admin/assignments/views/AssignmentsOverviewAdmin.tsx index 0ce19c7c8b..3fe6a0ab1a 100644 --- a/src/admin/assignments/views/AssignmentsOverviewAdmin.tsx +++ b/src/admin/assignments/views/AssignmentsOverviewAdmin.tsx @@ -5,17 +5,17 @@ import { getFilters, } from '@meemoo/admin-core-ui/dist/admin.mjs'; import { type Avo } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { noop, partition } from 'lodash-es'; import React, { type FC, type ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; import { Helmet } from 'react-helmet'; -import { type RouteComponentProps, withRouter } from 'react-router-dom'; -import { compose } from 'redux'; import { AssignmentService } from '../../../assignment/assignment.service'; import { type AssignmentTableColumns } from '../../../assignment/assignment.types'; import { useGetAssignmentsEditStatuses } from '../../../assignment/hooks/useGetAssignmentsEditStatuses'; +import { commonUserAtom } from '../../../authentication/authentication.store'; import { APP_PATH, GENERATE_SITE_TITLE } from '../../../constants'; -import { ErrorView } from '../../../error/views'; +import { ErrorView } from '../../../error/views/ErrorView'; import { OrderDirection } from '../../../search/search.const'; import { type CheckboxOption } from '../../../shared/components/CheckboxDropdownModal/CheckboxDropdownModal'; import { ConfirmModal } from '../../../shared/components/ConfirmModal/ConfirmModal'; @@ -27,15 +27,14 @@ import { EDIT_STATUS_REFETCH_TIME } from '../../../shared/constants'; import { buildLink } from '../../../shared/helpers/build-link'; import { CustomError } from '../../../shared/helpers/custom-error'; import { tableColumnListToCsvColumnList } from '../../../shared/helpers/table-column-list-to-csv-column-list'; -import withUser, { type UserProps } from '../../../shared/hocs/withUser'; import { useLomEducationLevelsAndDegrees } from '../../../shared/hooks/useLomEducationLevelsAndDegrees'; import { useLomSubjects } from '../../../shared/hooks/useLomSubjects'; import { useQualityLabels } from '../../../shared/hooks/useQualityLabels'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { ToastService } from '../../../shared/services/toast-service'; import { TableColumnDataType } from '../../../shared/types/table-column-data-type'; -import ChangeAuthorModal from '../../shared/components/ChangeAuthorModal/ChangeAuthorModal'; -import SubjectsBeingEditedWarningModal from '../../shared/components/SubjectsBeingEditedWarningModal/SubjectsBeingEditedWarningModal'; +import { ChangeAuthorModal } from '../../shared/components/ChangeAuthorModal/ChangeAuthorModal'; +import { SubjectsBeingEditedWarningModal } from '../../shared/components/SubjectsBeingEditedWarningModal/SubjectsBeingEditedWarningModal'; import { NULL_FILTER } from '../../shared/helpers/filters'; import { AdminLayout } from '../../shared/layouts/AdminLayout/AdminLayout'; import { AdminLayoutBody } from '../../shared/layouts/AdminLayout/AdminLayout.slots'; @@ -55,8 +54,9 @@ import { import './AssignmentsOverviewAdmin.scss'; -const AssignmentOverviewAdmin: FC = ({ commonUser }) => { +export const AssignmentOverviewAdmin: FC = () => { const { tText, tHtml } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); const [assignments, setAssignments] = useState(null); const [assignmentCount, setAssignmentCount] = useState(0); @@ -589,5 +589,3 @@ const AssignmentOverviewAdmin: FC = ({ commonUs ); }; - -export default compose(withRouter, withUser)(AssignmentOverviewAdmin) as unknown as FC; diff --git a/src/admin/collectionsOrBundles/collections-or-bundles.routes.tsx b/src/admin/collectionsOrBundles/collections-or-bundles.routes.tsx deleted file mode 100644 index 861e06a739..0000000000 --- a/src/admin/collectionsOrBundles/collections-or-bundles.routes.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { PermissionName } from '@viaa/avo2-types'; -import React, { type ReactNode } from 'react'; - -import { SecuredRoute } from '../../authentication/components'; -import { expandArray } from '../../shared/helpers/conditional-expand-array'; - -import { COLLECTIONS_OR_BUNDLES_PATH } from './collections-or-bundles.const'; -import { CollectionsOrBundlesOverview } from './views'; -import CollectionOrBundleActualisationOverview from './views/CollectionOrBundleActualisationOverview'; -import CollectionOrBundleMarcomOverview from './views/CollectionOrBundleMarcomOverview'; -import CollectionOrBundleQualityCheckOverview from './views/CollectionOrBundleQualityCheckOverview'; - -export const renderCollectionOrBundleRoutes = (userPermissions: string[]): ReactNode[] => - expandArray( - userPermissions.includes(PermissionName.VIEW_COLLECTIONS_OVERVIEW) && - (userPermissions.includes(PermissionName.VIEW_ANY_PUBLISHED_COLLECTIONS) || - userPermissions.includes(PermissionName.VIEW_ANY_UNPUBLISHED_COLLECTIONS)), - , - - userPermissions.includes(PermissionName.VIEW_COLLECTION_EDITORIAL_OVERVIEWS), - , - - userPermissions.includes(PermissionName.VIEW_COLLECTION_EDITORIAL_OVERVIEWS), - , - - userPermissions.includes(PermissionName.VIEW_COLLECTION_EDITORIAL_OVERVIEWS), - , - - userPermissions.includes(PermissionName.VIEW_BUNDLES_OVERVIEW) && - (userPermissions.includes(PermissionName.VIEW_ANY_PUBLISHED_BUNDLES) || - userPermissions.includes(PermissionName.VIEW_ANY_UNPUBLISHED_BUNDLES)), - , - - userPermissions.includes(PermissionName.VIEW_BUNDLE_EDITORIAL_OVERVIEWS), - , - - userPermissions.includes(PermissionName.VIEW_BUNDLE_EDITORIAL_OVERVIEWS), - , - - userPermissions.includes(PermissionName.VIEW_BUNDLE_EDITORIAL_OVERVIEWS), - - ); diff --git a/src/admin/collectionsOrBundles/views/CollectionOrBundleActualisationOverview.tsx b/src/admin/collectionsOrBundles/views/CollectionOrBundleActualisationOverview.tsx index 3688a82e52..bad5a00a29 100644 --- a/src/admin/collectionsOrBundles/views/CollectionOrBundleActualisationOverview.tsx +++ b/src/admin/collectionsOrBundles/views/CollectionOrBundleActualisationOverview.tsx @@ -5,15 +5,15 @@ import { getFilters, } from '@meemoo/admin-core-ui/dist/admin.mjs'; import { type Avo } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { noop } from 'lodash-es'; import React, { type FC, type ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; import { Helmet } from 'react-helmet'; -import { withRouter } from 'react-router-dom'; -import { compose } from 'redux'; +import { useLocation } from 'react-router-dom'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; +import { commonUserAtom } from '../../../authentication/authentication.store'; import { GENERATE_SITE_TITLE } from '../../../constants'; -import { ErrorView } from '../../../error/views'; +import { ErrorView } from '../../../error/views/ErrorView'; import { OrderDirection } from '../../../search/search.const'; import { type CheckboxOption } from '../../../shared/components/CheckboxDropdownModal/CheckboxDropdownModal'; import { @@ -22,12 +22,11 @@ import { } from '../../../shared/components/LoadingErrorLoadedComponent/LoadingErrorLoadedComponent'; import { CustomError } from '../../../shared/helpers/custom-error'; import { tableColumnListToCsvColumnList } from '../../../shared/helpers/table-column-list-to-csv-column-list'; -import withUser from '../../../shared/hocs/withUser'; import { useCompaniesWithUsers } from '../../../shared/hooks/useCompanies'; import { useLomEducationLevelsAndDegrees } from '../../../shared/hooks/useLomEducationLevelsAndDegrees'; import { useLomSubjects } from '../../../shared/hooks/useLomSubjects'; import { useQualityLabels } from '../../../shared/hooks/useQualityLabels'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { ToastService } from '../../../shared/services/toast-service'; import { TableColumnDataType } from '../../../shared/types/table-column-data-type'; import { NULL_FILTER } from '../../shared/helpers/filters'; @@ -52,11 +51,10 @@ import { renderCollectionsOrBundleActualisationCellText, } from '../helpers/render-collection-columns'; -const CollectionOrBundleActualisationOverview: FC = ({ - location, - commonUser, -}) => { +export const CollectionOrBundleActualisationOverview: FC = () => { const { tText, tHtml } = useTranslation(); + const location = useLocation(); + const commonUser = useAtomValue(commonUserAtom); const [collections, setCollections] = useState(null); const [collectionCount, setCollectionCount] = useState(0); @@ -455,5 +453,3 @@ const CollectionOrBundleActualisationOverview: FC = ({ ); }; - -export default compose(withRouter, withUser)(CollectionOrBundleActualisationOverview) as FC; diff --git a/src/admin/collectionsOrBundles/views/CollectionOrBundleMarcomOverview.tsx b/src/admin/collectionsOrBundles/views/CollectionOrBundleMarcomOverview.tsx index 49d339448f..3dc3b5379f 100644 --- a/src/admin/collectionsOrBundles/views/CollectionOrBundleMarcomOverview.tsx +++ b/src/admin/collectionsOrBundles/views/CollectionOrBundleMarcomOverview.tsx @@ -1,18 +1,18 @@ import { ExportAllToCsvModal, FilterTable, getFilters } from '@meemoo/admin-core-ui/dist/admin.mjs'; import { type Avo } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { noop } from 'lodash-es'; import React, { type FC, type ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; import { Helmet } from 'react-helmet'; -import { withRouter } from 'react-router-dom'; -import { compose } from 'redux'; +import { useLocation } from 'react-router-dom'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; +import { commonUserAtom } from '../../../authentication/authentication.store'; import { GET_MARCOM_CHANNEL_NAME_OPTIONS, GET_MARCOM_CHANNEL_TYPE_OPTIONS, } from '../../../collection/collection.const'; import { GENERATE_SITE_TITLE } from '../../../constants'; -import { ErrorView } from '../../../error/views'; +import { ErrorView } from '../../../error/views/ErrorView'; import { OrderDirection } from '../../../search/search.const'; import { type CheckboxOption } from '../../../shared/components/CheckboxDropdownModal/CheckboxDropdownModal'; import { @@ -21,12 +21,11 @@ import { } from '../../../shared/components/LoadingErrorLoadedComponent/LoadingErrorLoadedComponent'; import { CustomError } from '../../../shared/helpers/custom-error'; import { tableColumnListToCsvColumnList } from '../../../shared/helpers/table-column-list-to-csv-column-list'; -import withUser from '../../../shared/hocs/withUser'; import { useCompaniesWithUsers } from '../../../shared/hooks/useCompanies'; import { useLomEducationLevelsAndDegrees } from '../../../shared/hooks/useLomEducationLevelsAndDegrees'; import { useLomSubjects } from '../../../shared/hooks/useLomSubjects'; import { useQualityLabels } from '../../../shared/hooks/useQualityLabels'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { ToastService } from '../../../shared/services/toast-service'; import { NULL_FILTER } from '../../shared/helpers/filters'; import { AdminLayout } from '../../shared/layouts/AdminLayout/AdminLayout'; @@ -50,11 +49,10 @@ import { renderCollectionsOrBundlesMarcomCellText, } from '../helpers/render-collection-columns'; -const CollectionOrBundleMarcomOverview: FC = ({ - location, - commonUser, -}) => { +export const CollectionOrBundleMarcomOverview: FC = () => { const { tText, tHtml } = useTranslation(); + const location = useLocation(); + const commonUser = useAtomValue(commonUserAtom); const [collections, setCollections] = useState(null); const [collectionCount, setCollectionCount] = useState(0); @@ -483,5 +481,3 @@ const CollectionOrBundleMarcomOverview: FC = ({ ); }; - -export default compose(withRouter, withUser)(CollectionOrBundleMarcomOverview) as FC; diff --git a/src/admin/collectionsOrBundles/views/CollectionOrBundleQualityCheckOverview.tsx b/src/admin/collectionsOrBundles/views/CollectionOrBundleQualityCheckOverview.tsx index a20469f07c..c38156f4a2 100644 --- a/src/admin/collectionsOrBundles/views/CollectionOrBundleQualityCheckOverview.tsx +++ b/src/admin/collectionsOrBundles/views/CollectionOrBundleQualityCheckOverview.tsx @@ -5,13 +5,15 @@ import { getFilters, } from '@meemoo/admin-core-ui/dist/admin.mjs'; import { type Avo } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { noop } from 'lodash-es'; import React, { type FC, type ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; import { Helmet } from 'react-helmet'; +import { useLocation } from 'react-router-dom'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; +import { commonUserAtom } from '../../../authentication/authentication.store'; import { GENERATE_SITE_TITLE } from '../../../constants'; -import { ErrorView } from '../../../error/views'; +import { ErrorView } from '../../../error/views/ErrorView'; import { OrderDirection } from '../../../search/search.const'; import { type CheckboxOption } from '../../../shared/components/CheckboxDropdownModal/CheckboxDropdownModal'; import { @@ -20,12 +22,11 @@ import { } from '../../../shared/components/LoadingErrorLoadedComponent/LoadingErrorLoadedComponent'; import { CustomError } from '../../../shared/helpers/custom-error'; import { tableColumnListToCsvColumnList } from '../../../shared/helpers/table-column-list-to-csv-column-list'; -import withUser from '../../../shared/hocs/withUser'; import { useCompaniesWithUsers } from '../../../shared/hooks/useCompanies'; import { useLomEducationLevelsAndDegrees } from '../../../shared/hooks/useLomEducationLevelsAndDegrees'; import { useLomSubjects } from '../../../shared/hooks/useLomSubjects'; import { useQualityLabels } from '../../../shared/hooks/useQualityLabels'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { ToastService } from '../../../shared/services/toast-service'; import { TableColumnDataType } from '../../../shared/types/table-column-data-type'; import { NULL_FILTER } from '../../shared/helpers/filters'; @@ -50,11 +51,10 @@ import { renderCollectionOrBundleQualityCheckCellText, } from '../helpers/render-collection-columns'; -const CollectionOrBundleQualityCheckOverview: FC = ({ - location, - commonUser, -}) => { +export const CollectionOrBundleQualityCheckOverview: FC = () => { const { tText, tHtml } = useTranslation(); + const location = useLocation(); + const commonUser = useAtomValue(commonUserAtom); const [collections, setCollections] = useState(null); const [collectionCount, setCollectionCount] = useState(0); @@ -459,5 +459,3 @@ const CollectionOrBundleQualityCheckOverview: FC = ({ ); }; - -export default withUser(CollectionOrBundleQualityCheckOverview) as FC; diff --git a/src/admin/collectionsOrBundles/views/CollectionsOrBundlesOverview.tsx b/src/admin/collectionsOrBundles/views/CollectionsOrBundlesOverview.tsx index 8495fde1b1..d64d7fea57 100644 --- a/src/admin/collectionsOrBundles/views/CollectionsOrBundlesOverview.tsx +++ b/src/admin/collectionsOrBundles/views/CollectionsOrBundlesOverview.tsx @@ -1,15 +1,17 @@ import { ExportAllToCsvModal, FilterTable, getFilters } from '@meemoo/admin-core-ui/dist/admin.mjs'; import { type TagInfo } from '@viaa/avo2-components'; import { type Avo } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { compact, noop, partition } from 'lodash-es'; import React, { type FC, type ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; import { Helmet } from 'react-helmet'; +import { useLocation } from 'react-router-dom'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; +import { commonUserAtom } from '../../../authentication/authentication.store'; import { CollectionService } from '../../../collection/collection.service'; import { useGetCollectionsEditStatuses } from '../../../collection/hooks/useGetCollectionsEditStatuses'; import { APP_PATH, GENERATE_SITE_TITLE } from '../../../constants'; -import { ErrorView } from '../../../error/views'; +import { ErrorView } from '../../../error/views/ErrorView'; import { OrderDirection } from '../../../search/search.const'; import { type CheckboxOption } from '../../../shared/components/CheckboxDropdownModal/CheckboxDropdownModal'; import { @@ -20,18 +22,18 @@ import { EDIT_STATUS_REFETCH_TIME } from '../../../shared/constants'; import { CustomError } from '../../../shared/helpers/custom-error'; import { getFullNameCommonUser } from '../../../shared/helpers/formatters'; import { tableColumnListToCsvColumnList } from '../../../shared/helpers/table-column-list-to-csv-column-list'; -import withUser from '../../../shared/hocs/withUser'; import { useCompaniesWithUsers } from '../../../shared/hooks/useCompanies'; import { useLomEducationLevelsAndDegrees } from '../../../shared/hooks/useLomEducationLevelsAndDegrees'; import { useLomSubjects } from '../../../shared/hooks/useLomSubjects'; import { useQualityLabels } from '../../../shared/hooks/useQualityLabels'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { ToastService } from '../../../shared/services/toast-service'; -import AddOrRemoveLinkedElementsModal, { +import { type AddOrRemove, + AddOrRemoveLinkedElementsModal, } from '../../shared/components/AddOrRemoveLinkedElementsModal/AddOrRemoveLinkedElementsModal'; -import ChangeAuthorModal from '../../shared/components/ChangeAuthorModal/ChangeAuthorModal'; -import SubjectsBeingEditedWarningModal from '../../shared/components/SubjectsBeingEditedWarningModal/SubjectsBeingEditedWarningModal'; +import { ChangeAuthorModal } from '../../shared/components/ChangeAuthorModal/ChangeAuthorModal'; +import { SubjectsBeingEditedWarningModal } from '../../shared/components/SubjectsBeingEditedWarningModal/SubjectsBeingEditedWarningModal'; import { NULL_FILTER } from '../../shared/helpers/filters'; import { AdminLayout } from '../../shared/layouts/AdminLayout/AdminLayout'; import { AdminLayoutBody } from '../../shared/layouts/AdminLayout/AdminLayout.slots'; @@ -55,8 +57,10 @@ import { renderCollectionsOrBundlesOverviewCellText, } from '../helpers/render-collection-columns'; -const CollectionsOrBundlesOverview: FC = ({ location, commonUser }) => { +export const CollectionsOrBundlesOverview: FC = () => { const { tText, tHtml } = useTranslation(); + const location = useLocation(); + const commonUser = useAtomValue(commonUserAtom); const [collections, setCollections] = useState(null); const [collectionCount, setCollectionCount] = useState(0); @@ -747,5 +751,3 @@ const CollectionsOrBundlesOverview: FC = ({ location, c ); }; - -export default withUser(CollectionsOrBundlesOverview) as FC; diff --git a/src/admin/collectionsOrBundles/views/index.ts b/src/admin/collectionsOrBundles/views/index.ts deleted file mode 100644 index 8f27a08538..0000000000 --- a/src/admin/collectionsOrBundles/views/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as CollectionsOrBundlesOverview } from './CollectionsOrBundlesOverview'; diff --git a/src/admin/content-page-labels/content-page-label.routes.tsx b/src/admin/content-page-labels/content-page-label.routes.tsx deleted file mode 100644 index 8772dc5540..0000000000 --- a/src/admin/content-page-labels/content-page-label.routes.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React, { type ReactNode } from 'react'; - -import { SecuredRoute } from '../../authentication/components'; - -import { CONTENT_PAGE_LABEL_PATH } from './content-page-label.const'; -import ContentPageLabelDetailPage from './views/ContentPageLabelDetailPage'; -import ContentPageLabelEditPage from './views/ContentPageLabelEditPage'; -import ContentPageLabelOverviewPage from './views/ContentPageLabelOverviewPage'; - -export const renderAdminContentPageLabelRoutes = (): ReactNode[] => [ - , - , - , - , -]; diff --git a/src/admin/content-page-labels/views/ContentPageLabelDetailPage.tsx b/src/admin/content-page-labels/views/ContentPageLabelDetailPage.tsx index 66ca2d5469..dc723cf2a4 100644 --- a/src/admin/content-page-labels/views/ContentPageLabelDetailPage.tsx +++ b/src/admin/content-page-labels/views/ContentPageLabelDetailPage.tsx @@ -1,12 +1,11 @@ import { Flex, Spinner } from '@viaa/avo2-components'; import React, { type FC, lazy, Suspense } from 'react'; -import { withRouter } from 'react-router-dom'; -import { compose } from 'redux'; +import { useMatch, useNavigate } from 'react-router'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; import { goBrowserBackWithFallback } from '../../../shared/helpers/go-browser-back-with-fallback'; import { ADMIN_PATH } from '../../admin.const'; import { withAdminCoreConfig } from '../../shared/hoc/with-admin-core-config'; +import { CONTENT_PAGE_LABEL_PATH } from '../content-page-label.const'; const ContentPageLabelDetail = lazy(() => import('@meemoo/admin-core-ui/dist/admin.mjs').then((adminCoreModule) => ({ @@ -14,10 +13,12 @@ const ContentPageLabelDetail = lazy(() => })) ); -const ContentPageLabelDetailPage: FC> = ({ - match, - history, -}) => { +const ContentPageLabelDetailPage: FC = () => { + const navigateFunc = useNavigate(); + const match = useMatch<'id', string>(CONTENT_PAGE_LABEL_PATH.CONTENT_PAGE_LABEL_DETAIL); + + const id = match?.params.id; + return ( > = } > - - goBrowserBackWithFallback(ADMIN_PATH.CONTENT_PAGE_LABEL_OVERVIEW, history) - } - /> + {!!id && ( + + goBrowserBackWithFallback( + ADMIN_PATH.CONTENT_PAGE_LABEL_OVERVIEW, + navigateFunc + ) + } + /> + )} ); }; -export default compose( - withAdminCoreConfig, - withRouter -)(ContentPageLabelDetailPage as FC) as FC>; +export default withAdminCoreConfig(ContentPageLabelDetailPage as FC) as FC; diff --git a/src/admin/content-page-labels/views/ContentPageLabelEditPage.tsx b/src/admin/content-page-labels/views/ContentPageLabelEditPage.tsx index 51a8dabfbe..486cd280dc 100644 --- a/src/admin/content-page-labels/views/ContentPageLabelEditPage.tsx +++ b/src/admin/content-page-labels/views/ContentPageLabelEditPage.tsx @@ -1,13 +1,12 @@ import { Flex, Spinner } from '@viaa/avo2-components'; import React, { type FC, lazy, Suspense } from 'react'; -import { withRouter } from 'react-router-dom'; -import { compose } from 'redux'; +import { useMatch, useNavigate } from 'react-router'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; import { buildLink } from '../../../shared/helpers/build-link'; import { goBrowserBackWithFallback } from '../../../shared/helpers/go-browser-back-with-fallback'; import { ADMIN_PATH } from '../../admin.const'; import { withAdminCoreConfig } from '../../shared/hoc/with-admin-core-config'; +import { CONTENT_PAGE_LABEL_PATH } from '../content-page-label.const'; const ContentPageLabelEdit = lazy(() => import('@meemoo/admin-core-ui/dist/admin.mjs').then((adminCoreModule) => ({ @@ -15,10 +14,12 @@ const ContentPageLabelEdit = lazy(() => })) ); -const ContentPageLabelEditPage: FC> = ({ - match, - history, -}) => { +const ContentPageLabelEditPage: FC = () => { + const navigateFunc = useNavigate(); + const match = useMatch<'id', string>(CONTENT_PAGE_LABEL_PATH.CONTENT_PAGE_LABEL_EDIT); + + const contentPageLabelId = match?.params.id; + return ( > = ({ > goBrowserBackWithFallback( - buildLink(ADMIN_PATH.CONTENT_PAGE_DETAIL, { id: match.params.id }), - history + buildLink(ADMIN_PATH.CONTENT_PAGE_DETAIL, { id: contentPageLabelId }), + navigateFunc ) } /> @@ -41,6 +42,4 @@ const ContentPageLabelEditPage: FC> = ({ ); }; -export default compose(withAdminCoreConfig, withRouter)(ContentPageLabelEditPage as FC) as FC< - DefaultSecureRouteProps<{ id: string }> ->; +export default withAdminCoreConfig(ContentPageLabelEditPage) as FC; diff --git a/src/admin/content-page-labels/views/ContentPageLabelOverviewPage.tsx b/src/admin/content-page-labels/views/ContentPageLabelOverviewPage.tsx index 9405488061..b6ef11155e 100644 --- a/src/admin/content-page-labels/views/ContentPageLabelOverviewPage.tsx +++ b/src/admin/content-page-labels/views/ContentPageLabelOverviewPage.tsx @@ -1,8 +1,6 @@ import { Flex, Spinner } from '@viaa/avo2-components'; import React, { type FC, lazy, Suspense } from 'react'; -import { compose } from 'redux'; -import withUser from '../../../shared/hocs/withUser'; import { withAdminCoreConfig } from '../../shared/hoc/with-admin-core-config'; const ContentPageLabelOverview = lazy(() => @@ -25,4 +23,4 @@ const ContentPageLabelOverviewPage: FC = () => { ); }; -export default compose(withAdminCoreConfig, withUser)(ContentPageLabelOverviewPage) as FC; +export default withAdminCoreConfig(ContentPageLabelOverviewPage) as FC; diff --git a/src/admin/content-page/components/blocks/BlockSearch/BlockSearch.tsx b/src/admin/content-page/components/blocks/BlockSearch/BlockSearch.tsx index 1f2d6440de..e70b35e5e3 100644 --- a/src/admin/content-page/components/blocks/BlockSearch/BlockSearch.tsx +++ b/src/admin/content-page/components/blocks/BlockSearch/BlockSearch.tsx @@ -13,69 +13,64 @@ import { TextInput, } from '@viaa/avo2-components'; import { type Avo } from '@viaa/avo2-types'; -import { find, get, isNil } from 'lodash-es'; -import React, { type FC, type KeyboardEvent, useEffect, useState } from 'react'; -import { connect } from 'react-redux'; -import { withRouter } from 'react-router'; -import { type Dispatch } from 'redux'; +import { useAtom } from 'jotai'; +import { isNil } from 'lodash-es'; +import React, { type FC, type KeyboardEvent, useCallback, useEffect, useState } from 'react'; +import { useNavigate } from 'react-router'; -import { type DefaultSecureRouteProps } from '../../../../../authentication/components/SecuredRoute'; import { CONTENT_TYPE_TRANSLATIONS } from '../../../../../collection/collection.types'; import { OrderDirection, SearchFilter } from '../../../../../search/search.const'; -import { getSearchResults } from '../../../../../search/store/actions'; -import { selectSearchLoading, selectSearchResults } from '../../../../../search/store/selectors'; +import { fetchSearchResults } from '../../../../../search/search.service'; +import { searchAtom } from '../../../../../search/search.store'; +import { type SearchState } from '../../../../../search/search.types'; import { generateContentLinkString, generateSearchLinkString, } from '../../../../../shared/helpers/link'; import { useDebounce } from '../../../../../shared/hooks/useDebounce'; -import useTranslation from '../../../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../../../shared/hooks/useTranslation'; import { ToastService } from '../../../../../shared/services/toast-service'; import { KeyCode } from '../../../../../shared/types'; -import { type AppState } from '../../../../../store'; - import './BlockSearch.scss'; -interface BlockSearchProps { - searchResults: Avo.Search.Search | null; - searchResultsLoading: boolean; - search: ( - orderProperty: Avo.Search.OrderProperty, - orderDirection: Avo.Search.OrderDirection, - from: number, - size: number, - filters?: Partial, - filterOptionSearch?: Partial - ) => Dispatch; -} - const ITEMS_IN_AUTOCOMPLETE = 5; -const BlockSearch: FC = ({ - searchResults, - searchResultsLoading, - search, - history, -}) => { +export const BlockSearch: FC = () => { const { tText, tHtml } = useTranslation(); + const navigateFunc = useNavigate(); + const [searchState, setSearchState] = useAtom(searchAtom); const [searchTerms, setSearchTerms] = useState(''); const [isAutocompleteSearchOpen, setAutocompleteSearchOpen] = useState(false); const debouncedSearchTerms = useDebounce(searchTerms, 200); + const refetchSearchResults = useCallback(async () => { + // Only do initial search after query params have been analysed and have been added to the state + const filters = { query: debouncedSearchTerms || '' }; + const searchResults = await fetchSearchResults( + 'relevance', + OrderDirection.desc, + 0, + ITEMS_IN_AUTOCOMPLETE, + filters, + {} + ); + setSearchState({ + ...searchState, + data: searchResults, + }); + }, [debouncedSearchTerms, searchState, setSearchState]); + /** * Trigger a new call to the backend for getting new search results when the searchTerms change */ useEffect(() => { - // Only do initial search after query params have been analysed and have been added to the state - const filters = { query: debouncedSearchTerms || '' }; - - search('relevance', OrderDirection.desc, 0, ITEMS_IN_AUTOCOMPLETE, filters, {}); - }, [debouncedSearchTerms, search]); + refetchSearchResults(); + }, [refetchSearchResults]); // Computed const autocompleteMenuItems = ( - get(searchResults, 'results', []) as Avo.Search.ResultItem[] + (searchState?.data?.results || []) as Avo.Search.ResultItem[] ).map( (searchResult: Avo.Search.ResultItem): MenuSearchResultItemInfo => ({ label: searchResult.dc_title, @@ -91,21 +86,18 @@ const BlockSearch: FC = ({ // Methods const gotoSearchPage = () => { - history.push(generateSearchLinkString(SearchFilter.query, searchTerms)); + navigateFunc(generateSearchLinkString(SearchFilter.query, searchTerms)); }; const goToSearchResult = (searchResultId: string | undefined) => { if (!isNil(searchResultId)) { // Collection ids are numbers and item ids are strings - const searchResultItem: Avo.Search.ResultItem | undefined = find( - get(searchResults, 'results', []), - { - id: searchResultId.toString(), - } - ); + const searchResultItem: Avo.Search.ResultItem | undefined = ( + searchState?.data?.results || [] + ).find((searchResult) => searchResult.id === searchResultId.toString()); if (searchResultItem) { - history.push( + navigateFunc( generateContentLinkString( searchResultItem.administrative_type, searchResultItem.id @@ -161,7 +153,7 @@ const BlockSearch: FC = ({
- {!searchResultsLoading ? ( + {!searchState.data?.results ? ( = ({ ); }; - -const mapStateToProps = (state: AppState) => ({ - searchResults: selectSearchResults(state), - searchResultsLoading: selectSearchLoading(state), -}); - -const mapDispatchToProps = (dispatch: Dispatch) => { - return { - search: ( - orderProperty: Avo.Search.OrderProperty, - orderDirection: Avo.Search.OrderDirection, - from: number, - size: number, - filters?: Partial, - filterOptionSearch?: Partial - ) => - dispatch( - getSearchResults( - orderProperty, - orderDirection, - from, - size, - filters, - filterOptionSearch - ) as any - ), - }; -}; - -export default withRouter( - connect(mapStateToProps, mapDispatchToProps)(BlockSearch) -) as unknown as FC; diff --git a/src/admin/content-page/components/blocks/MediaGridWrapper/MediaGridWrapper.tsx b/src/admin/content-page/components/blocks/MediaGridWrapper/MediaGridWrapper.tsx index f5df43b4f4..0ea6b7eed2 100644 --- a/src/admin/content-page/components/blocks/MediaGridWrapper/MediaGridWrapper.tsx +++ b/src/admin/content-page/components/blocks/MediaGridWrapper/MediaGridWrapper.tsx @@ -12,19 +12,18 @@ import { type RenderLinkFunction, } from '@viaa/avo2-components'; import { type Avo } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { compact, isEmpty, isNil } from 'lodash-es'; import React, { type FC, type ReactNode, useCallback, useEffect, useState } from 'react'; -import { withRouter } from 'react-router'; -import { type RouteComponentProps } from 'react-router-dom'; -import { compose } from 'redux'; import placeholderImage from '../../../../../assets/images/assignment-placeholder.png'; +import { commonUserAtom } from '../../../../../authentication/authentication.store'; import { CONTENT_TYPE_TRANSLATIONS, ContentTypeString, } from '../../../../../collection/collection.types'; import { APP_PATH } from '../../../../../constants'; -import ItemVideoDescription from '../../../../../item/components/ItemVideoDescription'; +import { ItemVideoDescription } from '../../../../../item/components/ItemVideoDescription'; import { LoadingErrorLoadedComponent, type LoadingInfo, @@ -36,8 +35,7 @@ import { defaultRenderBookmarkButton } from '../../../../../shared/helpers/defau import { formatDate } from '../../../../../shared/helpers/formatters'; import { isMobileWidth } from '../../../../../shared/helpers/media-query'; import { parseIntOrDefault } from '../../../../../shared/helpers/parsers/number'; -import withUser, { type UserProps } from '../../../../../shared/hocs/withUser'; -import useTranslation from '../../../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../../../shared/hooks/useTranslation'; import { BookmarksViewsPlaysService } from '../../../../../shared/services/bookmarks-views-plays-service'; import { ToastService } from '../../../../../shared/services/toast-service'; import { ADMIN_PATH } from '../../../../admin.const'; @@ -59,7 +57,7 @@ interface MediaGridWrapperProps extends MediaGridBlockState { ctaButtonAltTitle?: string; } -const MediaGridWrapper: FC = ({ +export const MediaGridWrapper: FC = ({ title, titleType = 'h2', buttonLabel, @@ -85,12 +83,12 @@ const MediaGridWrapper: FC { // TODO remove any when typings for admin-core-ui is fixed const { tText, tHtml } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); + const [loadingInfo, setLoadingInfo] = useState({ state: 'loading' }); const [resolvedResults, setResolvedResults] = useState< ResolvedItemOrCollectionOrAssignmentOrContentPage[] | null @@ -588,5 +586,3 @@ const MediaGridWrapper: FC ); }; - -export default compose(withRouter, withUser)(MediaGridWrapper) as FC; diff --git a/src/admin/content-page/content-page.routes.tsx b/src/admin/content-page/content-page.routes.tsx deleted file mode 100644 index a11a95673a..0000000000 --- a/src/admin/content-page/content-page.routes.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import React, { type ReactNode } from 'react'; - -import { SecuredRoute } from '../../authentication/components'; - -import { CONTENT_PAGE_PATH } from './content-page.consts'; -import ContentPageDetailPage from './views/ContentPageDetailPage'; -import ContentPageEditPage from './views/ContentPageEditPage'; -import ContentPageOverviewPage from './views/ContentPageOverviewPage'; - -export const renderAdminContentPageRoutes = (): ReactNode[] => { - return [ - , - , - , - , - ]; -}; diff --git a/src/admin/content-page/views/ContentPageDetailPage.tsx b/src/admin/content-page/views/ContentPageDetailPage.tsx index 20c43a5436..b766624c6f 100644 --- a/src/admin/content-page/views/ContentPageDetailPage.tsx +++ b/src/admin/content-page/views/ContentPageDetailPage.tsx @@ -1,17 +1,17 @@ -import type { ContentPageDetailProps, ContentPageInfo } from '@meemoo/admin-core-ui/dist/admin.mjs'; +import type { ContentPageInfo } from '@meemoo/admin-core-ui/dist/admin.mjs'; import { Flex, Spinner } from '@viaa/avo2-components'; +import { useAtomValue } from 'jotai'; import React, { type FC, lazy, Suspense, useState } from 'react'; import { Helmet } from 'react-helmet'; -import { withRouter } from 'react-router-dom'; -import { compose } from 'redux'; +import { useMatch, useNavigate } from 'react-router'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; +import { commonUserAtom } from '../../../authentication/authentication.store'; import { GENERATE_SITE_TITLE } from '../../../constants'; import { goBrowserBackWithFallback } from '../../../shared/helpers/go-browser-back-with-fallback'; -import withUser, { type UserProps } from '../../../shared/hocs/withUser'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { ADMIN_PATH } from '../../admin.const'; import { withAdminCoreConfig } from '../../shared/hoc/with-admin-core-config'; +import { CONTENT_PAGE_PATH } from '../content-page.consts'; const ContentPageDetail = lazy(() => import('@meemoo/admin-core-ui/dist/admin.mjs').then((adminCoreModule) => ({ @@ -19,10 +19,11 @@ const ContentPageDetail = lazy(() => })) ); -const ContentPageDetailPage: FC< - DefaultSecureRouteProps<{ id: string }> & ContentPageDetailProps & UserProps -> = ({ match, history, commonUser }) => { - const { id } = match.params; +const ContentPageDetailPage: FC = () => { + const navigateFunc = useNavigate(); + const match = useMatch<'id', string>(CONTENT_PAGE_PATH.CONTENT_PAGE_DETAIL); + const id = match?.params.id; + const commonUser = useAtomValue(commonUserAtom); const { tText } = useTranslation(); const [item, setItem] = useState(undefined); @@ -49,18 +50,23 @@ const ContentPageDetailPage: FC< } > - - goBrowserBackWithFallback(ADMIN_PATH.CONTENT_PAGE_OVERVIEWS, history) - } - /> + {!!id && ( + + goBrowserBackWithFallback( + ADMIN_PATH.CONTENT_PAGE_OVERVIEWS, + navigateFunc + ) + } + /> + )} ); }; -export default compose(withAdminCoreConfig, withUser, withRouter)(ContentPageDetailPage) as FC; +export default withAdminCoreConfig(ContentPageDetailPage) as FC; diff --git a/src/admin/content-page/views/ContentPageEditPage.tsx b/src/admin/content-page/views/ContentPageEditPage.tsx index d5dd5cd8f2..4429bf08c5 100644 --- a/src/admin/content-page/views/ContentPageEditPage.tsx +++ b/src/admin/content-page/views/ContentPageEditPage.tsx @@ -1,17 +1,16 @@ -import type { ContentPageDetailProps } from '@meemoo/admin-core-ui/dist/admin.mjs'; import { Flex, Spinner } from '@viaa/avo2-components'; +import { useAtomValue } from 'jotai'; import React, { type FC, lazy, Suspense, useState } from 'react'; -import { withRouter } from 'react-router-dom'; -import { compose } from 'redux'; +import { useMatch, useNavigate } from 'react-router'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; +import { commonUserAtom } from '../../../authentication/authentication.store'; import { BeforeUnloadPrompt } from '../../../shared/components/BeforeUnloadPrompt/BeforeUnloadPrompt'; import { buildLink } from '../../../shared/helpers/build-link'; import { goBrowserBackWithFallback } from '../../../shared/helpers/go-browser-back-with-fallback'; -import withUser, { type UserProps } from '../../../shared/hocs/withUser'; import { useWarningBeforeUnload } from '../../../shared/hooks/useWarningBeforeUnload'; import { ADMIN_PATH } from '../../admin.const'; import { withAdminCoreConfig } from '../../shared/hoc/with-admin-core-config'; +import { CONTENT_PAGE_PATH } from '../content-page.consts'; const ContentPageEdit = lazy(() => import('@meemoo/admin-core-ui/dist/admin.mjs').then((adminCoreModule) => ({ @@ -19,12 +18,14 @@ const ContentPageEdit = lazy(() => })) ); -const ContentPageDetailPage: FC< - DefaultSecureRouteProps<{ id: string }> & ContentPageDetailProps & UserProps -> = ({ match, history, commonUser }) => { - const { id } = match.params; +const ContentPageDetailPage: FC = () => { + const navigateFunc = useNavigate(); + const match = useMatch<'id', string>(CONTENT_PAGE_PATH.CONTENT_PAGE_EDIT); - const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); + const contentPageId = match?.params.id; + + const commonUser = useAtomValue(commonUserAtom); + const [hasUnsavedChanges] = useState(false); useWarningBeforeUnload({ when: hasUnsavedChanges, @@ -40,13 +41,13 @@ const ContentPageDetailPage: FC< > goBrowserBackWithFallback( - buildLink(ADMIN_PATH.CONTENT_PAGE_DETAIL, { id }), - history + buildLink(ADMIN_PATH.CONTENT_PAGE_DETAIL, { id: contentPageId }), + navigateFunc ) } /> @@ -55,4 +56,4 @@ const ContentPageDetailPage: FC< ); }; -export default compose(withAdminCoreConfig, withUser, withRouter)(ContentPageDetailPage) as FC; +export default withAdminCoreConfig(ContentPageDetailPage) as FC; diff --git a/src/admin/content-page/views/ContentPageOverviewPage.tsx b/src/admin/content-page/views/ContentPageOverviewPage.tsx index c6d4bd2fde..c05c919328 100644 --- a/src/admin/content-page/views/ContentPageOverviewPage.tsx +++ b/src/admin/content-page/views/ContentPageOverviewPage.tsx @@ -1,14 +1,13 @@ import { Button, Flex, Spinner } from '@viaa/avo2-components'; import { PermissionName } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import React, { type FC, lazy, Suspense, useCallback } from 'react'; import { Helmet } from 'react-helmet'; -import { compose } from 'redux'; +import { useNavigate } from 'react-router'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; +import { commonUserAtom } from '../../../authentication/authentication.store'; import { GENERATE_SITE_TITLE } from '../../../constants'; -import withUser, { type UserProps } from '../../../shared/hocs/withUser'; -import useTranslation from '../../../shared/hooks/useTranslation'; -import { withAdminCoreConfig } from '../../shared/hoc/with-admin-core-config'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { AdminLayout } from '../../shared/layouts/AdminLayout/AdminLayout'; import { AdminLayoutBody, @@ -26,11 +25,10 @@ const ContentPageOverview = lazy(() => const { CREATE_CONTENT_PAGES } = PermissionName; -const ContentPageOverviewPage: FC = ({ - history, - commonUser, -}) => { +export const ContentPageOverviewPage: FC = () => { const { tText } = useTranslation(); + const navigateFunc = useNavigate(); + const commonUser = useAtomValue(commonUserAtom); const hasPerm = useCallback( (permission: PermissionName) => commonUser?.permissions?.includes(permission), @@ -66,7 +64,7 @@ const ContentPageOverviewPage: FC = ({ title={tText( 'admin/content/views/content-overview___maak-een-nieuwe-content-pagina-aan' )} - onClick={() => history.push(CONTENT_PAGE_PATH.CONTENT_PAGE_CREATE)} + onClick={() => navigateFunc(CONTENT_PAGE_PATH.CONTENT_PAGE_CREATE)} /> )} @@ -91,5 +89,3 @@ const ContentPageOverviewPage: FC = ({ ); }; - -export default compose(withAdminCoreConfig, withUser)(ContentPageOverviewPage) as FC; diff --git a/src/admin/dashboard/dashboard.routes.tsx b/src/admin/dashboard/dashboard.routes.tsx deleted file mode 100644 index 9766bff6c9..0000000000 --- a/src/admin/dashboard/dashboard.routes.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React, { type ReactNode } from 'react'; - -import { SecuredRoute } from '../../authentication/components'; - -import { DASHBOARD_PATH } from './dashboard.const'; -import { Dashboard } from './views'; - -export const renderAdminDashboardRoutes = (): ReactNode[] => [ - , -]; diff --git a/src/admin/dashboard/views/Dashboard.tsx b/src/admin/dashboard/views/Dashboard.tsx index 808fcef0d7..50d4e63634 100644 --- a/src/admin/dashboard/views/Dashboard.tsx +++ b/src/admin/dashboard/views/Dashboard.tsx @@ -1,12 +1,26 @@ import React from 'react'; import { Helmet } from 'react-helmet'; +import { type ClientLoaderFunctionArgs, redirect } from 'react-router'; -import { GENERATE_SITE_TITLE } from '../../../constants'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { commonUserAtom } from '../../../authentication/authentication.store'; +import { APP_PATH, GENERATE_SITE_TITLE } from '../../../constants'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; +import { store } from '../../../shared/store/ui.store'; import { AdminLayout } from '../../shared/layouts/AdminLayout/AdminLayout'; import { AdminLayoutBody } from '../../shared/layouts/AdminLayout/AdminLayout.slots'; -const Dashboard = () => { +export async function clientLoader({ serverLoader }: ClientLoaderFunctionArgs) { + const commonUser = store.get(commonUserAtom); + console.log('clientLoader called', { serverLoader, commonUser }); + if (!commonUser) { + throw redirect(APP_PATH.LOGIN.route); + } + return await serverLoader(); +} + +clientLoader.hydrate = true as const; + +export const Dashboard = () => { const { tText, tHtml } = useTranslation(); return ( @@ -30,5 +44,3 @@ const Dashboard = () => { ); }; - -export default Dashboard; diff --git a/src/admin/dashboard/views/index.ts b/src/admin/dashboard/views/index.ts deleted file mode 100644 index bc150a18cc..0000000000 --- a/src/admin/dashboard/views/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import Dashboard from './Dashboard'; - -export { Dashboard }; diff --git a/src/admin/interactive-tour/components/InteractiveTourStepAdd.tsx b/src/admin/interactive-tour/components/InteractiveTourStepAdd.tsx index b6e9bb2b7f..9e7a877869 100644 --- a/src/admin/interactive-tour/components/InteractiveTourStepAdd.tsx +++ b/src/admin/interactive-tour/components/InteractiveTourStepAdd.tsx @@ -3,7 +3,7 @@ import { cloneDeep } from 'lodash-es'; import React, { type FC } from 'react'; import { generateRandomId } from '../../../shared/helpers/uuid'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { type InteractiveTourAction } from '../helpers/reducers'; import { type EditableInteractiveTour, @@ -17,7 +17,7 @@ interface InteractiveTourAddProps { changeInteractiveTourState: (action: InteractiveTourAction) => void; } -const InteractiveTourAdd: FC = ({ +export const InteractiveTourAdd: FC = ({ index, interactiveTour, changeInteractiveTourState, @@ -75,5 +75,3 @@ const InteractiveTourAdd: FC = ({ ); }; - -export default InteractiveTourAdd; diff --git a/src/admin/interactive-tour/interactive-tour.routes.tsx b/src/admin/interactive-tour/interactive-tour.routes.tsx deleted file mode 100644 index 3d520b3797..0000000000 --- a/src/admin/interactive-tour/interactive-tour.routes.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React, { type ReactNode } from 'react'; - -import { SecuredRoute } from '../../authentication/components'; - -import { INTERACTIVE_TOUR_PATH } from './interactive-tour.const'; -import { InteractiveTourDetail, InteractiveTourEdit, InteractiveTourOverview } from './views'; - -export const renderInteractiveTourRoutes = (): ReactNode[] => [ - , - , - , - , -]; diff --git a/src/admin/interactive-tour/views/InteractiveTourDetail.tsx b/src/admin/interactive-tour/views/InteractiveTourDetail.tsx index 48783c1cab..b15db973f7 100644 --- a/src/admin/interactive-tour/views/InteractiveTourDetail.tsx +++ b/src/admin/interactive-tour/views/InteractiveTourDetail.tsx @@ -9,7 +9,7 @@ import { import { get } from 'lodash-es'; import React, { type FC, useCallback, useEffect, useState } from 'react'; import { Helmet } from 'react-helmet'; -import { type RouteComponentProps } from 'react-router'; +import { useMatch, useNavigate } from 'react-router'; import { redirectToClientPage } from '../../../authentication/helpers/redirects/redirect-to-client-page'; import { APP_PATH, GENERATE_SITE_TITLE } from '../../../constants'; @@ -21,7 +21,7 @@ import { import { buildLink } from '../../../shared/helpers/build-link'; import { CustomError } from '../../../shared/helpers/custom-error'; import { navigate } from '../../../shared/helpers/link'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { ToastService } from '../../../shared/services/toast-service'; import { ADMIN_PATH } from '../../admin.const'; import { @@ -38,9 +38,12 @@ import { INTERACTIVE_TOUR_PATH } from '../interactive-tour.const'; import { InteractiveTourService } from '../interactive-tour.service'; import { type InteractiveTour } from '../interactive-tour.types'; -type InteractiveTourDetailProps = RouteComponentProps<{ id: string }>; +export const InteractiveTourDetail: FC = () => { + const navigateFunc = useNavigate(); + const match = useMatch<'id', string>(INTERACTIVE_TOUR_PATH.INTERACTIVE_TOUR_DETAIL); + + const interactiveTourId = match?.params.id; -const InteractiveTourDetail: FC = ({ history, match }) => { // Hooks const [interactiveTour, setInteractiveTour] = useState(null); const [loadingInfo, setLoadingInfo] = useState({ state: 'loading' }); @@ -50,13 +53,24 @@ const InteractiveTourDetail: FC = ({ history, match const fetchInteractiveTourById = useCallback(async () => { try { - setInteractiveTour(await InteractiveTourService.fetchInteractiveTour(match.params.id)); + if (!interactiveTourId) { + setLoadingInfo({ + state: 'error', + message: tHtml( + 'admin/interactive-tour/views/interactive-tour-detail___het-ophalen-van-de-interactive-tour-is-mislukt' + ), + }); + return; + } + setInteractiveTour( + await InteractiveTourService.fetchInteractiveTour(interactiveTourId) + ); } catch (err) { console.error( new CustomError('Failed to get interactive tour by id', err, { query: 'GET_INTERACTIVE_TOUR_BY_ID', variables: { - id: match.params.id, + id: interactiveTourId, }, }) ); @@ -67,7 +81,7 @@ const InteractiveTourDetail: FC = ({ history, match ), }); } - }, [match.params.id, tHtml]); + }, [interactiveTourId, tHtml]); useEffect(() => { fetchInteractiveTourById(); @@ -105,7 +119,7 @@ const InteractiveTourDetail: FC = ({ history, match 'admin/interactive-tour/views/interactive-tour-detail___de-interactive-tour-is-verwijdert' ) ); - redirectToClientPage(ADMIN_PATH.INTERACTIVE_TOUR_OVERVIEW, history); + redirectToClientPage(ADMIN_PATH.INTERACTIVE_TOUR_OVERVIEW, navigateFunc); } catch (err) { console.error( new CustomError('Failed to delete interactive tour', err, { interactiveTour }) @@ -171,7 +185,7 @@ const InteractiveTourDetail: FC = ({ history, match const renderInteractiveTourDetailPage = () => ( navigate(history, ADMIN_PATH.INTERACTIVE_TOUR_OVERVIEW)} + onClickBackButton={() => navigate(navigateFunc, ADMIN_PATH.INTERACTIVE_TOUR_OVERVIEW)} pageTitle={tText( 'admin/interactive-tour/views/interactive-tour-detail___interactive-tour-details' )} @@ -194,9 +208,9 @@ const InteractiveTourDetail: FC = ({ history, match onClick={() => { redirectToClientPage( buildLink(INTERACTIVE_TOUR_PATH.INTERACTIVE_TOUR_EDIT, { - id: match.params.id, + id: interactiveTourId, }), - history + navigateFunc ); }} /> @@ -253,5 +267,3 @@ const InteractiveTourDetail: FC = ({ history, match ); }; - -export default InteractiveTourDetail; diff --git a/src/admin/interactive-tour/views/InteractiveTourEdit.tsx b/src/admin/interactive-tour/views/InteractiveTourEdit.tsx index ed403d1029..df1ef960d9 100644 --- a/src/admin/interactive-tour/views/InteractiveTourEdit.tsx +++ b/src/admin/interactive-tour/views/InteractiveTourEdit.tsx @@ -25,8 +25,9 @@ import React, { useState, } from 'react'; import { Helmet } from 'react-helmet'; +import { useMatch, useNavigate } from 'react-router'; +import { useLocation } from 'react-router-dom'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; import { redirectToClientPage } from '../../../authentication/helpers/redirects/redirect-to-client-page'; import { APP_PATH, GENERATE_SITE_TITLE } from '../../../constants'; import { OrderDirection } from '../../../search/search.const'; @@ -43,7 +44,7 @@ import { GetInteractiveTourByIdDocument } from '../../../shared/generated/graphq import { buildLink } from '../../../shared/helpers/build-link'; import { CustomError } from '../../../shared/helpers/custom-error'; import { navigate } from '../../../shared/helpers/link'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { dataService } from '../../../shared/services/data-service'; import { ToastService } from '../../../shared/services/toast-service'; import { ADMIN_PATH } from '../../admin.const'; @@ -54,7 +55,7 @@ import { AdminLayoutTopBarRight, } from '../../shared/layouts/AdminLayout/AdminLayout.slots'; import { type PickerItem } from '../../shared/types'; -import InteractiveTourAdd from '../components/InteractiveTourStepAdd'; +import { InteractiveTourAdd } from '../components/InteractiveTourStepAdd'; import { INTERACTIVE_TOUR_EDIT_INITIAL_STATE, type InteractiveTourAction, @@ -77,7 +78,7 @@ import { type InteractiveTourStep, } from '../interactive-tour.types'; -import InteractiveTourEditStep from './InteractiveTourEditStep'; +import { InteractiveTourEditStep } from './InteractiveTourEditStep'; import './InteractiveTourEdit.scss'; @@ -87,10 +88,13 @@ const BlockHeading = lazy(() => })) ); -type InteractiveTourEditProps = DefaultSecureRouteProps<{ id: string }>; - -const InteractiveTourEdit: FC = ({ history, match, location }) => { +export const InteractiveTourEdit: FC = () => { const { tText, tHtml } = useTranslation(); + const location = useLocation(); + const navigateFunc = useNavigate(); + const match = useMatch<'id', string>(INTERACTIVE_TOUR_PATH.INTERACTIVE_TOUR_EDIT); + + const interactiveTourId = match?.params.id; // Hooks const [formErrors, setFormErrors] = useState({}); @@ -142,12 +146,15 @@ const InteractiveTourEdit: FC = ({ history, match, loc }); } else { try { + if (!interactiveTourId) { + return; + } const response = await dataService.query< GetInteractiveTourByIdQuery, GetInteractiveTourByIdQueryVariables >({ query: GetInteractiveTourByIdDocument, - variables: { id: parseInt(match.params.id) }, + variables: { id: parseInt(interactiveTourId) }, }); const interactiveTourObj = response.app_interactive_tour[0]; @@ -173,7 +180,7 @@ const InteractiveTourEdit: FC = ({ history, match, loc console.error( new CustomError('Failed to get interactive tour by id', err, { query: 'GET_INTERACTIVE_TOUR_BY_ID', - variables: { id: match.params.id }, + variables: { id: interactiveTourId }, }) ); setLoadingInfo({ @@ -190,7 +197,7 @@ const InteractiveTourEdit: FC = ({ history, match, loc tHtml, isCreatePage, getPageType, - match.params.id, + interactiveTourId, ]); useEffect(() => { @@ -205,10 +212,10 @@ const InteractiveTourEdit: FC = ({ history, match, loc const navigateBack = () => { if (isCreatePage) { - history.push(INTERACTIVE_TOUR_PATH.INTERACTIVE_TOUR_OVERVIEW); + navigateFunc(INTERACTIVE_TOUR_PATH.INTERACTIVE_TOUR_OVERVIEW); } else { - navigate(history, INTERACTIVE_TOUR_PATH.INTERACTIVE_TOUR_DETAIL, { - id: match.params.id, + navigate(navigateFunc, INTERACTIVE_TOUR_PATH.INTERACTIVE_TOUR_DETAIL, { + id: interactiveTourId, }); } }; @@ -271,6 +278,9 @@ const InteractiveTourEdit: FC = ({ history, match, loc const handleSave = async () => { try { + if (!interactiveTourId) { + return; + } const errors = getFormErrors(); setFormErrors(errors || {}); if (errors) { @@ -301,21 +311,21 @@ const InteractiveTourEdit: FC = ({ history, match, loc interactiveTourState.currentInteractiveTour ); - let interactiveTourId: number | string; + let tempInteractiveTourId: number | string; if (isCreatePage) { // insert the interactive tour - interactiveTourId = await InteractiveTourService.insertInteractiveTour(tour); + tempInteractiveTourId = await InteractiveTourService.insertInteractiveTour(tour); } else { // Update existing interactive tour await InteractiveTourService.updateInteractiveTour(tour); - interactiveTourId = match.params.id; + tempInteractiveTourId = interactiveTourId; } redirectToClientPage( buildLink(INTERACTIVE_TOUR_PATH.INTERACTIVE_TOUR_DETAIL, { - id: interactiveTourId, + id: tempInteractiveTourId, }), - history + navigateFunc ); ToastService.success( tHtml( @@ -501,7 +511,7 @@ const InteractiveTourEdit: FC = ({ history, match, loc // Render const renderPage = () => ( navigate(history, ADMIN_PATH.INTERACTIVE_TOUR_OVERVIEW)} + onClickBackButton={() => navigate(navigateFunc, ADMIN_PATH.INTERACTIVE_TOUR_OVERVIEW)} pageTitle={tText( 'admin/interactive-tour/views/interactive-tour-edit___interactive-tour-aanpassen' )} @@ -565,5 +575,3 @@ const InteractiveTourEdit: FC = ({ history, match, loc ); }; - -export default InteractiveTourEdit; diff --git a/src/admin/interactive-tour/views/InteractiveTourEditStep.tsx b/src/admin/interactive-tour/views/InteractiveTourEditStep.tsx index 376db1cfa1..ea9e0a3cd3 100644 --- a/src/admin/interactive-tour/views/InteractiveTourEditStep.tsx +++ b/src/admin/interactive-tour/views/InteractiveTourEditStep.tsx @@ -21,9 +21,9 @@ import { get, isEqual } from 'lodash-es'; import React, { type FC } from 'react'; import { RICH_TEXT_EDITOR_OPTIONS_FULL } from '../../../shared/components/RichTextEditorWrapper/RichTextEditor.consts'; -import RichTextEditorWrapper from '../../../shared/components/RichTextEditorWrapper/RichTextEditorWrapper'; +import { RichTextEditorWrapper } from '../../../shared/components/RichTextEditorWrapper/RichTextEditorWrapper'; import { stripHtml } from '../../../shared/helpers/formatters'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { type InteractiveTourAction } from '../helpers/reducers'; import { type EditableStep, InteractiveTourEditActionType } from '../interactive-tour.types'; @@ -37,7 +37,7 @@ interface InteractiveTourEditStepProps { changeInteractiveTourState: (action: InteractiveTourAction) => void; } -const InteractiveTourEditStep: FC = ({ +export const InteractiveTourEditStep: FC = ({ step, index, numberOfSteps, diff --git a/src/admin/interactive-tour/views/InteractiveTourOverview.tsx b/src/admin/interactive-tour/views/InteractiveTourOverview.tsx index 34628bed26..3426655742 100644 --- a/src/admin/interactive-tour/views/InteractiveTourOverview.tsx +++ b/src/admin/interactive-tour/views/InteractiveTourOverview.tsx @@ -3,12 +3,12 @@ import { Button, ButtonToolbar, IconName, Spacer } from '@viaa/avo2-components'; import { get, isNil } from 'lodash-es'; import React, { type FC, useCallback, useEffect, useState } from 'react'; import { Helmet } from 'react-helmet'; +import { useNavigate } from 'react-router'; import { Link } from 'react-router-dom'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; import { redirectToClientPage } from '../../../authentication/helpers/redirects/redirect-to-client-page'; import { APP_PATH, GENERATE_SITE_TITLE } from '../../../constants'; -import { ErrorView } from '../../../error/views'; +import { ErrorView } from '../../../error/views/ErrorView'; import { OrderDirection } from '../../../search/search.const'; import { ConfirmModal } from '../../../shared/components/ConfirmModal/ConfirmModal'; import { @@ -20,7 +20,7 @@ import { CustomError } from '../../../shared/helpers/custom-error'; import { formatDate } from '../../../shared/helpers/formatters'; import { navigate } from '../../../shared/helpers/link'; import { ACTIONS_TABLE_COLUMN_ID } from '../../../shared/helpers/table-column-list-to-csv-column-list'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { ToastService } from '../../../shared/services/toast-service'; import { ADMIN_PATH } from '../../admin.const'; import { getDateRangeFilters, getQueryFilter } from '../../shared/helpers/filters'; @@ -41,10 +41,9 @@ import { type InteractiveTourTableState, } from '../interactive-tour.types'; -type InteractiveTourOverviewProps = DefaultSecureRouteProps; - -const InteractiveTourGroupOverview: FC = ({ history }) => { +export const InteractiveTourOverview: FC = () => { const { tText, tHtml } = useTranslation(); + const navigateFunc = useNavigate(); const [interactiveTourIdToDelete, setInteractiveTourIdToDelete] = useState(null); const [isConfirmModalOpen, setIsConfirmModalOpen] = useState(false); @@ -186,9 +185,13 @@ const InteractiveTourGroupOverview: FC = ({ histor type="secondary" icon={IconName.eye} onClick={() => - navigate(history, INTERACTIVE_TOUR_PATH.INTERACTIVE_TOUR_DETAIL, { - id: rowData.id, - }) + navigate( + navigateFunc, + INTERACTIVE_TOUR_PATH.INTERACTIVE_TOUR_DETAIL, + { + id: rowData.id, + } + ) } title={tText( 'admin/interactive-tour/views/interactive-tour-overview___bekijk-de-rondleiding-detail-pagina' @@ -200,9 +203,13 @@ const InteractiveTourGroupOverview: FC = ({ histor
+ ); + }; + + return ( + + {body} + + ); + }; + + return ; +}; diff --git a/src/admin/navigations/navigations.routes.tsx b/src/admin/navigations/navigations.routes.tsx deleted file mode 100644 index 672d4b887e..0000000000 --- a/src/admin/navigations/navigations.routes.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import React, { type ReactNode } from 'react'; - -import { SecuredRoute } from '../../authentication/components'; - -import { NAVIGATIONS_PATH } from './navigations.const'; -import { NavigationBarDetail, NavigationBarOverview, NavigationItemEdit } from './views'; - -export const renderAdminNavigationRoutes = (): ReactNode[] => [ - , - , - , - , - , -]; diff --git a/src/admin/navigations/views/NavigationBarDetail.tsx b/src/admin/navigations/views/NavigationBarDetail.tsx index 0c9821e672..8e864f5137 100644 --- a/src/admin/navigations/views/NavigationBarDetail.tsx +++ b/src/admin/navigations/views/NavigationBarDetail.tsx @@ -1,17 +1,16 @@ import { Flex, Spinner } from '@viaa/avo2-components'; import React, { type FC, lazy, Suspense } from 'react'; import { Helmet } from 'react-helmet'; -import { withRouter } from 'react-router-dom'; -import { compose } from 'redux'; +import { useMatch, useNavigate } from 'react-router'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; import { GENERATE_SITE_TITLE } from '../../../constants'; import { goBrowserBackWithFallback } from '../../../shared/helpers/go-browser-back-with-fallback'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { ADMIN_PATH } from '../../admin.const'; import { withAdminCoreConfig } from '../../shared/hoc/with-admin-core-config'; import './NavigationBarDetail.scss'; +import { NAVIGATIONS_PATH } from '../navigations.const'; const NavigationDetail = lazy(() => import('@meemoo/admin-core-ui/dist/admin.mjs').then((adminCoreModule) => ({ @@ -19,12 +18,12 @@ const NavigationDetail = lazy(() => })) ); -type NavigationBarDetailProps = DefaultSecureRouteProps<{ navigationBarId: string }>; - -const NavigationBarDetail: FC = ({ match, history }) => { +const NavigationBarDetail: FC = () => { const { tText } = useTranslation(); + const navigateFunc = useNavigate(); + const match = useMatch<'navigationBarId', string>(NAVIGATIONS_PATH.NAVIGATIONS_DETAIL); - const navigationBarId = match.params.navigationBarId; + const navigationBarId = match?.params.navigationBarId; return (
@@ -49,15 +48,17 @@ const NavigationBarDetail: FC = ({ match, history }) = } > - - goBrowserBackWithFallback(ADMIN_PATH.NAVIGATIONS_OVERVIEW, history) - } - /> + {!!navigationBarId && ( + + goBrowserBackWithFallback(ADMIN_PATH.NAVIGATIONS_OVERVIEW, navigateFunc) + } + /> + )}
); }; -export default compose(withAdminCoreConfig, withRouter)(NavigationBarDetail) as FC; +export default withAdminCoreConfig(NavigationBarDetail) as FC; diff --git a/src/admin/navigations/views/NavigationBarOverview.tsx b/src/admin/navigations/views/NavigationBarOverview.tsx index 6a364edc78..f7f772de85 100644 --- a/src/admin/navigations/views/NavigationBarOverview.tsx +++ b/src/admin/navigations/views/NavigationBarOverview.tsx @@ -2,9 +2,8 @@ import { Flex, Spinner } from '@viaa/avo2-components'; import React, { type FC, lazy, Suspense } from 'react'; import { Helmet } from 'react-helmet'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; import { GENERATE_SITE_TITLE } from '../../../constants'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { withAdminCoreConfig } from '../../shared/hoc/with-admin-core-config'; import './NavigationBarOverview.scss'; @@ -15,9 +14,7 @@ const NavigationOverview = lazy(() => })) ); -type NavigationBarOverviewProps = DefaultSecureRouteProps; - -const NavigationBarOverview: FC = () => { +export const NavigationBarOverview: FC = () => { const { tText } = useTranslation(); return ( @@ -48,4 +45,4 @@ const NavigationBarOverview: FC = () => { ); }; -export default withAdminCoreConfig(NavigationBarOverview as FC) as FC; +export default withAdminCoreConfig(NavigationBarOverview) as FC; diff --git a/src/admin/navigations/views/NavigationItemEdit.tsx b/src/admin/navigations/views/NavigationItemEdit.tsx index d5c9aa7953..087f87b20c 100644 --- a/src/admin/navigations/views/NavigationItemEdit.tsx +++ b/src/admin/navigations/views/NavigationItemEdit.tsx @@ -1,19 +1,17 @@ import { Flex, Spinner } from '@viaa/avo2-components'; import React, { type FC, lazy, Suspense } from 'react'; import { Helmet } from 'react-helmet'; -import { withRouter } from 'react-router-dom'; -import { compose } from 'redux'; +import { useMatch, useNavigate } from 'react-router'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; import { GENERATE_SITE_TITLE } from '../../../constants'; import { buildLink } from '../../../shared/helpers/build-link'; import { goBrowserBackWithFallback } from '../../../shared/helpers/go-browser-back-with-fallback'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { ADMIN_PATH } from '../../admin.const'; import { withAdminCoreConfig } from '../../shared/hoc/with-admin-core-config'; -import { type MenuEditParams } from '../navigations.types'; import './NavigationItemEdit.scss'; +import { NAVIGATIONS_PATH } from '../navigations.const'; const NavigationEdit = lazy(() => import('@meemoo/admin-core-ui/dist/admin.mjs').then((adminCoreModule) => ({ @@ -21,11 +19,15 @@ const NavigationEdit = lazy(() => })) ); -type NavigationItemEditProps = DefaultSecureRouteProps; - -const NavigationItemEdit: FC = ({ match, history }) => { +const NavigationItemEdit: FC = () => { const { tText } = useTranslation(); - const { navigationBarId, navigationItemId } = match.params; + const navigateFunc = useNavigate(); + const match = useMatch<'navigationBarId' | 'navigationItemId', string>( + NAVIGATIONS_PATH.NAVIGATIONS_ITEM_EDIT + ); + + const navigationBarId = match?.params.navigationBarId; + const navigationItemId = match?.params.navigationItemId; // Render return ( @@ -66,7 +68,7 @@ const NavigationItemEdit: FC = ({ match, history }) => onGoBack={() => goBrowserBackWithFallback( buildLink(ADMIN_PATH.NAVIGATIONS_DETAIL, { navigationBarId }), - history + navigateFunc ) } /> @@ -75,4 +77,4 @@ const NavigationItemEdit: FC = ({ match, history }) => ); }; -export default compose(withAdminCoreConfig, withRouter)(NavigationItemEdit) as FC; +export default withAdminCoreConfig(NavigationItemEdit) as FC; diff --git a/src/admin/pupil-collection/pupil-collection.routes.tsx b/src/admin/pupil-collection/pupil-collection.routes.tsx deleted file mode 100644 index af5946d863..0000000000 --- a/src/admin/pupil-collection/pupil-collection.routes.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React, { type ReactNode } from 'react'; - -import { SecuredRoute } from '../../authentication/components'; - -import PupilCollectionsOverview from './/views/PupilCollectionsOverview'; -import { PUPIL_COLLECTIONS_PATH } from './pupil-collection.const'; - -export const renderAdminPupilCollectionRoutes = (): ReactNode[] => [ - , -]; diff --git a/src/admin/pupil-collection/views/PupilCollectionsOverview.tsx b/src/admin/pupil-collection/views/PupilCollectionsOverview.tsx index 66d55244d3..7cd8f305e0 100644 --- a/src/admin/pupil-collection/views/PupilCollectionsOverview.tsx +++ b/src/admin/pupil-collection/views/PupilCollectionsOverview.tsx @@ -5,14 +5,14 @@ import { getFilters, } from '@meemoo/admin-core-ui/dist/admin.mjs'; import { type Avo } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { get, isNil } from 'lodash-es'; import React, { type FC, type ReactText, useCallback, useEffect, useMemo, useState } from 'react'; import { Helmet } from 'react-helmet'; -import { type RouteComponentProps, withRouter } from 'react-router-dom'; -import { compose } from 'redux'; +import { commonUserAtom } from '../../../authentication/authentication.store'; import { GENERATE_SITE_TITLE } from '../../../constants'; -import { ErrorView } from '../../../error/views'; +import { ErrorView } from '../../../error/views/ErrorView'; import { PupilCollectionService } from '../../../pupil-collection/pupil-collection.service'; import { type PupilCollectionOverviewTableColumns } from '../../../pupil-collection/pupil-collection.types'; import { OrderDirection } from '../../../search/search.const'; @@ -23,12 +23,11 @@ import { } from '../../../shared/components/LoadingErrorLoadedComponent/LoadingErrorLoadedComponent'; import { CustomError } from '../../../shared/helpers/custom-error'; import { tableColumnListToCsvColumnList } from '../../../shared/helpers/table-column-list-to-csv-column-list'; -import withUser, { type UserProps } from '../../../shared/hocs/withUser'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { ToastService } from '../../../shared/services/toast-service'; import { TableColumnDataType } from '../../../shared/types/table-column-data-type'; import { AssignmentsBulkAction } from '../../assignments/assignments.types'; -import ChangeAuthorModal from '../../shared/components/ChangeAuthorModal/ChangeAuthorModal'; +import { ChangeAuthorModal } from '../../shared/components/ChangeAuthorModal/ChangeAuthorModal'; import { getDateRangeFilters, getMultiOptionFilters } from '../../shared/helpers/filters'; import { AdminLayout } from '../../shared/layouts/AdminLayout/AdminLayout'; import { AdminLayoutBody } from '../../shared/layouts/AdminLayout/AdminLayout.slots'; @@ -44,8 +43,9 @@ import { } from '../pupil-collection.const'; import { type PupilCollectionsOverviewTableState } from '../pupil-collection.types'; -const PupilCollectionsOverview: FC = ({ commonUser }) => { +export const PupilCollectionsOverview: FC = () => { const { tText, tHtml } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); const [pupilCollections, setPupilCollections] = useState( null @@ -459,5 +459,3 @@ const PupilCollectionsOverview: FC = ({ commonU ); }; - -export default compose(withRouter, withUser)(PupilCollectionsOverview) as unknown as FC; diff --git a/src/admin/shared/components/AddOrRemoveLinkedElementsModal/AddOrRemoveLinkedElementsModal.tsx b/src/admin/shared/components/AddOrRemoveLinkedElementsModal/AddOrRemoveLinkedElementsModal.tsx index 56e4289eeb..095f0df579 100644 --- a/src/admin/shared/components/AddOrRemoveLinkedElementsModal/AddOrRemoveLinkedElementsModal.tsx +++ b/src/admin/shared/components/AddOrRemoveLinkedElementsModal/AddOrRemoveLinkedElementsModal.tsx @@ -16,7 +16,7 @@ import { import { noop } from 'lodash-es'; import React, { type FC, type ReactNode, useState } from 'react'; -import useTranslation from '../../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../../shared/hooks/useTranslation'; export type AddOrRemove = 'add' | 'remove'; @@ -30,7 +30,7 @@ interface AddOrRemoveLinkedElementsProps { callback: (addOrRemove: AddOrRemove, selectedLabels: TagInfo[]) => void; } -const AddOrRemoveLinkedElementsModal: FC = ({ +export const AddOrRemoveLinkedElementsModal: FC = ({ title, addOrRemoveLabel, contentLabel, @@ -119,5 +119,3 @@ const AddOrRemoveLinkedElementsModal: FC = ({ ); }; - -export default AddOrRemoveLinkedElementsModal; diff --git a/src/admin/shared/components/ChangeAuthorModal/ChangeAuthorModal.tsx b/src/admin/shared/components/ChangeAuthorModal/ChangeAuthorModal.tsx index fbec1c9805..3afa73d450 100644 --- a/src/admin/shared/components/ChangeAuthorModal/ChangeAuthorModal.tsx +++ b/src/admin/shared/components/ChangeAuthorModal/ChangeAuthorModal.tsx @@ -11,7 +11,7 @@ import { import { noop } from 'lodash-es'; import React, { type FC, useState } from 'react'; -import useTranslation from '../../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../../shared/hooks/useTranslation'; import { type PickerItem } from '../../types'; import { ContentPicker } from '../ContentPicker/ContentPicker'; @@ -22,7 +22,7 @@ interface ChangeAuthorModalProps { callback: (authorProfileId: PickerItem) => void; } -const ChangeAuthorModal: FC = ({ +export const ChangeAuthorModal: FC = ({ onClose = noop, isOpen, initialAuthor, @@ -93,5 +93,3 @@ const ChangeAuthorModal: FC = ({ ); }; - -export default ChangeAuthorModal; diff --git a/src/admin/shared/components/ContentPicker/ContentPicker.const.ts b/src/admin/shared/components/ContentPicker/ContentPicker.const.ts index 4a7bdf3c22..463cbea182 100644 --- a/src/admin/shared/components/ContentPicker/ContentPicker.const.ts +++ b/src/admin/shared/components/ContentPicker/ContentPicker.const.ts @@ -24,7 +24,7 @@ const GET_CONTENT_TYPE_LABELS: () => { [type: string]: string } = () => ({ FILE: tText('admin/shared/components/content-picker/content-picker___bestand'), }); -export const GET_CONTENT_TYPES: (user?: Avo.User.User) => PickerTypeOption[] = () => { +export const GET_CONTENT_TYPES: () => PickerTypeOption[] = () => { const labels = GET_CONTENT_TYPE_LABELS(); return [ { diff --git a/src/admin/shared/components/ContentPicker/ContentPicker.tsx b/src/admin/shared/components/ContentPicker/ContentPicker.tsx index 2fca7cba39..5d12da28a9 100644 --- a/src/admin/shared/components/ContentPicker/ContentPicker.tsx +++ b/src/admin/shared/components/ContentPicker/ContentPicker.tsx @@ -13,10 +13,9 @@ import React, { type FC, useCallback, useEffect, useState } from 'react'; import ReactSelect, { type ActionMeta, type PropsValue } from 'react-select'; import AsyncSelect from 'react-select/async'; -import FileUpload from '../../../../shared/components/FileUpload/FileUpload'; +import { FileUpload } from '../../../../shared/components/FileUpload/FileUpload'; import { CustomError } from '../../../../shared/helpers/custom-error'; -import withUser, { type UserProps } from '../../../../shared/hocs/withUser'; -import useTranslation from '../../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../../shared/hooks/useTranslation'; import { ToastService } from '../../../../shared/services/toast-service'; import { type PickerItem, type PickerTypeOption } from '../../types'; @@ -38,7 +37,7 @@ interface ContentPickerProps { errors?: string | string[]; } -const ContentPickerComponent: FC = ({ +export const ContentPicker: FC = ({ allowedTypes = DEFAULT_ALLOWED_TYPES, initialValue, onSelect, @@ -46,13 +45,12 @@ const ContentPickerComponent: FC = ({ hideTypeDropdown = false, hideTargetSwitch = false, errors = [], - user, }) => { const { tText, tHtml } = useTranslation(); // filter available options for the type picker const typeOptions = filterTypes( - GET_CONTENT_TYPES(user), + GET_CONTENT_TYPES(), allowedTypes as Avo.Core.ContentPickerType[] ); @@ -374,5 +372,3 @@ const ContentPickerComponent: FC = ({ ); }; - -export const ContentPicker = withUser(ContentPickerComponent) as FC; diff --git a/src/admin/shared/components/ContentPicker/item-providers/content-page.ts b/src/admin/shared/components/ContentPicker/item-providers/content-page.ts index 98c9712f4a..fa5ef87b71 100644 --- a/src/admin/shared/components/ContentPicker/item-providers/content-page.ts +++ b/src/admin/shared/components/ContentPicker/item-providers/content-page.ts @@ -12,8 +12,8 @@ export const retrieveContentPages = async ( try { const { ContentPageService } = await import('@meemoo/admin-core-ui/dist/admin.mjs'); const contentItems: Pick[] | null = title - ? await ContentPageService.getPublicContentItemsByTitle(`%${title}%`, limit) - : await ContentPageService.getPublicContentItemsByTitle(undefined, limit); + ? await ContentPageService.getPublicContentItemsByTitle(`%${title}%`, undefined, limit) + : await ContentPageService.getPublicContentItemsByTitle(undefined, undefined, limit); return parseContentPages(contentItems || []); } catch (err) { diff --git a/src/admin/shared/components/Sidebar/Sidebar.tsx b/src/admin/shared/components/Sidebar/Sidebar.tsx index 7a2f121af0..3ab2487064 100644 --- a/src/admin/shared/components/Sidebar/Sidebar.tsx +++ b/src/admin/shared/components/Sidebar/Sidebar.tsx @@ -2,12 +2,12 @@ import { Icon, IconName } from '@viaa/avo2-components'; import { clsx } from 'clsx'; import { flatten } from 'lodash-es'; import React, { type FC, type ReactElement, type ReactNode } from 'react'; -import { Link, NavLink, type RouteComponentProps } from 'react-router-dom'; +import { Link, type Location, NavLink, useLocation } from 'react-router-dom'; import { APP_PATH } from '../../../../constants'; import { CustomError } from '../../../../shared/helpers/custom-error'; import { tText } from '../../../../shared/helpers/translate-text'; -import useTranslation from '../../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../../shared/hooks/useTranslation'; import { type NavigationItemInfo } from '../../../../shared/types'; import './Sidebar.scss'; @@ -20,7 +20,7 @@ interface SidebarProps { navItems?: NavigationItemInfo[]; } -const Sidebar: FC = ({ +export const Sidebar: FC = ({ children, className, headerLink, @@ -28,11 +28,9 @@ const Sidebar: FC = ({ navItems, }) => { const { tHtml } = useTranslation(); + const location = useLocation(); - const isActiveClass = ( - item: NavigationItemInfo, - location: RouteComponentProps['location'] - ): boolean => { + const isActiveClass = (item: NavigationItemInfo, location: Location): boolean => { return ( (!!item.location && item.location === location.pathname && !item.exact) || (!!item.location && @@ -63,9 +61,12 @@ const Sidebar: FC = ({ })} > isActiveClass(navItem, location)} + className={clsx( + 'o-sidebar__avo__nav-item', + isActiveClass(navItem, location) + ? 'o-sidebar__avo__nav-item--active' + : undefined + )} to={navItem.location || '/'} > {navItem.label} @@ -124,5 +125,3 @@ const Sidebar: FC = ({
); }; - -export default Sidebar; diff --git a/src/admin/shared/components/SubjectsBeingEditedWarningModal/SubjectsBeingEditedWarningModal.tsx b/src/admin/shared/components/SubjectsBeingEditedWarningModal/SubjectsBeingEditedWarningModal.tsx index 8558cddfa6..5aea73ad95 100644 --- a/src/admin/shared/components/SubjectsBeingEditedWarningModal/SubjectsBeingEditedWarningModal.tsx +++ b/src/admin/shared/components/SubjectsBeingEditedWarningModal/SubjectsBeingEditedWarningModal.tsx @@ -5,7 +5,7 @@ import React, { type FC, type ReactNode } from 'react'; import { type APP_PATH } from '../../../../constants'; import { ConfirmModal } from '../../../../shared/components/ConfirmModal/ConfirmModal'; import { buildLink } from '../../../../shared/helpers/build-link'; -import useTranslation from '../../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../../shared/hooks/useTranslation'; import { type ValueOf } from '../../../../shared/types'; import './SubjectsBeingEditedWarningModal.scss'; @@ -21,7 +21,7 @@ interface SubjectsBeingEditedWarningModalProps { subjects: Avo.Share.EditStatus[]; } -const SubjectsBeingEditedWarningModal: FC = ({ +export const SubjectsBeingEditedWarningModal: FC = ({ onClose = noop, isOpen, title, @@ -71,5 +71,3 @@ const SubjectsBeingEditedWarningModal: FC /> ); }; - -export default SubjectsBeingEditedWarningModal; diff --git a/src/admin/shared/components/TopBar/TopBar.tsx b/src/admin/shared/components/TopBar/TopBar.tsx index bbb1ac95cd..caabf9b39e 100644 --- a/src/admin/shared/components/TopBar/TopBar.tsx +++ b/src/admin/shared/components/TopBar/TopBar.tsx @@ -13,9 +13,8 @@ import { ToolbarRight, } from '@viaa/avo2-components'; import React, { type FC, type ReactNode } from 'react'; -import { type RouteComponentProps, withRouter } from 'react-router'; -import useTranslation from '../../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../../shared/hooks/useTranslation'; import './TopBar.scss'; @@ -27,7 +26,7 @@ interface TopbarProps { size?: 'small' | 'medium' | 'large' | 'full-width'; } -const TopBarComponent: FC = ({ +export const TopBarComponent: FC = ({ onClickBackButton, title, center, @@ -73,4 +72,4 @@ const TopBarComponent: FC = ({ ); }; -export const TopBar = withRouter(TopBarComponent) as unknown as FC; +export const TopBar = TopBarComponent as unknown as FC; diff --git a/src/admin/shared/components/index.ts b/src/admin/shared/components/index.ts deleted file mode 100644 index dd3cf448b8..0000000000 --- a/src/admin/shared/components/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as Sidebar } from './Sidebar/Sidebar'; -export * from './TopBar/TopBar'; diff --git a/src/admin/shared/helpers/render-detail-fields.tsx b/src/admin/shared/helpers/render-detail-fields.tsx index 0937b584a4..4bc684d4e5 100644 --- a/src/admin/shared/helpers/render-detail-fields.tsx +++ b/src/admin/shared/helpers/render-detail-fields.tsx @@ -1,7 +1,7 @@ import { get, isBoolean, isNil, isString } from 'lodash-es'; import React, { type ReactElement, type ReactNode } from 'react'; -import Html from '../../../shared/components/Html/Html'; +import { Html } from '../../../shared/components/Html/Html'; import { formatDate } from '../../../shared/helpers/formatters'; import { tText } from '../../../shared/helpers/translate-text'; diff --git a/src/admin/shared/hoc/with-admin-core-config.const.tsx b/src/admin/shared/hoc/with-admin-core-config.const.tsx index 84ddee24f6..13f730376f 100644 --- a/src/admin/shared/hoc/with-admin-core-config.const.tsx +++ b/src/admin/shared/hoc/with-admin-core-config.const.tsx @@ -7,23 +7,26 @@ import { } from '@meemoo/admin-core-ui/dist/admin.mjs'; import { ContentBlockType, ContentPageWidth } from '@meemoo/admin-core-ui/dist/client.mjs'; import { Icon, IconName, Spinner } from '@viaa/avo2-components'; -import { DatabaseType } from '@viaa/avo2-types'; +import { type Avo, DatabaseType } from '@viaa/avo2-types'; import { compact, noop } from 'lodash-es'; import React, { type FC } from 'react'; -import { Link, useHistory } from 'react-router-dom'; +import { type NavigateFunction } from 'react-router'; +import { Link } from 'react-router-dom'; +import { commonUserAtom } from '../../../authentication/authentication.store'; import { APP_PATH, type RouteId } from '../../../constants'; -import FlowPlayerWrapper from '../../../shared/components/FlowPlayerWrapper/FlowPlayerWrapper'; +import { FlowPlayerWrapper } from '../../../shared/components/FlowPlayerWrapper/FlowPlayerWrapper'; import { DEFAULT_AUDIO_STILL, ROUTE_PARTS } from '../../../shared/constants'; import { getEnv } from '../../../shared/helpers/env'; import { tHtml } from '../../../shared/helpers/translate-html'; import { tText } from '../../../shared/helpers/translate-text'; import { EducationOrganisationService } from '../../../shared/services/education-organizations-service'; import { ToastService, ToastTypeToAvoToastType } from '../../../shared/services/toast-service'; +import { store } from '../../../shared/store/ui.store'; import { Locale } from '../../../shared/translations/translations.types'; import { ADMIN_PATH } from '../../admin.const'; -import BlockSearch from '../../content-page/components/blocks/BlockSearch/BlockSearch'; -import MediaGridWrapper from '../../content-page/components/blocks/MediaGridWrapper/MediaGridWrapper'; +import { BlockSearch } from '../../content-page/components/blocks/BlockSearch/BlockSearch'; +import { MediaGridWrapper } from '../../content-page/components/blocks/MediaGridWrapper/MediaGridWrapper'; import { GET_ADMIN_ICON_OPTIONS } from '../constants'; const alertIcons: IconName[] = [ @@ -65,9 +68,9 @@ const ALERT_ICON_LIST_CONFIG = (): { label: getAlertIconNames()[iconKey] || iconKey, })); -export function getAdminCoreConfig(): AdminConfig { +export function getAdminCoreConfig(navigateFunc: NavigateFunction): AdminConfig { const InternalLink = (linkInfo: LinkInfo) => { - return linkInfo.to || ''} />; + return ; }; const proxyUrl = getEnv('PROXY_URL') as string; @@ -259,7 +262,11 @@ export function getAdminCoreConfig(): AdminConfig { }, router: { Link: InternalLink as FC, - useHistory: useHistory, + useHistory: () => ({ + // TODO replace useHistory with single navigate function + push: (url: string) => navigateFunc(url), + replace: (url: string) => navigateFunc(url, { replace: true }), + }), }, queryCache: { // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -277,7 +284,7 @@ export function getAdminCoreConfig(): AdminConfig { onExternalLink: noop, }, routes: { - ADMIN_ALERTS_OVERVIEW: `/${ROUTE_PARTS.alerts}`, + ADMIN_ALERTS_OVERVIEW: `/${ROUTE_PARTS.admin}/${ROUTE_PARTS.alerts}`, ADMIN_ASSIGNMENTS_OVERVIEW: `/${ROUTE_PARTS.admin}/${ROUTE_PARTS.assignments}`, ADMIN_ASSIGNMENT_PUPIL_COLLECTIONS_OVERVIEW: `/${ROUTE_PARTS.admin}/${ROUTE_PARTS.pupilCollections}`, ADMIN_BUNDLES_OVERVIEW: `/${ROUTE_PARTS.admin}/${ROUTE_PARTS.bundles}`, @@ -320,6 +327,9 @@ export function getAdminCoreConfig(): AdminConfig { UserBulkAction.EXPORT_SELECTION, UserBulkAction.EXPORT_ALL, ], + getCommonUser: (): Avo.User.CommonUser | null => { + return store.get(commonUserAtom); + }, }, locale: Locale.Nl as any, env: { diff --git a/src/admin/shared/hoc/with-admin-core-config.tsx b/src/admin/shared/hoc/with-admin-core-config.tsx index ae697a4550..e91dffcb8a 100644 --- a/src/admin/shared/hoc/with-admin-core-config.tsx +++ b/src/admin/shared/hoc/with-admin-core-config.tsx @@ -1,16 +1,18 @@ import { type AdminConfig, AdminConfigManager } from '@meemoo/admin-core-ui/dist/client.mjs'; import { Spinner } from '@viaa/avo2-components'; import React, { type ComponentType, useCallback, useEffect, useState } from 'react'; -import { withRouter } from 'react-router'; +import { useNavigate } from 'react-router'; import { getAdminCoreConfig } from './with-admin-core-config.const'; export const withAdminCoreConfig = (WrappedComponent: ComponentType): ComponentType => { const Component = (props: { [key: string]: unknown }) => { + const navigateFunc = useNavigate(); + const [adminCoreConfig, setAdminCoreConfig] = useState(null); const initConfigValue = useCallback(() => { - const config: AdminConfig = getAdminCoreConfig(); + const config: AdminConfig = getAdminCoreConfig(navigateFunc); AdminConfigManager.setConfig(config); setAdminCoreConfig(config); }, []); @@ -26,5 +28,5 @@ export const withAdminCoreConfig = (WrappedComponent: ComponentType): ComponentT return )} />; }; - return withRouter(Component as any) as ComponentType; + return Component as any as ComponentType; }; diff --git a/src/admin/shared/layouts/AdminLayout/AdminLayout.tsx b/src/admin/shared/layouts/AdminLayout/AdminLayout.tsx index 5bdccd3d1b..eb2e580cab 100644 --- a/src/admin/shared/layouts/AdminLayout/AdminLayout.tsx +++ b/src/admin/shared/layouts/AdminLayout/AdminLayout.tsx @@ -1,7 +1,7 @@ import { Container, useSlot } from '@viaa/avo2-components'; import React, { type FC, type ReactNode } from 'react'; -import { TopBar } from '../../components'; +import { TopBar } from '../../components/TopBar/TopBar'; import './AdminLayout.scss'; import { diff --git a/src/admin/translations/translations.routes.tsx b/src/admin/translations/translations.routes.tsx deleted file mode 100644 index d9f896c145..0000000000 --- a/src/admin/translations/translations.routes.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React, { type ReactNode } from 'react'; - -import { SecuredRoute } from '../../authentication/components'; - -import { TRANSLATIONS_PATH } from './translations.const'; -import TranslationsOverviewPage from './views/TranslationsOverviewPage'; - -export const renderAdminTranslationsRoutes = (): ReactNode[] => [ - , -]; diff --git a/src/admin/translations/views/TranslationsOverviewPage.tsx b/src/admin/translations/views/TranslationsOverviewPage.tsx index fd5597bc41..b25106db11 100644 --- a/src/admin/translations/views/TranslationsOverviewPage.tsx +++ b/src/admin/translations/views/TranslationsOverviewPage.tsx @@ -5,7 +5,7 @@ import { Helmet } from 'react-helmet'; import { GENERATE_SITE_TITLE } from '../../../constants'; import { CustomError } from '../../../shared/helpers/custom-error'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { ToastService } from '../../../shared/services/toast-service'; import { withAdminCoreConfig } from '../../shared/hoc/with-admin-core-config'; import { AdminLayout } from '../../shared/layouts/AdminLayout/AdminLayout'; diff --git a/src/admin/user-groups/user-group.routes.tsx b/src/admin/user-groups/user-group.routes.tsx deleted file mode 100644 index 144c286a6c..0000000000 --- a/src/admin/user-groups/user-group.routes.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React, { type ReactNode } from 'react'; - -import { SecuredRoute } from '../../authentication/components'; - -import { USER_GROUP_PATH } from './user-group.const'; -import UserGroupOverviewPage from './views/UserGroupOverviewPage'; - -export const renderAdminUserGroupRoutes = (): ReactNode[] => [ - , -]; diff --git a/src/admin/user-groups/views/UserGroupOverviewPage.tsx b/src/admin/user-groups/views/UserGroupOverviewPage.tsx index c0302e05cb..dcf3d1b63c 100644 --- a/src/admin/user-groups/views/UserGroupOverviewPage.tsx +++ b/src/admin/user-groups/views/UserGroupOverviewPage.tsx @@ -4,7 +4,7 @@ import React, { type FC, lazy, Suspense, useRef, useState } from 'react'; import { Helmet } from 'react-helmet'; import { GENERATE_SITE_TITLE } from '../../../constants'; -import useTranslation from '../../../shared/hooks/use-translation/use-translation'; +import { useTranslation } from '../../../shared/hooks/use-translation/use-translation'; import { withAdminCoreConfig } from '../../shared/hoc/with-admin-core-config'; import { AdminLayout } from '../../shared/layouts/AdminLayout/AdminLayout'; import { diff --git a/src/admin/users/user.routes.tsx b/src/admin/users/user.routes.tsx deleted file mode 100644 index 8933775767..0000000000 --- a/src/admin/users/user.routes.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React, { type ReactNode } from 'react'; - -import { SecuredRoute } from '../../authentication/components'; - -import { USER_PATH } from './user.const'; -import UserDetailPage from './views/UserDetailPage'; -import UserEditPage from './views/UserEditPage'; -import UserOverviewPage from './views/UserOverviewPage'; - -export const renderAdminUserRoutes = (): ReactNode[] => [ - , - , - , -]; diff --git a/src/admin/users/views/UserDetailPage.tsx b/src/admin/users/views/UserDetailPage.tsx index 7ea412763f..7dc789baab 100644 --- a/src/admin/users/views/UserDetailPage.tsx +++ b/src/admin/users/views/UserDetailPage.tsx @@ -1,15 +1,13 @@ import { Flex, Spinner } from '@viaa/avo2-components'; -import { type Avo } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import React, { type FC, lazy, Suspense, useState } from 'react'; import { Helmet } from 'react-helmet'; -import { type RouteChildrenProps, useParams } from 'react-router'; -import { withRouter } from 'react-router-dom'; -import { compose } from 'redux'; +import { useNavigate, useParams } from 'react-router'; +import { commonUserAtom } from '../../../authentication/authentication.store'; import { GENERATE_SITE_TITLE } from '../../../constants'; import { goBrowserBackWithFallback } from '../../../shared/helpers/go-browser-back-with-fallback'; -import withUser, { type UserProps } from '../../../shared/hocs/withUser'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { ADMIN_PATH } from '../../admin.const'; import { withAdminCoreConfig } from '../../shared/hoc/with-admin-core-config'; import { UserService } from '../user.service'; @@ -22,8 +20,11 @@ const UserDetail = lazy(() => })) ); -const UserDetailPage: FC = ({ commonUser, history }) => { +const UserDetailPage: FC = () => { const { tText } = useTranslation(); + const navigateFunc = useNavigate(); + const commonUser = useAtomValue(commonUserAtom); + const [user, setUser] = useState<{ fullName?: string } | undefined>(); const { id } = useParams<{ id: string }>(); @@ -51,16 +52,20 @@ const UserDetailPage: FC = ({ commonUser, histor } > - goBrowserBackWithFallback(ADMIN_PATH.USER_OVERVIEW, history)} - commonUser={commonUser as Avo.User.CommonUser} - /> + {!!id && ( + + goBrowserBackWithFallback(ADMIN_PATH.USER_OVERVIEW, navigateFunc) + } + commonUser={commonUser} + /> + )} ); }; -export default compose(withAdminCoreConfig, withUser, withRouter)(UserDetailPage) as FC; +export default withAdminCoreConfig(UserDetailPage) as FC; diff --git a/src/admin/users/views/UserEditPage.tsx b/src/admin/users/views/UserEditPage.tsx index 15bc6ece44..2e46f2249e 100644 --- a/src/admin/users/views/UserEditPage.tsx +++ b/src/admin/users/views/UserEditPage.tsx @@ -13,19 +13,18 @@ import { type Avo } from '@viaa/avo2-types'; import { compact } from 'lodash-es'; import React, { type FC, useEffect, useState } from 'react'; import { Helmet } from 'react-helmet'; +import { useMatch, useNavigate } from 'react-router'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; import { redirectToClientPage } from '../../../authentication/helpers/redirects/redirect-to-client-page'; import { GENERATE_SITE_TITLE } from '../../../constants'; import { SettingsService } from '../../../settings/settings.service'; -import FileUpload from '../../../shared/components/FileUpload/FileUpload'; -import LomFieldsInput from '../../../shared/components/LomFieldsInput/LomFieldsInput'; +import { FileUpload } from '../../../shared/components/FileUpload/FileUpload'; +import { LomFieldsInput } from '../../../shared/components/LomFieldsInput/LomFieldsInput'; import { buildLink } from '../../../shared/helpers/build-link'; import { CustomError } from '../../../shared/helpers/custom-error'; import { PHOTO_TYPES } from '../../../shared/helpers/files'; import { navigate } from '../../../shared/helpers/link'; -import { type UserProps } from '../../../shared/hocs/withUser'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { ToastService } from '../../../shared/services/toast-service'; import { AdminLayout } from '../../shared/layouts/AdminLayout/AdminLayout'; import { @@ -35,13 +34,15 @@ import { import { useGetProfileById } from '../hooks/use-get-profile-by-id'; import { USER_PATH } from '../user.const'; -type UserEditPageProps = DefaultSecureRouteProps<{ id: string }>; - -const UserEditPage: FC = ({ history, match }) => { +export const UserEditPage: FC = () => { const { tText } = useTranslation(); + const navigateFunc = useNavigate(); + const match = useMatch<'id', string>(USER_PATH.USER_EDIT); + + const profileId = match?.params.id; // Hooks - const { data: profile, isLoading } = useGetProfileById(match.params.id); + const { data: profile, isLoading } = useGetProfileById(profileId); const [isSaving, setIsSaving] = useState(false); const [profileErrors, setProfileErrors] = useState< Partial<{ [prop in keyof Avo.User.UpdateProfileValues]: string }> @@ -73,8 +74,8 @@ const UserEditPage: FC = ({ history, match }) => }, [profile]); const navigateBack = () => { - navigate(history, USER_PATH.USER_DETAIL, { - id: match.params.id, + navigate(navigateFunc, USER_PATH.USER_DETAIL, { + id: profileId, }); }; @@ -123,10 +124,7 @@ const UserEditPage: FC = ({ history, match }) => throw err; } - redirectToClientPage( - buildLink(USER_PATH.USER_DETAIL, { id: match.params.id }), - history - ); + redirectToClientPage(buildLink(USER_PATH.USER_DETAIL, { id: profileId }), navigateFunc); ToastService.success(tText('admin/users/views/user-edit___de-gebruiker-is-aangepast')); } catch (err) { @@ -156,14 +154,14 @@ const UserEditPage: FC = ({ history, match }) =>
- {!companyId && ( + {!companyId && !!profileId && ( setAvatar(urls[0])} assetType="PROFILE_AVATAR" allowMulti={false} allowedTypes={PHOTO_TYPES} - ownerId={match.params.id} + ownerId={profileId} /> )} {!!companyId && !!companyLogo && ( @@ -245,5 +243,3 @@ const UserEditPage: FC = ({ history, match }) => ); }; - -export default UserEditPage as FC; diff --git a/src/admin/users/views/UserOverviewPage.tsx b/src/admin/users/views/UserOverviewPage.tsx index 19d7b2dcb2..4b1b1df649 100644 --- a/src/admin/users/views/UserOverviewPage.tsx +++ b/src/admin/users/views/UserOverviewPage.tsx @@ -1,13 +1,9 @@ import { Flex, Spinner } from '@viaa/avo2-components'; -import { type Avo } from '@viaa/avo2-types'; import React, { type FC, lazy, Suspense } from 'react'; import { Helmet } from 'react-helmet'; -import { compose } from 'redux'; import { GENERATE_SITE_TITLE } from '../../../constants'; -import withUser, { type UserProps } from '../../../shared/hocs/withUser'; -import useTranslation from '../../../shared/hooks/useTranslation'; -import { withAdminCoreConfig } from '../../shared/hoc/with-admin-core-config'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { AdminLayout } from '../../shared/layouts/AdminLayout/AdminLayout'; import { AdminLayoutBody } from '../../shared/layouts/AdminLayout/AdminLayout.slots'; @@ -17,7 +13,7 @@ const UserOverview = lazy(() => })) ); -const UserOverviewPage: FC = ({ commonUser }) => { +export const UserOverviewPage: FC = () => { const { tText } = useTranslation(); return ( @@ -49,11 +45,9 @@ const UserOverviewPage: FC = ({ commonUser }) => { } > - + ); }; - -export default compose(withAdminCoreConfig, withUser)(UserOverviewPage) as FC; diff --git a/src/assignment/assignment.helper.tsx b/src/assignment/assignment.helper.tsx index b03151714a..570660992a 100644 --- a/src/assignment/assignment.helper.tsx +++ b/src/assignment/assignment.helper.tsx @@ -96,7 +96,7 @@ export function getAssignmentErrorObj(errorType: AssignmentRetrieveError): { } export function isUserAssignmentOwner( - commonUser: Pick | null, + commonUser: Pick | null | undefined, assignment: Partial ): boolean { if (!commonUser) { @@ -111,7 +111,7 @@ export function isUserAssignmentOwner( } export function isUserAssignmentContributor( - commonUser: Avo.User.CommonUser, + commonUser: Avo.User.CommonUser | undefined, assignment: Partial ): boolean { if (assignment.contributors) { diff --git a/src/assignment/assignment.routes.tsx b/src/assignment/assignment.routes.tsx deleted file mode 100644 index 420ab0d303..0000000000 --- a/src/assignment/assignment.routes.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import React, { type ReactNode } from 'react'; - -import SecuredRoute from '../authentication/components/SecuredRoute'; -import { APP_PATH } from '../constants'; - -import AssignmentDetailSwitcher from './views/AssignmentDetailSwitcher'; -import AssignmentEdit from './views/AssignmentEdit'; -import AssignmentPupilCollectionDetail from './views/AssignmentPupilCollectionDetail'; -import AssignmentResponseAdminEdit from './views/AssignmentResponseEdit/AssignmentResponseAdminEdit'; - -export const renderAssignmentRoutes = (): ReactNode[] => [ - , - , - , - , - , - , - , - , -]; diff --git a/src/assignment/assignment.service.ts b/src/assignment/assignment.service.ts index e7f4a7d1eb..206e732652 100644 --- a/src/assignment/assignment.service.ts +++ b/src/assignment/assignment.service.ts @@ -529,7 +529,7 @@ export class AssignmentService { // Fetch assignment responses for response overview page static async fetchAssignmentResponses( assignmentId: string, - commonUser: Avo.User.CommonUser | null, + commonUser: Avo.User.CommonUser | null | undefined, sortColumn: AssignmentTableColumns, sortOrder: Avo.Search.OrderDirection, tableColumnDataType: TableColumnDataType, diff --git a/src/assignment/components/AssignmentActions.tsx b/src/assignment/components/AssignmentActions.tsx index 370bb2f800..798ecf24b5 100644 --- a/src/assignment/components/AssignmentActions.tsx +++ b/src/assignment/components/AssignmentActions.tsx @@ -8,11 +8,14 @@ import { } from '@viaa/avo2-components'; import { type Avo, PermissionName } from '@viaa/avo2-types'; import { clsx } from 'clsx'; +import { useAtomValue } from 'jotai'; import { noop } from 'lodash-es'; import React, { type FC, useCallback, useMemo, useState } from 'react'; +import { commonUserAtom } from '../../authentication/authentication.store'; import { APP_PATH } from '../../constants'; -import ShareDropdown, { +import { + ShareDropdown, type ShareDropdownProps, } from '../../shared/components/ShareDropdown/ShareDropdown'; import { type ContributorInfoRight } from '../../shared/components/ShareWithColleagues/ShareWithColleagues.types'; @@ -20,15 +23,14 @@ import { type ShareWithPupilsProps } from '../../shared/components/ShareWithPupi import { transformContributorsToSimpleContributors } from '../../shared/helpers/contributors'; import { isMobileWidth } from '../../shared/helpers/media-query'; import { renderMobileDesktop } from '../../shared/helpers/renderMobileDesktop'; -import withUser, { type UserProps } from '../../shared/hocs/withUser'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { onAddNewContributor, onDeleteContributor, onEditContributor, } from '../helpers/assignment-share-with-collegue-handlers'; -import DeleteAssignmentButton, { type DeleteAssignmentButtonProps } from './DeleteAssignmentButton'; +import { DeleteAssignmentButton, type DeleteAssignmentButtonProps } from './DeleteAssignmentButton'; interface ShareProps extends ShareWithPupilsProps { contributors: Avo.Assignment.Contributor[]; @@ -54,10 +56,9 @@ interface AssignmentActionsProps { assignment?: Partial; } -const AssignmentActions: FC = ({ +export const AssignmentActions: FC = ({ isCreating, assignment, - commonUser, onDuplicate, overflow, preview, @@ -69,6 +70,7 @@ const AssignmentActions: FC = ({ view, }) => { const { tText } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); const [isOverflowDropdownOpen, setOverflowDropdownOpen] = useState(false); const renderViewButton = useCallback( @@ -350,5 +352,3 @@ const AssignmentActions: FC = ({ ] ); }; - -export default withUser(AssignmentActions) as FC; diff --git a/src/assignment/components/AssignmentAdminFormEditable.tsx b/src/assignment/components/AssignmentAdminFormEditable.tsx index 4272cfd131..0388c22d46 100644 --- a/src/assignment/components/AssignmentAdminFormEditable.tsx +++ b/src/assignment/components/AssignmentAdminFormEditable.tsx @@ -11,30 +11,31 @@ import { TextInput, } from '@viaa/avo2-components'; import { type Avo, PermissionName } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { isNil } from 'lodash-es'; import React, { type FC } from 'react'; import { ContentPicker } from '../../admin/shared/components/ContentPicker/ContentPicker'; import { type PickerItem } from '../../admin/shared/types'; +import { commonUserAtom } from '../../authentication/authentication.store'; import { PermissionService } from '../../authentication/helpers/permission-service'; -import ContainedInBundlesTable from '../../bundle/components/ContainedInBundlesTable'; +import { ContainedInBundlesTable } from '../../bundle/components/ContainedInBundlesTable'; import { type QualityLabel } from '../../collection/collection.types'; import { formatTimestamp, getFullName } from '../../shared/helpers/formatters'; -import withUser, { type UserProps } from '../../shared/hocs/withUser'; import { useGetQualityLabels } from '../../shared/hooks/useGetQualityLabels'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; interface AssignmentAdminFormEditableProps { assignment: Avo.Assignment.Assignment; setAssignment: (newAssignment: Avo.Assignment.Assignment) => void; } -const AssignmentAdminFormEditable: FC = ({ +export const AssignmentAdminFormEditable: FC = ({ assignment, setAssignment, - commonUser, }) => { const { tText } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); const { data: allQualityLabels, isLoading } = useGetQualityLabels(); const owner: PickerItem | undefined = assignment.profile ? { @@ -238,5 +239,3 @@ const AssignmentAdminFormEditable: FC ); }; - -export default withUser(AssignmentAdminFormEditable) as FC; diff --git a/src/assignment/components/AssignmentConfirmSave.tsx b/src/assignment/components/AssignmentConfirmSave.tsx index 71c7280301..8a1fce91f1 100644 --- a/src/assignment/components/AssignmentConfirmSave.tsx +++ b/src/assignment/components/AssignmentConfirmSave.tsx @@ -6,7 +6,7 @@ import { ConfirmModal, type ConfirmModalProps, } from '../../shared/components/ConfirmModal/ConfirmModal'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; type AssignmentConfirmSaveProps = DefaultProps & { hasBlocks?: boolean; @@ -14,7 +14,7 @@ type AssignmentConfirmSaveProps = DefaultProps & { modal?: Partial; }; -const AssignmentConfirmSave: FC = ({ +export const AssignmentConfirmSave: FC = ({ hasBlocks, hasResponses, modal, @@ -48,5 +48,3 @@ const AssignmentConfirmSave: FC = ({ /> ); }; - -export default AssignmentConfirmSave; diff --git a/src/assignment/components/AssignmentDeadline.tsx b/src/assignment/components/AssignmentDeadline.tsx index 4aa196197a..5b470f0914 100644 --- a/src/assignment/components/AssignmentDeadline.tsx +++ b/src/assignment/components/AssignmentDeadline.tsx @@ -14,7 +14,7 @@ interface AssignmentDeadlineProps { deadline?: string | null | Date; } -const AssignmentDeadline: FC = ({ deadline }) => { +export const AssignmentDeadline: FC = ({ deadline }) => { const config: [DeadlineIndicatorColors, DeadlineIndicatorShapes] | undefined = useMemo(() => { if (!deadline) return undefined; @@ -47,5 +47,3 @@ const AssignmentDeadline: FC = ({ deadline }) => { ); }; - -export default AssignmentDeadline; diff --git a/src/assignment/components/AssignmentDetailsFormEditable.tsx b/src/assignment/components/AssignmentDetailsFormEditable.tsx index fd567b2f04..7861dcf421 100644 --- a/src/assignment/components/AssignmentDetailsFormEditable.tsx +++ b/src/assignment/components/AssignmentDetailsFormEditable.tsx @@ -14,18 +14,18 @@ import { } from '@viaa/avo2-components'; import { clsx } from 'clsx'; import { isAfter, isPast } from 'date-fns'; +import { useAtomValue } from 'jotai'; import React, { type FC, useCallback } from 'react'; -import { compose } from 'redux'; -import withUser, { type UserProps } from '../../shared/hocs/withUser'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { commonUserAtom } from '../../authentication/authentication.store'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { ToastService } from '../../shared/services/toast-service'; import { endOfAcademicYear } from '../helpers/academic-year'; import { isDeadlineBeforeAvailableAt } from '../helpers/is-deadline-before-available-at'; import { mergeWithOtherLabels } from '../helpers/merge-with-other-labels'; import { type AssignmentFields } from '../hooks/assignment-form'; -import AssignmentLabels from './AssignmentLabels'; +import { AssignmentLabels } from './AssignmentLabels'; import './AssignmentDetailsForm.scss'; @@ -43,10 +43,11 @@ interface AssignmentDetailsFormEditableProps { onFocus?: () => void; } -const AssignmentDetailsFormEditable: FC< - AssignmentDetailsFormEditableProps & UserProps & DefaultProps -> = ({ assignment, setAssignment, className, style, commonUser, onFocus }) => { +export const AssignmentDetailsFormEditable: FC< + AssignmentDetailsFormEditableProps & DefaultProps +> = ({ assignment, setAssignment, className, style, onFocus }) => { const { tText, tHtml } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); const getId = useCallback( (key: string | number) => `${assignment.id}--${key}`, @@ -259,7 +260,3 @@ const AssignmentDetailsFormEditable: FC< ); }; - -export default compose(withUser)( - AssignmentDetailsFormEditable -) as FC; diff --git a/src/assignment/components/AssignmentDetailsFormReadonly.tsx b/src/assignment/components/AssignmentDetailsFormReadonly.tsx index f9b5b5304d..e379cc1a0c 100644 --- a/src/assignment/components/AssignmentDetailsFormReadonly.tsx +++ b/src/assignment/components/AssignmentDetailsFormReadonly.tsx @@ -4,7 +4,7 @@ import { clsx } from 'clsx'; import React, { type FC } from 'react'; import { formatTimestamp } from '../../shared/helpers/formatters'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import './AssignmentDetailsForm.scss'; @@ -12,11 +12,9 @@ interface AssignmentDetailsFormReadonlyProps { assignment: Avo.Assignment.Assignment; } -const AssignmentDetailsFormReadonly: FC = ({ - assignment, - className, - style, -}) => { +export const AssignmentDetailsFormReadonly: FC< + AssignmentDetailsFormReadonlyProps & DefaultProps +> = ({ assignment, className, style }) => { const { tText } = useTranslation(); return ( @@ -71,5 +69,3 @@ const AssignmentDetailsFormReadonly: FC ); }; - -export default AssignmentDetailsFormReadonly; diff --git a/src/assignment/components/AssignmentHeading.tsx b/src/assignment/components/AssignmentHeading.tsx index d772f6da62..77501c172e 100644 --- a/src/assignment/components/AssignmentHeading.tsx +++ b/src/assignment/components/AssignmentHeading.tsx @@ -12,7 +12,7 @@ import { import { clsx } from 'clsx'; import React, { type FC, type ReactNode, useEffect, useState } from 'react'; -import InteractiveTour from '../../shared/components/InteractiveTour/InteractiveTour'; +import { InteractiveTour } from '../../shared/components/InteractiveTour/InteractiveTour'; interface AssignmentHeadingProps { actions?: ReactNode; @@ -23,7 +23,7 @@ interface AssignmentHeadingProps { tour?: ReactNode | null; } -const AssignmentHeading: FC = ({ +export const AssignmentHeading: FC = ({ actions, back, info, @@ -110,5 +110,3 @@ const AssignmentHeading: FC = ({ ); }; - -export default AssignmentHeading; diff --git a/src/assignment/components/AssignmentLabels.tsx b/src/assignment/components/AssignmentLabels.tsx index cb5a94ba98..5e14f64733 100644 --- a/src/assignment/components/AssignmentLabels.tsx +++ b/src/assignment/components/AssignmentLabels.tsx @@ -9,17 +9,18 @@ import { type TagOption, } from '@viaa/avo2-components'; import { type Avo } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { cloneDeep, get } from 'lodash-es'; import React, { type FC, type MouseEvent, useCallback, useEffect, useState } from 'react'; +import { commonUserAtom } from '../../authentication/authentication.store'; import { ColorSelect } from '../../shared/components/ColorSelect/ColorSelect'; import { type Lookup_Enum_Colors_Enum } from '../../shared/generated/graphql-db-types'; -import withUser, { type UserProps } from '../../shared/hocs/withUser'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { AssignmentLabelsService } from '../../shared/services/assignment-labels-service'; import { ToastService } from '../../shared/services/toast-service'; -import ManageAssignmentLabels from './modals/ManageAssignmentLabels'; +import { ManageAssignmentLabels } from './modals/ManageAssignmentLabels'; import './AssignmentLabels.scss'; @@ -34,15 +35,16 @@ type AssignmentLabelsProps = { type?: Avo.Assignment.LabelType; }; -const AssignmentLabels: FC = ({ +export const AssignmentLabels: FC = ({ id, labels, - commonUser, onChange, type = 'LABEL', ...props }) => { const { tText, tHtml } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); + const dictionary = { placeholder: tText('assignment/views/assignment-edit___voeg-een-vak-of-project-toe'), empty: tText('assignment/views/assignment-edit___geen-vakken-of-projecten-beschikbaar'), @@ -178,5 +180,3 @@ const AssignmentLabels: FC = ({ ); }; - -export default withUser(AssignmentLabels) as FC; diff --git a/src/assignment/components/AssignmentMetaDataFormEditable.tsx b/src/assignment/components/AssignmentMetaDataFormEditable.tsx index 5534fa1057..a4ab52a410 100644 --- a/src/assignment/components/AssignmentMetaDataFormEditable.tsx +++ b/src/assignment/components/AssignmentMetaDataFormEditable.tsx @@ -14,13 +14,13 @@ import { type Avo } from '@viaa/avo2-types'; import { intersection } from 'lodash-es'; import React, { type FC, useState } from 'react'; -import LomFieldsInput from '../../shared/components/LomFieldsInput/LomFieldsInput'; -import ShortDescriptionField from '../../shared/components/ShortDescriptionField/ShortDescriptionField'; -import ThumbnailStillsModal from '../../shared/components/ThumbnailStillsModal/ThumbnailStillsModal'; +import { LomFieldsInput } from '../../shared/components/LomFieldsInput/LomFieldsInput'; +import { ShortDescriptionField } from '../../shared/components/ShortDescriptionField/ShortDescriptionField'; +import { ThumbnailStillsModal } from '../../shared/components/ThumbnailStillsModal/ThumbnailStillsModal'; import { getBottomLoms } from '../../shared/helpers/get-bottom-loms'; import { EducationLevelType } from '../../shared/helpers/lom'; import { tHtml } from '../../shared/helpers/translate-html'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; type AssignmentMetaDataFormEditableProps = { assignment: Avo.Assignment.Assignment; @@ -28,7 +28,7 @@ type AssignmentMetaDataFormEditableProps = { onFocus?: () => void; }; -const AssignmentMetaDataFormEditable: FC = ({ +export const AssignmentMetaDataFormEditable: FC = ({ assignment, setAssignment, onFocus, @@ -182,5 +182,3 @@ const AssignmentMetaDataFormEditable: FC = ); }; - -export default AssignmentMetaDataFormEditable; diff --git a/src/assignment/components/AssignmentMetadata.tsx b/src/assignment/components/AssignmentMetadata.tsx index c311a3152e..25880b0b4d 100644 --- a/src/assignment/components/AssignmentMetadata.tsx +++ b/src/assignment/components/AssignmentMetadata.tsx @@ -3,7 +3,7 @@ import { type Avo } from '@viaa/avo2-types'; import React, { type FC } from 'react'; import { formatTimestamp } from '../../shared/helpers/formatters'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import './AssignmentMetadata.scss'; @@ -13,7 +13,7 @@ type AssignmentMetadataProps = { who: 'teacher' | 'pupil'; }; -const AssignmentMetadata: FC = ({ +export const AssignmentMetadata: FC = ({ assignment, assignmentResponse, who, @@ -64,5 +64,3 @@ const AssignmentMetadata: FC = ({ ); }; - -export default AssignmentMetadata; diff --git a/src/assignment/components/AssignmentPupilPreview.tsx b/src/assignment/components/AssignmentPupilPreview.tsx index a0cafd7252..0a83e76fd9 100644 --- a/src/assignment/components/AssignmentPupilPreview.tsx +++ b/src/assignment/components/AssignmentPupilPreview.tsx @@ -1,14 +1,15 @@ import { Button, IconName } from '@viaa/avo2-components'; import { type Avo } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { noop } from 'lodash-es'; import React, { type Dispatch, type FC, type SetStateAction, useMemo, useState } from 'react'; -import AlertBar from '../../shared/components/AlertBar/AlertBar'; +import { commonUserAtom } from '../../authentication/authentication.store'; +import { AlertBar } from '../../shared/components/AlertBar/AlertBar'; import { EducationLevelId } from '../../shared/helpers/lom'; import { isMobileWidth } from '../../shared/helpers/media-query'; -import withUser, { type UserProps } from '../../shared/hocs/withUser'; -import useTranslation from '../../shared/hooks/useTranslation'; -import AssignmentResponseEdit from '../views/AssignmentResponseEdit/AssignmentResponseEdit'; +import { useTranslation } from '../../shared/hooks/useTranslation'; +import { AssignmentResponseEdit } from '../views/AssignmentResponseEdit/AssignmentResponseEdit'; type AssignmentPupilPreviewProps = { assignment: Partial; @@ -16,13 +17,13 @@ type AssignmentPupilPreviewProps = { onClose: () => void; }; -const AssignmentPupilPreview: FC = ({ +export const AssignmentPupilPreview: FC = ({ assignment, isPreview = false, onClose, - user, }) => { const { tText, tHtml } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); const [assignmentResponse, setAssignmentResponse] = useState({ collection_title: '', pupil_collection_blocks: [], @@ -31,7 +32,7 @@ const AssignmentPupilPreview: FC = ({ owner: { full_name: tText('assignment/components/assignment-pupil-preview___naam-leerling'), }, - owner_profile_id: user?.profile?.id, + owner_profile_id: commonUser?.profileId, id: '///fake-assignment-response-id', created_at: new Date().toISOString(), updated_at: new Date().toISOString(), @@ -104,5 +105,3 @@ const AssignmentPupilPreview: FC = ({ ); }; - -export default withUser(AssignmentPupilPreview) as FC; diff --git a/src/assignment/components/AssignmentTeacherTabs.tsx b/src/assignment/components/AssignmentTeacherTabs.tsx index 23fc5a67e8..fa2d38dd67 100644 --- a/src/assignment/components/AssignmentTeacherTabs.tsx +++ b/src/assignment/components/AssignmentTeacherTabs.tsx @@ -1,14 +1,13 @@ import { IconName, Pill, PillVariants, type TabProps, Tabs } from '@viaa/avo2-components'; import { PermissionName } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import React, { type FC, useMemo } from 'react'; -import { type RouteComponentProps } from 'react-router'; -import { withRouter } from 'react-router-dom'; -import { compose } from 'redux'; +import { useLocation } from 'react-router-dom'; +import { commonUserAtom } from '../../authentication/authentication.store'; import { PermissionService } from '../../authentication/helpers/permission-service'; import { APP_PATH } from '../../constants'; -import withUser, { type UserProps } from '../../shared/hocs/withUser'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { ASSIGNMENT_CREATE_UPDATE_TABS } from '../assignment.const'; interface AssignmentTeacherTabsProps { @@ -18,15 +17,15 @@ interface AssignmentTeacherTabsProps { isManaged: boolean; } -const AssignmentTeacherTabs: FC = ({ - history, - commonUser, +export const AssignmentTeacherTabs: FC = ({ activeTab, onTabChange, clicksCount, isManaged, }) => { const { tText } = useTranslation(); + const location = useLocation(); + const commonUser = useAtomValue(commonUserAtom); const showAdminTab: boolean = PermissionService.hasAtLeastOnePerm(commonUser, [ PermissionName.EDIT_ASSIGNMENT_QUALITY_LABELS, @@ -52,7 +51,7 @@ const AssignmentTeacherTabs: FC ); }; - -export default compose( - withRouter, - withUser -)(AssignmentTeacherTabs) as FC; diff --git a/src/assignment/components/AssignmentTitle.tsx b/src/assignment/components/AssignmentTitle.tsx index a7686fc684..d55114c7c8 100644 --- a/src/assignment/components/AssignmentTitle.tsx +++ b/src/assignment/components/AssignmentTitle.tsx @@ -3,7 +3,7 @@ import { FormControl } from '@meemoo/react-components'; import { ContentInput, Flex, Icon, IconName } from '@viaa/avo2-components'; import React, { type FC, useState } from 'react'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { MAX_TITLE_LENGTH } from '../assignment.const'; type AssignmentTitleProps = { @@ -13,7 +13,7 @@ type AssignmentTitleProps = { onFocus?: () => void; }; -const AssignmentTitle: FC = ({ error, value, onChange, onFocus }) => { +export const AssignmentTitle: FC = ({ error, value, onChange, onFocus }) => { const { tText } = useTranslation(); const [isActive, setIsActive] = useState(false); const [titleTemp, setTitleTemp] = useState(value); @@ -54,5 +54,3 @@ const AssignmentTitle: FC = ({ error, value, onChange, onF ); }; - -export default AssignmentTitle; diff --git a/src/assignment/components/DeleteAssignmentButton.tsx b/src/assignment/components/DeleteAssignmentButton.tsx index f41b0ee84d..42ca4be202 100644 --- a/src/assignment/components/DeleteAssignmentButton.tsx +++ b/src/assignment/components/DeleteAssignmentButton.tsx @@ -1,32 +1,31 @@ import { Button, type ButtonProps, type DefaultProps, IconName } from '@viaa/avo2-components'; import { type Avo, PermissionName } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import React, { type FC, useState } from 'react'; -import { compose } from 'redux'; +import { commonUserAtom } from '../../authentication/authentication.store'; import { PermissionService } from '../../authentication/helpers/permission-service'; import { ConfirmModal, type ConfirmModalProps, } from '../../shared/components/ConfirmModal/ConfirmModal'; -import withUser, { type UserProps } from '../../shared/hocs/withUser'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { ToastService } from '../../shared/services/toast-service'; import { deleteAssignment, deleteAssignmentWarning } from '../helpers/delete-assignment'; -export type DeleteAssignmentButtonProps = DefaultProps & - Partial & { - assignment?: Avo.Assignment.Assignment; - button?: Partial; - modal?: Partial; - }; +export type DeleteAssignmentButtonProps = DefaultProps & { + assignment?: Avo.Assignment.Assignment; + button?: Partial; + modal?: Partial; +}; -const DeleteAssignmentButton: FC = ({ +export const DeleteAssignmentButton: FC = ({ assignment, button, modal, - commonUser, }) => { const { tText } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); const [isOpen, setOpen] = useState(false); const canDeleteAnyAssignments = PermissionService.hasPerm( @@ -95,5 +94,3 @@ const DeleteAssignmentButton: FC = ({ ); }; - -export default compose(withUser)(DeleteAssignmentButton) as FC; diff --git a/src/assignment/components/PupilCollectionForTeacherPreview.tsx b/src/assignment/components/PupilCollectionForTeacherPreview.tsx index 6f48a3f3c9..698ed30e0a 100644 --- a/src/assignment/components/PupilCollectionForTeacherPreview.tsx +++ b/src/assignment/components/PupilCollectionForTeacherPreview.tsx @@ -3,12 +3,12 @@ import { Button, Container, IconName } from '@viaa/avo2-components'; import { type Avo } from '@viaa/avo2-types'; import React, { type FC, type ReactNode } from 'react'; -import AlertBar from '../../shared/components/AlertBar/AlertBar'; -import BlockList from '../../shared/components/BlockList/BlockList'; +import { AlertBar } from '../../shared/components/AlertBar/AlertBar'; +import { BlockList } from '../../shared/components/BlockList/BlockList'; import { isMobileWidth } from '../../shared/helpers/media-query'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; -import AssignmentHeading from './AssignmentHeading'; +import { AssignmentHeading } from './AssignmentHeading'; type PupilCollectionForTeacherPreviewProps = { onClose: () => void; diff --git a/src/assignment/components/blocks/AssignmentBlockEditItem.tsx b/src/assignment/components/blocks/AssignmentBlockEditItem.tsx index bbec684e0e..7d1d4c1dad 100644 --- a/src/assignment/components/blocks/AssignmentBlockEditItem.tsx +++ b/src/assignment/components/blocks/AssignmentBlockEditItem.tsx @@ -5,12 +5,12 @@ import React, { type FC, type ReactNode } from 'react'; import { type FilterState } from '../../../search/search.types'; import { ItemMetadata } from '../../../shared/components/BlockItemMetadata/ItemMetadata'; import { CustomiseItemForm } from '../../../shared/components/CustomiseItemForm'; -import FlowPlayerWrapper from '../../../shared/components/FlowPlayerWrapper/FlowPlayerWrapper'; +import { FlowPlayerWrapper } from '../../../shared/components/FlowPlayerWrapper/FlowPlayerWrapper'; import { RICH_TEXT_EDITOR_OPTIONS_AUTHOR } from '../../../shared/components/RichTextEditorWrapper/RichTextEditor.consts'; import { getFlowPlayerPoster } from '../../../shared/helpers/get-poster'; import { isRichTextEmpty } from '../../../shared/helpers/is-rich-text-empty'; import { useCutModal } from '../../../shared/hooks/use-cut-modal'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { VideoStillService } from '../../../shared/services/video-stills-service'; import { type EditableAssignmentBlock, type EditBlockProps } from '../../assignment.types'; import { diff --git a/src/assignment/components/blocks/AssignmentBlockEditSearch.tsx b/src/assignment/components/blocks/AssignmentBlockEditSearch.tsx index e6da5cbfe0..1494f96f00 100644 --- a/src/assignment/components/blocks/AssignmentBlockEditSearch.tsx +++ b/src/assignment/components/blocks/AssignmentBlockEditSearch.tsx @@ -3,7 +3,7 @@ import React, { type FC } from 'react'; import { RICH_TEXT_EDITOR_OPTIONS_AUTHOR } from '../../../shared/components/RichTextEditorWrapper/RichTextEditor.consts'; import { TitleDescriptionForm } from '../../../shared/components/TitleDescriptionForm/TitleDescriptionForm'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { AssignmentBlockType, type EditBlockProps } from '../../assignment.types'; import { AssignmentBlockToggle } from '../AssignmentBlockToggle'; diff --git a/src/assignment/components/blocks/AssignmentBlockEditText.tsx b/src/assignment/components/blocks/AssignmentBlockEditText.tsx index 0686487e16..4a4ac80fe7 100644 --- a/src/assignment/components/blocks/AssignmentBlockEditText.tsx +++ b/src/assignment/components/blocks/AssignmentBlockEditText.tsx @@ -3,7 +3,7 @@ import React, { type FC } from 'react'; import { RICH_TEXT_EDITOR_OPTIONS_AUTHOR } from '../../../shared/components/RichTextEditorWrapper/RichTextEditor.consts'; import { TitleDescriptionForm } from '../../../shared/components/TitleDescriptionForm/TitleDescriptionForm'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { type EditBlockProps } from '../../assignment.types'; export const AssignmentBlockEditText: FC = ({ block, setBlock, onFocus }) => { diff --git a/src/assignment/components/modals/ManageAssignmentLabels.tsx b/src/assignment/components/modals/ManageAssignmentLabels.tsx index 3c6c2c723f..5e2cd1c11e 100644 --- a/src/assignment/components/modals/ManageAssignmentLabels.tsx +++ b/src/assignment/components/modals/ManageAssignmentLabels.tsx @@ -16,16 +16,17 @@ import { } from '@viaa/avo2-components'; import { type Avo } from '@viaa/avo2-types'; import { clsx } from 'clsx'; +import { useAtomValue } from 'jotai'; import { compact, intersection, sortBy, without } from 'lodash-es'; import React, { type FC, useCallback, useEffect, useState } from 'react'; +import { commonUserAtom } from '../../../authentication/authentication.store'; import { ColorSelect } from '../../../shared/components/ColorSelect/ColorSelect'; import { type Lookup_Enum_Colors_Enum } from '../../../shared/generated/graphql-db-types'; import { CustomError } from '../../../shared/helpers/custom-error'; import { ACTIONS_TABLE_COLUMN_ID } from '../../../shared/helpers/table-column-list-to-csv-column-list'; import { generateRandomId } from '../../../shared/helpers/uuid'; -import withUser, { type UserProps } from '../../../shared/hocs/withUser'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { AssignmentLabelsService } from '../../../shared/services/assignment-labels-service'; import { ToastService } from '../../../shared/services/toast-service'; import { MAX_LABEL_LENGTH } from '../../assignment.const'; @@ -41,13 +42,13 @@ export interface ManageAssignmentLabelsProps { type?: Avo.Assignment.LabelType; } -const ManageAssignmentLabels: FC = ({ +export const ManageAssignmentLabels: FC = ({ isOpen, onClose, type, - commonUser, }) => { const { tText, tHtml } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); const [assignmentLabels, setAssignmentLabels] = useState([]); const [initialAssignmentLabels, setInitialAssignmentLabels] = useState( @@ -78,7 +79,7 @@ const ManageAssignmentLabels: FC = ({ ) ); } - }, [commonUser, setAssignmentLabels, tText, type, tHtml]); + }, [profileId, type, commonUser, tHtml]); const fetchAssignmentColors = useCallback(async () => { try { @@ -352,5 +353,3 @@ const ManageAssignmentLabels: FC = ({ ); }; - -export default withUser(ManageAssignmentLabels) as FC; diff --git a/src/assignment/helpers/duplicate-assignment.ts b/src/assignment/helpers/duplicate-assignment.ts index 7165978165..5615f9462c 100644 --- a/src/assignment/helpers/duplicate-assignment.ts +++ b/src/assignment/helpers/duplicate-assignment.ts @@ -7,7 +7,7 @@ import { AssignmentService } from '../assignment.service'; export async function duplicateAssignment( assignment: Avo.Assignment.Assignment | null | undefined, - commonUser: Avo.User.CommonUser + commonUser?: Avo.User.CommonUser ): Promise { try { if (!assignment) { diff --git a/src/assignment/hooks/assignment-content-modals.tsx b/src/assignment/hooks/assignment-content-modals.tsx index a9fef26313..ec7ce62eac 100644 --- a/src/assignment/hooks/assignment-content-modals.tsx +++ b/src/assignment/hooks/assignment-content-modals.tsx @@ -4,25 +4,26 @@ import React, { useState } from 'react'; import { ItemsService } from '../../admin/items/items.service'; import { CollectionService } from '../../collection/collection.service'; import { CollectionOrBundle } from '../../collection/collection.types'; -import CutFragmentForAssignmentModal from '../../item/components/modals/CutFragmentForAssignmentModal'; +import { CutFragmentForAssignmentModal } from '../../item/components/modals/CutFragmentForAssignmentModal'; import { type ItemTrimInfo } from '../../item/item.types'; import { type SingleEntityModal, useSingleEntityModal, } from '../../shared/hooks/useSingleEntityModal'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { ToastService } from '../../shared/services/toast-service'; import { VideoStillService } from '../../shared/services/video-stills-service'; import { type Positioned } from '../../shared/types'; import { NEW_ASSIGNMENT_BLOCK_ID_PREFIX } from '../assignment.const'; import { AssignmentBlockType } from '../assignment.types'; import { insertMultipleAtPosition } from '../helpers/insert-at-position'; -import AddBlockModal, { type AddBlockModalProps } from '../modals/AddBlockModal'; -import AddBookmarkFragmentModal, { +import { AddBlockModal, type AddBlockModalProps } from '../modals/AddBlockModal'; +import { + AddBookmarkFragmentModal, type AddBookmarkFragmentModalProps, } from '../modals/AddBookmarkFragmentModal'; -import AddCollectionModal, { type AddCollectionModalProps } from '../modals/AddCollectionModal'; -import ConfirmSliceModal, { type ConfirmSliceModalProps } from '../modals/ConfirmSliceModal'; +import { AddCollectionModal, type AddCollectionModalProps } from '../modals/AddCollectionModal'; +import { ConfirmSliceModal, type ConfirmSliceModalProps } from '../modals/ConfirmSliceModal'; export function useBlockListModals( blocks: Avo.Core.BlockItemBase[], @@ -187,7 +188,10 @@ export function useBlockListModals( {...config?.addCollectionConfig} isOpen={isAddCollectionModalOpen} onClose={() => setIsAddCollectionModalOpen(false)} - addCollectionCallback={async (id, withDescription) => { + addCollectionCallback={async ( + collectionId: string, + withDescription: boolean + ) => { if (blockPosition === undefined) { return; } @@ -195,7 +199,7 @@ export function useBlockListModals( // fetch collection details const collection = await CollectionService.fetchCollectionOrBundleByIdOrInviteToken( - id, + collectionId, CollectionOrBundle.COLLECTION, undefined ); @@ -264,7 +268,7 @@ export function useBlockListModals( // Finish by triggering any configured callback const callback = config?.addCollectionConfig?.addCollectionCallback; - callback && callback(id, withDescription); + callback && callback(collectionId, withDescription); } }} /> diff --git a/src/assignment/hooks/assignment-pupil-tabs.tsx b/src/assignment/hooks/assignment-pupil-tabs.tsx index 74974f3d92..ca68d3731c 100644 --- a/src/assignment/hooks/assignment-pupil-tabs.tsx +++ b/src/assignment/hooks/assignment-pupil-tabs.tsx @@ -3,7 +3,7 @@ import { type Avo } from '@viaa/avo2-types'; import React, { useCallback, useMemo, useState } from 'react'; import { useAssignmentPastDeadline } from '../../shared/hooks/useAssignmentPastDeadline'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { ASSIGNMENT_RESPONSE_CREATE_UPDATE_TABS } from '../assignment.const'; import { AssignmentType } from '../assignment.types'; diff --git a/src/assignment/hooks/index.ts b/src/assignment/hooks/index.ts deleted file mode 100644 index a49e2f0d8e..0000000000 --- a/src/assignment/hooks/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { useAssignmentBlockChangeHandler } from './assignment-block-change-handler'; -export { useEditBlocks } from './use-edit-blocks'; -export { useBlockListModals } from './assignment-content-modals'; -export { useAssignmentForm } from './assignment-form'; -export { useAssignmentPupilTabs } from './assignment-pupil-tabs'; diff --git a/src/assignment/hooks/use-education-level-modal.tsx b/src/assignment/hooks/use-education-level-modal.tsx index 2a10d68804..f64c61a42f 100644 --- a/src/assignment/hooks/use-education-level-modal.tsx +++ b/src/assignment/hooks/use-education-level-modal.tsx @@ -5,7 +5,7 @@ import { isUserSecondaryElementary } from '../../shared/helpers/is-user'; import { isUserAssignmentOwner } from '../assignment.helper'; export function useEducationLevelModal( - commonUser: Avo.User.CommonUser | null, + commonUser: Avo.User.CommonUser | null | undefined, assignment: Partial | undefined, assignmentLoading = false ): [boolean, Dispatch>] { diff --git a/src/assignment/hooks/useGetKlascementAssignmentPublishInfo.tsx b/src/assignment/hooks/useGetKlascementAssignmentPublishInfo.tsx index 8c778efe63..f87a0ec28f 100644 --- a/src/assignment/hooks/useGetKlascementAssignmentPublishInfo.tsx +++ b/src/assignment/hooks/useGetKlascementAssignmentPublishInfo.tsx @@ -2,7 +2,10 @@ import { useQuery, type UseQueryResult } from '@tanstack/react-query'; import { QUERY_KEYS } from '../../shared/constants/query-keys'; import { tHtml } from '../../shared/helpers/translate-html'; -import { type KlascementAssignmentPublishInfo, KlascementService, } from '../../shared/services/klascement-service'; +import { + type KlascementAssignmentPublishInfo, + KlascementService, +} from '../../shared/services/klascement-service'; export const useGetKlascementAssignmentPublishInfo = ( assignmentId: string, diff --git a/src/assignment/modals/AddBlockModal.tsx b/src/assignment/modals/AddBlockModal.tsx index f0156cb0c0..469327ac58 100644 --- a/src/assignment/modals/AddBlockModal.tsx +++ b/src/assignment/modals/AddBlockModal.tsx @@ -16,7 +16,7 @@ import { BLOCK_TYPE_TO_ICON_NAME, BlockType, } from '../../shared/components/BlockList/BlockIconWrapper/BlockIconWrapper.consts'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { AssignmentBlockType } from '../assignment.types'; import './AddBlockModal.scss'; @@ -40,7 +40,7 @@ export interface AddBlockModalProps extends Pick void; } -const AddBlockModal: FC = ({ blocks, isOpen, onClose, onConfirm }) => { +export const AddBlockModal: FC = ({ blocks, isOpen, onClose, onConfirm }) => { const { tHtml } = useTranslation(); const disableSearchBlock = !!blocks.find( @@ -144,5 +144,3 @@ const AddBlockModal: FC = ({ blocks, isOpen, onClose, onConf ); }; - -export default AddBlockModal; diff --git a/src/assignment/modals/AddBookmarkFragmentModal.tsx b/src/assignment/modals/AddBookmarkFragmentModal.tsx index 2d0c645cb8..a5e9dd08e5 100644 --- a/src/assignment/modals/AddBookmarkFragmentModal.tsx +++ b/src/assignment/modals/AddBookmarkFragmentModal.tsx @@ -17,10 +17,11 @@ import { Thumbnail, } from '@viaa/avo2-components'; import { type Avo } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { noop } from 'lodash-es'; import React, { type FC, useCallback, useEffect, useMemo, useState } from 'react'; -import { compose } from 'redux'; +import { commonUserAtom } from '../../authentication/authentication.store'; import { LoadingErrorLoadedComponent, type LoadingInfo, @@ -31,9 +32,8 @@ import { getOrderObject } from '../../shared/helpers/generate-order-gql-query'; import { isMobileWidth } from '../../shared/helpers/media-query'; import { tText } from '../../shared/helpers/translate-text'; import { truncateTableValue } from '../../shared/helpers/truncate'; -import withUser from '../../shared/hocs/withUser'; import { useTableSort } from '../../shared/hooks/useTableSort'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { BookmarksViewsPlaysService } from '../../shared/services/bookmarks-views-plays-service'; import { type BookmarkInfo } from '../../shared/services/bookmarks-views-plays-service/bookmarks-views-plays-service.types'; import { ToastService } from '../../shared/services/toast-service'; @@ -88,14 +88,12 @@ const TABLE_COLUMN_TO_DATABASE_ORDER_OBJECT: Partial<{ }; export interface AddBookmarkFragmentModalProps { - commonUser?: Avo.User.CommonUser; isOpen: boolean; onClose?: () => void; addFragmentCallback?: (fragmentId: string) => void; } -const AddBookmarkFragmentModal: FC = ({ - commonUser, +export const AddBookmarkFragmentModal: FC = ({ isOpen, onClose, addFragmentCallback = () => { @@ -103,6 +101,7 @@ const AddBookmarkFragmentModal: FC = ({ }, }) => { const { tText, tHtml } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); const [loadingInfo, setLoadingInfo] = useState({ state: 'loading' }); const [bookmarks, setBookmarks] = useState(null); @@ -307,5 +306,3 @@ const AddBookmarkFragmentModal: FC = ({ ); }; - -export default compose(withUser)(AddBookmarkFragmentModal) as FC; diff --git a/src/assignment/modals/AddCollectionModal.tsx b/src/assignment/modals/AddCollectionModal.tsx index 9910387b1d..631062c79c 100644 --- a/src/assignment/modals/AddCollectionModal.tsx +++ b/src/assignment/modals/AddCollectionModal.tsx @@ -25,10 +25,11 @@ import { ToolbarRight, } from '@viaa/avo2-components'; import { type Avo } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { noop } from 'lodash-es'; import React, { type FC, useCallback, useEffect, useMemo, useState } from 'react'; -import { compose } from 'redux'; +import { commonUserAtom } from '../../authentication/authentication.store'; import { CollectionService } from '../../collection/collection.service'; import { type Collection, ContentTypeNumber } from '../../collection/collection.types'; import { OrderDirection } from '../../search/search.const'; @@ -41,9 +42,8 @@ import { formatDate, formatTimestamp } from '../../shared/helpers/formatters'; import { getOrderObject } from '../../shared/helpers/generate-order-gql-query'; import { tText } from '../../shared/helpers/translate-text'; import { truncateTableValue } from '../../shared/helpers/truncate'; -import withUser, { type UserProps } from '../../shared/hocs/withUser'; import { useTableSort } from '../../shared/hooks/useTableSort'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { ToastService } from '../../shared/services/toast-service'; import { TableColumnDataType } from '../../shared/types/table-column-data-type'; import { type AssignmentTableColumns } from '../assignment.types'; @@ -100,7 +100,7 @@ const BOOKMARKED_COLLECTION_TABLE_COLUMN_TO_DATABASE_ORDER_OBJECT: Partial<{ }), }; -export type AddCollectionModalProps = Partial & { +export type AddCollectionModalProps = { isOpen: boolean; onClose?: () => void; addCollectionCallback?: (fragmentId: string, withDescription: boolean) => void; @@ -111,13 +111,13 @@ enum AddCollectionTab { bookmarkedCollections = 'bookmarkedcollections', } -const AddCollectionModal: FC = ({ - commonUser, +export const AddCollectionModal: FC = ({ isOpen, onClose = noop, addCollectionCallback, }) => { const { tText, tHtml } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); const [loadingInfo, setLoadingInfo] = useState({ state: 'loading' }); const [createWithDescription, setCreateWithDescription] = useState(false); @@ -425,5 +425,3 @@ const AddCollectionModal: FC = ({ ); }; - -export default compose(withUser)(AddCollectionModal) as FC; diff --git a/src/assignment/modals/ConfirmImportToAssignmentWithResponsesModal.tsx b/src/assignment/modals/ConfirmImportToAssignmentWithResponsesModal.tsx index e6a97a2990..870cde4e1a 100644 --- a/src/assignment/modals/ConfirmImportToAssignmentWithResponsesModal.tsx +++ b/src/assignment/modals/ConfirmImportToAssignmentWithResponsesModal.tsx @@ -23,7 +23,7 @@ interface ConfirmImportToAssignmentWithResponsesModalProps { }; } -const ConfirmImportToAssignmentWithResponsesModal: FC< +export const ConfirmImportToAssignmentWithResponsesModal: FC< ConfirmImportToAssignmentWithResponsesModalProps > = ({ isOpen, onClose, confirmCallback, translations }) => { const renderConfirmButtons = () => { @@ -74,5 +74,3 @@ const ConfirmImportToAssignmentWithResponsesModal: FC< ); }; - -export default ConfirmImportToAssignmentWithResponsesModal; diff --git a/src/assignment/modals/ConfirmSliceModal.tsx b/src/assignment/modals/ConfirmSliceModal.tsx index 9624539106..e068d609f7 100644 --- a/src/assignment/modals/ConfirmSliceModal.tsx +++ b/src/assignment/modals/ConfirmSliceModal.tsx @@ -13,7 +13,7 @@ import { type Avo } from '@viaa/avo2-types'; import React, { type FC } from 'react'; import { BLOCK_ITEM_LABELS } from '../../shared/components/BlockList/BlockList.consts'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { AssignmentBlockType } from '../assignment.types'; export interface ConfirmSliceModalProps extends Pick { @@ -23,7 +23,7 @@ export interface ConfirmSliceModalProps extends Pick void; } -const ConfirmSliceModal: FC = ({ +export const ConfirmSliceModal: FC = ({ responses = [], block, isPupilCollection, @@ -112,5 +112,3 @@ const ConfirmSliceModal: FC = ({ ); }; - -export default ConfirmSliceModal; diff --git a/src/assignment/modals/CreateAssignmentModal.tsx b/src/assignment/modals/CreateAssignmentModal.tsx index 7186c1fb05..6bfed058bf 100644 --- a/src/assignment/modals/CreateAssignmentModal.tsx +++ b/src/assignment/modals/CreateAssignmentModal.tsx @@ -14,7 +14,7 @@ import { import { noop } from 'lodash-es'; import React, { type FC, type ReactNode, useState } from 'react'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; interface CreateAssignmentModalProps { isOpen: boolean; @@ -27,7 +27,7 @@ interface CreateAssignmentModalProps { }; } -const CreateAssignmentModal: FC = ({ +export const CreateAssignmentModal: FC = ({ isOpen, onClose, createAssignmentCallback, @@ -98,5 +98,3 @@ const CreateAssignmentModal: FC = ({ ); }; - -export default CreateAssignmentModal; diff --git a/src/assignment/modals/DeleteAssignmentModal.tsx b/src/assignment/modals/DeleteAssignmentModal.tsx index 1a23be9d0b..6348b6c4b6 100644 --- a/src/assignment/modals/DeleteAssignmentModal.tsx +++ b/src/assignment/modals/DeleteAssignmentModal.tsx @@ -2,7 +2,7 @@ import { noop } from 'lodash-es'; import React, { type FC, type ReactNode } from 'react'; import { ConfirmModal } from '../../shared/components/ConfirmModal/ConfirmModal'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; interface DeleteAssignmentModalProps { isOpen: boolean; @@ -19,7 +19,7 @@ interface DeleteAssignmentModalProps { shouldDeleteSelfFromAssignment: boolean; } -const DeleteAssignmentModal: FC = ({ +export const DeleteAssignmentModal: FC = ({ isOpen, onClose = noop, deleteAssignmentCallback, @@ -122,5 +122,3 @@ const DeleteAssignmentModal: FC = ({ /> ); }; - -export default DeleteAssignmentModal; diff --git a/src/assignment/modals/ImportToAssignmentModal.tsx b/src/assignment/modals/ImportToAssignmentModal.tsx index d5d132a8da..155c7dbaed 100644 --- a/src/assignment/modals/ImportToAssignmentModal.tsx +++ b/src/assignment/modals/ImportToAssignmentModal.tsx @@ -17,10 +17,12 @@ import { Toggle, } from '@viaa/avo2-components'; import { type Avo } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { noop } from 'lodash-es'; import React, { type FC, type ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; import { Link } from 'react-router-dom'; +import { commonUserAtom } from '../../authentication/authentication.store'; import { APP_PATH } from '../../constants'; import { LoadingErrorLoadedComponent, @@ -31,9 +33,8 @@ import { CustomError } from '../../shared/helpers/custom-error'; import { formatDate, renderAvatar } from '../../shared/helpers/formatters'; import { isMobileWidth } from '../../shared/helpers/media-query'; import { truncateTableValue } from '../../shared/helpers/truncate'; -import withUser, { type UserProps } from '../../shared/hocs/withUser'; import { useTableSort } from '../../shared/hooks/useTableSort'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { ToastService } from '../../shared/services/toast-service'; import { TableColumnDataType } from '../../shared/types/table-column-data-type'; import { @@ -44,7 +45,7 @@ import { import { AssignmentHelper } from '../assignment.helper'; import { AssignmentService } from '../assignment.service'; import { type AssignmentTableColumns } from '../assignment.types'; -import AssignmentDeadline from '../components/AssignmentDeadline'; +import { AssignmentDeadline } from '../components/AssignmentDeadline'; import './AddItemsModals.scss'; @@ -60,8 +61,7 @@ interface ImportToAssignmentModalProps { }; } -const ImportToAssignmentModal: FC = ({ - commonUser, +export const ImportToAssignmentModal: FC = ({ isOpen, onClose, importToAssignmentCallback, @@ -69,6 +69,7 @@ const ImportToAssignmentModal: FC = ({ translations, }) => { const { tText, tHtml } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); const [loadingInfo, setLoadingInfo] = useState({ state: 'loading' }); const [createWithDescription, setCreateWithDescription] = useState(false); @@ -320,5 +321,3 @@ const ImportToAssignmentModal: FC = ({ ); }; - -export default withUser(ImportToAssignmentModal) as FC; diff --git a/src/assignment/modals/PublishAssignmentModal.tsx b/src/assignment/modals/PublishAssignmentModal.tsx index 7400d1201f..49296385c7 100644 --- a/src/assignment/modals/PublishAssignmentModal.tsx +++ b/src/assignment/modals/PublishAssignmentModal.tsx @@ -12,13 +12,14 @@ import { ToolbarRight, } from '@viaa/avo2-components'; import { type Avo } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import React, { type FC, type ReactNode, useEffect, useState } from 'react'; +import { commonUserAtom } from '../../authentication/authentication.store'; import type { ParentBundle } from '../../collection/collection.types'; import { APP_PATH } from '../../constants'; import { buildLink } from '../../shared/helpers/build-link'; -import withUser, { type UserProps } from '../../shared/hocs/withUser'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { trackEvents } from '../../shared/services/event-logging-service'; import { ToastService } from '../../shared/services/toast-service'; import { getValidationErrorsForPublishAssignment } from '../assignment.helper'; @@ -31,14 +32,14 @@ interface PublishAssignmentModalProps { parentBundles: ParentBundle[] | undefined; } -const PublishAssignmentModal: FC = ({ +export const PublishAssignmentModal: FC = ({ onClose, isOpen, assignment, parentBundles, - commonUser, }) => { const { tText, tHtml } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); const [validationErrors, setValidationErrors] = useState<(string | ReactNode)[]>([]); const [isAssignmentPublic, setIsAssignmentPublic] = useState(assignment.is_public); @@ -210,5 +211,3 @@ const PublishAssignmentModal: FC = ({ ); }; - -export default withUser(PublishAssignmentModal) as FC; diff --git a/src/assignment/views/AssignmentDetail.tsx b/src/assignment/views/AssignmentDetail.tsx index b5cb8ae612..7bc04c9b0d 100644 --- a/src/assignment/views/AssignmentDetail.tsx +++ b/src/assignment/views/AssignmentDetail.tsx @@ -25,36 +25,37 @@ import { TooltipTrigger, } from '@viaa/avo2-components'; import { type Avo, PermissionName } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { noop } from 'lodash-es'; import React, { type FC, type ReactText, useCallback, useEffect, useState } from 'react'; import { Helmet } from 'react-helmet'; -import { generatePath } from 'react-router'; +import { generatePath, useMatch, useNavigate } from 'react-router'; import { Link } from 'react-router-dom'; import { BooleanParam, StringParam, useQueryParam, useQueryParams } from 'use-query-params'; -import { type DefaultSecureRouteProps } from '../../authentication/components/SecuredRoute'; +import { commonUserAtom } from '../../authentication/authentication.store'; import { PermissionService } from '../../authentication/helpers/permission-service'; import { redirectToClientPage } from '../../authentication/helpers/redirects/redirect-to-client-page'; import { renderRelatedItems } from '../../collection/collection.helpers'; import { CollectionFragmentType, type Relation } from '../../collection/collection.types'; -import AddToBundleModal from '../../collection/components/modals/AddToBundleModal'; +import { AddToBundleModal } from '../../collection/components/modals/AddToBundleModal'; import { BundleSortProp, useGetCollectionsOrBundlesContainingFragment, } from '../../collection/hooks/useGetCollectionsOrBundlesContainingFragment'; import { QUERY_PARAM_SHOW_PUBLISH_MODAL } from '../../collection/views/CollectionDetail.const'; import { APP_PATH, GENERATE_SITE_TITLE } from '../../constants'; -import { ErrorNoAccess } from '../../error/components'; -import ErrorView, { type ErrorViewQueryParams } from '../../error/views/ErrorView'; +import { ErrorNoAccess } from '../../error/components/ErrorNoAccess'; +import { ErrorView, type ErrorViewQueryParams } from '../../error/views/ErrorView'; import { ALL_SEARCH_FILTERS, type SearchFilter } from '../../search/search.const'; -import BlockList from '../../shared/components/BlockList/BlockList'; -import CommonMetaData from '../../shared/components/CommonMetaData/CommonMetaData'; -import EditButton from '../../shared/components/EditButton/EditButton'; -import HeaderOwnerAndContributors from '../../shared/components/HeaderOwnerAndContributors/HeaderOwnerAndContributors'; -import InteractiveTour from '../../shared/components/InteractiveTour/InteractiveTour'; -import MoreOptionsDropdownWrapper from '../../shared/components/MoreOptionsDropdownWrapper/MoreOptionsDropdownWrapper'; -import ShareDropdown from '../../shared/components/ShareDropdown/ShareDropdown'; -import ShareModal from '../../shared/components/ShareModal/ShareModal'; +import { BlockList } from '../../shared/components/BlockList/BlockList'; +import { CommonMetadata } from '../../shared/components/CommonMetaData/CommonMetaData'; +import { EditButton } from '../../shared/components/EditButton/EditButton'; +import { HeaderOwnerAndContributors } from '../../shared/components/HeaderOwnerAndContributors/HeaderOwnerAndContributors'; +import { InteractiveTour } from '../../shared/components/InteractiveTour/InteractiveTour'; +import { MoreOptionsDropdownWrapper } from '../../shared/components/MoreOptionsDropdownWrapper/MoreOptionsDropdownWrapper'; +import { ShareDropdown } from '../../shared/components/ShareDropdown/ShareDropdown'; +import { ShareModal } from '../../shared/components/ShareModal/ShareModal'; import { ContributorInfoRight } from '../../shared/components/ShareWithColleagues/ShareWithColleagues.types'; import { type ShareWithPupilsProps } from '../../shared/components/ShareWithPupils/ShareWithPupils'; import { StickyBar } from '../../shared/components/StickyBar/StickyBar'; @@ -69,8 +70,7 @@ import { createDropdownMenuItem } from '../../shared/helpers/dropdown'; import { navigate } from '../../shared/helpers/link'; import { type EducationLevelId } from '../../shared/helpers/lom'; import { isMobileWidth } from '../../shared/helpers/media-query'; -import withUser, { type UserProps } from '../../shared/hocs/withUser'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { BookmarksViewsPlaysService, DEFAULT_BOOKMARK_VIEW_PLAY_COUNTS, @@ -99,8 +99,8 @@ import { deleteAssignment, deleteSelfFromAssignment } from '../helpers/delete-as import { duplicateAssignment } from '../helpers/duplicate-assignment'; import { toAssignmentDetail } from '../helpers/links'; import { useGetAssignmentsEditStatuses } from '../hooks/useGetAssignmentsEditStatuses'; -import DeleteAssignmentModal from '../modals/DeleteAssignmentModal'; -import PublishAssignmentModal from '../modals/PublishAssignmentModal'; +import { DeleteAssignmentModal } from '../modals/DeleteAssignmentModal'; +import { PublishAssignmentModal } from '../modals/PublishAssignmentModal'; type AssignmentDetailPermissions = Partial<{ canCreateAssignments: boolean; @@ -115,11 +115,15 @@ type AssignmentDetailProps = { enabledMetaData: SearchFilter[]; }; -const AssignmentDetail: FC< - AssignmentDetailProps & DefaultSecureRouteProps<{ id: string }> & UserProps -> = ({ match, commonUser, history, enabledMetaData = ALL_SEARCH_FILTERS }) => { +export const AssignmentDetail: FC = ({ + enabledMetaData = ALL_SEARCH_FILTERS, +}) => { const { tText, tHtml } = useTranslation(); - const assignmentId = match.params.id; + const navigateFunc = useNavigate(); + const commonUser = useAtomValue(commonUserAtom); + const match = useMatch<'id', string>(APP_PATH.ASSIGNMENT_DETAIL.route); + + const assignmentId = match?.params.id; // Data const [assignment, setAssignment] = useState(null); @@ -130,18 +134,18 @@ const AssignmentDetail: FC< const [bookmarkViewCounts, setBookmarkViewCounts] = useState( DEFAULT_BOOKMARK_VIEW_PLAY_COUNTS ); - const { data: editStatuses } = useGetAssignmentsEditStatuses([assignmentId], { - enabled: !!permissions?.canEditAssignments, + const { data: editStatuses } = useGetAssignmentsEditStatuses([assignmentId as string], { + enabled: !!assignmentId && !!permissions?.canEditAssignments, refetchInterval: EDIT_STATUS_REFETCH_TIME, refetchIntervalInBackground: true, }); const { data: bundlesContainingAssignment, refetch: refetchBundlesContainingAssignment } = useGetCollectionsOrBundlesContainingFragment( - assignmentId, + assignmentId as string, BundleSortProp.title, OrderDirection.asc, - { enabled: !!assignment } + { enabled: !!assignmentId && !!assignment } ); // Errors @@ -183,18 +187,19 @@ const AssignmentDetail: FC< const isBeingEdited = editStatuses && + assignmentId && !!editStatuses[assignmentId] && editStatuses[assignmentId]?.editingUserId !== commonUser?.profileId; const shareWithPupilsProps: ShareWithPupilsProps = { assignment: assignment || undefined, // Needs to be saved before you can share onContentLinkClicked: () => - navigate(history, APP_PATH.ASSIGNMENT_EDIT_TAB.route, { + navigate(navigateFunc, APP_PATH.ASSIGNMENT_EDIT_TAB.route, { id: assignmentId, tabId: ASSIGNMENT_CREATE_UPDATE_TABS.CONTENT, }), onDetailLinkClicked: () => - navigate(history, APP_PATH.ASSIGNMENT_EDIT_TAB.route, { + navigate(navigateFunc, APP_PATH.ASSIGNMENT_EDIT_TAB.route, { id: assignmentId, tabId: ASSIGNMENT_CREATE_UPDATE_TABS.DETAILS, }), @@ -237,7 +242,7 @@ const AssignmentDetail: FC< const getRelatedAssignments = useCallback(async () => { try { - if (isUuid(assignmentId)) { + if (!!assignmentId && isUuid(assignmentId)) { setRelatedAssignments( await getRelatedItems( assignmentId, @@ -264,6 +269,9 @@ const AssignmentDetail: FC< const fetchAssignment = useCallback(async () => { try { + if (!assignmentId) { + return; + } setAssignmentLoading(true); setAssignmentError(null); @@ -482,7 +490,7 @@ const AssignmentDetail: FC< }; const onEditAssignment = () => { - history.push( + navigateFunc( generatePath(APP_PATH.ASSIGNMENT_EDIT_TAB.route, { id: assignmentId, tabId: ASSIGNMENT_CREATE_UPDATE_TABS.CONTENT, @@ -493,20 +501,20 @@ const AssignmentDetail: FC< const onDuplicateAssignment = async (): Promise => { const duplicatedAssignment = await duplicateAssignment(assignment, commonUser); if (duplicatedAssignment) { - redirectToClientPage(toAssignmentDetail(duplicatedAssignment), history); + redirectToClientPage(toAssignmentDetail(duplicatedAssignment), navigateFunc); } }; const onDeleteAssignment = async (): Promise => { if (!assignment) return; await deleteAssignment(assignment, commonUser, () => - history.push(APP_PATH.WORKSPACE_ASSIGNMENTS.route) + navigateFunc(APP_PATH.WORKSPACE_ASSIGNMENTS.route) ); }; const onDeleteSelfFromAssignment = async (): Promise => { await deleteSelfFromAssignment(assignmentId, commonUser, () => - history.push(APP_PATH.WORKSPACE_ASSIGNMENTS.route) + navigateFunc(APP_PATH.WORKSPACE_ASSIGNMENTS.route) ); }; @@ -545,6 +553,9 @@ const AssignmentDetail: FC< // Render const renderAssignmentDropdownOptions = () => { + if (!assignmentId) { + return null; + } const ASSIGNMENT_DROPDOWN_ITEMS = [ ...createDropdownMenuItem( assignmentId, @@ -553,7 +564,7 @@ const AssignmentDetail: FC< IconName.plus, !!( permissions?.canEditBundles && - commonUser.permissions?.includes(PermissionName.ADD_ASSIGNMENT_TO_BUNDLE) + commonUser?.permissions?.includes(PermissionName.ADD_ASSIGNMENT_TO_BUNDLE) ) ), ...createDropdownMenuItem( @@ -708,6 +719,9 @@ const AssignmentDetail: FC< }; const renderHeaderButtonsMobile = () => { + if (!assignmentId) { + return null; + } const ASSIGNMENT_DROPDOWN_ITEMS_MOBILE = [ ...createDropdownMenuItem( assignmentId, @@ -827,7 +841,7 @@ const AssignmentDetail: FC< {isMobileWidth() ? renderHeaderButtonsMobile() : renderHeaderButtons()} - + @@ -933,7 +947,7 @@ const AssignmentDetail: FC< {!!assignment && ( - ); }; - -export default withUser(AssignmentDetail) as FC; diff --git a/src/assignment/views/AssignmentDetailSwitcher.tsx b/src/assignment/views/AssignmentDetailSwitcher.tsx index de5ca81848..e468af6c9a 100644 --- a/src/assignment/views/AssignmentDetailSwitcher.tsx +++ b/src/assignment/views/AssignmentDetailSwitcher.tsx @@ -1,23 +1,21 @@ import { Flex, Spacer, Spinner } from '@viaa/avo2-components'; +import { useAtomValue } from 'jotai'; import React, { type FC } from 'react'; import { SpecialUserGroupId } from '../../admin/user-groups/user-group.const'; -import { type DefaultSecureRouteProps } from '../../authentication/components/SecuredRoute'; +import { commonUserAtom } from '../../authentication/authentication.store'; import { ALL_SEARCH_FILTERS } from '../../search/search.const'; -import withUser, { type UserProps } from '../../shared/hocs/withUser'; -import AssignmentDetail from './AssignmentDetail'; -import AssignmentResponseEditPage from './AssignmentResponseEdit/AssignmentResponseEditPage'; +import { AssignmentDetail } from './AssignmentDetail'; +import { AssignmentResponseEditPage } from './AssignmentResponseEdit/AssignmentResponseEditPage'; import './AssignmentEdit.scss'; import './AssignmentPage.scss'; -interface AssignmentEditProps extends DefaultSecureRouteProps<{ id: string; tabId: string }> { - onUpdate: () => void | Promise; -} +export const AssignmentDetailSwitcher: FC = () => { + const commonUser = useAtomValue(commonUserAtom); -const AssignmentDetailSwitcher: FC = (props) => { - if (!props.commonUser?.userGroup?.id) { + if (!commonUser?.userGroup?.id) { return ( @@ -29,13 +27,11 @@ const AssignmentDetailSwitcher: FC = (props) => { if ( [SpecialUserGroupId.PupilSecondary, SpecialUserGroupId.PupilElementary] .map(String) - .includes(String(props.commonUser?.userGroup?.id)) + .includes(String(commonUser?.userGroup?.id)) ) { // Render assignment response edit page return ; } // Render teacher assignment detail page - return ; + return ; }; - -export default withUser(AssignmentDetailSwitcher) as FC; diff --git a/src/assignment/views/AssignmentEdit.tsx b/src/assignment/views/AssignmentEdit.tsx index 896767efe6..75c48fec80 100644 --- a/src/assignment/views/AssignmentEdit.tsx +++ b/src/assignment/views/AssignmentEdit.tsx @@ -19,36 +19,36 @@ import { } from '@viaa/avo2-components'; import { type Avo, PermissionName } from '@viaa/avo2-types'; import { isAfter, isPast } from 'date-fns'; +import { useAtomValue } from 'jotai'; import { noop } from 'lodash-es'; import React, { type FC, useCallback, useEffect, useMemo, useState } from 'react'; import { Helmet } from 'react-helmet'; -import { matchPath, Redirect } from 'react-router'; -import { Link } from 'react-router-dom'; +import { matchPath, Navigate, useMatch, useNavigate } from 'react-router'; +import { Link, useLocation } from 'react-router-dom'; -import { type DefaultSecureRouteProps } from '../../authentication/components/SecuredRoute'; +import { commonUserAtom } from '../../authentication/authentication.store'; import { PermissionService } from '../../authentication/helpers/permission-service'; import { redirectToClientPage } from '../../authentication/helpers/redirects/redirect-to-client-page'; -import { BlockList } from '../../collection/components'; import type { MarcomNoteInfo } from '../../collection/components/CollectionOrBundleEdit.types'; import { BundleSortProp, useGetCollectionsOrBundlesContainingFragment, } from '../../collection/hooks/useGetCollectionsOrBundlesContainingFragment'; import { APP_PATH, GENERATE_SITE_TITLE } from '../../constants'; -import { ErrorNoAccess } from '../../error/components'; -import { ErrorView } from '../../error/views'; -import { type ErrorViewQueryParams } from '../../error/views/ErrorView'; +import { ErrorNoAccess } from '../../error/components/ErrorNoAccess'; +import { ErrorView, type ErrorViewQueryParams } from '../../error/views/ErrorView'; import { BeforeUnloadPrompt } from '../../shared/components/BeforeUnloadPrompt/BeforeUnloadPrompt'; -import EmptyStateMessage from '../../shared/components/EmptyStateMessage/EmptyStateMessage'; -import HeaderOwnerAndContributors from '../../shared/components/HeaderOwnerAndContributors/HeaderOwnerAndContributors'; -import InActivityWarningModal from '../../shared/components/InActivityWarningModal/InActivityWarningModal'; +import { BlockList } from '../../shared/components/BlockList/BlockList'; +import { EmptyStateMessage } from '../../shared/components/EmptyStateMessage/EmptyStateMessage'; +import { HeaderOwnerAndContributors } from '../../shared/components/HeaderOwnerAndContributors/HeaderOwnerAndContributors'; +import { InActivityWarningModal } from '../../shared/components/InActivityWarningModal/InActivityWarningModal'; import { ListSorterColor, ListSorterPosition, ListSorterSlice, } from '../../shared/components/ListSorter'; -import SelectEducationLevelModal from '../../shared/components/SelectEducationLevelModal/SelectEducationLevelModal'; -import ShareModal from '../../shared/components/ShareModal/ShareModal'; +import { SelectEducationLevelModal } from '../../shared/components/SelectEducationLevelModal/SelectEducationLevelModal'; +import { ShareModal } from '../../shared/components/ShareModal/ShareModal'; import { ContributorInfoRight } from '../../shared/components/ShareWithColleagues/ShareWithColleagues.types'; import { StickySaveBar } from '../../shared/components/StickySaveBar/StickySaveBar'; import { buildLink } from '../../shared/helpers/build-link'; @@ -61,11 +61,10 @@ import { navigate } from '../../shared/helpers/link'; import { type EducationLevelId } from '../../shared/helpers/lom'; import { isMobileWidth } from '../../shared/helpers/media-query'; import { renderMobileDesktop } from '../../shared/helpers/renderMobileDesktop'; -import withUser, { type UserProps } from '../../shared/hocs/withUser'; import { useBlocksList } from '../../shared/hooks/use-blocks-list'; import { useDraggableListModal } from '../../shared/hooks/use-draggable-list-modal'; import { useAssignmentPastDeadline } from '../../shared/hooks/useAssignmentPastDeadline'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { useWarningBeforeUnload } from '../../shared/hooks/useWarningBeforeUnload'; import { BookmarksViewsPlaysService, @@ -88,16 +87,16 @@ import { setBlockPositionToIndex, } from '../assignment.helper'; import { AssignmentService } from '../assignment.service'; -import AssignmentActions from '../components/AssignmentActions'; -import AssignmentAdminFormEditable from '../components/AssignmentAdminFormEditable'; -import AssignmentConfirmSave from '../components/AssignmentConfirmSave'; -import AssignmentDetailsFormEditable from '../components/AssignmentDetailsFormEditable'; -import AssignmentDetailsFormReadonly from '../components/AssignmentDetailsFormReadonly'; -import AssignmentHeading from '../components/AssignmentHeading'; -import AssignmentMetaDataFormEditable from '../components/AssignmentMetaDataFormEditable'; -import AssignmentPupilPreview from '../components/AssignmentPupilPreview'; -import AssignmentTeacherTabs from '../components/AssignmentTeacherTabs'; -import AssignmentTitle from '../components/AssignmentTitle'; +import { AssignmentActions } from '../components/AssignmentActions'; +import { AssignmentAdminFormEditable } from '../components/AssignmentAdminFormEditable'; +import { AssignmentConfirmSave } from '../components/AssignmentConfirmSave'; +import { AssignmentDetailsFormEditable } from '../components/AssignmentDetailsFormEditable'; +import { AssignmentDetailsFormReadonly } from '../components/AssignmentDetailsFormReadonly'; +import { AssignmentHeading } from '../components/AssignmentHeading'; +import { AssignmentMetaDataFormEditable } from '../components/AssignmentMetaDataFormEditable'; +import { AssignmentPupilPreview } from '../components/AssignmentPupilPreview'; +import { AssignmentTeacherTabs } from '../components/AssignmentTeacherTabs'; +import { AssignmentTitle } from '../components/AssignmentTitle'; import { endOfAcademicYear } from '../helpers/academic-year'; import { onAddNewContributor, @@ -109,28 +108,30 @@ import { cleanupTitleAndDescriptions } from '../helpers/cleanup-title-and-descri import { duplicateAssignment } from '../helpers/duplicate-assignment'; import { isDeadlineBeforeAvailableAt } from '../helpers/is-deadline-before-available-at'; import { backToOverview } from '../helpers/links'; -import { useAssignmentBlockChangeHandler, useBlockListModals, useEditBlocks } from '../hooks'; +import { useAssignmentBlockChangeHandler } from '../hooks/assignment-block-change-handler'; +import { useBlockListModals } from '../hooks/assignment-content-modals'; import { type AssignmentFields } from '../hooks/assignment-form'; +import { useEditBlocks } from '../hooks/use-edit-blocks'; import { useEducationLevelModal } from '../hooks/use-education-level-modal'; -import PublishAssignmentModal from '../modals/PublishAssignmentModal'; +import { PublishAssignmentModal } from '../modals/PublishAssignmentModal'; -import AssignmentEditMarcom from './AssignmentEditMarcom'; -import AssignmentResponses from './AssignmentResponses'; +import { AssignmentEditMarcom } from './AssignmentEditMarcom'; +import { AssignmentResponses } from './AssignmentResponses'; -interface AssignmentEditProps extends DefaultSecureRouteProps<{ id: string; tabId: string }> { - onUpdate: () => void | Promise; +interface AssignmentEditProps { + onUpdate?: () => void | Promise; } -const AssignmentEdit: FC = ({ - onUpdate = noop, - match, - commonUser, - history, - location, -}) => { +export const AssignmentEdit: FC = ({ onUpdate = noop }) => { const { tText, tHtml } = useTranslation(); + const location = useLocation(); + const navigateFunc = useNavigate(); + const match = useMatch<'id' | 'tabId', string>(APP_PATH.ASSIGNMENT_EDIT.route); - const assignmentId = match.params.id; + const assignmentId = match?.params.id; + const tabId = match?.params.tabId; + + const commonUser = useAtomValue(commonUserAtom); // Data const [tab, setTab] = useState( @@ -174,10 +175,10 @@ const AssignmentEdit: FC = ({ >({}); const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); const { data: bundlesContainingAssignment } = useGetCollectionsOrBundlesContainingFragment( - assignmentId, + assignmentId as string, BundleSortProp.title, OrderDirection.asc, - { enabled: !!assignment } + { enabled: !!assignmentId && !!assignment } ); // Computed @@ -216,6 +217,9 @@ const AssignmentEdit: FC = ({ const releaseAssignmentEditStatus = useCallback(async () => { try { + if (!assignmentId) { + return; + } await AssignmentService.releaseAssignmentEditStatus(assignmentId); } catch (err) { if ((err as CustomError)?.innerException?.additionalInfo?.statusCode !== 409) { @@ -230,11 +234,14 @@ const AssignmentEdit: FC = ({ const updateAssignmentEditor = useCallback(async () => { try { + if (!assignmentId) { + return; + } await AssignmentService.updateAssignmentEditor(assignmentId); } catch (err) { redirectToClientPage( buildLink(APP_PATH.ASSIGNMENT_DETAIL.route, { id: assignmentId }), - history + navigateFunc ); if ((err as CustomError)?.innerException?.additionalInfo?.statusCode === 409) { @@ -254,7 +261,7 @@ const AssignmentEdit: FC = ({ ); } } - }, [assignmentId, history, releaseAssignmentEditStatus, tHtml]); + }, [assignmentId, releaseAssignmentEditStatus, tHtml, navigateFunc]); const updateAssignmentEditorWithLoading = useCallback(async () => { setIsAssignmentLoading(true); @@ -262,10 +269,10 @@ const AssignmentEdit: FC = ({ }, [updateAssignmentEditor]); useEffect(() => { - if (match.params.tabId) { - setTab(match.params.tabId as ASSIGNMENT_CREATE_UPDATE_TABS); + if (tabId) { + setTab(tabId as ASSIGNMENT_CREATE_UPDATE_TABS); } - }, [match]); + }, [match, tabId]); useEffect(() => { if (!isCreatingAssignment) { @@ -295,9 +302,11 @@ const AssignmentEdit: FC = ({ // Get query string variables and fetch the existing object const fetchAssignment = useCallback(async () => { try { + if (!assignmentId) { + return; + } setIsAssignmentLoading(true); setAssignmentError(null); - const id = match.params.id; let tempAssignment: Avo.Assignment.Assignment | null = null; if ( @@ -315,7 +324,7 @@ const AssignmentEdit: FC = ({ } try { - tempAssignment = await AssignmentService.fetchAssignmentById(id); + tempAssignment = await AssignmentService.fetchAssignmentById(assignmentId); } catch (err) { if (JSON.stringify(err).includes(NO_RIGHTS_ERROR_MESSAGE)) { setAssignmentError({ @@ -400,7 +409,7 @@ const AssignmentEdit: FC = ({ return; } - if (checkedPermissions?.canFetchBookmarkAndViewCounts) { + if (checkedPermissions?.canFetchBookmarkAndViewCounts && !!assignment) { try { setBookmarkViewCounts( await BookmarksViewsPlaysService.getAssignmentCounts( @@ -435,7 +444,7 @@ const AssignmentEdit: FC = ({ }); } setIsAssignmentLoading(false); - }, [match.params.id, assignmentId, commonUser, setAssignmentFormValues, tHtml]); + }, [assignmentId, commonUser, setAssignmentFormValues, tHtml]); // Events @@ -498,6 +507,9 @@ const AssignmentEdit: FC = ({ const saveAssignment = async () => { try { + if (!assignmentId) { + return; + } setIsSaving(true); if (isCreatingAssignment) { // Create assignment @@ -553,7 +565,9 @@ const AssignmentEdit: FC = ({ // Delay navigation, until isDirty state becomes false, otherwise the "unsaved changes" modal will popup setTimeout(() => { - navigate(history, APP_PATH.ASSIGNMENT_DETAIL.route, { id: created.id }); + navigate(navigateFunc, APP_PATH.ASSIGNMENT_DETAIL.route, { + id: created.id, + }); }, 100); } } else { @@ -703,7 +717,7 @@ const AssignmentEdit: FC = ({ buildLink(APP_PATH.ASSIGNMENT_DETAIL.route, { id: assignmentId, }), - history + navigateFunc ); }; @@ -727,7 +741,7 @@ const AssignmentEdit: FC = ({ responses: originalAssignment?.responses || [], }, addCollectionConfig: { - addCollectionCallback: (id) => { + addCollectionCallback: (id: string) => { // Track import collection into assignment event trackEvents( { @@ -838,10 +852,10 @@ const AssignmentEdit: FC = ({ } return ( - + ); - }, [assignment, commonUser]); + }, [assignment]); const renderMeta = useMemo(() => { const bookmarks = String(bookmarkViewCounts.bookmarkCount || 0); @@ -958,7 +972,7 @@ const AssignmentEdit: FC = ({ ); case ASSIGNMENT_CREATE_UPDATE_TABS.CLICKS: - return ; + return ; case ASSIGNMENT_CREATE_UPDATE_TABS.ADMIN: return ( @@ -1018,7 +1032,7 @@ const AssignmentEdit: FC = ({ if (assignmentId) { navigate( - history, + navigateFunc, APP_PATH.ASSIGNMENT_EDIT_TAB.route, { id: assignmentId, tabId: tabId }, undefined, @@ -1030,7 +1044,7 @@ const AssignmentEdit: FC = ({ const handleDuplicateAssignment = async () => { const duplicatedAssignment = await duplicateAssignment(originalAssignment, commonUser); if (duplicatedAssignment) { - navigate(history, APP_PATH.ASSIGNMENT_DETAIL.route, { + navigate(navigateFunc, APP_PATH.ASSIGNMENT_DETAIL.route, { id: duplicatedAssignment.id, tabId: ASSIGNMENT_CREATE_UPDATE_TABS.CONTENT, }); @@ -1100,7 +1114,7 @@ const AssignmentEdit: FC = ({ buildLink(APP_PATH.ASSIGNMENT_DETAIL.route, { id: assignmentId, }), - history + navigateFunc ), }} preview={{ onClick: () => setIsViewAsPupilEnabled(true) }} @@ -1110,7 +1124,7 @@ const AssignmentEdit: FC = ({ modal: { confirmCallback: () => { reset(); - redirectToClientPage(backToOverview(), history); + redirectToClientPage(backToOverview(), navigateFunc); }, }, }} @@ -1196,7 +1210,7 @@ const AssignmentEdit: FC = ({ warningMessage={tHtml( 'assignment/views/assignment-edit___door-inactiviteit-zal-de-opdracht-zichzelf-sluiten' )} - currentPath={history.location.pathname} + currentPath={location.pathname} editPath={APP_PATH.ASSIGNMENT_EDIT_TAB.route} onForcedExit={onForcedExitPage} /> @@ -1264,9 +1278,9 @@ const AssignmentEdit: FC = ({ return renderEditAssignmentPage(); }; - if (matchPath(location.pathname, { path: APP_PATH.ASSIGNMENT_EDIT.route, exact: true })) { + if (matchPath(location.pathname, APP_PATH.ASSIGNMENT_EDIT.route)) { return ( - = ({ ); }; - -export default withUser(AssignmentEdit) as FC; diff --git a/src/assignment/views/AssignmentEditMarcom.tsx b/src/assignment/views/AssignmentEditMarcom.tsx index 3331ed1987..c883e4735e 100644 --- a/src/assignment/views/AssignmentEditMarcom.tsx +++ b/src/assignment/views/AssignmentEditMarcom.tsx @@ -20,11 +20,12 @@ import { TextInput, } from '@viaa/avo2-components'; import { type Avo, PermissionName } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { compact, get, isNil } from 'lodash-es'; import React, { type FC, type ReactNode, useMemo, useState } from 'react'; -import { Link, type RouteComponentProps, withRouter } from 'react-router-dom'; -import { compose } from 'redux'; +import { Link } from 'react-router-dom'; +import { commonUserAtom } from '../../authentication/authentication.store'; import { GET_MARCOM_CHANNEL_NAME_OPTIONS, GET_MARCOM_CHANNEL_TYPE_OPTIONS, @@ -42,8 +43,7 @@ import { extractKlascementError } from '../../shared/helpers/extract-klascement- import { formatDate } from '../../shared/helpers/formatters'; import { ACTIONS_TABLE_COLUMN_ID } from '../../shared/helpers/table-column-list-to-csv-column-list'; import { truncateTableValue } from '../../shared/helpers/truncate'; -import withUser, { type UserProps } from '../../shared/hocs/withUser'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { ToastService } from '../../shared/services/toast-service'; import { useDeleteAssignmentMarcomEntry } from '../hooks/useDeleteAssignmentMarcomEntry'; import { useGetAssignmentMarcomEntries } from '../hooks/useGetAssignmentMarcomEntries'; @@ -59,13 +59,13 @@ interface AssignmentEditMarcomProps { onFocus?: () => void; } -const AssignmentEditMarcom: FC = ({ +export const AssignmentEditMarcom: FC = ({ assignment, setAssignment, onFocus, - commonUser, }) => { const { tText, tHtml } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); const [marcomDate, setMarcomDate] = useState(new Date()); const [marcomChannelType, setMarcomChannelType] = useState(); @@ -412,5 +412,3 @@ const AssignmentEditMarcom: FC ); }; - -export default compose(withRouter, withUser)(AssignmentEditMarcom) as FC; diff --git a/src/assignment/views/AssignmentOverview.tsx b/src/assignment/views/AssignmentOverview.tsx index 6d6343c013..5b672d69ee 100644 --- a/src/assignment/views/AssignmentOverview.tsx +++ b/src/assignment/views/AssignmentOverview.tsx @@ -26,6 +26,7 @@ import { } from '@viaa/avo2-components'; import { type Avo, PermissionName, ShareWithColleagueTypeEnum } from '@viaa/avo2-types'; import { clsx } from 'clsx'; +import { useAtomValue } from 'jotai'; import { cloneDeep, compact, isArray, isNil, noop } from 'lodash-es'; import React, { type FC, @@ -36,8 +37,8 @@ import React, { useMemo, useState, } from 'react'; -import { Link, type RouteComponentProps, withRouter } from 'react-router-dom'; -import { compose } from 'redux'; +import { useNavigate } from 'react-router'; +import { Link } from 'react-router-dom'; import { ArrayParam, DelimitedArrayParam, @@ -48,10 +49,11 @@ import { } from 'use-query-params'; import { GET_DEFAULT_PAGINATION_BAR_PROPS } from '../../admin/shared/components/PaginationBar/PaginationBar.consts'; +import { commonUserAtom } from '../../authentication/authentication.store'; import { PermissionService } from '../../authentication/helpers/permission-service'; import { redirectToClientPage } from '../../authentication/helpers/redirects/redirect-to-client-page'; import { APP_PATH } from '../../constants'; -import { ErrorView } from '../../error/views'; +import { ErrorView } from '../../error/views/ErrorView'; import { OrderDirection } from '../../search/search.const'; import { CheckboxDropdownModal, @@ -72,8 +74,7 @@ import { renderMobileDesktop } from '../../shared/helpers/renderMobileDesktop'; import { createShareIconTableOverview } from '../../shared/helpers/share-icon-table-overview'; import { ACTIONS_TABLE_COLUMN_ID } from '../../shared/helpers/table-column-list-to-csv-column-list'; import { truncateTableValue } from '../../shared/helpers/truncate'; -import withUser, { type UserProps } from '../../shared/hocs/withUser'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { AssignmentLabelsService } from '../../shared/services/assignment-labels-service'; import { ToastService } from '../../shared/services/toast-service'; import { KeyCode } from '../../shared/types'; @@ -91,11 +92,11 @@ import { AssignmentType, AssignmentView, } from '../assignment.types'; -import AssignmentDeadline from '../components/AssignmentDeadline'; +import { AssignmentDeadline } from '../components/AssignmentDeadline'; import { deleteAssignment, deleteSelfFromAssignment } from '../helpers/delete-assignment'; import { duplicateAssignment } from '../helpers/duplicate-assignment'; import { useGetAssignments } from '../hooks/useGetAssignments'; -import DeleteAssignmentModal from '../modals/DeleteAssignmentModal'; +import { DeleteAssignmentModal } from '../modals/DeleteAssignmentModal'; interface AssignmentOverviewProps { onUpdate: () => void | Promise; @@ -114,12 +115,10 @@ const defaultFiltersAndSort = { sort_order: DEFAULT_SORT_ORDER, }; -const AssignmentOverview: FC = ({ - onUpdate = noop, - history, - commonUser, -}) => { +export const AssignmentOverview: FC = ({ onUpdate = noop }) => { const { tText, tHtml } = useTranslation(); + const navigateFunc = useNavigate(); + const commonUser = useAtomValue(commonUserAtom); const [allAssignmentLabels, setAllAssignmentLabels] = useState([]); const [filterString, setFilterString] = useState(undefined); @@ -296,7 +295,7 @@ const AssignmentOverview: FC - redirectToClientPage(buildLink(APP_PATH.ASSIGNMENT_CREATE.route), history); + redirectToClientPage(buildLink(APP_PATH.ASSIGNMENT_CREATE.route), navigateFunc); const getEmptyFallbackTitle = () => { const hasFilters: boolean = @@ -967,5 +966,3 @@ const AssignmentOverview: FC{renderAssignmentsView()}; }; - -export default compose(withRouter, withUser)(AssignmentOverview) as FC; diff --git a/src/assignment/views/AssignmentPupilCollectionDetail.tsx b/src/assignment/views/AssignmentPupilCollectionDetail.tsx index 3ea73fd417..e1c0ba9741 100644 --- a/src/assignment/views/AssignmentPupilCollectionDetail.tsx +++ b/src/assignment/views/AssignmentPupilCollectionDetail.tsx @@ -1,49 +1,52 @@ import { BlockHeading } from '@meemoo/admin-core-ui/dist/client.mjs'; import { Container, Icon, IconName } from '@viaa/avo2-components'; import { type Avo, PermissionName } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { noop } from 'lodash-es'; import React, { type FC, useCallback, useEffect, useMemo, useState } from 'react'; import { Helmet } from 'react-helmet'; +import { useMatch } from 'react-router'; import { Link } from 'react-router-dom'; -import { type DefaultSecureRouteProps } from '../../authentication/components/SecuredRoute'; +import { commonUserAtom } from '../../authentication/authentication.store'; import { PermissionService } from '../../authentication/helpers/permission-service'; -import { BlockList } from '../../collection/components'; -import { GENERATE_SITE_TITLE } from '../../constants'; -import { ErrorView } from '../../error/views'; +import { APP_PATH, GENERATE_SITE_TITLE } from '../../constants'; +import { ErrorView } from '../../error/views/ErrorView'; +import { BlockList } from '../../shared/components/BlockList/BlockList'; import { LoadingErrorLoadedComponent, type LoadingInfo, } from '../../shared/components/LoadingErrorLoadedComponent/LoadingErrorLoadedComponent'; import { CustomError } from '../../shared/helpers/custom-error'; -import withUser from '../../shared/hocs/withUser'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { AssignmentService } from '../assignment.service'; -import AssignmentHeading from '../components/AssignmentHeading'; -import AssignmentMetadata from '../components/AssignmentMetadata'; +import { AssignmentHeading } from '../components/AssignmentHeading'; +import { AssignmentMetadata } from '../components/AssignmentMetadata'; import { buildGlobalSearchLink } from '../helpers/build-search-link'; import { toAssignmentResponsesOverview } from '../helpers/links'; -type AssignmentPupilCollectionDetailProps = DefaultSecureRouteProps<{ - responseId: string; - assignmentId: string; -}>; - -const AssignmentPupilCollectionDetail: FC = ({ - match, - commonUser, -}) => { +export const AssignmentPupilCollectionDetail: FC = () => { const { tText, tHtml } = useTranslation(); + const commonUser = useAtomValue(commonUserAtom); + + const match = useMatch<'assignmentId' | 'responseId', string>( + APP_PATH.ASSIGNMENT_PUPIL_COLLECTION_DETAIL.route + ); + + const assignmentId = match?.params.assignmentId; + const assignmentResponseId = match?.params.responseId; + const [loadingInfo, setLoadingInfo] = useState({ state: 'loading' }); const [assignment, setAssignment] = useState(null); const [assignmentResponse, setAssignmentResponse] = useState(); - const assignmentId = match.params.assignmentId; - const assignmentResponseId = match.params.responseId; const fetchAssignmentResponse = useCallback( async ( tempAssignment: Avo.Assignment.Assignment ): Promise => { + if (!assignmentResponseId) { + return null; + } const canViewAssignmentResponses = await PermissionService.hasPermissions( [ PermissionName.EDIT_ANY_ASSIGNMENTS, @@ -68,6 +71,9 @@ const AssignmentPupilCollectionDetail: FC const fetchAssignment = useCallback(async () => { try { + if (!assignmentId) { + return; + } const tempAssignment: Avo.Assignment.Assignment = await AssignmentService.fetchAssignmentById(assignmentId); @@ -88,7 +94,7 @@ const AssignmentPupilCollectionDetail: FC ), }); } - }, [setAssignment, setLoadingInfo, assignmentResponseId, tText, commonUser, tHtml]); + }, [assignmentId, fetchAssignmentResponse, commonUser, assignmentResponseId, tHtml]); // Effects @@ -154,7 +160,7 @@ const AssignmentPupilCollectionDetail: FC PermissionName.VIEW_ANY_PUBLISHED_ITEMS ), }, - buildSeriesLink: (serie) => + buildSeriesLink: (serie: string) => buildGlobalSearchLink({ filters: { serie: [serie] } }), canOpenOriginal: true, }, @@ -197,7 +203,3 @@ const AssignmentPupilCollectionDetail: FC ); }; - -export default withUser( - AssignmentPupilCollectionDetail -) as FC; diff --git a/src/assignment/views/AssignmentResponseEdit/AssignmentResponseAdminEdit.tsx b/src/assignment/views/AssignmentResponseEdit/AssignmentResponseAdminEdit.tsx index 8b5b5b818e..b10440825b 100644 --- a/src/assignment/views/AssignmentResponseEdit/AssignmentResponseAdminEdit.tsx +++ b/src/assignment/views/AssignmentResponseEdit/AssignmentResponseAdminEdit.tsx @@ -1,5 +1,6 @@ import { Flex, IconName, Spacer, Spinner } from '@viaa/avo2-components'; import { type Avo, PermissionName } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { noop } from 'lodash-es'; import React, { type Dispatch, @@ -11,33 +12,33 @@ import React, { useState, } from 'react'; import { Helmet } from 'react-helmet'; -import { withRouter } from 'react-router-dom'; -import { compose } from 'redux'; +import { useMatch } from 'react-router'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; +import { commonUserAtom } from '../../../authentication/authentication.store'; import { PermissionService } from '../../../authentication/helpers/permission-service'; -import { GENERATE_SITE_TITLE } from '../../../constants'; -import { ErrorView } from '../../../error/views'; -import withUser, { type UserProps } from '../../../shared/hocs/withUser'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { APP_PATH, GENERATE_SITE_TITLE } from '../../../constants'; +import { ErrorView } from '../../../error/views/ErrorView'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { ToastService } from '../../../shared/services/toast-service'; import { AssignmentService } from '../../assignment.service'; -import AssignmentMetadata from '../../components/AssignmentMetadata'; +import { AssignmentMetadata } from '../../components/AssignmentMetadata'; import { PupilCollectionForTeacherPreview } from '../../components/PupilCollectionForTeacherPreview'; -import AssignmentResponseEdit from './AssignmentResponseEdit'; +import { AssignmentResponseEdit } from './AssignmentResponseEdit'; import '../AssignmentPage.scss'; import './AssignmentResponseEdit.scss'; -const AssignmentResponseAdminEdit: FC< - UserProps & DefaultSecureRouteProps<{ assignmentId: string; responseId: string }> -> = ({ match, commonUser }) => { +export const AssignmentResponseAdminEdit: FC = () => { const { tText, tHtml } = useTranslation(); + const match = useMatch<'responseId' | 'assignmentId', string>( + APP_PATH.ASSIGNMENT_PUPIL_COLLECTION_ADMIN_EDIT.route + ); + const commonUser = useAtomValue(commonUserAtom); // Data - const assignmentId = match.params.assignmentId; - const assignmentResponseId = match.params.responseId; + const assignmentId = match?.params.assignmentId; + const assignmentResponseId = match?.params.responseId; const [assignment, setAssignment] = useState(null); const [assignmentLoading, setAssignmentLoading] = useState(false); const [assignmentError, setAssignmentError] = useState<{ @@ -55,6 +56,9 @@ const AssignmentResponseAdminEdit: FC< // HTTP const fetchAssignment = useCallback(async () => { try { + if (!assignmentId || !assignmentResponseId) { + return; + } setAssignmentLoading(true); // Check if the user is a teacher, they do not have permission to create a response for assignments and should see a clear error message @@ -114,13 +118,13 @@ const AssignmentResponseAdminEdit: FC< }); } setAssignmentLoading(false); - }, [assignmentId, tHtml, tText]); + }, [assignmentId, assignmentResponseId, tHtml, tText]); // Effects useEffect(() => { fetchAssignment().then(noop); - }, []); + }, [fetchAssignment]); // Events @@ -237,5 +241,3 @@ const AssignmentResponseAdminEdit: FC< ); }; - -export default compose(withRouter, withUser)(AssignmentResponseAdminEdit) as FC; diff --git a/src/assignment/views/AssignmentResponseEdit/AssignmentResponseEdit.tsx b/src/assignment/views/AssignmentResponseEdit/AssignmentResponseEdit.tsx index 1e2334cfbe..0bdabc796e 100644 --- a/src/assignment/views/AssignmentResponseEdit/AssignmentResponseEdit.tsx +++ b/src/assignment/views/AssignmentResponseEdit/AssignmentResponseEdit.tsx @@ -13,6 +13,7 @@ import { } from '@viaa/avo2-components'; import { type Avo } from '@viaa/avo2-types'; import { clsx } from 'clsx'; +import { useAtomValue } from 'jotai'; import React, { type Dispatch, type FC, @@ -31,15 +32,15 @@ import { useQueryParams, } from 'use-query-params'; +import { commonUserAtom } from '../../../authentication/authentication.store'; import { CollectionBlockType } from '../../../collection/collection.const'; import { type FilterState } from '../../../search/search.types'; import { BeforeUnloadPrompt } from '../../../shared/components/BeforeUnloadPrompt/BeforeUnloadPrompt'; -import InteractiveTour from '../../../shared/components/InteractiveTour/InteractiveTour'; +import { InteractiveTour } from '../../../shared/components/InteractiveTour/InteractiveTour'; import { StickySaveBar } from '../../../shared/components/StickySaveBar/StickySaveBar'; import { formatTimestamp } from '../../../shared/helpers/formatters'; -import withUser, { type UserProps } from '../../../shared/hocs/withUser'; import { useAssignmentPastDeadline } from '../../../shared/hooks/useAssignmentPastDeadline'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { useWarningBeforeUnload } from '../../../shared/hooks/useWarningBeforeUnload'; import { ToastService } from '../../../shared/services/toast-service'; import { @@ -54,16 +55,16 @@ import { type PupilCollectionFragment, type PupilSearchFilterState, } from '../../assignment.types'; -import AssignmentHeading from '../../components/AssignmentHeading'; -import AssignmentMetadata from '../../components/AssignmentMetadata'; +import { AssignmentHeading } from '../../components/AssignmentHeading'; +import { AssignmentMetadata } from '../../components/AssignmentMetadata'; import { buildAssignmentSearchLink } from '../../helpers/build-search-link'; import { cleanupTitleAndDescriptions } from '../../helpers/cleanup-title-and-descriptions'; import { backToOverview } from '../../helpers/links'; import { useAssignmentPupilTabs } from '../../hooks/assignment-pupil-tabs'; -import AssignmentResponseAssignmentTab from './tabs/AssignmentResponseAssignmentTab'; -import AssignmentResponsePupilCollectionTab from './tabs/AssignmentResponsePupilCollectionTab'; -import AssignmentResponseSearchTab from './tabs/AssignmentResponseSearchTab'; +import { AssignmentResponseAssignmentTab } from './tabs/AssignmentResponseAssignmentTab'; +import { AssignmentResponsePupilCollectionTab } from './tabs/AssignmentResponsePupilCollectionTab'; +import { AssignmentResponseSearchTab } from './tabs/AssignmentResponseSearchTab'; import '../AssignmentPage.scss'; import './AssignmentResponseEdit.scss'; @@ -80,7 +81,7 @@ interface AssignmentResponseEditProps { onShowPreviewClicked: () => void; } -const AssignmentResponseEdit: FC = ({ +export const AssignmentResponseEdit: FC = ({ assignment, assignmentResponse, onAssignmentChanged, @@ -88,10 +89,10 @@ const AssignmentResponseEdit: FC = ({ showBackButton, isPreview = false, onShowPreviewClicked, - user, }) => { const { tText, tHtml } = useTranslation(); const [isSaving, setIsSaving] = useState(false); + const commonUser = useAtomValue(commonUserAtom); // Data const [assignmentResponseOriginal, setAssignmentResponseOriginal] = useState = ({ setIsSaving(false); return; } - if (!user?.profile?.id || !assignmentResponse || !assignmentResponseOriginal) { + if (!commonUser?.profileId || !assignmentResponse || !assignmentResponseOriginal) { setIsSaving(false); return; } @@ -278,7 +279,7 @@ const AssignmentResponseEdit: FC = ({ const renderBackButton = useMemo( () => ( - + {tText('assignment/views/assignment-edit___mijn-opdrachten')} @@ -450,5 +451,3 @@ const AssignmentResponseEdit: FC = ({ return renderAssignmentResponseEditView(); }; - -export default withUser(AssignmentResponseEdit) as FC; diff --git a/src/assignment/views/AssignmentResponseEdit/AssignmentResponseEditPage.tsx b/src/assignment/views/AssignmentResponseEdit/AssignmentResponseEditPage.tsx index 00c6cea316..ea8605e8f2 100644 --- a/src/assignment/views/AssignmentResponseEdit/AssignmentResponseEditPage.tsx +++ b/src/assignment/views/AssignmentResponseEdit/AssignmentResponseEditPage.tsx @@ -1,39 +1,38 @@ import { Flex, IconName, Spacer, Spinner } from '@viaa/avo2-components'; import { type Avo, PermissionName } from '@viaa/avo2-types'; +import { useAtomValue } from 'jotai'; import { isString, noop } from 'lodash-es'; import React, { type FC, type ReactNode, useCallback, useEffect, useState } from 'react'; import { Helmet } from 'react-helmet'; -import { withRouter } from 'react-router-dom'; -import { compose } from 'redux'; +import { useMatch } from 'react-router'; -import { type DefaultSecureRouteProps } from '../../../authentication/components/SecuredRoute'; +import { commonUserAtom } from '../../../authentication/authentication.store'; import { PermissionService } from '../../../authentication/helpers/permission-service'; -import { GENERATE_SITE_TITLE } from '../../../constants'; -import { ErrorView } from '../../../error/views'; -import withUser, { type UserProps } from '../../../shared/hocs/withUser'; -import useTranslation from '../../../shared/hooks/useTranslation'; +import { APP_PATH, GENERATE_SITE_TITLE } from '../../../constants'; +import { ErrorView } from '../../../error/views/ErrorView'; +import { useTranslation } from '../../../shared/hooks/useTranslation'; import { trackEvents } from '../../../shared/services/event-logging-service'; import { ToastService } from '../../../shared/services/toast-service'; import { getAssignmentErrorObj } from '../../assignment.helper'; import { AssignmentService } from '../../assignment.service'; import { AssignmentRetrieveError } from '../../assignment.types'; -import AssignmentMetadata from '../../components/AssignmentMetadata'; +import { AssignmentMetadata } from '../../components/AssignmentMetadata'; import { PupilCollectionForTeacherPreview } from '../../components/PupilCollectionForTeacherPreview'; import { canViewAnAssignment } from '../../helpers/can-view-an-assignment'; -import AssignmentResponseEdit from './AssignmentResponseEdit'; +import { AssignmentResponseEdit } from './AssignmentResponseEdit'; import '../AssignmentPage.scss'; import './AssignmentResponseEdit.scss'; -const AssignmentResponseEditPage: FC> = ({ - match, - commonUser, -}) => { +export const AssignmentResponseEditPage: FC = () => { const { tText, tHtml } = useTranslation(); + const match = useMatch<'id', string>(APP_PATH.ASSIGNMENT_RESPONSE_EDIT.route); + const assignmentId = match?.params.id; + + const commonUser = useAtomValue(commonUserAtom); // Data - const assignmentId = match.params.id; const [assignment, setAssignment] = useState(null); const [assignmentLoading, setAssignmentLoading] = useState(false); const [assignmentError, setAssignmentError] = useState<{ @@ -52,6 +51,9 @@ const AssignmentResponseEditPage: FC { try { + if (!assignmentId) { + return; + } setAssignmentLoading(true); // Check if the user is a teacher, they do not have permission to create a response for assignments and should see a clear error message @@ -154,7 +156,7 @@ const AssignmentResponseEditPage: FC { fetchAssignment().then(noop); - }, []); + }, [fetchAssignment]); // Events @@ -262,5 +264,3 @@ const AssignmentResponseEditPage: FC ); }; - -export default compose(withRouter, withUser)(AssignmentResponseEditPage) as FC; diff --git a/src/assignment/views/AssignmentResponseEdit/tabs/AssignmentResponseAssignmentTab.tsx b/src/assignment/views/AssignmentResponseEdit/tabs/AssignmentResponseAssignmentTab.tsx index 5428595b9b..543bd716fe 100644 --- a/src/assignment/views/AssignmentResponseEdit/tabs/AssignmentResponseAssignmentTab.tsx +++ b/src/assignment/views/AssignmentResponseEdit/tabs/AssignmentResponseAssignmentTab.tsx @@ -2,10 +2,10 @@ import { IconName } from '@viaa/avo2-components'; import { type Avo } from '@viaa/avo2-types'; import React, { type FC, type ReactNode } from 'react'; -import { ErrorView } from '../../../../error/views'; +import { ErrorView } from '../../../../error/views/ErrorView'; import { type FilterState } from '../../../../search/search.types'; -import BlockList from '../../../../shared/components/BlockList/BlockList'; -import useTranslation from '../../../../shared/hooks/useTranslation'; +import { BlockList } from '../../../../shared/components/BlockList/BlockList'; +import { useTranslation } from '../../../../shared/hooks/useTranslation'; import { ASSIGNMENT_RESPONSE_CREATE_UPDATE_TABS } from '../../../assignment.const'; interface AssignmentResponseAssignmentTabProps { @@ -15,7 +15,7 @@ interface AssignmentResponseAssignmentTabProps { buildSearchLink: (props: Partial) => ReactNode | string; } -const AssignmentResponseAssignmentTab: FC = ({ +export const AssignmentResponseAssignmentTab: FC = ({ blocks, pastDeadline, setTab, @@ -64,5 +64,3 @@ const AssignmentResponseAssignmentTab: FC return renderAssignmentBlocks(); }; - -export default AssignmentResponseAssignmentTab as FC; diff --git a/src/assignment/views/AssignmentResponseEdit/tabs/AssignmentResponsePupilCollectionTab.tsx b/src/assignment/views/AssignmentResponseEdit/tabs/AssignmentResponsePupilCollectionTab.tsx index e00022e528..7678eed965 100644 --- a/src/assignment/views/AssignmentResponseEdit/tabs/AssignmentResponsePupilCollectionTab.tsx +++ b/src/assignment/views/AssignmentResponseEdit/tabs/AssignmentResponsePupilCollectionTab.tsx @@ -18,15 +18,16 @@ import React, { type Dispatch, type FC, type SetStateAction, useState } from 're import { Controller, type UseFormReturn } from 'react-hook-form'; import { type UrlUpdateType } from 'use-query-params'; -import { ReactComponent as PupilSvg } from '../../../../assets/images/leerling.svg'; +// eslint-disable-next-line import/no-unresolved +import PupilSvg from '../../../../assets/images/leerling.svg?react'; import { CollectionBlockType } from '../../../../collection/collection.const'; -import { BlockList } from '../../../../collection/components'; -import EmptyStateMessage from '../../../../shared/components/EmptyStateMessage/EmptyStateMessage'; +import { BlockList } from '../../../../shared/components/BlockList/BlockList'; +import { EmptyStateMessage } from '../../../../shared/components/EmptyStateMessage/EmptyStateMessage'; import { getMoreOptionsLabel } from '../../../../shared/constants'; import { isMobileWidth } from '../../../../shared/helpers/media-query'; import { useBlocksList } from '../../../../shared/hooks/use-blocks-list'; import { useDraggableListModal } from '../../../../shared/hooks/use-draggable-list-modal'; -import useTranslation from '../../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../../shared/hooks/useTranslation'; import { ToastService } from '../../../../shared/services/toast-service'; import { ASSIGNMENT_RESPONSE_CREATE_UPDATE_TABS, @@ -41,7 +42,9 @@ import { import { AssignmentBlockItemDescriptionType } from '../../../components/AssignmentBlockDescriptionButtons'; import { buildAssignmentSearchLink } from '../../../helpers/build-search-link'; import { insertMultipleAtPosition } from '../../../helpers/insert-at-position'; -import { useAssignmentBlockChangeHandler, useBlockListModals, useEditBlocks } from '../../../hooks'; +import { useAssignmentBlockChangeHandler } from '../../../hooks/assignment-block-change-handler'; +import { useBlockListModals } from '../../../hooks/assignment-content-modals'; +import { useEditBlocks } from '../../../hooks/use-edit-blocks'; enum MobileActionId { reorderBlocks = 'reorderBlocks', @@ -57,7 +60,7 @@ interface AssignmentResponsePupilCollectionTabProps { setFilterState: (state: PupilSearchFilterState, urlPushType?: UrlUpdateType) => void; } -const AssignmentResponsePupilCollectionTab: FC< +export const AssignmentResponsePupilCollectionTab: FC< AssignmentResponsePupilCollectionTabProps & Pick, 'setValue' | 'control'> > = ({ @@ -343,5 +346,3 @@ const AssignmentResponsePupilCollectionTab: FC< ); }; - -export default AssignmentResponsePupilCollectionTab; diff --git a/src/assignment/views/AssignmentResponseEdit/tabs/AssignmentResponseSearchTab.tsx b/src/assignment/views/AssignmentResponseEdit/tabs/AssignmentResponseSearchTab.tsx index aa183ba269..3b3f050b3f 100644 --- a/src/assignment/views/AssignmentResponseEdit/tabs/AssignmentResponseSearchTab.tsx +++ b/src/assignment/views/AssignmentResponseEdit/tabs/AssignmentResponseSearchTab.tsx @@ -1,28 +1,26 @@ import { Button, Container, Icon, IconName, Spacer } from '@viaa/avo2-components'; import { type Avo, PermissionName } from '@viaa/avo2-types'; import { clsx } from 'clsx'; +import { useAtomValue } from 'jotai'; import { intersection } from 'lodash-es'; import React, { type FC, type ReactNode, useCallback, useEffect, useState } from 'react'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; import { type UrlUpdateType } from 'use-query-params'; +import { commonUserAtom } from '../../../../authentication/authentication.store'; import { PermissionService } from '../../../../authentication/helpers/permission-service'; -import { ErrorView } from '../../../../error/views'; -import CutFragmentForAssignmentModal from '../../../../item/components/modals/CutFragmentForAssignmentModal'; +import { ErrorView } from '../../../../error/views/ErrorView'; +import { CutFragmentForAssignmentModal } from '../../../../item/components/modals/CutFragmentForAssignmentModal'; import { type ItemTrimInfo } from '../../../../item/item.types'; -import ItemDetail from '../../../../item/views/ItemDetail'; +import { ItemDetail } from '../../../../item/views/ItemDetail'; import { PupilCollectionService } from '../../../../pupil-collection/pupil-collection.service'; -import { SearchFiltersAndResults } from '../../../../search/components'; +import { SearchFiltersAndResults } from '../../../../search/components/SearchFiltersAndResults'; +import { searchAtom } from '../../../../search/search.store'; import { type FilterState } from '../../../../search/search.types'; -import { selectSearchResults } from '../../../../search/store/selectors'; import { EducationLevelId } from '../../../../shared/helpers/lom'; -import withUser, { type UserProps } from '../../../../shared/hocs/withUser'; -import useTranslation from '../../../../shared/hooks/useTranslation'; +import { useTranslation } from '../../../../shared/hooks/useTranslation'; import { trackEvents } from '../../../../shared/services/event-logging-service'; import { ObjectTypesAll } from '../../../../shared/services/related-items-service'; import { ToastService } from '../../../../shared/services/toast-service'; -import { type AppState } from '../../../../store'; import { ENABLED_FILTERS_PUPIL_SEARCH, ENABLED_ORDER_PROPERTIES_PUPIL_SEARCH, @@ -39,20 +37,18 @@ interface AssignmentResponseSearchTabProps { appendBlockToPupilCollection: (block: Avo.Core.BlockItemBase) => void; // Appends a block to the end of the list of blocks of the current (unsaved) pupil collection } -const AssignmentResponseSearchTab: FC< - AssignmentResponseSearchTabProps & { searchResults: Avo.Search.Search } & UserProps -> = ({ +export const AssignmentResponseSearchTab: FC = ({ filterState, setFilterState, assignment, assignmentResponse, appendBlockToPupilCollection, - searchResults, - commonUser, }) => { const { tText, tHtml } = useTranslation(); // Data + const searchResults = useAtomValue(searchAtom); + const commonUser = useAtomValue(commonUserAtom); // UI const [isAddToAssignmentModalOpen, setIsAddToAssignmentModalOpen] = useState(false); @@ -339,12 +335,3 @@ const AssignmentResponseSearchTab: FC< ); }; - -const mapStateToProps = (state: AppState) => ({ - searchResults: selectSearchResults(state), -}); - -export default compose( - connect(mapStateToProps), - withUser -)(AssignmentResponseSearchTab) as FC; diff --git a/src/assignment/views/AssignmentResponses.tsx b/src/assignment/views/AssignmentResponses.tsx index 86dd01d46b..416e2396e0 100644 --- a/src/assignment/views/AssignmentResponses.tsx +++ b/src/assignment/views/AssignmentResponses.tsx @@ -18,17 +18,19 @@ import { } from '@viaa/avo2-components'; import { type Avo, PermissionName } from '@viaa/avo2-types'; import { clsx } from 'clsx'; +import { useAtomValue } from 'jotai'; import { cloneDeep, compact, get, isNil, noop, uniq } from 'lodash-es'; import React, { type FC, type ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; +import { useMatch } from 'react-router'; import { Link } from 'react-router-dom'; import { NumberParam, StringParam, useQueryParams } from 'use-query-params'; import { ItemsService } from '../../admin/items/items.service'; import { GET_DEFAULT_PAGINATION_BAR_PROPS } from '../../admin/shared/components/PaginationBar/PaginationBar.consts'; -import { type DefaultSecureRouteProps } from '../../authentication/components/SecuredRoute'; +import { commonUserAtom } from '../../authentication/authentication.store'; import { PermissionService } from '../../authentication/helpers/permission-service'; import { APP_PATH } from '../../constants'; -import { ErrorView } from '../../error/views'; +import { ErrorView } from '../../error/views/ErrorView'; import { OrderDirection } from '../../search/search.const'; import { ConfirmModal } from '../../shared/components/ConfirmModal/ConfirmModal'; import { @@ -40,9 +42,8 @@ import { formatDate } from '../../shared/helpers/formatters'; import { isMobileWidth } from '../../shared/helpers/media-query'; import { ACTIONS_TABLE_COLUMN_ID } from '../../shared/helpers/table-column-list-to-csv-column-list'; import { truncateTableValue } from '../../shared/helpers/truncate'; -import withUser from '../../shared/hocs/withUser'; import { useTableSort } from '../../shared/hooks/useTableSort'; -import useTranslation from '../../shared/hooks/useTranslation'; +import { useTranslation } from '../../shared/hooks/useTranslation'; import { NO_RIGHTS_ERROR_MESSAGE } from '../../shared/services/data-service'; import { ToastService } from '../../shared/services/toast-service'; import { TableColumnDataType } from '../../shared/types/table-column-data-type'; @@ -61,21 +62,20 @@ import { isItemWithMeta } from '../helpers/is-item-with-meta'; import './AssignmentOverview.scss'; import './AssignmentResponses.scss'; -interface AssignmentResponsesProps - extends Omit, 'location'> { +interface AssignmentResponsesProps { onUpdate: () => void | Promise; } const DEFAULT_SORT_COLUMN = 'updated_at'; const DEFAULT_SORT_ORDER = OrderDirection.desc; -const AssignmentResponses: FC = ({ - onUpdate = noop, - match, - commonUser, -}) => { +export const AssignmentResponses: FC = ({ onUpdate = noop }) => { const { tText, tHtml } = useTranslation(); + const match = useMatch<'id', string>(APP_PATH.ASSIGNMENT_EDIT.route); + const assignmentId = match?.params.id; + + const commonUser = useAtomValue(commonUserAtom); // Data const [assignment, setAssignment] = useState(null); const [assignmentResponses, setAssignmentResponses] = useState< @@ -197,6 +197,9 @@ const AssignmentResponses: FC = ({ const fetchAssignment = useCallback(async () => { try { + if (!assignmentId) { + return; + } if (!canViewAnAssignment(commonUser)) { setLoadingInfo({ message: tHtml( @@ -206,7 +209,6 @@ const AssignmentResponses: FC = ({ state: 'error', }); } - const assignmentId = match.params.id; const assignment = await AssignmentService.fetchAssignmentById(assignmentId); @@ -229,16 +231,17 @@ const AssignmentResponses: FC = ({ ), }); } - }, [match, tText, tHtml]); + }, [assignmentId, commonUser, tHtml]); const fetchAssignmentResponses = useCallback(async () => { try { + if (!assignmentId) { + return; + } if (isNil(canViewAssignmentResponses)) { return; } - const assignmentId = match.params.id; - const column = tableColumns.find( (tableColumn: any) => tableColumn.id || '' === (sortColumn as any) ); @@ -277,7 +280,7 @@ const AssignmentResponses: FC = ({ } }, [ canViewAssignmentResponses, - match.params.id, + assignmentId, tableColumns, commonUser, sortColumn, @@ -448,7 +451,7 @@ const AssignmentResponses: FC = ({ return renderDataCell( @@ -600,7 +603,3 @@ const AssignmentResponses: FC = ({ /> ) : null; }; - -export default withUser(AssignmentResponses) as FC< - Omit ->; diff --git a/src/assignment/views/index.ts b/src/assignment/views/index.ts deleted file mode 100644 index 47a0b645c0..0000000000 --- a/src/assignment/views/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { default as AssignmentDetail } from './AssignmentDetail'; -export { default as AssignmentEdit } from './AssignmentEdit'; -export { default as AssignmentOverview } from './AssignmentOverview'; -export { default as AssignmentResponses } from './AssignmentResponses'; diff --git a/src/authentication/authentication.routes.tsx b/src/authentication/authentication.routes.tsx deleted file mode 100644 index f7c876e81b..0000000000 --- a/src/authentication/authentication.routes.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React, { type ReactNode } from 'react'; -import { Route } from 'react-router'; - -import { APP_PATH } from '../constants'; -import CompleteProfileStep from '../settings/components/CompleteProfileStep'; - -import { LinkYourAccount, Login, Logout, RegisterOrLogin, RegisterStamboek } from './views'; -import AcceptConditions from './views/registration-flow/l8-accept-conditions'; -import StudentTeacher from './views/registration-flow/r10-student-teacher'; -import ManualRegistration from './views/registration-flow/r4-manual-registration'; - -export const renderAuthenticationRoutes = (): ReactNode[] => [ - , - , - , - , - , - , - , - , - , -]; diff --git a/src/authentication/authentication.store.actions.tsx b/src/authentication/authentication.store.actions.tsx new file mode 100644 index 0000000000..9dda16ccdd --- /dev/null +++ b/src/authentication/authentication.store.actions.tsx @@ -0,0 +1,151 @@ +import { Button, Spacer } from '@viaa/avo2-components'; +import { type Avo } from '@viaa/avo2-types'; +import { subMinutes } from 'date-fns'; +import { atom } from 'jotai'; +import { compact } from 'lodash-es'; +import queryString from 'query-string'; +import React from 'react'; +import { type Location } from 'react-router'; + +import { LTI_JWT_TOKEN_HEADER } from '../embed/embed.types'; +import { EmbedCodeService } from '../embed-code/embed-code-service'; +import { CustomError } from '../shared/helpers/custom-error'; +import { getEnv } from '../shared/helpers/env'; +import { tText } from '../shared/helpers/translate-text'; +import { ToastService } from '../shared/services/toast-service'; +import { historyLocationsAtom } from '../shared/store/ui.store'; + +import { loginAtom } from './authentication.store'; +import { LoginMessage, type LoginState } from './authentication.types'; +import { logoutAndRedirectToLogin } from './helpers/redirects'; + +let checkSessionTimeoutTimerId: number | null = null; + +function checkIfSessionExpires(expiresAt: string) { + const date = new Date(expiresAt); + + // Create fake location object + const location = { + pathname: window.location.pathname, + state: { + from: { pathname: window.location.pathname, search: window.location.search }, + }, + } as unknown as Location; + if (subMinutes(date, 5).getTime() < new Date().getTime()) { + logoutAndRedirectToLogin(location); + } else if (subMinutes(date, 10).getTime() < new Date().getTime()) { + // Show warning since user is about to be logged out + ToastService.info( + <> + {tText( + 'authentication/store/actions___je-sessie-gaat-over-5-min-verlopen-sla-je-werk-op-en-log-opnieuw-in' + )} + +