diff --git a/.gitignore b/.gitignore index 9a5aced..5fc2c03 100644 --- a/.gitignore +++ b/.gitignore @@ -124,6 +124,7 @@ dist # Stores VSCode versions used for testing VSCode extensions .vscode-test +.vscode # yarn v3 .pnp.* diff --git a/client/package-lock.json b/client/package-lock.json index 13c801e..d513afa 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -7,15 +7,16 @@ "": { "name": "client", "version": "0.0.0", + "license": "Apache-2.0", "dependencies": { "@progress/kendo-licensing": "^1.7.1", - "@progress/kendo-react-buttons": "^12.0.2", - "@progress/kendo-react-charts": "^12.0.2", - "@progress/kendo-react-common": "^12.0.2", - "@progress/kendo-react-conversational-ui": "^12.0.2", - "@progress/kendo-react-layout": "^12.0.2", - "@progress/kendo-theme-bootstrap": "^12.0.1", - "@progress/kendo-theme-utils": "^12.0.1", + "@progress/kendo-react-buttons": "^13.0.0", + "@progress/kendo-react-charts": "^13.0.0", + "@progress/kendo-react-common": "^13.0.0", + "@progress/kendo-react-conversational-ui": "^13.0.0", + "@progress/kendo-react-layout": "^13.0.0", + "@progress/kendo-theme-bootstrap": "^12.3.0-dev.1", + "@progress/kendo-theme-utils": "^12.3.0-dev.1", "@types/react-syntax-highlighter": "^15.5.13", "react": "^19.1.1", "react-dom": "^19.1.1", @@ -1023,9 +1024,9 @@ } }, "node_modules/@progress/kendo-charts": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@progress/kendo-charts/-/kendo-charts-2.8.0.tgz", - "integrity": "sha512-KHP6RgsCSFDTO1ZvdWgqK/9t0z/KEthhrqAmPC/EC5dqezGqfJJ5H1Y/Cw1e9HeQ4qgtZXz/q8R84cCJg/hTiQ==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@progress/kendo-charts/-/kendo-charts-2.9.0.tgz", + "integrity": "sha512-JINi23tklbEZ4G65OTRF2qe2rR6vYSIwbsHuU07ESXnumVifUYYuFr/jtO1co04f5s0b2NDweXHxwhViPdt+Bw==", "license": "SEE LICENSE IN license.txt", "peerDependencies": { "@progress/kendo-drawing": "^1.21.0" @@ -1113,16 +1114,16 @@ } }, "node_modules/@progress/kendo-popup-common": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@progress/kendo-popup-common/-/kendo-popup-common-1.9.2.tgz", - "integrity": "sha512-Gs50UafJcERiGuSP/47Yg7ftPX3HQXiK5M9zHB8sHSoc1/AEYd0/Sj5wh8UrVVBAM9b0pUTwmEuzQ/D5yDDd2Q==", + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/@progress/kendo-popup-common/-/kendo-popup-common-1.9.5.tgz", + "integrity": "sha512-HpUy0PLbS/bhhs/FxxFGaJxxbskQbAVMPWE5i6qxQ5G1krQHWApJ9B+43Rx5IQiWtoenjCGtYv0QSZlRQxDqsg==", "license": "Apache-2.0", "peer": true }, "node_modules/@progress/kendo-react-animation": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/@progress/kendo-react-animation/-/kendo-react-animation-12.0.2.tgz", - "integrity": "sha512-NBEPbWoEp8K53MXPMMPouLEGE56WVqkT0jdwr6TV1VyHFaAcYmNDwAaXnkKht+GfleIZ5OBHW4uIDQgrHIz/kA==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@progress/kendo-react-animation/-/kendo-react-animation-13.0.0.tgz", + "integrity": "sha512-e5ONG3wycwePYZvhVqQrBG7/cbA7R8eXjX2BiHxj/IxeHicWrX0gSLjZsd4YTLlh3nvPMsfcP2Zn/75sDi+gKQ==", "license": "SEE LICENSE IN LICENSE.md", "peer": true, "dependencies": { @@ -1130,7 +1131,7 @@ }, "peerDependencies": { "@progress/kendo-licensing": "^1.7.0", - "@progress/kendo-react-common": "12.0.2", + "@progress/kendo-react-common": "13.0.0", "@progress/kendo-svg-icons": "^4.0.0", "react": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", @@ -1138,18 +1139,18 @@ } }, "node_modules/@progress/kendo-react-buttons": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/@progress/kendo-react-buttons/-/kendo-react-buttons-12.0.2.tgz", - "integrity": "sha512-ZAYqF4lFf7E7F3ThNL6CECrqD2fUJWgh12n/qGCw4Rkd8Aa032gjlZ5u4+fZj/RQKpSt+BZWv+3lMZZFnhfrpQ==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@progress/kendo-react-buttons/-/kendo-react-buttons-13.0.0.tgz", + "integrity": "sha512-+th0uP35OirZ98dU7hAAISCyxOMjSNFYhm+UcYoM9GEra+LzW1Sdr1juwpfQ7V6hBtWo/VS66dnUGSNetW3Zjg==", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { "prop-types": "^15.6.0" }, "peerDependencies": { "@progress/kendo-licensing": "^1.7.0", - "@progress/kendo-react-common": "12.0.2", - "@progress/kendo-react-intl": "12.0.2", - "@progress/kendo-react-popup": "12.0.2", + "@progress/kendo-react-common": "13.0.0", + "@progress/kendo-react-intl": "13.0.0", + "@progress/kendo-react-popup": "13.0.0", "@progress/kendo-svg-icons": "^4.0.0", "@progress/kendo-webspeech-common": "^1.0.1", "react": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", @@ -1157,30 +1158,30 @@ } }, "node_modules/@progress/kendo-react-charts": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/@progress/kendo-react-charts/-/kendo-react-charts-12.0.2.tgz", - "integrity": "sha512-479cUtRhmiuE8dNdfEKVnDFYHBfDGWhWEPZmlQ/LV3wsVZGMW8HVSYGNhrC5zkloG2IZCb9HMgNXqAuJ6fdWnw==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@progress/kendo-react-charts/-/kendo-react-charts-13.0.0.tgz", + "integrity": "sha512-q6ugub8lBskUSA287P3pP8OZoucySFKmH7NjREplVldva8b8hRx55Ii7CyLqQU8+sNgifqFzIJ1ReYcROYsauA==", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "@progress/kendo-charts": "2.8.0", + "@progress/kendo-charts": "2.9.0", "prop-types": "^15.6.0" }, "peerDependencies": { "@progress/kendo-drawing": "^1.21.2", "@progress/kendo-licensing": "^1.7.0", - "@progress/kendo-react-common": "12.0.2", - "@progress/kendo-react-intl": "12.0.2", - "@progress/kendo-react-layout": "12.0.2", - "@progress/kendo-react-popup": "12.0.2", + "@progress/kendo-react-common": "13.0.0", + "@progress/kendo-react-intl": "13.0.0", + "@progress/kendo-react-layout": "13.0.0", + "@progress/kendo-react-popup": "13.0.0", "@progress/kendo-svg-icons": "^4.0.0", "react": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "node_modules/@progress/kendo-react-common": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/@progress/kendo-react-common/-/kendo-react-common-12.0.2.tgz", - "integrity": "sha512-+YP+Ao7hC8ywA7A19IsroGCB8jadA6VfaaGZOWNl8mOmvvFgb0DmswNBvaqMaYow19n+l727KGcGoz9HUvbsWw==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@progress/kendo-react-common/-/kendo-react-common-13.0.0.tgz", + "integrity": "sha512-QFuwyX9Dcl6fE1J5xU8aCod05dr8Wfq3uf9SZkpBiQmNwalfe+lRVecYupxC0InLlVLPGq1/vevZ1QOpdXQ84g==", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { "@progress/kendo-draggable-common": "^0.2.3", @@ -1194,33 +1195,33 @@ } }, "node_modules/@progress/kendo-react-conversational-ui": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/@progress/kendo-react-conversational-ui/-/kendo-react-conversational-ui-12.0.2.tgz", - "integrity": "sha512-/cr/9JweQJaB8MYWmCL6pw+vii7+6vWT1VeC9wPwYpPURsHDjC3sNDYEwlz62wUzgOtZCL0RD2baWL5iic+jBg==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@progress/kendo-react-conversational-ui/-/kendo-react-conversational-ui-13.0.0.tgz", + "integrity": "sha512-h9aLGqvYwYevxT6jbaJRKv2moeaRoPc3kpKJ8QEqUdzO3xLvIpR+djhb44AhhucLHDmizJfi+X7nXQWYjNldpg==", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { "prop-types": "^15.6.0" }, "peerDependencies": { "@progress/kendo-licensing": "^1.7.0", - "@progress/kendo-react-animation": "12.0.2", - "@progress/kendo-react-buttons": "12.0.2", - "@progress/kendo-react-common": "12.0.2", - "@progress/kendo-react-inputs": "12.0.2", - "@progress/kendo-react-intl": "12.0.2", - "@progress/kendo-react-layout": "12.0.2", - "@progress/kendo-react-notification": "12.0.2", - "@progress/kendo-react-popup": "12.0.2", - "@progress/kendo-react-upload": "12.0.2", + "@progress/kendo-react-animation": "13.0.0", + "@progress/kendo-react-buttons": "13.0.0", + "@progress/kendo-react-common": "13.0.0", + "@progress/kendo-react-inputs": "13.0.0", + "@progress/kendo-react-intl": "13.0.0", + "@progress/kendo-react-layout": "13.0.0", + "@progress/kendo-react-notification": "13.0.0", + "@progress/kendo-react-popup": "13.0.0", + "@progress/kendo-react-upload": "13.0.0", "@progress/kendo-svg-icons": "^4.0.0", "react": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "node_modules/@progress/kendo-react-dialogs": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/@progress/kendo-react-dialogs/-/kendo-react-dialogs-12.0.2.tgz", - "integrity": "sha512-D96aGoiWvjEVlEHtIe5c21IN3cBHD21rgjsqZkwdaWYHITE3CgI9GQSSi5tDf7RHx/Cs2hPhx784KKNon0aCPw==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@progress/kendo-react-dialogs/-/kendo-react-dialogs-13.0.0.tgz", + "integrity": "sha512-yqVbVDvw1OBO8hRm9kdG0NgDXaNtnqCN9l5EeG2IgakhjkMGeuzHZu9bX5wwf1CLz+gRCegx1sNgXao45vjdEQ==", "license": "SEE LICENSE IN LICENSE.md", "peer": true, "dependencies": { @@ -1228,18 +1229,18 @@ }, "peerDependencies": { "@progress/kendo-licensing": "^1.7.0", - "@progress/kendo-react-buttons": "12.0.2", - "@progress/kendo-react-common": "12.0.2", - "@progress/kendo-react-intl": "12.0.2", + "@progress/kendo-react-buttons": "13.0.0", + "@progress/kendo-react-common": "13.0.0", + "@progress/kendo-react-intl": "13.0.0", "@progress/kendo-svg-icons": "^4.0.0", "react": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "node_modules/@progress/kendo-react-inputs": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/@progress/kendo-react-inputs/-/kendo-react-inputs-12.0.2.tgz", - "integrity": "sha512-YlLsHA4OhcOMzTCdicrVj0avm2DxLZqza5QFpoYlyRezHhlcYRT/0lW2P4znIxz0+LUICz/yMcUJ2lYw8Z2BXQ==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@progress/kendo-react-inputs/-/kendo-react-inputs-13.0.0.tgz", + "integrity": "sha512-wYpjFJ3MmzqqXaTb8hjvLGd5+iNwmf/htAhNw2bH6ABnEj4dpd/0gWdq3htw9eQC3lzcJfKR2rWfFJCecB/gbg==", "license": "SEE LICENSE IN LICENSE.md", "peer": true, "dependencies": { @@ -1249,23 +1250,23 @@ "@progress/kendo-drawing": "^1.21.2", "@progress/kendo-inputs-common": "^3.1.0", "@progress/kendo-licensing": "^1.7.0", - "@progress/kendo-react-animation": "12.0.2", - "@progress/kendo-react-buttons": "12.0.2", - "@progress/kendo-react-common": "12.0.2", - "@progress/kendo-react-dialogs": "12.0.2", - "@progress/kendo-react-intl": "12.0.2", - "@progress/kendo-react-labels": "12.0.2", - "@progress/kendo-react-layout": "12.0.2", - "@progress/kendo-react-popup": "12.0.2", + "@progress/kendo-react-animation": "13.0.0", + "@progress/kendo-react-buttons": "13.0.0", + "@progress/kendo-react-common": "13.0.0", + "@progress/kendo-react-dialogs": "13.0.0", + "@progress/kendo-react-intl": "13.0.0", + "@progress/kendo-react-labels": "13.0.0", + "@progress/kendo-react-layout": "13.0.0", + "@progress/kendo-react-popup": "13.0.0", "@progress/kendo-svg-icons": "^4.0.0", "react": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "node_modules/@progress/kendo-react-intl": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/@progress/kendo-react-intl/-/kendo-react-intl-12.0.2.tgz", - "integrity": "sha512-deFiWuL4tEol7o/asUytTFcucWYU7XDQM5cvFAiJDnI+PQo+Iy0U5fGIB1TcNNZYjBmhs2sG4/ntZ2nrWFniYQ==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@progress/kendo-react-intl/-/kendo-react-intl-13.0.0.tgz", + "integrity": "sha512-WQhy1L98Mc4pPQ0NvYmnMi609dPnq2ksZyTBpKciFkKKCt6DCKbN5mEhziNkX8a8w5nWTWM+xRZFCIRUzYJBdA==", "license": "SEE LICENSE IN LICENSE.md", "peer": true, "dependencies": { @@ -1274,15 +1275,15 @@ "peerDependencies": { "@progress/kendo-intl": "^3.1.1", "@progress/kendo-licensing": "^1.7.0", - "@progress/kendo-react-common": "12.0.2", + "@progress/kendo-react-common": "13.0.0", "react": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "node_modules/@progress/kendo-react-labels": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/@progress/kendo-react-labels/-/kendo-react-labels-12.0.2.tgz", - "integrity": "sha512-fsQuDwJpn0NYEq4zezLrDKa8Q2CKrE0m446V+V0/WyqklDrkktV1glzJt2FV1dXE2suib8w/ZQuWtrPjcgHmkw==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@progress/kendo-react-labels/-/kendo-react-labels-13.0.0.tgz", + "integrity": "sha512-QSDdiIBHUkn6G3JhApE1lRfAZfrozCr+wM7/53Zpa2Pp8exYdKuFaIZUciYoua/+4Tk8RWcSrT2ybS1tWYM20A==", "license": "SEE LICENSE IN LICENSE.md", "peer": true, "dependencies": { @@ -1290,37 +1291,37 @@ }, "peerDependencies": { "@progress/kendo-licensing": "^1.7.0", - "@progress/kendo-react-common": "12.0.2", - "@progress/kendo-react-intl": "12.0.2", + "@progress/kendo-react-common": "13.0.0", + "@progress/kendo-react-intl": "13.0.0", "react": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "node_modules/@progress/kendo-react-layout": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/@progress/kendo-react-layout/-/kendo-react-layout-12.0.2.tgz", - "integrity": "sha512-A9hElW767JHW3sQTuQevyYd5tqKWoW/dPDfzLAKYy0VitC16OMAxhN57bQUzjerMTIZjjhkACYoMbEBPoy2PBQ==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@progress/kendo-react-layout/-/kendo-react-layout-13.0.0.tgz", + "integrity": "sha512-VK2D9K1BCK1G/0B6H0AF9P3H88xFVDTFJtQzmY3ewgNq+EKLrTpeoiOwfjwJuxBvdxJ6RSBzuR7vPblQ1L0vWg==", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { "prop-types": "^15.6.0" }, "peerDependencies": { "@progress/kendo-licensing": "^1.7.0", - "@progress/kendo-react-animation": "12.0.2", - "@progress/kendo-react-buttons": "12.0.2", - "@progress/kendo-react-common": "12.0.2", - "@progress/kendo-react-intl": "12.0.2", - "@progress/kendo-react-popup": "12.0.2", - "@progress/kendo-react-progressbars": "12.0.2", + "@progress/kendo-react-animation": "13.0.0", + "@progress/kendo-react-buttons": "13.0.0", + "@progress/kendo-react-common": "13.0.0", + "@progress/kendo-react-intl": "13.0.0", + "@progress/kendo-react-popup": "13.0.0", + "@progress/kendo-react-progressbars": "13.0.0", "@progress/kendo-svg-icons": "^4.0.0", "react": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "node_modules/@progress/kendo-react-notification": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/@progress/kendo-react-notification/-/kendo-react-notification-12.0.2.tgz", - "integrity": "sha512-MTjkdaqrWezg52NM92vNbiLVf7aKMZKgNBQoJrLscwGDsVX06Z8KDg3fa1ZM6w57tLyMpwKksSQfyRWKpAAcug==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@progress/kendo-react-notification/-/kendo-react-notification-13.0.0.tgz", + "integrity": "sha512-XrLvHEFQPUlbukCqOYwEGjj4RJNP/Gzi6ea0rPsO27vgipMBffp7uFtiVfEAOmKRbueDm3GN+NGGFq5ceIdKOQ==", "license": "SEE LICENSE IN LICENSE.md", "peer": true, "dependencies": { @@ -1328,16 +1329,16 @@ }, "peerDependencies": { "@progress/kendo-licensing": "^1.7.0", - "@progress/kendo-react-common": "12.0.2", + "@progress/kendo-react-common": "13.0.0", "@progress/kendo-svg-icons": "^4.0.0", "react": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "node_modules/@progress/kendo-react-popup": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/@progress/kendo-react-popup/-/kendo-react-popup-12.0.2.tgz", - "integrity": "sha512-ptT/CtE6IyBSjpg3cGZnvT/d1n3mXVws2IGp0pfw05KxWD/bvS1wXG3ENIfFGVpcDSBf3+Ak5A/P8IQ3xu6ghg==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@progress/kendo-react-popup/-/kendo-react-popup-13.0.0.tgz", + "integrity": "sha512-5xkrPuqSQNx9kn5z46ItG+kRTyn+ZQ/biMSPqlz/Y3HSBNBeiZX2GitXHJWzebeIfRKb2ccg9N1u98nrwT9Q7Q==", "license": "SEE LICENSE IN LICENSE.md", "peer": true, "dependencies": { @@ -1345,16 +1346,16 @@ }, "peerDependencies": { "@progress/kendo-licensing": "^1.7.0", - "@progress/kendo-popup-common": "^1.9.0", - "@progress/kendo-react-common": "12.0.2", + "@progress/kendo-popup-common": "^1.9.5", + "@progress/kendo-react-common": "13.0.0", "react": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "node_modules/@progress/kendo-react-progressbars": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/@progress/kendo-react-progressbars/-/kendo-react-progressbars-12.0.2.tgz", - "integrity": "sha512-+vVQmmGD4oVcpCjLSUNoDDl4L9uP9sqK9fyUNugIDSFdl1FsfQSW4kQARcQdRVK4jjqWGuDtUm16heLBDpehNg==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@progress/kendo-react-progressbars/-/kendo-react-progressbars-13.0.0.tgz", + "integrity": "sha512-rhFasI/sRi84Q9QpXw3b6xON+nmIvu5k4sUC2P2GJ1tbZcLjNewffinu/n2xm0GFvDMMJi9G3uiZyq2pWLMXhg==", "license": "SEE LICENSE IN LICENSE.md", "peer": true, "dependencies": { @@ -1362,16 +1363,16 @@ }, "peerDependencies": { "@progress/kendo-licensing": "^1.7.0", - "@progress/kendo-react-animation": "12.0.2", - "@progress/kendo-react-common": "12.0.2", + "@progress/kendo-react-animation": "13.0.0", + "@progress/kendo-react-common": "13.0.0", "react": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "node_modules/@progress/kendo-react-upload": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/@progress/kendo-react-upload/-/kendo-react-upload-12.0.2.tgz", - "integrity": "sha512-6K05UTDS9ljNWwb6NPhAX4lXhqQjLSmTwvCddUl+ZLj0E7W2OBI142rJEgKINfXiscGl129mVYtyVZ7NZee3hg==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@progress/kendo-react-upload/-/kendo-react-upload-13.0.0.tgz", + "integrity": "sha512-lK/ptL32+zS2JVRkryI9fS9UCgJ3yhTU2V0HAOXZf9o5XuUq0z33mCWeYzCEo1WfU6syLQszmdWighssNUeLRw==", "license": "SEE LICENSE IN LICENSE.md", "peer": true, "dependencies": { @@ -1379,10 +1380,10 @@ }, "peerDependencies": { "@progress/kendo-licensing": "^1.7.0", - "@progress/kendo-react-buttons": "12.0.2", - "@progress/kendo-react-common": "12.0.2", - "@progress/kendo-react-intl": "12.0.2", - "@progress/kendo-react-progressbars": "12.0.2", + "@progress/kendo-react-buttons": "13.0.0", + "@progress/kendo-react-common": "13.0.0", + "@progress/kendo-react-intl": "13.0.0", + "@progress/kendo-react-progressbars": "13.0.0", "@progress/kendo-svg-icons": "^4.0.0", "axios": "^1.7.4", "react": "^16.8.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", @@ -1396,29 +1397,29 @@ "license": "Apache-2.0" }, "node_modules/@progress/kendo-theme-bootstrap": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/@progress/kendo-theme-bootstrap/-/kendo-theme-bootstrap-12.0.1.tgz", - "integrity": "sha512-AymTtRHwYF0OR50k2xkaHXmt0Cu4SkLzHfNtxElUOrmVwnEv9/HpKAKSEP/qLIOQjM6nnweOesna2PH+mkwhKg==", + "version": "12.3.0-dev.1", + "resolved": "https://registry.npmjs.org/@progress/kendo-theme-bootstrap/-/kendo-theme-bootstrap-12.3.0-dev.1.tgz", + "integrity": "sha512-ETHeOIj9vGepL+FxNeXPAdszkDQZV5ctqoxE3H6Om7ru6nYVXQ6hHbnTtSJp/KHMr1DeHO3141M4haTzzCwVRA==", "license": "Apache-2.0", "dependencies": { "@progress/kendo-svg-icons": "^4.5.0", - "@progress/kendo-theme-core": "12.0.1", - "@progress/kendo-theme-utils": "12.0.1" + "@progress/kendo-theme-core": "12.3.0-dev.1", + "@progress/kendo-theme-utils": "12.3.0-dev.1" } }, "node_modules/@progress/kendo-theme-core": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/@progress/kendo-theme-core/-/kendo-theme-core-12.0.1.tgz", - "integrity": "sha512-Zn8J+grubbJJjyrOimkMswhZNYqZtglZMf+OTVc54igsyHI42e+ylJZIeE7odzW97S3FU2Kdwxvr9I8wa52OvQ==", + "version": "12.3.0-dev.1", + "resolved": "https://registry.npmjs.org/@progress/kendo-theme-core/-/kendo-theme-core-12.3.0-dev.1.tgz", + "integrity": "sha512-msE4hDnAP1o39soCA5Zmfsgx2leOH0uoHUY2+QsIDksZV0kiQw7At5ZEjyrQzQgvCtu8B8EPZRCnIYS51/eUzg==", "license": "Apache-2.0" }, "node_modules/@progress/kendo-theme-utils": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/@progress/kendo-theme-utils/-/kendo-theme-utils-12.0.1.tgz", - "integrity": "sha512-n7tMBzi/C5MezbAuhdwBImlL3ilv1+5eXStSHatcmV8wCQR8DvqkYZazVEp+6KVCk2rbnn+clQcN7iAowhLdiQ==", + "version": "12.3.0-dev.1", + "resolved": "https://registry.npmjs.org/@progress/kendo-theme-utils/-/kendo-theme-utils-12.3.0-dev.1.tgz", + "integrity": "sha512-+y32JdJsBY5Qulkt8Kg3coCqGW0n1erbfnJmW3HJhwGgimCD/2gcjI4nAV5H5npDSpF037YJ8iOgY6hwKRnQLA==", "license": "Apache-2.0", "dependencies": { - "@progress/kendo-theme-core": "12.0.1" + "@progress/kendo-theme-core": "12.3.0-dev.1" } }, "node_modules/@progress/kendo-webspeech-common": { @@ -2162,9 +2163,9 @@ "peer": true }, "node_modules/axios": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", - "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", "license": "MIT", "peer": true, "dependencies": { @@ -2935,9 +2936,9 @@ } }, "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "license": "MIT", "peer": true, "dependencies": { diff --git a/client/package.json b/client/package.json index 177a3fd..1bfbe01 100644 --- a/client/package.json +++ b/client/package.json @@ -13,13 +13,13 @@ }, "dependencies": { "@progress/kendo-licensing": "^1.7.1", - "@progress/kendo-react-buttons": "^12.0.2", - "@progress/kendo-react-charts": "^12.0.2", - "@progress/kendo-react-common": "^12.0.2", - "@progress/kendo-react-conversational-ui": "^12.0.2", - "@progress/kendo-react-layout": "^12.0.2", - "@progress/kendo-theme-bootstrap": "^12.0.1", - "@progress/kendo-theme-utils": "^12.0.1", + "@progress/kendo-react-buttons": "^13.0.0", + "@progress/kendo-react-charts": "^13.0.0", + "@progress/kendo-react-common": "^13.0.0", + "@progress/kendo-react-conversational-ui": "^13.0.0", + "@progress/kendo-react-layout": "^13.0.0", + "@progress/kendo-theme-bootstrap": "^12.3.0-dev.1", + "@progress/kendo-theme-utils": "^12.3.0-dev.1", "@types/react-syntax-highlighter": "^15.5.13", "react": "^19.1.1", "react-dom": "^19.1.1", diff --git a/client/public/background.svg b/client/public/background.svg new file mode 100644 index 0000000..599de01 --- /dev/null +++ b/client/public/background.svg @@ -0,0 +1,12 @@ + + +
+
+ + + + + + + +
diff --git a/client/public/book-open.svg b/client/public/book-open.svg new file mode 100644 index 0000000..2a52740 --- /dev/null +++ b/client/public/book-open.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/client/public/bot.svg b/client/public/bot.svg new file mode 100644 index 0000000..a5031c5 --- /dev/null +++ b/client/public/bot.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/client/public/chart-area.svg b/client/public/chart-area.svg new file mode 100644 index 0000000..49e33fd --- /dev/null +++ b/client/public/chart-area.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/client/public/drawer-user.svg b/client/public/drawer-user.svg new file mode 100644 index 0000000..d9b0f1f --- /dev/null +++ b/client/public/drawer-user.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/client/public/fonts/Metric-Light.woff2 b/client/public/fonts/Metric-Light.woff2 new file mode 100755 index 0000000..d315146 Binary files /dev/null and b/client/public/fonts/Metric-Light.woff2 differ diff --git a/client/public/fonts/Metric-Medium.woff2 b/client/public/fonts/Metric-Medium.woff2 new file mode 100755 index 0000000..951aa59 Binary files /dev/null and b/client/public/fonts/Metric-Medium.woff2 differ diff --git a/client/public/fonts/Metric-Regular.woff2 b/client/public/fonts/Metric-Regular.woff2 new file mode 100755 index 0000000..b748065 Binary files /dev/null and b/client/public/fonts/Metric-Regular.woff2 differ diff --git a/client/public/fonts/Metric-Semibold.woff2 b/client/public/fonts/Metric-Semibold.woff2 new file mode 100755 index 0000000..a9bb193 Binary files /dev/null and b/client/public/fonts/Metric-Semibold.woff2 differ diff --git a/client/public/new-chat.svg b/client/public/new-chat.svg new file mode 100644 index 0000000..1df4b69 --- /dev/null +++ b/client/public/new-chat.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/client/public/progress-logo-compact.svg b/client/public/progress-logo-compact.svg new file mode 100644 index 0000000..8572539 --- /dev/null +++ b/client/public/progress-logo-compact.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/progress-logo.svg b/client/public/progress-logo.svg new file mode 100644 index 0000000..26f1bdc --- /dev/null +++ b/client/public/progress-logo.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/client/public/scan-search.svg b/client/public/scan-search.svg new file mode 100644 index 0000000..3825f8f --- /dev/null +++ b/client/public/scan-search.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/client/public/search.svg b/client/public/search.svg new file mode 100644 index 0000000..2721c02 --- /dev/null +++ b/client/public/search.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/share.svg b/client/public/share.svg new file mode 100644 index 0000000..2679d3b --- /dev/null +++ b/client/public/share.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/client/public/sparkles.svg b/client/public/sparkles.svg new file mode 100644 index 0000000..fe8b726 --- /dev/null +++ b/client/public/sparkles.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/client/public/vectors.svg b/client/public/vectors.svg new file mode 100644 index 0000000..f841519 --- /dev/null +++ b/client/public/vectors.svg @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/App.tsx b/client/src/App.tsx index f332bba..f9c15d2 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,9 +1,10 @@ import { HashRouter, Route, Routes } from "react-router-dom"; import AppBarComponent from "./components/AppBarComponent"; -import DrawerComponent from "./components/DrawerComponent"; import Home from "./pages/Home"; import KnowledgeAssistant from "./pages/KnowledgeAssistant"; import FinanceAnalysis from "./pages/FinanceAnalysis"; +import AiSearch from "./pages/AiSearch"; +import ValueProposition from "./pages/ValueProposition"; export default function App() { @@ -11,13 +12,13 @@ export default function App() { <> - - - } /> - } /> - } /> - - + + } /> + } /> + } /> + } /> + } /> + ) diff --git a/client/src/components/AppBarComponent.tsx b/client/src/components/AppBarComponent.tsx index 8f056b8..f4a709f 100644 --- a/client/src/components/AppBarComponent.tsx +++ b/client/src/components/AppBarComponent.tsx @@ -1,87 +1,204 @@ -import { AppBar, AppBarSection, AppBarSpacer } from "@progress/kendo-react-layout"; -import { Button } from "@progress/kendo-react-buttons"; -import { SvgIcon } from "@progress/kendo-react-common"; -import { useNavigate } from 'react-router-dom'; +import { useState, useRef, useEffect } from "react"; import { - searchIcon, - homeIcon, - chartLineStackedMarkersIcon, - sparklesIcon -} from "@progress/kendo-svg-icons"; + AppBar, + AppBarSection, + AppBarSpacer, +} from "@progress/kendo-react-layout"; +import { Popup } from "@progress/kendo-react-popup"; +import { useLocation, useNavigate } from "react-router-dom"; + +const imgProgressLogo = `${import.meta.env.BASE_URL}progress-logo.svg`; +const imgProgressLogoCompact = `${import.meta.env.BASE_URL}progress-logo-compact.svg`; export default function AppBarComponent() { + const location = useLocation(); const navigate = useNavigate(); + const isHomePage = location.pathname === "/"; + const [showMenu, setShowMenu] = useState(false); + const [isMobile, setIsMobile] = useState(false); + const menuButtonRef = useRef(null); + + useEffect(() => { + const handleResize = () => { + setIsMobile(window.innerWidth < 1024); + if (window.innerWidth >= 1024) { + setShowMenu(false); + } + }; + + handleResize(); + window.addEventListener("resize", handleResize); + return () => window.removeEventListener("resize", handleResize); + }, []); + + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if ( + showMenu && + menuButtonRef.current && + !menuButtonRef.current.contains(event.target as Node) + ) { + const popup = document.querySelector(".mobile-menu-popup"); + if (popup && !popup.contains(event.target as Node)) { + setShowMenu(false); + } + } + }; - const handleHomeClick = () => { - navigate('/'); + if (showMenu) { + document.addEventListener("mousedown", handleClickOutside); + } + + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, [showMenu]); + + const navItems = [ + { label: "Intelligent Search", path: "/ai-search" }, + { label: "Finance Analysis", path: "/finance-analysis" }, + { label: "Knowledge Assistant", path: "/knowledge-assistant" }, + { label: "Agentic RAG Value", path: "/value-proposition" }, + ]; + + const handleNavClick = (path: string) => { + navigate(path); + setShowMenu(false); }; - const handleSearchClick = () => { - navigate('/knowledge-assistant'); - } + const handleLogoClick = () => { + navigate("/"); + }; + + const toggleMenu = () => { + setShowMenu(!showMenu); + }; - const handleChartClick = () => { - navigate('/finance-analysis'); + if (isHomePage) { + return ( + + +
+ Progress Logo +
+

+ Progress Agentic RAG + Telerik DevTools +

+
+
+ ); } return ( -
-
- +
+ Progress Logo
-

- Kendo + Progress Agentic RAG Demo -

+ + Agentic RAG + Telerik DevTools +
-
-
+ {!isMobile ? ( +
+ {navItems.map((item) => ( + handleNavClick(item.path)} + > + {item.label} + + ))} +
+ ) : ( + <> +
+ MENU + + + + + +
+ +
+ {navItems.map((item) => ( +
handleNavClick(item.path)} + > + {item.label} +
+ ))} +
+
+ + )}
); -} \ No newline at end of file +} diff --git a/client/src/components/ChatHeader.tsx b/client/src/components/ChatHeader.tsx new file mode 100644 index 0000000..e5dcb86 --- /dev/null +++ b/client/src/components/ChatHeader.tsx @@ -0,0 +1,37 @@ +import React from "react"; +import { type Message } from "@progress/kendo-react-conversational-ui"; +import { Button } from "@progress/kendo-react-buttons"; + +interface ChatHeaderTemplateProps { + messages: Message[]; +} + +/** + * Reusable header template for the Chat component. + * Displays the first user question as plain text in the header. + */ +const ChatHeaderTemplate: React.FC = ({ + messages, +}) => { + const shareIcon = `${import.meta.env.BASE_URL}share.svg`; + // Find the first user message (skip the initial bot message) + const firstUserMessage = React.useMemo(() => { + return messages.find((msg) => msg.author.id === 1); // User ID is 1 + }, [messages]); + + // Don't render anything if there's no user message yet + if (!firstUserMessage || !firstUserMessage.text) { + return null; + } + + return ( +
+ {firstUserMessage.text} + +
+ ); +}; + +export default ChatHeaderTemplate; diff --git a/client/src/components/ChatMessage.tsx b/client/src/components/ChatMessage.tsx index 700ecbc..a15fd5a 100644 --- a/client/src/components/ChatMessage.tsx +++ b/client/src/components/ChatMessage.tsx @@ -1,190 +1,47 @@ -import React, { useState } from 'react'; -import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; -import { oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism'; -import { Button } from '@progress/kendo-react-buttons'; -import { SvgIcon } from '@progress/kendo-react-common'; -import { copyIcon } from '@progress/kendo-svg-icons'; +import React from 'react'; import type { ChatMessageTemplateProps } from '@progress/kendo-react-conversational-ui'; +import { renderMarkdown } from '../utils/markdownRenderer'; const ChatMessage: React.FC = ({ item }) => { // Determine if this message is from the sender (user) or bot const isSenderMessage = item.author.id === 1; // User ID is 1, Bot ID is 0 - - // State for tracking copied status - const [copiedStates, setCopiedStates] = useState<{ [key: number]: boolean }>({}); - - // Copy function - const copyToClipboard = async (code: string, index: number) => { - try { - await navigator.clipboard.writeText(code); - setCopiedStates(prev => ({ ...prev, [index]: true })); - // Reset the copied state after 2 seconds - setTimeout(() => { - setCopiedStates(prev => ({ ...prev, [index]: false })); - }, 2000); - } catch (err) { - console.error('Failed to copy code:', err); - } - }; - - // Define styling classes based on message author - const messageClasses = isSenderMessage - ? "k-chat-message-text k-bg-primary k-text-surface k-border k-border-solid k-border-primary-emphasis k-p-4 k-rounded-lg" - : "k-chat-message-text k-bg-secondary-subtle k-border k-border-solid k-border-secondary-subtle k-p-4 k-rounded-lg"; - - const parseMessage = (text: string) => { - // Split the text by code blocks (```language\ncode\n```) - const codeBlockRegex = /```(\w+)?\n?([\s\S]*?)```/g; - const parts: (string | { type: 'code'; language: string; content: string })[] = []; - let lastIndex = 0; - let match; - - while ((match = codeBlockRegex.exec(text)) !== null) { - // Add text before the code block - if (match.index > lastIndex) { - const beforeText = text.slice(lastIndex, match.index); - if (beforeText.trim()) { - parts.push(beforeText); - } - } - - // Add the code block - const language = match[1] || 'text'; - const content = match[2].trim(); - parts.push({ - type: 'code', - language, - content - }); - - lastIndex = match.index + match[0].length; - } - - // Add remaining text after the last code block - if (lastIndex < text.length) { - const remainingText = text.slice(lastIndex); - if (remainingText.trim()) { - parts.push(remainingText); - } - } - - return parts; - }; - - const renderInlineCode = (text: string) => { - // Handle inline code with `code` - const inlineCodeRegex = /`([^`]+)`/g; - const parts = []; - let lastIndex = 0; - let match; - while ((match = inlineCodeRegex.exec(text)) !== null) { - // Add text before inline code - if (match.index > lastIndex) { - parts.push(text.slice(lastIndex, match.index)); - } + const renderContent = () => { + if (!item.text) return null; - // Add inline code with adaptive styling - parts.push( - - {match[1]} - + // For bot messages, use markdown renderer with design system styling + if (!isSenderMessage) { + const markdownElements = renderMarkdown(item.text); + return ( +
+ {markdownElements} +
); - - lastIndex = match.index + match[0].length; } - // Add remaining text - if (lastIndex < text.length) { - parts.push(text.slice(lastIndex)); - } - - return parts; + // For user messages, render with design styling + return ( +

