diff --git a/apps/demos/Demos/Chat/AIAndChatbotIntegration/jQuery/data.js b/apps/demos/Demos/Chat/AIAndChatbotIntegration/jQuery/data.js index ca66557ff1e..8240e9a0e4c 100644 --- a/apps/demos/Demos/Chat/AIAndChatbotIntegration/jQuery/data.js +++ b/apps/demos/Demos/Chat/AIAndChatbotIntegration/jQuery/data.js @@ -3,6 +3,8 @@ const apiVersion = '2024-02-01'; const endpoint = 'https://public-api.devexpress.com/demo-openai'; const apiKey = 'DEMO'; const REGENERATION_TEXT = 'Regeneration...'; +const CHAT_DISABLED_CLASS = 'dx-chat-disabled'; +const ALERT_TIMEOUT = 1000 * 60; const user = { id: 'user', }; diff --git a/apps/demos/Demos/Chat/AIAndChatbotIntegration/jQuery/index.js b/apps/demos/Demos/Chat/AIAndChatbotIntegration/jQuery/index.js index 23c3279605d..861136fb745 100644 --- a/apps/demos/Demos/Chat/AIAndChatbotIntegration/jQuery/index.js +++ b/apps/demos/Demos/Chat/AIAndChatbotIntegration/jQuery/index.js @@ -25,8 +25,8 @@ $(() => { temperature: 0.7, }; - const responseAzure = await chatService.chat.completions.create(params); - const data = { choices: responseAzure.choices }; + const response = await chatService.chat.completions.create(params); + const data = { choices: response.choices }; return data.choices[0].message?.content; } @@ -40,10 +40,23 @@ $(() => { setTimeout(() => { instance.option({ alerts: [] }); - }, 10000); + }, ALERT_TIMEOUT); } - async function processMessageSending() { + function toggleDisabledState(disabled, event) { + instance.element().toggleClass(CHAT_DISABLED_CLASS, disabled); + + if (disabled) { + event?.target.blur(); + } else { + event?.target.focus(); + } + }; + + async function processMessageSending(message, event) { + toggleDisabledState(true, event); + + messages.push({ role: 'user', content: message.text }); instance.option({ typingUsers: [assistant] }); try { @@ -54,15 +67,20 @@ $(() => { messages.push({ role: 'assistant', content: aiResponse }); - renderMessage(aiResponse); + renderAssistantMessage(aiResponse); }, 200); } catch { instance.option({ typingUsers: [] }); + messages.pop(); alertLimitReached(); + } finally { + toggleDisabledState(false, event); } } async function regenerate() { + toggleDisabledState(true); + try { const aiResponse = await getAIResponse(messages.slice(0, -1)); @@ -71,10 +89,12 @@ $(() => { } catch { updateLastMessage(messages.at(-1).content); alertLimitReached(); + } finally { + toggleDisabledState(false); } } - function renderMessage(text) { + function renderAssistantMessage(text) { const message = { id: Date.now(), timestamp: new Date(), @@ -82,17 +102,17 @@ $(() => { text, }; - customStore.push([{ type: 'insert', data: message }]); + dataSource.store().push([{ type: 'insert', data: message }]); } function updateLastMessage(text) { - const { items } = instance.option(); + const items = dataSource.items(); const lastMessage = items.at(-1); const data = { text: text ?? REGENERATION_TEXT, }; - customStore.push([{ + dataSource.store().push([{ type: 'update', key: lastMessage.id, data, @@ -110,6 +130,57 @@ $(() => { return result; } + function onCopyButtonClick(component, text) { + navigator.clipboard?.writeText(text); + + component.option({ icon: 'check' }); + + setTimeout(() => { + component.option({ icon: 'copy' }); + }, 2500); + } + + function onRegenerateButtonClick() { + if (instance.option('alerts').length) { + return; + } + + updateLastMessage(); + regenerate(); + } + + function renderMessageContent(message, element) { + $('