From a3277c74a2eae11807025c4e59c143c0b93264cf Mon Sep 17 00:00:00 2001 From: Emil Petrov Date: Thu, 27 Nov 2025 18:26:33 +0200 Subject: [PATCH 1/2] chore: fix chat scroll --- client/src/pages/FinanceAnalysis.tsx | 9 ++++---- client/src/pages/KnowledgeAssistant.tsx | 4 ++-- client/src/styles/styles.css | 29 +++++++++++++++++++------ 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/client/src/pages/FinanceAnalysis.tsx b/client/src/pages/FinanceAnalysis.tsx index d7bfae2..cb39f0d 100644 --- a/client/src/pages/FinanceAnalysis.tsx +++ b/client/src/pages/FinanceAnalysis.tsx @@ -285,9 +285,10 @@ export default function FinanceAnalysis() { {/* Page Header */} {chatBot.messages.length > 1 && } {/* Conversation Area */} -
+
1 ? "finance-analysis-chat-wrapper-conversation" : ""}`} + className={`k-d-flex k-flex-column k-align-items-center k-h-full ${chatBot.messages.length > 1 ? "finance-analysis-chat-wrapper-conversation" : ""}`} + style={chatBot.messages.length > 1 ? { minHeight: 0 } : { justifyContent: 'flex-end', paddingBottom: '64px' }} > {renderChat()}
@@ -299,9 +300,9 @@ export default function FinanceAnalysis() {
{/* Page Header */} -
+
{/* Left Panel - Chat (393px) */} -
+
{renderChat()}
diff --git a/client/src/pages/KnowledgeAssistant.tsx b/client/src/pages/KnowledgeAssistant.tsx index 93aa0a8..f2b08dd 100644 --- a/client/src/pages/KnowledgeAssistant.tsx +++ b/client/src/pages/KnowledgeAssistant.tsx @@ -60,7 +60,7 @@ const KnowledgeAssistant = () => { )} {hasConversationStarted && } {/* Chat Component */} -
+
{ onSendMessage={chatBot.addNewMessage} placeholder="Try a suggestion or ask about KendoReact" className="k-border-transparent" - height={hasConversationStarted ? "100%" : undefined} + height="100%" messageTemplate={ChatMessage} timestampTemplate={() => null } showUsername={false} diff --git a/client/src/styles/styles.css b/client/src/styles/styles.css index 7ab995b..ff61e43 100644 --- a/client/src/styles/styles.css +++ b/client/src/styles/styles.css @@ -184,7 +184,7 @@ html, body, #root { } .k-drawer-wrapper::after, -.preview .charts-preview:before { +.preview .chat-preview:before { content: ""; display: block; height: 100%; @@ -198,11 +198,12 @@ html, body, #root { border-radius: 815px; pointer-events: none; } -.k-drawer-wrapper::after { +.k-drawer-wrapper::after, +.preview .chat-preview:before { right: 0; } -.preview .charts-preview:before { - left: -60px; +.preview .chat-preview:before { + right: -80px; } .user-selection-wrapper:after, @@ -346,12 +347,11 @@ html, body, #root { display: none; } -.k-chat .k-message-list { +.k-chat .k-message-list-content { justify-content: flex-end; - + min-height: 100%; } - .finance-analysis-chat-default .k-message-list { padding-block: 64px; } @@ -1102,13 +1102,25 @@ html, body, #root { .finance-preview-wrapper { height: calc(100vh - 54px); + overflow: hidden; +} + +.finance-analysis-chat-expanded { + display: flex; + flex-direction: column; + height: 100%; + overflow-y: auto; } + + + .finance-charts-preview { border: 1px solid #FFF; background: rgba(255, 255, 255, 0.50); box-shadow: 0 4px 12px 0 rgba(13, 10, 44, 0.08); backdrop-filter: blur(2px); + overflow-y: auto; } .finance-charts-container { @@ -1210,6 +1222,7 @@ html, body, #root { .knowledge-assistant-conversation { box-sizing: border-box; + min-height: 0; } .knowledge-assistant-conversation-started { @@ -1223,6 +1236,8 @@ html, body, #root { .knowledge-assistant-chat-flex-full { flex: 1; + min-height: 0; + height: 100%; } .knowledge-assistant-chat-flex-none { From bfd2368beb1cb9c6dcc1ac7e721f60058881c04d Mon Sep 17 00:00:00 2001 From: Emil Petrov Date: Thu, 27 Nov 2025 18:26:48 +0200 Subject: [PATCH 2/2] chore: fix chat charts persistance --- client/src/hooks/useChatBot.tsx | 15 +++++++----- client/src/pages/FinanceAnalysis.tsx | 34 ++++++++++++++++++++-------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/client/src/hooks/useChatBot.tsx b/client/src/hooks/useChatBot.tsx index 57c3be9..db132e6 100644 --- a/client/src/hooks/useChatBot.tsx +++ b/client/src/hooks/useChatBot.tsx @@ -17,6 +17,7 @@ export interface StreamingResponse { json?: Record; // For chart data or other structured responses error?: string; incomplete?: boolean; + messageId?: string | number; // ID of the message associated with this response } export interface UseChatBotReturn { @@ -174,9 +175,10 @@ export const useChatBot = (config: ChatBotConfig): UseChatBotReturn => { setMessages(prev => prev.filter(msg => msg.id !== typingMessageId)); // Then add complete response after a tiny delay + const botMessageId = Date.now() + 2; setTimeout(() => { const botMessage: Message = { - id: Date.now() + 2, + id: botMessageId, author: bot, timestamp: new Date(), text: currentAnswer @@ -184,15 +186,16 @@ export const useChatBot = (config: ChatBotConfig): UseChatBotReturn => { setMessages(prev => [...prev, botMessage]); }, 10); + + // Set the final response with the message ID for any additional processing + if (finalResponse) { + finalResponse.messageId = botMessageId; + setLatestResponse(finalResponse); + } } else { // If no response, just remove typing indicator setMessages(prev => prev.filter(msg => msg.id !== typingMessageId)); } - - // Set the final response for any additional processing - if (finalResponse) { - setLatestResponse(finalResponse); - } } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Network error'; diff --git a/client/src/pages/FinanceAnalysis.tsx b/client/src/pages/FinanceAnalysis.tsx index cb39f0d..bb62bbf 100644 --- a/client/src/pages/FinanceAnalysis.tsx +++ b/client/src/pages/FinanceAnalysis.tsx @@ -147,6 +147,8 @@ export default function FinanceAnalysis() { const [selectedCharts, setSelectedCharts] = React.useState([]); const [isChartsExpanded, setIsChartsExpanded] = React.useState(false); + // Map message IDs to their associated charts + const [messageCharts, setMessageCharts] = React.useState>(new Map()); // Predefined suggestions related to financial data const financialSuggestions: ChatSuggestion[] = [ @@ -178,36 +180,48 @@ export default function FinanceAnalysis() { suggestions: financialSuggestions, }); - // Watch for changes in the latest response to update charts + // Associate charts with the latest bot message when response arrives React.useEffect(() => { if ( chatBot.latestResponse?.json?.charts && - Array.isArray(chatBot.latestResponse.json.charts) + Array.isArray(chatBot.latestResponse.json.charts) && + chatBot.latestResponse.messageId ) { const validCharts: BarChartDef[] = chatBot.latestResponse.json.charts .filter(isBarChartDef) .slice(0, 3); - setSelectedCharts(validCharts); - } else { - setSelectedCharts([]); + + if (validCharts.length > 0) { + setMessageCharts(prev => { + const newMap = new Map(prev); + newMap.set(chatBot.latestResponse!.messageId!, validCharts); + return newMap; + }); + setSelectedCharts(validCharts); + } } }, [chatBot.latestResponse, isBarChartDef]); // Custom message template that includes thumbnail when charts are available const customMessageTemplate = React.useCallback((props: ChatMessageTemplateProps) => { const isBot = props.item.author.id !== chatBot.user.id; - const isLatestBotMessage = isBot && props.item.id === chatBot.messages[chatBot.messages.length - 1]?.id; - const hasCharts = selectedCharts.length > 0; + const chartsForThisMessage = messageCharts.get(props.item.id); return (
- {isLatestBotMessage && hasCharts && ( - setIsChartsExpanded(true)} /> + {isBot && chartsForThisMessage && chartsForThisMessage.length > 0 && ( + { + const charts = messageCharts.get(props.item.id); + if (charts) { + setSelectedCharts(charts); + setIsChartsExpanded(true); + } + }} /> )}
); - }, [chatBot.user.id, chatBot.messages, selectedCharts]); + }, [chatBot.user.id, messageCharts]); // Memoized callback for sending messages const handleSendMessage = React.useCallback((text: string) => {