+ {item.text} +

+ ); }; - const renderContent = () => { - if (!item.text) return null; - - const parts = parseMessage(item.text); - - return parts.map((part, index) => { - if (typeof part === 'string') { - // Handle inline code in regular text - const inlineCodeParts = renderInlineCode(part); - return ( - - {inlineCodeParts.map((inlinePart, inlineIndex) => ( - - {inlinePart} - - ))} - - ); - } else if (part.type === 'code') { - // Render code block with syntax highlighting - const syntaxTheme = oneLight; - - return ( -
-
-
- {part.language} - -
- - {part.content} - -
-
- ); - } - return null; - }); - }; + // Apply different styling for user vs bot messages + if (isSenderMessage) { + return ( +
+
+ {renderContent()} +
+
+ ); + } + // Bot messages - no background, just text return (
-
+
{renderContent()}
diff --git a/client/src/components/ChatMessageBox.tsx b/client/src/components/ChatMessageBox.tsx new file mode 100644 index 0000000..7218d75 --- /dev/null +++ b/client/src/components/ChatMessageBox.tsx @@ -0,0 +1,80 @@ +import React from "react"; +import type { ChatMessageBoxProps, ChatSuggestion } from "@progress/kendo-react-conversational-ui"; +import type { TextAreaChangeEvent } from "@progress/kendo-react-inputs"; +import SearchInput from "./SearchInput"; +import SearchPill from "./SearchPill"; + +interface ChatMessageBoxAdapterProps extends ChatMessageBoxProps { + isLoading?: boolean; + onSendMessage?: (text: string) => void; + suggestions?: ChatSuggestion[]; + onSuggestionClick?: (suggestion: ChatSuggestion) => void; + placeholder?: string; + forceOneRow?: boolean; +} + +export const ChatMessageBox: React.FC = ({ + isLoading = false, + onSendMessage, + suggestions = [], + onSuggestionClick, + placeholder = 'Type a message...', + forceOneRow = false +}) => { + const [inputValue, setInputValue] = React.useState(''); + + const handleChange = (event: TextAreaChangeEvent) => { + setInputValue(String(event.value || '')); + }; + + const handleKeyPress = (event: React.KeyboardEvent) => { + if (event.key === 'Enter' && !event.shiftKey) { + event.preventDefault(); + handleSend(); + } + }; + + const handleSend = () => { + if (inputValue.trim() && onSendMessage) { + onSendMessage(inputValue); + setInputValue(''); + } + }; + + const handleSuggestionClick = (suggestion: ChatSuggestion) => { + if (onSuggestionClick && !isLoading) { + onSuggestionClick(suggestion); + } + }; + + return ( +
+ + + {suggestions.length > 0 && ( +
+ {suggestions.map((suggestion) => ( + handleSuggestionClick(suggestion)} + disabled={isLoading} + /> + ))} +
+ )} +
+ ); +}; + +export default ChatMessageBox; diff --git a/client/src/components/CodeBlockWithCopy.tsx b/client/src/components/CodeBlockWithCopy.tsx new file mode 100644 index 0000000..e420340 --- /dev/null +++ b/client/src/components/CodeBlockWithCopy.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import { Button } from '@progress/kendo-react-buttons'; +import { SvgIcon } from '@progress/kendo-react-common'; +import { copyIcon } from '@progress/kendo-svg-icons'; + +interface CodeBlockWithCopyProps { + code: string; + blockKey: string; +} + +const CodeBlockWithCopy: React.FC = ({ code, blockKey }) => { + const [copied, setCopied] = React.useState(false); + + const handleCopy = async () => { + try { + await navigator.clipboard.writeText(code); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch (err) { + console.error('Failed to copy code:', err); + } + }; + + return ( +
+
+
+          {code}
+        
+ +
+
+ ); +}; + +export default CodeBlockWithCopy; diff --git a/client/src/components/DrawerComponent.tsx b/client/src/components/DrawerComponent.tsx index 32dc64c..532684a 100644 --- a/client/src/components/DrawerComponent.tsx +++ b/client/src/components/DrawerComponent.tsx @@ -1,15 +1,22 @@ import React, { useState, useEffect } from "react"; -import { Drawer, DrawerContent, DrawerNavigation } from "@progress/kendo-react-layout"; -import { SvgIcon } from "@progress/kendo-react-common"; -import { folderIcon, searchIcon, chartLineStackedMarkersIcon } from "@progress/kendo-svg-icons"; -import type { To } from 'react-router-dom'; -import { useLocation, useNavigate } from 'react-router-dom'; +import { + Drawer, + DrawerContent, + DrawerNavigation, +} from "@progress/kendo-react-layout"; +import type { To } from "react-router-dom"; +import { useLocation, useNavigate } from "react-router-dom"; +import { Avatar } from "@progress/kendo-react-layout"; +const userImg = `${import.meta.env.BASE_URL}drawer-user.svg`; +const searchImg = `${import.meta.env.BASE_URL}search.svg`; +const chatImg = `${import.meta.env.BASE_URL}new-chat.svg`; +const libraryImg = `${import.meta.env.BASE_URL}book-open.svg`; const drawerItems = [ - { text: "Home", svgIcon: folderIcon, route: "/", selected: true }, - { text: "Knowledge Assistant", svgIcon: searchIcon, route: "/knowledge-assistant" }, - { text: "Finance Analysis", svgIcon: chartLineStackedMarkersIcon, route: "/finance-analysis" }, + { text: "New chat", icon: chatImg, route: "/knowledge-assistant" }, + { text: "Search chats", icon: searchImg, route: "/knowledge-assistant" }, + { text: "Library", icon: libraryImg, route: "/knowledge-assistant" }, ]; interface DrawerComponentProps { @@ -28,12 +35,15 @@ const DrawerComponent: React.FC = ({ children }) => { handleResize(); - window.addEventListener('resize', handleResize); + window.addEventListener("resize", handleResize); - return () => window.removeEventListener('resize', handleResize); + return () => window.removeEventListener("resize", handleResize); }, []); - const onSelect = (e: { itemTarget: { props: { route: To; }; }; itemIndex: React.SetStateAction; }) => { + const onSelect = (e: { + itemTarget: { props: { route: To } }; + itemIndex: React.SetStateAction; + }) => { navigate(e.itemTarget.props.route); }; @@ -52,24 +62,57 @@ const DrawerComponent: React.FC = ({ children }) => { mode="push" onSelect={onSelect} width={220} - className="k-h-full" drawerClassName="k-border-none" > - -
    - {drawerItems.map(item => ( -
    navigate(item.route)} key={item.text} className={`k-drawer-item ${selected === item.text ? 'k-selected' : ''}`}> - - {item.text} + +
    + {drawerItems.map((item) => ( +
    navigate(item.route)} + key={item.text} + className={`k-drawer-item ${ + selected === item.text ? "k-selected" : "" + }`} + > + {item.text} + {item.text} +
    + ))} +
    +
    + + Chats + +
    + How do I get started with KendoReact components? +
    +
    + + What are the best KendoReact components for data + visualization? + +
    +
    + + How to implement theming and styling with KendoReact? + +
    +
    +
    + + User + +
    + John Smith + Manager +
    +
    - ))} -
+
- - {children} - + {children} ); -} +}; -export default DrawerComponent; \ No newline at end of file +export default DrawerComponent; diff --git a/client/src/components/GradientLoader.tsx b/client/src/components/GradientLoader.tsx new file mode 100644 index 0000000..4400ef5 --- /dev/null +++ b/client/src/components/GradientLoader.tsx @@ -0,0 +1,21 @@ +import React from 'react'; + +interface GradientLoaderProps { + title: string; + subtitle: string; +} + +export const GradientLoader: React.FC = ({ title, subtitle }) => { + return ( +
+

+
+

+ {subtitle} +

+

+ ); +}; diff --git a/client/src/components/SearchInput.tsx b/client/src/components/SearchInput.tsx new file mode 100644 index 0000000..28bc17f --- /dev/null +++ b/client/src/components/SearchInput.tsx @@ -0,0 +1,108 @@ +import React, { useState, useEffect } from "react"; +import { TextArea, type TextAreaProps, type TextAreaChangeEvent } from "@progress/kendo-react-inputs"; +import { Button } from "@progress/kendo-react-buttons"; +import { plusIcon, microphoneOutlineIcon, arrowUpIcon } from "@progress/kendo-svg-icons"; + +interface SearchInputProps { + query: TextAreaProps['value']; + onQueryChange: (event: TextAreaChangeEvent) => void; + onKeyPress: (event: React.KeyboardEvent) => void; + onSearchClick: () => void; + isLoading: boolean; + placeholder: string; + forceOneRow?: boolean; +} + +export const SearchInput: React.FC = ({ + query, + onQueryChange, + onKeyPress, + onSearchClick, + isLoading, + placeholder, + forceOneRow = false, +}) => { + const [isMobile, setIsMobile] = useState(false); + + useEffect(() => { + const checkMobile = () => { + setIsMobile(window.innerWidth < 768); + }; + + checkMobile(); + window.addEventListener('resize', checkMobile); + + return () => window.removeEventListener('resize', checkMobile); + }, []); + + return ( +