From db67f3008272559d77c4de64739a51c232d1d9ae Mon Sep 17 00:00:00 2001 From: josc146 Date: Sun, 25 Jun 2023 00:07:14 +0800 Subject: [PATCH] feat: chat presets (experimental) --- .gitignore | 1 + frontend/package-lock.json | 422 +++++++++++------ frontend/package.json | 2 + frontend/src/App.tsx | 18 +- frontend/src/_locales/zh-hans/main.json | 27 +- .../src/components/CustomToastContainer.tsx | 17 + frontend/src/components/ToolTipButton.tsx | 8 +- frontend/src/pages/Chat.tsx | 25 +- frontend/src/pages/Completion.tsx | 29 +- .../pages/PresetsManager/MessagesEditor.tsx | 154 +++++++ .../pages/PresetsManager/PresetsButton.tsx | 432 ++++++++++++++++++ frontend/src/startup.ts | 12 +- frontend/src/stores/commonStore.ts | 21 +- frontend/src/utils/get-conversation-pairs.ts | 27 -- frontend/src/utils/index.tsx | 4 + 15 files changed, 987 insertions(+), 212 deletions(-) create mode 100644 frontend/src/components/CustomToastContainer.tsx create mode 100644 frontend/src/pages/PresetsManager/MessagesEditor.tsx create mode 100644 frontend/src/pages/PresetsManager/PresetsButton.tsx delete mode 100644 frontend/src/utils/get-conversation-pairs.ts diff --git a/.gitignore b/.gitignore index 1869823..9f182cc 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ __pycache__ *.bin /config.json /cache.json +/presets.json /frontend/stats.html /frontend/package.json.md5 /py310 diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c87535b..a83d946 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -18,6 +18,7 @@ "mobx": "^6.9.0", "mobx-react-lite": "^3.4.3", "react": "^18.2.0", + "react-beautiful-dnd": "^13.1.1", "react-dom": "^18.2.0", "react-i18next": "^12.2.2", "react-markdown": "^8.0.7", @@ -33,6 +34,7 @@ }, "devDependencies": { "@types/react": "^18.2.6", + "@types/react-beautiful-dnd": "^13.1.4", "@types/react-dom": "^18.2.4", "@types/uuid": "^9.0.1", "@vitejs/plugin-react": "^4.0.0", @@ -56,7 +58,7 @@ }, "node_modules/@ampproject/remapping": { "version": "2.2.1", - "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.2.1.tgz", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, "dependencies": { @@ -68,42 +70,42 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.21.4", - "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.21.4.tgz", - "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", + "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", "dev": true, "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.21.7", - "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.21.7.tgz", - "integrity": "sha512-KYMqFYTaenzMK4yUtf4EW9wc4N9ef80FsbMtkwool5zpwl4YrT1SdWYSTRcT94KO4hannogdS+LxY7L+arP3gA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.5.tgz", + "integrity": "sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.21.8", - "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.21.8.tgz", - "integrity": "sha512-YeM22Sondbo523Sz0+CirSPnbj9bG3P0CdHcBZdqUuaeOaYEFbOLoGU7lebvGP6P5J/WE9wOn7u7C4J9HvS1xQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.5.tgz", + "integrity": "sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.5", - "@babel/helper-compilation-targets": "^7.21.5", - "@babel/helper-module-transforms": "^7.21.5", - "@babel/helpers": "^7.21.5", - "@babel/parser": "^7.21.8", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helpers": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -112,15 +114,19 @@ }, "engines": { "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, "node_modules/@babel/generator": { - "version": "7.21.5", - "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.21.5.tgz", - "integrity": "sha512-SrKK/sRv8GesIW1bDagf9cCG38IOMYZusoe1dfg0D8aiUe3Amvoj1QtjTPAWcfrZFvIwlleLb0gxzQidL9w14w==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.5.tgz", + "integrity": "sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==", "dev": true, "dependencies": { - "@babel/types": "^7.21.5", + "@babel/types": "^7.22.5", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -130,13 +136,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.21.5", - "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.5.tgz", - "integrity": "sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz", + "integrity": "sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.21.5", - "@babel/helper-validator-option": "^7.21.0", + "@babel/compat-data": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" @@ -149,151 +155,151 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.21.5", - "resolved": "https://registry.npmmirror.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.21.5.tgz", - "integrity": "sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", + "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmmirror.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", + "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", "dev": true, "dependencies": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmmirror.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.21.4", - "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", - "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", "dev": true, "dependencies": { - "@babel/types": "^7.21.4" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.21.5", - "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.21.5.tgz", - "integrity": "sha512-bI2Z9zBGY2q5yMHoBvJ2a9iX3ZOAzJPm7Q8Yz6YeoUjU/Cvhmi2G4QyTNyPBqqXSgTjUxRg3L0xV45HvkNWWBw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz", + "integrity": "sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.21.5", - "@babel/helper-module-imports": "^7.21.4", - "@babel/helper-simple-access": "^7.21.5", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5" + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.21.5", - "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.21.5.tgz", - "integrity": "sha512-0WDaIlXKOX/3KfBK/dwP1oQGiPh6rjMkT7HIRv7i5RR2VUMwrx5ZL0dwBkKx7+SW1zwNdgjHd34IMk5ZjTeHVg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.21.5", - "resolved": "https://registry.npmmirror.com/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz", - "integrity": "sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, "dependencies": { - "@babel/types": "^7.21.5" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmmirror.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz", + "integrity": "sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.21.5", - "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz", - "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", + "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", + "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.21.5", - "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.21.5.tgz", - "integrity": "sha512-BSY+JSlHxOmGsPTydUkPf1MdMQ3M81x5xGCOVgWM3G8XH77sJ292Y2oqcp0CbbgxhqBuI46iUz1tT7hqP7EfgA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.5.tgz", + "integrity": "sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==", "dev": true, "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5" + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", + "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", + "@babel/helper-validator-identifier": "^7.22.5", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -302,9 +308,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.8", - "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.21.8.tgz", - "integrity": "sha512-6zavDGdzG3gUqAdWvlLFfk+36RilI+Pwyuuh7HItyeScCWP3k6i8vKclAQ0bM/0y/Kz/xiwvxhMv9MgTJP5gmA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz", + "integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -314,12 +320,12 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.21.0", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.21.0.tgz", - "integrity": "sha512-f/Eq+79JEu+KUANFks9UZCcvydOOGMgF7jBrcwjHa5jTZD8JivnhCJYvmlhR/WTXBWonDExPoW0eO/CR4QJirA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.22.5.tgz", + "integrity": "sha512-nTh2ogNUtxbiSbxaT4Ds6aXnXEipHweN9YRgOX/oNXdf0cCrGn/+2LozFa3lnPV5D90MkjhgckCPBrsoSc1a7g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -329,12 +335,12 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.19.6", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.19.6.tgz", - "integrity": "sha512-RpAi004QyMNisst/pvSanoRdJ4q+jMCWyk9zdw/CyLB9j8RXEahodR6l2GyttDRyEVWZtbN+TpLiHJ3t34LbsQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.22.5.tgz", + "integrity": "sha512-yIiRO6yobeEIaI0RTbIr8iAK9FcBHLtZq0S89ZPjDLQXBA4xvghaKqI0etp/tF3htTM0sazJKKLz9oEiGRtu7w==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -355,33 +361,33 @@ } }, "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.21.5", - "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.21.5.tgz", - "integrity": "sha512-AhQoI3YjWi6u/y/ntv7k48mcrCXmus0t79J9qPNlk/lAsFlCiJ047RmbfMOawySTHtywXhbXgpx/8nXMYd+oFw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.5.tgz", + "integrity": "sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.5", - "@babel/helper-environment-visitor": "^7.21.5", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.5", - "@babel/types": "^7.21.5", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -390,13 +396,13 @@ } }, "node_modules/@babel/types": { - "version": "7.21.5", - "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.21.5.tgz", - "integrity": "sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", + "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.21.5", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", "to-fast-properties": "^2.0.0" }, "engines": { @@ -1980,6 +1986,15 @@ "@types/unist": "*" } }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/mdast": { "version": "3.0.11", "resolved": "https://registry.npmmirror.com/@types/mdast/-/mdast-3.0.11.tgz", @@ -2013,6 +2028,15 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-beautiful-dnd": { + "version": "13.1.4", + "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.4.tgz", + "integrity": "sha512-4bIBdzOr0aavN+88q3C7Pgz+xkb7tz3whORYrmSj77wfVEMfiWiooIwVWFR7KM2e+uGTe5BVrXqSfb0aHeflJA==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-dom": { "version": "18.2.4", "resolved": "https://registry.npmmirror.com/@types/react-dom/-/react-dom-18.2.4.tgz", @@ -2021,6 +2045,17 @@ "@types/react": "*" } }, + "node_modules/@types/react-redux": { + "version": "7.1.25", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.25.tgz", + "integrity": "sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "node_modules/@types/scheduler": { "version": "0.16.3", "resolved": "https://registry.npmmirror.com/@types/scheduler/-/scheduler-0.16.3.tgz", @@ -2038,14 +2073,14 @@ "dev": true }, "node_modules/@vitejs/plugin-react": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-4.0.0.tgz", - "integrity": "sha512-HX0XzMjL3hhOYm+0s95pb0Z7F8O81G7joUHgfDd/9J/ZZf5k4xX6QAMFkKsHFxaHlf6X7GD7+XuaZ66ULiJuhQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.1.tgz", + "integrity": "sha512-g25lL98essfeSj43HJ0o4DMp0325XK0ITkxpgChzJU/CyemgyChtlxfnRbjfwxDGCTRxTiXtQAsdebQXKMRSOA==", "dev": true, "dependencies": { - "@babel/core": "^7.21.4", - "@babel/plugin-transform-react-jsx-self": "^7.21.0", - "@babel/plugin-transform-react-jsx-source": "^7.19.6", + "@babel/core": "^7.22.5", + "@babel/plugin-transform-react-jsx-self": "^7.22.5", + "@babel/plugin-transform-react-jsx-source": "^7.22.5", "react-refresh": "^0.14.0" }, "engines": { @@ -2066,7 +2101,7 @@ }, "node_modules/ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "dependencies": { @@ -2206,7 +2241,7 @@ }, "node_modules/chalk": { "version": "2.4.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "dependencies": { @@ -2285,7 +2320,7 @@ }, "node_modules/color-convert": { "version": "1.9.3", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "dependencies": { @@ -2294,7 +2329,7 @@ }, "node_modules/color-name": { "version": "1.1.3", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, @@ -2320,10 +2355,18 @@ }, "node_modules/convert-source-map": { "version": "1.9.0", - "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-1.9.0.tgz", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, + "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==", + "dependencies": { + "tiny-invariant": "^1.0.6" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz", @@ -2462,7 +2505,7 @@ }, "node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "engines": { @@ -2576,7 +2619,7 @@ }, "node_modules/gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, "engines": { @@ -2628,7 +2671,7 @@ }, "node_modules/globals": { "version": "11.12.0", - "resolved": "https://registry.npmmirror.com/globals/-/globals-11.12.0.tgz", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, "engines": { @@ -2649,7 +2692,7 @@ }, "node_modules/has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "engines": { @@ -2754,6 +2797,19 @@ "node": ">=12.0.0" } }, + "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==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "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==" + }, "node_modules/html-parse-stringify": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", @@ -2918,7 +2974,7 @@ }, "node_modules/jsesc": { "version": "2.5.2", - "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-2.5.2.tgz", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, "bin": { @@ -2930,7 +2986,7 @@ }, "node_modules/json5": { "version": "2.2.3", - "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "bin": { @@ -2996,7 +3052,7 @@ }, "node_modules/lru-cache": { "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "dependencies": { @@ -3176,6 +3232,11 @@ "@types/mdast": "^3.0.0" } }, + "node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", @@ -3789,6 +3850,11 @@ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, + "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==" + }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmmirror.com/react/-/react-18.2.0.tgz", @@ -3800,6 +3866,24 @@ "node": ">=0.10.0" } }, + "node_modules/react-beautiful-dnd": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz", + "integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==", + "dependencies": { + "@babel/runtime": "^7.9.2", + "css-box-model": "^1.2.0", + "memoize-one": "^5.1.1", + "raf-schd": "^4.0.2", + "react-redux": "^7.2.0", + "redux": "^4.0.4", + "use-memo-one": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.5 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmmirror.com/react-dom/-/react-dom-18.2.0.tgz", @@ -3872,6 +3956,35 @@ "react": ">=16" } }, + "node_modules/react-redux": { + "version": "7.2.9", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", + "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", + "dependencies": { + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" + }, + "peerDependencies": { + "react": "^16.8.3 || ^17 || ^18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/react-redux/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, "node_modules/react-refresh": { "version": "0.14.0", "resolved": "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.14.0.tgz", @@ -3944,6 +4057,14 @@ "node": ">=8.10.0" } }, + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, "node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", @@ -4145,7 +4266,7 @@ }, "node_modules/semver": { "version": "6.3.0", - "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.0.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { @@ -4238,7 +4359,7 @@ }, "node_modules/supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "dependencies": { @@ -4350,9 +4471,14 @@ "node": ">=0.8" } }, + "node_modules/tiny-invariant": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", + "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" + }, "node_modules/to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, "engines": { @@ -4503,6 +4629,14 @@ "react-dom": ">=16.8.0 <19.0.0" } }, + "node_modules/use-memo-one": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", + "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/usehooks-ts": { "version": "2.9.1", "resolved": "https://registry.npmmirror.com/usehooks-ts/-/usehooks-ts-2.9.1.tgz", @@ -4580,9 +4714,9 @@ } }, "node_modules/vite": { - "version": "4.3.6", - "resolved": "https://registry.npmmirror.com/vite/-/vite-4.3.6.tgz", - "integrity": "sha512-cqIyLSbA6gornMS659AXTVKF7cvSHMdKmJJwQ9DXq3lwsT1uZSdktuBRlpHQ8VnOWx0QHtjDwxPpGtyo9Fh/Qg==", + "version": "4.3.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz", + "integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==", "dev": true, "dependencies": { "esbuild": "^0.17.5", @@ -4701,7 +4835,7 @@ }, "node_modules/yallist": { "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, diff --git a/frontend/package.json b/frontend/package.json index 17afc8f..464ea14 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -19,6 +19,7 @@ "mobx": "^6.9.0", "mobx-react-lite": "^3.4.3", "react": "^18.2.0", + "react-beautiful-dnd": "^13.1.1", "react-dom": "^18.2.0", "react-i18next": "^12.2.2", "react-markdown": "^8.0.7", @@ -34,6 +35,7 @@ }, "devDependencies": { "@types/react": "^18.2.6", + "@types/react-beautiful-dnd": "^13.1.4", "@types/react-dom": "^18.2.4", "@types/uuid": "^9.0.1", "@vitejs/plugin-react": "^4.0.0", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 5894033..829546c 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -28,10 +28,10 @@ import { FC, useEffect, useState } from 'react'; import { Route, Routes, useLocation, useNavigate } from 'react-router'; import { pages } from './pages'; import { useMediaQuery } from 'usehooks-ts'; -import { ToastContainer } from 'react-toastify'; import commonStore from './stores/commonStore'; import { observer } from 'mobx-react-lite'; import { useTranslation } from 'react-i18next'; +import { CustomToastContainer } from './components/CustomToastContainer'; const App: FC = observer(() => { const { t } = useTranslation(); @@ -87,21 +87,7 @@ const App: FC = observer(() => { - + ); }); diff --git a/frontend/src/_locales/zh-hans/main.json b/frontend/src/_locales/zh-hans/main.json index 3128354..bd59da8 100644 --- a/frontend/src/_locales/zh-hans/main.json +++ b/frontend/src/_locales/zh-hans/main.json @@ -163,5 +163,30 @@ "The model file is corrupted, please download again.": "模型文件损坏,请重新下载", "Found no NVIDIA driver, please install the latest driver.": "没有找到NVIDIA驱动,请安装最新驱动", "VRAM is not enough, please reduce stored layers or use a lower precision in Configs page.": "显存不足,请在配置页面减少载入显存层数,或使用更低的精度", - "Failed to enable custom CUDA kernel, ninja is required to load C++ extensions. You may be using the CPU version of PyTorch, please reinstall PyTorch with CUDA. Or if you are using a custom Python interpreter, you must compile the CUDA kernel by yourself or disable Custom CUDA kernel acceleration.": "自定义CUDA算子开启失败,需要安装Ninja来读取C++扩展。你可能正在使用CPU版本的PyTorch,请重新安装CUDA版本的PyTorch。如果你正在使用自定义Python解释器,你必须自己编译CUDA算子或禁用自定义CUDA算子加速" + "Failed to enable custom CUDA kernel, ninja is required to load C++ extensions. You may be using the CPU version of PyTorch, please reinstall PyTorch with CUDA. Or if you are using a custom Python interpreter, you must compile the CUDA kernel by yourself or disable Custom CUDA kernel acceleration.": "自定义CUDA算子开启失败,需要安装Ninja来读取C++扩展。你可能正在使用CPU版本的PyTorch,请重新安装CUDA版本的PyTorch。如果你正在使用自定义Python解释器,你必须自己编译CUDA算子或禁用自定义CUDA算子加速", + "Presets": "预设", + "Online": "在线", + "english": "英文", + "chinese": "中文", + "default": "默认", + "japanese": "日文", + "New Preset": "新建预设", + "Import": "导入", + "Name": "名称", + "Imported successfully": "导入成功", + "Failed to import. Please copy a preset to the clipboard.": "导入失败。请复制一个预设到剪贴板", + "Clipboard is empty.": "剪贴板没有内容", + "Successfully copied to clipboard.": "成功复制到剪贴板", + "Edit Messages": "编辑对话", + "Go Back": "返回", + "Description": "描述", + "Avatar Url": "头像图片地址", + "Welcome Message": "欢迎语", + "Display Preset Messages": "显示预设中的对话", + "Tag": "标签", + "Activate": "激活", + "New": "新建", + "user": "用户", + "assistant": "AI", + "system": "系统" } \ No newline at end of file diff --git a/frontend/src/components/CustomToastContainer.tsx b/frontend/src/components/CustomToastContainer.tsx new file mode 100644 index 0000000..eb8e6ca --- /dev/null +++ b/frontend/src/components/CustomToastContainer.tsx @@ -0,0 +1,17 @@ +import commonStore from '../stores/commonStore'; +import { ToastContainer } from 'react-toastify'; + +export const CustomToastContainer = () => + ; \ No newline at end of file diff --git a/frontend/src/components/ToolTipButton.tsx b/frontend/src/components/ToolTipButton.tsx index 441a834..d769144 100644 --- a/frontend/src/components/ToolTipButton.tsx +++ b/frontend/src/components/ToolTipButton.tsx @@ -1,4 +1,4 @@ -import React, { FC, MouseEventHandler, ReactElement } from 'react'; +import React, { CSSProperties, FC, MouseEventHandler, ReactElement } from 'react'; import { Button, Tooltip } from '@fluentui/react-components'; export const ToolTipButton: FC<{ @@ -6,6 +6,7 @@ export const ToolTipButton: FC<{ desc: string, icon?: ReactElement, className?: string, + style?: CSSProperties, size?: 'small' | 'medium' | 'large', shape?: 'rounded' | 'circular' | 'square'; appearance?: 'secondary' | 'primary' | 'outline' | 'subtle' | 'transparent'; @@ -17,6 +18,7 @@ export const ToolTipButton: FC<{ desc, icon, className, + style, size, shape, appearance, @@ -26,8 +28,8 @@ export const ToolTipButton: FC<{ }) => { return ( - + ); }; diff --git a/frontend/src/pages/Chat.tsx b/frontend/src/pages/Chat.tsx index ffd34d2..1f3181d 100644 --- a/frontend/src/pages/Chat.tsx +++ b/frontend/src/pages/Chat.tsx @@ -7,7 +7,6 @@ import { v4 as uuid } from 'uuid'; import classnames from 'classnames'; import { fetchEventSource } from '@microsoft/fetch-event-source'; import { KebabHorizontalIcon, PencilIcon, SyncIcon, TrashIcon } from '@primer/octicons-react'; -import { ConversationPair } from '../utils/get-conversation-pairs'; import logo from '../assets/images/logo.jpg'; import MarkdownRender from '../components/MarkdownRender'; import { ToolTipButton } from '../components/ToolTipButton'; @@ -19,6 +18,8 @@ import { WorkHeader } from '../components/WorkHeader'; import { DialogButton } from '../components/DialogButton'; import { OpenFileFolder, OpenSaveFileDialog } from '../../wailsjs/go/backend_golang/App'; import { toastWithButton } from '../utils'; +import { PresetsButton } from './PresetsManager/PresetsButton'; +import { useMediaQuery } from 'usehooks-ts'; export const userName = 'M E'; export const botName = 'A I'; @@ -49,6 +50,13 @@ export type Conversation = { [uuid: string]: MessageItem } +export type Role = 'assistant' | 'user' | 'system'; + +export type ConversationMessage = { + role: Role; + content: string; +} + let chatSseController: AbortController | null = null; const MoreUtilsButton: FC<{ uuid: string, setEditing: (editing: boolean) => void }> = observer(({ @@ -123,7 +131,7 @@ const ChatMessageItem: FC<{
{ const { t } = useTranslation(); const bodyRef = useRef(null); const inputRef = useRef(null); + const mq = useMediaQuery('(min-width: 640px)'); const port = commonStore.getCurrentModelConfig().apiParameters.apiPort; let lastMessageId: string; @@ -255,7 +264,7 @@ const ChatPanel: FC = observer(() => { let endIndex = endUuid ? (commonStore.conversationOrder.indexOf(endUuid) + (includeEndUuid ? 1 : 0)) : commonStore.conversationOrder.length; let targetRange = commonStore.conversationOrder.slice(startIndex, endIndex); - const messages: ConversationPair[] = []; + const messages: ConversationMessage[] = []; targetRange.forEach((uuid, index) => { if (uuid === welcomeUuid) return; @@ -357,10 +366,11 @@ const ChatPanel: FC = observer(() => { )}
-
+
+ } - size="large" shape="circular" appearance="subtle" title={t('Clear')} + size={mq ? 'large' : 'small'} shape="circular" appearance="subtle" title={t('Clear')} contentText={t('Are you sure you want to clear the conversation? It cannot be undone.')} onConfirm={() => { if (generating) @@ -370,6 +380,7 @@ const ChatPanel: FC = observer(() => { }} /> + } onClick={() => { + deleteItem(item.id); + }} /> +
+
+ )} + + ))} + {provided.placeholder} + + )} + + + + + ); +}); diff --git a/frontend/src/pages/PresetsManager/PresetsButton.tsx b/frontend/src/pages/PresetsManager/PresetsButton.tsx new file mode 100644 index 0000000..2fe1ec0 --- /dev/null +++ b/frontend/src/pages/PresetsManager/PresetsButton.tsx @@ -0,0 +1,432 @@ +// TODO refactor + +import React, { FC, PropsWithChildren, ReactElement, useState } from 'react'; +import { + Button, + Dialog, + DialogBody, + DialogContent, + DialogSurface, + DialogTrigger, + Input, + Switch, + Tab, + TabList, + Text +} from '@fluentui/react-components'; +import { + Accessibility28Regular, + Chat20Regular, + ClipboardEdit20Regular, + Delete20Regular, + Dismiss20Regular, + Edit20Regular, + Globe20Regular +} from '@fluentui/react-icons'; +import { ToolTipButton } from '../../components/ToolTipButton'; +import { useTranslation } from 'react-i18next'; +import { botName, Conversation, ConversationMessage, MessageType, userName } from '../Chat'; +import { SelectTabEventHandler } from '@fluentui/react-tabs'; +import { Labeled } from '../../components/Labeled'; +import commonStore from '../../stores/commonStore'; +import logo from '../../assets/images/logo.jpg'; +import { observer } from 'mobx-react-lite'; +import { MessagesEditor } from './MessagesEditor'; +import { ClipboardGetText, ClipboardSetText } from '../../../wailsjs/runtime'; +import { toast } from 'react-toastify'; +import { CustomToastContainer } from '../../components/CustomToastContainer'; +import { v4 as uuid } from 'uuid'; + +export type PresetType = 'chat' | 'completion' | 'chatInCompletion' + +export type Preset = { + name: string, + tag: string, + // if name and sourceUrl are same, it will be overridden when importing + sourceUrl: string, + desc: string, + avatarImg: string, + type: PresetType, + // chat + welcomeMessage: string, + messages: ConversationMessage[], + displayPresetMessages: boolean, + // completion + prompt: string, + stop: string, + injectStart: string, + injectEnd: string, +} + +export const defaultPreset: Preset = { + name: 'RWKV', + tag: 'default', + sourceUrl: '', + desc: '', + avatarImg: logo, + type: 'chat', + welcomeMessage: '', + displayPresetMessages: true, + messages: [], + prompt: '', + stop: '', + injectStart: '', + injectEnd: '' +}; + +const setActivePreset = (preset: Preset) => { + commonStore.setActivePreset(preset); + //TODO if (preset.displayPresetMessages) { + const conversation: Conversation = {}; + const conversationOrder: string[] = []; + for (const message of preset.messages) { + const newUuid = uuid(); + conversationOrder.push(newUuid); + conversation[newUuid] = { + sender: message.role === 'user' ? userName : botName, + type: MessageType.Normal, + color: message.role === 'user' ? 'brand' : 'colorful', + time: new Date().toISOString(), + content: message.content, + side: message.role === 'user' ? 'right' : 'left', + done: true + }; + } + commonStore.setConversation(conversation); + commonStore.setConversationOrder(conversationOrder); + //} +}; + +export const PresetCardFrame: FC void }> = (props) => { + return ; +}; + +export const PresetCard: FC<{ + avatarImg: string, + name: string, + desc: string, + tag: string, + editable: boolean, + presetIndex: number, + onClick?: () => void +}> = observer(({ + avatarImg, name, desc, tag, editable, presetIndex, onClick +}) => { + const { t } = useTranslation(); + + return + + {name} + {desc} +
+
+
{t(tag)}
+ {editable ? + } + onClick={() => { + commonStore.setEditingPreset({ ...commonStore.presets[presetIndex] }); + }} /> + } /> + :
+ } +
+ ; +}); + +export const ChatPresetEditor: FC<{ + triggerButton: ReactElement, + presetIndex: number +}> = observer(({ triggerButton, presetIndex }) => { + const { t } = useTranslation(); + const [editingMessages, setEditingMessages] = useState(false); + + if (!commonStore.editingPreset) + commonStore.setEditingPreset({ ...defaultPreset }); + const editingPreset = commonStore.editingPreset!; + + const setEditingPreset = (newParams: Partial) => { + commonStore.setEditingPreset({ + ...editingPreset, + ...newParams + }); + }; + + const importPreset = () => { + ClipboardGetText().then((text) => { + try { + const preset = JSON.parse(text); + setEditingPreset(preset); + toast(t('Imported successfully'), { + type: 'success', + autoClose: 1000 + }); + } catch (e) { + toast(t('Failed to import. Please copy a preset to the clipboard.'), { + type: 'error', + autoClose: 2500 + }); + } + }).catch(() => { + toast(t('Clipboard is empty.'), { + type: 'info', + autoClose: 1000 + }); + }); + }; + + const copyPreset = () => { + ClipboardSetText(JSON.stringify(editingPreset)).then((success) => { + if (success) + toast(t('Successfully copied to clipboard.'), { + type: 'success', + autoClose: 1000 + }); + }); + }; + + const savePreset = () => { + if (presetIndex === -1) { + commonStore.setPresets([...commonStore.presets, { ...editingPreset }]); + setEditingPreset(defaultPreset); + } else { + commonStore.presets[presetIndex] = editingPreset; + commonStore.setPresets(commonStore.presets); + } + }; + + const activatePreset = () => { + savePreset(); + setActivePreset(editingPreset); + }; + + const deletePreset = () => { + commonStore.presets.splice(presetIndex, 1); + commonStore.setPresets(commonStore.presets); + }; + + return + + {triggerButton} + + + + + +
{ + presetIndex === -1 + ?
+ : +
+ + + { + setEditingPreset({ + name: data.value + }); + }} /> + : } onClick={() => { + setEditingMessages(!editingMessages); + }} /> +
+ } /> + { + editingMessages ? + : +
+ { + setEditingPreset({ + desc: data.value + }); + }} /> + } /> + { + setEditingPreset({ + avatarImg: data.value + }); + }} /> + } /> + { + setEditingPreset({ + welcomeMessage: data.value + }); + }} /> + } /> + { + setEditingPreset({ + displayPresetMessages: data.checked + }); + }} /> + } /> + { + setEditingPreset({ + tag: data.value + }); + }} /> + } /> +
+ } +
+
+ + +
+
+ + + + + + +
+ + + +
; +}); + +export const ChatPresets: FC = observer(() => { + const { t } = useTranslation(); + + return
+ +
+ {t('New Preset')} +
+ } + /> + {/*TODO */} + {/*
*/} + {/* {t('Import')}*/} + {/*
*/} + {/*
*/} + { + setActivePreset(defaultPreset); + }} avatarImg={defaultPreset.avatarImg} name={defaultPreset.name} desc={defaultPreset.desc} tag={defaultPreset.tag} + /> + {commonStore.presets.map((preset, index) => { + return { + setActivePreset(preset); + }} + key={index} avatarImg={preset.avatarImg} name={preset.name} desc={preset.desc} tag={preset.tag} + />; + })} +
; +}); + +type PresetsNavigationItem = { + icon: ReactElement; + element: ReactElement; +}; + +const pages: { [label: string]: PresetsNavigationItem } = { + Chat: { + icon: , + element: + }, + Completion: { + icon: , + element:
In Development
+ }, + Online: { + icon: , + element:
In Development
+ } +}; + +export const PresetsManager: FC<{ initTab: string }> = ({ initTab }) => { + const { t } = useTranslation(); + const [tab, setTab] = useState(initTab); + + const selectTab: SelectTabEventHandler = (e, data) => + typeof data.value === 'string' ? setTab(data.value) : null; + + return
+
+ + {Object.entries(pages).map(([label, { icon }]) => ( + + {t(label)} + + ))} + + +
+
+ {pages[tab].element} +
+
; +}; + +export const PresetsButton: FC<{ + tab: string, + size?: 'small' | 'medium' | 'large', + shape?: 'rounded' | 'circular' | 'square'; + appearance?: 'secondary' | 'primary' | 'outline' | 'subtle' | 'transparent'; +}> = ({ tab, size, shape, appearance }) => { + const { t } = useTranslation(); + + return + + } /> + + + + + + + + + + ; +}; \ No newline at end of file diff --git a/frontend/src/startup.ts b/frontend/src/startup.ts index dadca46..cee3e26 100644 --- a/frontend/src/startup.ts +++ b/frontend/src/startup.ts @@ -5,6 +5,7 @@ import { getStatus } from './apis'; import { EventsOn } from '../wailsjs/runtime'; import manifest from '../../manifest.json'; import { defaultModelConfigs, defaultModelConfigsMac } from './pages/defaultModelConfigs'; +import { Preset } from './pages/PresetsManager/PresetsButton'; export async function startup() { downloadProgramFiles(); @@ -13,6 +14,8 @@ export async function startup() { commonStore.setDownloadList(data); }); + initPresets(); + await GetPlatform().then(p => commonStore.setPlatform(p as Platform)); await initConfig(); @@ -65,4 +68,11 @@ async function initCache(initUnfinishedModels: boolean) { }).catch(() => { }); await refreshModels(false, initUnfinishedModels); -} \ No newline at end of file +} + +async function initPresets() { + await ReadJson('presets.json').then((presets: Preset[]) => { + commonStore.setPresets(presets, false); + }).catch(() => { + }); +} diff --git a/frontend/src/stores/commonStore.ts b/frontend/src/stores/commonStore.ts index 398f7ea..5fb996a 100644 --- a/frontend/src/stores/commonStore.ts +++ b/frontend/src/stores/commonStore.ts @@ -1,5 +1,5 @@ import { makeAutoObservable } from 'mobx'; -import { getUserLanguage, isSystemLightMode, saveConfigs } from '../utils'; +import { getUserLanguage, isSystemLightMode, saveConfigs, savePresets } from '../utils'; import { WindowSetDarkTheme, WindowSetLightTheme } from '../../wailsjs/runtime'; import manifest from '../../../manifest.json'; import { ModelConfig } from '../pages/Configs'; @@ -13,6 +13,7 @@ import i18n from 'i18next'; import { CompletionPreset } from '../pages/Completion'; import { defaultModelConfigs, defaultModelConfigsMac } from '../pages/defaultModelConfigs'; import commonStore from './commonStore'; +import { Preset } from '../pages/PresetsManager/PresetsButton'; export enum ModelStatus { Offline, @@ -38,12 +39,16 @@ class CommonStore { }; depComplete: boolean = false; platform: Platform = 'windows'; + // presets manager + editingPreset: Preset | null = null; + presets: Preset[] = []; // home introduction: IntroductionContent = manifest.introduction; // chat currentInput: string = ''; conversation: Conversation = {}; conversationOrder: string[] = []; + activePreset: Preset | null = null; // completion completionPreset: CompletionPreset | null = null; completionGenerating: boolean = false; @@ -202,6 +207,20 @@ class CommonStore { setLastUnfinishedModelDownloads(value: DownloadStatus[]) { this.lastUnfinishedModelDownloads = value; } + + setEditingPreset(value: Preset) { + this.editingPreset = value; + } + + setPresets(value: Preset[], savePreset: boolean = true) { + this.presets = value; + if (savePreset) + savePresets(); + } + + setActivePreset(value: Preset) { + this.activePreset = value; + } } export default new CommonStore(); \ No newline at end of file diff --git a/frontend/src/utils/get-conversation-pairs.ts b/frontend/src/utils/get-conversation-pairs.ts deleted file mode 100644 index 6ba2209..0000000 --- a/frontend/src/utils/get-conversation-pairs.ts +++ /dev/null @@ -1,27 +0,0 @@ -export type Record = { - question: string; - answer: string; -} - -export type ConversationPair = { - role: string; - content: string; -} - -export function getConversationPairs(records: Record[], isCompletion: boolean): string | ConversationPair[] { - let pairs; - if (isCompletion) { - pairs = ''; - for (const record of records) { - pairs += 'Human: ' + record.question + '\nAI: ' + record.answer + '\n'; - } - } else { - pairs = []; - for (const record of records) { - pairs.push({ role: 'user', content: record.question }); - pairs.push({ role: 'assistant', content: record.answer }); - } - } - - return pairs; -} diff --git a/frontend/src/utils/index.tsx b/frontend/src/utils/index.tsx index 2ac09af..6f45bdd 100644 --- a/frontend/src/utils/index.tsx +++ b/frontend/src/utils/index.tsx @@ -206,6 +206,10 @@ export const saveCache = async () => { return SaveJson('cache.json', data); }; +export const savePresets = async () => { + return SaveJson('presets.json', commonStore.presets); +}; + export function getUserLanguage(): Language { // const l = navigator.language.toLowerCase(); // if (['zh-hk', 'zh-mo', 'zh-tw', 'zh-cht', 'zh-hant'].includes(l)) return 'zhHant'