Spaces:
Running
Running
update
Browse files- package-lock.json +141 -1
- package.json +1 -0
- src/App.css +4 -0
- src/App.tsx +12 -7
- src/api/qePrompts/hooks.ts +49 -0
- src/api/qePrompts/qePromptApi.ts +79 -0
- src/api/qePrompts/types.ts +9 -0
- src/components/common/navbar/Navbar.tsx +9 -1
- src/components/generics/button/Button.scss +1 -0
- src/components/generics/button/Button.tsx +1 -1
- src/components/pages/documentsPage/Documents.tsx +2 -2
- src/components/pages/llmConfigs/LlmConfigModal.scss +1 -1
- src/components/pages/llmConfigs/LlmConfigModal.tsx +10 -10
- src/components/pages/llmPrompts/LlmPromptModal.scss +2 -1
- src/components/pages/llmPrompts/LlmPromptModal.tsx +4 -4
- src/components/pages/qePrompts/QePromptList.scss +209 -0
- src/components/pages/qePrompts/QePromptList.tsx +124 -0
- src/components/pages/qePrompts/QePromptModal.scss +137 -0
- src/components/pages/qePrompts/QePromptModal.tsx +159 -0
- src/components/views/documents/docsList/DocsList.tsx +2 -2
package-lock.json
CHANGED
|
@@ -9,6 +9,7 @@
|
|
| 9 |
"version": "0.0.0",
|
| 10 |
"dependencies": {
|
| 11 |
"@fontsource/fira-mono": "^5.0.14",
|
|
|
|
| 12 |
"@reduxjs/toolkit": "^2.3.0",
|
| 13 |
"@tanstack/react-query": "^5.54.1",
|
| 14 |
"@tanstack/react-query-devtools": "^5.54.1",
|
|
@@ -1175,6 +1176,23 @@
|
|
| 1175 |
"@jridgewell/sourcemap-codec": "^1.4.14"
|
| 1176 |
}
|
| 1177 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1178 |
"node_modules/@nodelib/fs.scandir": {
|
| 1179 |
"version": "2.1.5",
|
| 1180 |
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
|
@@ -1610,6 +1628,11 @@
|
|
| 1610 |
"@babel/types": "^7.20.7"
|
| 1611 |
}
|
| 1612 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1613 |
"node_modules/@types/estree": {
|
| 1614 |
"version": "1.0.6",
|
| 1615 |
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
|
@@ -1624,6 +1647,11 @@
|
|
| 1624 |
"dev": true,
|
| 1625 |
"license": "MIT"
|
| 1626 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1627 |
"node_modules/@types/node": {
|
| 1628 |
"version": "22.13.0",
|
| 1629 |
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.0.tgz",
|
|
@@ -2051,6 +2079,11 @@
|
|
| 2051 |
"dev": true,
|
| 2052 |
"license": "MIT"
|
| 2053 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2054 |
"node_modules/base64-js": {
|
| 2055 |
"version": "1.5.1",
|
| 2056 |
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
|
@@ -2273,6 +2306,15 @@
|
|
| 2273 |
"node": ">=0.8"
|
| 2274 |
}
|
| 2275 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2276 |
"node_modules/color-convert": {
|
| 2277 |
"version": "2.0.1",
|
| 2278 |
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
|
@@ -2290,9 +2332,30 @@
|
|
| 2290 |
"version": "1.1.4",
|
| 2291 |
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
| 2292 |
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
| 2293 |
-
"dev": true,
|
| 2294 |
"license": "MIT"
|
| 2295 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2296 |
"node_modules/colorjs.io": {
|
| 2297 |
"version": "0.5.2",
|
| 2298 |
"resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz",
|
|
@@ -3408,6 +3471,11 @@
|
|
| 3408 |
"url": "https://github.com/sponsors/sindresorhus"
|
| 3409 |
}
|
| 3410 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3411 |
"node_modules/lodash.merge": {
|
| 3412 |
"version": "4.6.2",
|
| 3413 |
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
|
@@ -3988,6 +4056,20 @@
|
|
| 3988 |
"node": ">=0.10.0"
|
| 3989 |
}
|
| 3990 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3991 |
"node_modules/react-contenteditable": {
|
| 3992 |
"version": "3.3.7",
|
| 3993 |
"resolved": "https://registry.npmjs.org/react-contenteditable/-/react-contenteditable-3.3.7.tgz",
|
|
@@ -4191,6 +4273,22 @@
|
|
| 4191 |
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
| 4192 |
}
|
| 4193 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4194 |
"node_modules/react-transition-group": {
|
| 4195 |
"version": "4.4.5",
|
| 4196 |
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
|
@@ -4887,6 +4985,19 @@
|
|
| 4887 |
"simple-concat": "^1.0.0"
|
| 4888 |
}
|
| 4889 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4890 |
"node_modules/source-map": {
|
| 4891 |
"version": "0.5.7",
|
| 4892 |
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
|
@@ -5180,6 +5291,19 @@
|
|
| 5180 |
"punycode": "^2.1.0"
|
| 5181 |
}
|
| 5182 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5183 |
"node_modules/use-isomorphic-layout-effect": {
|
| 5184 |
"version": "1.2.0",
|
| 5185 |
"resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.0.tgz",
|
|
@@ -5194,6 +5318,22 @@
|
|
| 5194 |
}
|
| 5195 |
}
|
| 5196 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5197 |
"node_modules/use-sync-external-store": {
|
| 5198 |
"version": "1.4.0",
|
| 5199 |
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz",
|
|
|
|
| 9 |
"version": "0.0.0",
|
| 10 |
"dependencies": {
|
| 11 |
"@fontsource/fira-mono": "^5.0.14",
|
| 12 |
+
"@microlink/react-json-view": "^1.26.1",
|
| 13 |
"@reduxjs/toolkit": "^2.3.0",
|
| 14 |
"@tanstack/react-query": "^5.54.1",
|
| 15 |
"@tanstack/react-query-devtools": "^5.54.1",
|
|
|
|
| 1176 |
"@jridgewell/sourcemap-codec": "^1.4.14"
|
| 1177 |
}
|
| 1178 |
},
|
| 1179 |
+
"node_modules/@microlink/react-json-view": {
|
| 1180 |
+
"version": "1.26.1",
|
| 1181 |
+
"resolved": "https://registry.npmjs.org/@microlink/react-json-view/-/react-json-view-1.26.1.tgz",
|
| 1182 |
+
"integrity": "sha512-2H5QCYdZlJi+oN4YBiUYPPFTNh/KLCN9i9yz8NwmSkRqXSRXYtEVIRffc9L34jdopKGK/tK21SeuzXVJHQLkfQ==",
|
| 1183 |
+
"dependencies": {
|
| 1184 |
+
"react-base16-styling": "~0.9.0",
|
| 1185 |
+
"react-lifecycles-compat": "~3.0.4",
|
| 1186 |
+
"react-textarea-autosize": "~8.5.7"
|
| 1187 |
+
},
|
| 1188 |
+
"engines": {
|
| 1189 |
+
"node": ">=17"
|
| 1190 |
+
},
|
| 1191 |
+
"peerDependencies": {
|
| 1192 |
+
"react": ">= 15",
|
| 1193 |
+
"react-dom": ">= 15"
|
| 1194 |
+
}
|
| 1195 |
+
},
|
| 1196 |
"node_modules/@nodelib/fs.scandir": {
|
| 1197 |
"version": "2.1.5",
|
| 1198 |
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
|
|
|
| 1628 |
"@babel/types": "^7.20.7"
|
| 1629 |
}
|
| 1630 |
},
|
| 1631 |
+
"node_modules/@types/base16": {
|
| 1632 |
+
"version": "1.0.5",
|
| 1633 |
+
"resolved": "https://registry.npmjs.org/@types/base16/-/base16-1.0.5.tgz",
|
| 1634 |
+
"integrity": "sha512-OzOWrTluG9cwqidEzC/Q6FAmIPcnZfm8BFRlIx0+UIUqnuAmi5OS88O0RpT3Yz6qdmqObvUhasrbNsCofE4W9A=="
|
| 1635 |
+
},
|
| 1636 |
"node_modules/@types/estree": {
|
| 1637 |
"version": "1.0.6",
|
| 1638 |
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
|
|
|
| 1647 |
"dev": true,
|
| 1648 |
"license": "MIT"
|
| 1649 |
},
|
| 1650 |
+
"node_modules/@types/lodash": {
|
| 1651 |
+
"version": "4.17.16",
|
| 1652 |
+
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz",
|
| 1653 |
+
"integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g=="
|
| 1654 |
+
},
|
| 1655 |
"node_modules/@types/node": {
|
| 1656 |
"version": "22.13.0",
|
| 1657 |
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.0.tgz",
|
|
|
|
| 2079 |
"dev": true,
|
| 2080 |
"license": "MIT"
|
| 2081 |
},
|
| 2082 |
+
"node_modules/base16": {
|
| 2083 |
+
"version": "1.0.0",
|
| 2084 |
+
"resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz",
|
| 2085 |
+
"integrity": "sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ=="
|
| 2086 |
+
},
|
| 2087 |
"node_modules/base64-js": {
|
| 2088 |
"version": "1.5.1",
|
| 2089 |
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
|
|
|
| 2306 |
"node": ">=0.8"
|
| 2307 |
}
|
| 2308 |
},
|
| 2309 |
+
"node_modules/color": {
|
| 2310 |
+
"version": "3.2.1",
|
| 2311 |
+
"resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
|
| 2312 |
+
"integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
|
| 2313 |
+
"dependencies": {
|
| 2314 |
+
"color-convert": "^1.9.3",
|
| 2315 |
+
"color-string": "^1.6.0"
|
| 2316 |
+
}
|
| 2317 |
+
},
|
| 2318 |
"node_modules/color-convert": {
|
| 2319 |
"version": "2.0.1",
|
| 2320 |
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
|
|
|
| 2332 |
"version": "1.1.4",
|
| 2333 |
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
| 2334 |
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
|
|
|
| 2335 |
"license": "MIT"
|
| 2336 |
},
|
| 2337 |
+
"node_modules/color-string": {
|
| 2338 |
+
"version": "1.9.1",
|
| 2339 |
+
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
|
| 2340 |
+
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
|
| 2341 |
+
"dependencies": {
|
| 2342 |
+
"color-name": "^1.0.0",
|
| 2343 |
+
"simple-swizzle": "^0.2.2"
|
| 2344 |
+
}
|
| 2345 |
+
},
|
| 2346 |
+
"node_modules/color/node_modules/color-convert": {
|
| 2347 |
+
"version": "1.9.3",
|
| 2348 |
+
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
| 2349 |
+
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
| 2350 |
+
"dependencies": {
|
| 2351 |
+
"color-name": "1.1.3"
|
| 2352 |
+
}
|
| 2353 |
+
},
|
| 2354 |
+
"node_modules/color/node_modules/color-name": {
|
| 2355 |
+
"version": "1.1.3",
|
| 2356 |
+
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
| 2357 |
+
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
|
| 2358 |
+
},
|
| 2359 |
"node_modules/colorjs.io": {
|
| 2360 |
"version": "0.5.2",
|
| 2361 |
"resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz",
|
|
|
|
| 3471 |
"url": "https://github.com/sponsors/sindresorhus"
|
| 3472 |
}
|
| 3473 |
},
|
| 3474 |
+
"node_modules/lodash.curry": {
|
| 3475 |
+
"version": "4.1.1",
|
| 3476 |
+
"resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz",
|
| 3477 |
+
"integrity": "sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA=="
|
| 3478 |
+
},
|
| 3479 |
"node_modules/lodash.merge": {
|
| 3480 |
"version": "4.6.2",
|
| 3481 |
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
|
|
|
| 4056 |
"node": ">=0.10.0"
|
| 4057 |
}
|
| 4058 |
},
|
| 4059 |
+
"node_modules/react-base16-styling": {
|
| 4060 |
+
"version": "0.9.1",
|
| 4061 |
+
"resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.9.1.tgz",
|
| 4062 |
+
"integrity": "sha512-1s0CY1zRBOQ5M3T61wetEpvQmsYSNtWEcdYzyZNxKa8t7oDvaOn9d21xrGezGAHFWLM7SHcktPuPTrvoqxSfKw==",
|
| 4063 |
+
"dependencies": {
|
| 4064 |
+
"@babel/runtime": "^7.16.7",
|
| 4065 |
+
"@types/base16": "^1.0.2",
|
| 4066 |
+
"@types/lodash": "^4.14.178",
|
| 4067 |
+
"base16": "^1.0.0",
|
| 4068 |
+
"color": "^3.2.1",
|
| 4069 |
+
"csstype": "^3.0.10",
|
| 4070 |
+
"lodash.curry": "^4.1.1"
|
| 4071 |
+
}
|
| 4072 |
+
},
|
| 4073 |
"node_modules/react-contenteditable": {
|
| 4074 |
"version": "3.3.7",
|
| 4075 |
"resolved": "https://registry.npmjs.org/react-contenteditable/-/react-contenteditable-3.3.7.tgz",
|
|
|
|
| 4273 |
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
| 4274 |
}
|
| 4275 |
},
|
| 4276 |
+
"node_modules/react-textarea-autosize": {
|
| 4277 |
+
"version": "8.5.9",
|
| 4278 |
+
"resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz",
|
| 4279 |
+
"integrity": "sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==",
|
| 4280 |
+
"dependencies": {
|
| 4281 |
+
"@babel/runtime": "^7.20.13",
|
| 4282 |
+
"use-composed-ref": "^1.3.0",
|
| 4283 |
+
"use-latest": "^1.2.1"
|
| 4284 |
+
},
|
| 4285 |
+
"engines": {
|
| 4286 |
+
"node": ">=10"
|
| 4287 |
+
},
|
| 4288 |
+
"peerDependencies": {
|
| 4289 |
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
| 4290 |
+
}
|
| 4291 |
+
},
|
| 4292 |
"node_modules/react-transition-group": {
|
| 4293 |
"version": "4.4.5",
|
| 4294 |
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
|
|
|
| 4985 |
"simple-concat": "^1.0.0"
|
| 4986 |
}
|
| 4987 |
},
|
| 4988 |
+
"node_modules/simple-swizzle": {
|
| 4989 |
+
"version": "0.2.2",
|
| 4990 |
+
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
| 4991 |
+
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
|
| 4992 |
+
"dependencies": {
|
| 4993 |
+
"is-arrayish": "^0.3.1"
|
| 4994 |
+
}
|
| 4995 |
+
},
|
| 4996 |
+
"node_modules/simple-swizzle/node_modules/is-arrayish": {
|
| 4997 |
+
"version": "0.3.2",
|
| 4998 |
+
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
|
| 4999 |
+
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
|
| 5000 |
+
},
|
| 5001 |
"node_modules/source-map": {
|
| 5002 |
"version": "0.5.7",
|
| 5003 |
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
|
|
|
| 5291 |
"punycode": "^2.1.0"
|
| 5292 |
}
|
| 5293 |
},
|
| 5294 |
+
"node_modules/use-composed-ref": {
|
| 5295 |
+
"version": "1.4.0",
|
| 5296 |
+
"resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz",
|
| 5297 |
+
"integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==",
|
| 5298 |
+
"peerDependencies": {
|
| 5299 |
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
| 5300 |
+
},
|
| 5301 |
+
"peerDependenciesMeta": {
|
| 5302 |
+
"@types/react": {
|
| 5303 |
+
"optional": true
|
| 5304 |
+
}
|
| 5305 |
+
}
|
| 5306 |
+
},
|
| 5307 |
"node_modules/use-isomorphic-layout-effect": {
|
| 5308 |
"version": "1.2.0",
|
| 5309 |
"resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.0.tgz",
|
|
|
|
| 5318 |
}
|
| 5319 |
}
|
| 5320 |
},
|
| 5321 |
+
"node_modules/use-latest": {
|
| 5322 |
+
"version": "1.3.0",
|
| 5323 |
+
"resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz",
|
| 5324 |
+
"integrity": "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==",
|
| 5325 |
+
"dependencies": {
|
| 5326 |
+
"use-isomorphic-layout-effect": "^1.1.1"
|
| 5327 |
+
},
|
| 5328 |
+
"peerDependencies": {
|
| 5329 |
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
| 5330 |
+
},
|
| 5331 |
+
"peerDependenciesMeta": {
|
| 5332 |
+
"@types/react": {
|
| 5333 |
+
"optional": true
|
| 5334 |
+
}
|
| 5335 |
+
}
|
| 5336 |
+
},
|
| 5337 |
"node_modules/use-sync-external-store": {
|
| 5338 |
"version": "1.4.0",
|
| 5339 |
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz",
|
package.json
CHANGED
|
@@ -11,6 +11,7 @@
|
|
| 11 |
},
|
| 12 |
"dependencies": {
|
| 13 |
"@fontsource/fira-mono": "^5.0.14",
|
|
|
|
| 14 |
"@reduxjs/toolkit": "^2.3.0",
|
| 15 |
"@tanstack/react-query": "^5.54.1",
|
| 16 |
"@tanstack/react-query-devtools": "^5.54.1",
|
|
|
|
| 11 |
},
|
| 12 |
"dependencies": {
|
| 13 |
"@fontsource/fira-mono": "^5.0.14",
|
| 14 |
+
"@microlink/react-json-view": "^1.26.1",
|
| 15 |
"@reduxjs/toolkit": "^2.3.0",
|
| 16 |
"@tanstack/react-query": "^5.54.1",
|
| 17 |
"@tanstack/react-query-devtools": "^5.54.1",
|
src/App.css
CHANGED
|
@@ -11,3 +11,7 @@
|
|
| 11 |
padding-left: 10px;
|
| 12 |
font-weight: 600;
|
| 13 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
padding-left: 10px;
|
| 12 |
font-weight: 600;
|
| 13 |
}
|
| 14 |
+
|
| 15 |
+
.app-content {
|
| 16 |
+
margin-top: 40px;
|
| 17 |
+
}
|
src/App.tsx
CHANGED
|
@@ -1,14 +1,15 @@
|
|
| 1 |
-
import "./App.css";
|
| 2 |
-
import { Routes, Route, BrowserRouter as Router, Navigate } from "react-router-dom";
|
| 3 |
import Navbar from '@/components/common/navbar/Navbar';
|
| 4 |
-
import
|
| 5 |
-
import Logs from "@/components/pages/logsPage/Logs";
|
| 6 |
-
import Vectorization from "@/components/pages/vectorizationPage/Vectorization";
|
| 7 |
-
import { pdfjs } from "react-pdf";
|
| 8 |
import LLMConfigList from "@/components/pages/llmConfigs/LlmConfigList";
|
| 9 |
import LlmPromptList from "@/components/pages/llmPrompts/LlmPromptList";
|
| 10 |
-
import
|
|
|
|
| 11 |
import { AuthProvider, useAuth } from "@/context/AuthContext";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
|
| 13 |
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
|
| 14 |
"pdfjs-dist/build/pdf.worker.min.mjs",
|
|
@@ -45,6 +46,10 @@ const App: React.FC = () => {
|
|
| 45 |
<PrivateRoute>
|
| 46 |
<LlmPromptList />
|
| 47 |
</PrivateRoute>} />
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
</Routes>
|
| 49 |
</div>
|
| 50 |
</Router>
|
|
|
|
|
|
|
|
|
|
| 1 |
import Navbar from '@/components/common/navbar/Navbar';
|
| 2 |
+
import LoginPage from "@/components/pages/auth/Login";
|
|
|
|
|
|
|
|
|
|
| 3 |
import LLMConfigList from "@/components/pages/llmConfigs/LlmConfigList";
|
| 4 |
import LlmPromptList from "@/components/pages/llmPrompts/LlmPromptList";
|
| 5 |
+
import Logs from "@/components/pages/logs/Logs";
|
| 6 |
+
import Vectorization from "@/components/pages/vectorizationPage/Vectorization";
|
| 7 |
import { AuthProvider, useAuth } from "@/context/AuthContext";
|
| 8 |
+
import { pdfjs } from "react-pdf";
|
| 9 |
+
import { Navigate, Route, BrowserRouter as Router, Routes } from "react-router-dom";
|
| 10 |
+
import "./App.css";
|
| 11 |
+
import QePromptList from "./components/pages/qePrompts/QePromptList";
|
| 12 |
+
|
| 13 |
|
| 14 |
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
|
| 15 |
"pdfjs-dist/build/pdf.worker.min.mjs",
|
|
|
|
| 46 |
<PrivateRoute>
|
| 47 |
<LlmPromptList />
|
| 48 |
</PrivateRoute>} />
|
| 49 |
+
<Route path="/qeprompt" element={
|
| 50 |
+
<PrivateRoute>
|
| 51 |
+
<QePromptList />
|
| 52 |
+
</PrivateRoute>} />
|
| 53 |
</Routes>
|
| 54 |
</div>
|
| 55 |
</Router>
|
src/api/qePrompts/hooks.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
| 2 |
+
import { createQePrompt, deleteQePrompt, fetchQePrompts, setDefaultQePrompt, updateQePrompt } from './qePromptApi';
|
| 3 |
+
|
| 4 |
+
export const useQePrompts = () => {
|
| 5 |
+
const queryClient = useQueryClient();
|
| 6 |
+
|
| 7 |
+
const { data: prompts = [], isLoading, error } = useQuery({
|
| 8 |
+
queryKey: ['qePrompts'],
|
| 9 |
+
queryFn: fetchQePrompts,
|
| 10 |
+
});
|
| 11 |
+
|
| 12 |
+
const createMutation = useMutation({
|
| 13 |
+
mutationFn: createQePrompt,
|
| 14 |
+
onSuccess: () => {
|
| 15 |
+
queryClient.invalidateQueries({ queryKey: ['qePrompts'] });
|
| 16 |
+
},
|
| 17 |
+
});
|
| 18 |
+
|
| 19 |
+
const updateMutation = useMutation({
|
| 20 |
+
mutationFn: updateQePrompt,
|
| 21 |
+
onSuccess: () => {
|
| 22 |
+
queryClient.invalidateQueries({ queryKey: ['qePrompts'] });
|
| 23 |
+
},
|
| 24 |
+
});
|
| 25 |
+
|
| 26 |
+
const setDefaultMutation = useMutation({
|
| 27 |
+
mutationFn: setDefaultQePrompt,
|
| 28 |
+
onSuccess: () => {
|
| 29 |
+
queryClient.invalidateQueries({ queryKey: ['qePrompts'] });
|
| 30 |
+
},
|
| 31 |
+
});
|
| 32 |
+
|
| 33 |
+
const deleteMutation = useMutation({
|
| 34 |
+
mutationFn: deleteQePrompt,
|
| 35 |
+
onSuccess: () => {
|
| 36 |
+
queryClient.invalidateQueries({ queryKey: ['qePrompts'] });
|
| 37 |
+
},
|
| 38 |
+
});
|
| 39 |
+
|
| 40 |
+
return {
|
| 41 |
+
prompts,
|
| 42 |
+
isLoading,
|
| 43 |
+
error: error ? (error instanceof Error ? error.message : 'Failed to fetch prompturations') : null,
|
| 44 |
+
createPrompt: createMutation.mutateAsync,
|
| 45 |
+
updatePrompt: updateMutation.mutateAsync,
|
| 46 |
+
setAsDefaultPrompt: setDefaultMutation.mutateAsync,
|
| 47 |
+
deletePrompt: deleteMutation.mutateAsync,
|
| 48 |
+
};
|
| 49 |
+
};
|
src/api/qePrompts/qePromptApi.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { query } from '@/shared/api/query';
|
| 2 |
+
import { QePrompt } from './types';
|
| 3 |
+
|
| 4 |
+
export const fetchQePrompts = async (): Promise<QePrompt[]> => {
|
| 5 |
+
const response = await query<QePrompt[]>({
|
| 6 |
+
url: '/qe_prompt/',
|
| 7 |
+
method: 'get',
|
| 8 |
+
});
|
| 9 |
+
if ('error' in response) {
|
| 10 |
+
throw new Error(`Ошибка получения промптов: ${response.error.status}`);
|
| 11 |
+
}
|
| 12 |
+
return response.data;
|
| 13 |
+
};
|
| 14 |
+
|
| 15 |
+
export const fetchQePromptById = async (id: number): Promise<QePrompt> => {
|
| 16 |
+
const response = await query<QePrompt>({
|
| 17 |
+
url: `/qe_prompt/${id}`,
|
| 18 |
+
method: 'get',
|
| 19 |
+
});
|
| 20 |
+
if ('error' in response) {
|
| 21 |
+
throw new Error(`Ошибка получения промпта: ${response.error.status}`);
|
| 22 |
+
}
|
| 23 |
+
return response.data;
|
| 24 |
+
};
|
| 25 |
+
|
| 26 |
+
export const createQePrompt = async (config: Omit<QePrompt, 'id' | 'created_at'>): Promise<QePrompt> => {
|
| 27 |
+
const response = await query<QePrompt>({
|
| 28 |
+
url: '/qe_prompt/',
|
| 29 |
+
method: 'post',
|
| 30 |
+
data: config,
|
| 31 |
+
});
|
| 32 |
+
if ('error' in response) {
|
| 33 |
+
throw new Error(`Ошибка создания промпта: ${response.error.status}`);
|
| 34 |
+
}
|
| 35 |
+
return response.data;
|
| 36 |
+
};
|
| 37 |
+
|
| 38 |
+
export const updateQePrompt = async (config: QePrompt): Promise<void> => {
|
| 39 |
+
const response = await query<void>({
|
| 40 |
+
url: `/qe_prompt/${config.id}`,
|
| 41 |
+
method: 'put',
|
| 42 |
+
data: config,
|
| 43 |
+
});
|
| 44 |
+
if ('error' in response) {
|
| 45 |
+
throw new Error(`Ошибка обновления промпта: ${response.error.status}`);
|
| 46 |
+
}
|
| 47 |
+
};
|
| 48 |
+
|
| 49 |
+
export const setDefaultQePrompt = async (id: number): Promise<void> => {
|
| 50 |
+
const response = await query<void>({
|
| 51 |
+
url: `/qe_prompt/default/${id}`,
|
| 52 |
+
method: 'put',
|
| 53 |
+
});
|
| 54 |
+
if ('error' in response) {
|
| 55 |
+
throw new Error(`Ошибка установки промпта по умолчанию: ${response.error.status}`);
|
| 56 |
+
}
|
| 57 |
+
};
|
| 58 |
+
|
| 59 |
+
export const deleteQePrompt = async (id: number): Promise<void> => {
|
| 60 |
+
const response = await query<void>({
|
| 61 |
+
url: `/qe_prompt/${id}`,
|
| 62 |
+
method: 'delete',
|
| 63 |
+
});
|
| 64 |
+
if ('error' in response) {
|
| 65 |
+
throw new Error(`Ошибка удаления промпта: ${response.error.status}`);
|
| 66 |
+
}
|
| 67 |
+
};
|
| 68 |
+
|
| 69 |
+
export const fetchDefaultQePrompt = async (): Promise<QePrompt | null> => {
|
| 70 |
+
const response = await query<QePrompt>({
|
| 71 |
+
url: '/qe_prompt/default',
|
| 72 |
+
method: 'get',
|
| 73 |
+
});
|
| 74 |
+
if ('error' in response) {
|
| 75 |
+
if (response.error.status === 404) return null; // Если дефолтной записи нет
|
| 76 |
+
throw new Error(`Ошибка получения дефолтной промпта: ${response.error.status}`);
|
| 77 |
+
}
|
| 78 |
+
return response.data;
|
| 79 |
+
};
|
src/api/qePrompts/types.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// src/api/qe_configs/types.ts
|
| 2 |
+
export interface QePrompt {
|
| 3 |
+
id: number;
|
| 4 |
+
is_default: boolean;
|
| 5 |
+
text: string;
|
| 6 |
+
name: string;
|
| 7 |
+
type: string;
|
| 8 |
+
created_at?: string;
|
| 9 |
+
}
|
src/components/common/navbar/Navbar.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
|
|
| 1 |
import React from 'react';
|
| 2 |
import { NavLink, useNavigate } from 'react-router-dom';
|
| 3 |
import './Navbar.scss';
|
| 4 |
-
import { useAuth } from '@/context/AuthContext';
|
| 5 |
|
| 6 |
const Navbar: React.FC = () => {
|
| 7 |
const { isAuthenticated, logout } = useAuth();
|
|
@@ -49,6 +49,14 @@ const Navbar: React.FC = () => {
|
|
| 49 |
Системные промпты
|
| 50 |
</NavLink>
|
| 51 |
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
<li>
|
| 53 |
<button onClick={handleLogout}>Выход</button>
|
| 54 |
</li>
|
|
|
|
| 1 |
+
import { useAuth } from '@/context/AuthContext';
|
| 2 |
import React from 'react';
|
| 3 |
import { NavLink, useNavigate } from 'react-router-dom';
|
| 4 |
import './Navbar.scss';
|
|
|
|
| 5 |
|
| 6 |
const Navbar: React.FC = () => {
|
| 7 |
const { isAuthenticated, logout } = useAuth();
|
|
|
|
| 49 |
Системные промпты
|
| 50 |
</NavLink>
|
| 51 |
</li>
|
| 52 |
+
<li>
|
| 53 |
+
<NavLink
|
| 54 |
+
to="/qeprompt"
|
| 55 |
+
className={({ isActive }) => (isActive ? 'active' : '')}
|
| 56 |
+
>
|
| 57 |
+
QE промпты
|
| 58 |
+
</NavLink>
|
| 59 |
+
</li>
|
| 60 |
<li>
|
| 61 |
<button onClick={handleLogout}>Выход</button>
|
| 62 |
</li>
|
src/components/generics/button/Button.scss
CHANGED
|
@@ -9,6 +9,7 @@
|
|
| 9 |
font-family: inherit;
|
| 10 |
display: flex;
|
| 11 |
gap: 10px;
|
|
|
|
| 12 |
}
|
| 13 |
|
| 14 |
.btn:hover {
|
|
|
|
| 9 |
font-family: inherit;
|
| 10 |
display: flex;
|
| 11 |
gap: 10px;
|
| 12 |
+
align-items: center;
|
| 13 |
}
|
| 14 |
|
| 15 |
.btn:hover {
|
src/components/generics/button/Button.tsx
CHANGED
|
@@ -12,7 +12,7 @@ const Button = ({
|
|
| 12 |
className,
|
| 13 |
}: ButtonProps) => {
|
| 14 |
return (
|
| 15 |
-
<button onClick={onClick} className={`btn ${buttonType} ${className}`} disabled={disabled}>
|
| 16 |
{name}
|
| 17 |
{icon}
|
| 18 |
{loading && <Spinner />}
|
|
|
|
| 12 |
className,
|
| 13 |
}: ButtonProps) => {
|
| 14 |
return (
|
| 15 |
+
<button onClick={onClick} className={`btn ${buttonType} ${className ?? ''}`} disabled={disabled}>
|
| 16 |
{name}
|
| 17 |
{icon}
|
| 18 |
{loading && <Spinner />}
|
src/components/pages/documentsPage/Documents.tsx
CHANGED
|
@@ -33,9 +33,9 @@ const Documents: FC = () => {
|
|
| 33 |
if (
|
| 34 |
(!searchParams.get("datasetId") ||
|
| 35 |
!datasetsData?.find((e) => e.id.toString() == searchParams.get("datasetId"))) &&
|
| 36 |
-
datasetsData?.[0]
|
| 37 |
) {
|
| 38 |
-
setSearchParams({ datasetId: String(datasetsData?.[0]
|
| 39 |
}
|
| 40 |
}, [datasetsData, searchParams, setSearchParams]);
|
| 41 |
|
|
|
|
| 33 |
if (
|
| 34 |
(!searchParams.get("datasetId") ||
|
| 35 |
!datasetsData?.find((e) => e.id.toString() == searchParams.get("datasetId"))) &&
|
| 36 |
+
datasetsData?.[0]?.id
|
| 37 |
) {
|
| 38 |
+
setSearchParams({ datasetId: String(datasetsData?.[0]?.id) });
|
| 39 |
}
|
| 40 |
}, [datasetsData, searchParams, setSearchParams]);
|
| 41 |
|
src/components/pages/llmConfigs/LlmConfigModal.scss
CHANGED
|
@@ -49,7 +49,7 @@
|
|
| 49 |
label {
|
| 50 |
display: contents;
|
| 51 |
|
| 52 |
-
span {
|
| 53 |
font-weight: 500;
|
| 54 |
color: #444;
|
| 55 |
text-align: right;
|
|
|
|
| 49 |
label {
|
| 50 |
display: contents;
|
| 51 |
|
| 52 |
+
span.title {
|
| 53 |
font-weight: 500;
|
| 54 |
color: #444;
|
| 55 |
text-align: right;
|
src/components/pages/llmConfigs/LlmConfigModal.tsx
CHANGED
|
@@ -128,12 +128,12 @@ interface LLMConfigModalProps {
|
|
| 128 |
<form onSubmit={handleSubmit}>
|
| 129 |
{isEditMode && 'id' in formData && (
|
| 130 |
<label>
|
| 131 |
-
<span>ID:</span>
|
| 132 |
<input type="text" value={formData.id} disabled />
|
| 133 |
</label>
|
| 134 |
)}
|
| 135 |
<label>
|
| 136 |
-
<span>Задать по-умолчанию:</span>
|
| 137 |
<input
|
| 138 |
type="checkbox"
|
| 139 |
name="is_default"
|
|
@@ -142,7 +142,7 @@ interface LLMConfigModalProps {
|
|
| 142 |
/>
|
| 143 |
</label>
|
| 144 |
<label>
|
| 145 |
-
<span>Модель:</span>
|
| 146 |
<input
|
| 147 |
type="text"
|
| 148 |
name="model"
|
|
@@ -151,7 +151,7 @@ interface LLMConfigModalProps {
|
|
| 151 |
/>
|
| 152 |
</label>
|
| 153 |
<label>
|
| 154 |
-
<span>Temperature:</span>
|
| 155 |
<input
|
| 156 |
type="number"
|
| 157 |
name="temperature"
|
|
@@ -161,7 +161,7 @@ interface LLMConfigModalProps {
|
|
| 161 |
/>
|
| 162 |
</label>
|
| 163 |
<label>
|
| 164 |
-
<span>Top P:</span>
|
| 165 |
<input
|
| 166 |
type="number"
|
| 167 |
name="top_p"
|
|
@@ -171,7 +171,7 @@ interface LLMConfigModalProps {
|
|
| 171 |
/>
|
| 172 |
</label>
|
| 173 |
<label>
|
| 174 |
-
<span>Min P:</span>
|
| 175 |
<input
|
| 176 |
type="number"
|
| 177 |
name="min_p"
|
|
@@ -181,7 +181,7 @@ interface LLMConfigModalProps {
|
|
| 181 |
/>
|
| 182 |
</label>
|
| 183 |
<label>
|
| 184 |
-
<span>Frequency Penalty:</span>
|
| 185 |
<input
|
| 186 |
type="number"
|
| 187 |
name="frequency_penalty"
|
|
@@ -191,7 +191,7 @@ interface LLMConfigModalProps {
|
|
| 191 |
/>
|
| 192 |
</label>
|
| 193 |
<label>
|
| 194 |
-
<span>Presence Penalty:</span>
|
| 195 |
<input
|
| 196 |
type="number"
|
| 197 |
name="presence_penalty"
|
|
@@ -201,7 +201,7 @@ interface LLMConfigModalProps {
|
|
| 201 |
/>
|
| 202 |
</label>
|
| 203 |
<label>
|
| 204 |
-
<span>N predict:</span>
|
| 205 |
<input
|
| 206 |
type="number"
|
| 207 |
name="n_predict"
|
|
@@ -211,7 +211,7 @@ interface LLMConfigModalProps {
|
|
| 211 |
/>
|
| 212 |
</label>
|
| 213 |
<label>
|
| 214 |
-
<span>Seed:</span>
|
| 215 |
<input
|
| 216 |
type="number"
|
| 217 |
name="seed"
|
|
|
|
| 128 |
<form onSubmit={handleSubmit}>
|
| 129 |
{isEditMode && 'id' in formData && (
|
| 130 |
<label>
|
| 131 |
+
<span className='title'>ID:</span>
|
| 132 |
<input type="text" value={formData.id} disabled />
|
| 133 |
</label>
|
| 134 |
)}
|
| 135 |
<label>
|
| 136 |
+
<span className='title'>Задать по-умолчанию:</span>
|
| 137 |
<input
|
| 138 |
type="checkbox"
|
| 139 |
name="is_default"
|
|
|
|
| 142 |
/>
|
| 143 |
</label>
|
| 144 |
<label>
|
| 145 |
+
<span className='title'>Модель:</span>
|
| 146 |
<input
|
| 147 |
type="text"
|
| 148 |
name="model"
|
|
|
|
| 151 |
/>
|
| 152 |
</label>
|
| 153 |
<label>
|
| 154 |
+
<span className='title'>Temperature:</span>
|
| 155 |
<input
|
| 156 |
type="number"
|
| 157 |
name="temperature"
|
|
|
|
| 161 |
/>
|
| 162 |
</label>
|
| 163 |
<label>
|
| 164 |
+
<span className='title'>Top P:</span>
|
| 165 |
<input
|
| 166 |
type="number"
|
| 167 |
name="top_p"
|
|
|
|
| 171 |
/>
|
| 172 |
</label>
|
| 173 |
<label>
|
| 174 |
+
<span className='title'>Min P:</span>
|
| 175 |
<input
|
| 176 |
type="number"
|
| 177 |
name="min_p"
|
|
|
|
| 181 |
/>
|
| 182 |
</label>
|
| 183 |
<label>
|
| 184 |
+
<span className='title'>Frequency Penalty:</span>
|
| 185 |
<input
|
| 186 |
type="number"
|
| 187 |
name="frequency_penalty"
|
|
|
|
| 191 |
/>
|
| 192 |
</label>
|
| 193 |
<label>
|
| 194 |
+
<span className='title'>Presence Penalty:</span>
|
| 195 |
<input
|
| 196 |
type="number"
|
| 197 |
name="presence_penalty"
|
|
|
|
| 201 |
/>
|
| 202 |
</label>
|
| 203 |
<label>
|
| 204 |
+
<span className='title'>N predict:</span>
|
| 205 |
<input
|
| 206 |
type="number"
|
| 207 |
name="n_predict"
|
|
|
|
| 211 |
/>
|
| 212 |
</label>
|
| 213 |
<label>
|
| 214 |
+
<span className='title'>Seed:</span>
|
| 215 |
<input
|
| 216 |
type="number"
|
| 217 |
name="seed"
|
src/components/pages/llmPrompts/LlmPromptModal.scss
CHANGED
|
@@ -13,6 +13,7 @@
|
|
| 13 |
overflow-y: auto;
|
| 14 |
overflow-x: hidden;
|
| 15 |
|
|
|
|
| 16 |
.label {
|
| 17 |
display: flex;
|
| 18 |
justify-content: space-between;
|
|
@@ -49,7 +50,7 @@
|
|
| 49 |
label {
|
| 50 |
display: contents;
|
| 51 |
|
| 52 |
-
span {
|
| 53 |
font-weight: 500;
|
| 54 |
color: #444;
|
| 55 |
text-align: right;
|
|
|
|
| 13 |
overflow-y: auto;
|
| 14 |
overflow-x: hidden;
|
| 15 |
|
| 16 |
+
|
| 17 |
.label {
|
| 18 |
display: flex;
|
| 19 |
justify-content: space-between;
|
|
|
|
| 50 |
label {
|
| 51 |
display: contents;
|
| 52 |
|
| 53 |
+
span.title {
|
| 54 |
font-weight: 500;
|
| 55 |
color: #444;
|
| 56 |
text-align: right;
|
src/components/pages/llmPrompts/LlmPromptModal.tsx
CHANGED
|
@@ -117,12 +117,12 @@ const LlmPromptModal: React.FC<LlmPromptModalProps> = ({
|
|
| 117 |
<form onSubmit={handleSubmit}>
|
| 118 |
{isEditMode && 'id' in formData && (
|
| 119 |
<label>
|
| 120 |
-
<span>ID:</span>
|
| 121 |
<input type="text" value={formData.id} disabled />
|
| 122 |
</label>
|
| 123 |
)}
|
| 124 |
<label>
|
| 125 |
-
<span>Задать по-умолчанию:</span>
|
| 126 |
<input
|
| 127 |
type="checkbox"
|
| 128 |
name="is_default"
|
|
@@ -131,7 +131,7 @@ const LlmPromptModal: React.FC<LlmPromptModalProps> = ({
|
|
| 131 |
/>
|
| 132 |
</label>
|
| 133 |
<label>
|
| 134 |
-
<span>Название:</span>
|
| 135 |
<input
|
| 136 |
type="text"
|
| 137 |
name="name"
|
|
@@ -140,7 +140,7 @@ const LlmPromptModal: React.FC<LlmPromptModalProps> = ({
|
|
| 140 |
/>
|
| 141 |
</label>
|
| 142 |
<label>
|
| 143 |
-
<span>Текст:</span>
|
| 144 |
<textarea
|
| 145 |
name="text"
|
| 146 |
value={formData.text || ''}
|
|
|
|
| 117 |
<form onSubmit={handleSubmit}>
|
| 118 |
{isEditMode && 'id' in formData && (
|
| 119 |
<label>
|
| 120 |
+
<span className='title'>ID:</span>
|
| 121 |
<input type="text" value={formData.id} disabled />
|
| 122 |
</label>
|
| 123 |
)}
|
| 124 |
<label>
|
| 125 |
+
<span className='title'>Задать по-умолчанию:</span>
|
| 126 |
<input
|
| 127 |
type="checkbox"
|
| 128 |
name="is_default"
|
|
|
|
| 131 |
/>
|
| 132 |
</label>
|
| 133 |
<label>
|
| 134 |
+
<span className='title'>Название:</span>
|
| 135 |
<input
|
| 136 |
type="text"
|
| 137 |
name="name"
|
|
|
|
| 140 |
/>
|
| 141 |
</label>
|
| 142 |
<label>
|
| 143 |
+
<span className='title'>Текст:</span>
|
| 144 |
<textarea
|
| 145 |
name="text"
|
| 146 |
value={formData.text || ''}
|
src/components/pages/qePrompts/QePromptList.scss
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.qe-prompt-list {
|
| 2 |
+
padding: 20px;
|
| 3 |
+
|
| 4 |
+
.create-button {
|
| 5 |
+
margin-bottom: 20px;
|
| 6 |
+
padding: 8px 16px;
|
| 7 |
+
background-color: #007bff;
|
| 8 |
+
color: white;
|
| 9 |
+
border: none;
|
| 10 |
+
border-radius: 5px;
|
| 11 |
+
cursor: pointer;
|
| 12 |
+
|
| 13 |
+
&:hover {
|
| 14 |
+
background-color: #0056b3;
|
| 15 |
+
}
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
.table-container {
|
| 19 |
+
width: 100%;
|
| 20 |
+
margin-top: 20px;
|
| 21 |
+
border: 1px solid #ddd;
|
| 22 |
+
|
| 23 |
+
.table-header {
|
| 24 |
+
display: flex;
|
| 25 |
+
background-color: #f2f2f2;
|
| 26 |
+
font-weight: bold;
|
| 27 |
+
|
| 28 |
+
.table-cell {
|
| 29 |
+
flex: 1;
|
| 30 |
+
padding: 8px;
|
| 31 |
+
border-right: 1px solid #ddd;
|
| 32 |
+
cursor: pointer;
|
| 33 |
+
|
| 34 |
+
&:nth-child(1) {
|
| 35 |
+
min-width: 30px;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
&:nth-child(2) {
|
| 39 |
+
flex: 30;
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
&:nth-child(3) {
|
| 43 |
+
min-width: 100px;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
&:last-child {
|
| 47 |
+
border-right: none;
|
| 48 |
+
}
|
| 49 |
+
}
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
.table-row {
|
| 53 |
+
display: flex;
|
| 54 |
+
border-top: 1px solid #ddd;
|
| 55 |
+
|
| 56 |
+
&:hover {
|
| 57 |
+
background-color: #f5f5f5;
|
| 58 |
+
cursor: pointer;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
.table-cell {
|
| 62 |
+
flex: 1;
|
| 63 |
+
padding: 8px;
|
| 64 |
+
border-right: 1px solid #ddd;
|
| 65 |
+
|
| 66 |
+
&:nth-child(1) {
|
| 67 |
+
min-width: 30px;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
&:nth-child(2) {
|
| 71 |
+
flex: 30;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
&:nth-child(3) {
|
| 75 |
+
min-width: 100px;
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
&:last-child {
|
| 79 |
+
border-right: none;
|
| 80 |
+
display: flex;
|
| 81 |
+
justify-content: center;
|
| 82 |
+
}
|
| 83 |
+
}
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
.set-default-button,
|
| 87 |
+
.delete-button {
|
| 88 |
+
padding: 5px;
|
| 89 |
+
display: flex;
|
| 90 |
+
align-items: center;
|
| 91 |
+
justify-content: center;
|
| 92 |
+
margin:3px;
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
.delete-button {
|
| 96 |
+
background-color: #dc3545;
|
| 97 |
+
color: white;
|
| 98 |
+
border: none;
|
| 99 |
+
border-radius: 5px;
|
| 100 |
+
cursor: pointer;
|
| 101 |
+
|
| 102 |
+
&:hover {
|
| 103 |
+
background-color: #c82333;
|
| 104 |
+
}
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
.set-default-button {
|
| 108 |
+
background-color: #28a745;
|
| 109 |
+
color: white;
|
| 110 |
+
border: none;
|
| 111 |
+
border-radius: 5px;
|
| 112 |
+
cursor: pointer;
|
| 113 |
+
|
| 114 |
+
&:hover {
|
| 115 |
+
background-color: #218838;
|
| 116 |
+
}
|
| 117 |
+
}
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
.modal-overlay {
|
| 121 |
+
position: fixed;
|
| 122 |
+
top: 0;
|
| 123 |
+
left: 0;
|
| 124 |
+
right: 0;
|
| 125 |
+
bottom: 0;
|
| 126 |
+
background-color: rgba(0, 0, 0, 0.5);
|
| 127 |
+
z-index: 1000;
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
+
.modal-content {
|
| 131 |
+
padding: 20px;
|
| 132 |
+
|
| 133 |
+
.label {
|
| 134 |
+
display: flex;
|
| 135 |
+
justify-content: space-between;
|
| 136 |
+
align-items: center;
|
| 137 |
+
margin-bottom: 20px;
|
| 138 |
+
|
| 139 |
+
.name {
|
| 140 |
+
margin: 0;
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
.close-button {
|
| 144 |
+
background: none;
|
| 145 |
+
border: none;
|
| 146 |
+
cursor: pointer;
|
| 147 |
+
padding: 0;
|
| 148 |
+
}
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
form {
|
| 152 |
+
display: flex;
|
| 153 |
+
flex-direction: column;
|
| 154 |
+
gap: 15px;
|
| 155 |
+
|
| 156 |
+
label {
|
| 157 |
+
display: flex;
|
| 158 |
+
flex-direction: column;
|
| 159 |
+
gap: 5px;
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
input {
|
| 163 |
+
padding: 8px;
|
| 164 |
+
border: 1px solid #ddd;
|
| 165 |
+
border-radius: 5px;
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
.button-group {
|
| 169 |
+
display: flex;
|
| 170 |
+
gap: 10px;
|
| 171 |
+
margin-top: 20px;
|
| 172 |
+
|
| 173 |
+
button {
|
| 174 |
+
padding: 8px 16px;
|
| 175 |
+
border: none;
|
| 176 |
+
border-radius: 5px;
|
| 177 |
+
cursor: pointer;
|
| 178 |
+
|
| 179 |
+
&:first-child {
|
| 180 |
+
background-color: #007bff;
|
| 181 |
+
color: white;
|
| 182 |
+
|
| 183 |
+
&:hover {
|
| 184 |
+
background-color: #0056b3;
|
| 185 |
+
}
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
&:nth-child(2) {
|
| 189 |
+
background-color: #28a745;
|
| 190 |
+
color: white;
|
| 191 |
+
|
| 192 |
+
&:hover {
|
| 193 |
+
background-color: #218838;
|
| 194 |
+
}
|
| 195 |
+
}
|
| 196 |
+
|
| 197 |
+
&:last-child {
|
| 198 |
+
background-color: #6c757d;
|
| 199 |
+
color: white;
|
| 200 |
+
|
| 201 |
+
&:hover {
|
| 202 |
+
background-color: #5a6268;
|
| 203 |
+
}
|
| 204 |
+
}
|
| 205 |
+
}
|
| 206 |
+
}
|
| 207 |
+
}
|
| 208 |
+
}
|
| 209 |
+
}
|
src/components/pages/qePrompts/QePromptList.tsx
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useQePrompts, } from "@/api/qePrompts/hooks";
|
| 2 |
+
import { QePrompt } from "@/api/qePrompts/types";
|
| 3 |
+
import React, { useState } from 'react';
|
| 4 |
+
import { GoStar, GoStarFill, GoTrash } from 'react-icons/go';
|
| 5 |
+
import Modal from 'react-modal';
|
| 6 |
+
import './QePromptList.scss';
|
| 7 |
+
import QePromptModal from './QePromptModal';
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
Modal.setAppElement('#root');
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
const QePromptList: React.FC = () => {
|
| 16 |
+
const { prompts, isLoading, error, createPrompt, updatePrompt, setAsDefaultPrompt, deletePrompt } = useQePrompts();
|
| 17 |
+
const [sortField, setSortField] = useState<keyof QePrompt | 'created_at'>('id');
|
| 18 |
+
const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('asc');
|
| 19 |
+
const [selectedPrompt, setSelectedPrompt] = useState<QePrompt | null>(null);
|
| 20 |
+
const [isModalOpen, setIsModalOpen] = useState(false);
|
| 21 |
+
const [isEditMode, setIsEditMode] = useState(false);
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
const handleSort = (field: keyof QePrompt | 'created_at') => {
|
| 25 |
+
const newDirection = sortField === field && sortDirection === 'asc' ? 'desc' : 'asc';
|
| 26 |
+
setSortField(field);
|
| 27 |
+
setSortDirection(newDirection);
|
| 28 |
+
const sortedPrompts = [...prompts].sort((a, b) => {
|
| 29 |
+
const aValue = field === 'created_at' ? a.created_at || '' : a[field];
|
| 30 |
+
const bValue = field === 'created_at' ? b.created_at || '' : b[field];
|
| 31 |
+
return newDirection === 'asc' ? (aValue > bValue ? 1 : -1) : (aValue < bValue ? 1 : -1);
|
| 32 |
+
});
|
| 33 |
+
prompts.splice(0, prompts.length, ...sortedPrompts);
|
| 34 |
+
};
|
| 35 |
+
|
| 36 |
+
const openEditModal = (prompt: QePrompt) => {
|
| 37 |
+
setSelectedPrompt(prompt);
|
| 38 |
+
setIsEditMode(true);
|
| 39 |
+
setIsModalOpen(true);
|
| 40 |
+
};
|
| 41 |
+
|
| 42 |
+
const openCreateModal = () => {
|
| 43 |
+
setSelectedPrompt(null); // Ничего не передаем, запрос будет в модалке
|
| 44 |
+
setIsEditMode(false);
|
| 45 |
+
setIsModalOpen(true);
|
| 46 |
+
};
|
| 47 |
+
|
| 48 |
+
const closeModal = () => {
|
| 49 |
+
setSelectedPrompt(null);
|
| 50 |
+
setIsModalOpen(false);
|
| 51 |
+
};
|
| 52 |
+
|
| 53 |
+
const handleSave = async (prompt: QePrompt | Omit<QePrompt, 'id' | 'created_at'>) => {
|
| 54 |
+
if (isEditMode && 'id' in prompt) {
|
| 55 |
+
await updatePrompt(prompt as QePrompt);
|
| 56 |
+
} else {
|
| 57 |
+
await createPrompt(prompt as Omit<QePrompt, 'id' | 'created_at'>);
|
| 58 |
+
}
|
| 59 |
+
};
|
| 60 |
+
|
| 61 |
+
const handleDelete = async (id: number) => {
|
| 62 |
+
if (window.confirm('Удаляем версию промпта?')) {
|
| 63 |
+
await deletePrompt(id);
|
| 64 |
+
}
|
| 65 |
+
};
|
| 66 |
+
|
| 67 |
+
const handleSetDefault = async (id: number) => {
|
| 68 |
+
await setAsDefaultPrompt(id);
|
| 69 |
+
};
|
| 70 |
+
|
| 71 |
+
if (isLoading) return <div>Loading...</div>;
|
| 72 |
+
if (error) return <div>Error: {error}</div>;
|
| 73 |
+
|
| 74 |
+
return (
|
| 75 |
+
<div className="qe-prompt-list">
|
| 76 |
+
<h1>Промпты Query Expansion</h1>
|
| 77 |
+
<button className="create-button" onClick={openCreateModal}>
|
| 78 |
+
Добавить промпт
|
| 79 |
+
</button>
|
| 80 |
+
<div className="table-container">
|
| 81 |
+
<div className="table-header">
|
| 82 |
+
<div className="table-cell"></div>
|
| 83 |
+
<div className="table-cell" onClick={() => handleSort('created_at')}>
|
| 84 |
+
Промпты
|
| 85 |
+
</div>
|
| 86 |
+
<div className="table-cell"></div>
|
| 87 |
+
</div>
|
| 88 |
+
{prompts.map(prompt => (
|
| 89 |
+
<div key={prompt.id} className="table-row">
|
| 90 |
+
<div className="table-cell">
|
| 91 |
+
<button
|
| 92 |
+
className="set-default-button"
|
| 93 |
+
onClick={() => handleSetDefault(prompt.id)}
|
| 94 |
+
>
|
| 95 |
+
{prompt.is_default ? <GoStarFill size={20} /> : <GoStar size={20} />}
|
| 96 |
+
</button>
|
| 97 |
+
</div>
|
| 98 |
+
<div className="table-cell" onClick={() => openEditModal(prompt)}>
|
| 99 |
+
{prompt.name}
|
| 100 |
+
</div>
|
| 101 |
+
{/* <div className="table-cell" onClick={() => openEditModal(prompt)}>
|
| 102 |
+
{prompt.created_at || 'N/A'}
|
| 103 |
+
</div> */}
|
| 104 |
+
<div className="table-cell">
|
| 105 |
+
<button className="delete-button" onClick={() => handleDelete(prompt.id)}>
|
| 106 |
+
<GoTrash size={20} />
|
| 107 |
+
</button>
|
| 108 |
+
</div>
|
| 109 |
+
</div>
|
| 110 |
+
))}
|
| 111 |
+
</div>
|
| 112 |
+
|
| 113 |
+
<QePromptModal
|
| 114 |
+
isOpen={isModalOpen}
|
| 115 |
+
onRequestClose={closeModal}
|
| 116 |
+
prompt={selectedPrompt}
|
| 117 |
+
onSave={handleSave}
|
| 118 |
+
isEditMode={isEditMode}
|
| 119 |
+
/>
|
| 120 |
+
</div>
|
| 121 |
+
);
|
| 122 |
+
};
|
| 123 |
+
|
| 124 |
+
export default QePromptList;
|
src/components/pages/qePrompts/QePromptModal.scss
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.modal-overlay {
|
| 2 |
+
position: fixed;
|
| 3 |
+
top: 0;
|
| 4 |
+
left: 0;
|
| 5 |
+
right: 0;
|
| 6 |
+
bottom: 0;
|
| 7 |
+
background-color: rgba(0, 0, 0, 0.5);
|
| 8 |
+
z-index: 1000;
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
.modal-content {
|
| 12 |
+
max-height: 80vh;
|
| 13 |
+
overflow-y: auto;
|
| 14 |
+
overflow-x: hidden;
|
| 15 |
+
|
| 16 |
+
.label {
|
| 17 |
+
display: flex;
|
| 18 |
+
justify-content: space-between;
|
| 19 |
+
align-items: center;
|
| 20 |
+
margin-bottom: 20px;
|
| 21 |
+
|
| 22 |
+
.name {
|
| 23 |
+
margin: 0;
|
| 24 |
+
font-size: 1.5rem;
|
| 25 |
+
color: #333;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
.close-button {
|
| 29 |
+
background: none;
|
| 30 |
+
border: none;
|
| 31 |
+
cursor: pointer;
|
| 32 |
+
padding: 0;
|
| 33 |
+
color: #666;
|
| 34 |
+
|
| 35 |
+
&:hover {
|
| 36 |
+
color: #333;
|
| 37 |
+
}
|
| 38 |
+
}
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
form {
|
| 42 |
+
display: grid;
|
| 43 |
+
grid-template-columns: 1fr 2fr;
|
| 44 |
+
gap: 15px;
|
| 45 |
+
align-items: center;
|
| 46 |
+
width: 100%;
|
| 47 |
+
box-sizing: border-box;
|
| 48 |
+
|
| 49 |
+
label {
|
| 50 |
+
display: contents;
|
| 51 |
+
|
| 52 |
+
span.title {
|
| 53 |
+
font-weight: 500;
|
| 54 |
+
color: #444;
|
| 55 |
+
text-align: right;
|
| 56 |
+
padding-right: 10px;
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
input {
|
| 60 |
+
max-width: 100%;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
input[type="text"],
|
| 64 |
+
input[type="number"] {
|
| 65 |
+
padding: 8px 12px;
|
| 66 |
+
border: 1px solid #ccc;
|
| 67 |
+
border-radius: 5px;
|
| 68 |
+
font-size: 1rem;
|
| 69 |
+
color: #333;
|
| 70 |
+
background-color: #f9f9f9;
|
| 71 |
+
transition: border-color 0.2s;
|
| 72 |
+
|
| 73 |
+
&:focus {
|
| 74 |
+
border-color: #007bff;
|
| 75 |
+
outline: none;
|
| 76 |
+
background-color: #fff;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
&:disabled {
|
| 80 |
+
background-color: #e9ecef;
|
| 81 |
+
color: #666;
|
| 82 |
+
}
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
input[type="checkbox"] {
|
| 86 |
+
width: 20px;
|
| 87 |
+
height: 20px;
|
| 88 |
+
margin: 0;
|
| 89 |
+
cursor: pointer;
|
| 90 |
+
}
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
.button-group {
|
| 94 |
+
grid-column: span 2;
|
| 95 |
+
display: flex;
|
| 96 |
+
justify-content: flex-end;
|
| 97 |
+
gap: 10px;
|
| 98 |
+
margin-top: 20px;
|
| 99 |
+
|
| 100 |
+
button {
|
| 101 |
+
padding: 10px 20px;
|
| 102 |
+
border: none;
|
| 103 |
+
border-radius: 5px;
|
| 104 |
+
font-size: 1rem;
|
| 105 |
+
cursor: pointer;
|
| 106 |
+
transition: background-color 0.2s;
|
| 107 |
+
|
| 108 |
+
&:first-child {
|
| 109 |
+
background-color: #007bff;
|
| 110 |
+
color: white;
|
| 111 |
+
|
| 112 |
+
&:hover {
|
| 113 |
+
background-color: #0056b3;
|
| 114 |
+
}
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
&:nth-child(2) {
|
| 118 |
+
background-color: #28a745;
|
| 119 |
+
color: white;
|
| 120 |
+
|
| 121 |
+
&:hover {
|
| 122 |
+
background-color: #218838;
|
| 123 |
+
}
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
&:last-child {
|
| 127 |
+
background-color: #6c757d;
|
| 128 |
+
color: white;
|
| 129 |
+
|
| 130 |
+
&:hover {
|
| 131 |
+
background-color: #5a6268;
|
| 132 |
+
}
|
| 133 |
+
}
|
| 134 |
+
}
|
| 135 |
+
}
|
| 136 |
+
}
|
| 137 |
+
}
|
src/components/pages/qePrompts/QePromptModal.tsx
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { fetchDefaultQePrompt, fetchQePromptById } from '@/api/qePrompts/qePromptApi';
|
| 2 |
+
import { QePrompt } from '@/api/qePrompts/types';
|
| 3 |
+
import { useQuery } from '@tanstack/react-query';
|
| 4 |
+
import React from 'react';
|
| 5 |
+
import { GoX } from 'react-icons/go';
|
| 6 |
+
import Modal from 'react-modal';
|
| 7 |
+
import './QePromptModal.scss';
|
| 8 |
+
|
| 9 |
+
interface QePromptModalProps {
|
| 10 |
+
isOpen: boolean;
|
| 11 |
+
onRequestClose: () => void;
|
| 12 |
+
prompt: QePrompt | null;
|
| 13 |
+
onSave: (prompt: QePrompt | Omit<QePrompt, 'id' | 'created_at'>) => Promise<void>;
|
| 14 |
+
isEditMode: boolean;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
const customStyles = {
|
| 18 |
+
content: {
|
| 19 |
+
top: '40%',
|
| 20 |
+
left: '50%',
|
| 21 |
+
right: 'auto',
|
| 22 |
+
bottom: 'auto',
|
| 23 |
+
transform: 'translate(-50%, -50%)',
|
| 24 |
+
borderRadius: '15px',
|
| 25 |
+
maxWidth: '100%',
|
| 26 |
+
overflow: 'hidden',
|
| 27 |
+
},
|
| 28 |
+
};
|
| 29 |
+
|
| 30 |
+
const QePromptModal: React.FC<QePromptModalProps> = ({
|
| 31 |
+
isOpen,
|
| 32 |
+
onRequestClose,
|
| 33 |
+
prompt,
|
| 34 |
+
onSave,
|
| 35 |
+
isEditMode,
|
| 36 |
+
}) => {
|
| 37 |
+
const [formData, setFormData] = React.useState<QePrompt | Omit<QePrompt, 'id' | 'created_at'>>(() => ({
|
| 38 |
+
is_default: false,
|
| 39 |
+
name: 'Промпт ' + Date.now().toLocaleString(),
|
| 40 |
+
text: "",
|
| 41 |
+
type: 'query_expansion'
|
| 42 |
+
}));
|
| 43 |
+
|
| 44 |
+
// Запрос промпта для редактирования
|
| 45 |
+
const { data: serverPrompt, isLoading: isPromptLoading } = useQuery({
|
| 46 |
+
queryKey: ['qePrompt', prompt?.id],
|
| 47 |
+
queryFn: () => fetchQePromptById(prompt!.id),
|
| 48 |
+
enabled: isOpen && isEditMode && !!prompt?.id,
|
| 49 |
+
});
|
| 50 |
+
|
| 51 |
+
// Запрос дефолтного промпта для создания
|
| 52 |
+
const { data: defaultPrompt, isLoading: isDefaultLoading } = useQuery({
|
| 53 |
+
queryKey: ['defaultQePrompt'],
|
| 54 |
+
queryFn: fetchDefaultQePrompt,
|
| 55 |
+
enabled: isOpen && !isEditMode, // Запрашиваем только при создании
|
| 56 |
+
});
|
| 57 |
+
|
| 58 |
+
React.useEffect(() => {
|
| 59 |
+
if (isOpen) {
|
| 60 |
+
if (isEditMode && serverPrompt) {
|
| 61 |
+
setFormData(serverPrompt); // Данные с сервера для редактирования
|
| 62 |
+
} else if (!isEditMode && defaultPrompt) {
|
| 63 |
+
setFormData(defaultPrompt); // Дефолтная запись с сервера для создания
|
| 64 |
+
} else if (!isEditMode && !defaultPrompt && !isDefaultLoading) {
|
| 65 |
+
setFormData({ // Если дефолтной записи нет и загрузка завершена
|
| 66 |
+
is_default: true,
|
| 67 |
+
name: 'Промпт ' + Date.now().toLocaleString(),
|
| 68 |
+
text: "",
|
| 69 |
+
type: 'query_expansion'
|
| 70 |
+
});
|
| 71 |
+
}
|
| 72 |
+
}
|
| 73 |
+
}, [isOpen, isEditMode, serverPrompt, defaultPrompt, isDefaultLoading]);
|
| 74 |
+
|
| 75 |
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
| 76 |
+
const { name, value } = e.target;
|
| 77 |
+
setFormData(prev => ({
|
| 78 |
+
...prev,
|
| 79 |
+
[name]:
|
| 80 |
+
name === 'is_default' ? (e.target as HTMLInputElement).checked :
|
| 81 |
+
name === 'text' || name === 'name' ? value :
|
| 82 |
+
parseFloat(value) || 0,
|
| 83 |
+
}));
|
| 84 |
+
};
|
| 85 |
+
|
| 86 |
+
const handleSubmit = async (e: React.FormEvent) => {
|
| 87 |
+
e.preventDefault();
|
| 88 |
+
try {
|
| 89 |
+
await onSave(formData);
|
| 90 |
+
onRequestClose();
|
| 91 |
+
} catch (err) {
|
| 92 |
+
console.error('Save failed:', err);
|
| 93 |
+
}
|
| 94 |
+
};
|
| 95 |
+
|
| 96 |
+
if (isPromptLoading && isEditMode) {
|
| 97 |
+
return <div>Loading prompt...</div>;
|
| 98 |
+
}
|
| 99 |
+
if (isDefaultLoading && !isEditMode) {
|
| 100 |
+
return <div>Loading default prompt...</div>;
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
return (
|
| 104 |
+
<Modal
|
| 105 |
+
isOpen={isOpen}
|
| 106 |
+
onRequestClose={onRequestClose}
|
| 107 |
+
style={customStyles}
|
| 108 |
+
overlayClassName="modal-overlay"
|
| 109 |
+
>
|
| 110 |
+
<div className="modal-content">
|
| 111 |
+
<div className="label">
|
| 112 |
+
<h3 className="name">{isEditMode ? 'Редактирование промпта' : 'Новый промпт'}</h3>
|
| 113 |
+
<button className="close-button" onClick={onRequestClose}>
|
| 114 |
+
<GoX style={{ height: '25px', width: '25px' }} />
|
| 115 |
+
</button>
|
| 116 |
+
</div>
|
| 117 |
+
<form onSubmit={handleSubmit}>
|
| 118 |
+
{isEditMode && 'id' in formData && (
|
| 119 |
+
<label>
|
| 120 |
+
<span className='title'>ID:</span>
|
| 121 |
+
<input type="text" value={formData.id} disabled />
|
| 122 |
+
</label>
|
| 123 |
+
)}
|
| 124 |
+
<label>
|
| 125 |
+
<span className='title'>Задать по-умолчанию:</span>
|
| 126 |
+
<input
|
| 127 |
+
type="checkbox"
|
| 128 |
+
name="is_default"
|
| 129 |
+
checked={formData.is_default}
|
| 130 |
+
onChange={handleChange}
|
| 131 |
+
/>
|
| 132 |
+
</label>
|
| 133 |
+
<label>
|
| 134 |
+
<span className='title'>Название:</span>
|
| 135 |
+
<input
|
| 136 |
+
type="text"
|
| 137 |
+
name="name"
|
| 138 |
+
value={formData.name}
|
| 139 |
+
onChange={handleChange}
|
| 140 |
+
/>
|
| 141 |
+
</label>
|
| 142 |
+
<label>
|
| 143 |
+
<span className='title'>Текст:</span>
|
| 144 |
+
<textarea
|
| 145 |
+
name="text"
|
| 146 |
+
value={formData.text || ''}
|
| 147 |
+
onChange={handleChange}
|
| 148 |
+
/>
|
| 149 |
+
</label>
|
| 150 |
+
<div className="button-group">
|
| 151 |
+
<button type="submit">{isEditMode ? 'Сохранит��' : 'Создать'}</button>
|
| 152 |
+
</div>
|
| 153 |
+
</form>
|
| 154 |
+
</div>
|
| 155 |
+
</Modal>
|
| 156 |
+
);
|
| 157 |
+
};
|
| 158 |
+
|
| 159 |
+
export default QePromptModal;
|
src/components/views/documents/docsList/DocsList.tsx
CHANGED
|
@@ -21,9 +21,9 @@ export const DocsList: FC<DocsListProps> = ({ datasetId, handleDeleteFile }) =>
|
|
| 21 |
const [searchInput, setSearchInput] = useState<string | undefined>(undefined);
|
| 22 |
const [search, setSearch] = useState<string | undefined>(undefined);
|
| 23 |
const [sort, setSort] = useState<undefined | { field: string; direction: SortDirections }[]>(undefined);
|
| 24 |
-
|
| 25 |
const { data: datasetData, isFetching } = useGetDataset(datasetId ?? -1, { page, page_size: pageSize, search, sort });
|
| 26 |
-
|
| 27 |
const toggleSort = (field: string) => {
|
| 28 |
setSort((prevSort) => {
|
| 29 |
if (prevSort?.length && prevSort?.length > 0) {
|
|
|
|
| 21 |
const [searchInput, setSearchInput] = useState<string | undefined>(undefined);
|
| 22 |
const [search, setSearch] = useState<string | undefined>(undefined);
|
| 23 |
const [sort, setSort] = useState<undefined | { field: string; direction: SortDirections }[]>(undefined);
|
| 24 |
+
|
| 25 |
const { data: datasetData, isFetching } = useGetDataset(datasetId ?? -1, { page, page_size: pageSize, search, sort });
|
| 26 |
+
|
| 27 |
const toggleSort = (field: string) => {
|
| 28 |
setSort((prevSort) => {
|
| 29 |
if (prevSort?.length && prevSort?.length > 0) {
|