From 1e46d8f93effc9687a1399de7c94537bab0eea1d Mon Sep 17 00:00:00 2001 From: Ida Dittrich Date: Wed, 20 Aug 2025 16:21:13 +0200 Subject: [PATCH] changed styling and organization of messages --- .../DashboardChatAreaMessageItem.tsx | 241 ++++++------- .../DashboardChatAreaMessageList.tsx | 154 +++----- .../DashboardChat.module.css | 41 +-- .../DashboardChatMessages.module.css | 341 ++++++++++++++++++ .../Home/HomeStyles/Dashboard.module.css | 2 +- 5 files changed, 506 insertions(+), 273 deletions(-) create mode 100644 src/components/Dashboard/DashboardChat/DashboardChatAreaStyles/DashboardChatMessages.module.css diff --git a/src/components/Dashboard/DashboardChat/DashboardChatAreaMessageItem.tsx b/src/components/Dashboard/DashboardChat/DashboardChatAreaMessageItem.tsx index 8ee37ab..67dd908 100644 --- a/src/components/Dashboard/DashboardChat/DashboardChatAreaMessageItem.tsx +++ b/src/components/Dashboard/DashboardChat/DashboardChatAreaMessageItem.tsx @@ -1,9 +1,7 @@ -import React, { useState } from "react"; -import { FaDownload } from "react-icons/fa"; -import { MdOutlineRemoveRedEye } from "react-icons/md"; +import React from "react"; import { useFileDownload } from "../../../hooks/useWorkflows"; -import { useLanguage } from "../../../contexts/LanguageContext"; import { Message, Document } from "./dashboardChatAreaTypes"; +import messageStyles from './DashboardChatAreaStyles/DashboardChatMessages.module.css'; interface MessageItemProps { message: Message; @@ -61,9 +59,8 @@ const getFileIcon = (type?: string, ext?: string): string => { return '📄'; }; -const MessageItem: React.FC = ({ message, index, onFilePreview }) => { - const { t } = useLanguage(); - const { downloadFile, isDownloading, error: downloadError } = useFileDownload(); +const MessageItem: React.FC = ({ message, onFilePreview }) => { + const { downloadFile, isDownloading } = useFileDownload(); // Debug: Log what the MessageItem is receiving console.log(`🎭 MessageItem rendering:`, { @@ -75,7 +72,11 @@ const MessageItem: React.FC = ({ message, index, onFilePreview hasDocuments: !!(message.documents), documentsArray: message.documents, documentsLength: message.documents?.length || 0, - documentsCheck: message.documents && message.documents.length > 0 + documentsCheck: message.documents && message.documents.length > 0, + // Timestamp debugging + timestamp: message.timestamp, + hasTimestamp: !!message.timestamp, + timestampType: typeof message.timestamp }); const handleDocumentClick = (document: Document) => { @@ -149,134 +150,120 @@ const MessageItem: React.FC = ({ message, index, onFilePreview console.log(`📭 No documents to render for message ${message.id}`); } + // Format timestamp + const formatTimestamp = (timestamp?: string) => { + console.log(`⏰ formatTimestamp called with:`, { timestamp, type: typeof timestamp, hasValue: !!timestamp }); + + if (!timestamp) { + console.log(`⏰ No timestamp provided, returning empty string`); + return ''; + } + + const date = new Date(timestamp); + console.log(`⏰ Parsed date:`, { date, isValid: !isNaN(date.getTime()) }); + + if (isNaN(date.getTime())) { + console.log(`⏰ Invalid date, returning empty string`); + return ''; + } + + const now = new Date(); + const isToday = date.toDateString() === now.toDateString(); + + let formatted = ''; + if (isToday) { + formatted = date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); + } else { + formatted = date.toLocaleDateString([], { month: 'short', day: 'numeric' }) + ' ' + + date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); + } + + console.log(`⏰ Formatted timestamp:`, { formatted }); + return formatted; + }; + return (
-
+
{message.role === 'user' ? 'You' : message.agentName} - {message.timestamp && ` • ${new Date(message.timestamp).toLocaleTimeString()}`} -
- -
- {message.content || ( - - [No message content] + {message.timestamp && ( + + • {formatTimestamp(message.timestamp)} )}
- {hasDocuments && ( -
-
- 📎 Attached Files ({message.documents!.length}) -
-
- {message.documents!.map((document, docIndex) => { - console.log(`📄 Rendering document ${docIndex + 1}:`, document); - return ( -
handleDocumentClick(document)} - title={`Click to open ${document.name}`} - > - - {getFileIcon(document.type, document.ext)} - -
-
- {document.ext ? `${document.name}.${document.ext}` : document.name} -
- {document.size && ( -
- {formatFileSize(document.size)} +
+
+ {message.content || ( + + [No message content] + + )} +
+ + {hasDocuments && ( +
+
+ 📎 {message.role === 'user' ? 'Uploaded' : 'Attached'} Files ({message.documents!.length}) +
+
+ {message.documents!.map((document, docIndex) => { + console.log(`📄 Rendering document ${docIndex + 1}:`, document); + return ( +
handleDocumentClick(document)} + title={`Click to open ${document.name}`} + > + + {getFileIcon(document.type, document.ext)} + +
+
+ {document.ext ? `${document.name}.${document.ext}` : document.name} +
+ {document.size && ( +
+ {formatFileSize(document.size)} +
+ )}
- )} -
-
- - -
-
- ); - })} -
-
- )} +
+ + +
+
+ ); + })} +
+
+ )} +
); }; diff --git a/src/components/Dashboard/DashboardChat/DashboardChatAreaMessageList.tsx b/src/components/Dashboard/DashboardChat/DashboardChatAreaMessageList.tsx index ba12b51..61760d8 100644 --- a/src/components/Dashboard/DashboardChat/DashboardChatAreaMessageList.tsx +++ b/src/components/Dashboard/DashboardChat/DashboardChatAreaMessageList.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { useApiRequest } from '../../../hooks/useApi'; import MessageItem from './DashboardChatAreaMessageItem'; import { WorkflowMessage, Document, WorkflowState } from './dashboardChatAreaTypes'; +import messageStyles from './DashboardChatAreaStyles/DashboardChatMessages.module.css'; interface MessageListProps { workflowState: WorkflowState; @@ -17,7 +18,7 @@ const transformWorkflowMessage = async (workflowMessage: WorkflowMessage, reques // Use documents directly from the API documents = workflowMessage.documents.map(doc => ({ id: doc.id || doc.fileId, - fileId: parseInt(doc.fileId), + fileId: typeof doc.fileId === 'string' ? parseInt(doc.fileId) : doc.fileId, name: doc.filename, ext: doc.filename.split('.').pop() || 'unknown', type: doc.mimeType, @@ -77,11 +78,12 @@ const transformWorkflowMessage = async (workflowMessage: WorkflowMessage, reques role: workflowMessage.role, agentName: workflowMessage.role === 'user' ? 'You' : 'Assistant', content: possibleContent, - timestamp: workflowMessage.timestamp, + timestamp: workflowMessage.publishedAt || workflowMessage.timestamp, documents: documents }; console.log(`🔄 Transformation result for ${workflowMessage.id}:`, { + role: workflowMessage.role, originalMessage: workflowMessage, originalContent: workflowMessage.content, originalContentType: typeof workflowMessage.content, @@ -89,6 +91,13 @@ const transformWorkflowMessage = async (workflowMessage: WorkflowMessage, reques possibleContentType: typeof possibleContent, transformedContent: transformedMessage.content, transformedContentType: typeof transformedMessage.content, + documentsCount: documents.length, + hasDocuments: documents.length > 0, + // Timestamp debugging + publishedAt: workflowMessage.publishedAt, + timestamp: workflowMessage.timestamp, + finalTimestamp: transformedMessage.timestamp, + hasTimestamp: !!transformedMessage.timestamp, allOriginalKeys: Object.keys(workflowMessage), // Check for alternative field names alternativeFields: { @@ -99,6 +108,14 @@ const transformWorkflowMessage = async (workflowMessage: WorkflowMessage, reques } }); + // Special logging for user messages with documents + if (workflowMessage.role === 'user' && documents.length > 0) { + console.log(`👤📎 USER message with ${documents.length} documents:`, { + messageId: workflowMessage.id, + documents: documents.map(doc => ({ name: doc.name, fileId: doc.fileId, type: doc.type })) + }); + } + return transformedMessage; }; @@ -212,76 +229,23 @@ const MessageList: React.FC = ({ } }, [transformedMessages.length, scrollToBottom]); - const { currentWorkflowId, workflow, isLoading, error } = workflowState; + const { currentWorkflowId, isLoading, error } = workflowState; return ( - <> - {/* Add CSS animations */} - -
+
+
{error && ( -
+
Error: {error}
)} - - {workflow && ( -
- Workflow: {workflow.id} -
- Status: {workflow.status} - {workflow.currentRound && ` (Round ${workflow.currentRound})`} - {/* Show polling indicator */} - {workflow && ['running', 'processing', 'started'].includes(workflow.status) && ( - - 🔄 Live updates (2s) - - )} -
- )} -
+ +
{transformedMessages.map((message, index) => { console.log(`🎨 Rendering transformed message ${message.id}:`, { role: message.role, @@ -302,58 +266,38 @@ const MessageList: React.FC = ({
{(isLoading || isTransforming) && ( -
-

- {isTransforming ? 'Processing messages...' : 'Loading messages...'} -

+
+ {isTransforming ? 'Processing messages...' : 'Loading messages...'}
)} {transformedMessages.length === 0 && !isLoading && !isTransforming && !currentWorkflowId && ( -

+

No workflow selected. Start a conversation to create a new workflow. -

+
)} {transformedMessages.length === 0 && !isLoading && !isTransforming && currentWorkflowId && ( -

+

No messages in this workflow yet. -

+
)} +
+ + {/* Scroll to bottom button - positioned relative to message list container */} +
- - {/* Scroll to bottom button - positioned relative to parent container, not scrollable area */} - - ); }; diff --git a/src/components/Dashboard/DashboardChat/DashboardChatAreaStyles/DashboardChat.module.css b/src/components/Dashboard/DashboardChat/DashboardChatAreaStyles/DashboardChat.module.css index 8157e68..69fb345 100644 --- a/src/components/Dashboard/DashboardChat/DashboardChatAreaStyles/DashboardChat.module.css +++ b/src/components/Dashboard/DashboardChat/DashboardChatAreaStyles/DashboardChat.module.css @@ -56,46 +56,7 @@ grid-column: 2; } -/* Chat Messages */ -.chat_messages { - flex: 1; - padding: 15px; - border-radius: 15px; - margin-bottom: 15px; - min-height: 0; - overflow-y: auto; - overflow-x: hidden; - scroll-behavior: smooth; -} - -.chat_messages::-webkit-scrollbar { - width: 6px; -} - -.chat_messages::-webkit-scrollbar-track { - background: transparent; -} - -.chat_messages::-webkit-scrollbar-thumb { - background: var(--color-gray-disabled); - border-radius: 3px; -} - -.chat_messages::-webkit-scrollbar-thumb:hover { - background: var(--color-gray); -} - -.messages_container { - min-height: 100%; - display: flex; - flex-direction: column; - justify-content: flex-start; -} - -.messages_spacer { - flex: 1; - min-height: 20px; -} +/* Chat Messages styles moved to DashboardChatMessages.module.css */ /* Chat Input */ .chat_input { diff --git a/src/components/Dashboard/DashboardChat/DashboardChatAreaStyles/DashboardChatMessages.module.css b/src/components/Dashboard/DashboardChat/DashboardChatAreaStyles/DashboardChatMessages.module.css new file mode 100644 index 0000000..c2fd999 --- /dev/null +++ b/src/components/Dashboard/DashboardChat/DashboardChatAreaStyles/DashboardChatMessages.module.css @@ -0,0 +1,341 @@ +/* Message-specific styles for DashboardChat components */ + +/* Message List Container - wraps the entire message list and positions scroll button */ +.message_list_container { + position: relative; + height: 100%; + width: 100%; + display: flex; + flex-direction: column; +} + +/* Chat Messages Scrollable Area */ +.chat_messages { + flex: 1; + padding: 15px; + border-radius: 15px; + margin-bottom: 15px; + min-height: 0; + overflow-y: auto; + overflow-x: hidden; + scroll-behavior: smooth; +} + +.chat_messages::-webkit-scrollbar { + width: 6px; +} + +.chat_messages::-webkit-scrollbar-track { + background: transparent; +} + +.chat_messages::-webkit-scrollbar-thumb { + background: var(--color-gray-disabled); + border-radius: 3px; +} + +.chat_messages::-webkit-scrollbar-thumb:hover { + background: var(--color-gray); +} + +/* Messages Container */ +.messages_container { + min-height: 100%; + display: flex; + flex-direction: column; + justify-content: flex-start; + padding: 8px; + gap: 16px; +} + +.messages_spacer { + flex: 1; + min-height: 20px; +} + +/* Message Item Styles - Modern Chat Layout */ +.message_item { + display: flex; + flex-direction: column; + max-width: 80%; + min-width: 10%; + margin-bottom: 4px; + position: relative; +} + +/* Responsive design for smaller screens */ +@media (max-width: 768px) { + .message_item { + max-width: 85%; + min-width: 150px; + } +} + +@media (max-width: 480px) { + .message_item { + max-width: 95%; + min-width: 120px; + } +} + +/* User messages - right aligned */ +.message_item.user { + align-self: flex-end; + align-items: flex-end; +} + +/* Assistant messages - left aligned */ +.message_item.assistant { + align-self: flex-start; + align-items: flex-start; +} + +.message_header { + font-size: 11px; + color: var(--color-gray); + margin-bottom: 4px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + display: flex; + align-items: center; + gap: 6px; +} + +.message_bubble { + padding: 12px 16px; + border-radius: 18px; + position: relative; + word-wrap: break-word; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); + width: 100%; +} + +/* User message bubble */ +.message_bubble.user { + background: linear-gradient(135deg, var(--color-secondary) 0%, var(--color-secondary-hover) 100%); + color: white; + border-bottom-right-radius: 4px; +} + +/* Assistant message bubble */ +.message_bubble.assistant { + background-color: var(--color-surface); + color: var(--color-text); + border: 1px solid var(--color-gray-disabled); + border-bottom-left-radius: 4px; +} + +.message_content { + line-height: 1.4; + white-space: pre-wrap; + font-size: 14px; +} + +.message_timestamp { + font-size: 10px; + color: var(--color-gray); + margin-top: 4px; + opacity: 0.7; +} + +.message_timestamp_inline { + font-size: 10px; + color: var(--color-gray); + opacity: 0.8; + font-weight: 400; + text-transform: none; + letter-spacing: normal; +} + +.message_no_content { + color: var(--color-gray); + font-style: italic; +} + +/* Document/File Attachments in Messages */ +.message_documents { + margin-top: 8px; + padding: 8px; + background-color: rgba(0, 0, 0, 0.05); + border-radius: 12px; + border: 1px solid rgba(0, 0, 0, 0.1); + width: 100%; + box-sizing: border-box; +} + +/* Document styling for user messages */ +.message_documents.user { + background-color: rgba(255, 255, 255, 0.15); + border: 1px solid rgba(255, 255, 255, 0.2); +} + +/* Document styling for assistant messages */ +.message_documents.assistant { + background-color: var(--color-bg); + border: 1px solid var(--color-gray-disabled); +} + +.message_documents_header { + font-size: 12px; + color: var(--color-gray); + margin-bottom: 8px; + font-weight: 500; +} + +/* Document header styling for user messages */ +.message_documents_header.user { + color: rgba(255, 255, 255, 0.8); +} + +/* Document header styling for assistant messages */ +.message_documents_header.assistant { + color: var(--color-gray); +} + +.message_document_item { + display: flex; + align-items: center; + gap: 8px; + padding: 6px; + border-radius: 4px; + background-color: var(--color-surface); + margin-bottom: 4px; + cursor: pointer; +} + +.message_document_icon { + font-size: 16px; +} + +.message_document_info { + flex: 1; + min-width: 0; +} + +.message_document_name { + font-size: 14px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.message_document_size { + font-size: 12px; + color: var(--color-gray); +} + +.message_document_actions { + display: flex; + gap: 4px; +} + +.message_document_action { + padding: 4px 8px; + font-size: 12px; + background-color: transparent; + border: 1px solid var(--color-gray-disabled); + border-radius: 4px; + cursor: pointer; +} + +.message_document_action:hover { + background-color: var(--color-gray-disabled); +} + +.message_document_action:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +/* Scroll to Bottom Button */ +.scroll_to_bottom_btn { + position: absolute; + bottom: 20px; + right: 20px; + background-color: var(--color-secondary); + color: white; + border: none; + border-radius: 50%; + width: 48px; + height: 48px; + font-size: 20px; + cursor: pointer; + box-shadow: 0 2px 8px rgba(0,0,0,0.2); + z-index: 1000; + display: flex; + align-items: center; + justify-content: center; + transition: opacity 0.3s ease-in-out, visibility 0.3s ease-in-out, transform 0.2s ease-in-out; +} + +.scroll_to_bottom_btn:hover { + transform: scale(1.1); + box-shadow: 0 4px 12px rgba(0,0,0,0.3); +} + +.scroll_to_bottom_btn:active { + transform: scale(0.95); +} + +.scroll_to_bottom_btn.hidden { + opacity: 0; + visibility: hidden; + pointer-events: none; +} + +.scroll_to_bottom_btn.visible { + opacity: 1; + visibility: visible; + pointer-events: auto; +} + +/* Loading and Error States */ +.message_loading { + text-align: center; + padding: 16px; + color: var(--color-gray); +} + +.message_error { + padding: 8px; + background-color: var(--color-error); + color: white; + border-radius: 4px; + margin-bottom: 16px; +} + +.message_empty_state { + color: var(--color-gray); + text-align: center; + padding: 16px; +} + +/* Workflow Status Display */ +.workflow_status { + padding: 8px; + background-color: var(--color-surface); + border-radius: 4px; + margin-bottom: 16px; +} + +.workflow_status_title { + font-weight: bold; +} + +.workflow_status_polling { + margin-left: 8px; + font-size: 12px; + color: var(--color-secondary); + opacity: 0.7; +} + +/* Animation for polling indicator */ +@keyframes pulse { + 0%, 100% { opacity: 0.7; } + 50% { opacity: 1; } +} + +.polling_indicator { + animation: pulse 2s infinite; +} diff --git a/src/pages/Home/HomeStyles/Dashboard.module.css b/src/pages/Home/HomeStyles/Dashboard.module.css index e1ede65..55d2b96 100644 --- a/src/pages/Home/HomeStyles/Dashboard.module.css +++ b/src/pages/Home/HomeStyles/Dashboard.module.css @@ -29,7 +29,7 @@ .verticalDivider { position: absolute; - top: calc(86px + 20px + 1px); /* pageHeader height + gap + horizontalDivider height */ + top: calc(86px + 23px + 1px); /* pageHeader height + gap + horizontalDivider height */ bottom: 0; left: calc(66.666% - 9px); width: 1px;