From 0d67f9457b00721457245108a754d028be0debd6 Mon Sep 17 00:00:00 2001 From: "maksat.allakyev" Date: Wed, 11 Dec 2024 17:34:00 +0500 Subject: [PATCH 1/4] Add copy and refresh buttons for AIChat - Assistant messages --- CS/ReportingApp/wwwroot/css/site.css | 6 ++ CS/ReportingApp/wwwroot/js/aiIntegration.js | 107 +++++++++++++++----- 2 files changed, 90 insertions(+), 23 deletions(-) diff --git a/CS/ReportingApp/wwwroot/css/site.css b/CS/ReportingApp/wwwroot/css/site.css index 6b112ea..4604314 100644 --- a/CS/ReportingApp/wwwroot/css/site.css +++ b/CS/ReportingApp/wwwroot/css/site.css @@ -112,3 +112,9 @@ min-height: 100%; line-height: 50px; height: 60px; } + +.dx-chat-messagegroup-alignment-start:last-child .dx-chat-messagebubble:last-child .dx-bubble-button-containder { + display: flex; + gap: 4px; + margin-top: 8px; +} diff --git a/CS/ReportingApp/wwwroot/js/aiIntegration.js b/CS/ReportingApp/wwwroot/js/aiIntegration.js index c376509..e3b1f37 100644 --- a/CS/ReportingApp/wwwroot/js/aiIntegration.js +++ b/CS/ReportingApp/wwwroot/js/aiIntegration.js @@ -1,4 +1,16 @@ -function normilizeAIResponse(text) { + +let lastUserQuery; + +const assistant = { + id: 'assistant', + name: 'Virtual Assistant', +}; + +const user = { + id: 'user', +}; + +function normilizeAIResponse(text) { text = text.replace(/【\d+:\d+†[^\】]+】/g, ""); let html = marked.parse(text); if (/

\.\s*<\/p>\s*$/.test(html)) @@ -6,41 +18,90 @@ return html; } +function copyText(text) { + navigator.clipboard.writeText(text); +} + +async function getAIResponse(text, id) { + const formData = new FormData(); + formData.append('text', text); + formData.append('chatId', id); + lastUserQuery = text; + const response = await fetch(`/AI/GetAnswer`, { + method: 'POST', + body: formData + }); + return await response.text(); +} + +function RenderAssistantMessage(instance, message) { + instance.option({ typingUsers: [] }); + instance.renderMessage({ timestamp: new Date(), text: message, author: assistant.name, id: assistant.id }); +} + +async function refreshAnswer(instance) { + const items = instance.option('items'); + const newItems = items.slice(0, -1); + instance.option({ items: newItems }); + instance.option({ typingUsers: [assistant] }); + const aiResponse = await getAIResponse(lastUserQuery, assistant.id); + setTimeout(() => { + instance.option({ typingUsers: [] }); + RenderAssistantMessage(instance, aiResponse); + }, 200); +} + function createAssistantTab(chatId) { + assistant.id = chatId; const model = { title: 'AI Assistant', - chatId: chatId, showAvatar: false, showUserName: false, showMessageTimestamp: false, - user: { - id: 1, - }, + user: user, messageTemplate: (data, container) => { - if(data.message.author.id === 'Assistant') - return normilizeAIResponse(data.message.text); - return data.message.text; + const { message } = data; + + if (message.author.id && message.author.id !== assistant.id) + return message.text; + + const $textElement = $('

') + .html(normilizeAIResponse(message.text)) + .appendTo(container); + const $buttonContainer = $('
') + .addClass('dx-bubble-button-containder'); + $('
') + .dxButton({ + icon: 'copy', + stylingMode: 'text', + onClick: () => { + const text = $textElement.text(); + copyText(text); + } + }) + .appendTo($buttonContainer); + $('
') + .dxButton({ + icon: 'refresh', + stylingMode: 'text', + onClick: () => { + refreshAnswer(data.component); + }, + }) + .appendTo($buttonContainer); + $buttonContainer.appendTo(container); }, - onMessageEntered: (e) => { + onMessageEntered: async (e) => { const instance = e.component; instance.renderMessage(e.message); + instance.option({ typingUsers: [assistant] }); + const userInput = e.message.text; - const formData = new FormData(); - formData.append('text', e.message.text); - formData.append('chatId', model.chatId); - fetch(`/AI/GetAnswer`, { - method: 'POST', - body: formData - }).then((x) => { - x.text().then((res) => { - instance.renderMessage({ - text: res, - author: { id: 'Assistant' } - }, { id: 'Assistant' }); - }); - }); + var response = await getAIResponse(userInput, assistant.id); + RenderAssistantMessage(instance, response); } }; + return new DevExpress.Analytics.Utils.TabInfo({ text: 'AI Assistant', template: 'dxrd-ai-panel', From 325aef1cf39809998c52214f90da5b4b2896d7e8 Mon Sep 17 00:00:00 2001 From: DevExpressExampleBot Date: Wed, 11 Dec 2024 16:38:59 +0400 Subject: [PATCH 2/4] README auto update [skip ci] --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index dbdef01..35d1804 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -![](https://img.shields.io/endpoint?url=https://codecentral.devexpress.com/api/v1/VersionRange/853003889/24.2.2%2B) [![](https://img.shields.io/badge/Open_in_DevExpress_Support_Center-FF7200?style=flat-square&logo=DevExpress&logoColor=white)](https://supportcenter.devexpress.com/ticket/details/T1252182) [![](https://img.shields.io/badge/📖_How_to_use_DevExpress_Examples-e9f6fc?style=flat-square)](https://docs.devexpress.com/GeneralInformation/403183) [![](https://img.shields.io/badge/💬_Leave_Feedback-feecdd?style=flat-square)](#does-this-example-address-your-development-requirementsobjectives) From 68b32575999c1053d9c82b19fd984d17f0d77492 Mon Sep 17 00:00:00 2001 From: "alexey.kochkin" Date: Thu, 12 Dec 2024 19:46:13 +0400 Subject: [PATCH 3/4] adjust gitignore, bump package versions --- .gitignore | 5 +++++ CS/ReportingApp/package.json | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index a5aba93..58f37a8 100644 --- a/.gitignore +++ b/.gitignore @@ -311,3 +311,8 @@ TesterMetadata.xml package-lock.json .angular/ +**/wwwroot/css/ace +**/wwwroot/css/icons/ +**/wwwroot/css/*bundle.css +**/wwwroot/css/*skeleton-screen.css +**/wwwroot/js/*bundle.js diff --git a/CS/ReportingApp/package.json b/CS/ReportingApp/package.json index f4a7796..3afa505 100644 --- a/CS/ReportingApp/package.json +++ b/CS/ReportingApp/package.json @@ -4,10 +4,10 @@ "license": "MIT", "private": true, "dependencies": { - "@devexpress/analytics-core": "24.2.2-beta", + "@devexpress/analytics-core": "24.2-stable", "bootstrap": "^4.3.1", - "devexpress-reporting": "24.2.2-beta", - "devextreme-dist": "24.2.2-beta", + "devexpress-reporting": "24.2-stable", + "devextreme-dist": "24.2-stable", "marked": "^14.1.3" } } \ No newline at end of file From f15f19c1ff53134e4409d769e68c53fc7e1ef857 Mon Sep 17 00:00:00 2001 From: "maksat.allakyev" Date: Fri, 13 Dec 2024 10:22:40 +0500 Subject: [PATCH 4/4] update images and create assistant for document viewer --- .../Views/Home/DocumentViewer.cshtml | 9 +++++---- web-document-viewer.png | Bin 213613 -> 161829 bytes web-report-designer.png | Bin 327655 -> 150761 bytes 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CS/ReportingApp/Views/Home/DocumentViewer.cshtml b/CS/ReportingApp/Views/Home/DocumentViewer.cshtml index 4b1e667..87f2ecf 100644 --- a/CS/ReportingApp/Views/Home/DocumentViewer.cshtml +++ b/CS/ReportingApp/Views/Home/DocumentViewer.cshtml @@ -2,11 +2,12 @@ @await Html.PartialAsync("_AILayout")