From 7129943bfdc03d063aa20fcea3ee0c412a43f98a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Dombya?= <135591453+hervedombya@users.noreply.github.com> Date: Wed, 20 Nov 2024 14:23:05 +0100 Subject: [PATCH] ARTESCA-13969 // Migration to React 18 ARTESCA-13969 // Migration to React 18 refactor: update NotificationCenter styles and improve test assertions refactor: migrate to React 18's createRoot for rendering refactor: implement external store for WebFingers context and update related hooks refactor: remove console logs and simplify state update logic in WebFingersStore refactor: update dependencies to React 18 and related packages Add ShellHooksProvider and integrate shell hooks into FederableApp Add shell hooks integration and update useAlerts function to accept optional filters Pass shellHooks and shellAlerts as props to FederatedComponent in ProtectedFederatedRoute Add @types/react-router-dom to package.json Refactor to useShellHooks for improved context integration across components Refactor context creation to eliminate reliance on window.shellContexts Update module-federation dependency and enhance shell hooks integration in FederatedApp Update @scality/module-federation dependency to latest version refactor: update history management and fix type errors across components --- shell-ui/package-lock.json | 495 ++++++------- shell-ui/package.json | 29 +- shell-ui/src/FederatedApp.tsx | 162 +---- shell-ui/src/NotificationCenterProvider.tsx | 20 +- shell-ui/src/alerts/Alerts.spec.tsx | 1 - shell-ui/src/alerts/alertContext.ts | 14 +- shell-ui/src/alerts/alertHooks.ts | 4 +- shell-ui/src/auth/useFirstTimeLogin.spec.tsx | 12 +- shell-ui/src/hooks/useShellHooks.ts | 102 +++ shell-ui/src/index.tsx | 18 +- .../initFederation/ConfigurationProviders.tsx | 113 ++- .../initFederation/ShellConfigProvider.tsx | 36 +- .../initFederation/ShellHistoryProvider.tsx | 22 +- .../ShellThemeSelectorProvider.tsx | 22 +- .../src/initFederation/UIListProvider.tsx | 40 +- shell-ui/src/navbar/NavBar.tsx | 11 +- .../src/navbar/NotificationCenter.spec.tsx | 10 +- shell-ui/src/navbar/NotificationCenter.tsx | 4 +- .../navbar/__TESTS__/testMultipleHooks.tsx | 2 +- shell-ui/src/navbar/index.spec.tsx | 73 +- shell-ui/src/navbar/lang.tsx | 22 +- shell-ui/src/navbar/navbarContext.ts | 14 +- shell-ui/src/navbar/navbarHooks.ts | 1 - ui/package-lock.json | 658 +++++++++++------- ui/package.json | 25 +- ui/src/FederableApp.tsx | 63 +- ui/src/ShellHooksContext.tsx | 99 +++ .../ConfigureAlerting.test.tsx | 20 +- .../alert-configuration/ConfigureAlerting.tsx | 8 +- ui/src/components/ActiveAlertsCounter.tsx | 12 +- ui/src/components/ActiveAlertsFilters.tsx | 8 +- .../AlertNavbarUpdaterComponent.tsx | 1 + ui/src/components/DashboardAlerts.tsx | 6 +- ui/src/components/DashboardInventory.tsx | 13 +- ui/src/components/HealthItem.tsx | 6 +- ui/src/components/NodeListTable.tsx | 33 +- ui/src/components/NodePageVolumesTable.tsx | 18 +- ui/src/components/VolumeListTable.tsx | 12 +- ui/src/components/VolumeOverviewTab.tsx | 14 +- ui/src/components/__TEST__/util.tsx | 6 +- ui/src/containers/AlertPage.tsx | 30 +- ui/src/containers/AlertProvider.tsx | 21 +- ui/src/containers/ConfigProvider.tsx | 8 +- ui/src/containers/CreateVolume.tsx | 56 +- ui/src/containers/IntlProvider.tsx | 4 +- ui/src/containers/Layout.tsx | 105 ++- ui/src/containers/NodeCreateForm.tsx | 7 +- ui/src/containers/NodePage.tsx | 1 - ui/src/containers/NodePageContent.tsx | 34 +- ui/src/containers/NodePageMetricsTab.tsx | 53 +- ui/src/containers/NodePageRSP.tsx | 5 +- ui/src/containers/PrivateRoute.tsx | 19 +- ui/src/containers/TimespanSelector.tsx | 11 +- ui/src/containers/VolumePage.tsx | 25 +- ui/src/containers/VolumePageContent.tsx | 27 +- ui/src/ducks/history.ts | 23 +- ui/src/ducks/reducer.ts | 2 +- ui/src/hooks.tsx | 1 - ui/src/services/utils.ts | 24 +- 59 files changed, 1381 insertions(+), 1304 deletions(-) create mode 100644 shell-ui/src/hooks/useShellHooks.ts create mode 100644 ui/src/ShellHooksContext.tsx diff --git a/shell-ui/package-lock.json b/shell-ui/package-lock.json index 7c7a717d7d..c6de922916 100644 --- a/shell-ui/package-lock.json +++ b/shell-ui/package-lock.json @@ -8,20 +8,20 @@ "name": "shell-ui", "version": "1.0.0", "dependencies": { - "@scality/core-ui": "0.151.0", - "@scality/module-federation": "^1.3.4", + "@scality/core-ui": "git+https://github.com/scality/core-ui#bf0c36da657737f47dabe310bb1a20c136877970", + "@scality/module-federation": "git+https://github.com/scality/module-federation#c571388783a2a51ae3bf5d36ae66753c8b014bb5", "downshift": "^8.0.0", "jest-environment-jsdom": "^29.7.0", "oidc-client-ts": "^3.0.1", "oidc-react": "^3.2.2", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.3.1", + "react-dom": "^18.3.1", "react-error-boundary": "^4.0.2", "react-intl": "^5.15.3", "react-query": "^3.34.0", - "react-router": "5.2.0", - "react-router-dom": "5.2.0", - "styled-components": "^5.2.1", + "react-router": "^6.28.0", + "react-router-dom": "^6.28.0", + "styled-components": "^5.3.11", "typescript": "^5.6.3" }, "devDependencies": { @@ -35,14 +35,15 @@ "@rspack/core": "^0.7.5", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^5.11.9", - "@testing-library/react": "^11.2.5", - "@testing-library/react-hooks": "^5.1.1", + "@testing-library/react": "^15.0.7", + "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^13.0.10", - "@types/react": "^17.0.39", - "@types/react-dom": "^17.0.13", + "@types/react": "^18.3.12", + "@types/react-dom": "^18.3.1", "@types/react-router": "^5.1.20", - "@types/react-router-dom": "^5.2.0", - "@types/styled-components": "^5.1.26", + "@types/react-router-dom": "^5.3.3", + "@types/react-test-renderer": "^18.3.0", + "@types/styled-components": "^5.1.34", "babel-jest": "^26.6.3", "babel-loader": "^8.2.2", "fs-extra": "^10.0.0", @@ -52,7 +53,7 @@ "jest-preview": "^0.3.1", "msw": "0.36.8", "node-fetch": "^2.6.1", - "react-test-renderer": "^17.0.2", + "react-test-renderer": "^18.3.1", "ts-node": "^10.9.2" } }, @@ -1864,19 +1865,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/runtime-corejs3": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.26.0.tgz", - "integrity": "sha512-YXHu5lN8kJCb1LOb9PgV6pvak43X2h4HvRApcN5SdWeaItQOzfn1hgP6jasD6KWQyJDBxrVmA9o9OivlnNJK/w==", - "dev": true, - "dependencies": { - "core-js-pure": "^3.30.2", - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/template": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", @@ -2043,8 +2031,7 @@ }, "node_modules/@emotion/is-prop-valid": { "version": "0.8.8", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", - "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "license": "MIT", "optional": true, "dependencies": { "@emotion/memoize": "0.7.4" @@ -2052,8 +2039,7 @@ }, "node_modules/@emotion/memoize": { "version": "0.7.4", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", - "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "license": "MIT", "optional": true }, "node_modules/@emotion/react": { @@ -3619,6 +3605,14 @@ "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", "dev": true }, + "node_modules/@remix-run/router": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.21.0.tgz", + "integrity": "sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rsdoctor/client": { "version": "0.3.11", "resolved": "https://registry.npmjs.org/@rsdoctor/client/-/client-0.3.11.tgz", @@ -4175,8 +4169,9 @@ }, "node_modules/@scality/core-ui": { "version": "0.151.0", - "resolved": "https://registry.npmjs.org/@scality/core-ui/-/core-ui-0.151.0.tgz", - "integrity": "sha512-OeAhs+uiOOBDSGqzZGpIka1iCtRrGJkjNhzdRJhJtLwxKDFU7iyPUPA3MbJ8DoGJQN0do8k3PTyei1fZEiMXJA==", + "resolved": "git+ssh://git@github.com/scality/core-ui.git#bf0c36da657737f47dabe310bb1a20c136877970", + "integrity": "sha512-dC/zNxvxU7DVgxhbyKHgwwVyM2CwWACrwyVbh1VP0/7KTcgTmoYR2hO9qAMi9t8yyNWidOi9AVVzKupes13wRw==", + "license": "SEE LICENSE IN LICENSE", "dependencies": { "@floating-ui/dom": "^1.6.3", "@fortawesome/fontawesome-free": "^5.10.2", @@ -4190,9 +4185,9 @@ "framer-motion": "^4.1.17", "polished": "3.4.1", "pretty-bytes": "^5.6.0", - "react": "^17.0.2", + "react": "^18.3.1", "react-debounce-input": "3.2.2", - "react-dom": "^17.0.2", + "react-dom": "^18.3.1", "react-dropzone": "^14.2.3", "react-hook-form": "^7.49.2", "react-query": "^3.34.0", @@ -4200,6 +4195,7 @@ "react-router-dom": "5.2.0", "react-select": "4.3.1", "react-table": "^7.7.0", + "react-test-renderer": "^18.3.1", "react-virtualized": "9.22.3", "react-virtualized-auto-sizer": "^1.0.24", "react-window": "^1.8.6", @@ -4231,18 +4227,74 @@ "react": ">=16.12.0" } }, + "node_modules/@scality/core-ui/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/@scality/core-ui/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/@scality/core-ui/node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/@scality/core-ui/node_modules/react-router": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", + "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "dependencies": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "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" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/@scality/core-ui/node_modules/react-router-dom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz", + "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==", + "dependencies": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.2.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/@scality/core-ui/node_modules/react-router/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/@scality/module-federation": { "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@scality/module-federation/-/module-federation-1.3.4.tgz", - "integrity": "sha512-Okmgh+s9UTM6ropLt5QIJhswaN3m0hGNjGI2w/al+a4H+fQs5x/rAYngzWhFnHxdox0RUSRwA7aOZH1fBAvnmA==", + "resolved": "git+ssh://git@github.com/scality/module-federation.git#c571388783a2a51ae3bf5d36ae66753c8b014bb5", + "integrity": "sha512-lrpXm7Skkq/CtGQRI563pSelewbeNaBBbs3J4zzCiheb0H2fSs6JF6lqQHQjL9A0HRVjfnArotXlF8E8JzVtnw==", + "license": "SEE LICENSE IN LICENSE", "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^18.3.1", + "react-dom": "^18.3.1" } }, "node_modules/@sinclair/typebox": { @@ -4290,9 +4342,9 @@ "dev": true }, "node_modules/@storybook/preview-api": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.4.5.tgz", - "integrity": "sha512-MKIZ2jQO/3cUdsT57eq8jRgB6inALo9BxrQ88f7mqzltOkMvADvTAY6y8JZqTUoDzWTH/ny/8SGGdtpqlxRuiQ==", + "version": "8.4.4", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.4.4.tgz", + "integrity": "sha512-iZrWQcjRBqBHFdDXVxGpw6mHBZMCMYqhWXdyJ0d1S2y3PwcfOjkcXlQ1UiAenFHlA6dKrcYw8luKUQTL9bKReA==", "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" @@ -4698,41 +4750,51 @@ } }, "node_modules/@testing-library/react": { - "version": "11.2.7", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.7.tgz", - "integrity": "sha512-tzRNp7pzd5QmbtXNG/mhdcl7Awfu/Iz1RaVHY75zTdOkmHCuzMhRL83gWHSgOAcjS3CCbyfwUHMZgRJb4kAfpA==", + "version": "15.0.7", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-15.0.7.tgz", + "integrity": "sha512-cg0RvEdD1TIhhkm1IeYMQxrzy0MtUNfa3minv4MjbgcYzJAZ7yD0i0lwoPOTPr+INtiXFezt2o8xMSnyHhEn2Q==", "dev": true, "dependencies": { "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^7.28.1" + "@testing-library/dom": "^10.0.0", + "@types/react-dom": "^18.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "peerDependencies": { - "react": "*", - "react-dom": "*" + "@types/react": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, "node_modules/@testing-library/react-hooks": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-5.1.3.tgz", - "integrity": "sha512-UdEUtlQapQ579NEcXDAUE275u+KUsPtxW7NmFrNt0bE6lW8lqNCyxDK0RSuECmNZ/S0/fgP00W9RWRhVKO/hRg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz", + "integrity": "sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==", "dev": true, "dependencies": { "@babel/runtime": "^7.12.5", - "@types/react": ">=16.9.0", - "@types/react-dom": ">=16.9.0", - "@types/react-test-renderer": ">=16.9.0", - "filter-console": "^0.1.1", "react-error-boundary": "^3.1.0" }, + "engines": { + "node": ">=12" + }, "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0", - "react-test-renderer": ">=16.9.0" + "@types/react": "^16.9.0 || ^17.0.0", + "react": "^16.9.0 || ^17.0.0", + "react-dom": "^16.9.0 || ^17.0.0", + "react-test-renderer": "^16.9.0 || ^17.0.0" }, "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, "react-dom": { "optional": true }, @@ -4757,81 +4819,6 @@ "react": ">=16.13.1" } }, - "node_modules/@testing-library/react/node_modules/@testing-library/dom": { - "version": "7.31.2", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.31.2.tgz", - "integrity": "sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^4.2.0", - "aria-query": "^4.2.2", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.6", - "lz-string": "^1.4.4", - "pretty-format": "^26.6.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@testing-library/react/node_modules/@types/aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==", - "dev": true - }, - "node_modules/@testing-library/react/node_modules/aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/@testing-library/react/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@testing-library/react/node_modules/pretty-format": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", - "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", - "dev": true, - "dependencies": { - "@jest/types": "^26.6.2", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@testing-library/react/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, "node_modules/@testing-library/user-event": { "version": "13.5.0", "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.5.0.tgz", @@ -4900,37 +4887,34 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "version": "7.6.2", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "version": "7.4.0", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "version": "7.11.0", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.20.7" } }, "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", "dev": true, "dependencies": { "@types/connect": "*", @@ -5011,9 +4995,9 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" }, "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", "dev": true, "dependencies": { "@types/body-parser": "*", @@ -5023,9 +5007,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz", - "integrity": "sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==", + "version": "4.17.33", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz", + "integrity": "sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==", "dev": true, "dependencies": { "@types/node": "*", @@ -5188,12 +5172,6 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true - }, "node_modules/@types/node": { "version": "22.9.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.1.tgz", @@ -5222,34 +5200,33 @@ "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==" }, "node_modules/@types/qs": { - "version": "6.9.17", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", - "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==", + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", "dev": true }, "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", "dev": true }, "node_modules/@types/react": { - "version": "17.0.83", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.83.tgz", - "integrity": "sha512-l0m4ArKJvmFtR4e8UmKrj1pB4tUgOhJITf+mADyF/p69Ts1YAR/E+G9XEM0mHXKVRa1dQNHseyyDNzeuAXfXQw==", + "version": "18.3.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", + "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", "dependencies": { "@types/prop-types": "*", - "@types/scheduler": "^0.16", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "17.0.25", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.25.tgz", - "integrity": "sha512-urx7A7UxkZQmThYA4So0NelOVjx3V4rNFVJwp0WZlbIK5eM4rNJDiN3R/E9ix0MBh6kAEojk/9YL+Te6D9zHNA==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", "dev": true, "dependencies": { - "@types/react": "^17" + "@types/react": "*" } }, "node_modules/@types/react-router": { @@ -5288,11 +5265,6 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, - "node_modules/@types/scheduler": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" - }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", @@ -5303,6 +5275,12 @@ "@types/node": "*" } }, + "node_modules/@types/send/node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, "node_modules/@types/serve-index": { "version": "1.9.4", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", @@ -5313,9 +5291,9 @@ } }, "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", + "integrity": "sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==", "dev": true, "dependencies": { "@types/http-errors": "*", @@ -7174,17 +7152,6 @@ "url": "https://opencollective.com/core-js" } }, - "node_modules/core-js-pure": { - "version": "3.39.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.39.0.tgz", - "integrity": "sha512-7fEcWwKI4rJinnK+wLTezeg2smbFFdSBP6E2kQZNbnzM2s1rpKQ6aaRteZSSg7FLU3P0HGGVo/gbpfanU36urg==", - "dev": true, - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -8789,15 +8756,6 @@ "node": ">=8" } }, - "node_modules/filter-console": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/filter-console/-/filter-console-0.1.1.tgz", - "integrity": "sha512-zrXoV1Uaz52DqPs+qEwNJWJFAWZpYJ47UNmpN9q4j+/EYsz85uV0DC9k8tRND5kYmoVzL0W+Y75q4Rg8sRJCdg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/finalhandler": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", @@ -9361,9 +9319,8 @@ }, "node_modules/harmony-reflect": { "version": "1.6.2", - "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", - "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==", - "dev": true + "dev": true, + "license": "(Apache-2.0 OR MPL-1.1)" }, "node_modules/has-flag": { "version": "4.0.0", @@ -12898,9 +12855,8 @@ }, "node_modules/jsonfile": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -14670,12 +14626,11 @@ } }, "node_modules/react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" }, "engines": { "node": ">=0.10.0" @@ -14694,16 +14649,15 @@ } }, "node_modules/react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "dependencies": { "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" + "scheduler": "^0.23.2" }, "peerDependencies": { - "react": "17.0.2" + "react": "^18.3.1" } }, "node_modules/react-dropzone": { @@ -14821,60 +14775,35 @@ } }, "node_modules/react-router": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", - "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.0.tgz", + "integrity": "sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==", "dependencies": { - "@babel/runtime": "^7.1.2", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "mini-create-react-context": "^0.4.0", - "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" + "@remix-run/router": "1.21.0" + }, + "engines": { + "node": ">=14.0.0" }, "peerDependencies": { - "react": ">=15" + "react": ">=16.8" } }, "node_modules/react-router-dom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz", - "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==", + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.28.0.tgz", + "integrity": "sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==", "dependencies": { - "@babel/runtime": "^7.1.2", - "history": "^4.9.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-router": "5.2.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "@remix-run/router": "1.21.0", + "react-router": "6.28.0" + }, + "engines": { + "node": ">=14.0.0" }, "peerDependencies": { - "react": ">=15" + "react": ">=16.8", + "react-dom": ">=16.8" } }, - "node_modules/react-router/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, - "node_modules/react-router/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/react-router/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, "node_modules/react-select": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/react-select/-/react-select-4.3.1.tgz", @@ -14897,7 +14826,6 @@ "version": "16.15.0", "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", - "dev": true, "dependencies": { "object-assign": "^4.1.1", "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" @@ -14919,26 +14847,18 @@ } }, "node_modules/react-test-renderer": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-17.0.2.tgz", - "integrity": "sha512-yaQ9cB89c17PUb0x6UfWRs7kQCorVdHlutU1boVPEsB8IDZH6n9tHxMacc3y0JoXOJUsZb/t/Mb8FUWMKaM7iQ==", - "dev": true, + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-18.3.1.tgz", + "integrity": "sha512-KkAgygexHUkQqtvvx/otwxtuFu5cVjfzTCtjXLH9boS19/Nbtg84zS7wIQn39G8IlrhThBpQsMKkq5ZHZIYFXA==", "dependencies": { - "object-assign": "^4.1.1", - "react-is": "^17.0.2", - "react-shallow-renderer": "^16.13.1", - "scheduler": "^0.20.2" + "react-is": "^18.3.1", + "react-shallow-renderer": "^16.15.0", + "scheduler": "^0.23.2" }, "peerDependencies": { - "react": "17.0.2" + "react": "^18.3.1" } }, - "node_modules/react-test-renderer/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -15729,12 +15649,11 @@ } }, "node_modules/scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" } }, "node_modules/schema-utils": { @@ -16036,9 +15955,9 @@ } }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "dev": true, "dependencies": { "call-bind": "^1.0.7", @@ -17247,10 +17166,9 @@ } }, "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "version": "2.0.0", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -17465,9 +17383,8 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/utils-merge": { "version": "1.0.1", diff --git a/shell-ui/package.json b/shell-ui/package.json index d871b5156a..2caf607b12 100644 --- a/shell-ui/package.json +++ b/shell-ui/package.json @@ -22,14 +22,15 @@ "@rspack/core": "^0.7.5", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^5.11.9", - "@testing-library/react": "^11.2.5", - "@testing-library/react-hooks": "^5.1.1", + "@testing-library/react": "^15.0.7", + "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^13.0.10", - "@types/react": "^17.0.39", - "@types/react-dom": "^17.0.13", + "@types/react": "^18.3.12", + "@types/react-dom": "^18.3.1", "@types/react-router": "^5.1.20", - "@types/react-router-dom": "^5.2.0", - "@types/styled-components": "^5.1.26", + "@types/react-router-dom": "^5.3.3", + "@types/react-test-renderer": "^18.3.0", + "@types/styled-components": "^5.1.34", "babel-jest": "^26.6.3", "babel-loader": "^8.2.2", "fs-extra": "^10.0.0", @@ -39,24 +40,24 @@ "jest-preview": "^0.3.1", "msw": "0.36.8", "node-fetch": "^2.6.1", - "react-test-renderer": "^17.0.2", + "react-test-renderer": "^18.3.1", "ts-node": "^10.9.2" }, "dependencies": { - "@scality/core-ui": "0.151.0", - "@scality/module-federation": "^1.3.4", + "@scality/core-ui": "git+https://github.com/scality/core-ui#bf0c36da657737f47dabe310bb1a20c136877970", + "@scality/module-federation": "git+https://github.com/scality/module-federation#c571388783a2a51ae3bf5d36ae66753c8b014bb5", "downshift": "^8.0.0", "jest-environment-jsdom": "^29.7.0", "oidc-client-ts": "^3.0.1", "oidc-react": "^3.2.2", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.3.1", + "react-dom": "^18.3.1", "react-error-boundary": "^4.0.2", "react-intl": "^5.15.3", "react-query": "^3.34.0", - "react-router": "5.2.0", - "react-router-dom": "5.2.0", - "styled-components": "^5.2.1", + "react-router": "^6.28.0", + "react-router-dom": "^6.28.0", + "styled-components": "^5.3.11", "typescript": "^5.6.3" } } diff --git a/shell-ui/src/FederatedApp.tsx b/shell-ui/src/FederatedApp.tsx index cae930c6ab..1bdb30c25b 100644 --- a/shell-ui/src/FederatedApp.tsx +++ b/shell-ui/src/FederatedApp.tsx @@ -1,5 +1,6 @@ import { CoreUiThemeProvider } from '@scality/core-ui/dist/components/coreuithemeprovider/CoreUiThemeProvider'; import { ErrorPage500 } from '@scality/core-ui/dist/components/error-pages/ErrorPage500.component'; +import { Loader } from '@scality/core-ui/dist/components/loader/Loader.component'; import { ScrollbarWrapper } from '@scality/core-ui/dist/components/scrollbarwrapper/ScrollbarWrapper.component'; import { ToastProvider } from '@scality/core-ui/dist/components/toast/ToastProvider'; import { @@ -11,62 +12,36 @@ import { createBrowserHistory } from 'history'; import React, { useEffect, useMemo } from 'react'; import { ErrorBoundary } from 'react-error-boundary'; import { QueryClient, QueryClientProvider } from 'react-query'; -import { Route, Router, Switch } from 'react-router-dom'; -import { Loader } from '@scality/core-ui/dist/components/loader/Loader.component'; +import { BrowserRouter, Route, Router, Routes } from 'react-router-dom'; -import NotificationCenterProvider, { - NotificationCenterContextType, -} from './NotificationCenterProvider'; +import { loadShare } from '@module-federation/enhanced/runtime'; +import { useQuery } from 'react-query'; +import NotificationCenterProvider from './NotificationCenterProvider'; import { AuthConfigProvider, useAuthConfig } from './auth/AuthConfigProvider'; import { AuthProvider, useAuth } from './auth/AuthProvider'; import { FirstTimeLoginProvider } from './auth/FirstTimeLoginProvider'; +import { + ShellAlerts, + shellAlerts, + ShellHooks, + shellHooks, +} from './hooks/useShellHooks'; import './index.css'; import { ConfigurationProvider, FederatedView, useConfigRetriever, - useConfig, useDiscoveredViews, - useLinkOpener, - BuildtimeWebFinger, - RuntimeWebFinger, } from './initFederation/ConfigurationProviders'; import { ShellConfigProvider, useShellConfig, } from './initFederation/ShellConfigProvider'; import { ShellHistoryProvider } from './initFederation/ShellHistoryProvider'; -import { - ShellThemeSelectorProvider, - useShellThemeSelector, -} from './initFederation/ShellThemeSelectorProvider'; -import { - UIListProvider, - useDeployedApps, -} from './initFederation/UIListProvider'; +import { ShellThemeSelectorProvider } from './initFederation/ShellThemeSelectorProvider'; +import { UIListProvider } from './initFederation/UIListProvider'; import { SolutionsNavbar } from './navbar'; import { LanguageProvider, useLanguage } from './navbar/lang'; -import AlertProvider from './alerts/AlertProvider'; -import { - getAlertingAlertSelectors, - getAuthenticationAlertSelectors, - getBootstrapAlertSelectors, - getDashboardingAlertSelectors, - getIngressControllerAlertSelectors, - getK8SMasterAlertSelectors, - getLoggingAlertSelectors, - getMonitoringAlertSelectors, - getNetworksAlertSelectors, - getNodesAlertSelectors, - getPlatformAlertSelectors, - getServicesAlertSelectors, - getVolumesAlertSelectors, - useAlerts, - useHighestSeverityAlerts, -} from './alerts'; -import { useHistory } from 'react-router'; -import { useQuery, UseQueryResult } from 'react-query'; -import { loadShare } from '@module-federation/enhanced/runtime'; /** * This is a mock function to replace the real loadShare function when running tests. @@ -86,95 +61,9 @@ const loadShareModule = export const queryClient = new QueryClient(); -export type ShellTypes = { - shellHooks: { - useAuthConfig: typeof useAuthConfig; - useAuth: typeof useAuth; - useConfigRetriever: typeof useConfigRetriever; - useDiscoveredViews: typeof useDiscoveredViews; - useShellConfig: typeof useShellConfig; - useLanguage: typeof useLanguage; - useConfig: typeof useConfig; - useLinkOpener: typeof useLinkOpener; - useDeployedApps: typeof useDeployedApps; - useShellThemeSelector: typeof useShellThemeSelector; - }; - shellAlerts: { - AlertsProvider: typeof AlertProvider; - hooks: { - useAlerts: typeof useAlerts; - useHighestSeverityAlerts: typeof useHighestSeverityAlerts; - }; - alertSelectors: { - getPlatformAlertSelectors: typeof getPlatformAlertSelectors; - getNodesAlertSelectors: typeof getNodesAlertSelectors; - getVolumesAlertSelectors: typeof getVolumesAlertSelectors; - getNetworksAlertSelectors: typeof getNetworksAlertSelectors; - getServicesAlertSelectors: typeof getServicesAlertSelectors; - getK8SMasterAlertSelectors: typeof getK8SMasterAlertSelectors; - getBootstrapAlertSelectors: typeof getBootstrapAlertSelectors; - getMonitoringAlertSelectors: typeof getMonitoringAlertSelectors; - getAlertingAlertSelectors: typeof getAlertingAlertSelectors; - getLoggingAlertSelectors: typeof getLoggingAlertSelectors; - getDashboardingAlertSelectors: typeof getDashboardingAlertSelectors; - getIngressControllerAlertSelectors: typeof getIngressControllerAlertSelectors; - getAuthenticationAlertSelectors: typeof getAuthenticationAlertSelectors; - }; - }; -}; - -declare global { - interface Window { - shellContexts: { - ShellHistoryContext: React.Context | null>; - NotificationContext: React.Context; - WebFingersContext: React.Context< - | null - | UseQueryResult< - BuildtimeWebFinger | RuntimeWebFinger>, - unknown - >[] - >; - }; - shellHooks: ShellTypes['shellHooks']; - shellAlerts: ShellTypes['shellAlerts']; - } -} - -window.shellHooks = { - useAuthConfig, - useAuth, - useConfigRetriever, - useDiscoveredViews, - useShellConfig, - useLanguage, - useConfig, - useLinkOpener: useLinkOpener, - useDeployedApps: useDeployedApps, - useShellThemeSelector: useShellThemeSelector, -}; - -window.shellAlerts = { - AlertsProvider: AlertProvider, - hooks: { - useAlerts: useAlerts, - useHighestSeverityAlerts: useHighestSeverityAlerts, - }, - alertSelectors: { - getPlatformAlertSelectors: getPlatformAlertSelectors, - getNodesAlertSelectors: getNodesAlertSelectors, - getVolumesAlertSelectors: getVolumesAlertSelectors, - getNetworksAlertSelectors: getNetworksAlertSelectors, - getServicesAlertSelectors: getServicesAlertSelectors, - getK8SMasterAlertSelectors: getK8SMasterAlertSelectors, - getBootstrapAlertSelectors: getBootstrapAlertSelectors, - getMonitoringAlertSelectors: getMonitoringAlertSelectors, - getAlertingAlertSelectors: getAlertingAlertSelectors, - getLoggingAlertSelectors: getLoggingAlertSelectors, - getDashboardingAlertSelectors: getDashboardingAlertSelectors, - getIngressControllerAlertSelectors: getIngressControllerAlertSelectors, - getAuthenticationAlertSelectors: getAuthenticationAlertSelectors, - }, +export type FederatedAppProps = { + shellHooks: ShellHooks; + shellAlerts: ShellAlerts; }; function FederatedRoute({ @@ -230,6 +119,11 @@ function ProtectedFederatedRoute({ const { userData } = useAuth(); const { retrieveConfiguration } = useConfigRetriever(); + const federatedAppProps: FederatedAppProps = { + shellHooks, + shellAlerts, + }; + if ( userData && (groups?.some((group) => userData.groups.includes(group)) ?? true) @@ -242,7 +136,7 @@ function ProtectedFederatedRoute({ @@ -296,7 +190,7 @@ function InternalRouter() { [], ); return ( - + - + ); }, })), @@ -318,11 +212,11 @@ function InternalRouter() { ); return ( <> - + {routes.map((route) => ( ))} - + ); } @@ -349,7 +243,7 @@ function InternalApp() { }); return ( - + @@ -365,7 +259,7 @@ function InternalApp() { - + ); } diff --git a/shell-ui/src/NotificationCenterProvider.tsx b/shell-ui/src/NotificationCenterProvider.tsx index d1cd131136..63ed86ad38 100644 --- a/shell-ui/src/NotificationCenterProvider.tsx +++ b/shell-ui/src/NotificationCenterProvider.tsx @@ -1,4 +1,4 @@ -import React, { Dispatch, createContext, useReducer } from 'react'; +import { Dispatch, FC, ReactNode, createContext, useReducer } from 'react'; export type Notification = { id: string; @@ -18,16 +18,12 @@ export type NotificationCenterContextType = { dispatch: Dispatch; }; -if (!window.shellContexts) { - //@ts-ignore - window.shellContexts = {}; -} -if (!window.shellContexts.NotificationContext) { - window.shellContexts.NotificationContext = - createContext(null); -} export const NotificationCenterContext = - window.shellContexts.NotificationContext; + createContext(null); + +type NotificationCenterProviderProps = { + children: ReactNode; +}; export enum NotificationActionType { PUBLISH, @@ -50,7 +46,9 @@ export type NotificationCenterActions = const LOCAL_STORAGE_NOTIFICATION_PREFIX = 'notification-center__'; -const NotificationCenterProvider = ({ children }) => { +const NotificationCenterProvider: FC = ({ + children, +}) => { const notificationReducer = ( state: InternalNotification[], action: NotificationCenterActions, diff --git a/shell-ui/src/alerts/Alerts.spec.tsx b/shell-ui/src/alerts/Alerts.spec.tsx index d39000c011..f7e9e298af 100644 --- a/shell-ui/src/alerts/Alerts.spec.tsx +++ b/shell-ui/src/alerts/Alerts.spec.tsx @@ -135,7 +135,6 @@ describe('alerts', () => { ); //E - // @ts-expect-error - FIXME when you are working on it const { result, waitForNextUpdate } = renderHook(() => useAlerts(), { wrapper, }); diff --git a/shell-ui/src/alerts/alertContext.ts b/shell-ui/src/alerts/alertContext.ts index fe8b222bf4..a1647e6fc4 100644 --- a/shell-ui/src/alerts/alertContext.ts +++ b/shell-ui/src/alerts/alertContext.ts @@ -1,15 +1,3 @@ import { createContext } from 'react'; -if (!window.shellContexts) { - // @ts-expect-error - FIXME when you are working on it - window.shellContexts = {}; -} - -// @ts-expect-error - FIXME when you are working on it -if (!window.shellContexts.AlertContext) { - // @ts-expect-error - FIXME when you are working on it - window.shellContexts.AlertContext = createContext(null); -} - -// @ts-expect-error - FIXME when you are working on it -export const AlertContext = window.shellContexts.AlertContext; +export const AlertContext = createContext(null); diff --git a/shell-ui/src/alerts/alertHooks.ts b/shell-ui/src/alerts/alertHooks.ts index 8393d6dd4d..0790969b15 100644 --- a/shell-ui/src/alerts/alertHooks.ts +++ b/shell-ui/src/alerts/alertHooks.ts @@ -90,16 +90,14 @@ export const useHighestSeverityAlerts = (filters: FilterLabels): Alert[] => { * * @returns react query result */ -export function useAlerts(filters: FilterLabels) { +export function useAlerts(filters?: FilterLabels) { const query = useContext(AlertContext); if (!query) { throw new Error( 'The useAlerts hook can only be used within AlertProvider.', ); - // @ts-expect-error - FIXME when you are working on it } else if (query.status === 'success') { - // @ts-expect-error - FIXME when you are working on it const newQuery = { ...query, alerts: filterAlerts(query.data, filters) }; delete newQuery.data; return newQuery; diff --git a/shell-ui/src/auth/useFirstTimeLogin.spec.tsx b/shell-ui/src/auth/useFirstTimeLogin.spec.tsx index f918b33d18..9eb73076ff 100644 --- a/shell-ui/src/auth/useFirstTimeLogin.spec.tsx +++ b/shell-ui/src/auth/useFirstTimeLogin.spec.tsx @@ -3,6 +3,7 @@ import { useFirstTimeLogin } from './FirstTimeLoginProvider'; import { wrapper } from '../navbar/index.spec'; import { configurationHandlers } from '../FederatedApp.spec'; import { setupServer } from 'msw/node'; +import { waitFor } from '@testing-library/react'; const server = setupServer(...configurationHandlers); @@ -28,14 +29,11 @@ describe('useFirstTimeLogin hook', () => { it('should return firstTimeLogin as true if the user is logging in for the first time', async () => { //S - const { result, waitForNextUpdate } = renderHook( - () => useFirstTimeLogin(), - { wrapper }, - ); - //E - await waitForNextUpdate(); + const { result } = renderHook(() => useFirstTimeLogin(), { wrapper }); //V - expect(result.current.firstTimeLogin).toEqual(true); + await waitFor(() => { + expect(result.current.firstTimeLogin).toEqual(true); + }); }); it('should return firstTimeLogin as false if the user is NOT logging in for the first time', async () => { diff --git a/shell-ui/src/hooks/useShellHooks.ts b/shell-ui/src/hooks/useShellHooks.ts new file mode 100644 index 0000000000..fc2643f590 --- /dev/null +++ b/shell-ui/src/hooks/useShellHooks.ts @@ -0,0 +1,102 @@ +import { + useAlerts, + getPlatformAlertSelectors, + getNodesAlertSelectors, + getVolumesAlertSelectors, + getNetworksAlertSelectors, + getServicesAlertSelectors, + getK8SMasterAlertSelectors, + getBootstrapAlertSelectors, + getMonitoringAlertSelectors, + getAlertingAlertSelectors, + getLoggingAlertSelectors, + getDashboardingAlertSelectors, + getIngressControllerAlertSelectors, + getAuthenticationAlertSelectors, + useHighestSeverityAlerts, +} from '../alerts'; +import AlertProvider from '../alerts/AlertProvider'; +import { useAuthConfig } from '../auth/AuthConfigProvider'; +import { useAuth } from '../auth/AuthProvider'; +import { + useConfig, + useConfigRetriever, + useDiscoveredViews, + useLinkOpener, +} from '../initFederation/ConfigurationProviders'; +import { useShellConfig } from '../initFederation/ShellConfigProvider'; +import { useShellThemeSelector } from '../initFederation/ShellThemeSelectorProvider'; +import { useDeployedApps } from '../initFederation/UIListProvider'; +import { useLanguage } from '../navbar/lang'; + +export type ShellHooks = { + useAuthConfig: typeof useAuthConfig; + useAuth: typeof useAuth; + useConfigRetriever: typeof useConfigRetriever; + useDiscoveredViews: typeof useDiscoveredViews; + useShellConfig: typeof useShellConfig; + useLanguage: typeof useLanguage; + useConfig: typeof useConfig; + useLinkOpener: typeof useLinkOpener; + useDeployedApps: typeof useDeployedApps; + useShellThemeSelector: typeof useShellThemeSelector; +}; + +export type ShellAlerts = { + AlertsProvider: typeof AlertProvider; + alertHooks: { + useAlerts: typeof useAlerts; + useHighestSeverityAlerts: typeof useHighestSeverityAlerts; + }; + alertSelectors: { + getPlatformAlertSelectors: typeof getPlatformAlertSelectors; + getNodesAlertSelectors: typeof getNodesAlertSelectors; + getVolumesAlertSelectors: typeof getVolumesAlertSelectors; + getNetworksAlertSelectors: typeof getNetworksAlertSelectors; + getServicesAlertSelectors: typeof getServicesAlertSelectors; + getK8SMasterAlertSelectors: typeof getK8SMasterAlertSelectors; + getBootstrapAlertSelectors: typeof getBootstrapAlertSelectors; + getMonitoringAlertSelectors: typeof getMonitoringAlertSelectors; + getAlertingAlertSelectors: typeof getAlertingAlertSelectors; + getLoggingAlertSelectors: typeof getLoggingAlertSelectors; + getDashboardingAlertSelectors: typeof getDashboardingAlertSelectors; + getIngressControllerAlertSelectors: typeof getIngressControllerAlertSelectors; + getAuthenticationAlertSelectors: typeof getAuthenticationAlertSelectors; + }; +}; + +export const shellHooks: ShellHooks = { + useAuthConfig, + useAuth, + useConfigRetriever, + useDiscoveredViews, + useShellConfig, + useLanguage, + useConfig, + useLinkOpener, + useDeployedApps, + useShellThemeSelector, +}; + +export const shellAlerts: ShellAlerts = { + AlertsProvider: AlertProvider, + alertHooks: { + useAlerts, + useHighestSeverityAlerts, + }, + alertSelectors: { + getPlatformAlertSelectors, + getNodesAlertSelectors, + getVolumesAlertSelectors, + getNetworksAlertSelectors, + getServicesAlertSelectors, + getK8SMasterAlertSelectors, + getBootstrapAlertSelectors, + getMonitoringAlertSelectors, + getAlertingAlertSelectors, + getLoggingAlertSelectors, + getDashboardingAlertSelectors, + getIngressControllerAlertSelectors, + getAuthenticationAlertSelectors, + }, +}; diff --git a/shell-ui/src/index.tsx b/shell-ui/src/index.tsx index fc4c4670b4..82892eb7bd 100644 --- a/shell-ui/src/index.tsx +++ b/shell-ui/src/index.tsx @@ -1,11 +1,9 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import App, { ShellTypes } from './FederatedApp'; -import { NotificationCenterContextType } from './NotificationCenterProvider'; -import { History } from 'history'; -import { - BuildtimeWebFinger, - RuntimeWebFinger, -} from './initFederation/ConfigurationProviders'; +import { createRoot } from 'react-dom/client'; +import App from './FederatedApp'; -ReactDOM.render(, document.getElementById('app')); +const rootElement = document.getElementById('app'); + +if (rootElement) { + const root = createRoot(rootElement); + root.render(); +} diff --git a/shell-ui/src/initFederation/ConfigurationProviders.tsx b/shell-ui/src/initFederation/ConfigurationProviders.tsx index 33d1093b0f..fadaf605fe 100644 --- a/shell-ui/src/initFederation/ConfigurationProviders.tsx +++ b/shell-ui/src/initFederation/ConfigurationProviders.tsx @@ -2,27 +2,12 @@ import { ErrorPage500 } from '@scality/core-ui/dist/components/error-pages/Error import { IconName } from '@scality/core-ui/dist/components/icon/Icon.component'; import { Loader } from '@scality/core-ui/dist/components/loader/Loader.component'; import { SolutionUI } from '@scality/module-federation'; -import React, { createContext, useContext } from 'react'; +import React, { useMemo, useSyncExternalStore } from 'react'; import { useQueries, UseQueryResult } from 'react-query'; import { useShellConfig } from './ShellConfigProvider'; import { useShellHistory } from './ShellHistoryProvider'; import { useDeployedApps, useDeployedAppsRetriever } from './UIListProvider'; -if (!window.shellContexts) { - // @ts-expect-error - FIXME when you are working on it - window.shellContexts = {}; -} - -if (!window.shellContexts.WebFingersContext) { - window.shellContexts.WebFingersContext = createContext< - | null - | UseQueryResult< - BuildtimeWebFinger | RuntimeWebFinger>, - unknown - >[] - >(null); -} - export type OAuth2ProxyConfig = { kind: 'OAuth2Proxy'; //todo : add other entries }; @@ -85,10 +70,8 @@ export function useConfigRetriever(): { name: string; }) => (T extends 'build' ? BuildtimeWebFinger : RuntimeWebFinger) | null; } { + const { state: webFingerContextValue } = useWebFingersStore(); const { retrieveDeployedApps } = useDeployedAppsRetriever(); - const webFingerContextValue = useContext( - window.shellContexts.WebFingersContext, - ); if (!webFingerContextValue) { throw new Error( @@ -142,15 +125,18 @@ export function useConfig>({ configType: T extends 'build' ? 'build' : 'run'; name: string; }): null | T extends 'build' ? BuildtimeWebFinger : RuntimeWebFinger { + // Utiliser le nouveau hook useWebFingersStore + const { state: webFingerContextValue } = useWebFingersStore(); + + // Utiliser le retrieveConfiguration du hook useConfigRetriever const { retrieveConfiguration } = useConfigRetriever(); - const webFingerContextValue = useContext( - window.shellContexts.WebFingersContext, - ); - if (!webFingerContextValue) { + // Vérifier que le contexte est disponible + if (!webFingerContextValue || webFingerContextValue.length === 0) { throw new Error("Can't use useConfig outside of ConfigurationProvider"); } + // Récupérer et retourner la configuration return retrieveConfiguration({ configType, name, @@ -179,6 +165,72 @@ export type NonFederatedView = { icon?: IconName; }; export type ViewDefinition = FederatedView | NonFederatedView; + +// External store implementation +class WebFingersStore { + private listeners: Set<() => void> = new Set(); + private _state: UseQueryResult< + BuildtimeWebFinger | RuntimeWebFinger>, + unknown + >[] = []; + + subscribe = (listener: () => void) => { + this.listeners.add(listener); + return () => { + this.listeners.delete(listener); + }; + }; + + getState = () => { + return this._state; + }; + + private isStateEqual( + currentState: UseQueryResult< + BuildtimeWebFinger | RuntimeWebFinger>, + unknown + >[], + newState: UseQueryResult< + BuildtimeWebFinger | RuntimeWebFinger>, + unknown + >[], + ) { + return ( + currentState.length === newState.length && + currentState.every( + (item, index) => + JSON.stringify(item) === JSON.stringify(newState[index]), + ) + ); + } + + updateState = ( + newState: UseQueryResult< + BuildtimeWebFinger | RuntimeWebFinger>, + unknown + >[], + ) => { + if (!this.isStateEqual(this._state, newState)) { + this._state = newState; + this.listeners.forEach((listener) => listener()); + } + }; +} + +const webFingersStore = new WebFingersStore(); + +export function useWebFingersStore() { + const state = useSyncExternalStore( + webFingersStore.subscribe, + webFingersStore.getState, + ); + + return { + state, + updateWebFingersState: webFingersStore.updateState, + }; +} + export function useDiscoveredViews(): ViewDefinition[] { const { retrieveConfiguration } = useConfigRetriever(); const { retrieveDeployedApps } = useDeployedAppsRetriever(); @@ -249,7 +301,7 @@ export function useDiscoveredViews(): ViewDefinition[] { return discoveredViews; } export const useLinkOpener = () => { - const history = useShellHistory(); + const navigate = useShellHistory(); return { openLink: ( to: @@ -273,7 +325,7 @@ export const useLinkOpener = () => { window.open(to.url, '_blank'); } } else if (to.isFederated) { - history.push(to.app.appHistoryBasePath + to.view.path); + navigate(to.app.appHistoryBasePath + to.view.path); } else { // @ts-expect-error - FIXME when you are working on it window.location.href = to.url; @@ -286,6 +338,7 @@ export const ConfigurationProvider = ({ }: { children: React.ReactNode; }) => { + const { updateWebFingersState } = useWebFingersStore(); const deployedUIs = useDeployedApps(); const results = useQueries( deployedUIs.flatMap((ui) => [ @@ -323,6 +376,11 @@ export const ConfigurationProvider = ({ }, ]), ); + + useMemo(() => { + updateWebFingersState(results); + }, [results]); + const statuses = Array.from(new Set(results.map((result) => result.status))); const globalStatus = statuses.includes('error') ? 'error' @@ -333,13 +391,14 @@ export const ConfigurationProvider = ({ : statuses.includes('idle') && statuses.includes('success') ? 'loading' : 'success'; + return ( - + <> {(globalStatus === 'loading' || globalStatus === 'idle') && ( )} {globalStatus === 'error' && } {globalStatus === 'success' && children} - + ); }; diff --git a/shell-ui/src/initFederation/ShellConfigProvider.tsx b/shell-ui/src/initFederation/ShellConfigProvider.tsx index 486dcb9667..7d4b80546e 100644 --- a/shell-ui/src/initFederation/ShellConfigProvider.tsx +++ b/shell-ui/src/initFederation/ShellConfigProvider.tsx @@ -7,15 +7,7 @@ import { import React, { createContext, useContext } from 'react'; import { useQuery } from 'react-query'; -if (!window.shellContexts) { - // @ts-expect-error - FIXME when you are working on it - window.shellContexts = {}; -} -// @ts-expect-error - FIXME when you are working on it -if (!window.shellContexts.ShellConfigContext) { - // @ts-expect-error - FIXME when you are working on it - window.shellContexts.ShellConfigContext = createContext(null); -} +const ShellConfigContext = createContext(null); export type NavbarEntry = { groups?: string[]; @@ -78,10 +70,7 @@ export type ShellConfig = { }; export const useShellConfig = () => { - const contextValue = useContext( - // @ts-expect-error - FIXME when you are working on it - window.shellContexts.ShellConfigContext, - ); + const contextValue = useContext(ShellConfigContext); if (!contextValue) { throw new Error("useShellConfig can't be used outside ShellConfigProvider"); @@ -99,14 +88,13 @@ export const useShellConfig = () => { export const ShellConfigProvider = ({ shellConfigUrl, children }) => { const { data: config, status } = useQuery( 'getShellJSONConfigFile', - () => { - return fetch(shellConfigUrl).then((r) => { - if (r.ok) { - return r.json(); - } else { - return Promise.reject(); - } - }); + async () => { + const r = await fetch(shellConfigUrl); + if (r.ok) { + return r.json(); + } else { + return Promise.reject(); + } }, { refetchOnWindowFocus: false, @@ -114,8 +102,7 @@ export const ShellConfigProvider = ({ shellConfigUrl, children }) => { ); return ( - // @ts-expect-error - FIXME when you are working on it - { )} {status === 'error' && } {status === 'success' && children} - {/* @ts-expect-error - FIXME when you are working on it */} - + ); }; diff --git a/shell-ui/src/initFederation/ShellHistoryProvider.tsx b/shell-ui/src/initFederation/ShellHistoryProvider.tsx index 65ab8f9d9f..f37ae58754 100644 --- a/shell-ui/src/initFederation/ShellHistoryProvider.tsx +++ b/shell-ui/src/initFederation/ShellHistoryProvider.tsx @@ -1,22 +1,12 @@ import { createContext, useContext } from 'react'; -import { useHistory } from 'react-router'; +import { useNavigate } from 'react-router'; const ShellHistoryContext = createContext + typeof useNavigate > | null>(null); -if (!window.shellContexts) { - window.shellContexts = { - ShellHistoryContext, - ...window.shellContexts, - }; -} - -if (!window.shellContexts.ShellHistoryContext) { - window.shellContexts.ShellHistoryContext = ShellHistoryContext; -} export const useShellHistory = () => { - const contextValue = useContext(window.shellContexts.ShellHistoryContext); + const contextValue = useContext(ShellHistoryContext); if (!contextValue) { throw new Error( @@ -27,10 +17,10 @@ export const useShellHistory = () => { return contextValue; }; export const ShellHistoryProvider = ({ children }) => { - const history = useHistory(); + const history = useNavigate(); return ( - + {children} - + ); }; diff --git a/shell-ui/src/initFederation/ShellThemeSelectorProvider.tsx b/shell-ui/src/initFederation/ShellThemeSelectorProvider.tsx index b69b9be5e9..e1e095677c 100644 --- a/shell-ui/src/initFederation/ShellThemeSelectorProvider.tsx +++ b/shell-ui/src/initFederation/ShellThemeSelectorProvider.tsx @@ -13,22 +13,10 @@ type ThemeContextValues = { assets: { logoPath: string }; }; -if (!window.shellContexts) { - // @ts-expect-error - FIXME when you are working on it - window.shellContexts = {}; -} -// @ts-expect-error - FIXME when you are working on it -if (!window.shellContexts.ShellThemeContext) { - // @ts-expect-error - FIXME when you are working on it - window.shellContexts.ShellThemeContext = - React.createContext(null); -} +const ShellThemeContext = React.createContext(null); export function useShellThemeSelector(): ThemeContextValues { - const themeContext: ThemeContextValues = useContext( - // @ts-expect-error - FIXME when you are working on it - window.shellContexts.ShellThemeContext, - ); + const themeContext: ThemeContextValues = useContext(ShellThemeContext); if (themeContext === null) { throw new Error( @@ -97,8 +85,7 @@ export function ShellThemeSelectorProvider({ }; return ( - // @ts-expect-error - FIXME when you are working on it - {children(selectedTheme, themeMode)} - {/* @ts-expect-error - FIXME when you are working on it */} - + ); } diff --git a/shell-ui/src/initFederation/UIListProvider.tsx b/shell-ui/src/initFederation/UIListProvider.tsx index 7b7839a885..28e1d45053 100644 --- a/shell-ui/src/initFederation/UIListProvider.tsx +++ b/shell-ui/src/initFederation/UIListProvider.tsx @@ -5,15 +5,7 @@ import { Loader } from '@scality/core-ui/dist/components/loader/Loader.component import { ErrorPage500 } from '@scality/core-ui/dist/components/error-pages/ErrorPage500.component'; import type { SolutionUI } from '@scality/module-federation'; -if (!window.shellContexts) { - // @ts-expect-error - FIXME when you are working on it - window.shellContexts = {}; -} -// @ts-expect-error - FIXME when you are working on it -if (!window.shellContexts.UIListContext) { - // @ts-expect-error - FIXME when you are working on it - window.shellContexts.UIListContext = createContext(null); -} +const UIListContext = createContext(null); export function useDeployedAppsRetriever(): { retrieveDeployedApps: (selectors?: { @@ -21,8 +13,7 @@ export function useDeployedAppsRetriever(): { name?: string; }) => SolutionUI[]; } { - // @ts-expect-error - FIXME when you are working on it - const uiListContext = useContext(window.shellContexts.UIListContext); + const uiListContext = useContext(UIListContext); if (!uiListContext) { throw new Error( @@ -32,9 +23,7 @@ export function useDeployedAppsRetriever(): { return { retrieveDeployedApps: (selectors) => { - // @ts-expect-error - FIXME when you are working on it if (selectors && uiListContext.uis) { - // @ts-expect-error - FIXME when you are working on it return uiListContext.uis.filter((ui) => { return ( ((selectors.kind && selectors.kind === ui.kind) || @@ -43,7 +32,6 @@ export function useDeployedAppsRetriever(): { ); }); } - // @ts-expect-error - FIXME when you are working on it return uiListContext.uis || []; }, }; @@ -52,8 +40,7 @@ export const useDeployedApps = (selectors?: { kind?: string; name?: string; }): SolutionUI[] => { - // @ts-expect-error - FIXME when you are working on it - const uiListContext = useContext(window.shellContexts.UIListContext); + const uiListContext = useContext(UIListContext); if (!uiListContext) { throw new Error("Can't use useDeployedApps outside of UIListProvider"); @@ -71,22 +58,20 @@ export const UIListProvider = ({ }) => { const { status, data } = useQuery( 'discoveredUIs', - () => { - return fetch(discoveryURL, { cache: 'no-cache' }).then((r) => { - if (r.ok) { - return r.json(); - } else { - return Promise.reject(); - } - }); + async () => { + const r = await fetch(discoveryURL, { cache: 'no-cache' }); + if (r.ok) { + return r.json(); + } else { + return Promise.reject(); + } }, { refetchOnWindowFocus: false, }, ); return ( - // @ts-expect-error - FIXME when you are working on it - } {status === 'success' && children} - {/* @ts-expect-error - FIXME when you are working on it */} - + ); }; diff --git a/shell-ui/src/navbar/NavBar.tsx b/shell-ui/src/navbar/NavBar.tsx index 2dad490330..adf1ff2519 100644 --- a/shell-ui/src/navbar/NavBar.tsx +++ b/shell-ui/src/navbar/NavBar.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useEffect, useMemo } from 'react'; -import { RouteProps, matchPath, useHistory } from 'react-router'; +import { RouteProps, matchPath, useNavigate } from 'react-router'; import { useLocation } from 'react-router-dom'; import styled, { createGlobalStyle } from 'styled-components'; @@ -155,7 +155,7 @@ export const useNavbarLinksToActions = ( const location = useLocation(); const doesRouteMatch = useCallback( (path: RouteProps) => { - return matchPath(location.pathname, path); + return matchPath(location.pathname, path.path); }, [location], ); @@ -188,9 +188,6 @@ export const useNavbarLinksToActions = ( 'i', ).toString() : link.view.app.appHistoryBasePath + link.view.view.path, - exact: link.view.view.exact, - strict: link.view.view.strict, - sensitive: link.view.view.sensitive, }) : normalizePath((link.view as NonFederatedView).url) === window.location.origin + window.location.pathname, @@ -261,7 +258,7 @@ export const Navbar = ({ const { openLink } = useLinkOpener(); const { logOut } = useLogOut(); const { getLinks } = useNavbar(); - const history = useHistory(); + const navigate = useNavigate(); const navbarLinks = useMemo(() => getLinks(), [getLinks]); const navbarMainActions = useNavbarLinksToActions(navbarLinks.main); const navbarSecondaryActions = useNavbarLinksToActions(navbarLinks.secondary); @@ -303,7 +300,7 @@ export const Navbar = ({ const url = link.view.isFederated ? link.view.app.appHistoryBasePath + link.view.view.path : (link.view as NonFederatedView).url; - history.replace(url); + navigate(url, { replace: true }); } }, [navbarMainActions]); diff --git a/shell-ui/src/navbar/NotificationCenter.spec.tsx b/shell-ui/src/navbar/NotificationCenter.spec.tsx index 5b4d385399..f53a611c50 100644 --- a/shell-ui/src/navbar/NotificationCenter.spec.tsx +++ b/shell-ui/src/navbar/NotificationCenter.spec.tsx @@ -8,7 +8,7 @@ import NotificationCenter from './NotificationCenter'; import userEvent from '@testing-library/user-event'; import { QueryClient, QueryClientProvider } from 'react-query'; import { prepareRenderMultipleHooks } from './__TESTS__/testMultipleHooks'; -import { MemoryRouter, Route, Switch } from 'react-router-dom'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; import { ShellHistoryProvider } from '../initFederation/ShellHistoryProvider'; import { useNotificationCenter } from '../useNotificationCenter'; @@ -33,14 +33,12 @@ describe('NotificationCenter', () => {
{children}
- - - Home page - + + Home page Alert page License page New version page - +
diff --git a/shell-ui/src/navbar/NotificationCenter.tsx b/shell-ui/src/navbar/NotificationCenter.tsx index dfc5e033fc..36d0ecb336 100644 --- a/shell-ui/src/navbar/NotificationCenter.tsx +++ b/shell-ui/src/navbar/NotificationCenter.tsx @@ -103,14 +103,14 @@ const NotificationCenter = () => { if (!selectedItem) { return; } - history.push(selectedItem.redirectUrl); + navigate(selectedItem.redirectUrl); readAllNotifications(); }, }); const isAtLeastOneNotificationUnread = notifications.some( (notification) => !notification.readOn, ); - const history = useShellHistory(); + const navigate = useShellHistory(); return (
( }; export function prepareRenderMultipleHooks(options: { - wrapper: FunctionComponent>>; + wrapper: FunctionComponent>>>; }): { renderAdditionalHook: RenderAdditionalHook; waitForWrapperToBeReady: () => Promise; diff --git a/shell-ui/src/navbar/index.spec.tsx b/shell-ui/src/navbar/index.spec.tsx index 812fead4ca..f25e4d74da 100644 --- a/shell-ui/src/navbar/index.spec.tsx +++ b/shell-ui/src/navbar/index.spec.tsx @@ -5,9 +5,8 @@ import React from 'react'; import { QueryClient, QueryClientProvider } from 'react-query'; import { MemoryRouter } from 'react-router'; -import { render, screen } from '@testing-library/react'; +import { render, screen, waitFor, act } from '@testing-library/react'; import { useAuth } from 'oidc-react'; -import { act } from 'react-test-renderer'; import { SolutionsNavbar } from '.'; import { WithInitFederationProviders } from '../FederatedApp'; import { configurationHandlers } from '../FederatedApp.spec'; @@ -128,77 +127,99 @@ describe('useNavbar', () => { }; it('should retrieve navbar configuration', async () => { //E - const { result, waitForNextUpdate } = renderHook(() => useNavbar(), { + const { result } = renderHook(() => useNavbar(), { wrapper, }); - await waitForNextUpdate(); - //V - expect(result.current.getLinks()).toStrictEqual(expectedDefaultNavbarLinks); + await waitFor(() => { + expect(result.current.getLinks()).toStrictEqual( + expectedDefaultNavbarLinks, + ); + }); }); it('should set main navbar links', async () => { //S - const { result, waitForNextUpdate } = renderHook(() => useNavbar(), { + const { result } = renderHook(() => useNavbar(), { wrapper, }); - await act(() => waitForNextUpdate()); + await waitFor(() => { + expect(result.current.setMainLinks).toBeDefined(); + }); + //E act(() => // @ts-expect-error - FIXME when you are working on it result.current.setMainLinks([expectedDefaultNavbarLinks.main[0]]), ); + //V - expect(result.current.getLinks()).toStrictEqual({ - ...expectedDefaultNavbarLinks, - main: [expectedDefaultNavbarLinks.main[0]], + await waitFor(() => { + expect(result.current.getLinks()).toStrictEqual({ + ...expectedDefaultNavbarLinks, + main: [expectedDefaultNavbarLinks.main[0]], + }); }); }); it('should set secondary navbar links', async () => { //S - const { result, waitForNextUpdate } = renderHook(() => useNavbar(), { + const { result } = renderHook(() => useNavbar(), { wrapper, }); - await waitForNextUpdate(); + + await waitFor(() => { + expect(result.current.setSecondaryLinks).toBeDefined(); + }); //E act(() => // @ts-expect-error - FIXME when you are working on it result.current.setSecondaryLinks([expectedDefaultNavbarLinks.main[0]]), ); //V - expect(result.current.getLinks()).toStrictEqual({ - ...expectedDefaultNavbarLinks, - secondary: [expectedDefaultNavbarLinks.main[0]], + await waitFor(() => { + expect(result.current.getLinks()).toStrictEqual({ + ...expectedDefaultNavbarLinks, + secondary: [expectedDefaultNavbarLinks.main[0]], + }); }); }); it('should set user dropdown links', async () => { //S - const { result, waitForNextUpdate } = renderHook(() => useNavbar(), { + const { result } = renderHook(() => useNavbar(), { wrapper, }); - await waitForNextUpdate(); //E + await waitFor(() => { + expect(result.current.setUserDropdownLinks).toBeDefined(); + }); act(() => // @ts-expect-error - FIXME when you are working on it result.current.setUserDropdownLinks([expectedDefaultNavbarLinks.main[0]]), ); //V - expect(result.current.getLinks()).toStrictEqual({ - ...expectedDefaultNavbarLinks, - userDropdown: [expectedDefaultNavbarLinks.main[0]], + await waitFor(() => { + expect(result.current.getLinks()).toStrictEqual({ + ...expectedDefaultNavbarLinks, + userDropdown: [expectedDefaultNavbarLinks.main[0]], + }); }); }); it('should set logo link', async () => { //S - const { result, waitForNextUpdate } = renderHook(() => useNavbar(), { + const { result } = renderHook(() => useNavbar(), { wrapper, }); - await waitForNextUpdate(); //E + await waitFor(() => { + expect(result.current.setLogoLink).toBeDefined(); + }); + act(() => result.current.setLogoLink('http://localhost:3000')); //V - expect(result.current.getLinks()).toStrictEqual({ - ...expectedDefaultNavbarLinks, - logoHref: 'http://localhost:3000', + await waitFor(() => { + expect(result.current.getLinks()).toStrictEqual({ + ...expectedDefaultNavbarLinks, + logoHref: 'http://localhost:3000', + }); }); }); it('should display the Notification Center for Platform Admin', async () => { diff --git a/shell-ui/src/navbar/lang.tsx b/shell-ui/src/navbar/lang.tsx index b51cea7f53..5da8ab569b 100644 --- a/shell-ui/src/navbar/lang.tsx +++ b/shell-ui/src/navbar/lang.tsx @@ -9,15 +9,7 @@ import translations_en from './translations/en.json'; import translations_fr from './translations/fr.json'; import { LANGUAGE_CHANGED_EVENT } from './events'; -if (!window.shellContexts) { - // @ts-expect-error - FIXME when you are working on it - window.shellContexts = {}; -} -// @ts-expect-error - FIXME when you are working on it -if (!window.shellContexts.LanguageContext) { - // @ts-expect-error - FIXME when you are working on it - window.shellContexts.LanguageContext = createContext(null); -} +const LanguageContext = createContext(null); type Language = 'en' | 'fr'; export const languages: Language[] = ['en', 'fr']; @@ -30,8 +22,7 @@ export function useLanguage(): { setLanguage: (language: Language) => void; unSelectedLanguages: Language[]; } { - // @ts-expect-error - FIXME when you are working on it - const languageContext = useContext(window.shellContexts.LanguageContext); + const languageContext = useContext(LanguageContext); if (languageContext === null) { throw new Error( @@ -40,12 +31,9 @@ export function useLanguage(): { } return { - // @ts-expect-error - FIXME when you are working on it language: languageContext.language, - // @ts-expect-error - FIXME when you are working on it setLanguage: languageContext.setLanguage, unSelectedLanguages: languages.filter( - // @ts-expect-error - FIXME when you are working on it (lang) => lang !== languageContext.language, ), }; @@ -81,8 +69,7 @@ export function LanguageProvider({ }; return ( - // @ts-expect-error - FIXME when you are working on it - {children} - {/* @ts-expect-error - FIXME when you are working on it */} - + ); } diff --git a/shell-ui/src/navbar/navbarContext.ts b/shell-ui/src/navbar/navbarContext.ts index 74865b34e9..018b9f1782 100644 --- a/shell-ui/src/navbar/navbarContext.ts +++ b/shell-ui/src/navbar/navbarContext.ts @@ -2,16 +2,4 @@ import { createContext } from 'react'; import type { Navbar } from './navbarHooks'; import './navbarHooks'; -if (!window.shellContexts) { - // @ts-expect-error - FIXME when you are working on it - window.shellContexts = {}; -} - -// @ts-expect-error - FIXME when you are working on it -if (!window.shellContexts.NavbarContext) { - // @ts-expect-error - FIXME when you are working on it - window.shellContexts.NavbarContext = createContext(null); -} - -// @ts-expect-error - FIXME when you are working on it -export const NavbarContext = window.shellContexts.NavbarContext; +export const NavbarContext = createContext(null); diff --git a/shell-ui/src/navbar/navbarHooks.ts b/shell-ui/src/navbar/navbarHooks.ts index a1a86305d4..f30556fecc 100644 --- a/shell-ui/src/navbar/navbarHooks.ts +++ b/shell-ui/src/navbar/navbarHooks.ts @@ -27,6 +27,5 @@ export const useNavbar = (): Navbar => { throw new Error("Can't use useNavbar outside of NavbarConfigProvider"); } - // @ts-expect-error - FIXME when you are working on it return navbar; }; diff --git a/ui/package-lock.json b/ui/package-lock.json index 88fb780ef1..9ce6463490 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -12,8 +12,8 @@ "@hookform/resolvers": "^3.1.0", "@js-temporal/polyfill": "^0.4.4", "@kubernetes/client-node": "github:scality/kubernetes-client-javascript.git#browser-0.10.4-64-ge7c6721", - "@scality/core-ui": "0.151.0", - "@scality/module-federation": "^1.3.4", + "@scality/core-ui": "git+https://github.com/scality/core-ui#bf0c36da657737f47dabe310bb1a20c136877970", + "@scality/module-federation": "git+https://github.com/scality/module-federation#c571388783a2a51ae3bf5d36ae66753c8b014bb5", "axios": "^0.21.1", "formik": "2.2.5", "jsonpath": "^1.1.1", @@ -21,20 +21,20 @@ "lodash.isequal": "^4.5.0", "lodash.sortby": "^4.7.0", "luxon": "^2.1.1", - "react": "^17.0.1", - "react-dom": "^17.0.1", - "react-error-boundary": "^3.1.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-error-boundary": "^4.1.2", "react-hook-form": "^7.44.3", "react-intl": "^5.15.3", "react-json-view": "^1.21.3", "react-query": "^3.34.0", "react-redux": "^7.1.0", - "react-router": "5.2.0", - "react-router-dom": "5.2.0", + "react-router": "^6.28.0", + "react-router-dom": "^6.28.0", "redux": "^4.0.1", "redux-saga": "^1.0.2", "reselect": "^2.5.4", - "styled-components": "^5.0.1", + "styled-components": "^5.3.11", "uuid": "3.3.2", "yup": "^0.32.9" }, @@ -50,7 +50,7 @@ "@rspack/core": "^0.7.5", "@testing-library/dom": "^9.3.1", "@testing-library/jest-dom": "^5.11.9", - "@testing-library/react": "^11.2.3", + "@testing-library/react": "^15.0.7", "@testing-library/react-hooks": "^3.4.2", "@testing-library/user-event": "^14.4.3", "@types/hapi__joi": "^17.1.9", @@ -58,10 +58,13 @@ "@types/lodash.isempty": "^4.4.7", "@types/lodash.isequal": "^4.5.6", "@types/lodash.sortby": "^4.7.7", + "@types/react": "^18.3.12", + "@types/react-dom": "^18.3.1", "@types/react-redux": "^7.1.25", "@types/react-router": "^5.1.20", "@types/react-router-dom": "^5.3.3", - "@types/styled-components": "^5.1.26", + "@types/react-test-renderer": "^18.3.0", + "@types/styled-components": "^5.1.34", "@typescript-eslint/eslint-plugin": "^5.62.0", "babel-eslint": "^10.1.0", "babel-jest": "^26.6.3", @@ -84,7 +87,7 @@ "jest-preview": "^0.3.1", "msw": "0.36.8", "oidc-client": "^1.8.0", - "react-test-renderer": "^17.0.1", + "react-test-renderer": "^18.3.1", "ts-node": "^10.9.2", "typescript": "^5.3.3" }, @@ -2637,13 +2640,15 @@ "node_modules/@emotion/is-prop-valid": { "version": "0.8.8", "license": "MIT", + "optional": true, "dependencies": { "@emotion/memoize": "0.7.4" } }, "node_modules/@emotion/memoize": { "version": "0.7.4", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/@emotion/react": { "version": "11.11.3", @@ -5209,6 +5214,14 @@ "version": "1.1.0", "license": "MIT" }, + "node_modules/@remix-run/router": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.21.0.tgz", + "integrity": "sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rspack/binding": { "version": "0.7.5", "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-0.7.5.tgz", @@ -5532,8 +5545,9 @@ }, "node_modules/@scality/core-ui": { "version": "0.151.0", - "resolved": "https://registry.npmjs.org/@scality/core-ui/-/core-ui-0.151.0.tgz", - "integrity": "sha512-OeAhs+uiOOBDSGqzZGpIka1iCtRrGJkjNhzdRJhJtLwxKDFU7iyPUPA3MbJ8DoGJQN0do8k3PTyei1fZEiMXJA==", + "resolved": "git+ssh://git@github.com/scality/core-ui.git#bf0c36da657737f47dabe310bb1a20c136877970", + "integrity": "sha512-dC/zNxvxU7DVgxhbyKHgwwVyM2CwWACrwyVbh1VP0/7KTcgTmoYR2hO9qAMi9t8yyNWidOi9AVVzKupes13wRw==", + "license": "SEE LICENSE IN LICENSE", "dependencies": { "@floating-ui/dom": "^1.6.3", "@fortawesome/fontawesome-free": "^5.10.2", @@ -5547,9 +5561,9 @@ "framer-motion": "^4.1.17", "polished": "3.4.1", "pretty-bytes": "^5.6.0", - "react": "^17.0.2", + "react": "^18.3.1", "react-debounce-input": "3.2.2", - "react-dom": "^17.0.2", + "react-dom": "^18.3.1", "react-dropzone": "^14.2.3", "react-hook-form": "^7.49.2", "react-query": "^3.34.0", @@ -5557,6 +5571,7 @@ "react-router-dom": "5.2.0", "react-select": "4.3.1", "react-table": "^7.7.0", + "react-test-renderer": "^18.3.1", "react-virtualized": "9.22.3", "react-virtualized-auto-sizer": "^1.0.24", "react-window": "^1.8.6", @@ -5585,13 +5600,51 @@ "@floating-ui/utils": "^0.2.0" } }, + "node_modules/@scality/core-ui/node_modules/react-router": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", + "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "dependencies": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "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" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/@scality/core-ui/node_modules/react-router-dom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz", + "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==", + "dependencies": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.2.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, "node_modules/@scality/module-federation": { "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@scality/module-federation/-/module-federation-1.3.4.tgz", - "integrity": "sha512-Okmgh+s9UTM6ropLt5QIJhswaN3m0hGNjGI2w/al+a4H+fQs5x/rAYngzWhFnHxdox0RUSRwA7aOZH1fBAvnmA==", + "resolved": "git+ssh://git@github.com/scality/module-federation.git#c571388783a2a51ae3bf5d36ae66753c8b014bb5", + "integrity": "sha512-lrpXm7Skkq/CtGQRI563pSelewbeNaBBbs3J4zzCiheb0H2fSs6JF6lqQHQjL9A0HRVjfnArotXlF8E8JzVtnw==", + "license": "SEE LICENSE IN LICENSE", "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^18.3.1", + "react-dom": "^18.3.1" } }, "node_modules/@sinclair/typebox": { @@ -5628,9 +5681,9 @@ } }, "node_modules/@storybook/preview-api": { - "version": "8.4.4", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.4.4.tgz", - "integrity": "sha512-iZrWQcjRBqBHFdDXVxGpw6mHBZMCMYqhWXdyJ0d1S2y3PwcfOjkcXlQ1UiAenFHlA6dKrcYw8luKUQTL9bKReA==", + "version": "8.4.5", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.4.5.tgz", + "integrity": "sha512-MKIZ2jQO/3cUdsT57eq8jRgB6inALo9BxrQ88f7mqzltOkMvADvTAY6y8JZqTUoDzWTH/ny/8SGGdtpqlxRuiQ==", "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" @@ -6196,19 +6249,27 @@ } }, "node_modules/@testing-library/react": { - "version": "11.2.5", + "version": "15.0.7", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-15.0.7.tgz", + "integrity": "sha512-cg0RvEdD1TIhhkm1IeYMQxrzy0MtUNfa3minv4MjbgcYzJAZ7yD0i0lwoPOTPr+INtiXFezt2o8xMSnyHhEn2Q==", "dev": true, - "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^7.28.1" + "@testing-library/dom": "^10.0.0", + "@types/react-dom": "^18.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "peerDependencies": { - "react": "*", - "react-dom": "*" + "@types/react": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, "node_modules/@testing-library/react-hooks": { @@ -6224,54 +6285,32 @@ "react-test-renderer": ">=16.9.0" } }, - "node_modules/@testing-library/react/node_modules/@jest/types": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", - "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, "node_modules/@testing-library/react/node_modules/@testing-library/dom": { - "version": "7.31.2", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.31.2.tgz", - "integrity": "sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", - "@types/aria-query": "^4.2.0", - "aria-query": "^4.2.2", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.6", - "lz-string": "^1.4.4", - "pretty-format": "^26.6.2" + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@testing-library/react/node_modules/@types/aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==", - "dev": true - }, - "node_modules/@testing-library/react/node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "node_modules/@testing-library/react/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "dev": true, "dependencies": { - "@types/istanbul-lib-report": "*" + "dequal": "^2.0.3" } }, "node_modules/@testing-library/react/node_modules/chalk": { @@ -6291,18 +6330,29 @@ } }, "node_modules/@testing-library/react/node_modules/pretty-format": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", - "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "dependencies": { - "@jest/types": "^26.6.2", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", "react-is": "^17.0.1" }, "engines": { - "node": ">= 10" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@testing-library/react/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/@testing-library/react/node_modules/react-is": { @@ -6739,14 +6789,23 @@ "dev": true }, "node_modules/@types/react": { - "version": "17.0.3", - "license": "MIT", + "version": "18.3.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", + "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", "dependencies": { "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, + "node_modules/@types/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-redux": { "version": "7.1.25", "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.25.tgz", @@ -6781,9 +6840,10 @@ } }, "node_modules/@types/react-test-renderer": { - "version": "17.0.1", + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-18.3.0.tgz", + "integrity": "sha512-HW4MuEYxfDbOHQsVlY/XtOvNHftCVEPhJF2pQXXwcUiUF+Oyb0usgp48HSgpK5rt8m9KZb22yqOeZm+rrVG8gw==", "dev": true, - "license": "MIT", "dependencies": { "@types/react": "*" } @@ -6804,10 +6864,6 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, - "node_modules/@types/scheduler": { - "version": "0.16.1", - "license": "MIT" - }, "node_modules/@types/semver": { "version": "7.3.13", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", @@ -6861,9 +6917,9 @@ } }, "node_modules/@types/styled-components": { - "version": "5.1.26", - "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.26.tgz", - "integrity": "sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==", + "version": "5.1.34", + "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.34.tgz", + "integrity": "sha512-mmiVvwpYklFIv9E8qfxuPyIt/OuyIrn6gMOAMOFUO3WJfSrSE+sGUoa4PiZj77Ut7bKZpaa6o1fBKS/4TOEvnA==", "dev": true, "dependencies": { "@types/hoist-non-react-statics": "*", @@ -11968,6 +12024,15 @@ "deps-sort": "bin/cmd.js" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/des.js": { "version": "1.0.1", "license": "MIT", @@ -16035,7 +16100,8 @@ }, "node_modules/isarray": { "version": "0.0.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" }, "node_modules/isexe": { "version": "2.0.0", @@ -21328,7 +21394,9 @@ }, "node_modules/mini-create-react-context": { "version": "0.4.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", + "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "dependencies": { "@babel/runtime": "^7.12.1", "tiny-warning": "^1.0.3" @@ -22374,8 +22442,9 @@ } }, "node_modules/path-to-regexp": { - "version": "1.8.0", - "license": "MIT", + "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" } @@ -22939,12 +23008,11 @@ } }, "node_modules/react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" }, "engines": { "node": ">=0.10.0" @@ -22973,16 +23041,15 @@ } }, "node_modules/react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "dependencies": { "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" + "scheduler": "^0.23.2" }, "peerDependencies": { - "react": "17.0.2" + "react": "^18.3.1" } }, "node_modules/react-dropzone": { @@ -23002,15 +23069,12 @@ } }, "node_modules/react-error-boundary": { - "version": "3.1.1", - "license": "MIT", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.1.2.tgz", + "integrity": "sha512-GQDxZ5Jd+Aq/qUxbCm1UtzmL/s++V7zKgE8yMktJiCQXCCFZnMZh9ng+6/Ne6PjNSXH0L9CjeOEREfRnq6Duag==", "dependencies": { "@babel/runtime": "^7.12.5" }, - "engines": { - "node": ">=10", - "npm": ">=6" - }, "peerDependencies": { "react": ">=16.13.1" } @@ -23166,38 +23230,33 @@ } }, "node_modules/react-router": { - "version": "5.2.0", - "license": "MIT", + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.0.tgz", + "integrity": "sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==", "dependencies": { - "@babel/runtime": "^7.1.2", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "mini-create-react-context": "^0.4.0", - "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" + "@remix-run/router": "1.21.0" + }, + "engines": { + "node": ">=14.0.0" }, "peerDependencies": { - "react": ">=15" + "react": ">=16.8" } }, "node_modules/react-router-dom": { - "version": "5.2.0", - "license": "MIT", + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.28.0.tgz", + "integrity": "sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==", "dependencies": { - "@babel/runtime": "^7.1.2", - "history": "^4.9.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-router": "5.2.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "@remix-run/router": "1.21.0", + "react-router": "6.28.0" + }, + "engines": { + "node": ">=14.0.0" }, "peerDependencies": { - "react": ">=15" + "react": ">=16.8", + "react-dom": ">=16.8" } }, "node_modules/react-select": { @@ -23219,15 +23278,15 @@ } }, "node_modules/react-shallow-renderer": { - "version": "16.14.1", - "dev": true, - "license": "MIT", + "version": "16.15.0", + "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", + "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", "dependencies": { "object-assign": "^4.1.1", - "react-is": "^16.12.0 || ^17.0.0" + "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" }, "peerDependencies": { - "react": "^16.0.0 || ^17.0.0" + "react": "^16.0.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/react-table": { @@ -23243,23 +23302,22 @@ } }, "node_modules/react-test-renderer": { - "version": "17.0.1", - "dev": true, - "license": "MIT", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-18.3.1.tgz", + "integrity": "sha512-KkAgygexHUkQqtvvx/otwxtuFu5cVjfzTCtjXLH9boS19/Nbtg84zS7wIQn39G8IlrhThBpQsMKkq5ZHZIYFXA==", "dependencies": { - "object-assign": "^4.1.1", - "react-is": "^17.0.1", - "react-shallow-renderer": "^16.13.1", - "scheduler": "^0.20.1" + "react-is": "^18.3.1", + "react-shallow-renderer": "^16.15.0", + "scheduler": "^0.23.2" }, "peerDependencies": { - "react": "17.0.1" + "react": "^18.3.1" } }, "node_modules/react-test-renderer/node_modules/react-is": { - "version": "17.0.1", - "dev": true, - "license": "MIT" + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, "node_modules/react-textarea-autosize": { "version": "8.3.2", @@ -24066,12 +24124,11 @@ } }, "node_modules/scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" } }, "node_modules/schema-utils": { @@ -25308,15 +25365,16 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/styled-components": { - "version": "5.2.1", - "license": "MIT", + "version": "5.3.11", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.11.tgz", + "integrity": "sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==", "dependencies": { "@babel/helper-module-imports": "^7.0.0", "@babel/traverse": "^7.4.5", - "@emotion/is-prop-valid": "^0.8.8", + "@emotion/is-prop-valid": "^1.1.0", "@emotion/stylis": "^0.8.4", "@emotion/unitless": "^0.7.4", - "babel-plugin-styled-components": ">= 1", + "babel-plugin-styled-components": ">= 1.12.0", "css-to-react-native": "^3.0.0", "hoist-non-react-statics": "^3.0.0", "shallowequal": "^1.1.0", @@ -25335,6 +25393,19 @@ "react-is": ">= 16.8.0" } }, + "node_modules/styled-components/node_modules/@emotion/is-prop-valid": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz", + "integrity": "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/styled-components/node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" + }, "node_modules/styled-components/node_modules/has-flag": { "version": "3.0.0", "license": "MIT", @@ -29891,12 +29962,14 @@ }, "@emotion/is-prop-valid": { "version": "0.8.8", + "optional": true, "requires": { "@emotion/memoize": "0.7.4" } }, "@emotion/memoize": { - "version": "0.7.4" + "version": "0.7.4", + "optional": true }, "@emotion/react": { "version": "11.11.3", @@ -31946,6 +32019,11 @@ "@redux-saga/types": { "version": "1.1.0" }, + "@remix-run/router": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.21.0.tgz", + "integrity": "sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==" + }, "@rspack/binding": { "version": "0.7.5", "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-0.7.5.tgz", @@ -32152,9 +32230,9 @@ } }, "@scality/core-ui": { - "version": "0.151.0", - "resolved": "https://registry.npmjs.org/@scality/core-ui/-/core-ui-0.151.0.tgz", - "integrity": "sha512-OeAhs+uiOOBDSGqzZGpIka1iCtRrGJkjNhzdRJhJtLwxKDFU7iyPUPA3MbJ8DoGJQN0do8k3PTyei1fZEiMXJA==", + "version": "git+ssh://git@github.com/scality/core-ui.git#bf0c36da657737f47dabe310bb1a20c136877970", + "integrity": "sha512-dC/zNxvxU7DVgxhbyKHgwwVyM2CwWACrwyVbh1VP0/7KTcgTmoYR2hO9qAMi9t8yyNWidOi9AVVzKupes13wRw==", + "from": "@scality/core-ui@git+https://github.com/scality/core-ui#bf0c36da657737f47dabe310bb1a20c136877970", "requires": { "@floating-ui/dom": "^1.6.3", "@fortawesome/fontawesome-free": "^5.10.2", @@ -32168,9 +32246,9 @@ "framer-motion": "^4.1.17", "polished": "3.4.1", "pretty-bytes": "^5.6.0", - "react": "^17.0.2", + "react": "^18.3.1", "react-debounce-input": "3.2.2", - "react-dom": "^17.0.2", + "react-dom": "^18.3.1", "react-dropzone": "^14.2.3", "react-hook-form": "^7.49.2", "react-query": "^3.34.0", @@ -32178,6 +32256,7 @@ "react-router-dom": "5.2.0", "react-select": "4.3.1", "react-table": "^7.7.0", + "react-test-renderer": "^18.3.1", "react-virtualized": "9.22.3", "react-virtualized-auto-sizer": "^1.0.24", "react-window": "^1.8.6", @@ -32205,13 +32284,44 @@ "@floating-ui/core": "^1.0.0", "@floating-ui/utils": "^0.2.0" } + }, + "react-router": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", + "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "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" + } + }, + "react-router-dom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz", + "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.2.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } } } }, "@scality/module-federation": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@scality/module-federation/-/module-federation-1.3.4.tgz", - "integrity": "sha512-Okmgh+s9UTM6ropLt5QIJhswaN3m0hGNjGI2w/al+a4H+fQs5x/rAYngzWhFnHxdox0RUSRwA7aOZH1fBAvnmA==" + "version": "git+ssh://git@github.com/scality/module-federation.git#c571388783a2a51ae3bf5d36ae66753c8b014bb5", + "integrity": "sha512-lrpXm7Skkq/CtGQRI563pSelewbeNaBBbs3J4zzCiheb0H2fSs6JF6lqQHQjL9A0HRVjfnArotXlF8E8JzVtnw==", + "from": "@scality/module-federation@git+https://github.com/scality/module-federation#c571388783a2a51ae3bf5d36ae66753c8b014bb5" }, "@sinclair/typebox": { "version": "0.27.8", @@ -32246,9 +32356,9 @@ } }, "@storybook/preview-api": { - "version": "8.4.4", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.4.4.tgz", - "integrity": "sha512-iZrWQcjRBqBHFdDXVxGpw6mHBZMCMYqhWXdyJ0d1S2y3PwcfOjkcXlQ1UiAenFHlA6dKrcYw8luKUQTL9bKReA==" + "version": "8.4.5", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.4.5.tgz", + "integrity": "sha512-MKIZ2jQO/3cUdsT57eq8jRgB6inALo9BxrQ88f7mqzltOkMvADvTAY6y8JZqTUoDzWTH/ny/8SGGdtpqlxRuiQ==" }, "@styled-system/background": { "version": "5.1.2", @@ -32628,55 +32738,39 @@ } }, "@testing-library/react": { - "version": "11.2.5", + "version": "15.0.7", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-15.0.7.tgz", + "integrity": "sha512-cg0RvEdD1TIhhkm1IeYMQxrzy0MtUNfa3minv4MjbgcYzJAZ7yD0i0lwoPOTPr+INtiXFezt2o8xMSnyHhEn2Q==", "dev": true, "requires": { "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^7.28.1" + "@testing-library/dom": "^10.0.0", + "@types/react-dom": "^18.0.0" }, "dependencies": { - "@jest/types": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", - "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" - } - }, "@testing-library/dom": { - "version": "7.31.2", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.31.2.tgz", - "integrity": "sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", - "@types/aria-query": "^4.2.0", - "aria-query": "^4.2.2", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.6", - "lz-string": "^1.4.4", - "pretty-format": "^26.6.2" + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" } }, - "@types/aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==", - "dev": true - }, - "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "dev": true, "requires": { - "@types/istanbul-lib-report": "*" + "dequal": "^2.0.3" } }, "chalk": { @@ -32690,15 +32784,22 @@ } }, "pretty-format": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", - "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "requires": { - "@jest/types": "^26.6.2", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } } }, "react-is": { @@ -33104,13 +33205,23 @@ "dev": true }, "@types/react": { - "version": "17.0.3", + "version": "18.3.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", + "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", "requires": { "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, + "@types/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, "@types/react-redux": { "version": "7.1.25", "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.25.tgz", @@ -33145,7 +33256,9 @@ } }, "@types/react-test-renderer": { - "version": "17.0.1", + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-18.3.0.tgz", + "integrity": "sha512-HW4MuEYxfDbOHQsVlY/XtOvNHftCVEPhJF2pQXXwcUiUF+Oyb0usgp48HSgpK5rt8m9KZb22yqOeZm+rrVG8gw==", "dev": true, "requires": { "@types/react": "*" @@ -33166,9 +33279,6 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, - "@types/scheduler": { - "version": "0.16.1" - }, "@types/semver": { "version": "7.3.13", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", @@ -33219,9 +33329,9 @@ } }, "@types/styled-components": { - "version": "5.1.26", - "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.26.tgz", - "integrity": "sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==", + "version": "5.1.34", + "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.34.tgz", + "integrity": "sha512-mmiVvwpYklFIv9E8qfxuPyIt/OuyIrn6gMOAMOFUO3WJfSrSE+sGUoa4PiZj77Ut7bKZpaa6o1fBKS/4TOEvnA==", "dev": true, "requires": { "@types/hoist-non-react-statics": "*", @@ -36854,6 +36964,12 @@ "through2": "^2.0.0" } }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true + }, "des.js": { "version": "1.0.1", "optional": true, @@ -39786,7 +39902,9 @@ "dev": true }, "isarray": { - "version": "0.0.1" + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" }, "isexe": { "version": "2.0.0" @@ -43719,6 +43837,8 @@ }, "mini-create-react-context": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", + "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", "requires": { "@babel/runtime": "^7.12.1", "tiny-warning": "^1.0.3" @@ -44450,7 +44570,9 @@ "optional": true }, "path-to-regexp": { - "version": "1.8.0", + "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==", "requires": { "isarray": "0.0.1" } @@ -44850,12 +44972,11 @@ } }, "react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" } }, "react-base16-styling": { @@ -44877,13 +44998,12 @@ } }, "react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "requires": { "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" + "scheduler": "^0.23.2" } }, "react-dropzone": { @@ -44897,7 +45017,9 @@ } }, "react-error-boundary": { - "version": "3.1.1", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.1.2.tgz", + "integrity": "sha512-GQDxZ5Jd+Aq/qUxbCm1UtzmL/s++V7zKgE8yMktJiCQXCCFZnMZh9ng+6/Ne6PjNSXH0L9CjeOEREfRnq6Duag==", "requires": { "@babel/runtime": "^7.12.5" } @@ -44985,30 +45107,20 @@ } }, "react-router": { - "version": "5.2.0", + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.0.tgz", + "integrity": "sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==", "requires": { - "@babel/runtime": "^7.1.2", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "mini-create-react-context": "^0.4.0", - "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" + "@remix-run/router": "1.21.0" } }, "react-router-dom": { - "version": "5.2.0", + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.28.0.tgz", + "integrity": "sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==", "requires": { - "@babel/runtime": "^7.1.2", - "history": "^4.9.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-router": "5.2.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "@remix-run/router": "1.21.0", + "react-router": "6.28.0" } }, "react-select": { @@ -45026,11 +45138,12 @@ } }, "react-shallow-renderer": { - "version": "16.14.1", - "dev": true, + "version": "16.15.0", + "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", + "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", "requires": { "object-assign": "^4.1.1", - "react-is": "^16.12.0 || ^17.0.0" + "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" } }, "react-table": { @@ -45039,18 +45152,19 @@ "integrity": "sha512-hNaz4ygkZO4bESeFfnfOft73iBUj8K5oKi1EcSHPAibEydfsX2MyU6Z8KCr3mv3C9Kqqh71U+DhZkFvibbnPbA==" }, "react-test-renderer": { - "version": "17.0.1", - "dev": true, + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-18.3.1.tgz", + "integrity": "sha512-KkAgygexHUkQqtvvx/otwxtuFu5cVjfzTCtjXLH9boS19/Nbtg84zS7wIQn39G8IlrhThBpQsMKkq5ZHZIYFXA==", "requires": { - "object-assign": "^4.1.1", - "react-is": "^17.0.1", - "react-shallow-renderer": "^16.13.1", - "scheduler": "^0.20.1" + "react-is": "^18.3.1", + "react-shallow-renderer": "^16.15.0", + "scheduler": "^0.23.2" }, "dependencies": { "react-is": { - "version": "17.0.1", - "dev": true + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" } } }, @@ -45629,12 +45743,11 @@ } }, "scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" } }, "schema-utils": { @@ -46592,20 +46705,35 @@ } }, "styled-components": { - "version": "5.2.1", + "version": "5.3.11", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.11.tgz", + "integrity": "sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==", "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/traverse": "^7.4.5", - "@emotion/is-prop-valid": "^0.8.8", + "@emotion/is-prop-valid": "^1.1.0", "@emotion/stylis": "^0.8.4", "@emotion/unitless": "^0.7.4", - "babel-plugin-styled-components": ">= 1", + "babel-plugin-styled-components": ">= 1.12.0", "css-to-react-native": "^3.0.0", "hoist-non-react-statics": "^3.0.0", "shallowequal": "^1.1.0", "supports-color": "^5.5.0" }, "dependencies": { + "@emotion/is-prop-valid": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz", + "integrity": "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==", + "requires": { + "@emotion/memoize": "^0.9.0" + } + }, + "@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" + }, "has-flag": { "version": "3.0.0" }, diff --git a/ui/package.json b/ui/package.json index fcdc2e4949..d1255b2059 100644 --- a/ui/package.json +++ b/ui/package.json @@ -7,8 +7,8 @@ "@hookform/resolvers": "^3.1.0", "@js-temporal/polyfill": "^0.4.4", "@kubernetes/client-node": "github:scality/kubernetes-client-javascript.git#browser-0.10.4-64-ge7c6721", - "@scality/core-ui": "0.151.0", - "@scality/module-federation": "^1.3.4", + "@scality/core-ui": "git+https://github.com/scality/core-ui#bf0c36da657737f47dabe310bb1a20c136877970", + "@scality/module-federation": "git+https://github.com/scality/module-federation#c571388783a2a51ae3bf5d36ae66753c8b014bb5", "axios": "^0.21.1", "formik": "2.2.5", "jsonpath": "^1.1.1", @@ -16,20 +16,20 @@ "lodash.isequal": "^4.5.0", "lodash.sortby": "^4.7.0", "luxon": "^2.1.1", - "react": "^17.0.1", - "react-dom": "^17.0.1", - "react-error-boundary": "^3.1.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-error-boundary": "^4.1.2", "react-hook-form": "^7.44.3", "react-intl": "^5.15.3", "react-json-view": "^1.21.3", "react-query": "^3.34.0", "react-redux": "^7.1.0", - "react-router": "5.2.0", - "react-router-dom": "5.2.0", + "react-router": "^6.28.0", + "react-router-dom": "^6.28.0", "redux": "^4.0.1", "redux-saga": "^1.0.2", "reselect": "^2.5.4", - "styled-components": "^5.0.1", + "styled-components": "^5.3.11", "uuid": "3.3.2", "yup": "^0.32.9" }, @@ -78,7 +78,7 @@ "@rspack/core": "^0.7.5", "@testing-library/dom": "^9.3.1", "@testing-library/jest-dom": "^5.11.9", - "@testing-library/react": "^11.2.3", + "@testing-library/react": "^15.0.7", "@testing-library/react-hooks": "^3.4.2", "@testing-library/user-event": "^14.4.3", "@types/hapi__joi": "^17.1.9", @@ -86,10 +86,13 @@ "@types/lodash.isempty": "^4.4.7", "@types/lodash.isequal": "^4.5.6", "@types/lodash.sortby": "^4.7.7", + "@types/react": "^18.3.12", + "@types/react-dom": "^18.3.1", "@types/react-redux": "^7.1.25", "@types/react-router": "^5.1.20", "@types/react-router-dom": "^5.3.3", - "@types/styled-components": "^5.1.26", + "@types/react-test-renderer": "^18.3.0", + "@types/styled-components": "^5.1.34", "@typescript-eslint/eslint-plugin": "^5.62.0", "babel-eslint": "^10.1.0", "babel-jest": "^26.6.3", @@ -112,7 +115,7 @@ "jest-preview": "^0.3.1", "msw": "0.36.8", "oidc-client": "^1.8.0", - "react-test-renderer": "^17.0.1", + "react-test-renderer": "^18.3.1", "ts-node": "^10.9.2", "typescript": "^5.3.3" }, diff --git a/ui/src/FederableApp.tsx b/ui/src/FederableApp.tsx index 43a6b68b1c..b8741471dc 100644 --- a/ui/src/FederableApp.tsx +++ b/ui/src/FederableApp.tsx @@ -2,7 +2,7 @@ import 'regenerator-runtime/runtime'; import { PropsWithChildren, ReactNode, useEffect, useMemo } from 'react'; import { Provider, useDispatch } from 'react-redux'; import { createStore, applyMiddleware, compose, Store } from 'redux'; -import { Router } from 'react-router-dom'; +import { BrowserRouter as Router } from 'react-router-dom'; import createSagaMiddleware from 'redux-saga'; import { useCurrentApp } from '@scality/module-federation'; import { Loader, ToastProvider } from '@scality/core-ui'; @@ -16,6 +16,7 @@ import { setHistory as setReduxHistory } from './ducks/history'; import { setApiConfigAction } from './ducks/config'; import { authErrorAction } from './ducks/app/authError'; import { AuthError } from './services/errorhandler'; +import { ShellHooksProvider, useShellHooks } from './ShellHooksContext'; const composeEnhancers = // @ts-expect-error - FIXME when you are working on it typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ @@ -35,29 +36,23 @@ export const store: Store = createStore(reducer, enhancer); if (window.Cypress) window.__store__ = store; sagaMiddleware.run(sagas); -const RouterWithBaseName = ({ children }) => { +const RouterWithBaseName = ({ children }: { children: ReactNode }) => { const configStatus = useTypedSelector((state) => state.config.status); const basename = useTypedSelector((state) => state.config.api?.ui_base_path); const dispatch = useDispatch(); - const history = useMemo(() => { - let history = createBrowserHistory({}); - if (basename) { - const historyWithBasename = createBrowserHistory({ - basename, - }); - history = historyWithBasename; - // @ts-expect-error - FIXME when you are working on it - dispatch(setReduxHistory(historyWithBasename)); - } else { + useMemo(() => { + const history = createBrowserHistory({ basename }); + dispatch(setReduxHistory(history)); + + // @ts-expect-error - FIXME when you are working on it + if (window.Cypress) { // @ts-expect-error - FIXME when you are working on it - dispatch(setReduxHistory(history)); + window.__history__ = history; } - // @ts-expect-error - FIXME when you are working on it - if (window.Cypress) window.__history__ = history; - return history; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [basename]); + return history; + }, [basename, dispatch]); if (configStatus === 'error') { return ; @@ -67,11 +62,7 @@ const RouterWithBaseName = ({ children }) => { return <>{children}; } - return ( - - {children} - - ); + return {children}; }; type Config = { url: string; @@ -87,7 +78,8 @@ type Config = { }; export const useConfig = () => { const { name } = useCurrentApp(); - const runtimeConfiguration = window.shellHooks.useConfig({ + const { useConfig } = useShellHooks(); + const runtimeConfiguration = useConfig({ configType: 'run', name, }); @@ -131,16 +123,21 @@ export const AppConfigProvider = ({ ); }; -export default function FederableApp() { +export default function FederableApp(props) { return ( - - - - - - - - - + + + + + + + + + + + ); } diff --git a/ui/src/ShellHooksContext.tsx b/ui/src/ShellHooksContext.tsx new file mode 100644 index 0000000000..13e72f3f0e --- /dev/null +++ b/ui/src/ShellHooksContext.tsx @@ -0,0 +1,99 @@ +import { FC, ReactNode, useMemo, useSyncExternalStore } from 'react'; +import { ShellTypes } from '../@mf-types/shell/compiled-types/src/FederatedApp'; + +export type ShellHooks = ShellTypes['shellHooks']; +export type ShellAlerts = ShellTypes['shellAlerts']; + +type Listener = () => void; + +const createShellHooksStore = () => { + let shellHooks: ShellHooks | null = null; + + const listeners: Set = new Set(); + + return { + getShellHooks: () => shellHooks, + + subscribe: (listener: Listener) => { + listeners.add(listener); + return () => { + listeners.delete(listener); + }; + }, + + setShellHooks: (newHooks: ShellHooks) => { + if (shellHooks !== newHooks) { + shellHooks = newHooks; + listeners.forEach((listener) => listener()); + } + }, + }; +}; + +const createShellAlertsStore = () => { + let shellAlerts: ShellAlerts | null = null; + const listeners: Set = new Set(); + + return { + getShellAlerts: () => shellAlerts, + + subscribe: (listener: Listener) => { + listeners.add(listener); + return () => { + listeners.delete(listener); + }; + }, + + setShellAlerts: (newAlerts: ShellAlerts) => { + if (shellAlerts !== newAlerts) { + shellAlerts = newAlerts; + listeners.forEach((listener) => listener()); + } + }, + }; +}; + +export const shellHooksStore = createShellHooksStore(); +export const shellAlertsStore = createShellAlertsStore(); + +export const useShellHooks = (): ShellHooks => { + const hooks = useSyncExternalStore( + shellHooksStore.subscribe, + shellHooksStore.getShellHooks, + ); + + if (!hooks) { + throw new Error( + 'useShellHooks must be used within a ShellHooksProvider and initialized with valid hooks.', + ); + } + + return hooks; +}; + +export const useShellAlerts = (): ShellAlerts => { + const alerts = useSyncExternalStore( + shellAlertsStore.subscribe, + shellAlertsStore.getShellAlerts, + ); + + if (!alerts) { + throw new Error( + 'useShellAlerts must be used within a ShellHooksProvider and initialized with valid alerts.', + ); + } + + return alerts; +}; + +export const ShellHooksProvider: FC<{ + shellHooks: ShellHooks; + shellAlerts: ShellAlerts; + children: ReactNode; +}> = ({ shellHooks, shellAlerts, children }) => { + useMemo(() => { + shellHooksStore.setShellHooks(shellHooks); + shellAlertsStore.setShellAlerts(shellAlerts); + }, [shellHooks, shellAlerts]); + return <>{children}; +}; diff --git a/ui/src/alert-configuration/ConfigureAlerting.test.tsx b/ui/src/alert-configuration/ConfigureAlerting.test.tsx index e72b272ede..9a212018e0 100644 --- a/ui/src/alert-configuration/ConfigureAlerting.test.tsx +++ b/ui/src/alert-configuration/ConfigureAlerting.test.tsx @@ -1,20 +1,20 @@ -import fs from 'fs'; -import path from 'path'; import { act, + configure, screen, waitFor, waitForElementToBeRemoved, - configure, } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import fs from 'fs'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; -import userEvent from '@testing-library/user-event'; -import { Route, Switch } from 'react-router'; +import path from 'path'; +import { Route, Routes } from 'react-router'; -import ConfigureAlerting from './ConfigureAlerting'; import { render, waitForLoadingToFinish } from '../components/__TEST__/util'; import { NotificationDisplayer } from '../containers/Layout'; +import ConfigureAlerting from './ConfigureAlerting'; const saltLoginRequest = jest.fn(); const patchAlertmanagerConfig = jest.fn(); @@ -164,14 +164,14 @@ const commonSetup = async () => { render( <> - - + +
Redirected Alert Page
- + -
+ , ); diff --git a/ui/src/alert-configuration/ConfigureAlerting.tsx b/ui/src/alert-configuration/ConfigureAlerting.tsx index 4b8322b310..6bd3ee55c5 100644 --- a/ui/src/alert-configuration/ConfigureAlerting.tsx +++ b/ui/src/alert-configuration/ConfigureAlerting.tsx @@ -18,7 +18,7 @@ import { Box, Button, Input, Select } from '@scality/core-ui/dist/next'; import { useEffect, useRef } from 'react'; import { Controller, useForm } from 'react-hook-form'; import { useDispatch } from 'react-redux'; -import { useHistory } from 'react-router'; +import { useNavigate } from 'react-router'; import { useTheme } from 'styled-components'; import { useAuth } from '../containers/PrivateRoute'; @@ -116,7 +116,7 @@ const schema = Joi.object({ export default function ConfigureAlerting() { const theme = useTheme(); - const history = useHistory(); + const navigate = useNavigate(); const dispatch = useDispatch(); const { register, @@ -165,7 +165,7 @@ export default function ConfigureAlerting() { message: 'The email notification configuration has been saved', }), ); - history.push('/alerts'); + navigate('/alerts'); } }, [editAlertMutation.status]); @@ -215,7 +215,7 @@ export default function ConfigureAlerting() {