From 06e5855c8cb2b28ce733bbc56f76a9c2cb252b24 Mon Sep 17 00:00:00 2001 From: Arnei Date: Wed, 8 Apr 2026 13:53:27 +0200 Subject: [PATCH 1/8] LifeCycle Policies - Squashed The old PR for lifecycle policies was old, had many commits and many merges. Creating a squashed commit seemed like the simplest option to bring lifecycle policies from the old history to the new history. --- package-lock.json | 1752 ++++++++--------- package.json | 1 + src/App.tsx | 3 + src/components/events/LifeCyclePolicies.tsx | 121 ++ .../events/partials/EventsNavigation.tsx | 5 + .../partials/LifeCyclePolicyActionCell.tsx | 54 + .../partials/LifeCyclePolicyIsActiveCell.tsx | 21 + .../EventDetailsLifeCyclePolicy.tsx | 111 ++ .../EventDetailsWorkflowSchedulingTab.tsx | 4 +- .../LifeCyclePolicyAccessTab.tsx | 56 + .../LifeCyclePolicyGeneralTab.tsx | 188 ++ .../ModalTabsAndPages/NewAccessPage.tsx | 8 +- .../NewLifeCyclePolicyGeneralPage.tsx | 37 + .../ModalTabsAndPages/NewProcessingPage.tsx | 5 +- .../events/partials/modals/EventDetails.tsx | 13 + .../modals/LifeCyclePolicyDetails.tsx | 78 + .../modals/LifeCyclePolicyDetailsModal.tsx | 68 + .../wizards/LifeCyclePolicyGeneralFields.tsx | 584 ++++++ .../partials/wizards/NewEventWizard.tsx | 3 - .../wizards/NewLifeCyclePolicySummary.tsx | 124 ++ .../wizards/NewLifeCyclePolicyWizard.tsx | 181 ++ .../partials/wizards/RenderWorkflowConfig.tsx | 113 +- src/components/shared/ConfirmModal.tsx | 2 +- src/components/shared/MainNav.tsx | 6 + src/components/shared/NewResourceModal.tsx | 17 +- src/components/shared/modals/Modal.tsx | 7 +- src/components/shared/wizard/RenderField.tsx | 40 + src/configs/modalConfig.ts | 35 + .../lifeCyclePoliciesTableConfig.ts | 30 + .../tableConfigs/lifeCyclePoliciesTableMap.ts | 11 + .../adminui/languages/lang-en_US.json | 89 +- src/selectors/eventDetailsSelectors.ts | 3 + src/selectors/lifeCycleDetailsSelectors.ts | 14 + src/selectors/lifeCycleSelectors.ts | 7 + src/slices/eventDetailsSlice.ts | 29 + src/slices/lifeCycleDetailsSlice.ts | 278 +++ src/slices/lifeCycleSlice.ts | 186 ++ src/slices/tableSlice.ts | 15 +- src/slices/workflowSlice.ts | 2 +- src/store.ts | 5 + src/thunks/tableThunks.ts | 40 + src/utils/dropDownUtils.ts | 4 + src/utils/lifeCycleUtils.ts | 38 + src/utils/validate.ts | 93 + 44 files changed, 3510 insertions(+), 971 deletions(-) create mode 100644 src/components/events/LifeCyclePolicies.tsx create mode 100644 src/components/events/partials/LifeCyclePolicyActionCell.tsx create mode 100644 src/components/events/partials/LifeCyclePolicyIsActiveCell.tsx create mode 100644 src/components/events/partials/ModalTabsAndPages/EventDetailsLifeCyclePolicy.tsx create mode 100644 src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyAccessTab.tsx create mode 100644 src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyGeneralTab.tsx create mode 100644 src/components/events/partials/ModalTabsAndPages/NewLifeCyclePolicyGeneralPage.tsx create mode 100644 src/components/events/partials/modals/LifeCyclePolicyDetails.tsx create mode 100644 src/components/events/partials/modals/LifeCyclePolicyDetailsModal.tsx create mode 100644 src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx create mode 100644 src/components/events/partials/wizards/NewLifeCyclePolicySummary.tsx create mode 100644 src/components/events/partials/wizards/NewLifeCyclePolicyWizard.tsx create mode 100644 src/configs/tableConfigs/lifeCyclePoliciesTableConfig.ts create mode 100644 src/configs/tableConfigs/lifeCyclePoliciesTableMap.ts create mode 100644 src/selectors/lifeCycleDetailsSelectors.ts create mode 100644 src/selectors/lifeCycleSelectors.ts create mode 100644 src/slices/lifeCycleDetailsSlice.ts create mode 100644 src/slices/lifeCycleSlice.ts create mode 100644 src/utils/lifeCycleUtils.ts diff --git a/package-lock.json b/package-lock.json index 80d1fd7862..e135f2ac09 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,7 @@ "react-hotkeys-hook": "^5.2.4", "react-i18next": "16.5.0", "react-icons": "^5.5.0", + "react-js-cron": "^5.0.1", "react-redux": "^9.2.0", "react-router": "^7.13.0", "react-select": "^5.10.2", @@ -63,10 +64,99 @@ "vitest": "^4.0.18" } }, + "node_modules/@ant-design/colors": { + "version": "8.0.1", + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^3.0.0" + } + }, + "node_modules/@ant-design/cssinjs": { + "version": "2.1.2", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "@emotion/hash": "^0.8.0", + "@emotion/unitless": "^0.7.5", + "@rc-component/util": "^1.4.0", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "stylis": "^4.3.4" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/cssinjs-utils": { + "version": "2.1.2", + "license": "MIT", + "dependencies": { + "@ant-design/cssinjs": "^2.1.2", + "@babel/runtime": "^7.23.2", + "@rc-component/util": "^1.4.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/@ant-design/cssinjs/node_modules/@emotion/hash": { + "version": "0.8.0", + "license": "MIT" + }, + "node_modules/@ant-design/cssinjs/node_modules/@emotion/unitless": { + "version": "0.7.5", + "license": "MIT" + }, + "node_modules/@ant-design/cssinjs/node_modules/stylis": { + "version": "4.4.0", + "license": "MIT" + }, + "node_modules/@ant-design/fast-color": { + "version": "3.0.1", + "license": "MIT", + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@ant-design/icons": { + "version": "6.1.1", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^8.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.4.2", + "license": "MIT" + }, + "node_modules/@ant-design/react-slick": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "clsx": "^2.1.1", + "json2mq": "^0.2.0", + "throttle-debounce": "^5.0.0" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", @@ -79,8 +169,6 @@ }, "node_modules/@babel/generator": { "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "license": "MIT", "dependencies": { "@babel/parser": "^7.29.0", @@ -95,8 +183,6 @@ }, "node_modules/@babel/helper-globals": { "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -104,8 +190,6 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", "license": "MIT", "dependencies": { "@babel/traverse": "^7.28.6", @@ -117,8 +201,6 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -126,8 +208,6 @@ }, "node_modules/@babel/helper-validator-identifier": { "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -135,8 +215,6 @@ }, "node_modules/@babel/parser": { "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", - "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", "license": "MIT", "dependencies": { "@babel/types": "^7.29.0" @@ -150,8 +228,6 @@ }, "node_modules/@babel/runtime": { "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", - "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -159,8 +235,6 @@ }, "node_modules/@babel/template": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.28.6", @@ -173,8 +247,6 @@ }, "node_modules/@babel/traverse": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.29.0", @@ -191,8 +263,6 @@ }, "node_modules/@babel/types": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -202,29 +272,6 @@ "node": ">=6.9.0" } }, - "node_modules/@emnapi/core": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", - "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.1", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", - "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@emnapi/wasi-threads": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", @@ -238,8 +285,6 @@ }, "node_modules/@emotion/babel-plugin": { "version": "11.13.5", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", - "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.16.7", @@ -257,8 +302,6 @@ }, "node_modules/@emotion/cache": { "version": "11.14.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", - "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", "license": "MIT", "dependencies": { "@emotion/memoize": "^0.9.0", @@ -270,14 +313,10 @@ }, "node_modules/@emotion/hash": { "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", - "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", "license": "MIT" }, "node_modules/@emotion/is-prop-valid": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz", - "integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==", "license": "MIT", "dependencies": { "@emotion/memoize": "^0.9.0" @@ -285,15 +324,12 @@ }, "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==", "license": "MIT" }, "node_modules/@emotion/react": { "version": "11.14.0", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", - "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -315,8 +351,6 @@ }, "node_modules/@emotion/serialize": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", - "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", "license": "MIT", "dependencies": { "@emotion/hash": "^0.9.2", @@ -328,15 +362,12 @@ }, "node_modules/@emotion/sheet": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", - "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", "license": "MIT" }, "node_modules/@emotion/styled": { "version": "11.14.1", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", - "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -357,14 +388,10 @@ }, "node_modules/@emotion/unitless": { "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", - "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", "license": "MIT" }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", - "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", "license": "MIT", "peerDependencies": { "react": ">=16.8.0" @@ -372,20 +399,14 @@ }, "node_modules/@emotion/utils": { "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", - "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", "license": "MIT" }, "node_modules/@emotion/weak-memoize": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", - "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", "license": "MIT" }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", - "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -403,8 +424,6 @@ }, "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "license": "Apache-2.0", "engines": { @@ -416,8 +435,6 @@ }, "node_modules/@eslint-community/regexpp": { "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", "engines": { @@ -426,8 +443,6 @@ }, "node_modules/@eslint/config-array": { "version": "0.21.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", - "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -441,8 +456,6 @@ }, "node_modules/@eslint/config-helpers": { "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", - "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -454,8 +467,6 @@ }, "node_modules/@eslint/core": { "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -467,8 +478,6 @@ }, "node_modules/@eslint/eslintrc": { "version": "3.3.5", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", - "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", "dev": true, "license": "MIT", "dependencies": { @@ -491,8 +500,6 @@ }, "node_modules/@eslint/js": { "version": "9.39.4", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", - "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", "dev": true, "license": "MIT", "engines": { @@ -504,8 +511,6 @@ }, "node_modules/@eslint/object-schema": { "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", - "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -514,8 +519,6 @@ }, "node_modules/@eslint/plugin-kit": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", - "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -528,8 +531,6 @@ }, "node_modules/@floating-ui/core": { "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", - "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", "license": "MIT", "dependencies": { "@floating-ui/utils": "^0.2.11" @@ -537,8 +538,6 @@ }, "node_modules/@floating-ui/dom": { "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", - "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", "license": "MIT", "dependencies": { "@floating-ui/core": "^1.7.5", @@ -547,8 +546,6 @@ }, "node_modules/@floating-ui/react": { "version": "0.27.19", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.19.tgz", - "integrity": "sha512-31B8h5mm8YxotlE7/AU/PhNAl8eWxAmjL/v2QOxroDNkTFLk3Uu82u63N3b6TXa4EGJeeZLVcd/9AlNlVqzeog==", "license": "MIT", "dependencies": { "@floating-ui/react-dom": "^2.1.8", @@ -562,8 +559,6 @@ }, "node_modules/@floating-ui/react-dom": { "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz", - "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==", "license": "MIT", "dependencies": { "@floating-ui/dom": "^1.7.6" @@ -575,14 +570,10 @@ }, "node_modules/@floating-ui/utils": { "version": "0.2.11", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", - "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", "license": "MIT" }, "node_modules/@hello-pangea/dnd": { "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@hello-pangea/dnd/-/dnd-18.0.1.tgz", - "integrity": "sha512-xojVWG8s/TGrKT1fC8K2tIWeejJYTAeJuj36zM//yEm/ZrnZUSFGS15BpO+jGZT1ybWvyXmeDJwPYb4dhWlbZQ==", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.26.7", @@ -598,8 +589,6 @@ }, "node_modules/@humanfs/core": { "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -608,8 +597,6 @@ }, "node_modules/@humanfs/node": { "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -622,8 +609,6 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -636,8 +621,6 @@ }, "node_modules/@humanwhocodes/retry": { "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -650,8 +633,6 @@ }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -660,8 +641,6 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "license": "MIT", "engines": { "node": ">=6.0.0" @@ -669,14 +648,10 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -685,15 +660,10 @@ }, "node_modules/@kurkle/color": { "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz", - "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@mui/core-downloads-tracker": { "version": "7.3.10", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.3.10.tgz", - "integrity": "sha512-vrOpWRmPJSuwLo23J62wggEm/jvGdzqctej+UOCtgDUz6nZJQuj3ByPccVyaa7eQmwAzUwKN56FQPMKkqbj1GA==", "license": "MIT", "funding": { "type": "opencollective", @@ -702,8 +672,6 @@ }, "node_modules/@mui/material": { "version": "7.3.10", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.10.tgz", - "integrity": "sha512-cHvGOk2ZEfbQt3LnGe0ZKd/ETs9gsUpkW66DCO+GSjMZhpdKU4XsuIr7zJ/B/2XaN8ihxuzHfYAR4zPtCN4RYg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.6", @@ -751,8 +719,6 @@ }, "node_modules/@mui/private-theming": { "version": "7.3.10", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.3.10.tgz", - "integrity": "sha512-j3EZN+zOctxUISvJSmsEPo5o2F8zse4l5vRkBY+ps6UtnL6J7o14kUaI4w7gwo73id9e3cDNMVQK/9BVaMHVBw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.6", @@ -778,8 +744,6 @@ }, "node_modules/@mui/styled-engine": { "version": "7.3.10", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.3.10.tgz", - "integrity": "sha512-WxE9SiF8xskAQqGjsp0poXCkCqsoXFEsSr0HBXfApmGHR+DBnXRp+z46Vsltg4gpPM4Z96DeAQRpeAOnhNg7Ng==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.6", @@ -812,8 +776,6 @@ }, "node_modules/@mui/system": { "version": "7.3.10", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-7.3.10.tgz", - "integrity": "sha512-/sfPpdpJaQn7BSF+avjIdHSYmxHp0UOBYNxSG9QGKfMOD6sLANCpRPCnanq1Pe0lFf0NHkO2iUk0TNzdWC1USQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.6", @@ -852,8 +814,6 @@ }, "node_modules/@mui/types": { "version": "7.4.12", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.12.tgz", - "integrity": "sha512-iKNAF2u9PzSIj40CjvKJWxFXJo122jXVdrmdh0hMYd+FR+NuJMkr/L88XwWLCRiJ5P1j+uyac25+Kp6YC4hu6w==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.6" @@ -869,8 +829,6 @@ }, "node_modules/@mui/utils": { "version": "7.3.10", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.3.10.tgz", - "integrity": "sha512-7y2eIfy0h7JPz+Yy4pS+wgV68d46PuuxDqKBN4Q8VlPQSsCAGwroMCV6xWyc7g9dvEp8ZNFsknc59GHWO+r6Ow==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.6", @@ -918,8 +876,6 @@ }, "node_modules/@opencast/eslint-config-ts-react": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@opencast/eslint-config-ts-react/-/eslint-config-ts-react-0.3.0.tgz", - "integrity": "sha512-8yv/28DuIE4UQYz5irfmcx+9hkPPB8nQcSD3JLJ/1ZFlt/qCrFuhWnwPPgdzHGhF8In+LHE2gyY7CdUNdnj0pg==", "dev": true, "license": "CC0-1.0", "dependencies": { @@ -943,8 +899,6 @@ }, "node_modules/@parcel/watcher": { "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", - "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1148,8 +1102,6 @@ }, "node_modules/@parcel/watcher-linux-x64-glibc": { "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", - "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", "cpu": [ "x64" ], @@ -1169,8 +1121,6 @@ }, "node_modules/@parcel/watcher-linux-x64-musl": { "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", - "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", "cpu": [ "x64" ], @@ -1253,8 +1203,6 @@ }, "node_modules/@parcel/watcher/node_modules/picomatch": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "optional": true, @@ -1267,18 +1215,645 @@ }, "node_modules/@popperjs/core": { "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" } }, + "node_modules/@rc-component/async-validator": { + "version": "5.1.0", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.4" + }, + "engines": { + "node": ">=14.x" + } + }, + "node_modules/@rc-component/cascader": { + "version": "1.14.0", + "license": "MIT", + "dependencies": { + "@rc-component/select": "~1.6.0", + "@rc-component/tree": "~1.2.0", + "@rc-component/util": "^1.4.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/checkbox": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/collapse": { + "version": "1.2.0", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/motion": "^1.1.4", + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/color-picker": { + "version": "3.1.1", + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^3.0.1", + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/context": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.3.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/dialog": { + "version": "1.8.4", + "license": "MIT", + "dependencies": { + "@rc-component/motion": "^1.1.3", + "@rc-component/portal": "^2.1.0", + "@rc-component/util": "^1.9.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/drawer": { + "version": "1.4.2", + "license": "MIT", + "dependencies": { + "@rc-component/motion": "^1.1.4", + "@rc-component/portal": "^2.1.3", + "@rc-component/util": "^1.9.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/dropdown": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "@rc-component/trigger": "^3.0.0", + "@rc-component/util": "^1.2.1", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.11.0", + "react-dom": ">=16.11.0" + } + }, + "node_modules/@rc-component/form": { + "version": "1.8.1", + "license": "MIT", + "dependencies": { + "@rc-component/async-validator": "^5.1.0", + "@rc-component/util": "^1.6.2", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/image": { + "version": "1.9.0", + "license": "MIT", + "dependencies": { + "@rc-component/motion": "^1.0.0", + "@rc-component/portal": "^2.1.2", + "@rc-component/util": "^1.10.1", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/input": { + "version": "1.1.2", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.4.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@rc-component/input-number": { + "version": "1.6.2", + "license": "MIT", + "dependencies": { + "@rc-component/mini-decimal": "^1.0.1", + "@rc-component/util": "^1.4.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/mentions": { + "version": "1.6.0", + "license": "MIT", + "dependencies": { + "@rc-component/input": "~1.1.0", + "@rc-component/menu": "~1.2.0", + "@rc-component/textarea": "~1.1.0", + "@rc-component/trigger": "^3.0.0", + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/menu": { + "version": "1.2.0", + "license": "MIT", + "dependencies": { + "@rc-component/motion": "^1.1.4", + "@rc-component/overflow": "^1.0.0", + "@rc-component/trigger": "^3.0.0", + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/mini-decimal": { + "version": "1.1.3", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@rc-component/motion": { + "version": "1.3.2", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.2.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/mutate-observer": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.2.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/notification": { + "version": "1.2.0", + "license": "MIT", + "dependencies": { + "@rc-component/motion": "^1.1.4", + "@rc-component/util": "^1.2.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/overflow": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "@rc-component/resize-observer": "^1.0.1", + "@rc-component/util": "^1.4.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/pagination": { + "version": "1.2.0", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/picker": { + "version": "1.9.1", + "license": "MIT", + "dependencies": { + "@rc-component/overflow": "^1.0.0", + "@rc-component/resize-observer": "^1.0.0", + "@rc-component/trigger": "^3.6.15", + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=12.x" + }, + "peerDependencies": { + "date-fns": ">= 2.x", + "dayjs": ">= 1.x", + "luxon": ">= 3.x", + "moment": ">= 2.x", + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + }, + "peerDependenciesMeta": { + "date-fns": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + } + } + }, + "node_modules/@rc-component/portal": { + "version": "2.2.0", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.2.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=12.x" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/progress": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.2.1", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/qrcode": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/rate": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/resize-observer": { + "version": "1.1.2", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/segmented": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "@rc-component/motion": "^1.1.4", + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@rc-component/select": { + "version": "1.6.15", + "license": "MIT", + "dependencies": { + "@rc-component/overflow": "^1.0.0", + "@rc-component/trigger": "^3.0.0", + "@rc-component/util": "^1.3.0", + "@rc-component/virtual-list": "^1.0.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@rc-component/slider": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/steps": { + "version": "1.2.2", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.2.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/switch": { + "version": "1.0.3", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/table": { + "version": "1.9.1", + "license": "MIT", + "dependencies": { + "@rc-component/context": "^2.0.1", + "@rc-component/resize-observer": "^1.0.0", + "@rc-component/util": "^1.1.0", + "@rc-component/virtual-list": "^1.0.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/tabs": { + "version": "1.7.0", + "license": "MIT", + "dependencies": { + "@rc-component/dropdown": "~1.0.0", + "@rc-component/menu": "~1.2.0", + "@rc-component/motion": "^1.1.3", + "@rc-component/resize-observer": "^1.0.0", + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/textarea": { + "version": "1.1.2", + "license": "MIT", + "dependencies": { + "@rc-component/input": "~1.1.0", + "@rc-component/resize-observer": "^1.0.0", + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/tooltip": { + "version": "1.4.0", + "license": "MIT", + "dependencies": { + "@rc-component/trigger": "^3.7.1", + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/tour": { + "version": "2.3.0", + "license": "MIT", + "dependencies": { + "@rc-component/portal": "^2.2.0", + "@rc-component/trigger": "^3.0.0", + "@rc-component/util": "^1.7.0", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/tree": { + "version": "1.2.4", + "license": "MIT", + "dependencies": { + "@rc-component/motion": "^1.0.0", + "@rc-component/util": "^1.8.1", + "@rc-component/virtual-list": "^1.0.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=10.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@rc-component/tree-select": { + "version": "1.8.0", + "license": "MIT", + "dependencies": { + "@rc-component/select": "~1.6.0", + "@rc-component/tree": "~1.2.0", + "@rc-component/util": "^1.4.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@rc-component/trigger": { + "version": "3.9.0", + "license": "MIT", + "dependencies": { + "@rc-component/motion": "^1.1.4", + "@rc-component/portal": "^2.2.0", + "@rc-component/resize-observer": "^1.1.1", + "@rc-component/util": "^1.2.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/upload": { + "version": "1.1.0", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/util": { + "version": "1.10.1", + "license": "MIT", + "dependencies": { + "is-mobile": "^5.0.0", + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/util/node_modules/react-is": { + "version": "18.3.1", + "license": "MIT" + }, + "node_modules/@rc-component/virtual-list": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.0", + "@rc-component/resize-observer": "^1.0.1", + "@rc-component/util": "^1.4.0", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, "node_modules/@redux-devtools/extension": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@redux-devtools/extension/-/extension-4.0.0.tgz", - "integrity": "sha512-pLIzgo5MvqdDLe5D1pzHLgmr8THra/DOyRf5MvOEPZnKKDn6RhFbNSS5oXZ3Cal0cpx08kx7sR6zD8QgoXEnZA==", "dev": true, "license": "MIT", "peerDependencies": { @@ -1287,8 +1862,6 @@ }, "node_modules/@reduxjs/toolkit": { "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.2.tgz", - "integrity": "sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==", "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.0.0", @@ -1570,21 +2143,15 @@ }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-rc.7", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.7.tgz", - "integrity": "sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==", "dev": true, "license": "MIT" }, "node_modules/@standard-schema/spec": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", "license": "MIT" }, "node_modules/@standard-schema/utils": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", - "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", "license": "MIT" }, "node_modules/@tybys/wasm-util": { @@ -1600,8 +2167,6 @@ }, "node_modules/@types/chai": { "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", - "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { @@ -1611,22 +2176,16 @@ }, "node_modules/@types/deep-eql": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, "node_modules/@types/hoist-non-react-statics": { "version": "3.3.7", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.7.tgz", - "integrity": "sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g==", "license": "MIT", "dependencies": { "hoist-non-react-statics": "^3.3.0" @@ -1637,8 +2196,6 @@ }, "node_modules/@types/http-proxy": { "version": "1.17.17", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.17.tgz", - "integrity": "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -1646,22 +2203,16 @@ }, "node_modules/@types/json-schema": { "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true, "license": "MIT" }, "node_modules/@types/lodash": { "version": "4.17.24", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz", - "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", "dev": true, "license": "MIT" }, "node_modules/@types/node": { "version": "25.6.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz", - "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", "license": "MIT", "dependencies": { "undici-types": "~7.19.0" @@ -1669,20 +2220,14 @@ }, "node_modules/@types/parse-json": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", "license": "MIT" }, "node_modules/@types/prop-types": { "version": "15.7.15", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", - "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", "license": "MIT" }, "node_modules/@types/react": { "version": "19.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", - "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "license": "MIT", "peer": true, "dependencies": { @@ -1691,17 +2236,14 @@ }, "node_modules/@types/react-dom": { "version": "19.2.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", - "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } }, "node_modules/@types/react-transition-group": { "version": "4.4.12", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", - "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", "license": "MIT", "peerDependencies": { "@types/react": "*" @@ -1709,21 +2251,15 @@ }, "node_modules/@types/trusted-types": { "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", "license": "MIT", "optional": true }, "node_modules/@types/use-sync-external-store": { "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", - "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", "license": "MIT" }, "node_modules/@types/uuid": { "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-11.0.0.tgz", - "integrity": "sha512-HVyk8nj2m+jcFRNazzqyVKiZezyhDKrGUA3jlEcg/nZ6Ms+qHwocba1Y/AaVaznJTAM9xpdFSh+ptbNrhOGvZA==", "deprecated": "This is a stub types definition. uuid provides its own type definitions, so you do not need this installed.", "dev": true, "license": "MIT", @@ -1733,8 +2269,6 @@ }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.2.tgz", - "integrity": "sha512-aC2qc5thQahutKjP+cl8cgN9DWe3ZUqVko30CMSZHnFEHyhOYoZSzkGtAI2mcwZ38xeImDucI4dnqsHiOYuuCw==", "dev": true, "license": "MIT", "dependencies": { @@ -1762,8 +2296,6 @@ }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", "engines": { @@ -1772,10 +2304,9 @@ }, "node_modules/@typescript-eslint/parser": { "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.58.2.tgz", - "integrity": "sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.58.2", "@typescript-eslint/types": "8.58.2", @@ -1797,8 +2328,6 @@ }, "node_modules/@typescript-eslint/project-service": { "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.2.tgz", - "integrity": "sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg==", "dev": true, "license": "MIT", "dependencies": { @@ -1819,8 +2348,6 @@ }, "node_modules/@typescript-eslint/scope-manager": { "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.2.tgz", - "integrity": "sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1837,8 +2364,6 @@ }, "node_modules/@typescript-eslint/tsconfig-utils": { "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.2.tgz", - "integrity": "sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A==", "dev": true, "license": "MIT", "engines": { @@ -1854,8 +2379,6 @@ }, "node_modules/@typescript-eslint/type-utils": { "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.58.2.tgz", - "integrity": "sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg==", "dev": true, "license": "MIT", "dependencies": { @@ -1879,8 +2402,6 @@ }, "node_modules/@typescript-eslint/types": { "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.2.tgz", - "integrity": "sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ==", "dev": true, "license": "MIT", "engines": { @@ -1893,8 +2414,6 @@ }, "node_modules/@typescript-eslint/typescript-estree": { "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.2.tgz", - "integrity": "sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw==", "dev": true, "license": "MIT", "dependencies": { @@ -1921,8 +2440,6 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "license": "MIT", "engines": { @@ -1931,8 +2448,6 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1944,8 +2459,6 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -1960,8 +2473,6 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", "bin": { @@ -1973,8 +2484,6 @@ }, "node_modules/@typescript-eslint/utils": { "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.2.tgz", - "integrity": "sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA==", "dev": true, "license": "MIT", "dependencies": { @@ -1997,8 +2506,6 @@ }, "node_modules/@typescript-eslint/visitor-keys": { "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.2.tgz", - "integrity": "sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==", "dev": true, "license": "MIT", "dependencies": { @@ -2015,8 +2522,6 @@ }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2028,8 +2533,6 @@ }, "node_modules/@vitejs/plugin-react": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.1.tgz", - "integrity": "sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2054,8 +2557,6 @@ }, "node_modules/@vitest/expect": { "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.4.tgz", - "integrity": "sha512-iPBpra+VDuXmBFI3FMKHSFXp3Gx5HfmSCE8X67Dn+bwephCnQCaB7qWK2ldHa+8ncN8hJU8VTMcxjPpyMkUjww==", "dev": true, "license": "MIT", "dependencies": { @@ -2072,8 +2573,6 @@ }, "node_modules/@vitest/mocker": { "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.4.tgz", - "integrity": "sha512-R9HTZBhW6yCSGbGQnDnH3QHfJxokKN4KB+Yvk9Q1le7eQNYwiCyKxmLmurSpFy6BzJanSLuEUDrD+j97Q+ZLPg==", "dev": true, "license": "MIT", "dependencies": { @@ -2099,8 +2598,6 @@ }, "node_modules/@vitest/pretty-format": { "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.4.tgz", - "integrity": "sha512-ddmDHU0gjEUyEVLxtZa7xamrpIefdEETu3nZjWtHeZX4QxqJ7tRxSteHVXJOcr8jhiLoGAhkK4WJ3WqBpjx42A==", "dev": true, "license": "MIT", "dependencies": { @@ -2112,8 +2609,6 @@ }, "node_modules/@vitest/runner": { "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.4.tgz", - "integrity": "sha512-xTp7VZ5aXP5ZJrn15UtJUWlx6qXLnGtF6jNxHepdPHpMfz/aVPx+htHtgcAL2mDXJgKhpoo2e9/hVJsIeFbytQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2126,8 +2621,6 @@ }, "node_modules/@vitest/snapshot": { "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.4.tgz", - "integrity": "sha512-MCjCFgaS8aZz+m5nTcEcgk/xhWv0rEH4Yl53PPlMXOZ1/Ka2VcZU6CJ+MgYCZbcJvzGhQRjVrGQNZqkGPttIKw==", "dev": true, "license": "MIT", "dependencies": { @@ -2142,8 +2635,6 @@ }, "node_modules/@vitest/spy": { "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.4.tgz", - "integrity": "sha512-XxNdAsKW7C+FLydqFJLb5KhJtl3PGCMmYwFRfhvIgxJvLSXhhVI1zM8f1qD3Zg7RCjTSzDVyct6sghs9UEgBEQ==", "dev": true, "license": "MIT", "funding": { @@ -2152,8 +2643,6 @@ }, "node_modules/@vitest/utils": { "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.4.tgz", - "integrity": "sha512-13QMT+eysM5uVGa1rG4kegGYNp6cnQcsTc67ELFbhNLQO+vgsygtYJx2khvdt4gVQqSSpC/KT5FZZxUpP3Oatw==", "dev": true, "license": "MIT", "dependencies": { @@ -2167,17 +2656,14 @@ }, "node_modules/@vitest/utils/node_modules/convert-source-map": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, "license": "MIT" }, "node_modules/acorn": { "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2187,8 +2673,6 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -2197,8 +2681,6 @@ }, "node_modules/ajv": { "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -2214,8 +2696,6 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { @@ -2228,17 +2708,76 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/antd": { + "version": "6.3.6", + "license": "MIT", + "peer": true, + "dependencies": { + "@ant-design/colors": "^8.0.1", + "@ant-design/cssinjs": "^2.1.2", + "@ant-design/cssinjs-utils": "^2.1.2", + "@ant-design/fast-color": "^3.0.1", + "@ant-design/icons": "^6.1.1", + "@ant-design/react-slick": "~2.0.0", + "@babel/runtime": "^7.28.4", + "@rc-component/cascader": "~1.14.0", + "@rc-component/checkbox": "~2.0.0", + "@rc-component/collapse": "~1.2.0", + "@rc-component/color-picker": "~3.1.1", + "@rc-component/dialog": "~1.8.4", + "@rc-component/drawer": "~1.4.2", + "@rc-component/dropdown": "~1.0.2", + "@rc-component/form": "~1.8.0", + "@rc-component/image": "~1.9.0", + "@rc-component/input": "~1.1.2", + "@rc-component/input-number": "~1.6.2", + "@rc-component/mentions": "~1.6.0", + "@rc-component/menu": "~1.2.0", + "@rc-component/motion": "^1.3.2", + "@rc-component/mutate-observer": "^2.0.1", + "@rc-component/notification": "~1.2.0", + "@rc-component/pagination": "~1.2.0", + "@rc-component/picker": "~1.9.1", + "@rc-component/progress": "~1.0.2", + "@rc-component/qrcode": "~1.1.1", + "@rc-component/rate": "~1.0.1", + "@rc-component/resize-observer": "^1.1.2", + "@rc-component/segmented": "~1.3.0", + "@rc-component/select": "~1.6.15", + "@rc-component/slider": "~1.0.1", + "@rc-component/steps": "~1.2.2", + "@rc-component/switch": "~1.0.3", + "@rc-component/table": "~1.9.1", + "@rc-component/tabs": "~1.7.0", + "@rc-component/textarea": "~1.1.2", + "@rc-component/tooltip": "~1.4.0", + "@rc-component/tour": "~2.3.0", + "@rc-component/tree": "~1.2.4", + "@rc-component/tree-select": "~1.8.0", + "@rc-component/trigger": "^3.9.0", + "@rc-component/upload": "~1.1.0", + "@rc-component/util": "^1.10.1", + "clsx": "^2.1.1", + "dayjs": "^1.11.11", + "scroll-into-view-if-needed": "^3.1.0", + "throttle-debounce": "^5.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, "node_modules/argparse": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, "license": "Python-2.0" }, "node_modules/array-buffer-byte-length": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, "license": "MIT", "dependencies": { @@ -2254,8 +2793,6 @@ }, "node_modules/array-includes": { "version": "3.1.9", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", - "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2277,8 +2814,6 @@ }, "node_modules/array-move": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/array-move/-/array-move-4.0.0.tgz", - "integrity": "sha512-+RY54S8OuVvg94THpneQvFRmqWdAHeqtMzgMW6JNurHxe8rsS07cHQdfGkXnTUXiBcyZ0j3SiDIxxj0RPiqCkQ==", "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" @@ -2289,8 +2824,6 @@ }, "node_modules/array.prototype.findlast": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2310,8 +2843,6 @@ }, "node_modules/array.prototype.flat": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", - "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, "license": "MIT", "dependencies": { @@ -2329,8 +2860,6 @@ }, "node_modules/array.prototype.flatmap": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", - "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, "license": "MIT", "dependencies": { @@ -2348,8 +2877,6 @@ }, "node_modules/array.prototype.tosorted": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, "license": "MIT", "dependencies": { @@ -2365,8 +2892,6 @@ }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2387,8 +2912,6 @@ }, "node_modules/assertion-error": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", "engines": { @@ -2397,8 +2920,6 @@ }, "node_modules/async-function": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", - "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", "dev": true, "license": "MIT", "engines": { @@ -2407,14 +2928,10 @@ }, "node_modules/asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, "node_modules/available-typed-arrays": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2428,9 +2945,9 @@ } }, "node_modules/axios": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.1.tgz", - "integrity": "sha512-WOG+Jj8ZOvR0a3rAn+Tuf1UQJRxw5venr6DgdbJzngJE3qG7X0kL83CZGpdHMxEm+ZK3seAbvFsw4FfOfP9vxg==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.2.tgz", + "integrity": "sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.11", @@ -2440,8 +2957,6 @@ }, "node_modules/babel-plugin-macros": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5", @@ -2455,15 +2970,11 @@ }, "node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, "license": "MIT" }, "node_modules/brace-expansion": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", "dependencies": { @@ -2473,8 +2984,6 @@ }, "node_modules/braces": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -2485,8 +2994,6 @@ }, "node_modules/call-bind": { "version": "1.0.9", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", - "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2504,8 +3011,6 @@ }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -2517,8 +3022,6 @@ }, "node_modules/call-bound": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, "license": "MIT", "dependencies": { @@ -2534,8 +3037,6 @@ }, "node_modules/callsites": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "license": "MIT", "engines": { "node": ">=6" @@ -2543,8 +3044,6 @@ }, "node_modules/camelcase": { "version": "9.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-9.0.0.tgz", - "integrity": "sha512-TO9xmyXTZ9HUHI8M1OnvExxYB0eYVS/1e5s7IDMTAoIcwUd+aNcFODs6Xk83mobk0velyHFQgA1yIrvYc6wclw==", "license": "MIT", "engines": { "node": ">=20" @@ -2555,8 +3054,6 @@ }, "node_modules/camelcase-keys": { "version": "10.0.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-10.0.2.tgz", - "integrity": "sha512-PVHCLVbJ7nWGal0lPAmBN5eSLjIynlMUk2EPmL9aPl6QyJ6+FoszTKwldPzkuVqg5teZbPTbb8Oenzyw9GSJRw==", "license": "MIT", "dependencies": { "camelcase": "^9.0.0", @@ -2573,8 +3070,6 @@ }, "node_modules/chai": { "version": "6.2.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", - "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, "license": "MIT", "engines": { @@ -2583,8 +3078,6 @@ }, "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, "license": "MIT", "dependencies": { @@ -2600,8 +3093,6 @@ }, "node_modules/chart.js": { "version": "4.5.1", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.1.tgz", - "integrity": "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==", "license": "MIT", "peer": true, "dependencies": { @@ -2613,8 +3104,6 @@ }, "node_modules/chokidar": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", "dependencies": { @@ -2629,14 +3118,10 @@ }, "node_modules/classnames": { "version": "2.5.1", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", - "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", "license": "MIT" }, "node_modules/clsx": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "license": "MIT", "engines": { "node": ">=6" @@ -2644,8 +3129,6 @@ }, "node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2657,15 +3140,11 @@ }, "node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -2674,23 +3153,21 @@ "node": ">= 0.8" } }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.1", + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, "license": "MIT" }, "node_modules/convert-source-map": { "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "license": "MIT" }, "node_modules/cookie": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", - "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", "license": "MIT", "engines": { "node": ">=18" @@ -2702,8 +3179,6 @@ }, "node_modules/cosmiconfig": { "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "license": "MIT", "dependencies": { "@types/parse-json": "^4.0.0", @@ -2718,8 +3193,6 @@ }, "node_modules/cosmiconfig/node_modules/yaml": { "version": "1.10.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", - "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", "license": "ISC", "engines": { "node": ">= 6" @@ -2727,8 +3200,6 @@ }, "node_modules/cross-fetch": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", - "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", "license": "MIT", "dependencies": { "node-fetch": "^2.7.0" @@ -2736,8 +3207,6 @@ }, "node_modules/cross-spawn": { "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { @@ -2751,8 +3220,6 @@ }, "node_modules/css-box-model": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", - "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", "license": "MIT", "dependencies": { "tiny-invariant": "^1.0.6" @@ -2760,14 +3227,10 @@ }, "node_modules/csstype": { "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, "node_modules/data-view-buffer": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2784,8 +3247,6 @@ }, "node_modules/data-view-byte-length": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2802,8 +3263,6 @@ }, "node_modules/data-view-byte-offset": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2820,18 +3279,19 @@ }, "node_modules/date-fns": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", - "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/kossnocorp" } }, + "node_modules/dayjs": { + "version": "1.11.20", + "license": "MIT", + "peer": true + }, "node_modules/debug": { "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2847,15 +3307,11 @@ }, "node_modules/deep-is": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, "license": "MIT" }, "node_modules/deepmerge": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", - "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -2863,8 +3319,6 @@ }, "node_modules/define-data-property": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "license": "MIT", "dependencies": { @@ -2881,8 +3335,6 @@ }, "node_modules/define-properties": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "license": "MIT", "dependencies": { @@ -2899,8 +3351,6 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "license": "MIT", "engines": { "node": ">=0.4.0" @@ -2908,8 +3358,6 @@ }, "node_modules/detect-libc": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2918,8 +3366,6 @@ }, "node_modules/doctrine": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2931,8 +3377,6 @@ }, "node_modules/dom-helpers": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.8.7", @@ -2941,8 +3385,6 @@ }, "node_modules/dompurify": { "version": "3.4.0", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.0.tgz", - "integrity": "sha512-nolgK9JcaUXMSmW+j1yaSvaEaoXYHwWyGJlkoCTghc97KgGDDSnpoU/PlEnw63Ah+TGKFOyY+X5LnxaWbCSfXg==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -2950,8 +3392,6 @@ }, "node_modules/dunder-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -2964,8 +3404,6 @@ }, "node_modules/error-ex": { "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" @@ -2973,8 +3411,6 @@ }, "node_modules/es-abstract": { "version": "1.24.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", - "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", "dev": true, "license": "MIT", "dependencies": { @@ -3042,8 +3478,6 @@ }, "node_modules/es-define-property": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -3051,8 +3485,6 @@ }, "node_modules/es-errors": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -3060,8 +3492,6 @@ }, "node_modules/es-iterator-helpers": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz", - "integrity": "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==", "dev": true, "license": "MIT", "dependencies": { @@ -3088,15 +3518,11 @@ }, "node_modules/es-module-lexer": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -3107,8 +3533,6 @@ }, "node_modules/es-set-tostringtag": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -3122,8 +3546,6 @@ }, "node_modules/es-shim-unscopables": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", - "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, "license": "MIT", "dependencies": { @@ -3135,8 +3557,6 @@ }, "node_modules/es-to-primitive": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, "license": "MIT", "dependencies": { @@ -3153,8 +3573,6 @@ }, "node_modules/escape-string-regexp": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "license": "MIT", "engines": { "node": ">=10" @@ -3165,10 +3583,9 @@ }, "node_modules/eslint": { "version": "9.39.4", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", - "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -3225,8 +3642,6 @@ }, "node_modules/eslint-plugin-react": { "version": "7.37.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", - "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", "dev": true, "license": "MIT", "dependencies": { @@ -3258,8 +3673,6 @@ }, "node_modules/eslint-plugin-react-hooks": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", - "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", "dev": true, "license": "MIT", "engines": { @@ -3271,8 +3684,6 @@ }, "node_modules/eslint-plugin-react/node_modules/resolve": { "version": "2.0.0-next.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.6.tgz", - "integrity": "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==", "dev": true, "license": "MIT", "dependencies": { @@ -3295,8 +3706,6 @@ }, "node_modules/eslint-scope": { "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -3312,8 +3721,6 @@ }, "node_modules/eslint-visitor-keys": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3325,8 +3732,6 @@ }, "node_modules/espree": { "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -3343,8 +3748,6 @@ }, "node_modules/esquery": { "version": "1.7.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", - "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -3356,8 +3759,6 @@ }, "node_modules/esrecurse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -3369,8 +3770,6 @@ }, "node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -3379,8 +3778,6 @@ }, "node_modules/estree-walker": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "license": "MIT", "dependencies": { @@ -3389,8 +3786,6 @@ }, "node_modules/esutils": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -3399,14 +3794,10 @@ }, "node_modules/eventemitter3": { "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "license": "MIT" }, "node_modules/expect-type": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", - "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3415,29 +3806,21 @@ }, "node_modules/fast-deep-equal": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, "license": "MIT" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, "license": "MIT" }, "node_modules/file-entry-cache": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3449,8 +3832,6 @@ }, "node_modules/fill-range": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -3461,14 +3842,10 @@ }, "node_modules/find-root": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", "license": "MIT" }, "node_modules/find-up": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", "dependencies": { @@ -3484,8 +3861,6 @@ }, "node_modules/flat-cache": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { @@ -3498,15 +3873,11 @@ }, "node_modules/flatted": { "version": "3.4.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", - "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true, "license": "ISC" }, "node_modules/focus-trap": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-8.0.1.tgz", - "integrity": "sha512-9ptSG6z51YQOstI/oN4XuVGP/03u2nh0g//qz7L6zX0i6PZiPnkcf3GenXq7N2hZnASXaMxTPpbKwdI+PFvxlw==", "license": "MIT", "dependencies": { "tabbable": "^6.4.0" @@ -3514,8 +3885,6 @@ }, "node_modules/focus-trap-react": { "version": "12.0.0", - "resolved": "https://registry.npmjs.org/focus-trap-react/-/focus-trap-react-12.0.0.tgz", - "integrity": "sha512-bTPk+jbG0Q3zqHjY7KjdmjqMKGKVrKbMwXxHX9+FTYENWxmLryJVoI3ZfStRSJ26uPipl+th9DIPhCyjeEBYdg==", "license": "MIT", "dependencies": { "focus-trap": "^8.0.0", @@ -3530,8 +3899,6 @@ }, "node_modules/follow-redirects": { "version": "1.16.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", - "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", @@ -3550,8 +3917,6 @@ }, "node_modules/for-each": { "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, "license": "MIT", "dependencies": { @@ -3566,8 +3931,6 @@ }, "node_modules/form-data": { "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -3582,8 +3945,6 @@ }, "node_modules/formik": { "version": "2.4.9", - "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.9.tgz", - "integrity": "sha512-5nI94BMnlFDdQRBY4Sz39WkhxajZJ57Fzs8wVbtsQlm5ScKIR1QLYqv/ultBnobObtlUyxpxoLodpixrsf36Og==", "funding": [ { "type": "individual", @@ -3622,8 +3983,6 @@ }, "node_modules/function-bind": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3631,8 +3990,6 @@ }, "node_modules/function.prototype.name": { "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, "license": "MIT", "dependencies": { @@ -3652,8 +4009,6 @@ }, "node_modules/functions-have-names": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, "license": "MIT", "funding": { @@ -3662,8 +4017,6 @@ }, "node_modules/generator-function": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", - "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", "dev": true, "license": "MIT", "engines": { @@ -3672,8 +4025,6 @@ }, "node_modules/get-intrinsic": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -3696,8 +4047,6 @@ }, "node_modules/get-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -3709,8 +4058,6 @@ }, "node_modules/get-symbol-description": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, "license": "MIT", "dependencies": { @@ -3727,8 +4074,6 @@ }, "node_modules/glob-parent": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "license": "ISC", "dependencies": { @@ -3740,8 +4085,6 @@ }, "node_modules/globals": { "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", "engines": { @@ -3753,8 +4096,6 @@ }, "node_modules/globalthis": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3770,8 +4111,6 @@ }, "node_modules/gopd": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -3782,8 +4121,6 @@ }, "node_modules/has-bigints": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, "license": "MIT", "engines": { @@ -3795,8 +4132,6 @@ }, "node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", "engines": { @@ -3805,8 +4140,6 @@ }, "node_modules/has-property-descriptors": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "license": "MIT", "dependencies": { @@ -3818,8 +4151,6 @@ }, "node_modules/has-proto": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3834,8 +4165,6 @@ }, "node_modules/has-symbols": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -3846,8 +4175,6 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -3861,8 +4188,6 @@ }, "node_modules/hasown": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -3873,8 +4198,6 @@ }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "license": "BSD-3-Clause", "dependencies": { "react-is": "^16.7.0" @@ -3882,14 +4205,10 @@ }, "node_modules/hoist-non-react-statics/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==", "license": "MIT" }, "node_modules/html-parse-stringify": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", - "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", "license": "MIT", "dependencies": { "void-elements": "3.1.0" @@ -3897,8 +4216,6 @@ }, "node_modules/http-proxy": { "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "license": "MIT", "dependencies": { "eventemitter3": "^4.0.0", @@ -3911,8 +4228,6 @@ }, "node_modules/http-proxy-middleware": { "version": "3.0.5", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.5.tgz", - "integrity": "sha512-GLZZm1X38BPY4lkXA01jhwxvDoOkkXqjgVyUzVxiEK4iuRu03PZoYHhHRwxnfhQMDuaxi3vVri0YgSro/1oWqg==", "license": "MIT", "dependencies": { "@types/http-proxy": "^1.17.15", @@ -3928,8 +4243,6 @@ }, "node_modules/i18next": { "version": "25.8.11", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.11.tgz", - "integrity": "sha512-LZ32llTLGludnddjLoijHV7TbmVubU5eJnsWf8taiuM3jmSfUuvBLuyDeubJKS1yBjLBgb7As124M4KWNcBvpw==", "funding": [ { "type": "individual", @@ -3945,6 +4258,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.28.4" }, @@ -3959,8 +4273,6 @@ }, "node_modules/i18next-browser-languagedetector": { "version": "8.2.1", - "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.2.1.tgz", - "integrity": "sha512-bZg8+4bdmaOiApD7N7BPT9W8MLZG+nPTOFlLiJiT8uzKXFjhxw4v2ierCXOwB5sFDMtuA5G4kgYZ0AznZxQ/cw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.23.2" @@ -3977,8 +4289,6 @@ }, "node_modules/ignore": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { @@ -3987,8 +4297,6 @@ }, "node_modules/immer": { "version": "11.1.4", - "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.4.tgz", - "integrity": "sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw==", "license": "MIT", "funding": { "type": "opencollective", @@ -3997,15 +4305,11 @@ }, "node_modules/immutable": { "version": "5.1.5", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", - "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", "dev": true, "license": "MIT" }, "node_modules/import-fresh": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -4020,8 +4324,6 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", "engines": { @@ -4030,8 +4332,6 @@ }, "node_modules/internal-slot": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, "license": "MIT", "dependencies": { @@ -4045,8 +4345,6 @@ }, "node_modules/is-array-buffer": { "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, "license": "MIT", "dependencies": { @@ -4063,14 +4361,10 @@ }, "node_modules/is-arrayish": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "license": "MIT" }, "node_modules/is-async-function": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4089,8 +4383,6 @@ }, "node_modules/is-bigint": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4105,8 +4397,6 @@ }, "node_modules/is-boolean-object": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, "license": "MIT", "dependencies": { @@ -4122,8 +4412,6 @@ }, "node_modules/is-callable": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, "license": "MIT", "engines": { @@ -4135,8 +4423,6 @@ }, "node_modules/is-core-module": { "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -4150,8 +4436,6 @@ }, "node_modules/is-data-view": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, "license": "MIT", "dependencies": { @@ -4168,8 +4452,6 @@ }, "node_modules/is-date-object": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, "license": "MIT", "dependencies": { @@ -4185,8 +4467,6 @@ }, "node_modules/is-extglob": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -4194,8 +4474,6 @@ }, "node_modules/is-finalizationregistry": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, "license": "MIT", "dependencies": { @@ -4210,8 +4488,6 @@ }, "node_modules/is-generator-function": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", - "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", "dev": true, "license": "MIT", "dependencies": { @@ -4230,8 +4506,6 @@ }, "node_modules/is-glob": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -4242,8 +4516,6 @@ }, "node_modules/is-map": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, "license": "MIT", "engines": { @@ -4253,10 +4525,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-mobile": { + "version": "5.0.0", + "license": "MIT" + }, "node_modules/is-negative-zero": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "license": "MIT", "engines": { @@ -4268,8 +4542,6 @@ }, "node_modules/is-number": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "license": "MIT", "engines": { "node": ">=0.12.0" @@ -4277,8 +4549,6 @@ }, "node_modules/is-number-object": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, "license": "MIT", "dependencies": { @@ -4294,8 +4564,6 @@ }, "node_modules/is-plain-object": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -4303,8 +4571,6 @@ }, "node_modules/is-regex": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, "license": "MIT", "dependencies": { @@ -4322,8 +4588,6 @@ }, "node_modules/is-set": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, "license": "MIT", "engines": { @@ -4335,8 +4599,6 @@ }, "node_modules/is-shared-array-buffer": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, "license": "MIT", "dependencies": { @@ -4351,8 +4613,6 @@ }, "node_modules/is-string": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, "license": "MIT", "dependencies": { @@ -4368,8 +4628,6 @@ }, "node_modules/is-symbol": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, "license": "MIT", "dependencies": { @@ -4386,8 +4644,6 @@ }, "node_modules/is-typed-array": { "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4402,8 +4658,6 @@ }, "node_modules/is-weakmap": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, "license": "MIT", "engines": { @@ -4415,8 +4669,6 @@ }, "node_modules/is-weakref": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, "license": "MIT", "dependencies": { @@ -4431,8 +4683,6 @@ }, "node_modules/is-weakset": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4448,22 +4698,16 @@ }, "node_modules/isarray": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true, "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, "license": "ISC" }, "node_modules/iterator.prototype": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", - "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", "dev": true, "license": "MIT", "dependencies": { @@ -4480,14 +4724,10 @@ }, "node_modules/js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -4499,8 +4739,6 @@ }, "node_modules/jsesc": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -4511,35 +4749,32 @@ }, "node_modules/json-buffer": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, "license": "MIT" }, + "node_modules/json2mq": { + "version": "0.2.0", + "license": "MIT", + "dependencies": { + "string-convert": "^0.2.0" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4554,8 +4789,6 @@ }, "node_modules/keyv": { "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "license": "MIT", "dependencies": { @@ -4564,8 +4797,6 @@ }, "node_modules/levn": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4578,8 +4809,6 @@ }, "node_modules/lightningcss": { "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", "dev": true, "license": "MPL-2.0", "dependencies": { @@ -4755,8 +4984,6 @@ }, "node_modules/lightningcss-linux-x64-gnu": { "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", - "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", "cpu": [ "x64" ], @@ -4776,8 +5003,6 @@ }, "node_modules/lightningcss-linux-x64-musl": { "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", - "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", "cpu": [ "x64" ], @@ -4839,14 +5064,10 @@ }, "node_modules/lines-and-columns": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, "node_modules/locate-path": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { @@ -4861,27 +5082,19 @@ }, "node_modules/lodash": { "version": "4.18.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", - "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, "node_modules/lodash-es": { "version": "4.18.1", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", - "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, "license": "MIT" }, "node_modules/loose-envify": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -4892,8 +5105,6 @@ }, "node_modules/magic-string": { "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4902,8 +5113,6 @@ }, "node_modules/map-obj": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-6.0.0.tgz", - "integrity": "sha512-PwDvwt/tK70+luLw5k9ySLtzLAzwf7tZTY9GBj63Y010nHRPjwHcQTpTd5JwQqITC2ty7prtxBo71iwyYY0TAg==", "license": "MIT", "engines": { "node": ">=20" @@ -4914,8 +5123,6 @@ }, "node_modules/math-intrinsics": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -4923,14 +5130,10 @@ }, "node_modules/memoize-one": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", - "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", "license": "MIT" }, "node_modules/micromatch": { "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -4942,8 +5145,6 @@ }, "node_modules/mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -4951,8 +5152,6 @@ }, "node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -4963,8 +5162,6 @@ }, "node_modules/minimatch": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -4976,8 +5173,6 @@ }, "node_modules/ms": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/nanoid": { @@ -5001,23 +5196,17 @@ }, "node_modules/natural-compare": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, "license": "MIT" }, "node_modules/node-addon-api": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "dev": true, "license": "MIT", "optional": true }, "node_modules/node-exports-info": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", - "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==", "dev": true, "license": "MIT", "dependencies": { @@ -5035,8 +5224,6 @@ }, "node_modules/node-fetch": { "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" @@ -5055,8 +5242,6 @@ }, "node_modules/object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5064,8 +5249,6 @@ }, "node_modules/object-inspect": { "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "license": "MIT", "engines": { @@ -5077,8 +5260,6 @@ }, "node_modules/object-keys": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, "license": "MIT", "engines": { @@ -5087,8 +5268,6 @@ }, "node_modules/object.assign": { "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, "license": "MIT", "dependencies": { @@ -5108,8 +5287,6 @@ }, "node_modules/object.entries": { "version": "1.1.9", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", - "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, "license": "MIT", "dependencies": { @@ -5124,8 +5301,6 @@ }, "node_modules/object.fromentries": { "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5143,8 +5318,6 @@ }, "node_modules/object.values": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", - "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, "license": "MIT", "dependencies": { @@ -5162,8 +5335,6 @@ }, "node_modules/obug": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", - "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", "dev": true, "funding": [ "https://github.com/sponsors/sxzz", @@ -5173,8 +5344,6 @@ }, "node_modules/optionator": { "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", "dependencies": { @@ -5191,8 +5360,6 @@ }, "node_modules/own-keys": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", "dev": true, "license": "MIT", "dependencies": { @@ -5209,8 +5376,6 @@ }, "node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5225,8 +5390,6 @@ }, "node_modules/p-locate": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { @@ -5241,8 +5404,6 @@ }, "node_modules/parent-module": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -5253,8 +5414,6 @@ }, "node_modules/parse-json": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", @@ -5271,8 +5430,6 @@ }, "node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", "engines": { @@ -5281,8 +5438,6 @@ }, "node_modules/path-key": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", "engines": { @@ -5291,14 +5446,10 @@ }, "node_modules/path-parse": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "license": "MIT" }, "node_modules/path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "license": "MIT", "engines": { "node": ">=8" @@ -5306,21 +5457,15 @@ }, "node_modules/pathe": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, "node_modules/picocolors": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "license": "MIT", "engines": { "node": ">=8.6" @@ -5331,8 +5476,6 @@ }, "node_modules/possible-typed-array-names": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true, "license": "MIT", "engines": { @@ -5370,8 +5513,6 @@ }, "node_modules/prelude-ls": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", "engines": { @@ -5380,8 +5521,6 @@ }, "node_modules/prop-types": { "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -5391,20 +5530,14 @@ }, "node_modules/prop-types/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==", "license": "MIT" }, "node_modules/property-expr": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", - "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==", "license": "MIT" }, "node_modules/proxy-from-env": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", - "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", "license": "MIT", "engines": { "node": ">=10" @@ -5412,8 +5545,6 @@ }, "node_modules/punycode": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", "engines": { @@ -5422,8 +5553,6 @@ }, "node_modules/quick-lru": { "version": "7.3.0", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-7.3.0.tgz", - "integrity": "sha512-k9lSsjl36EJdK7I06v7APZCbyGT2vMTsYSRX1Q2nbYmnkBqgUhRkAuzH08Ciotteu/PLJmIF2+tti7o3C/ts2g==", "license": "MIT", "engines": { "node": ">=18" @@ -5434,14 +5563,10 @@ }, "node_modules/raf-schd": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", - "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==", "license": "MIT" }, "node_modules/react": { "version": "19.2.5", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.5.tgz", - "integrity": "sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5449,8 +5574,6 @@ }, "node_modules/react-chartjs-2": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.1.tgz", - "integrity": "sha512-h5IPXKg9EXpjoBzUfyWJvllMjG2mQ4EiuHQFhms/AjUm0XSZHhyRy2xVmLXHKrtcdrPO4mnGqRtYoD0vp95A0A==", "license": "MIT", "peerDependencies": { "chart.js": "^4.1.1", @@ -5459,8 +5582,6 @@ }, "node_modules/react-datepicker": { "version": "8.10.0", - "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-8.10.0.tgz", - "integrity": "sha512-JIXuA+g+qP3c4MVJpx24o7n1gnv3WV/8A/D6964HucY1FlSEc30+ITPNUfbKZXYHl5rruCtxYCwi2lzn7gaz7g==", "license": "MIT", "dependencies": { "@floating-ui/react": "^0.27.15", @@ -5474,9 +5595,8 @@ }, "node_modules/react-dom": { "version": "19.2.5", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.5.tgz", - "integrity": "sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -5486,14 +5606,10 @@ }, "node_modules/react-fast-compare": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", - "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==", "license": "MIT" }, "node_modules/react-hotkeys-hook": { "version": "5.2.4", - "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-5.2.4.tgz", - "integrity": "sha512-BgKg+A1+TawkYluh5Bo4cTmcgMN5L29uhJbDUQdHwPX+qgXRjIPYU5kIDHyxnAwCkCBiu9V5OpB2mpyeluVF2A==", "license": "MIT", "peerDependencies": { "react": ">=16.8.0", @@ -5502,8 +5618,6 @@ }, "node_modules/react-i18next": { "version": "16.5.0", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.5.0.tgz", - "integrity": "sha512-IMpPTyCTKxEj8klCrLKUTIUa8uYTd851+jcu2fJuUB9Agkk9Qq8asw4omyeHVnOXHrLgQJGTm5zTvn8HpaPiqw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.27.6", @@ -5529,8 +5643,6 @@ }, "node_modules/react-icons": { "version": "5.6.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.6.0.tgz", - "integrity": "sha512-RH93p5ki6LfOiIt0UtDyNg/cee+HLVR6cHHtW3wALfo+eOHTp8RnU2kRkI6E+H19zMIs03DyxUG/GfZMOGvmiA==", "license": "MIT", "peerDependencies": { "react": "*" @@ -5538,14 +5650,19 @@ }, "node_modules/react-is": { "version": "19.2.5", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.5.tgz", - "integrity": "sha512-Dn0t8IQhCmeIT3wu+Apm1/YVsJXsGWi6k4sPdnBIdqMVtHtv0IGi6dcpNpNkNac0zB2uUAqNX3MHzN8c+z2rwQ==", "license": "MIT" }, + "node_modules/react-js-cron": { + "version": "5.2.0", + "license": "MIT", + "peerDependencies": { + "antd": ">=5.8.0", + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + } + }, "node_modules/react-redux": { "version": "9.2.0", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", - "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", "license": "MIT", "dependencies": { "@types/use-sync-external-store": "^0.0.6", @@ -5567,8 +5684,6 @@ }, "node_modules/react-router": { "version": "7.14.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.14.1.tgz", - "integrity": "sha512-5BCvFskyAAVumqhEKh/iPhLOIkfxcEUz8WqFIARCkMg8hZZzDYX9CtwxXA0e+qT8zAxmMC0x3Ckb9iMONwc5jg==", "license": "MIT", "dependencies": { "cookie": "^1.0.1", @@ -5589,8 +5704,6 @@ }, "node_modules/react-select": { "version": "5.10.2", - "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.10.2.tgz", - "integrity": "sha512-Z33nHdEFWq9tfnfVXaiM12rbJmk+QjFEztWLtmXqQhz6Al4UZZ9xc0wiatmGtUOCCnHN0WizL3tCMYRENX4rVQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.0", @@ -5610,8 +5723,6 @@ }, "node_modules/react-textarea-autosize": { "version": "8.5.9", - "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz", - "integrity": "sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.20.13", @@ -5627,8 +5738,6 @@ }, "node_modules/react-tooltip": { "version": "5.30.1", - "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.30.1.tgz", - "integrity": "sha512-1lSPLQXuVooePxadUpmcwLgOsF1mIty7UZTJ9XnyfX4drOzStYs4JMXnazcDLguQr41W5OUZddOp9kfvArdpEQ==", "license": "MIT", "dependencies": { "@floating-ui/dom": "^1.6.1", @@ -5641,8 +5750,6 @@ }, "node_modules/react-transition-group": { "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", "license": "BSD-3-Clause", "dependencies": { "@babel/runtime": "^7.5.5", @@ -5657,8 +5764,6 @@ }, "node_modules/react-window": { "version": "2.2.7", - "resolved": "https://registry.npmjs.org/react-window/-/react-window-2.2.7.tgz", - "integrity": "sha512-SH5nvfUQwGHYyriDUAOt7wfPsfG9Qxd6OdzQxl5oQ4dsSsUicqQvjV7dR+NqZ4coY0fUn3w1jnC5PwzIUWEg5w==", "license": "MIT", "peerDependencies": { "react": "^18.0.0 || ^19.0.0", @@ -5667,8 +5772,6 @@ }, "node_modules/readdirp": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, "license": "MIT", "engines": { @@ -5681,14 +5784,11 @@ }, "node_modules/redux": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", - "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/redux-persist": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz", - "integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==", "license": "MIT", "peerDependencies": { "redux": ">4.0.0" @@ -5696,8 +5796,6 @@ }, "node_modules/redux-thunk": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", - "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", "license": "MIT", "peerDependencies": { "redux": "^5.0.0" @@ -5705,8 +5803,6 @@ }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, "license": "MIT", "dependencies": { @@ -5728,8 +5824,6 @@ }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, "license": "MIT", "dependencies": { @@ -5749,20 +5843,14 @@ }, "node_modules/requires-port": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "license": "MIT" }, "node_modules/reselect": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", - "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", "license": "MIT" }, "node_modules/resolve": { "version": "1.22.12", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", - "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -5782,8 +5870,6 @@ }, "node_modules/resolve-from": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "license": "MIT", "engines": { "node": ">=4" @@ -5832,8 +5918,6 @@ }, "node_modules/safe-array-concat": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, "license": "MIT", "dependencies": { @@ -5852,8 +5936,6 @@ }, "node_modules/safe-push-apply": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, "license": "MIT", "dependencies": { @@ -5869,8 +5951,6 @@ }, "node_modules/safe-regex-test": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, "license": "MIT", "dependencies": { @@ -5887,10 +5967,9 @@ }, "node_modules/sass": { "version": "1.99.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.99.0.tgz", - "integrity": "sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.1.5", @@ -5908,14 +5987,17 @@ }, "node_modules/scheduler": { "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "license": "MIT" }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, "node_modules/semver": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { @@ -5924,14 +6006,10 @@ }, "node_modules/set-cookie-parser": { "version": "2.7.2", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", - "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", "license": "MIT" }, "node_modules/set-function-length": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "license": "MIT", "dependencies": { @@ -5948,8 +6026,6 @@ }, "node_modules/set-function-name": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5964,8 +6040,6 @@ }, "node_modules/set-proto": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", "dev": true, "license": "MIT", "dependencies": { @@ -5979,8 +6053,6 @@ }, "node_modules/shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", "dependencies": { @@ -5992,8 +6064,6 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { @@ -6002,8 +6072,6 @@ }, "node_modules/side-channel": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "license": "MIT", "dependencies": { @@ -6022,8 +6090,6 @@ }, "node_modules/side-channel-list": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", - "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "dev": true, "license": "MIT", "dependencies": { @@ -6039,8 +6105,6 @@ }, "node_modules/side-channel-map": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "license": "MIT", "dependencies": { @@ -6058,8 +6122,6 @@ }, "node_modules/side-channel-weakmap": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "license": "MIT", "dependencies": { @@ -6078,15 +6140,11 @@ }, "node_modules/siginfo": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, "license": "ISC" }, "node_modules/source-map": { "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -6094,8 +6152,6 @@ }, "node_modules/source-map-js": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -6104,22 +6160,16 @@ }, "node_modules/stackback": { "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, "license": "MIT" }, "node_modules/std-env": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", - "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", "dev": true, "license": "MIT" }, "node_modules/stop-iteration-iterator": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", - "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6130,10 +6180,12 @@ "node": ">= 0.4" } }, + "node_modules/string-convert": { + "version": "0.2.1", + "license": "MIT" + }, "node_modules/string.prototype.matchall": { "version": "4.0.12", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", - "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", "dev": true, "license": "MIT", "dependencies": { @@ -6160,8 +6212,6 @@ }, "node_modules/string.prototype.repeat": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", - "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", "dev": true, "license": "MIT", "dependencies": { @@ -6171,8 +6221,6 @@ }, "node_modules/string.prototype.trim": { "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "license": "MIT", "dependencies": { @@ -6193,8 +6241,6 @@ }, "node_modules/string.prototype.trimend": { "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6212,8 +6258,6 @@ }, "node_modules/string.prototype.trimstart": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "license": "MIT", "dependencies": { @@ -6230,8 +6274,6 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", "engines": { @@ -6243,14 +6285,10 @@ }, "node_modules/stylis": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", "license": "MIT" }, "node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { @@ -6262,8 +6300,6 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -6274,14 +6310,10 @@ }, "node_modules/tabbable": { "version": "6.4.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", - "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", "license": "MIT" }, "node_modules/tagged-tag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", - "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", "license": "MIT", "engines": { "node": ">=20" @@ -6290,35 +6322,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/throttle-debounce": { + "version": "5.0.2", + "license": "MIT", + "engines": { + "node": ">=12.22" + } + }, "node_modules/tiny-case": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", - "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==", "license": "MIT" }, "node_modules/tiny-invariant": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", "license": "MIT" }, "node_modules/tiny-warning": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", "license": "MIT" }, "node_modules/tinybench": { "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", "dev": true, "license": "MIT" }, "node_modules/tinyexec": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", - "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==", "dev": true, "license": "MIT", "engines": { @@ -6327,8 +6356,6 @@ }, "node_modules/tinyglobby": { "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", "dev": true, "license": "MIT", "dependencies": { @@ -6344,8 +6371,6 @@ }, "node_modules/tinyglobby/node_modules/fdir": { "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", "engines": { @@ -6362,10 +6387,9 @@ }, "node_modules/tinyglobby/node_modules/picomatch": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -6375,8 +6399,6 @@ }, "node_modules/tinyrainbow": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", - "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", "dev": true, "license": "MIT", "engines": { @@ -6385,8 +6407,6 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -6397,20 +6417,14 @@ }, "node_modules/toposort": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", "license": "MIT" }, "node_modules/tr46": { "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, "node_modules/ts-api-utils": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", - "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "license": "MIT", "engines": { @@ -6422,14 +6436,10 @@ }, "node_modules/tslib": { "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", "dependencies": { @@ -6441,8 +6451,6 @@ }, "node_modules/type-fest": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.5.0.tgz", - "integrity": "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==", "license": "(MIT OR CC0-1.0)", "dependencies": { "tagged-tag": "^1.0.0" @@ -6456,8 +6464,6 @@ }, "node_modules/typed-array-buffer": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, "license": "MIT", "dependencies": { @@ -6471,8 +6477,6 @@ }, "node_modules/typed-array-byte-length": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, "license": "MIT", "dependencies": { @@ -6491,8 +6495,6 @@ }, "node_modules/typed-array-byte-offset": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6513,8 +6515,6 @@ }, "node_modules/typed-array-length": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, "license": "MIT", "dependencies": { @@ -6534,10 +6534,9 @@ }, "node_modules/typescript": { "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6548,8 +6547,6 @@ }, "node_modules/typescript-eslint": { "version": "8.58.2", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.58.2.tgz", - "integrity": "sha512-V8iSng9mRbdZjl54VJ9NKr6ZB+dW0J3TzRXRGcSbLIej9jV86ZRtlYeTKDR/QLxXykocJ5icNzbsl2+5TzIvcQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6572,8 +6569,6 @@ }, "node_modules/unbox-primitive": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, "license": "MIT", "dependencies": { @@ -6591,14 +6586,10 @@ }, "node_modules/undici-types": { "version": "7.19.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", - "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", "license": "MIT" }, "node_modules/uri-js": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -6607,8 +6598,6 @@ }, "node_modules/use-composed-ref": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz", - "integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==", "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -6621,8 +6610,6 @@ }, "node_modules/use-isomorphic-layout-effect": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz", - "integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==", "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -6635,8 +6622,6 @@ }, "node_modules/use-latest": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz", - "integrity": "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==", "license": "MIT", "dependencies": { "use-isomorphic-layout-effect": "^1.1.1" @@ -6652,8 +6637,6 @@ }, "node_modules/use-sync-external-store": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", - "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -6661,8 +6644,6 @@ }, "node_modules/uuid": { "version": "13.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz", - "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", "dev": true, "funding": [ "https://github.com/sponsors/broofa", @@ -6679,6 +6660,7 @@ "integrity": "sha512-t7g7GVRpMXjNpa67HaVWI/8BWtdVIQPCL2WoozXXA7LBGEFK4AkkKkHx2hAQf5x1GZSlcmEDPkVLSGahxnEEZw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", @@ -6753,8 +6735,6 @@ }, "node_modules/vite/node_modules/picomatch": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -6766,8 +6746,6 @@ }, "node_modules/vitest": { "version": "4.1.4", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.4.tgz", - "integrity": "sha512-tFuJqTxKb8AvfyqMfnavXdzfy3h3sWZRWwfluGbkeR7n0HUev+FmNgZ8SDrRBTVrVCjgH5cA21qGbCffMNtWvg==", "dev": true, "license": "MIT", "dependencies": { @@ -6856,8 +6834,6 @@ }, "node_modules/vitest/node_modules/picomatch": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -6869,8 +6845,6 @@ }, "node_modules/void-elements": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", - "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -6878,14 +6852,10 @@ }, "node_modules/webidl-conversions": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "license": "BSD-2-Clause" }, "node_modules/whatwg-url": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "license": "MIT", "dependencies": { "tr46": "~0.0.3", @@ -6894,8 +6864,6 @@ }, "node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "license": "ISC", "dependencies": { @@ -6910,8 +6878,6 @@ }, "node_modules/which-boxed-primitive": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, "license": "MIT", "dependencies": { @@ -6930,8 +6896,6 @@ }, "node_modules/which-builtin-type": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dev": true, "license": "MIT", "dependencies": { @@ -6958,8 +6922,6 @@ }, "node_modules/which-collection": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, "license": "MIT", "dependencies": { @@ -6977,8 +6939,6 @@ }, "node_modules/which-typed-array": { "version": "1.1.20", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", - "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", "dev": true, "license": "MIT", "dependencies": { @@ -6999,8 +6959,6 @@ }, "node_modules/why-is-node-running": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, "license": "MIT", "dependencies": { @@ -7016,8 +6974,6 @@ }, "node_modules/word-wrap": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "license": "MIT", "engines": { @@ -7026,8 +6982,6 @@ }, "node_modules/yocto-queue": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", "engines": { @@ -7039,8 +6993,6 @@ }, "node_modules/yup": { "version": "1.7.1", - "resolved": "https://registry.npmjs.org/yup/-/yup-1.7.1.tgz", - "integrity": "sha512-GKHFX2nXul2/4Dtfxhozv701jLQHdf6J34YDh2cEkpqoo8le5Mg6/LrdseVLrFarmFygZTlfIhHx/QKfb/QWXw==", "license": "MIT", "dependencies": { "property-expr": "^2.0.5", @@ -7051,8 +7003,6 @@ }, "node_modules/yup/node_modules/type-fest": { "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=12.20" diff --git a/package.json b/package.json index 034aaad995..0ca4f4cebb 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "react-hotkeys-hook": "^5.2.4", "react-i18next": "16.5.0", "react-icons": "^5.5.0", + "react-js-cron": "^5.0.1", "react-redux": "^9.2.0", "react-router": "^7.13.0", "react-select": "^5.10.2", diff --git a/src/App.tsx b/src/App.tsx index 3f1a0b7a1c..80e34ec2e4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -15,6 +15,7 @@ import Acls from "./components/users/Acls"; import About from "./components/About"; import { useAppDispatch } from "./store"; import { fetchOcVersion, fetchUserInfo } from "./slices/userInfoSlice"; +import LifeCyclePolicies from "./components/events/LifeCyclePolicies"; import { subscribeToAuthEvents } from "./utils/broadcastSync"; import { useTableFilterStateValidation } from "./hooks/useTableFilterStateValidation"; import { Tooltip } from "react-tooltip"; @@ -48,6 +49,8 @@ function App() { } /> + } /> + } /> } /> diff --git a/src/components/events/LifeCyclePolicies.tsx b/src/components/events/LifeCyclePolicies.tsx new file mode 100644 index 0000000000..2143a9e4cb --- /dev/null +++ b/src/components/events/LifeCyclePolicies.tsx @@ -0,0 +1,121 @@ +import { useEffect, useRef, useState } from "react"; +import { useTranslation } from "react-i18next"; +import TableFilters from "../shared/TableFilters"; +import Table from "../shared/Table"; +import Notifications from "../shared/Notifications"; +import { loadLifeCyclePoliciesIntoTable } from "../../thunks/tableThunks"; +import { fetchFilters } from "../../slices/tableFilterSlice"; +import Header from "../Header"; +import NavBar from "../NavBar"; +import MainView from "../MainView"; +import Footer from "../Footer"; +import { useAppDispatch, useAppSelector } from "../../store"; +import { AsyncThunk } from "@reduxjs/toolkit"; +import { getTotalLifeCyclePolicies } from "../../selectors/lifeCycleSelectors"; +import { fetchLifeCyclePolicies } from "../../slices/lifeCycleSlice"; +import { lifeCyclePoliciesTemplateMap } from "../../configs/tableConfigs/lifeCyclePoliciesTableMap"; +import { fetchLifeCyclePolicyActions, fetchLifeCyclePolicyTargetTypes, fetchLifeCyclePolicyTimings } from "../../slices/lifeCycleDetailsSlice"; +import { ModalHandle } from "../shared/modals/Modal"; +import { eventsLinks } from "./partials/EventsNavigation"; +import { resetTableProperties } from "../../slices/tableSlice"; +import LifeCyclePolicyDetailsModal from "./partials/modals/LifeCyclePolicyDetailsModal"; + +/** + * This component renders the table view of policies + */ +const LifeCyclePolicies = () => { + const { t } = useTranslation(); + const dispatch = useAppDispatch(); + const [displayNavigation, setNavigation] = useState(false); + const newPolicyModalRef = useRef(null); + + const policiesTotal = useAppSelector(state => getTotalLifeCyclePolicies(state)); + + useEffect(() => { + // State variable for interrupting the load function + let allowLoadIntoTable = true; + + // Clear table of previous data + dispatch(resetTableProperties()); + + dispatch(fetchFilters("lifeCyclePolicies")); + + // Load policies on mount + const loadLifeCyclePolicies = async () => { + // Fetching policies from server + await dispatch(fetchLifeCyclePolicies()); + + // Load policies into table + if (allowLoadIntoTable) { + dispatch(loadLifeCyclePoliciesIntoTable()); + } + }; + loadLifeCyclePolicies(); + + // Fetch policies repeatedly + const fetchInterval = setInterval(loadLifeCyclePolicies, 5000); + + return () => { + allowLoadIntoTable = false; + clearInterval(fetchInterval); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const showNewPolicyModal = async () => { + await dispatch(fetchLifeCyclePolicyActions()); + await dispatch(fetchLifeCyclePolicyTargetTypes()); + await dispatch(fetchLifeCyclePolicyTimings()); + + newPolicyModalRef.current?.open(); + }; + + return ( + <> +
+ + + + + {/* Include notifications component */} + + +
+ {/* Include filters component */} + {/* LifeCycle policies are not indexed, can't search or filter them */} + {/* But if we don't include this component, the policies won't load on page load, because the first + fetch request we send to the backend contains invalid params >.> */} + } + loadResourceIntoTable={loadLifeCyclePoliciesIntoTable} + resource={"lifeCyclePolicies"} + /> + +

{t("LIFECYCLE.POLICIES.TABLE.CAPTION")}

+

{t("TABLE_SUMMARY", { numberOfRows: policiesTotal })}

+
+ {/* Include table component */} + + +
+ + {/* Include table modal */} + + + ); +}; + +export default LifeCyclePolicies; diff --git a/src/components/events/partials/EventsNavigation.tsx b/src/components/events/partials/EventsNavigation.tsx index 5c21a230ec..45d0eac8e9 100644 --- a/src/components/events/partials/EventsNavigation.tsx +++ b/src/components/events/partials/EventsNavigation.tsx @@ -18,4 +18,9 @@ export const eventsLinks: { accessRole: "ROLE_UI_SERIES_VIEW", text: "EVENTS.EVENTS.NAVIGATION.SERIES", }, + { + path: "/events/lifeCyclePolicies", + accessRole: "ROLE_UI_LIFECYCLEPOLICIES_VIEW", + text: "LIFECYCLE.NAVIGATION.POLICIES", + }, ]; diff --git a/src/components/events/partials/LifeCyclePolicyActionCell.tsx b/src/components/events/partials/LifeCyclePolicyActionCell.tsx new file mode 100644 index 0000000000..357e41ed69 --- /dev/null +++ b/src/components/events/partials/LifeCyclePolicyActionCell.tsx @@ -0,0 +1,54 @@ +import { useAppDispatch } from "../../../store"; +import { deleteLifeCyclePolicy, LifeCyclePolicy } from "../../../slices/lifeCycleSlice"; +import { fetchLifeCyclePolicyDetails, openModal } from "../../../slices/lifeCycleDetailsSlice"; +import ButtonLikeAnchor from "../../shared/ButtonLikeAnchor"; +import { LuFileText } from "react-icons/lu"; +import { ActionCellDelete } from "../../shared/ActionCellDelete"; + +/** + * This component renders the title cells of series in the table view + */ +const LifeCyclePolicyActionCell = ({ + row, +}: { + row: LifeCyclePolicy +}) => { + const dispatch = useAppDispatch(); + + const showLifeCyclePolicyDetails = async () => { + await dispatch(fetchLifeCyclePolicyDetails(row.id)); + + dispatch(openModal(row)); + }; + + const deletingPolicy = (id: string) => { + dispatch(deleteLifeCyclePolicy(id)); + }; + + return ( + <> + {/* view details location/recording */} + showLifeCyclePolicyDetails()} + className={"action-cell-button"} + editAccessRole={"ROLE_UI_LIFECYCLEPOLICY_DETAILS_VIEW"} + // tooltipText={"LIFECYCLE.POLICIES.TABLE.TOOLTIP.DETAILS"} // Disabled due to performance concerns + > + + + + + {/* delete policy */} + + + ); +}; + +export default LifeCyclePolicyActionCell; diff --git a/src/components/events/partials/LifeCyclePolicyIsActiveCell.tsx b/src/components/events/partials/LifeCyclePolicyIsActiveCell.tsx new file mode 100644 index 0000000000..358c5c131e --- /dev/null +++ b/src/components/events/partials/LifeCyclePolicyIsActiveCell.tsx @@ -0,0 +1,21 @@ +import { LifeCyclePolicy } from "../../../slices/lifeCycleSlice"; + +/** + * This component renders the maintenance cells of servers in the table view + */ +const LifeCyclePolicyIsActiveCell = ({ + row, +}: { + row: LifeCyclePolicy +}) => { + + return ( + + ); +}; + +export default LifeCyclePolicyIsActiveCell; diff --git a/src/components/events/partials/ModalTabsAndPages/EventDetailsLifeCyclePolicy.tsx b/src/components/events/partials/ModalTabsAndPages/EventDetailsLifeCyclePolicy.tsx new file mode 100644 index 0000000000..7b15f69ab3 --- /dev/null +++ b/src/components/events/partials/ModalTabsAndPages/EventDetailsLifeCyclePolicy.tsx @@ -0,0 +1,111 @@ +import { useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import { useAppDispatch, useAppSelector } from "../../../../store"; +import { getLifeCyclePoliciesForEvent } from "../../../../selectors/eventDetailsSelectors"; +import { fetchEventLifeCyclePolicies } from "../../../../slices/eventDetailsSlice"; +import ModalContentTable from "../../../shared/modals/ModalContentTable"; +import Notifications from "../../../shared/Notifications"; +import ButtonLikeAnchor from "../../../shared/ButtonLikeAnchor"; +import { LuChevronRight } from "react-icons/lu"; +import { useNavigate } from "react-router"; +import { fetchLifeCyclePolicyDetails, openModal } from "../../../../slices/lifeCycleDetailsSlice"; +import { LifeCyclePolicy } from "../../../../slices/lifeCycleSlice"; + + +/** + * This component shows lifecycle policies that would affect the event + */ +const EventDetailsLifeCyclePolicy = ({ + eventId, +}: { + eventId: string, +}) => { + const { t } = useTranslation(); + const dispatch = useAppDispatch(); + const navigate = useNavigate(); + + const policies = useAppSelector(state => getLifeCyclePoliciesForEvent(state)); + + useEffect(() => { + dispatch(fetchEventLifeCyclePolicies(eventId)); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const openPolicyDetails = async (policy: LifeCyclePolicy) => { + await dispatch(fetchLifeCyclePolicyDetails(policy.id)); + dispatch(openModal(policy)); + navigate("/events/lifeCyclePolicies"); + }; + + return ( + } + > + {/* Disclaimer */} +
+
+ {t("EVENTS.EVENTS.DETAILS.LIFECYCLEPOLICIES.DISCLAIMER.TITLE")} +
+
+ {t("EVENTS.EVENTS.DETAILS.LIFECYCLEPOLICIES.DISCLAIMER.MESSAGE")} +
+
+ +
+ { + /* No policies message */ + policies.length === 0 && ( +
+ + + +
+ {t("EVENTS.EVENTS.DETAILS.LIFECYCLEPOLICIES.EMPTY")} +
+ ) + } + + { policies.length !== 0 && ( +
+ + <> + + + + + + + { + policies.map((policy, key) => ( + + + + {/* link to 'Details' sub-Tab */} + + + )) + } + + +
+ {t("EVENTS.EVENTS.DETAILS.LIFECYCLEPOLICIES.TABLE_TITLE")} + +
+ {policy.title} + + openPolicyDetails(policy)} + > + {t("EVENTS.EVENTS.DETAILS.MEDIA.DETAILS")} + + +
+
+ )} + + + ); +}; + +export default EventDetailsLifeCyclePolicy; diff --git a/src/components/events/partials/ModalTabsAndPages/EventDetailsWorkflowSchedulingTab.tsx b/src/components/events/partials/ModalTabsAndPages/EventDetailsWorkflowSchedulingTab.tsx index 20dad74e06..c6befa37b0 100644 --- a/src/components/events/partials/ModalTabsAndPages/EventDetailsWorkflowSchedulingTab.tsx +++ b/src/components/events/partials/ModalTabsAndPages/EventDetailsWorkflowSchedulingTab.tsx @@ -187,6 +187,7 @@ const EventDetailsWorkflowSchedulingTab = ({
{hasCurrentAgentAccess() && isRoleWorkflowEdit && + formik.values.configuration && !!workflowConfiguration && !!workflowConfiguration.workflowId && (
)} diff --git a/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyAccessTab.tsx b/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyAccessTab.tsx new file mode 100644 index 0000000000..e375ee96fd --- /dev/null +++ b/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyAccessTab.tsx @@ -0,0 +1,56 @@ +import { useEffect } from "react"; +import ResourceDetailsAccessPolicyTab from "../../../shared/modals/ResourceDetailsAccessPolicyTab"; +import { removeNotificationWizardForm } from "../../../../slices/notificationSlice"; +import { useAppDispatch, useAppSelector } from "../../../../store"; +import { getLifeCyclePolicyDetailsAcl } from "../../../../selectors/lifeCycleDetailsSelectors"; +import { fetchLifeCyclePolicyDetailsAcls, updateLifeCyclePolicyAccess } from "../../../../slices/lifeCycleDetailsSlice"; +import { ParseKeys } from "i18next"; + +/** + * This component manages the access policy tab of the series details modal + */ +const LifeCyclePolicyDetailsAccessTab = ({ + seriesId, + header, + policyChanged, + setPolicyChanged, +}: { + seriesId: string, + header: ParseKeys, + policyChanged: boolean, + setPolicyChanged: (value: boolean) => void, +}) => { + const dispatch = useAppDispatch(); + + const acl = useAppSelector(state => getLifeCyclePolicyDetailsAcl(state)); + + useEffect(() => { + dispatch(removeNotificationWizardForm()); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( + + ); +}; + +export default LifeCyclePolicyDetailsAccessTab; diff --git a/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyGeneralTab.tsx b/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyGeneralTab.tsx new file mode 100644 index 0000000000..5e1ba8b7dc --- /dev/null +++ b/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyGeneralTab.tsx @@ -0,0 +1,188 @@ +import { useTranslation } from "react-i18next"; +import { LifeCyclePolicy, TargetFilter } from "../../../../slices/lifeCycleSlice"; +import { useAppDispatch, useAppSelector } from "../../../../store"; +import { Formik, FormikProps } from "formik"; +import Notifications from "../../../shared/Notifications"; +import cn from "classnames"; +import { ConfigurationPanelField } from "../../../../slices/workflowSlice"; +import { updateLifeCyclePolicy } from "../../../../slices/lifeCycleDetailsSlice"; +import LifeCyclePolicyGeneralFields from "../wizards/LifeCyclePolicyGeneralFields"; +import { hasAccess } from "../../../../utils/utils"; +import { getUserInformation } from "../../../../selectors/userInfoSelectors"; +import { LifeCyclePolicySchema } from "../../../../utils/validate"; +import _ from "lodash"; +import { parseTargetFiltersForEditing, parseTargetFiltersForSubmit } from "../../../../utils/lifeCycleUtils"; + +/** + * This component renders details about a recording/capture agent + */ +const LifeCyclePolicyGeneralTab = ({ + policy, +}: { + policy: LifeCyclePolicy +}) => { + const { t } = useTranslation(); + const dispatch = useAppDispatch(); + + const user = useAppSelector(state => getUserInformation(state)); + + const handleSubmit = (values: LifeCyclePolicy & { + workflowParameters: ConfigurationPanelField[], + targetFiltersTransformed: { [key: string]: (TargetFilter & { filter: string })[] } + }) => { + + // Parse filters + const targetFilters: typeof values["targetFilters"] = parseTargetFiltersForSubmit(values.targetFiltersTransformed); + + // TODO: Improve workflowParameters rendering + // Parse action parameters + // const workflowParameters: { [key: string]: unknown} = {}; + // for (const field of values.workflowParameters) { + // if (field.fieldset && field.fieldset.length > 0) { + // workflowParameters[field.fieldset[0].name] = field.fieldset[0].value + // } + // } + // const newActionParameters = { + // ...values.actionParameters, + // workflowParameters + // } + + const newValues = { + ...values, + targetFilters: targetFilters, + // actionParameters: newActionParameters, + }; + // values.actionParameters["workflowParameters"] = JSON.stringify(workflowParameters); + + dispatch(updateLifeCyclePolicy(newValues)); + }; + + // set current values of metadata fields as initial values + const getInitialValues = (policy: LifeCyclePolicy) => { + const initialValues: LifeCyclePolicy & { + workflowParameters: ConfigurationPanelField[], + targetFiltersTransformed: { [key: string]: (TargetFilter & { filter: string })[] } + } = { + workflowParameters: [], + targetFiltersTransformed: {}, + ...policy, + }; + + // Access policies are handled in a different tab + // Remove them here, else they will delete the ACL due to their formatting + // @ts-expect-error: TODO: Find a typesafe (or straight up better) way to do this + delete initialValues.accessControlEntries; + + // Transform filters into something more editable + const targetFiltersTransformed = { + "dublincore/episode": [], + ...parseTargetFiltersForEditing(policy.targetFilters), + }; + // for (const key in policy.targetFilters) { + // targetFiltersArray.push({ + // filter: key, + // ...policy.targetFilters[key], + // }); + // } + + // TODO: Improve workflowParameters rendering + // Parse action parameters + // const configPanelFields: ConfigurationPanelField[] = [] + // const workflowParameters = JSON.parse(policy.actionParameters["workflowParameters"] as string) + // Object.entries(workflowParameters).forEach(([key, value]) => { + // configPanelFields.push({ + // fieldset: [{ + // name: key, + // value: value, + // defaultValue: value, + // type: "text", + // checked: false, + // label: key, + // }] + // }); + // }); + + initialValues.targetFiltersTransformed = targetFiltersTransformed; + // initialValues.workflowParameters = configPanelFields; + + return initialValues; + }; + + const checkValidity = (formik: FormikProps) => { + if (formik.dirty && formik.isValid && hasAccess("ROLE_UI_LIFECYCLEPOLICY_DETAILS_GENERAL_EDIT", user)) { + // check if user provided values differ from initial ones + return !_.isEqual(formik.values, formik.initialValues); + } else { + return false; + } + }; + + return ( + // initialize form + handleSubmit(values)} + > + {formik => ( + <> +
+
+ +
+ {/*
+
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.CAPTION")}
*/} + + {/* Render fields */} + + +
+
+ {t("LIFECYCLE.POLICIES.DETAILS.GENERAL.NOTE.TITLE")} +
+
+ {t("LIFECYCLE.POLICIES.DETAILS.GENERAL.NOTE.MESSAGE")} +
+
+ + {formik.dirty && ( + <> + {/* Render buttons for updating metadata */} +
+ + +
+ +
+ + )} + {/*
*/} +
+
+
+ + )} + + ); +}; + +export default LifeCyclePolicyGeneralTab; diff --git a/src/components/events/partials/ModalTabsAndPages/NewAccessPage.tsx b/src/components/events/partials/ModalTabsAndPages/NewAccessPage.tsx index b2a7d9961b..c1bbf944a3 100644 --- a/src/components/events/partials/ModalTabsAndPages/NewAccessPage.tsx +++ b/src/components/events/partials/ModalTabsAndPages/NewAccessPage.tsx @@ -25,7 +25,7 @@ import ModalContentTable from "../../../shared/modals/ModalContentTable"; */ interface RequiredFormProps { metadata: { - "dublincore/episode_isPartOf": string, + "dublincore/episode_isPartOf"?: string, }, policies: TransformedAcl[], aclTemplate: string, @@ -81,16 +81,14 @@ const NewAccessPage = ({ if (initEventAclWithSeriesAcl && formik.values.metadata["dublincore/episode_isPartOf"]) { dispatch(fetchSeriesDetailsAcls(formik.values.metadata["dublincore/episode_isPartOf"])); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [formik.values.metadata["dublincore/episode_isPartOf"], initEventAclWithSeriesAcl, dispatch]); + }, [initEventAclWithSeriesAcl, dispatch, formik.values.metadata]); // If we have to use series ACL, overwrite existing rules useEffect(() => { if (initEventAclWithSeriesAcl && formik.values.metadata["dublincore/episode_isPartOf"] && seriesAcl) { formik.setFieldValue("policies", seriesAcl); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [initEventAclWithSeriesAcl, seriesAcl]); + }, [formik, initEventAclWithSeriesAcl, seriesAcl]); return ( <> diff --git a/src/components/events/partials/ModalTabsAndPages/NewLifeCyclePolicyGeneralPage.tsx b/src/components/events/partials/ModalTabsAndPages/NewLifeCyclePolicyGeneralPage.tsx new file mode 100644 index 0000000000..06aa64f775 --- /dev/null +++ b/src/components/events/partials/ModalTabsAndPages/NewLifeCyclePolicyGeneralPage.tsx @@ -0,0 +1,37 @@ +import { FormikProps } from "formik"; +import WizardNavigationButtons from "../../../shared/wizard/WizardNavigationButtons"; +import LifeCyclePolicyGeneralFields from "../wizards/LifeCyclePolicyGeneralFields"; +import { LifeCyclePolicy, TargetFilter } from "../../../../slices/lifeCycleSlice"; + +/** + * This component renders the metadata page for new events and series in the wizards. + */ +const NewLifeCyclePolicyGeneralPage = ({ + formik, + nextPage, +}: { + formik: FormikProps, + nextPage: (values: T) => void, +}) => { + + return ( + <> +
+
+
+ {/* Table view containing input fields for metadata */} + +
+
+
+ + {/* Button for navigation to next page */} + + + ); +}; + +export default NewLifeCyclePolicyGeneralPage; diff --git a/src/components/events/partials/ModalTabsAndPages/NewProcessingPage.tsx b/src/components/events/partials/ModalTabsAndPages/NewProcessingPage.tsx index 4cf30ad41b..9fb09e62a7 100644 --- a/src/components/events/partials/ModalTabsAndPages/NewProcessingPage.tsx +++ b/src/components/events/partials/ModalTabsAndPages/NewProcessingPage.tsx @@ -17,6 +17,7 @@ import ModalContentTable from "../../../shared/modals/ModalContentTable"; interface RequiredFormProps { sourceMode: string, processingWorkflow: string, + configuration: { [key: string]: any }, } const NewProcessingPage = ({ @@ -118,8 +119,8 @@ const NewProcessingPage = ({ ) : null}
diff --git a/src/components/events/partials/modals/EventDetails.tsx b/src/components/events/partials/modals/EventDetails.tsx index 6e190df462..2380f55fcc 100644 --- a/src/components/events/partials/modals/EventDetails.tsx +++ b/src/components/events/partials/modals/EventDetails.tsx @@ -51,6 +51,7 @@ import { NOTIFICATION_CONTEXT } from "../../../../configs/modalConfig"; import { unwrapResult } from "@reduxjs/toolkit"; import { ParseKeys } from "i18next"; import EventDetailsWorkflowSchedulingTab from "../ModalTabsAndPages/EventDetailsWorkflowSchedulingTab"; +import EventDetailsLifeCyclePolicy from "../ModalTabsAndPages/EventDetailsLifeCyclePolicy"; import { useHotkeys } from "react-hotkeys-hook"; import { availableHotkeys } from "../../../../configs/hotkeysConfig"; @@ -65,6 +66,7 @@ export enum EventDetailsPage { Comments, Tobira, Statistics, + LifeCyclePolicies, } export type WorkflowTabHierarchy = "workflows" | "workflow-details" | "workflow-operations" | "workflow-operation-details" | "errors-and-warnings" | "workflow-error-details" @@ -219,6 +221,12 @@ const EventDetails = ({ page: EventDetailsPage.Statistics, hidden: !hasStatistics, }, + { + tabNameTranslation: "EVENTS.EVENTS.DETAILS.TABS.LIFECYCLEPOLICIES", + accessRole: "ROLE_UI_EVENTS_DETAILS_LIFECYCLEPOLICIES_VIEW", + name: "lifecyclepolicies", + page: EventDetailsPage.LifeCyclePolicies, + }, ]; const openTab = (tabNr: EventDetailsPage) => { @@ -372,6 +380,11 @@ const EventDetails = ({ header={tabs[page].bodyHeaderTranslation ?? "EVENTS.EVENTS.DETAILS.STATISTICS.CAPTION"} /> )} + {page === EventDetailsPage.LifeCyclePolicies && ( + + )}
); diff --git a/src/components/events/partials/modals/LifeCyclePolicyDetails.tsx b/src/components/events/partials/modals/LifeCyclePolicyDetails.tsx new file mode 100644 index 0000000000..cd3d871a4e --- /dev/null +++ b/src/components/events/partials/modals/LifeCyclePolicyDetails.tsx @@ -0,0 +1,78 @@ +import { useEffect, useState } from "react"; +import ModalNavigation from "../../../shared/modals/ModalNavigation"; +import { getLifeCyclePolicyDetails } from "../../../../selectors/lifeCycleDetailsSelectors"; +import LifeCyclePolicyGeneralTab from "../ModalTabsAndPages/LifeCyclePolicyGeneralTab"; +import LifeCyclePolicyDetailsAccessTab from "../ModalTabsAndPages/LifeCyclePolicyAccessTab"; +import { useAppDispatch, useAppSelector } from "../../../../store"; +import { removeNotificationWizardForm } from "../../../../slices/notificationSlice"; +import { fetchLifeCyclePolicyActions, fetchLifeCyclePolicyTargetTypes, fetchLifeCyclePolicyTimings } from "../../../../slices/lifeCycleDetailsSlice"; +import { ParseKeys } from "i18next"; + +/** + * This component manages the tabs of the series details modal + */ +const LifeCyclePolicyDetails = ({ + policyId, + policyChanged, + setPolicyChanged, +}: { + policyId: string + policyChanged: boolean + setPolicyChanged: (policyChanged: boolean) => void +}) => { + const [page, setPage] = useState(0); + const dispatch = useAppDispatch(); + + useEffect(() => { + dispatch(removeNotificationWizardForm()); + dispatch(fetchLifeCyclePolicyActions()); + dispatch(fetchLifeCyclePolicyTargetTypes()); + dispatch(fetchLifeCyclePolicyTimings()); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const policy = useAppSelector(state => getLifeCyclePolicyDetails(state)); + + // information about tabs + const tabs: { + tabTranslation: ParseKeys, + accessRole: string, + name: string, + }[] = [ + { + tabTranslation: "LIFECYCLE.POLICIES.DETAILS.TAB.GENERAL", + accessRole: "ROLE_UI_LIFECYCLEPOLICIES_DETAILS_GENERAL_VIEW", + name: "general", + }, + { + tabTranslation: "LIFECYCLE.POLICIES.DETAILS.TAB.ACCESSPOLICIES", + accessRole: "ROLE_UI_LIFECYCLEPOLICIES_DETAILS_ACCESSPOLICIES_VIEW", + name: "Access Policies", + }, + ]; + + const openTab = (tabNr: number) => { + setPage(tabNr); + }; + + return ( + <> + {/* Navigation */} + + +
+ {page === 0 && } + {page === 1 && + + } +
+ + ); +}; + +export default LifeCyclePolicyDetails; diff --git a/src/components/events/partials/modals/LifeCyclePolicyDetailsModal.tsx b/src/components/events/partials/modals/LifeCyclePolicyDetailsModal.tsx new file mode 100644 index 0000000000..fccb476353 --- /dev/null +++ b/src/components/events/partials/modals/LifeCyclePolicyDetailsModal.tsx @@ -0,0 +1,68 @@ +import { useRef, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { removeNotificationWizardForm } from "../../../../slices/notificationSlice"; +import { useAppDispatch, useAppSelector } from "../../../../store"; +import { Modal } from "../../../shared/modals/Modal"; +import { confirmUnsaved } from "../../../../utils/utils"; +import { FormikProps } from "formik"; +import LifeCyclePolicyDetails from "./LifeCyclePolicyDetails"; +import { getModalLifeCyclePolicy, showModal } from "../../../../selectors/lifeCycleDetailsSelectors"; +import { setModalLifeCyclePolicy, setShowModal } from "../../../../slices/lifeCycleDetailsSlice"; + +/** + * This component renders the modal for displaying lifecycle policy details + */ +const LifeCyclePolicyDetailsModal = () => { + const { t } = useTranslation(); + const dispatch = useAppDispatch(); + + // tracks, whether the policies are different to the initial value + const [policyChanged, setPolicyChanged] = useState(false); + const formikRef = useRef>(null); + + const displayDetailsModal = useAppSelector(state => showModal(state)); + const policy = useAppSelector(state => getModalLifeCyclePolicy(state))!; + + const hideModal = () => { + dispatch(setModalLifeCyclePolicy(null)); + dispatch(setShowModal(false)); + }; + + const close = () => { + let isUnsavedChanges = false; + isUnsavedChanges = policyChanged; + if (formikRef.current && formikRef.current.dirty !== undefined && formikRef.current.dirty) { + isUnsavedChanges = true; + } + + if (!isUnsavedChanges || confirmUnsaved(t)) { + setPolicyChanged(false); + dispatch(removeNotificationWizardForm()); + hideModal(); + return true; + } + return false; + }; + + return ( + <> + {displayDetailsModal && + + setPolicyChanged(value)} + /> + + } + + ); +}; + +export default LifeCyclePolicyDetailsModal; diff --git a/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx b/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx new file mode 100644 index 0000000000..24a83d0e6e --- /dev/null +++ b/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx @@ -0,0 +1,584 @@ +import { useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import { FieldArray, FieldProps, FormikProps } from "formik"; +import { Field } from "../../../shared/Field"; +import RenderField from "../../../shared/wizard/RenderField"; +import { ALL_TARGET_FILTER_TYPES, LifeCyclePolicy, TargetFilter } from "../../../../slices/lifeCycleSlice"; +import { useAppDispatch, useAppSelector } from "../../../../store"; +import { getLifeCyclePolicyActions, getLifeCyclePolicyTargetTypes, getLifeCyclePolicyTimings } from "../../../../selectors/lifeCycleDetailsSelectors"; +import DropDown from "../../../shared/DropDown"; +import { getEventMetadata } from "../../../../selectors/eventSelectors"; +import { fetchEventMetadata } from "../../../../slices/eventSlice"; +import { formatPolicyActionsForDropdown, formatWorkflowsForDropdown } from "../../../../utils/dropDownUtils"; +import { getWorkflowDef } from "../../../../selectors/workflowSelectors"; +import { fetchWorkflowDef } from "../../../../slices/workflowSlice"; +import RenderWorkflowConfig, { Configuration } from "./RenderWorkflowConfig"; +import { setDefaultConfig } from "../../../../utils/workflowPanelUtils"; +import ButtonLikeAnchor from "../../../shared/ButtonLikeAnchor"; +import { LuCircleX } from "react-icons/lu"; + +/** + * This component renders the metadata page for new events and series in the wizards. + */ +// interface RequiredFormProps { +// sourceMode: string, +// processingWorkflow: string, +// } +type EventFilterOption = { + id: string, + type: string, + collection?: unknown +} + +const LifeCyclePolicyGeneralFields = ({ + formik, + isNew, +}: { + formik: FormikProps, + isNew: boolean +}) => { + const { t } = useTranslation(); + const dispatch = useAppDispatch(); + + const actions = useAppSelector(state => getLifeCyclePolicyActions(state)); + const targetTypes = useAppSelector(state => getLifeCyclePolicyTargetTypes(state)); + const timings = useAppSelector(state => getLifeCyclePolicyTimings(state)); + const metadataFields = useAppSelector(state => getEventMetadata(state)); + + useEffect(() => { + dispatch(fetchEventMetadata()); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const ADDITIONAL_TARGET_FILTER_KEYS_EVENTS = [ + { + id: "series_name", + type: "text", + collection: undefined, + }, + { + id: "presenter", + type: "text", + collection: undefined, + }, + { + id: "start_date", + type: "date", + collection: undefined, + }, + { + id: "end_date", + type: "date", + collection: undefined, + }, + { + id: "created", + type: "date", + collection: undefined, + }, + { + id: "source", + type: "text", + collection: undefined, + }, + { + id: "rights", + type: "text", + collection: undefined, + }, + { + id: "location", + type: "text", + collection: undefined, + }, + ]; + + const eventFilterOptions: EventFilterOption[] = []; + for (const field of metadataFields.fields) { + eventFilterOptions.push(field); + } + for (const field of ADDITIONAL_TARGET_FILTER_KEYS_EVENTS) { + eventFilterOptions.push(field); + } + + const createTargetFilter = (): TargetFilter => { + return { + value: "", + type: "SEARCH", + must: true, + }; + }; + + const filterOptions = (targetType: string) => { + switch (targetType) { + case "EVENT": + return eventFilterOptions; + default: + return []; + } + }; + + const filterTargetTypesByFilter = (filter: string) => { + const event = eventFilterOptions.find(event => event.id === filter); + + if (!event) { + return ALL_TARGET_FILTER_TYPES; + } + if (event.type.includes("text")) { + return ["SEARCH", "WILDCARD"]; + } + if (event.type.includes("date")) { + return ["GREATER_THAN", "LESS_THAN"]; + } + return ALL_TARGET_FILTER_TYPES; + }; + + + return ( + <> +
+
{t("LIFECYCLE.POLICIES.NEW.GENERAL.CAPTION")}
+ + + + + + + + + + + + {!isNew && + + + + + } + + + + + + + + + + + + + {formik.values.timing === "SPECIFIC_DATE" && + + + + + } + {formik.values.timing === "REPEATING" && + + + + + } + {!isNew && + + + + + } + + +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TITLE")}* + +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ISACTIVE")}* + +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ISCREATEDFROMCONFIG")} + +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETTYPE")}* + ({ value: element, name: element })), + id: "language", + }} + component={RenderField} + /> +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TIMING")}* + ({ value: element, name: element })), + id: "language", + }} + component={RenderField} + /> +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTION")}* + ({ value: element, name: element })), + id: "language", + }} + component={RenderField} + /> +
+ {t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTIONDATE")} + {formik.values.timing === "SPECIFIC_DATE" && *} + + +
+ {t("LIFECYCLE.POLICIES.DETAILS.GENERAL.CRONTRIGGER")} + {formik.values.timing === "REPEATING" && *} + + +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ID")} + {formik.values.id} +
+
+ +
+ + + {/* Target Filters like the ACLs + Can we make "key" a dropdown? + Type of "Value" should depend on key, e.g. for key "start_date" show a date picker + */} +
+
+ { t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETFILTERS.CAPTION") } +
+ + + {/* column headers */} + + + + + + + + + + + + {Object.entries(formik.values.targetFiltersTransformed).map(([outerKey, filters]) => { + if (outerKey !== "dublincore/episode") { return null; } + + return ( + ( + <> + {Object.entries(filters).map(([key, filter], index) => { + // Get available filter options + const availableFilterOptions = filterOptions(formik.values.targetType); + + // Derive available type options based on selected filter + const dependentTypeOptions = filterTargetTypesByFilter(filter.filter); + + return ( + + + + + + + + ); + })} + + + + + )} + /> + ); + })} + +
+ { t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETFILTERS.FILTER") } + + { t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETFILTERS.VALUE") } + + { t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETFILTERS.TYPE") } + + { t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETFILTERS.MUST") } + + { t("EVENTS.EVENTS.DETAILS.ACCESS.ACCESS_POLICY.ACTION") } +
+ e.id)} + creatable={true} + clearFieldName={`targetFiltersTransformed.${outerKey}.${key}.value`} + component={DropdownField} + onChangeOverride={(element: { value: string; label: string } | null) => { + formik.setFieldValue(`targetFiltersTransformed.${outerKey}.${key}.value`, undefined); + formik.setFieldValue(`targetFiltersTransformed.${outerKey}.${key}.filter`, element?.value ?? undefined); + // Reset type when filter changes + formik.setFieldValue(`targetFiltersTransformed.${outerKey}.${key}.type`, undefined); + }} + /> + + + + + + + + arrayHelpers.remove(index)} + className="action-cell-button remove" + > + + +
+ + arrayHelpers.push(createTargetFilter()) + } + className="button-like-anchor" + > + +{" "} + {t( + "LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETFILTERS.NEW", + )} + +
+
+ + {formik.values.action === "START_WORKFLOW" && + + } + + ); +}; + + +export default LifeCyclePolicyGeneralFields; + +const DropdownField = ({ + field, + form: { setFieldValue }, + value, + values, + clearFieldName, + creatable = false, + onChangeOverride, +}: { + field: FieldProps["field"] + form: FieldProps["form"] + value: string, + values: string[] + clearFieldName: string + creatable: boolean + onChangeOverride?: (element: { value: string; label: string } | null) => void +}) => { + const { t } = useTranslation(); + + const handleChange = (element: { value: string; label: string } | null) => { + if (onChangeOverride) { + // call the override function if provided + onChangeOverride(element); + } else { + // default behavior + setFieldValue(clearFieldName, undefined); + if (element) { + setFieldValue(field.name, element.value); + } + } + }; + + return ( + + ); +}; + +const getTargetFilterRenderType = (filterName: string, targetFilterOptions: { id: string, type: string, collection?: unknown }[]) => { + const option = targetFilterOptions.find(e => e.id === filterName); + if (option === undefined) { + return "text"; + } + // Simplify types like "long_text" or "mixed_text" + if (option.type.includes("text")) { + return "text"; + } + return option.type; +}; + +const getTargetFilterRenderCollection = (filterName: string, targetFilterOptions: { id: string, type: string, collection?: unknown }[]) => { + const option = targetFilterOptions.find(e => e.id === filterName); + return option !== undefined ? option.collection : undefined; +}; + +const WorkflowSelector = ({ + formik, +}: { + formik: FormikProps, +}) => { + const { t } = useTranslation(); + const dispatch = useAppDispatch(); + + const workflowDef = useAppSelector(state => getWorkflowDef(state)); + // const lol = JSON.parse(formik.values.actionParameters.workflowParameters) + + useEffect(() => { + // Load workflow definitions for selecting + dispatch(fetchWorkflowDef("tasks")); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const setDefaultValues = (value: string) => { + const workflowId = value; + // fill values with default configuration of chosen workflow + const defaultConfiguration = setDefaultConfig(workflowDef, workflowId); + + // set default configuration in formik + formik.setFieldValue("actionParameters.workflowParameters", defaultConfiguration); + // set chosen workflow in formik + formik.setFieldValue("actionParameters.workflowId", workflowId); + }; + + return ( +
+
+ {t("EVENTS.EVENTS.NEW.PROCESSING.SELECT_WORKFLOW")} +
+
+ {workflowDef.length > 0 ? ( +
+ + formik.values.actionParameters.workflowId === workflow.id, + )?.title ?? "" + } + options={formatWorkflowsForDropdown(workflowDef)} + required={true} + handleChange={element => { + if (element) { + setDefaultValues(element.value as string); + } + }} + placeholder={t( + "EVENTS.EVENTS.NEW.PROCESSING.SELECT_WORKFLOW", + )} + customCSS={{ width: "100%" }} + /> +
+ ) : ( + + {t("EVENTS.EVENTS.NEW.PROCESSING.SELECT_WORKFLOW_EMPTY")} + + )} + + {/* Configuration panel of selected workflow */} +
+
+ {formik.values.actionParameters.workflowId ? ( + + ) : null} +
+
+
+
+ ); +}; diff --git a/src/components/events/partials/wizards/NewEventWizard.tsx b/src/components/events/partials/wizards/NewEventWizard.tsx index 1512c7021b..e6d616185a 100644 --- a/src/components/events/partials/wizards/NewEventWizard.tsx +++ b/src/components/events/partials/wizards/NewEventWizard.tsx @@ -225,11 +225,8 @@ const NewEventWizard = ({ )} {steps[page].name === "access" && ( ({ + formik, + previousPage, +}: { + formik: FormikProps, + previousPage: (values: T, twoPagesBack?: boolean) => void, +}) => { + const { t } = useTranslation(); + + return ( + <> +
+
+
+ +
+
{t("LIFECYCLE.POLICIES.NEW.CAPTION")}
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + )) + ))} + + + + + + {/* @ts-expect-error: Potentially unknown */} + + + + + + ))} + + + } + + + +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TITLE")}{formik.values.title}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ISACTIVE")}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETTYPE")}{formik.values.targetType}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TIMING")}{formik.values.timing}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTION")}{formik.values.action}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTIONDATE")}{t("dateFormats.dateTime.medium", { dateTime: renderValidDate(formik.values.actionDate) })}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.CRONTRIGGER")}{formik.values.cronTrigger}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETFILTERS.CAPTION")} + {Object.entries(formik.values.targetFiltersTransformed) + .filter(([outerKey]) => outerKey === "dublincore/episode") + .map(([_outerKey, filters]) => ( + filters.map((filter, key) => ( +
{filter.filter}{filter.value.toString()}{filter.type}{filter.must.toString()}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTIONPARAMETERS.CAPTION")} + {formik.values.action === "START_WORKFLOW" && +
{formik.values.actionParameters.workflowId} + {/* @ts-expect-error: Potentially unknown */} + {Object.entries(formik.values.actionParameters.workflowParameters).map(([key, value]) => ( +
{key}{String(value)}
+
+
+ {/* Summary access configuration */} + + +
+
+
+ + {/* Button for navigation to next page and previous page */} + + + ); +}; + +export default NewLifeCyclePolicySummary; diff --git a/src/components/events/partials/wizards/NewLifeCyclePolicyWizard.tsx b/src/components/events/partials/wizards/NewLifeCyclePolicyWizard.tsx new file mode 100644 index 0000000000..050b75e7f0 --- /dev/null +++ b/src/components/events/partials/wizards/NewLifeCyclePolicyWizard.tsx @@ -0,0 +1,181 @@ +import { useEffect, useState } from "react"; +import { Formik } from "formik"; +import NewAccessPage from "../ModalTabsAndPages/NewAccessPage"; +import WizardStepper from "../../../shared/wizard/WizardStepper"; +import { useAppDispatch, useAppSelector } from "../../../../store"; +import { getUserInformation } from "../../../../selectors/userInfoSelectors"; +import { UserInfoState } from "../../../../slices/userInfoSlice"; +import { postNewLifeCyclePolicy } from "../../../../slices/lifeCycleSlice"; +import NewLifeCyclePolicyGeneralPage from "../ModalTabsAndPages/NewLifeCyclePolicyGeneralPage"; +import NewLifeCyclePolicySummary from "./NewLifeCyclePolicySummary"; +import { LifeCyclePolicySchema } from "../../../../utils/validate"; +import { initialFormValuesNewLifeCyclePolicy } from "../../../../configs/modalConfig"; +import { parseTargetFiltersForSubmit } from "../../../../utils/lifeCycleUtils"; +import { ParseKeys } from "i18next"; + +/** + * This component manages the pages of the new event wizard and the submission of values + */ +const NewLifeCyclePolicyWizard = ({ + close, +}: { + close: () => void +}) => { + const dispatch = useAppDispatch(); + + const user = useAppSelector(state => getUserInformation(state)); + + const initialValues = getInitialValues(user); + + const [page, setPage] = useState(0); + const [snapshot, setSnapshot] = useState(initialValues); + const [pageCompleted, setPageCompleted] = useState<{ [key: number]: boolean }>({}); + + // Caption of steps used by Stepper + const steps: { + translation: ParseKeys, + name: string, + hidden: boolean, + }[] = [ + { + translation: "LIFECYCLE.POLICIES.NEW.GENERAL.CAPTION", + name: "general", + hidden: false, + }, + { + translation: "EVENTS.EVENTS.NEW.ACCESS.CAPTION", + name: "access", + hidden: false, + }, + { + translation: "EVENTS.EVENTS.NEW.SUMMARY.CAPTION", + name: "summary", + hidden: false, + }, + ]; + + const nextPage = (values: typeof initialValues) => { + setSnapshot(values); + + // set page as completely filled out + const updatedPageCompleted = pageCompleted; + updatedPageCompleted[page] = true; + setPageCompleted(updatedPageCompleted); + + let newPage = page; + do { + newPage = newPage + 1; + } while (steps[newPage] && steps[newPage].hidden); + if (steps[newPage]) { + setPage(newPage); + } + }; + + const previousPage = (values: typeof initialValues) => { + setSnapshot(values); + + let newPage = page; + do { + newPage = newPage - 1; + } while (steps[newPage] && steps[newPage].hidden); + if (steps[newPage]) { + setPage(newPage); + } + }; + + const handleSubmit = (values: typeof initialValues) => { + const fixedValues = { + ...values, + targetFilters: parseTargetFiltersForSubmit(values.targetFiltersTransformed), + accessControlEntries: values.policies, + }; + + const response = dispatch(postNewLifeCyclePolicy(fixedValues)); + console.info(response); + close(); + }; + + return ( + <> + handleSubmit(values)} + > + {/* Render wizard pages depending on current value of page variable */} + {formik => { + // eslint-disable-next-line react-hooks/rules-of-hooks + useEffect(() => { + formik.validateForm(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [page]); + + return ( + <> + {/* Stepper that shows each step of wizard as header */} + +
+ {page === 0 && ( + + )} + {page === 1 && ( + + )} + {page === 2 && ( + + )} +
+ + ); + }} +
+ + ); +}; + +// Transform all initial values needed from information provided by backend +const getInitialValues = ( + user: UserInfoState, +) => { + const initialValues = initialFormValuesNewLifeCyclePolicy; + + initialValues["policies"] = [ + { + role: user.userRole, + read: true, + write: true, + actions: [], + user: user.user, + }, + ]; + + return initialValues; +}; + +export default NewLifeCyclePolicyWizard; diff --git a/src/components/events/partials/wizards/RenderWorkflowConfig.tsx b/src/components/events/partials/wizards/RenderWorkflowConfig.tsx index cbff50f703..ea25c00685 100644 --- a/src/components/events/partials/wizards/RenderWorkflowConfig.tsx +++ b/src/components/events/partials/wizards/RenderWorkflowConfig.tsx @@ -1,28 +1,27 @@ import React from "react"; import { v4 as uuidv4 } from "uuid"; -import { FormikProps } from "formik"; import { Field } from "../../../shared/Field"; import { getWorkflowDefById, } from "../../../../selectors/workflowSelectors"; import { useAppSelector } from "../../../../store"; -import { FieldSetField } from "../../../../slices/workflowSlice"; +import { ConfigurationPanelField, FieldSetField } from "../../../../slices/workflowSlice"; /** * This component renders the configuration panel for the selected workflow in the processing step of the new event * wizard chosen via dropdown. */ -interface RequiredFormProps { - configuration?: { [key: string]: any } -} +export type Configuration = { [key: string]: any } -const RenderWorkflowConfig = ({ +const RenderWorkflowConfig = ({ workflowId, - formik, + configuration, + configurationName, displayDescription, }: { workflowId: string - formik: FormikProps + configuration: Configuration + configurationName: string displayDescription?: boolean }) => { @@ -32,13 +31,35 @@ const RenderWorkflowConfig = ({ const configPanel = !!workflowDef && workflowDef.configurationPanelJson ? workflowDef.configurationPanelJson : []; - const description = !!workflowDef && workflowDef.description + const description = !!workflowDef && workflowDef.description && !displayDescription ? workflowDef.description : ""; + return ( + + ); +}; + +export const WorkflowConfig = ({ + configuration, + configurationName, + configPanel, + description, +}: { + configuration: Configuration + configurationName: string + configPanel: string | ConfigurationPanelField[] + description: string +}) => { + return ( <> - {displayDescription && description.length > 0 && ( + {description.length > 0 && (
{description.trim()}
@@ -57,7 +78,7 @@ const RenderWorkflowConfig = ({ )}
    {configOption.fieldset?.map((field, keys) => - renderInputByType(field, keys, formik), + renderInputByType(field, keys, configuration, configurationName), )}
@@ -70,50 +91,50 @@ const RenderWorkflowConfig = ({ }; // render input depending on field type -const renderInputByType = ( +const renderInputByType = ( field: FieldSetField, key: React.Key | null | undefined, - formik: FormikProps, + configuration: Configuration, + configurationName: string, ) => { switch (field.type) { case "checkbox": - return ; + return ; case "radio": - return ; + return ; case "number": - return ; + return ; case "text": - return ; + return ; case "datetime-local": - return ; + return ; default: return ""; } }; -const RenderDatetimeLocal = ( - { field, formik } : { field: FieldSetField, formik: FormikProps }) => { - return ; +const RenderDatetimeLocal = ( + { field, configuration, configurationName } : { field: FieldSetField, configuration: Configuration, configurationName: string }) => { + return ; }; -const RenderCheckbox = ( - { field, formik } : { field: FieldSetField, formik: FormikProps }) => { - return ; +const RenderCheckbox = ( + { field, configuration, configurationName } : { field: FieldSetField, configuration: Configuration, configurationName: string }) => { + return ; }; -const RenderRadio = ( - { field } : { field: FieldSetField, formik: FormikProps }) => { +const RenderRadio = ( + { field, configuration, configurationName } : { field: FieldSetField, configuration: Configuration, configurationName: string }) => { return (
  • {field.options?.map(option => , @@ -123,8 +144,8 @@ const RenderRadio = ( ); }; -const RenderNumber = ( - { field, formik } : { field: FieldSetField, formik: FormikProps }) => { +const RenderNumber = ( + { field, configuration, configurationName } : { field: FieldSetField, configuration: Configuration, configurationName: string }) => { // validate that value of number is between max and min const validate = (value: string) => { let error; @@ -134,26 +155,30 @@ const RenderNumber = ( return error; }; - return ; + return ; }; -const RenderText = ({ +const RenderText = ({ field, - formik, + configuration, + configurationName, }: { field: FieldSetField, - formik: FormikProps, + configuration: Configuration, + configurationName: string, }) => { - return ; + return ; }; -const RenderField = ({ +const RenderField = ({ field, - formik, + configuration, + configurationName, validate = undefined, }: { field: FieldSetField, - formik: FormikProps, + configuration: Configuration, + configurationName: string, validate?: (value: any) => string | undefined, }) => { // id used for Field and label @@ -167,7 +192,7 @@ const RenderField = ({ defaultValue={field.defaultValue} validate={validate} className="configField" - name={"configuration." + field.name} + name={configurationName + "." + field.name} disabled={disabled} type={field.type} min={field.min} @@ -182,9 +207,9 @@ const RenderField = ({ {/* if input has an additional fieldset or further configuration inputs then render again by input type*/} - {!!field.fieldset && !!formik.values.configuration && !!formik.values.configuration[field.name] && ( + {!!field.fieldset && !!configuration && !!configuration[field.name] && (
      - {field.fieldset?.map((f, keys) => renderInputByType(f, keys, formik))} + {field.fieldset?.map((f, keys) => renderInputByType(f, keys, configuration, configurationName))}
    )}
  • diff --git a/src/components/shared/ConfirmModal.tsx b/src/components/shared/ConfirmModal.tsx index 200bcf6e46..91f758002b 100644 --- a/src/components/shared/ConfirmModal.tsx +++ b/src/components/shared/ConfirmModal.tsx @@ -5,7 +5,7 @@ import { NotificationComponent } from "./Notifications"; import { ParseKeys } from "i18next"; import BaseButton from "./BaseButton"; -export type ResourceType = "EVENT" | "SERIES" | "LOCATION" | "USER" | "GROUP" | "ACL" | "THEME" | "TOBIRA_PATH"; +export type ResourceType = "EVENT" | "SERIES" | "LOCATION" | "USER" | "GROUP" | "ACL" | "THEME" | "TOBIRA_PATH" | "LIFECYCLE_POLICY"; const ConfirmModal = ({ close, diff --git a/src/components/shared/MainNav.tsx b/src/components/shared/MainNav.tsx index d4c4445f4b..a52db1ca41 100644 --- a/src/components/shared/MainNav.tsx +++ b/src/components/shared/MainNav.tsx @@ -91,6 +91,12 @@ const MainNav = ({ tooltipTitle: "NAV.EVENTS.TITLE", Icon: LuCalendarCheck, }, + { + path: "/events/lifeCyclePolicies", + accessRole: "ROLE_UI_LIFECYCLEPOLICIES_VIEW", + tooltipTitle: "NAV.EVENTS.TITLE", + Icon: LuCalendarCheck, + }, ], }, "recordings": { diff --git a/src/components/shared/NewResourceModal.tsx b/src/components/shared/NewResourceModal.tsx index 488931b7f1..610c26dfb2 100644 --- a/src/components/shared/NewResourceModal.tsx +++ b/src/components/shared/NewResourceModal.tsx @@ -6,6 +6,7 @@ import NewThemeWizard from "../configuration/partials/wizard/NewThemeWizard"; import NewAclWizard from "../users/partials/wizard/NewAclWizard"; import NewGroupWizard from "../users/partials/wizard/NewGroupWizard"; import NewUserWizard from "../users/partials/wizard/NewUserWizard"; +import NewLifeCyclePolicyWizard from "../events/partials/wizards/NewLifeCyclePolicyWizard"; import { Modal, ModalHandle } from "./modals/Modal"; /** @@ -17,16 +18,17 @@ export type NewResource = | "user" | "group" | "acl" - | "themes"; + | "themes" + | "lifecyclepolicy"; const NewResourceModal = ({ handleClose, resource, modalRef, }: { - handleClose: () => void; - resource: "events" | "series" | "user" | "group" | "acl" | "themes"; - modalRef: React.RefObject; + handleClose: () => void, + resource: NewResource + modalRef: React.RefObject }) => { const { t } = useTranslation(); @@ -48,6 +50,8 @@ const NewResourceModal = ({ return t("USERS.GROUPS.NEW.CAPTION"); case "user": return t("USERS.USERS.DETAILS.NEWCAPTION"); + case "lifecyclepolicy": + return t("LIFECYCLE.POLICIES.NEW.CAPTION"); } }; @@ -56,6 +60,7 @@ const NewResourceModal = ({ header={headerText()} classId="add-event-modal" // initialFocus={"#firstField"} + focusTrapActive={resource === "lifecyclepolicy" ? false : true} ref={modalRef} > {resource === "events" && ( @@ -82,6 +87,10 @@ const NewResourceModal = ({ // New User Wizard )} + {resource === "lifecyclepolicy" && ( + // New LifeCyclePolicy Wizard + + )} ); }; diff --git a/src/components/shared/modals/Modal.tsx b/src/components/shared/modals/Modal.tsx index 3f9e471d65..f117c4e560 100644 --- a/src/components/shared/modals/Modal.tsx +++ b/src/components/shared/modals/Modal.tsx @@ -23,6 +23,7 @@ export type ModalProps = { header: string; classId: string; className?: string; + focusTrapActive?: boolean; // Deactive focus trap, because it clashes with react-js-cron (can't click on dropdown elements) }; export type ModalHandle = { @@ -33,7 +34,7 @@ export type ModalHandle = { export const Modal = forwardRef>( ( - { open = false, closeCallback, header, classId, className, children }, + { open = false, closeCallback, header, classId, className, children, focusTrapActive = true }, ref, ) => { const { t } = useTranslation(); @@ -69,7 +70,9 @@ export const Modal = forwardRef>( return ReactDOM.createPortal( isOpen && - +
    )} + {metadataField.type === "cron" && ( + + )}
    {!focused && showCheck && ( { + + return ( +
    + setFieldValue(field.name, value)} + /> +
    + ); + //
    setEditMode(true)} className="show-edit"> + // {text || ""} + //
    + // + // {showCheck && ( + // + // )} + //
    + //
    +}; + /** * Special case for series. Uses an async selector to fetch options. * diff --git a/src/configs/modalConfig.ts b/src/configs/modalConfig.ts index b1c9cf6ed9..69bb0c4623 100644 --- a/src/configs/modalConfig.ts +++ b/src/configs/modalConfig.ts @@ -5,6 +5,7 @@ import { TobiraPage } from "../slices/seriesSlice"; import { initArray } from "../utils/utils"; import { EditedEvents, Event, UploadAssetsTrack } from "../slices/eventSlice"; import { Role } from "../slices/aclSlice"; +import { TargetFilter } from "../slices/lifeCycleSlice"; import { ParseKeys } from "i18next"; import { UserRole } from "../slices/userSlice"; @@ -220,3 +221,37 @@ export const initialFormValuesEditScheduledEvents: { editedEvents: [], changedEvents: [], }; + +export const initialFormValuesNewLifeCyclePolicy: { + title: string, + isActive: boolean, + isCreatedFromConfig: boolean, + targetType: string, + timing: string, + action: string, + actionDate: string, + cronTrigger: string, + actionParameters: { [key: string]: unknown } + policies: TransformedAcl[] + targetFiltersTransformed: { [key: string]: (TargetFilter & { filter: string })[] }, +} = { + title: "", + isActive: true, + isCreatedFromConfig: false, + targetType: "EVENT", + timing: "SPECIFIC_DATE", + action: "START_WORKFLOW", + actionDate: "", + cronTrigger: "", + actionParameters: { + // workflowId: "noop", + // workflowParameters: "{\"straightToPublishing\": true}", + workflowId: "", + workflowParameters: { }, + }, + + policies: [], + targetFiltersTransformed: { + "dublincore/episode": [], + }, +}; diff --git a/src/configs/tableConfigs/lifeCyclePoliciesTableConfig.ts b/src/configs/tableConfigs/lifeCyclePoliciesTableConfig.ts new file mode 100644 index 0000000000..71a47c8a8e --- /dev/null +++ b/src/configs/tableConfigs/lifeCyclePoliciesTableConfig.ts @@ -0,0 +1,30 @@ +import { TableConfig } from "./aclsTableConfig"; + +export const lifeCyclePolicyTableConfig: TableConfig = { + columns: [ + { + name: "title", + label: "LIFECYCLE.POLICIES.TABLE.TITLE", + sortable: true, + }, + { + template: "LifeCyclePolicyIsActiveCell", + name: "isActive", + label: "LIFECYCLE.POLICIES.TABLE.ISACTIVE", + }, + { + name: "timing", + label: "LIFECYCLE.POLICIES.TABLE.TIMING", + sortable: true, + }, + { + template: "LifeCyclePolicyActionCell", + name: "actions", + label: "LIFECYCLE.POLICIES.TABLE.ACTION", + }, + ], + caption: "TABLE.CAPTION", + resource: "lifeCyclePolicies", + category: "events", + multiSelect: false, +}; diff --git a/src/configs/tableConfigs/lifeCyclePoliciesTableMap.ts b/src/configs/tableConfigs/lifeCyclePoliciesTableMap.ts new file mode 100644 index 0000000000..7a460a6363 --- /dev/null +++ b/src/configs/tableConfigs/lifeCyclePoliciesTableMap.ts @@ -0,0 +1,11 @@ +import LifeCyclePolicyActionCell from "../../components/events/partials/LifeCyclePolicyActionCell"; +import LifeCyclePolicyIsActiveCell from "../../components/events/partials/LifeCyclePolicyIsActiveCell"; + +/** + * This map contains the mapping between the template strings above and the corresponding react component. + * This helps to render different templates of cells more dynamically + */ +export const lifeCyclePoliciesTemplateMap = { + LifeCyclePolicyIsActiveCell: LifeCyclePolicyIsActiveCell, + LifeCyclePolicyActionCell: LifeCyclePolicyActionCell, +}; diff --git a/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json b/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json index 27ad431218..57a6c729f3 100644 --- a/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json +++ b/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json @@ -122,6 +122,7 @@ "USER": "The following user will be deleted", "THEME": "The following theme will be deleted", "LOCATION": "The following location will be deleted", + "LIFECYCLE_POLICY": "The following lifeCycle policy will be deleted", "TOBIRA_PATH": "The series will be removed from the following path in Tobira:" }, "NAME": "Name" @@ -203,6 +204,10 @@ "EVENTS_NOT_DELETED_NOT_AUTHORIZED": "The event(s) could not be deleted, because you don't have the permission to do so.", "SERIES_DELETED": "The series has been deleted", "SERIES_NOT_DELETED": "The series could not be deleted", + "LIFECYCLE_POLICY_ADDED": "The lifeCycle policy has been created", + "LIFECYCLE_POLICY_NOT_SAVED": "The lifeCycle policy could not be saved", + "LIFECYCLE_POLICY_DELETED": "The lifeCycle policy has been deleted", + "LIFECYCLE_POLICY_NOT_DELETED": "The lifeCycle policy could not be deleted", "LOCATION_DELETED": "The location has been deleted", "LOCATION_NOT_DELETED": "The location could not be deleted", "LOCATION_NOT_DELETED_NOT_AUTHORIZED": "The location could not be deleted, because you don't have the permission to do so.", @@ -211,7 +216,6 @@ "CONFLICT_ALREADY_ENDED": "Scheduling error: The event has already ended.", "CONFLICT_END_BEFORE_START": "Scheduling error: Schedule end has to be later than the start.", "CONFLICT_IN_THE_PAST": "The schedule could not be updated: You cannot schedule an event to be in the past.", - "CONFLICT_END_TIME_TOO_EARLY": "This event cannot be modified because it is currently in progress.", "CONFLICT_RANGE_DAYS":"At least one repeat day must be within the scheduled date range.", "INVALID_ACL_RULES": "Rules have to contain a valid role and read or/and write right(s).", "MISSING_ACL_RULES": "At least one role with Read and Write permissions is required!", @@ -710,7 +714,8 @@ "ACCESS": "Access policy", "COMMENTS": "Comments", "STATISTICS": "Statistics", - "TOBIRA": "Tobira" + "TOBIRA": "Tobira", + "LIFECYCLEPOLICIES": "LifeCycle Policies" }, "PUBLICATIONS": { "CAPTION": "Publications", @@ -1114,6 +1119,15 @@ "TECHNICAL_DETAILS": "Technical details", "OPERATION": "Operation the error occured in" } + }, + "LIFECYCLEPOLICIES": { + "EMPTY": "No policies found", + "TABLE_TITLE": "LifeCycle Policies", + "TITLE": "Policy title", + "DISCLAIMER": { + "TITLE": "Important note", + "MESSAGE": "The list contains lifecycle policies that would affect this event, were the policies to be executed right now. Since policies only decide which events they affect on the moment of their execution, this list cannot claim to be accurate. A policy appearing in the list below is no guarantee that the policy will affect this event." + } } } }, @@ -1291,6 +1305,77 @@ } } }, + "LIFECYCLE": { + "NAVIGATION": { + "POLICIES": "LifeCycle Policies" + }, + "POLICIES": { + "TABLE": { + "ACTION": "Actions", + "CAPTION": "LifeCycle Policies", + "ISACTIVE": "Active", + "TIMING": "Timing", + "TITLE": "Title", + "TOOLTIP": { + "DETAILS": "LifeCycle Policy Details", + "DELETE": "Delete LifeCycle Policy" + }, + "ADD_POLICY": "Add LifeCycle Policy" + }, + "NEW": { + "CAPTION": "Create LifeCycle Policy", + "GENERAL": { + "CAPTION": "General" + } + }, + "DETAILS": { + "HEADER": "LifeCycle Policy Details", + "GENERAL": { + "ACTION": "Action", + "ACTIONDATE": "Action Date", + "ACTIONPARAMETERS": { + "CAPTION": "Action Parameters", + "WORKFLOW_ID": "Workflow ID", + "WORKFLOW_PARAMETERS": "Workflow Parameters" + }, + "CAPTION": "LifeCycle Policy Details", + "CRONTRIGGER": "Cron Trigger", + "ID": "Identifier", + "ISACTIVE": "Active", + "ISCREATEDFROMCONFIG": "Created from Config", + "TARGETTYPE": "Target Type", + "TARGETFILTERS": { + "CAPTION": "Target Filters", + "FILTER": "Filter", + "VALUE": "Value", + "TYPE": "Type", + "MUST": "Must", + "NEW": "New Filter" + }, + "TIMING": "Timing", + "TITLE": "Title", + "NOTE": { + "TITLE": "A note on editing LifeCycle Policies", + "MESSAGE": "The same policy cannot affect the same target multiple times. Depending on your goals, creating a new policy may be required." + } + }, + "ACCESS": { + "LABEL": "Select a template", + "DESCRIPTION": "At least one role with Read and Write permissions is required.", + "NON_USER_ROLES": "Roles and Groups authorized for the policy", + "ROLE": "Role", + "NEW": "New policy", + "USER": "User", + "USERS": "Users who are authorized for the policy", + "NEW_USER": "New user" + }, + "TAB": { + "GENERAL": "General", + "ACCESSPOLICIES": "Access Policies" + } + } + } + }, "RECORDINGS": { "NAVIGATION": { "LOCATIONS": "Locations" diff --git a/src/selectors/eventDetailsSelectors.ts b/src/selectors/eventDetailsSelectors.ts index 5ca19b608d..993e9cc777 100644 --- a/src/selectors/eventDetailsSelectors.ts +++ b/src/selectors/eventDetailsSelectors.ts @@ -193,3 +193,6 @@ export const hasStatisticsError = (state: RootState) => state.eventDetails.hasStatisticsError; export const isFetchingStatistics = (state: RootState) => state.eventDetails.statusStatistics === "loading"; + +export const getLifeCyclePoliciesForEvent = (state: RootState) => + state.eventDetails.lifeCyclePolicies; diff --git a/src/selectors/lifeCycleDetailsSelectors.ts b/src/selectors/lifeCycleDetailsSelectors.ts new file mode 100644 index 0000000000..6db657af6d --- /dev/null +++ b/src/selectors/lifeCycleDetailsSelectors.ts @@ -0,0 +1,14 @@ +import { RootState } from "../store"; + +/** + * This file contains selectors regarding details of a certain lifeCyclePolicy/capture agent + */ +/* selectors for modal */ +export const showModal = (state: RootState) => state.lifeCyclePolicyDetails.modal.show; +export const getModalLifeCyclePolicy = (state: RootState) => state.lifeCyclePolicyDetails.modal.policy; + +export const getLifeCyclePolicyDetails = (state: RootState) => state.lifeCyclePolicyDetails; +export const getLifeCyclePolicyDetailsAcl = (state: RootState) => state.lifeCyclePolicyDetails.accessControlEntries; +export const getLifeCyclePolicyActions = (state: RootState) => state.lifeCyclePolicyDetails.actionsEnum; +export const getLifeCyclePolicyTargetTypes = (state: RootState) => state.lifeCyclePolicyDetails.targetTypesEnum; +export const getLifeCyclePolicyTimings = (state: RootState) => state.lifeCyclePolicyDetails.timingsEnum; diff --git a/src/selectors/lifeCycleSelectors.ts b/src/selectors/lifeCycleSelectors.ts new file mode 100644 index 0000000000..fadb641e3d --- /dev/null +++ b/src/selectors/lifeCycleSelectors.ts @@ -0,0 +1,7 @@ +import { RootState } from "../store"; + +/** + * This file contains selectors regarding acls + */ +export const getLifeCyclePolicies = (state: RootState) => state.lifeCycle.results; +export const getTotalLifeCyclePolicies = (state: RootState) => state.lifeCycle.total; diff --git a/src/slices/eventDetailsSlice.ts b/src/slices/eventDetailsSlice.ts index 879ce760d2..a435b176b2 100644 --- a/src/slices/eventDetailsSlice.ts +++ b/src/slices/eventDetailsSlice.ts @@ -38,6 +38,7 @@ import { Ace } from "./aclSlice"; import { setTobiraTabHierarchy, TobiraData } from "./seriesDetailsSlice"; import { handleTobiraError } from "./shared/tobiraErrors"; import camelcaseKeys from "camelcase-keys"; +import { LifeCyclePolicy } from "./lifeCycleSlice"; // Contains the navigation logic for the modal type EventDetailsModal = { @@ -218,6 +219,8 @@ type EventDetailsState = { errorStatisticsValue: SerializedError | null, statusTobiraData: "uninitialized" | "loading" | "succeeded" | "failed", errorTobiraData: SerializedError | null, + statusLifeCyclePolicies: "uninitialized" | "loading" | "succeeded" | "failed", + errorLifeCyclePolicies: SerializedError | null, eventId: string, modal: EventDetailsModal, metadata: MetadataCatalog, @@ -377,6 +380,7 @@ type EventDetailsState = { statistics: Statistics[], hasStatisticsError: boolean, tobiraData: TobiraData, + lifeCyclePolicies: LifeCyclePolicy[] } // Initial state of event details in redux store @@ -441,6 +445,8 @@ const initialState: EventDetailsState = { errorStatisticsValue: null, statusTobiraData: "uninitialized", errorTobiraData: null, + statusLifeCyclePolicies: "uninitialized", + errorLifeCyclePolicies: null, eventId: "", modal: { show: false, @@ -609,6 +615,7 @@ const initialState: EventDetailsState = { id: "", hostPages: [], }, + lifeCyclePolicies: [], }; @@ -1573,6 +1580,13 @@ export const fetchEventStatisticsValueUpdate = createAppAsyncThunk("eventDetails ); }); +export const fetchEventLifeCyclePolicies = createAppAsyncThunk("eventDetails/fetchLifeCyclePolicies", async (eventId: Event["id"]) => { + const data = await axios.get( + `/api/lifecyclemanagement/policiesForEvent/${eventId}`, + ); + return data.data; +}); + export const updateMetadata = createAppAsyncThunk("eventDetails/updateMetadata", async (params: { id: Event["id"], values: { [key: string]: MetadataCatalog["fields"][0]["value"] } @@ -2546,6 +2560,21 @@ const eventDetailsSlice = createSlice({ .addCase(fetchEventDetailsTobira.rejected, (state, action) => { state.statusTobiraData = "failed"; state.errorTobiraData = action.error; + }) + // fetch lifecycle + .addCase(fetchEventLifeCyclePolicies.pending, state => { + state.statusLifeCyclePolicies = "loading"; + }) + .addCase(fetchEventLifeCyclePolicies.fulfilled, (state, action: PayloadAction< + EventDetailsState["lifeCyclePolicies"] + >) => { + state.statusLifeCyclePolicies = "succeeded"; + state.lifeCyclePolicies = action.payload; + state.errorLifeCyclePolicies = null; + }) + .addCase(fetchEventLifeCyclePolicies.rejected, (state, action) => { + state.statusLifeCyclePolicies = "failed"; + state.errorLifeCyclePolicies = action.error; }); }, }); diff --git a/src/slices/lifeCycleDetailsSlice.ts b/src/slices/lifeCycleDetailsSlice.ts new file mode 100644 index 0000000000..47fc9048a2 --- /dev/null +++ b/src/slices/lifeCycleDetailsSlice.ts @@ -0,0 +1,278 @@ +import { PayloadAction, SerializedError, createSlice } from "@reduxjs/toolkit"; +import axios from "axios"; +import { createAppAsyncThunk } from "../createAsyncThunkWithTypes"; +import { LifeCyclePolicy } from "./lifeCycleSlice"; +import { TransformedAcl } from "./aclDetailsSlice"; +import { createPolicy } from "../utils/resourceUtils"; +import { Ace } from "./aclSlice"; +import { addNotification } from "./notificationSlice"; +import { AppDispatch } from "../store"; + + +/** + * This file contains redux reducer for actions affecting the state of a lifeCyclePolicy/capture agent + */ +type LifeCyclePolicyDetailsModal = { + show: boolean, + policy: { id: string, title: string } | null, +} + +interface LifeCyclePolicyDetailsState extends LifeCyclePolicy { + statusLifeCyclePolicyDetails: "uninitialized" | "loading" | "succeeded" | "failed", + errorLifeCyclePolicyDetails: SerializedError | null, + + modal: LifeCyclePolicyDetailsModal, + actionsEnum: string[], + targetTypesEnum: string[], + timingsEnum: string[], +} + +// Initial state of lifeCyclePolicy details in redux store +const initialState: LifeCyclePolicyDetailsState = { + statusLifeCyclePolicyDetails: "uninitialized", + errorLifeCyclePolicyDetails: null, + modal: { + show: false, + policy: null, + }, + actionParameters: {}, + timing: "SPECIFIC_DATE", + action: "START_WORKFLOW", + targetType: "EVENT", + id: "", + title: "", + isActive: false, + isCreatedFromConfig: false, + actionDate: "", + cronTrigger: "", + targetFilters: {}, + accessControlEntries: [], + + actionsEnum: [], + targetTypesEnum: [], + timingsEnum: [], +}; + +// fetch details of certain lifeCyclePolicy from server +export const fetchLifeCyclePolicyDetails = createAppAsyncThunk("lifeCyclePolicyDetails/fetchLifeCyclePolicyDetails", async (id: string) => { + type ReturnType = LifeCyclePolicy & { actionParameters: string, targetFilters: string, accessControlEntries: { + id: number, + allow: boolean, + role: string, + action: string, + }[] } + const res = await axios.get(`/api/lifecyclemanagement/policies/${id}`); + const data = res.data; + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + data.actionParameters = JSON.parse(data.actionParameters); + if (data.action === "START_WORKFLOW") { + data.actionParameters.workflowParameters = JSON.parse(data.actionParameters.workflowParameters as string); + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + data.targetFilters = JSON.parse(data.targetFilters); + + const accessPolicies : { + id: number, + allow: boolean, + role: string, + action: string, + }[] = data.accessControlEntries; + let acls: TransformedAcl[] = []; + + const json = accessPolicies; + const newPolicies: { [key: string]: TransformedAcl } = {}; + const policyRoles: string[] = []; + for (let i = 0; i < json.length; i++) { + const policy: Ace = json[i]; + if (!newPolicies[policy.role]) { + newPolicies[policy.role] = createPolicy(policy.role); + policyRoles.push(policy.role); + } + if (policy.action === "read" || policy.action === "write") { + newPolicies[policy.role][policy.action] = policy.allow; + } else if (policy.allow === true) { // || policy.allow === "true") { + newPolicies[policy.role].actions.push(policy.action); + } + } + acls = policyRoles.map(role => newPolicies[role]); + + const result = { + ...data, + accessControlEntries: acls, + }; + + return result; +}); + +export const fetchLifeCyclePolicyActions = createAppAsyncThunk("lifeCyclePolicyDetails/fetchLifeCyclePolicyActions", async () => { + const res = await axios.get("/api/lifecyclemanagement/policies/actions"); + const data = res.data; + + return data; +}); + +export const fetchLifeCyclePolicyTargetTypes = createAppAsyncThunk("lifeCyclePolicyDetails/fetchLifeCyclePolicyTargetTypes", async () => { + const res = await axios.get("/api/lifecyclemanagement/policies/targettypes"); + const data = res.data; + + return data; +}); + +export const fetchLifeCyclePolicyTimings = createAppAsyncThunk("lifeCyclePolicyDetails/fetchLifeCyclePolicyTimings", async () => { + const res = await axios.get("/api/lifecyclemanagement/policies/timings"); + const data = res.data; + + return data; +}); + +// Dummy function for compatability +// eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-unused-vars +export const fetchLifeCyclePolicyDetailsAcls = createAppAsyncThunk("lifeCyclePolicyDetails/fetchLifeCyclePolicyDetailsAcls", async (id: string, { getState }) => { + const state = getState(); + return state.lifeCyclePolicyDetails.accessControlEntries; +}); + +// Dummy function for compatability +export const updateLifeCyclePolicyAccess = createAppAsyncThunk("lifeCyclePolicyDetails/fetchLifeCyclePolicyDetailsAcls", async (params: { + id: string, + policies: { acl: { ace: Ace[] } } +}, { dispatch }) => { + const { id, policies } = params; + + const data = new URLSearchParams(); + data.append("accessControlEntries", JSON.stringify(policies.acl.ace)); + + await axios.put(`/api/lifecyclemanagement/policies/${id}`, data) + .then(response => { + console.info(response); + dispatch(addNotification({ type: "success", key: "LIFECYCLE_POLICY_ADDED" })); + return true; + }) + .catch(response => { + console.error(response); + dispatch(addNotification({ type: "error", key: "LIFECYCLEPOLICY_NOT_SAVED" })); + return false; + }); +}); + +export const updateLifeCyclePolicy = createAppAsyncThunk("lifeCyclePolicyDetails/updateLifeCyclePolicy", async (policy: LifeCyclePolicy, { dispatch }) => { + const data = new URLSearchParams(); + + Object.entries(policy).forEach(([key, value]) => { + let stringified = value; + if (stringified instanceof Date) { + stringified = stringified.toJSON(); + } else if (stringified === Object(stringified)) { + stringified = JSON.stringify(stringified); + } + // @ts-expect-error: ??? + data.append(key, stringified); + }); + + await axios.put(`/api/lifecyclemanagement/policies/${policy.id}`, data) + .then(response => { + console.info(response); + dispatch(addNotification({ type: "success", key: "LIFECYCLE_POLICY_ADDED" })); + }) + .catch(response => { + console.error(response); + dispatch(addNotification({ type: "error", key: "LIFECYCLEPOLICY_NOT_SAVED" })); + }); +}); + +/** + * Open details modal externally + * + * @param page modal page + * @param policy policy to show + */ +export const openModal = ( + policy: LifeCyclePolicyDetailsModal["policy"], +) => (dispatch: AppDispatch) => { + dispatch(setModalLifeCyclePolicy(policy)); + dispatch(setShowModal(true)); +}; + +const lifeCyclePolicyDetailsSlice = createSlice({ + name: "lifeCyclePolicyDetails", + initialState, + reducers: { + setShowModal(state, action: PayloadAction< + LifeCyclePolicyDetailsState["modal"]["show"] + >) { + state.modal.show = action.payload; + }, + setModalLifeCyclePolicy(state, action: PayloadAction< + LifeCyclePolicyDetailsState["modal"]["policy"] + >) { + state.modal.policy = action.payload; + }, + }, + // These are used for thunks + extraReducers: builder => { + builder + .addCase(fetchLifeCyclePolicyDetails.pending, state => { + state.statusLifeCyclePolicyDetails = "loading"; + }) + .addCase(fetchLifeCyclePolicyDetails.fulfilled, (state, action: PayloadAction<{ + actionParameters: LifeCyclePolicyDetailsState["actionParameters"], + timing: LifeCyclePolicyDetailsState["timing"], + action: LifeCyclePolicyDetailsState["action"], + targetType: LifeCyclePolicyDetailsState["targetType"], + id: LifeCyclePolicyDetailsState["id"], + title: LifeCyclePolicyDetailsState["title"], + isActive: LifeCyclePolicyDetailsState["isActive"], + isCreatedFromConfig: LifeCyclePolicyDetailsState["isCreatedFromConfig"], + actionDate: LifeCyclePolicyDetailsState["actionDate"], + cronTrigger: LifeCyclePolicyDetailsState["cronTrigger"], + targetFilters: LifeCyclePolicyDetailsState["targetFilters"], + accessControlEntries: LifeCyclePolicyDetailsState["accessControlEntries"], + }>) => { + state.statusLifeCyclePolicyDetails = "succeeded"; + const lifeCyclePolicyDetails = action.payload; + state.actionParameters = lifeCyclePolicyDetails.actionParameters; + state.timing = lifeCyclePolicyDetails.timing; + state.action = lifeCyclePolicyDetails.action; + state.targetType = lifeCyclePolicyDetails.targetType; + state.id = lifeCyclePolicyDetails.id; + state.title = lifeCyclePolicyDetails.title; + state.isActive = lifeCyclePolicyDetails.isActive; + state.isCreatedFromConfig = lifeCyclePolicyDetails.isCreatedFromConfig; + state.actionDate = lifeCyclePolicyDetails.actionDate; + state.cronTrigger = lifeCyclePolicyDetails.cronTrigger; + state.targetFilters = lifeCyclePolicyDetails.targetFilters; + state.accessControlEntries = lifeCyclePolicyDetails.accessControlEntries; + }) + .addCase(fetchLifeCyclePolicyDetails.rejected, (state, action) => { + state.statusLifeCyclePolicyDetails = "failed"; + state.errorLifeCyclePolicyDetails = action.error; + }) + .addCase(fetchLifeCyclePolicyActions.fulfilled, (state, action: PayloadAction< + LifeCyclePolicyDetailsState["actionsEnum"] + >) => { + const actionsEnum = action.payload; + state.actionsEnum = actionsEnum; + }) + .addCase(fetchLifeCyclePolicyTargetTypes.fulfilled, (state, action: PayloadAction< + LifeCyclePolicyDetailsState["actionsEnum"] + >) => { + const targetTypesEnum = action.payload; + state.targetTypesEnum = targetTypesEnum; + }) + .addCase(fetchLifeCyclePolicyTimings.fulfilled, (state, action: PayloadAction< + LifeCyclePolicyDetailsState["actionsEnum"] + >) => { + const timingsEnum = action.payload; + state.timingsEnum = timingsEnum; + }); + }, +}); + +export const { + setShowModal, + setModalLifeCyclePolicy, +} = lifeCyclePolicyDetailsSlice.actions; + +// Export the slice reducer as the default export +export default lifeCyclePolicyDetailsSlice.reducer; diff --git a/src/slices/lifeCycleSlice.ts b/src/slices/lifeCycleSlice.ts new file mode 100644 index 0000000000..ed99509dc1 --- /dev/null +++ b/src/slices/lifeCycleSlice.ts @@ -0,0 +1,186 @@ +import { PayloadAction, SerializedError, createSlice } from "@reduxjs/toolkit"; +import { TableConfig } from "../configs/tableConfigs/aclsTableConfig"; +import { lifeCyclePolicyTableConfig } from "../configs/tableConfigs/lifeCyclePoliciesTableConfig"; +import axios from "axios"; +import { getURLParams, prepareAccessPolicyRulesForPost } from "../utils/resourceUtils"; +import { createAppAsyncThunk } from "../createAsyncThunkWithTypes"; +import { TransformedAcl } from "./aclDetailsSlice"; +import { addNotification } from "./notificationSlice"; + +// type LifeCyclePolicyTiming = "SPECIFIC_DATE" | "REPEATING" | "ALWAYS"; +// type LifeCyclePolicyAction = "START_WORKFLOW" +// type LifeCyclePolicyTargetType = "EVENT" +export type CommonMetadataCatalogFlavor = "dublincore/episode"; // TODO: Get this from the backend +export type TargetFilter = { + value: string | string[], + type: TargetFiltersType, + must: boolean +} +export const ALL_TARGET_FILTER_TYPES = ["SEARCH", "WILDCARD", "GREATER_THAN", "LESS_THAN"] as const; +type TargetFilterTypesTuple = typeof ALL_TARGET_FILTER_TYPES; +type TargetFiltersType = TargetFilterTypesTuple[number]; + +export type LifeCyclePolicy = { + actionParameters: { [key: string]: unknown }, // JSON. Variable, depends on action1 + timing: string, + action: string, + targetType: string, + id: string, + title: string, + isActive: boolean, + isCreatedFromConfig: boolean, + actionDate: string, // Date + cronTrigger: string, + targetFilters: { [key: string]: { [key: string]: TargetFilter } }, + accessControlEntries: TransformedAcl[] +} + +type LifeCycleState = { + status: "uninitialized" | "loading" | "succeeded" | "failed", + error: SerializedError | null, + results: LifeCyclePolicy[], + columns: TableConfig["columns"], + total: number, + offset: number, + limit: number, +}; + +// Fill columns initially with columns defined in aclsTableConfig +const initialColumns = lifeCyclePolicyTableConfig.columns.map(column => ({ + ...column, + deactivated: false, +})); + +// Initial state of acls in redux store +const initialState: LifeCycleState = { + status: "uninitialized", + error: null, + results: [], + columns: initialColumns, + total: 0, + offset: 0, + limit: 0, +}; + +type FetchLifeCyclePolicies = { + total: number, + offset: number, + limit: number, + results: LifeCyclePolicy[] +} + +export const fetchLifeCyclePolicies = createAppAsyncThunk("lifeCycle/fetchLifeCyclePolicies", async (_, { getState }) => { + const state = getState(); + const params = getURLParams(state, "lifeCyclePolicies"); + const res = await axios.get("/api/lifecyclemanagement/policies", { params: params }); + return res.data; +}); + +export const postNewLifeCyclePolicy = createAppAsyncThunk("lifeCycle/postNewLifeCyclePolicy", async ( + policy: { + actionParameters: { [key: string]: unknown }, + timing: string, + action: string, + targetType: string, + title: string, + isActive: boolean, + actionDate: string, + cronTrigger: string, + targetFilters: { [key: string]: { [key: string]: TargetFilter } }, + accessControlEntries: TransformedAcl[] + }, + { dispatch }, +) => { + const data = new URLSearchParams(); + + // Format filter collections + // for (const filterName in policy.targetFilters) { + // // policy.targetFilters[filterName] + // if (hasOwnProperty(TARGET_FILTER_KEYS_EVENTS, filterName) + // && TARGET_FILTER_KEYS_EVENTS[filterName].collection) { + // policy.targetFilters[filterName].value = policy.targetFilters[filterName].value.toString() + // } + // } + + // Stringify + Object.entries(policy).forEach(([key, value]) => { + let stringified = value; + if (stringified instanceof Date) { + stringified = stringified.toJSON(); + } else if (stringified === Object(stringified)) { + stringified = JSON.stringify(stringified); + } + // @ts-expect-error: ??? + data.append(key, stringified); + }); + + data.delete("accessControlEntries"); + data.append("accessControlEntries", JSON.stringify(prepareAccessPolicyRulesForPost(policy.accessControlEntries).acl.ace)); + + await axios.post("/api/lifecyclemanagement/policies", data) + .then(res => { + console.info(res); + dispatch(addNotification({ type: "success", key: "LIFECYCLE_POLICY_ADDED" })); + }) + .catch(res => { + console.error(res); + dispatch(addNotification({ type: "error", key: "LIFECYCLE_POLICY_NOT_SAVED" })); + }); +}); + +export const deleteLifeCyclePolicy = createAppAsyncThunk("lifeCycle/fetchLifeCyclePolicies", async (id: string, { dispatch }) => { + await axios + .delete(`/api/lifecyclemanagement/policies/${id}`) + .then(res => { + console.info(res); + dispatch(addNotification({ type: "success", key: "LIFECYCLE_POLICY_DELETED" })); + }) + .catch(res => { + console.error(res); + dispatch(addNotification({ type: "error", key: "LIFECYCLE_POLICY_NOT_DELETED" })); + }); +}); + +const lifeCycleSlice = createSlice({ + name: "lifeCycle", + initialState, + reducers: { + setLifeCycleColumns(state, action: PayloadAction< + LifeCycleState["columns"] + >) { + state.columns = action.payload; + }, + }, + // These are used for thunks + extraReducers: builder => { + builder + .addCase(fetchLifeCyclePolicies.pending, state => { + state.status = "loading"; + }) + // Pass the generated action creators to `.addCase()` + .addCase(fetchLifeCyclePolicies.fulfilled, (state, action: PayloadAction<{ + total: LifeCycleState["total"], + limit: LifeCycleState["limit"], + offset: LifeCycleState["offset"], + results: LifeCycleState["results"], + }>) => { + // Same "mutating" update syntax thanks to Immer + state.status = "succeeded"; + const policies = action.payload; + state.total = policies.total; + state.limit = policies.limit; + state.offset = policies.offset; + state.results = policies.results; + }) + .addCase(fetchLifeCyclePolicies.rejected, (state, action) => { + state.status = "failed"; + state.results = []; + state.error = action.error; + }); + }, +}); + +export const { setLifeCycleColumns } = lifeCycleSlice.actions; + +// Export the slice reducer as the default export +export default lifeCycleSlice.reducer; diff --git a/src/slices/tableSlice.ts b/src/slices/tableSlice.ts index 997aafe23a..615e6c29c0 100644 --- a/src/slices/tableSlice.ts +++ b/src/slices/tableSlice.ts @@ -10,6 +10,7 @@ import { AclResult } from "./aclSlice"; import { ThemeDetailsType } from "./themeSlice"; import { Series } from "./seriesSlice"; import { Event } from "./eventSlice"; +import { LifeCyclePolicy } from "./lifeCycleSlice"; import { eventsTableConfig } from "../configs/tableConfigs/eventsTableConfig"; import { seriesTableConfig } from "../configs/tableConfigs/seriesTableConfig"; import { recordingsTableConfig } from "../configs/tableConfigs/recordingsTableConfig"; @@ -19,6 +20,7 @@ import { servicesTableConfig } from "../configs/tableConfigs/servicesTableConfig import { usersTableConfig } from "../configs/tableConfigs/usersTableConfig"; import { groupsTableConfig } from "../configs/tableConfigs/groupsTableConfig"; import { themesTableConfig } from "../configs/tableConfigs/themesTableConfig"; +import { lifeCyclePolicyTableConfig } from "../configs/tableConfigs/lifeCyclePoliciesTableConfig"; import { RootState } from "../store"; /* @@ -69,11 +71,11 @@ export function isRowSelectable(row: Row) { return false; } -export function isEvent(row: Event | Series | Recording | Server | Job | Service | User | Group | AclResult | ThemeDetailsType): row is Event { +export function isEvent(row: Event | Series | Recording | Server | Job | Service | User | Group | AclResult | ThemeDetailsType | LifeCyclePolicy): row is Event { return (row as Event).event_status !== undefined; } -export function isSeries(row: Row | Event | Series | Recording | Server | Job | Service | User | Group | AclResult | ThemeDetailsType): row is Series { +export function isSeries(row: Row | Event | Series | Recording | Server | Job | Service | User | Group | AclResult | ThemeDetailsType | LifeCyclePolicy): row is Series { return (row as Series).organizers !== undefined; } @@ -81,13 +83,13 @@ export function isSeries(row: Row | Event | Series | Recording | Server | Job | export type Row = { id: string, // For use with entityAdapter. Directly taken from event/series etc. if available selected: boolean // If the row was marked in the ui by the user -} & (Event | Series | Recording | Server | Job | Service | User | Group | AclResult | ThemeDetailsType) +} & (Event | Series | Recording | Server | Job | Service | User | Group | AclResult | ThemeDetailsType | LifeCyclePolicy) export type SubmitRow = { selected: boolean -} & (Event | Series | Recording | Server | Job | Service | User | Group | AclResult | ThemeDetailsType) +} & (Event | Series | Recording | Server | Job | Service | User | Group | AclResult | ThemeDetailsType | LifeCyclePolicy) -export type Resource = "events" | "series" | "recordings" | "jobs" | "servers" | "services" | "users" | "groups" | "acls" | "themes" +export type Resource = "events" | "series" | "recordings" | "jobs" | "servers" | "services" | "users" | "groups" | "acls" | "themes" | "lifeCyclePolicies" export type ReverseOptions = "ASC" | "DESC" | "NONE" @@ -143,6 +145,7 @@ const initialState: TableState = { groups: groupsTableConfig.multiSelect, acls: aclsTableConfig.multiSelect, themes: themesTableConfig.multiSelect, + lifeCyclePolicies: lifeCyclePolicyTableConfig.multiSelect, }, resource: "events", pages: [], @@ -158,6 +161,7 @@ const initialState: TableState = { groups: "name", acls: "name", themes: "name", + lifeCyclePolicies: "title", }, predicate: "", reverse: { @@ -171,6 +175,7 @@ const initialState: TableState = { groups: "ASC", acls: "ASC", themes: "ASC", + lifeCyclePolicies: "ASC", }, rows: rowsAdapter.getInitialState(), maxLabel: "", diff --git a/src/slices/workflowSlice.ts b/src/slices/workflowSlice.ts index b7cc78ea8a..1b0f724a54 100644 --- a/src/slices/workflowSlice.ts +++ b/src/slices/workflowSlice.ts @@ -19,7 +19,7 @@ export type FieldSetField = { [key: string]: unknown } -type ConfigurationPanelField = { +export type ConfigurationPanelField = { // We could potentially specify 'fieldset' more, but I cannot find a definition // for which key value pairs are allowed fieldset?: FieldSetField[] // Values can be anything diff --git a/src/store.ts b/src/store.ts index 8983774bc4..e23f39c281 100644 --- a/src/store.ts +++ b/src/store.ts @@ -6,6 +6,7 @@ import tableFilterProfiles from "./slices/tableFilterProfilesSlice"; import events from "./slices/eventSlice"; import table from "./slices/tableSlice"; import series from "./slices/seriesSlice"; +import lifeCycle from "./slices/lifeCycleSlice"; import recordings from "./slices/recordingSlice"; import jobs from "./slices/jobSlice"; import servers from "./slices/serverSlice"; @@ -19,6 +20,7 @@ import notifications from "./slices/notificationSlice"; import workflows from "./slices/workflowSlice"; import eventDetails from "./slices/eventDetailsSlice"; import seriesDetails from "./slices/seriesDetailsSlice"; +import lifeCyclePolicyDetails from "./slices/lifeCycleDetailsSlice"; import userDetails from "./slices/userDetailsSlice"; import recordingDetails from "./slices/recordingDetailsSlice"; import groupDetails from "./slices/groupDetailsSlice"; @@ -38,6 +40,7 @@ import autoMergeLevel2 from "redux-persist/es/stateReconciler/autoMergeLevel2"; const tableFilterProfilesPersistConfig = { key: "tableFilterProfiles", storage, whitelist: ["profiles"] }; const eventsPersistConfig = { key: "events", storage, whitelist: ["columns"] }; const seriesPersistConfig = { key: "series", storage, whitelist: ["columns"] }; +const lifeCyclePersistConfig = { key: "lifeCycle", storage, whitelist: ["columns"] }; const tablePersistConfig = { key: "table", storage, whitelist: ["pagination", "sortBy", "reverse"] }; const recordingsPersistConfig = { key: "recordings", storage, whitelist: ["columns"] }; const jobsPersistConfig = { key: "jobs", storage, whitelist: ["columns"] }; @@ -54,6 +57,7 @@ const reducers = combineReducers({ tableFilterProfiles: persistReducer(tableFilterProfilesPersistConfig, tableFilterProfiles), events: persistReducer(eventsPersistConfig, events), series: persistReducer(seriesPersistConfig, series), + lifeCycle: persistReducer(lifeCyclePersistConfig, lifeCycle), table: persistReducer(tablePersistConfig, table), recordings: persistReducer(recordingsPersistConfig, recordings), jobs: persistReducer(jobsPersistConfig, jobs), @@ -69,6 +73,7 @@ const reducers = combineReducers({ eventDetails, themeDetails, seriesDetails, + lifeCyclePolicyDetails, recordingDetails, userDetails, groupDetails, diff --git a/src/thunks/tableThunks.ts b/src/thunks/tableThunks.ts index f3d78dfba5..38a142fe89 100644 --- a/src/thunks/tableThunks.ts +++ b/src/thunks/tableThunks.ts @@ -35,6 +35,7 @@ import { fetchRecordings, setRecordingsColumns } from "../slices/recordingSlice" import { setGroupColumns } from "../slices/groupSlice"; import { fetchAcls, setAclColumns } from "../slices/aclSlice"; import { AppDispatch, AppThunk, RootState } from "../store"; +import { fetchLifeCyclePolicies, setLifeCycleColumns } from "../slices/lifeCycleSlice"; /** * This file contains methods/thunks used to manage the table in the main view and its state changes @@ -121,6 +122,30 @@ export const loadSeriesIntoTable = (): AppThunk => (dispatch, getState) => { dispatch(loadResourceIntoTable(tableData)); }; +export const loadLifeCyclePoliciesIntoTable = (): AppThunk => (dispatch, getState) => { + const { lifeCycle, table } = getState(); + const pagination = table.pagination; + const resource = lifeCycle.results; + const total = lifeCycle.total; + + const pages = calculatePages(total / pagination.limit, pagination.offset); + + const tableData = { + resource: "lifeCyclePolicies" as const, + rows: resource.map(obj => { + return { ...obj, selected: false }; + }), + columns: lifeCycle.columns, + multiSelect: table.multiSelect["lifeCyclePolicies"], + pages: pages, + sortBy: table.sortBy["lifeCyclePolicies"], + reverse: table.reverse["lifeCyclePolicies"], + totalItems: total, + }; + + dispatch(loadResourceIntoTable(tableData)); +}; + export const loadRecordingsIntoTable = (): AppThunk => (dispatch, getState) => { const { recordings, table } = getState(); const pagination = table.pagination; @@ -338,6 +363,11 @@ export const goToPage = (pageNumber: number) => async (dispatch: AppDispatch, ge dispatch(loadSeriesIntoTable()); break; } + case "lifeCyclePolicies": { + await dispatch(fetchLifeCyclePolicies()); + dispatch(loadLifeCyclePoliciesIntoTable()); + break; + } case "recordings": { await dispatch(fetchRecordings()); dispatch(loadRecordingsIntoTable()); @@ -406,6 +436,11 @@ export const updatePages = () => async (dispatch: AppDispatch, getState: () => R dispatch(loadSeriesIntoTable()); break; } + case "lifeCyclePolicies": { + await dispatch(fetchLifeCyclePolicies()); + dispatch(loadLifeCyclePoliciesIntoTable()); + break; + } case "recordings": { await dispatch(fetchRecordings()); dispatch(loadRecordingsIntoTable()); @@ -515,6 +550,11 @@ export const changeColumnSelection = (updatedColumns: TableConfig["columns"]) => dispatch(loadSeriesIntoTable()); break; } + case "lifeCyclePolicies": { + dispatch(setLifeCycleColumns(updatedColumns)); + dispatch(loadLifeCyclePoliciesIntoTable()); + break; + } case "recordings": { dispatch(setRecordingsColumns(updatedColumns)); dispatch(loadRecordingsIntoTable()); diff --git a/src/utils/dropDownUtils.ts b/src/utils/dropDownUtils.ts index bad70de163..5338f779c4 100644 --- a/src/utils/dropDownUtils.ts +++ b/src/utils/dropDownUtils.ts @@ -19,3 +19,7 @@ export const formatWorkflowsForDropdown = (workflows: Workflow[]) => { export const formatAclTemplatesForDropdown = (templates: { id: string, value: string }[]) => { return templates.map(template => ({ label: template.value, value: template.id })); }; + +export const formatPolicyActionsForDropdown = (policieActions: string[]) => { + return policieActions.map(action => ({ label: action, value: action })); +}; diff --git a/src/utils/lifeCycleUtils.ts b/src/utils/lifeCycleUtils.ts new file mode 100644 index 0000000000..7de6597fcb --- /dev/null +++ b/src/utils/lifeCycleUtils.ts @@ -0,0 +1,38 @@ +import { TargetFilter } from "../slices/lifeCycleSlice"; + +export function parseTargetFiltersForSubmit( + transformed: { [key: string]: (TargetFilter & { filter: string })[] }, +): { [key: string]: { [key: string]: TargetFilter } } { + const result: { [key: string]: { [key: string]: TargetFilter } } = {}; + + for (const outerKey in transformed) { + const list = transformed[outerKey]; + const innerMap: { [key: string]: TargetFilter } = {}; + + for (const item of list) { + const { filter, ...rest } = item; + innerMap[filter] = rest; + } + + result[outerKey] = innerMap; + } + + return result; +} + +export function parseTargetFiltersForEditing( + targetFilters: { [key: string]: { [key: string]: TargetFilter } }, +): { [key: string]: (TargetFilter & { filter: string })[] } { + const result: { [key: string]: (TargetFilter & { filter: string })[] } = {}; + + for (const outerKey in targetFilters) { + const innerMap = targetFilters[outerKey]; + + result[outerKey] = Object.entries(innerMap).map(([innerKey, filterObj]) => ({ + ...filterObj, + filter: innerKey, + })); + } + + return result; +}; diff --git a/src/utils/validate.ts b/src/utils/validate.ts index 9ef13471b9..07fb4d8b59 100644 --- a/src/utils/validate.ts +++ b/src/utils/validate.ts @@ -252,3 +252,96 @@ export const EditGroupSchema = Yup.object().shape({ export const AdopterRegistrationSchema = Yup.object().shape({ email: Yup.string().email(), }); + +/** + * Validation Schema used in lifecycle policy modal + */ +const filterItemSchema = Yup.object({ + filter: Yup.string().required("Required"), + value: Yup.mixed().required("Required"), + type: Yup.string().required("Required"), + must: Yup.boolean(), +}); + +const targetFiltersSchema = Yup.object() + .test( + "has-at-least-one-array", + "At least one filter group is required", + function (obj) { + if (!obj || typeof obj !== "object") { return false; } + return Object.keys(obj).length > 0; + }, + ) + .test( + "has-at-least-one-item", + "At least one filter must be defined", + function (obj) { + if (!obj || typeof obj !== "object") { return false; } + + let total = 0; + + for (const key of Object.keys(obj)) { + const arr = (obj as Record)[key]; + if (Array.isArray(arr)) { + total += arr.length; + } + } + + return total > 0; + }, + ) + .test( + "validate-items", + "Invalid filter structure", + function (obj) { + if (!obj || typeof obj !== "object") { return false; } + + for (const key of Object.keys(obj)) { + const arr = (obj as Record)[key]; + + if (!Array.isArray(arr)) { + return this.createError({ + message: `Filter "${key}" must be an array`, + }); + } + + for (const item of arr) { + try { + filterItemSchema.validateSync(item); + } catch (err) { + return this.createError({ message: (err as Error).message }); + } + } + } + + return true; + }, + ); + +export const LifeCyclePolicySchema = [ + Yup.object().shape({ + title: Yup.string().required("Required"), + isActive: Yup.bool().required("Required"), + targetType: Yup.string().required("Required"), + timing: Yup.string().required("Required"), + action: Yup.string().required("Required"), + actionParameters: Yup.object().shape({ + // Property only required if it actually exists on the object + workflowId: Yup.string().required("Required"), + // workflowId: Yup.string().when("workflowId", { + // is: (exists: any) => !!exists, + // then: Yup.string().required("Required"), + // }), + }), + actionDate: Yup.date().when("timing", { + is: (timing: string) => timing === "SPECIFIC_DATE", + then: () => Yup.date().required("Required"), + }), + cronTrigger: Yup.string().when("timing", { + is: (timing: string) => timing === "REPEATING", + then: () => Yup.string().required("Required"), + }), + targetFiltersTransformed: targetFiltersSchema, + }), +]; + From 466ba2228e7fd2ec207458f23bf7e92efd5a3edb Mon Sep 17 00:00:00 2001 From: Arnei Date: Tue, 14 Apr 2026 11:09:32 +0200 Subject: [PATCH 2/8] Fix typing errors from new i18n version --- package-lock.json | 27 +++++++++++++++++++++ src/components/events/LifeCyclePolicies.tsx | 6 ++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index e135f2ac09..7f41bae33b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2107,6 +2107,29 @@ "node": "^20.19.0 || >=22.12.0" } }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", + "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@rolldown/binding-win32-arm64-msvc": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.16.tgz", @@ -4243,6 +4266,8 @@ }, "node_modules/i18next": { "version": "25.8.11", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.11.tgz", + "integrity": "sha512-LZ32llTLGludnddjLoijHV7TbmVubU5eJnsWf8taiuM3jmSfUuvBLuyDeubJKS1yBjLBgb7As124M4KWNcBvpw==", "funding": [ { "type": "individual", @@ -5618,6 +5643,8 @@ }, "node_modules/react-i18next": { "version": "16.5.0", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.5.0.tgz", + "integrity": "sha512-IMpPTyCTKxEj8klCrLKUTIUa8uYTd851+jcu2fJuUB9Agkk9Qq8asw4omyeHVnOXHrLgQJGTm5zTvn8HpaPiqw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.27.6", diff --git a/src/components/events/LifeCyclePolicies.tsx b/src/components/events/LifeCyclePolicies.tsx index 2143a9e4cb..3ac392cbf5 100644 --- a/src/components/events/LifeCyclePolicies.tsx +++ b/src/components/events/LifeCyclePolicies.tsx @@ -108,7 +108,11 @@ const LifeCyclePolicies = () => {

    {t("TABLE_SUMMARY", { numberOfRows: policiesTotal })}

    {/* Include table component */} - +
    From 2a9e3de435e0412b8147de6c7fe1032f805936f7 Mon Sep 17 00:00:00 2001 From: Arnei Date: Wed, 22 Apr 2026 15:31:15 +0200 Subject: [PATCH 3/8] Remove superfluous logging of responses for lifecycle responses --- src/slices/lifeCycleDetailsSlice.ts | 6 ++---- src/slices/lifeCycleSlice.ts | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/slices/lifeCycleDetailsSlice.ts b/src/slices/lifeCycleDetailsSlice.ts index 47fc9048a2..c963a271b7 100644 --- a/src/slices/lifeCycleDetailsSlice.ts +++ b/src/slices/lifeCycleDetailsSlice.ts @@ -144,8 +144,7 @@ export const updateLifeCyclePolicyAccess = createAppAsyncThunk("lifeCyclePolicyD data.append("accessControlEntries", JSON.stringify(policies.acl.ace)); await axios.put(`/api/lifecyclemanagement/policies/${id}`, data) - .then(response => { - console.info(response); + .then(_response => { dispatch(addNotification({ type: "success", key: "LIFECYCLE_POLICY_ADDED" })); return true; }) @@ -171,8 +170,7 @@ export const updateLifeCyclePolicy = createAppAsyncThunk("lifeCyclePolicyDetails }); await axios.put(`/api/lifecyclemanagement/policies/${policy.id}`, data) - .then(response => { - console.info(response); + .then(_response => { dispatch(addNotification({ type: "success", key: "LIFECYCLE_POLICY_ADDED" })); }) .catch(response => { diff --git a/src/slices/lifeCycleSlice.ts b/src/slices/lifeCycleSlice.ts index ed99509dc1..859f967987 100644 --- a/src/slices/lifeCycleSlice.ts +++ b/src/slices/lifeCycleSlice.ts @@ -118,8 +118,7 @@ export const postNewLifeCyclePolicy = createAppAsyncThunk("lifeCycle/postNewLife data.append("accessControlEntries", JSON.stringify(prepareAccessPolicyRulesForPost(policy.accessControlEntries).acl.ace)); await axios.post("/api/lifecyclemanagement/policies", data) - .then(res => { - console.info(res); + .then(_res => { dispatch(addNotification({ type: "success", key: "LIFECYCLE_POLICY_ADDED" })); }) .catch(res => { @@ -131,8 +130,7 @@ export const postNewLifeCyclePolicy = createAppAsyncThunk("lifeCycle/postNewLife export const deleteLifeCyclePolicy = createAppAsyncThunk("lifeCycle/fetchLifeCyclePolicies", async (id: string, { dispatch }) => { await axios .delete(`/api/lifecyclemanagement/policies/${id}`) - .then(res => { - console.info(res); + .then(_res => { dispatch(addNotification({ type: "success", key: "LIFECYCLE_POLICY_DELETED" })); }) .catch(res => { From 68bbb0d48802a8a2ca6a0c6b68a9e100722eb102 Mon Sep 17 00:00:00 2001 From: Arnei Date: Wed, 22 Apr 2026 16:24:35 +0200 Subject: [PATCH 4/8] Bring lifecycle policy save behaviour in line The general lifecycle policy should now behave similar to events and series in regards to how the save button, the resulting notification and the cancel button works. --- .../LifeCyclePolicyGeneralTab.tsx | 56 ++++++++++--------- .../adminui/languages/lang-en_US.json | 1 + src/slices/lifeCycleDetailsSlice.ts | 11 +--- 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyGeneralTab.tsx b/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyGeneralTab.tsx index 5e1ba8b7dc..a6973ee0e5 100644 --- a/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyGeneralTab.tsx +++ b/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyGeneralTab.tsx @@ -3,7 +3,6 @@ import { LifeCyclePolicy, TargetFilter } from "../../../../slices/lifeCycleSlice import { useAppDispatch, useAppSelector } from "../../../../store"; import { Formik, FormikProps } from "formik"; import Notifications from "../../../shared/Notifications"; -import cn from "classnames"; import { ConfigurationPanelField } from "../../../../slices/workflowSlice"; import { updateLifeCyclePolicy } from "../../../../slices/lifeCycleDetailsSlice"; import LifeCyclePolicyGeneralFields from "../wizards/LifeCyclePolicyGeneralFields"; @@ -12,6 +11,9 @@ import { getUserInformation } from "../../../../selectors/userInfoSelectors"; import { LifeCyclePolicySchema } from "../../../../utils/validate"; import _ from "lodash"; import { parseTargetFiltersForEditing, parseTargetFiltersForSubmit } from "../../../../utils/lifeCycleUtils"; +import WizardNavigationButtons from "../../../shared/wizard/WizardNavigationButtons"; +import { addNotification } from "../../../../slices/notificationSlice"; +import { NOTIFICATION_CONTEXT } from "../../../../configs/modalConfig"; /** * This component renders details about a recording/capture agent @@ -54,7 +56,24 @@ const LifeCyclePolicyGeneralTab = ({ }; // values.actionParameters["workflowParameters"] = JSON.stringify(workflowParameters); - dispatch(updateLifeCyclePolicy(newValues)); + dispatch(updateLifeCyclePolicy(newValues)) + .unwrap() + .then(() => { + dispatch(addNotification({ + type: "info", + key: "LIFECYCLE_POLICY_SAVED", + duration: 3, + context: NOTIFICATION_CONTEXT, + })); + }) + .catch(() => { + dispatch(addNotification({ + type: "warning", + key: "LIFECYCLE_POLICY_NOT_SAVED", + duration: 3, + context: NOTIFICATION_CONTEXT, + })); + }); }; // set current values of metadata fields as initial values @@ -150,30 +169,15 @@ const LifeCyclePolicyGeneralTab = ({ {formik.dirty && ( - <> - {/* Render buttons for updating metadata */} -
    - - -
    - -
    - + // Render buttons for updating metadata + formik.resetForm()} + createTranslationString="SAVE" + cancelTranslationString="CANCEL" + isLast + /> )} {/*
    */} diff --git a/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json b/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json index 57a6c729f3..3f310aa84d 100644 --- a/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json +++ b/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json @@ -205,6 +205,7 @@ "SERIES_DELETED": "The series has been deleted", "SERIES_NOT_DELETED": "The series could not be deleted", "LIFECYCLE_POLICY_ADDED": "The lifeCycle policy has been created", + "LIFECYCLE_POLICY_SAVED": "The lifeCycle policy was saved", "LIFECYCLE_POLICY_NOT_SAVED": "The lifeCycle policy could not be saved", "LIFECYCLE_POLICY_DELETED": "The lifeCycle policy has been deleted", "LIFECYCLE_POLICY_NOT_DELETED": "The lifeCycle policy could not be deleted", diff --git a/src/slices/lifeCycleDetailsSlice.ts b/src/slices/lifeCycleDetailsSlice.ts index c963a271b7..8d2ae0a7a8 100644 --- a/src/slices/lifeCycleDetailsSlice.ts +++ b/src/slices/lifeCycleDetailsSlice.ts @@ -155,7 +155,7 @@ export const updateLifeCyclePolicyAccess = createAppAsyncThunk("lifeCyclePolicyD }); }); -export const updateLifeCyclePolicy = createAppAsyncThunk("lifeCyclePolicyDetails/updateLifeCyclePolicy", async (policy: LifeCyclePolicy, { dispatch }) => { +export const updateLifeCyclePolicy = createAppAsyncThunk("lifeCyclePolicyDetails/updateLifeCyclePolicy", async (policy: LifeCyclePolicy) => { const data = new URLSearchParams(); Object.entries(policy).forEach(([key, value]) => { @@ -169,14 +169,7 @@ export const updateLifeCyclePolicy = createAppAsyncThunk("lifeCyclePolicyDetails data.append(key, stringified); }); - await axios.put(`/api/lifecyclemanagement/policies/${policy.id}`, data) - .then(_response => { - dispatch(addNotification({ type: "success", key: "LIFECYCLE_POLICY_ADDED" })); - }) - .catch(response => { - console.error(response); - dispatch(addNotification({ type: "error", key: "LIFECYCLEPOLICY_NOT_SAVED" })); - }); + await axios.put(`/api/lifecyclemanagement/policies/${policy.id}`, data); }); /** From b291d9b6efd4f61a041fba4de379316ade5fab66 Mon Sep 17 00:00:00 2001 From: Arnei Date: Wed, 22 Apr 2026 16:59:12 +0200 Subject: [PATCH 5/8] Disable the isActive field for lifecycle policies It is not supposed to be user controlled. --- .../wizards/LifeCyclePolicyGeneralFields.tsx | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx b/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx index 24a83d0e6e..67888be333 100644 --- a/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx +++ b/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx @@ -158,22 +158,18 @@ const LifeCyclePolicyGeneralFields = -
    - - - + {!isNew && + + + + + } {!isNew && From 640fab6da602597b6cdbd5292eb1056a329ccb78 Mon Sep 17 00:00:00 2001 From: Arnei Date: Thu, 23 Apr 2026 11:22:54 +0200 Subject: [PATCH 6/8] Fix isPartOf dropdown for lifecycle policies When setting a filter for a lifecycle policy to "isPartOf", the value dropdown would be empty, so you could not select any series. This fixes that. --- .../events/partials/wizards/LifeCyclePolicyGeneralFields.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx b/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx index 67888be333..f67c91570f 100644 --- a/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx +++ b/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx @@ -363,7 +363,7 @@ const LifeCyclePolicyGeneralFields = From 0dfbcd4f4e0afa721d9297bf9e50842a861cb630 Mon Sep 17 00:00:00 2001 From: Arnei Date: Thu, 23 Apr 2026 13:33:39 +0200 Subject: [PATCH 7/8] Prefill type when changing filter for lifecycle policy When changing the filter for a lifecycle policy, the filters type was reset to undefined. Undefined is never a legal value, so it would always have to be manually set afterwards. This changes it so that instead of undefined, one of the legal values for the filters type is already filled in. --- .../events/partials/wizards/LifeCyclePolicyGeneralFields.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx b/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx index f67c91570f..3ae0b075cb 100644 --- a/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx +++ b/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx @@ -351,7 +351,7 @@ const LifeCyclePolicyGeneralFields = From b2c4a3606c06141b74b52512acf9c2f36b0c8c8c Mon Sep 17 00:00:00 2001 From: Arnei Date: Thu, 23 Apr 2026 14:48:54 +0200 Subject: [PATCH 8/8] Fix internal state not updating properly for lifecycle metadata Since we are not refetching lifecycle metadata all the time, we need to make sure our state is up to date. This should help in ensuring that. --- src/slices/lifeCycleDetailsSlice.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/slices/lifeCycleDetailsSlice.ts b/src/slices/lifeCycleDetailsSlice.ts index 8d2ae0a7a8..cd45477de5 100644 --- a/src/slices/lifeCycleDetailsSlice.ts +++ b/src/slices/lifeCycleDetailsSlice.ts @@ -155,7 +155,7 @@ export const updateLifeCyclePolicyAccess = createAppAsyncThunk("lifeCyclePolicyD }); }); -export const updateLifeCyclePolicy = createAppAsyncThunk("lifeCyclePolicyDetails/updateLifeCyclePolicy", async (policy: LifeCyclePolicy) => { +export const updateLifeCyclePolicy = createAppAsyncThunk("lifeCyclePolicyDetails/updateLifeCyclePolicy", async (policy: LifeCyclePolicy, { dispatch }) => { const data = new URLSearchParams(); Object.entries(policy).forEach(([key, value]) => { @@ -170,6 +170,8 @@ export const updateLifeCyclePolicy = createAppAsyncThunk("lifeCyclePolicyDetails }); await axios.put(`/api/lifecyclemanagement/policies/${policy.id}`, data); + + dispatch(setPolicy(policy)); }); /** @@ -199,6 +201,20 @@ const lifeCyclePolicyDetailsSlice = createSlice({ >) { state.modal.policy = action.payload; }, + setPolicy(state, action: PayloadAction) { + state.actionParameters = action.payload.actionParameters; + state.timing = action.payload.timing; + state.action = action.payload.action; + state.targetType = action.payload.targetType; + state.id = action.payload.id; + state.title = action.payload.title; + state.isActive = action.payload.isActive; + state.isCreatedFromConfig = action.payload.isCreatedFromConfig; + state.actionDate = action.payload.actionDate; + state.cronTrigger = action.payload.cronTrigger; + state.targetFilters = action.payload.targetFilters; + state.accessControlEntries = action.payload.accessControlEntries; + }, }, // These are used for thunks extraReducers: builder => { @@ -263,6 +279,7 @@ const lifeCyclePolicyDetailsSlice = createSlice({ export const { setShowModal, setModalLifeCyclePolicy, + setPolicy, } = lifeCyclePolicyDetailsSlice.actions; // Export the slice reducer as the default export
    {t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ISACTIVE")}* - -
    {t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ISACTIVE")}* + +
    {t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ISCREATEDFROMCONFIG")}