From 8276b77c184beff41bc607890158674a9ac4ab3c Mon Sep 17 00:00:00 2001 From: Vladislav Date: Wed, 16 Apr 2025 13:14:02 +0500 Subject: [PATCH 01/11] chore: add antd deps --- client/package-lock.json | 1087 +++++++++++++++++++++++++++++++++++++- client/package.json | 3 + 2 files changed, 1088 insertions(+), 2 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index ed65a7b..a81a568 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1,13 +1,14 @@ { "name": "client", - "version": "0.1.0", + "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "client", - "version": "0.1.0", + "version": "0.0.1", "dependencies": { + "@ant-design/icons": "^5.6.1", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.2.0", @@ -16,8 +17,10 @@ "@types/node": "^16.18.126", "@types/react": "^19.0.11", "@types/react-dom": "^19.0.4", + "antd": "^5.24.7", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-router-dom": "^7.5.0", "react-scripts": "5.0.1", "typescript": "^4.9.5", "web-vitals": "^2.1.4" @@ -54,6 +57,103 @@ "node": ">=6.0.0" } }, + "node_modules/@ant-design/colors": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.2.0.tgz", + "integrity": "sha512-bjTObSnZ9C/O8MB/B4OUtd/q9COomuJAR2SYfhxLyHvCKn4EKwCN3e+fWGMo7H5InAyV0wL17jdE9ALrdOW/6A==", + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^2.0.6" + } + }, + "node_modules/@ant-design/cssinjs": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.23.0.tgz", + "integrity": "sha512-7GAg9bD/iC9ikWatU9ym+P9ugJhi/WbsTWzcKN6T4gU0aehsprtke1UAaaSxxkjjmkJb3llet/rbUSLPgwlY4w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "@emotion/hash": "^0.8.0", + "@emotion/unitless": "^0.7.5", + "classnames": "^2.3.1", + "csstype": "^3.1.3", + "rc-util": "^5.35.0", + "stylis": "^4.3.4" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/cssinjs-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-1.1.3.tgz", + "integrity": "sha512-nOoQMLW1l+xR1Co8NFVYiP8pZp3VjIIzqV6D6ShYF2ljtdwWJn5WSsH+7kvCktXL/yhEtWURKOfH5Xz/gzlwsg==", + "license": "MIT", + "dependencies": { + "@ant-design/cssinjs": "^1.21.0", + "@babel/runtime": "^7.23.2", + "rc-util": "^5.38.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@ant-design/fast-color": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-2.0.6.tgz", + "integrity": "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", + "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==", + "license": "MIT" + }, + "node_modules/@ant-design/react-slick": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.1.2.tgz", + "integrity": "sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.4", + "classnames": "^2.2.5", + "json2mq": "^0.2.0", + "resize-observer-polyfill": "^1.5.1", + "throttle-debounce": "^5.0.0" + }, + "peerDependencies": { + "react": ">=16.9.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", @@ -2359,6 +2459,18 @@ "postcss-selector-parser": "^6.0.10" } }, + "node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", + "license": "MIT" + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.5.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz", @@ -3095,6 +3207,155 @@ } } }, + "node_modules/@rc-component/async-validator": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.0.4.tgz", + "integrity": "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.4" + }, + "engines": { + "node": ">=14.x" + } + }, + "node_modules/@rc-component/color-picker": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-2.0.1.tgz", + "integrity": "sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q==", + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^2.0.6", + "@babel/runtime": "^7.23.6", + "classnames": "^2.2.6", + "rc-util": "^5.38.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/context": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz", + "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/mini-decimal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz", + "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@rc-component/mutate-observer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz", + "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz", + "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/qrcode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rc-component/qrcode/-/qrcode-1.0.0.tgz", + "integrity": "sha512-L+rZ4HXP2sJ1gHMGHjsg9jlYBX/SLN2D6OxP9Zn3qgtpMWtO2vUfxVFwiogHpAIqs54FnALxraUy/BCO1yRIgg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "classnames": "^2.3.2", + "rc-util": "^5.38.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/tour": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.15.1.tgz", + "integrity": "sha512-Tr2t7J1DKZUpfJuDZWHxyxWpfmj8EZrqSgyMZ+BCdvKZ6r1UDsfU46M/iWAAFBy961Ssfom2kv5f3UcjIL2CmQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/portal": "^1.0.0-9", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/trigger": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.2.6.tgz", + "integrity": "sha512-/9zuTnWwhQ3S3WT1T8BubuFTT46kvnXgaERR9f4BTKyn61/wpf/BvbImzYBubzJibU707FxwbKszLlHjcLiv1Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2", + "@rc-component/portal": "^1.1.0", + "classnames": "^2.3.2", + "rc-motion": "^2.0.0", + "rc-resize-observer": "^1.3.1", + "rc-util": "^5.44.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -3656,6 +3917,12 @@ "@types/node": "*" } }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "license": "MIT" + }, "node_modules/@types/eslint": { "version": "8.56.12", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.12.tgz", @@ -4594,6 +4861,71 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/antd": { + "version": "5.24.7", + "resolved": "https://registry.npmjs.org/antd/-/antd-5.24.7.tgz", + "integrity": "sha512-xROWsw0yYFGiNFpVSUZ9/Gs43q0qIM9BkfjugeqgePlZBpLZzLjtOpf4UGM+5aijelHqMi8864KZCX5BbcZYfA==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.2.0", + "@ant-design/cssinjs": "^1.23.0", + "@ant-design/cssinjs-utils": "^1.1.3", + "@ant-design/fast-color": "^2.0.6", + "@ant-design/icons": "^5.6.1", + "@ant-design/react-slick": "~1.1.2", + "@babel/runtime": "^7.26.0", + "@rc-component/color-picker": "~2.0.1", + "@rc-component/mutate-observer": "^1.1.0", + "@rc-component/qrcode": "~1.0.0", + "@rc-component/tour": "~1.15.1", + "@rc-component/trigger": "^2.2.6", + "classnames": "^2.5.1", + "copy-to-clipboard": "^3.3.3", + "dayjs": "^1.11.11", + "rc-cascader": "~3.33.1", + "rc-checkbox": "~3.5.0", + "rc-collapse": "~3.9.0", + "rc-dialog": "~9.6.0", + "rc-drawer": "~7.2.0", + "rc-dropdown": "~4.2.1", + "rc-field-form": "~2.7.0", + "rc-image": "~7.11.1", + "rc-input": "~1.8.0", + "rc-input-number": "~9.5.0", + "rc-mentions": "~2.20.0", + "rc-menu": "~9.16.1", + "rc-motion": "^2.9.5", + "rc-notification": "~5.6.3", + "rc-pagination": "~5.1.0", + "rc-picker": "~4.11.3", + "rc-progress": "~4.0.0", + "rc-rate": "~2.13.1", + "rc-resize-observer": "^1.4.3", + "rc-segmented": "~2.7.0", + "rc-select": "~14.16.6", + "rc-slider": "~11.1.8", + "rc-steps": "~6.0.1", + "rc-switch": "~4.1.0", + "rc-table": "~7.50.4", + "rc-tabs": "~15.5.2", + "rc-textarea": "~1.10.0", + "rc-tooltip": "~6.4.0", + "rc-tree": "~5.13.1", + "rc-tree-select": "~5.27.0", + "rc-upload": "~4.8.1", + "rc-util": "^5.44.4", + "scroll-into-view-if-needed": "^3.1.0", + "throttle-debounce": "^5.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -5633,6 +5965,12 @@ "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", "license": "MIT" }, + "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/clean-css": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", @@ -5877,6 +6215,12 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", + "integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==", + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5940,6 +6284,15 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "license": "MIT", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, "node_modules/core-js": { "version": "3.41.0", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.41.0.tgz", @@ -6472,6 +6825,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", @@ -10983,6 +11342,15 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "license": "MIT" }, + "node_modules/json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", + "license": "MIT", + "dependencies": { + "string-convert": "^0.2.0" + } + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -13792,6 +14160,618 @@ "node": ">=0.10.0" } }, + "node_modules/rc-cascader": { + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.33.1.tgz", + "integrity": "sha512-Kyl4EJ7ZfCBuidmZVieegcbFw0RcU5bHHSbtEdmuLYd0fYHCAiYKZ6zon7fWAVyC6rWWOOib0XKdTSf7ElC9rg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "classnames": "^2.3.1", + "rc-select": "~14.16.2", + "rc-tree": "~5.13.0", + "rc-util": "^5.43.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-checkbox": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.5.0.tgz", + "integrity": "sha512-aOAQc3E98HteIIsSqm6Xk2FPKIER6+5vyEFMZfo73TqM+VVAIqOkHoPjgKLqSNtVLWScoaM7vY2ZrGEheI79yg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.25.2" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-collapse": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.9.0.tgz", + "integrity": "sha512-swDdz4QZ4dFTo4RAUMLL50qP0EY62N2kvmk2We5xYdRwcRn8WcYtuetCJpwpaCbUfUt5+huLpVxhvmnK+PHrkA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.3.4", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dialog": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.6.0.tgz", + "integrity": "sha512-ApoVi9Z8PaCQg6FsUzS8yvBEQy0ZL2PkuvAgrmohPkN3okps5WZ5WQWPc1RNuiOKaAYv8B97ACdsFU5LizzCqg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/portal": "^1.0.0-8", + "classnames": "^2.2.6", + "rc-motion": "^2.3.0", + "rc-util": "^5.21.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-drawer": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-7.2.0.tgz", + "integrity": "sha512-9lOQ7kBekEJRdEpScHvtmEtXnAsy+NGDXiRWc2ZVC7QXAazNVbeT4EraQKYwCME8BJLa8Bxqxvs5swwyOepRwg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@rc-component/portal": "^1.1.1", + "classnames": "^2.2.6", + "rc-motion": "^2.6.1", + "rc-util": "^5.38.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dropdown": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.2.1.tgz", + "integrity": "sha512-YDAlXsPv3I1n42dv1JpdM7wJ+gSUBfeyPK59ZpBD9jQhK9jVuxpjj3NmWQHOBceA1zEPVX84T2wbdb2SD0UjmA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.6", + "rc-util": "^5.44.1" + }, + "peerDependencies": { + "react": ">=16.11.0", + "react-dom": ">=16.11.0" + } + }, + "node_modules/rc-field-form": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.7.0.tgz", + "integrity": "sha512-hgKsCay2taxzVnBPZl+1n4ZondsV78G++XVsMIJCAoioMjlMQR9YwAp7JZDIECzIu2Z66R+f4SFIRrO2DjDNAA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/async-validator": "^5.0.3", + "rc-util": "^5.32.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-image": { + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.11.1.tgz", + "integrity": "sha512-XuoWx4KUXg7hNy5mRTy1i8c8p3K8boWg6UajbHpDXS5AlRVucNfTi5YxTtPBTBzegxAZpvuLfh3emXFt6ybUdA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/portal": "^1.0.2", + "classnames": "^2.2.6", + "rc-dialog": "~9.6.0", + "rc-motion": "^2.6.2", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-input": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.8.0.tgz", + "integrity": "sha512-KXvaTbX+7ha8a/k+eg6SYRVERK0NddX8QX7a7AnRvUa/rEH0CNMlpcBzBkhI0wp2C8C4HlMoYl8TImSN+fuHKA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.18.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-input-number": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.5.0.tgz", + "integrity": "sha512-bKaEvB5tHebUURAEXw35LDcnRZLq3x1k7GxfAqBMzmpHkDGzjAtnUL8y4y5N15rIFIg5IJgwr211jInl3cipag==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/mini-decimal": "^1.0.1", + "classnames": "^2.2.5", + "rc-input": "~1.8.0", + "rc-util": "^5.40.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-mentions": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.20.0.tgz", + "integrity": "sha512-w8HCMZEh3f0nR8ZEd466ATqmXFCMGMN5UFCzEUL0bM/nGw/wOS2GgRzKBcm19K++jDyuWCOJOdgcKGXU3fXfbQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.22.5", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.6", + "rc-input": "~1.8.0", + "rc-menu": "~9.16.0", + "rc-textarea": "~1.10.0", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-menu": { + "version": "9.16.1", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.16.1.tgz", + "integrity": "sha512-ghHx6/6Dvp+fw8CJhDUHFHDJ84hJE3BXNCzSgLdmNiFErWSOaZNsihDAsKq9ByTALo/xkNIwtDFGIl6r+RPXBg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.0.0", + "classnames": "2.x", + "rc-motion": "^2.4.3", + "rc-overflow": "^1.3.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-motion": { + "version": "2.9.5", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.5.tgz", + "integrity": "sha512-w+XTUrfh7ArbYEd2582uDrEhmBHwK1ZENJiSJVb7uRxdE7qJSYjbO2eksRXmndqyKqKoYPc9ClpPh5242mV1vA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.44.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-notification": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.6.3.tgz", + "integrity": "sha512-42szwnn8VYQoT6GnjO00i1iwqV9D1TTMvxObWsuLwgl0TsOokzhkYiufdtQBsJMFjJravS1hfDKVMHLKLcPE4g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.9.0", + "rc-util": "^5.20.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-overflow": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.4.1.tgz", + "integrity": "sha512-3MoPQQPV1uKyOMVNd6SZfONi+f3st0r8PksexIdBTeIYbMX0Jr+k7pHEDvsXtR4BpCv90/Pv2MovVNhktKrwvw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.37.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-pagination": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-5.1.0.tgz", + "integrity": "sha512-8416Yip/+eclTFdHXLKTxZvn70duYVGTvUUWbckCCZoIl3jagqke3GLsFrMs0bsQBikiYpZLD9206Ej4SOdOXQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.38.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-picker": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.11.3.tgz", + "integrity": "sha512-MJ5teb7FlNE0NFHTncxXQ62Y5lytq6sh5nUw0iH8OkHL/TjARSEvSHpr940pWgjGANpjCwyMdvsEV55l5tYNSg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.1", + "rc-overflow": "^1.3.2", + "rc-resize-observer": "^1.4.0", + "rc-util": "^5.43.0" + }, + "engines": { + "node": ">=8.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-progress": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-4.0.0.tgz", + "integrity": "sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-util": "^5.16.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-rate": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.1.tgz", + "integrity": "sha512-QUhQ9ivQ8Gy7mtMZPAjLbxBt5y9GRp65VcUyGUMF3N3fhiftivPHdpuDIaWIMOTEprAjZPC08bls1dQB+I1F2Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-resize-observer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.4.3.tgz", + "integrity": "sha512-YZLjUbyIWox8E9i9C3Tm7ia+W7euPItNWSPX5sCcQTYbnwDb5uNpnLHQCG1f22oZWUhLw4Mv2tFmeWe68CDQRQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.7", + "classnames": "^2.2.1", + "rc-util": "^5.44.1", + "resize-observer-polyfill": "^1.5.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-segmented": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.7.0.tgz", + "integrity": "sha512-liijAjXz+KnTRVnxxXG2sYDGd6iLL7VpGGdR8gwoxAXy2KglviKCxLWZdjKYJzYzGSUwKDSTdYk8brj54Bn5BA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-motion": "^2.4.4", + "rc-util": "^5.17.0" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-select": { + "version": "14.16.6", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.16.6.tgz", + "integrity": "sha512-YPMtRPqfZWOm2XGTbx5/YVr1HT0vn//8QS77At0Gjb3Lv+Lbut0IORJPKLWu1hQ3u4GsA0SrDzs7nI8JG7Zmyg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.1.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-overflow": "^1.3.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-slider": { + "version": "11.1.8", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-11.1.8.tgz", + "integrity": "sha512-2gg/72YFSpKP+Ja5AjC5DPL1YnV8DEITDQrcc1eASrUYjl0esptaBVJBh5nLTXCCp15eD8EuGjwezVGSHhs9tQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-steps": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz", + "integrity": "sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.16.7", + "classnames": "^2.2.3", + "rc-util": "^5.16.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-switch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz", + "integrity": "sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0", + "classnames": "^2.2.1", + "rc-util": "^5.30.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-table": { + "version": "7.50.4", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.50.4.tgz", + "integrity": "sha512-Y+YuncnQqoS5e7yHvfvlv8BmCvwDYDX/2VixTBEhkMDk9itS9aBINp4nhzXFKiBP/frG4w0pS9d9Rgisl0T1Bw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/context": "^1.4.0", + "classnames": "^2.2.5", + "rc-resize-observer": "^1.1.0", + "rc-util": "^5.44.3", + "rc-virtual-list": "^3.14.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tabs": { + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.5.2.tgz", + "integrity": "sha512-Hbqf2IV6k/jPgfMjPtIDmPV0D0C9c/fN4B/fYcoh9qqaUzUZQoK0PYzsV3UaV+3UsmyoYt48p74m/HkLhGTw+w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "classnames": "2.x", + "rc-dropdown": "~4.2.0", + "rc-menu": "~9.16.0", + "rc-motion": "^2.6.2", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.34.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-textarea": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.10.0.tgz", + "integrity": "sha512-ai9IkanNuyBS4x6sOL8qu/Ld40e6cEs6pgk93R+XLYg0mDSjNBGey6/ZpDs5+gNLD7urQ14po3V6Ck2dJLt9SA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-input": "~1.8.0", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tooltip": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.4.0.tgz", + "integrity": "sha512-kqyivim5cp8I5RkHmpsp1Nn/Wk+1oeloMv9c7LXNgDxUpGm+RbXJGL+OPvDlcRnx9DBeOe4wyOIl4OKUERyH1g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.3.1", + "rc-util": "^5.44.3" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tree": { + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.13.1.tgz", + "integrity": "sha512-FNhIefhftobCdUJshO7M8uZTA9F4OPGVXqGfZkkD/5soDeOhwO06T/aKTrg0WD8gRg/pyfq+ql3aMymLHCTC4A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.1" + }, + "engines": { + "node": ">=10.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-tree-select": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.27.0.tgz", + "integrity": "sha512-2qTBTzwIT7LRI1o7zLyrCzmo5tQanmyGbSaGTIf7sYimCklAToVVfpMC6OAldSKolcnjorBYPNSKQqJmN3TCww==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "classnames": "2.x", + "rc-select": "~14.16.2", + "rc-tree": "~5.13.0", + "rc-util": "^5.43.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-upload": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.8.1.tgz", + "integrity": "sha512-toEAhwl4hjLAI1u8/CgKWt30BR06ulPa4iGQSMvSXoHzO88gPCslxqV/mnn4gJU7PDoltGIC9Eh+wkeudqgHyw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.5", + "rc-util": "^5.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util": { + "version": "5.44.4", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.44.4.tgz", + "integrity": "sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/rc-virtual-list": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.18.5.tgz", + "integrity": "sha512-1FuxVSxhzTj3y8k5xMPbhXCB0t2TOiI3Tq+qE2Bu+GGV7f+ECVuQl4OUg6lZ2qT5fordTW7CBpr9czdzXCI7Pg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.0", + "classnames": "^2.2.6", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -13966,6 +14946,55 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.5.0.tgz", + "integrity": "sha512-estOHrRlDMKdlQa6Mj32gIks4J+AxNsYoE0DbTTxiMy2mPzZuWSDU+N85/r1IlNR7kGfznF3VCUlvc5IUO+B9g==", + "license": "MIT", + "dependencies": { + "@types/cookie": "^0.6.0", + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0", + "turbo-stream": "2.4.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.5.0.tgz", + "integrity": "sha512-fFhGFCULy4vIseTtH5PNcY/VvDJK5gvOWcwJVHQp8JQcWVr85ENhJ3UpuF/zP1tQOIFYNRJHzXtyhU1Bdgw0RA==", + "license": "MIT", + "dependencies": { + "react-router": "7.5.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/react-router/node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -14273,6 +15302,12 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "license": "MIT" }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "license": "MIT" + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -14703,6 +15738,15 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", + "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -14884,6 +15928,12 @@ "node": ">= 0.8.0" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -15332,6 +16382,12 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==", + "license": "MIT" + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -15621,6 +16677,12 @@ "postcss": "^8.2.15" } }, + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "license": "MIT" + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -16121,6 +17183,15 @@ "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==", "license": "MIT" }, + "node_modules/throttle-debounce": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", + "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==", + "license": "MIT", + "engines": { + "node": ">=12.22" + } + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -16145,6 +17216,12 @@ "node": ">=8.0" } }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", + "license": "MIT" + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -16262,6 +17339,12 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "license": "0BSD" }, + "node_modules/turbo-stream": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz", + "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==", + "license": "ISC" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/client/package.json b/client/package.json index 12c4f19..197b1db 100644 --- a/client/package.json +++ b/client/package.json @@ -3,6 +3,7 @@ "version": "0.0.1", "private": true, "dependencies": { + "@ant-design/icons": "^5.6.1", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.2.0", @@ -11,8 +12,10 @@ "@types/node": "^16.18.126", "@types/react": "^19.0.11", "@types/react-dom": "^19.0.4", + "antd": "^5.24.7", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-router-dom": "^7.5.0", "react-scripts": "5.0.1", "typescript": "^4.9.5", "web-vitals": "^2.1.4" -- 2.39.5 From 51227bfd7b9c37592a77f3ff19921a21db0b7f29 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Wed, 16 Apr 2025 13:14:26 +0500 Subject: [PATCH 02/11] feat: add MainLayout with sidebar --- client/public/icons/sider/menu.svg | 3 + client/public/icons/sider/menu_open.svg | 3 + client/public/icons/sider/process-diagram.svg | 3 + .../public/icons/sider/running-processes.svg | 3 + client/public/icons/sider/settings.svg | 3 + client/src/App.tsx | 16 ++++- client/src/components/SiderMenu.tsx | 61 +++++++++++++++++++ client/src/index.tsx | 7 ++- client/src/pages/MainLayout.tsx | 40 ++++++++++++ client/src/pages/ProtectedRoute.tsx | 8 +++ 10 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 client/public/icons/sider/menu.svg create mode 100644 client/public/icons/sider/menu_open.svg create mode 100644 client/public/icons/sider/process-diagram.svg create mode 100644 client/public/icons/sider/running-processes.svg create mode 100644 client/public/icons/sider/settings.svg create mode 100644 client/src/components/SiderMenu.tsx create mode 100644 client/src/pages/MainLayout.tsx create mode 100644 client/src/pages/ProtectedRoute.tsx diff --git a/client/public/icons/sider/menu.svg b/client/public/icons/sider/menu.svg new file mode 100644 index 0000000..f380914 --- /dev/null +++ b/client/public/icons/sider/menu.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/icons/sider/menu_open.svg b/client/public/icons/sider/menu_open.svg new file mode 100644 index 0000000..9cf2fd4 --- /dev/null +++ b/client/public/icons/sider/menu_open.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/icons/sider/process-diagram.svg b/client/public/icons/sider/process-diagram.svg new file mode 100644 index 0000000..639c697 --- /dev/null +++ b/client/public/icons/sider/process-diagram.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/icons/sider/running-processes.svg b/client/public/icons/sider/running-processes.svg new file mode 100644 index 0000000..d68fcb5 --- /dev/null +++ b/client/public/icons/sider/running-processes.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/icons/sider/settings.svg b/client/public/icons/sider/settings.svg new file mode 100644 index 0000000..562ed62 --- /dev/null +++ b/client/public/icons/sider/settings.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/src/App.tsx b/client/src/App.tsx index e91ac07..a413c05 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,7 +1,21 @@ import React from 'react'; +import { Route, Routes } from 'react-router-dom'; +import MainLayout from './pages/MainLayout'; +import ProtectedRoute from './pages/ProtectedRoute'; function App() { - return
; + return ( +
+
+ + login
} /> + }> + }> + + +
+ + ); } export default App; diff --git a/client/src/components/SiderMenu.tsx b/client/src/components/SiderMenu.tsx new file mode 100644 index 0000000..ea0d238 --- /dev/null +++ b/client/src/components/SiderMenu.tsx @@ -0,0 +1,61 @@ +import { Menu, MenuProps } from 'antd'; + +type MenuItem = Required['items'][number]; + +function getItem( + label: React.ReactNode, + key: React.Key, + icon?: React.ReactNode, + children?: MenuItem[] +): MenuItem { + return { + key, + icon, + children, + label, + } as MenuItem; +} + +const sidebarItems: MenuItem[] = [ + getItem('VORKOUT', '0', toggle), + getItem( + 'Схемы процессов', + '1', + process diagram + ), + getItem( + 'Запущенные процессы', + '2', + running processes + ), + getItem( + 'Настройки', + 'sub1', + settings, + [ + getItem('Учетные записи', '3'), + getItem('Справичник событий', '4'), + getItem('Конфигурация', '5'), + ] + ), +]; + +interface SiderMenuProps { + selectedKey: string; + hangleMenuClick: (e: any) => void; +} + +export default function SiderMenu({ + selectedKey, + hangleMenuClick, +}: SiderMenuProps) { + return ( + + ); +} diff --git a/client/src/index.tsx b/client/src/index.tsx index 0a219d4..7087bbe 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -2,8 +2,13 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; +import { BrowserRouter } from 'react-router-dom'; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement ); -root.render(); +root.render( + + + +); diff --git a/client/src/pages/MainLayout.tsx b/client/src/pages/MainLayout.tsx new file mode 100644 index 0000000..1641576 --- /dev/null +++ b/client/src/pages/MainLayout.tsx @@ -0,0 +1,40 @@ +import React, { useState } from 'react'; +import { Layout } from 'antd'; +import Sider from 'antd/es/layout/Sider'; +import SiderMenu from '../components/SiderMenu'; + +export default function MainLayout() { + const [collapsed, setCollapsed] = useState(false); + const [selectedKey, setSelectedKey] = useState('1'); + + function hangleMenuClick(e: any) { + if (e.key === '0') { + setCollapsed((prev) => !prev); + return; + } + + setSelectedKey(e.key); + } + + return ( + + setCollapsed(value)} + theme="light" + width={'15%'} + collapsedWidth={'3.8%'} + trigger={null} + > + + + +
Main layout
+
+
+ ); +} diff --git a/client/src/pages/ProtectedRoute.tsx b/client/src/pages/ProtectedRoute.tsx new file mode 100644 index 0000000..43fc045 --- /dev/null +++ b/client/src/pages/ProtectedRoute.tsx @@ -0,0 +1,8 @@ +// ProtectedRoute.js +import { Outlet } from 'react-router-dom'; +import React from 'react'; + +const ProtectedRoute = (): React.JSX.Element => { + return ; +}; +export default ProtectedRoute; -- 2.39.5 From 583d2005a797d1fb70116d3b95807fe776698e83 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 17 Apr 2025 12:24:03 +0500 Subject: [PATCH 03/11] feat: add base styles and base routes --- client/public/icons/sider/more.svg | 3 + client/src/App.tsx | 14 ++- client/src/components/Header.tsx | 56 ++++++++++ client/src/components/SiderMenu.tsx | 121 ++++++++++++++-------- client/src/config/customTheme.ts | 14 +++ client/src/index.css | 14 +++ client/src/index.tsx | 11 +- client/src/pages/AccountsPage.tsx | 9 ++ client/src/pages/ConfigurationPage.tsx | 9 ++ client/src/pages/EventsListPage.tsx | 9 ++ client/src/pages/MainLayout.tsx | 40 ++++++- client/src/pages/ProcessDiagramPage.tsx | 9 ++ client/src/pages/RunningProcessesPage.tsx | 9 ++ 13 files changed, 259 insertions(+), 59 deletions(-) create mode 100644 client/public/icons/sider/more.svg create mode 100644 client/src/components/Header.tsx create mode 100644 client/src/config/customTheme.ts create mode 100644 client/src/pages/AccountsPage.tsx create mode 100644 client/src/pages/ConfigurationPage.tsx create mode 100644 client/src/pages/EventsListPage.tsx create mode 100644 client/src/pages/ProcessDiagramPage.tsx create mode 100644 client/src/pages/RunningProcessesPage.tsx diff --git a/client/public/icons/sider/more.svg b/client/public/icons/sider/more.svg new file mode 100644 index 0000000..c1efe35 --- /dev/null +++ b/client/public/icons/sider/more.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/src/App.tsx b/client/src/App.tsx index a413c05..7fc96c3 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -6,14 +6,12 @@ import ProtectedRoute from './pages/ProtectedRoute'; function App() { return (
-
- - login
} /> - }> - }> - - -
+ + login} /> + }> + }> + + ); } diff --git a/client/src/components/Header.tsx b/client/src/components/Header.tsx new file mode 100644 index 0000000..18a3b7b --- /dev/null +++ b/client/src/components/Header.tsx @@ -0,0 +1,56 @@ +import Title from 'antd/es/typography/Title'; + +interface HeaderProps { + title: string; +} + +export default function Header({ title }: HeaderProps) { + return ( +
+ + {title} + +
+ more +
+ user +
+
+
+ ); +} diff --git a/client/src/components/SiderMenu.tsx b/client/src/components/SiderMenu.tsx index ea0d238..a80bced 100644 --- a/client/src/components/SiderMenu.tsx +++ b/client/src/components/SiderMenu.tsx @@ -1,61 +1,96 @@ -import { Menu, MenuProps } from 'antd'; - -type MenuItem = Required['items'][number]; - -function getItem( - label: React.ReactNode, - key: React.Key, - icon?: React.ReactNode, - children?: MenuItem[] -): MenuItem { - return { - key, - icon, - children, - label, - } as MenuItem; -} - -const sidebarItems: MenuItem[] = [ - getItem('VORKOUT', '0', toggle), - getItem( - 'Схемы процессов', - '1', - process diagram - ), - getItem( - 'Запущенные процессы', - '2', - running processes - ), - getItem( - 'Настройки', - 'sub1', - settings, - [ - getItem('Учетные записи', '3'), - getItem('Справичник событий', '4'), - getItem('Конфигурация', '5'), - ] - ), -]; +import { Divider, Menu } from 'antd'; +import React from 'react'; interface SiderMenuProps { + collapsed: boolean; selectedKey: string; hangleMenuClick: (e: any) => void; } export default function SiderMenu({ + collapsed, selectedKey, hangleMenuClick, }: SiderMenuProps) { + const menuItems = ( + + + } + style={{ fontSize: '20px' }} + > + VORKOUT + + + + } + > + Схемы процессов + + + + } + > + Запущенные процессы + + + {!collapsed && } + + } + title="Настройки" + expandIcon={false} + > + + Учетные записи + + + Справочник событий + + + Конфигурация + + + + ); + return ( + defaultOpenKeys={['sub1']} + > + {menuItems} + ); } diff --git a/client/src/config/customTheme.ts b/client/src/config/customTheme.ts new file mode 100644 index 0000000..b79c59a --- /dev/null +++ b/client/src/config/customTheme.ts @@ -0,0 +1,14 @@ +export const theme = { + token: { + fontFamily: 'Roboto, sans-serif', + colorPrimary: '#548d10', + Menu: { + itemColor: 'f2f2f2', + itemBg: '#f2f2f2', + subMenuItemBg: '#f2f2f2', + }, + Layout: { + bodyBg: '#f2f2f2', + }, + }, +}; diff --git a/client/src/index.css b/client/src/index.css index ec2585e..ee20a4e 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -11,3 +11,17 @@ code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } + +.ant-menu-inline .ant-menu-submenu-selected { + border: none; +} + +.ant-menu-inline .ant-menu-submenu-selected > .ant-menu-submenu-title { + color: #548d10; +} + +.ant-menu-inline .ant-menu-item-selected { + background-color: transparent; + border: none; + color: #548d10; +} diff --git a/client/src/index.tsx b/client/src/index.tsx index 7087bbe..cceac43 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -3,12 +3,17 @@ import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import { BrowserRouter } from 'react-router-dom'; +import { ConfigProvider } from 'antd'; +import { theme } from './config/customTheme'; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement ); + root.render( - - - + + + + + ); diff --git a/client/src/pages/AccountsPage.tsx b/client/src/pages/AccountsPage.tsx new file mode 100644 index 0000000..979f796 --- /dev/null +++ b/client/src/pages/AccountsPage.tsx @@ -0,0 +1,9 @@ +import Header from '../components/Header'; + +export default function AccountsPage() { + return ( + <> +
+ + ); +} diff --git a/client/src/pages/ConfigurationPage.tsx b/client/src/pages/ConfigurationPage.tsx new file mode 100644 index 0000000..186a170 --- /dev/null +++ b/client/src/pages/ConfigurationPage.tsx @@ -0,0 +1,9 @@ +import Header from '../components/Header'; + +export default function ConfigurationPage() { + return ( + <> +
+ + ); +} diff --git a/client/src/pages/EventsListPage.tsx b/client/src/pages/EventsListPage.tsx new file mode 100644 index 0000000..453381a --- /dev/null +++ b/client/src/pages/EventsListPage.tsx @@ -0,0 +1,9 @@ +import Header from '../components/Header'; + +export default function EventsListPage() { + return ( + <> +
+ + ); +} diff --git a/client/src/pages/MainLayout.tsx b/client/src/pages/MainLayout.tsx index 1641576..604e343 100644 --- a/client/src/pages/MainLayout.tsx +++ b/client/src/pages/MainLayout.tsx @@ -1,19 +1,40 @@ -import React, { useState } from 'react'; +/* eslint-disable react-hooks/exhaustive-deps */ +import React, { useEffect, useState } from 'react'; import { Layout } from 'antd'; import Sider from 'antd/es/layout/Sider'; import SiderMenu from '../components/SiderMenu'; +import { Route, Routes, useLocation, useNavigate } from 'react-router-dom'; +import ProcessDiagramPage from './ProcessDiagramPage'; +import RunningProcessesPage from './RunningProcessesPage'; +import AccountsPage from './AccountsPage'; +import EventsListPage from './EventsListPage'; +import ConfigurationPage from './ConfigurationPage'; export default function MainLayout() { + const navigate = useNavigate(); + const location = useLocation(); const [collapsed, setCollapsed] = useState(false); const [selectedKey, setSelectedKey] = useState('1'); + useEffect(() => { + if (location.pathname === '/') { + navigate('/process-diagram'); + } + }, [location.pathname]); + + useEffect(() => { + setSelectedKey(location.pathname); + }); + function hangleMenuClick(e: any) { - if (e.key === '0') { - setCollapsed((prev) => !prev); + const key = e.key; + if (key === '0') { + setCollapsed(!collapsed); return; } - setSelectedKey(e.key); + setSelectedKey(key); + navigate(key); } return ( @@ -26,14 +47,23 @@ export default function MainLayout() { width={'15%'} collapsedWidth={'3.8%'} trigger={null} + style={{ backgroundColor: '#f2f2f2' }} > -
Main layout
+ + } /> + } /> + } /> + } /> + } /> + 404 Not Found} /> +
); diff --git a/client/src/pages/ProcessDiagramPage.tsx b/client/src/pages/ProcessDiagramPage.tsx new file mode 100644 index 0000000..5f8d212 --- /dev/null +++ b/client/src/pages/ProcessDiagramPage.tsx @@ -0,0 +1,9 @@ +import Header from '../components/Header'; + +export default function ProcessDiagramPage() { + return ( + <> +
+ + ); +} diff --git a/client/src/pages/RunningProcessesPage.tsx b/client/src/pages/RunningProcessesPage.tsx new file mode 100644 index 0000000..9063283 --- /dev/null +++ b/client/src/pages/RunningProcessesPage.tsx @@ -0,0 +1,9 @@ +import Header from '../components/Header'; + +export default function RunningProcessesPage() { + return ( + <> +
+ + ); +} -- 2.39.5 From 9f6b489bffed6a81c7524168dafb3e35f100904e Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 17 Apr 2025 20:55:57 +0500 Subject: [PATCH 04/11] feat: add styles for sider and remove deprecated menu elements --- client/src/components/SiderMenu.tsx | 141 ++++++++++++++-------------- client/src/index.css | 8 ++ client/src/pages/MainLayout.tsx | 33 +++++-- 3 files changed, 103 insertions(+), 79 deletions(-) diff --git a/client/src/components/SiderMenu.tsx b/client/src/components/SiderMenu.tsx index a80bced..cada106 100644 --- a/client/src/components/SiderMenu.tsx +++ b/client/src/components/SiderMenu.tsx @@ -12,75 +12,75 @@ export default function SiderMenu({ selectedKey, hangleMenuClick, }: SiderMenuProps) { - const menuItems = ( - - + const menuItems = [ + { + key: 'toggle', + icon: ( + toggle + ), + label: 'VORKOUT', + style: { fontSize: '20px' }, + }, + { + key: '/process-diagram', + icon: ( + process diagram + ), + label: 'Схемы процессов', + }, + { + key: '/running-processes', + icon: ( + running processes + ), + label: 'Запущенные процессы', + }, + !collapsed + ? { + key: 'divider', + label: , + style: { + marginBottom: '-16px', + marginTop: '-4px', + cursor: 'default', + }, + disabled: true, } - style={{ fontSize: '20px' }} - > - VORKOUT - - - - } - > - Схемы процессов - - - - } - > - Запущенные процессы - - - {!collapsed && } - - } - title="Настройки" - expandIcon={false} - > - - Учетные записи - - - Справочник событий - - - Конфигурация - - - - ); + : null, + { + key: 'sub1', + icon: settings, + label: 'Настройки', + className: 'no-expand-icon', + children: [ + { + key: '/accounts', + label: 'Учетные записи', + style: { fontSize: '12px', paddingLeft: '52px' }, + }, + { + key: '/events-list', + label: 'Справочник событий', + style: { fontSize: '12px', paddingLeft: '52px' }, + }, + { + key: '/configuration', + label: 'Конфигурация', + style: { fontSize: '12px', paddingLeft: '52px' }, + }, + ], + }, + ]; return ( - {menuItems} - + items={menuItems} + /> ); } diff --git a/client/src/index.css b/client/src/index.css index ee20a4e..46693ff 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -25,3 +25,11 @@ code { border: none; color: #548d10; } + +.sider { + background-color: #f2f2f2; +} + +.no-expand-icon .ant-menu-submenu-arrow { + display: none !important; +} diff --git a/client/src/pages/MainLayout.tsx b/client/src/pages/MainLayout.tsx index 604e343..2933a89 100644 --- a/client/src/pages/MainLayout.tsx +++ b/client/src/pages/MainLayout.tsx @@ -16,22 +16,39 @@ export default function MainLayout() { const [collapsed, setCollapsed] = useState(false); const [selectedKey, setSelectedKey] = useState('1'); + const [width, setWidth] = useState('15%'); + const [collapsedWidth, setCollapsedWidth] = useState(50); + + const calculateWidths = () => { + const windowWidth = window.innerWidth; + const expanded = Math.min(Math.max(windowWidth * 0.15, 180), 240); + const collapsed = Math.max(windowWidth * 0.038, 50); + setWidth(expanded); + setCollapsedWidth(collapsed); + }; + + useEffect(() => { + calculateWidths(); + window.addEventListener('resize', calculateWidths); + return () => window.removeEventListener('resize', calculateWidths); + }, []); + useEffect(() => { if (location.pathname === '/') { navigate('/process-diagram'); } - }, [location.pathname]); - - useEffect(() => { setSelectedKey(location.pathname); - }); + }, [location.pathname]); function hangleMenuClick(e: any) { const key = e.key; - if (key === '0') { + if (key === 'toggle') { setCollapsed(!collapsed); return; } + if (key === 'divider') { + return; + } setSelectedKey(key); navigate(key); @@ -40,14 +57,14 @@ export default function MainLayout() { return ( setCollapsed(value)} theme="light" - width={'15%'} - collapsedWidth={'3.8%'} + width={width} + collapsedWidth={collapsedWidth} trigger={null} - style={{ backgroundColor: '#f2f2f2' }} > Date: Fri, 18 Apr 2025 17:59:10 +0500 Subject: [PATCH 05/11] feat: resize icons in menu and add tooltips for labels --- client/src/components/SiderMenu.tsx | 35 +++++++++++++++++++++-------- client/src/config/customTheme.ts | 1 + 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/client/src/components/SiderMenu.tsx b/client/src/components/SiderMenu.tsx index cada106..8403cf0 100644 --- a/client/src/components/SiderMenu.tsx +++ b/client/src/components/SiderMenu.tsx @@ -1,4 +1,4 @@ -import { Divider, Menu } from 'antd'; +import { Divider, Menu, Tooltip } from 'antd'; import React from 'react'; interface SiderMenuProps { @@ -12,6 +12,10 @@ export default function SiderMenu({ selectedKey, hangleMenuClick, }: SiderMenuProps) { + const collapseStyle = collapsed + ? { fontSize: '12px' } + : { fontSize: '12px', paddingLeft: '52px' }; + const menuItems = [ { key: 'toggle', @@ -33,7 +37,7 @@ export default function SiderMenu({ icon: ( process diagram ), - label: 'Схемы процессов', + label: Схемы процессов, }, { key: '/running-processes', @@ -43,7 +47,7 @@ export default function SiderMenu({ alt="running processes" /> ), - label: 'Запущенные процессы', + label: Запущенные процессы, }, !collapsed ? { @@ -53,6 +57,7 @@ export default function SiderMenu({ marginBottom: '-16px', marginTop: '-4px', cursor: 'default', + width: '100%', }, disabled: true, } @@ -65,18 +70,30 @@ export default function SiderMenu({ children: [ { key: '/accounts', - label: 'Учетные записи', - style: { fontSize: '12px', paddingLeft: '52px' }, + label: !collapsed ? ( + Учетные записи + ) : ( + 'Учетные записи' + ), + style: collapseStyle, }, { key: '/events-list', - label: 'Справочник событий', - style: { fontSize: '12px', paddingLeft: '52px' }, + label: !collapsed ? ( + Справочник событий + ) : ( + 'Справочник событий' + ), + style: collapseStyle, }, { key: '/configuration', - label: 'Конфигурация', - style: { fontSize: '12px', paddingLeft: '52px' }, + label: !collapsed ? ( + Конфигурация + ) : ( + 'Конфигурация' + ), + style: collapseStyle, }, ], }, diff --git a/client/src/config/customTheme.ts b/client/src/config/customTheme.ts index b79c59a..3863996 100644 --- a/client/src/config/customTheme.ts +++ b/client/src/config/customTheme.ts @@ -6,6 +6,7 @@ export const theme = { itemColor: 'f2f2f2', itemBg: '#f2f2f2', subMenuItemBg: '#f2f2f2', + iconSize: '18px', }, Layout: { bodyBg: '#f2f2f2', -- 2.39.5 From e7fbd53dfe88842ea04c669ac603bb073c9c73e4 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Mon, 21 Apr 2025 13:19:30 +0500 Subject: [PATCH 06/11] feat: add content drawer and change header img to avatar --- client/public/icons/drawer/arrow_back.svg | 3 + client/public/icons/drawer/delete.svg | 3 + client/src/components/ContentDrawer.tsx | 101 ++++++++++++++++++++++ client/src/components/Header.tsx | 11 +-- 4 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 client/public/icons/drawer/arrow_back.svg create mode 100644 client/public/icons/drawer/delete.svg create mode 100644 client/src/components/ContentDrawer.tsx diff --git a/client/public/icons/drawer/arrow_back.svg b/client/public/icons/drawer/arrow_back.svg new file mode 100644 index 0000000..8f4a6dc --- /dev/null +++ b/client/public/icons/drawer/arrow_back.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/icons/drawer/delete.svg b/client/public/icons/drawer/delete.svg new file mode 100644 index 0000000..e2c48d6 --- /dev/null +++ b/client/public/icons/drawer/delete.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/src/components/ContentDrawer.tsx b/client/src/components/ContentDrawer.tsx new file mode 100644 index 0000000..5c83586 --- /dev/null +++ b/client/src/components/ContentDrawer.tsx @@ -0,0 +1,101 @@ +import { Drawer } from 'antd'; +import { useEffect, useState } from 'react'; +import { Avatar, Typography } from 'antd'; + +interface ContentDrawerProps { + open: boolean; + closeDrawer: () => void; + children: React.ReactNode; +} + +export default function ContentDrawer({ + open, + closeDrawer, + children, +}: ContentDrawerProps) { + const [width, setWidth] = useState('30%'); + + const calculateWidths = () => { + const windowWidth = window.innerWidth; + const expanded = Math.max(windowWidth * 0.3, 300); + setWidth(expanded); + }; + + useEffect(() => { + calculateWidths(); + window.addEventListener('resize', calculateWidths); + return () => window.removeEventListener('resize', calculateWidths); + }, []); + + const drawerTitle = ( +
+
+ close_drawer +
+ +
+ +
+ + Александр Александров + + + alexandralex@vorkout.ru + +
+
+ +
+ delete +
+
+ ); + + return ( + + {children} + + ); +} diff --git a/client/src/components/Header.tsx b/client/src/components/Header.tsx index 18a3b7b..1dd99bf 100644 --- a/client/src/components/Header.tsx +++ b/client/src/components/Header.tsx @@ -1,3 +1,4 @@ +import { Avatar } from 'antd'; import Title from 'antd/es/typography/Title'; interface HeaderProps { @@ -41,13 +42,9 @@ export default function Header({ title }: HeaderProps) { justifyContent: 'center', }} > - user -- 2.39.5 From 5300e53c437e3e03911d63f6b3492984ae5345e2 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Tue, 22 Apr 2025 11:53:36 +0500 Subject: [PATCH 07/11] feat: add form for drawer and refactor styles --- client/public/icons/drawer/reg.svg | 3 + client/public/icons/drawer/save.svg | 3 + client/public/icons/header/add_2.svg | 3 + .../public/icons/{sider => header}/more.svg | 0 client/src/components/Header.tsx | 6 +- client/src/config/customTheme.ts | 2 +- client/src/index.css | 9 ++ client/src/pages/AccountsPage.tsx | 136 +++++++++++++++++- 8 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 client/public/icons/drawer/reg.svg create mode 100644 client/public/icons/drawer/save.svg create mode 100644 client/public/icons/header/add_2.svg rename client/public/icons/{sider => header}/more.svg (100%) diff --git a/client/public/icons/drawer/reg.svg b/client/public/icons/drawer/reg.svg new file mode 100644 index 0000000..8567abe --- /dev/null +++ b/client/public/icons/drawer/reg.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/icons/drawer/save.svg b/client/public/icons/drawer/save.svg new file mode 100644 index 0000000..f23b41b --- /dev/null +++ b/client/public/icons/drawer/save.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/icons/header/add_2.svg b/client/public/icons/header/add_2.svg new file mode 100644 index 0000000..a53ab05 --- /dev/null +++ b/client/public/icons/header/add_2.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/icons/sider/more.svg b/client/public/icons/header/more.svg similarity index 100% rename from client/public/icons/sider/more.svg rename to client/public/icons/header/more.svg diff --git a/client/src/components/Header.tsx b/client/src/components/Header.tsx index 1dd99bf..2ff9076 100644 --- a/client/src/components/Header.tsx +++ b/client/src/components/Header.tsx @@ -3,9 +3,10 @@ import Title from 'antd/es/typography/Title'; interface HeaderProps { title: string; + additionalContent?: React.ReactNode; } -export default function Header({ title }: HeaderProps) { +export default function Header({ title, additionalContent }: HeaderProps) { return (
+ {additionalContent} more diff --git a/client/src/config/customTheme.ts b/client/src/config/customTheme.ts index 3863996..fa1ae99 100644 --- a/client/src/config/customTheme.ts +++ b/client/src/config/customTheme.ts @@ -1,7 +1,7 @@ export const theme = { token: { fontFamily: 'Roboto, sans-serif', - colorPrimary: '#548d10', + colorPrimary: '#C2DA3D', Menu: { itemColor: 'f2f2f2', itemBg: '#f2f2f2', diff --git a/client/src/index.css b/client/src/index.css index 46693ff..1cd3abf 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -26,6 +26,15 @@ code { color: #548d10; } +.ant-menu-item-selected { + background-color: transparent !important; +} + +.ant-menu-item-selected a, +.ant-menu-item-selected { + color: #548d10 !important; +} + .sider { background-color: #f2f2f2; } diff --git a/client/src/pages/AccountsPage.tsx b/client/src/pages/AccountsPage.tsx index 979f796..cb47e41 100644 --- a/client/src/pages/AccountsPage.tsx +++ b/client/src/pages/AccountsPage.tsx @@ -1,9 +1,143 @@ +import { Button, Form, Input, Select } from 'antd'; import Header from '../components/Header'; +import { useState } from 'react'; +import ContentDrawer from '../components/ContentDrawer'; + +const { Option } = Select; export default function AccountsPage() { + const [open, setOpen] = useState(false); + + const showDrawer = () => setOpen(true); + const closeDrawer = () => setOpen(false); + + const userEdit = ( +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ ); + return ( <> -
+
+ } + /> + + + {userEdit} + ); } -- 2.39.5 From 732dd701afc3708bc0142f5f41851bfaccfc59ff Mon Sep 17 00:00:00 2001 From: Vladislav Date: Wed, 23 Apr 2025 12:22:45 +0500 Subject: [PATCH 08/11] feat: add form for create new user --- .../icons/drawer/add_photo_alternate.svg | 3 + client/src/components/ContentDrawer.tsx | 61 ++++- client/src/components/UserCreate.tsx | 227 ++++++++++++++++++ client/src/components/UserEdit.tsx | 111 +++++++++ client/src/pages/AccountsPage.tsx | 114 +-------- 5 files changed, 403 insertions(+), 113 deletions(-) create mode 100644 client/public/icons/drawer/add_photo_alternate.svg create mode 100644 client/src/components/UserCreate.tsx create mode 100644 client/src/components/UserEdit.tsx diff --git a/client/public/icons/drawer/add_photo_alternate.svg b/client/public/icons/drawer/add_photo_alternate.svg new file mode 100644 index 0000000..7ea4048 --- /dev/null +++ b/client/public/icons/drawer/add_photo_alternate.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/src/components/ContentDrawer.tsx b/client/src/components/ContentDrawer.tsx index 5c83586..531ae40 100644 --- a/client/src/components/ContentDrawer.tsx +++ b/client/src/components/ContentDrawer.tsx @@ -6,12 +6,14 @@ interface ContentDrawerProps { open: boolean; closeDrawer: () => void; children: React.ReactNode; + type: 'create' | 'edit'; } export default function ContentDrawer({ open, closeDrawer, children, + type, }: ContentDrawerProps) { const [width, setWidth] = useState('30%'); @@ -27,7 +29,7 @@ export default function ContentDrawer({ return () => window.removeEventListener('resize', calculateWidths); }, []); - const drawerTitle = ( + const editDrawerTitle = (
); + const createDrawerTitle = ( +
+
+ close_drawer +
+ +
+ Новая учетная запись +
+ +
+ delete +
+
+ ); + return ( >[0]; + +const getBase64 = (file: FileType): Promise => + new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = () => resolve(reader.result as string); + reader.onerror = (error) => reject(error); + }); + +export default function UserCreate() { + const [previewOpen, setPreviewOpen] = useState(false); + const [previewImage, setPreviewImage] = useState(''); + + const [fileList, setFileList] = useState([]); + + const handlePreview = async (file: UploadFile) => { + if (!file.url && !file.preview) { + file.preview = await getBase64(file.originFileObj as FileType); + } + + setPreviewImage(file.url || (file.preview as string)); + setPreviewOpen(true); + }; + + const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => + setFileList(newFileList); + + const customUploadButton = ( +
+
+ add_photo_alternate +
+ + Выбрать фото +
+ ); + + const photoToUpload = ( + <> + false} + > + {fileList.length > 0 ? null : customUploadButton} + + {previewImage && ( + setPreviewOpen(visible), + afterOpenChange: (visible) => !visible && setPreviewImage(''), + }} + src={previewImage} + /> + )} + + ); + + return ( +
+
+
+ {photoToUpload} +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ ); +} diff --git a/client/src/components/UserEdit.tsx b/client/src/components/UserEdit.tsx new file mode 100644 index 0000000..c194bff --- /dev/null +++ b/client/src/components/UserEdit.tsx @@ -0,0 +1,111 @@ +import { Button, Form, Input, Select } from 'antd'; + +const { Option } = Select; + +export default function UserEdit() { + return ( +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ ); +} diff --git a/client/src/pages/AccountsPage.tsx b/client/src/pages/AccountsPage.tsx index cb47e41..aa6a98e 100644 --- a/client/src/pages/AccountsPage.tsx +++ b/client/src/pages/AccountsPage.tsx @@ -1,9 +1,7 @@ -import { Button, Form, Input, Select } from 'antd'; import Header from '../components/Header'; import { useState } from 'react'; import ContentDrawer from '../components/ContentDrawer'; - -const { Option } = Select; +import UserCreate from '../components/UserCreate'; export default function AccountsPage() { const [open, setOpen] = useState(false); @@ -11,112 +9,6 @@ export default function AccountsPage() { const showDrawer = () => setOpen(true); const closeDrawer = () => setOpen(false); - const userEdit = ( -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- ); - return ( <>
- - {userEdit} + + ); -- 2.39.5 From d6911626a792d196bdbf41cc6dc03139a9f11d52 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Wed, 23 Apr 2025 12:44:48 +0500 Subject: [PATCH 09/11] refactor: remove twitch animation on upload photo --- client/src/components/UserCreate.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/client/src/components/UserCreate.tsx b/client/src/components/UserCreate.tsx index 177a802..4eeb231 100644 --- a/client/src/components/UserCreate.tsx +++ b/client/src/components/UserCreate.tsx @@ -1,6 +1,4 @@ -import { PlusOutlined } from '@ant-design/icons'; import { - Avatar, Button, Form, Input, @@ -71,7 +69,7 @@ export default function UserCreate() { ); const photoToUpload = ( - <> +
)} - +
); return ( -- 2.39.5 From dc1b74348fcf806b6348a931a1dadb3529e9c0cd Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 24 Apr 2025 16:14:16 +0500 Subject: [PATCH 10/11] chore: add i18n --- client/package-lock.json | 87 +++++++++++++++++++++++++++++ client/package.json | 3 + client/src/components/SiderMenu.tsx | 24 +++++--- client/src/index.tsx | 7 +-- client/src/pages/AccountsPage.tsx | 4 +- 5 files changed, 111 insertions(+), 14 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index a81a568..838d78d 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -18,8 +18,11 @@ "@types/react": "^19.0.11", "@types/react-dom": "^19.0.4", "antd": "^5.24.7", + "i18next": "^25.0.1", + "i18next-browser-languagedetector": "^8.0.5", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-i18next": "^15.5.1", "react-router-dom": "^7.5.0", "react-scripts": "5.0.1", "typescript": "^4.9.5", @@ -9351,6 +9354,15 @@ "node": ">=12" } }, + "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" + } + }, "node_modules/html-webpack-plugin": { "version": "5.6.3", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz", @@ -9504,6 +9516,46 @@ "node": ">=10.17.0" } }, + "node_modules/i18next": { + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.0.1.tgz", + "integrity": "sha512-8S8PyZbrymJZn3DaN70/34JYWNhsqrU6yA4MuzcygJBv+41dgNMocEA8h+kV1P7MCc1ll03lOTOIXE7mpNCicw==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.10" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/i18next-browser-languagedetector": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.5.tgz", + "integrity": "sha512-OstebRKqKiQw8xEvQF5aRyUujsCatanj7Q9eo5iiH2gJpoXGZ7483ol3sVBwfqbobTQPNH1J+NAyJ1aCQoEC+w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -14931,6 +14983,32 @@ "integrity": "sha512-SN/U6Ytxf1QGkw/9ve5Y+NxBbZM6Ht95tuXNMKs8EJyFa/Vy/+Co3stop3KBHARfn/giv+Lj1uUnTfOJ3moFEQ==", "license": "MIT" }, + "node_modules/react-i18next": { + "version": "15.5.1", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.5.1.tgz", + "integrity": "sha512-C8RZ7N7H0L+flitiX6ASjq9p5puVJU1Z8VyL3OgM/QOMRf40BMZX+5TkpxzZVcTmOLPX5zlti4InEX5pFyiVeA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "html-parse-stringify": "^3.0.1" + }, + "peerDependencies": { + "i18next": ">= 23.2.3", + "react": ">= 16.8.0", + "typescript": "^5" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -17720,6 +17798,15 @@ "node": ">= 0.8" } }, + "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" + } + }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", diff --git a/client/package.json b/client/package.json index 197b1db..956c0ce 100644 --- a/client/package.json +++ b/client/package.json @@ -13,8 +13,11 @@ "@types/react": "^19.0.11", "@types/react-dom": "^19.0.4", "antd": "^5.24.7", + "i18next": "^25.0.1", + "i18next-browser-languagedetector": "^8.0.5", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-i18next": "^15.5.1", "react-router-dom": "^7.5.0", "react-scripts": "5.0.1", "typescript": "^4.9.5", diff --git a/client/src/components/SiderMenu.tsx b/client/src/components/SiderMenu.tsx index 8403cf0..8ce7ab4 100644 --- a/client/src/components/SiderMenu.tsx +++ b/client/src/components/SiderMenu.tsx @@ -1,5 +1,6 @@ import { Divider, Menu, Tooltip } from 'antd'; import React from 'react'; +import { useTranslation } from 'react-i18next'; interface SiderMenuProps { collapsed: boolean; @@ -12,6 +13,7 @@ export default function SiderMenu({ selectedKey, hangleMenuClick, }: SiderMenuProps) { + const { t } = useTranslation(); const collapseStyle = collapsed ? { fontSize: '12px' } : { fontSize: '12px', paddingLeft: '52px' }; @@ -37,7 +39,9 @@ export default function SiderMenu({ icon: ( process diagram ), - label: Схемы процессов, + label: ( + {t('processDiagrams')} + ), }, { key: '/running-processes', @@ -47,7 +51,9 @@ export default function SiderMenu({ alt="running processes" /> ), - label: Запущенные процессы, + label: ( + {t('runningProcesses')} + ), }, !collapsed ? { @@ -65,33 +71,33 @@ export default function SiderMenu({ { key: 'sub1', icon: settings, - label: 'Настройки', + label: t('settings'), className: 'no-expand-icon', children: [ { key: '/accounts', label: !collapsed ? ( - Учетные записи + {t('accounts')} ) : ( - 'Учетные записи' + t('accounts') ), style: collapseStyle, }, { key: '/events-list', label: !collapsed ? ( - Справочник событий + {t('eventsList')} ) : ( - 'Справочник событий' + t('eventsList') ), style: collapseStyle, }, { key: '/configuration', label: !collapsed ? ( - Конфигурация + {t('configuration')} ) : ( - 'Конфигурация' + t('configuration') ), style: collapseStyle, }, diff --git a/client/src/index.tsx b/client/src/index.tsx index cceac43..2631204 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -3,17 +3,16 @@ import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import { BrowserRouter } from 'react-router-dom'; -import { ConfigProvider } from 'antd'; -import { theme } from './config/customTheme'; +import AppWrapper from './config/AppWrapper'; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement ); root.render( - + - + ); diff --git a/client/src/pages/AccountsPage.tsx b/client/src/pages/AccountsPage.tsx index aa6a98e..4387052 100644 --- a/client/src/pages/AccountsPage.tsx +++ b/client/src/pages/AccountsPage.tsx @@ -2,8 +2,10 @@ import Header from '../components/Header'; import { useState } from 'react'; import ContentDrawer from '../components/ContentDrawer'; import UserCreate from '../components/UserCreate'; +import { useTranslation } from 'react-i18next'; export default function AccountsPage() { + const { t } = useTranslation(); const [open, setOpen] = useState(false); const showDrawer = () => setOpen(true); @@ -12,7 +14,7 @@ export default function AccountsPage() { return ( <>
Date: Thu, 24 Apr 2025 16:59:18 +0500 Subject: [PATCH 11/11] feat: add en language --- client/public/index.html | 2 +- client/src/components/ContentDrawer.tsx | 5 +- client/src/components/UserCreate.tsx | 42 +++++++------ client/src/components/UserEdit.tsx | 38 ++++++------ client/src/config/AppWrapper.tsx | 24 ++++++++ client/src/config/i18n.ts | 74 +++++++++++++++++++++++ client/src/pages/ConfigurationPage.tsx | 4 +- client/src/pages/EventsListPage.tsx | 4 +- client/src/pages/ProcessDiagramPage.tsx | 4 +- client/src/pages/RunningProcessesPage.tsx | 4 +- 10 files changed, 158 insertions(+), 43 deletions(-) create mode 100644 client/src/config/AppWrapper.tsx create mode 100644 client/src/config/i18n.ts diff --git a/client/public/index.html b/client/public/index.html index aa069f2..0fc0d9c 100644 --- a/client/public/index.html +++ b/client/public/index.html @@ -24,7 +24,7 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> - React App + VORKOUT diff --git a/client/src/components/ContentDrawer.tsx b/client/src/components/ContentDrawer.tsx index 531ae40..f02b6f4 100644 --- a/client/src/components/ContentDrawer.tsx +++ b/client/src/components/ContentDrawer.tsx @@ -1,6 +1,7 @@ import { Drawer } from 'antd'; import { useEffect, useState } from 'react'; import { Avatar, Typography } from 'antd'; +import { useTranslation } from 'react-i18next'; interface ContentDrawerProps { open: boolean; @@ -15,6 +16,7 @@ export default function ContentDrawer({ children, type, }: ContentDrawerProps) { + const { t } = useTranslation(); const [width, setWidth] = useState('30%'); const calculateWidths = () => { @@ -123,7 +125,7 @@ export default function ContentDrawer({ fontSize: '20px', }} > - Новая учетная запись + {t('newAccount')}
=> }); export default function UserCreate() { + const { t } = useTranslation(); const [previewOpen, setPreviewOpen] = useState(false); const [previewImage, setPreviewImage] = useState(''); @@ -64,7 +66,9 @@ export default function UserCreate() { />
- Выбрать фото + + {t('selectPhoto')} +
); @@ -135,54 +139,54 @@ export default function UserCreate() { style={{ flex: 1, display: 'flex', flexDirection: 'column' }} > - @@ -190,11 +194,11 @@ export default function UserCreate() { - @@ -216,7 +220,7 @@ export default function UserCreate() { alt="save" style={{ height: '18px', width: '18px' }} />{' '} - Добавить аккаунт + {t('addAccount')} diff --git a/client/src/components/UserEdit.tsx b/client/src/components/UserEdit.tsx index c194bff..bd5e8f0 100644 --- a/client/src/components/UserEdit.tsx +++ b/client/src/components/UserEdit.tsx @@ -1,8 +1,10 @@ import { Button, Form, Input, Select } from 'antd'; +import { useTranslation } from 'react-i18next'; const { Option } = Select; export default function UserEdit() { + const { t } = useTranslation(); return (
- @@ -76,11 +78,11 @@ export default function UserEdit() { - @@ -102,7 +104,7 @@ export default function UserEdit() { alt="save" style={{ height: '18px', width: '18px' }} />{' '} - Сохранить изменения + {t('save')}
diff --git a/client/src/config/AppWrapper.tsx b/client/src/config/AppWrapper.tsx new file mode 100644 index 0000000..6bea4bc --- /dev/null +++ b/client/src/config/AppWrapper.tsx @@ -0,0 +1,24 @@ +import './i18n'; +import { ConfigProvider } from 'antd'; +import { useTranslation } from 'react-i18next'; + +import { theme } from './customTheme'; + +import en from 'antd/locale/en_US'; +import ru from 'antd/locale/ru_RU'; + +const antdLocales = { + en: en, + ru: ru, +}; + +export default function AppWrapper({ children }: any) { + const { i18n } = useTranslation(); + const currentLang = i18n.language.split('-')[0] as 'en' | 'ru'; + + return ( + + {children} + + ); +} diff --git a/client/src/config/i18n.ts b/client/src/config/i18n.ts new file mode 100644 index 0000000..09bd8b8 --- /dev/null +++ b/client/src/config/i18n.ts @@ -0,0 +1,74 @@ +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; +import LanguageDetector from 'i18next-browser-languagedetector'; + +i18n + .use(LanguageDetector) + .use(initReactI18next) + .init({ + fallbackLng: 'en', + supportedLngs: ['en', 'ru'], + interpolation: { escapeValue: false }, + resources: { + en: { + translation: { + accounts: 'Accounts', + processDiagrams: 'Process diagrams', + runningProcesses: 'Running processes', + settings: 'Settings', + eventsList: 'Events list', + configuration: 'Configuration', + selectPhoto: 'Select photo', + name: 'Name', + login: 'Login', + password: 'Password', + email: 'Email', + tenant: 'Tenant', + role: 'Role', + status: 'Status', + nameMessage: 'Enter name', + loginMessage: 'Enter login', + passwordMessage: 'Enter password', + emailMessage: 'Enter email', + emailErrorMessage: 'Incorrect email', + tenantMessage: 'Enter tenant', + roleMessage: 'Choose role', + statusMessage: 'Choose status', + addAccount: 'Add account', + save: 'Save changes', + newAccount: 'New account', + }, + }, + ru: { + translation: { + accounts: 'Учетные записи', + processDiagrams: 'Схемы процессов', + runningProcesses: 'Запущенные процессы', + settings: 'Настройки', + eventsList: 'Справочкин событий', + configuration: 'Конфигурация', + selectPhoto: 'Выбрать фото', + name: 'Имя', + login: 'Логин', + password: 'Пароль', + email: 'Имейл', + tenant: 'Привязка', + role: 'Роль', + status: 'Статус', + nameMessage: 'Введите имя', + loginMessage: 'Введите логин', + passwordMessage: 'Введите пароль', + emailMessage: 'Введите имейл', + emailErrorMessage: 'Некорректный имейл', + tenantMessage: 'Введите привязку', + roleMessage: 'Выберите роль', + statusMessage: 'Выберите статус', + addAccount: 'Добавить аккаунт', + save: 'Сохранить изменения', + newAccount: 'Новая учетная запись', + }, + }, + }, + }); + +export default i18n; diff --git a/client/src/pages/ConfigurationPage.tsx b/client/src/pages/ConfigurationPage.tsx index 186a170..b157e42 100644 --- a/client/src/pages/ConfigurationPage.tsx +++ b/client/src/pages/ConfigurationPage.tsx @@ -1,9 +1,11 @@ +import { useTranslation } from 'react-i18next'; import Header from '../components/Header'; export default function ConfigurationPage() { + const { t } = useTranslation(); return ( <> -
+
); } diff --git a/client/src/pages/EventsListPage.tsx b/client/src/pages/EventsListPage.tsx index 453381a..dd7d5d4 100644 --- a/client/src/pages/EventsListPage.tsx +++ b/client/src/pages/EventsListPage.tsx @@ -1,9 +1,11 @@ +import { useTranslation } from 'react-i18next'; import Header from '../components/Header'; export default function EventsListPage() { + const { t } = useTranslation(); return ( <> -
+
); } diff --git a/client/src/pages/ProcessDiagramPage.tsx b/client/src/pages/ProcessDiagramPage.tsx index 5f8d212..5ab0d5c 100644 --- a/client/src/pages/ProcessDiagramPage.tsx +++ b/client/src/pages/ProcessDiagramPage.tsx @@ -1,9 +1,11 @@ +import { useTranslation } from 'react-i18next'; import Header from '../components/Header'; export default function ProcessDiagramPage() { + const { t } = useTranslation(); return ( <> -
+
); } diff --git a/client/src/pages/RunningProcessesPage.tsx b/client/src/pages/RunningProcessesPage.tsx index 9063283..6da1e34 100644 --- a/client/src/pages/RunningProcessesPage.tsx +++ b/client/src/pages/RunningProcessesPage.tsx @@ -1,9 +1,11 @@ +import { useTranslation } from 'react-i18next'; import Header from '../components/Header'; export default function RunningProcessesPage() { + const { t } = useTranslation(); return ( <> -
+
); } -- 2.39.5