diff options
-rw-r--r-- | src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss | 77 | ||||
-rw-r--r-- | src/client/views/nodes/chatbot/chatboxcomponents/MessageComponent.tsx | 43 |
2 files changed, 78 insertions, 42 deletions
diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss index ea461388f..9cf760a12 100644 --- a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss +++ b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss @@ -86,11 +86,10 @@ $transition: all 0.2s ease-in-out; height: 48px; margin-left: 10px; cursor: pointer; - transition: $transition; display: flex; align-items: center; justify-content: center; - position: relative; + transition: $transition; &:hover { background-color: darken($primary-color, 10%); @@ -102,12 +101,12 @@ $transition: all 0.2s ease-in-out; } .spinner { - height: 24px; - width: 24px; + width: 20px; + height: 20px; border: 3px solid rgba(255, 255, 255, 0.3); border-top: 3px solid #fff; border-radius: 50%; - animation: spin 1s linear infinite; + animation: spin 0.6s linear infinite; } } } @@ -143,12 +142,14 @@ $transition: all 0.2s ease-in-out; .message { max-width: 75%; - padding: 14px 18px; - border-radius: 16px; + padding: 12px 16px; + border-radius: 12px; font-size: 15px; line-height: 1.6; box-shadow: 0 1px 3px $shadow-color; word-wrap: break-word; + display: flex; + flex-direction: column; &.user { align-self: flex-end; @@ -164,10 +165,6 @@ $transition: all 0.2s ease-in-out; border-bottom-left-radius: 4px; } - .message-content { - // Additional styles if needed - } - .toggle-info { margin-top: 10px; background-color: transparent; @@ -178,7 +175,7 @@ $transition: all 0.2s ease-in-out; font-size: 14px; cursor: pointer; transition: $transition; - margin-bottom: 12px; // Adds space between button and thoughts/actions text + margin-bottom: 16px; &:hover { background-color: rgba($primary-color, 0.1); @@ -186,7 +183,12 @@ $transition: all 0.2s ease-in-out; } .processing-info { - margin-top: 10px; + margin-bottom: 12px; + padding: 10px 15px; + background-color: #f9f9f9; + border-radius: 8px; + box-shadow: 0 1px 3px $shadow-color; + font-size: 14px; .processing-item { margin-bottom: 5px; @@ -194,6 +196,35 @@ $transition: all 0.2s ease-in-out; color: $light-text-color; } } + + .message-content { + background-color: inherit; + padding: 10px; + border-radius: 8px; + font-size: 15px; + line-height: 1.5; + + .citation-button { + display: inline-flex; + align-items: center; + justify-content: center; + width: 22px; + height: 22px; + border-radius: 50%; + background-color: rgba(0, 0, 0, 0.1); + color: $text-color; + font-size: 12px; + font-weight: bold; + margin-left: 5px; + cursor: pointer; + transition: $transition; + + &:hover { + background-color: rgba($primary-color, 0.2); + color: #fff; + } + } + } } .follow-up-questions { @@ -229,26 +260,6 @@ $transition: all 0.2s ease-in-out; } } -.citation-button { - display: inline-flex; - align-items: center; - justify-content: center; - width: 22px; - height: 22px; - border-radius: 50%; - background-color: rgba(0, 0, 0, 0.1); - color: $text-color; - font-size: 12px; - font-weight: bold; - margin-left: 5px; - cursor: pointer; - transition: $transition; - - &:hover { - background-color: rgba(0, 0, 0, 0.2); - } -} - .uploading-overlay { position: absolute; top: 0; diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/MessageComponent.tsx b/src/client/views/nodes/chatbot/chatboxcomponents/MessageComponent.tsx index 44dedca78..120e20001 100644 --- a/src/client/views/nodes/chatbot/chatboxcomponents/MessageComponent.tsx +++ b/src/client/views/nodes/chatbot/chatboxcomponents/MessageComponent.tsx @@ -34,40 +34,57 @@ interface MessageComponentProps { * @param {MessageComponentProps} props - The props for the component. */ const MessageComponentBox: React.FC<MessageComponentProps> = ({ message, onFollowUpClick, onCitationClick }) => { + // State for managing whether the dropdown is open or closed for processing info const [dropdownOpen, setDropdownOpen] = useState(false); + /** + * Renders the content of the message based on the type (e.g., grounded text, normal text). + * @param {MessageContent} item - The content item to render. + * @returns {JSX.Element} JSX element rendering the content. + */ const renderContent = (item: MessageContent) => { const i = item.index; + // Handle grounded text with citations if (item.type === TEXT_TYPE.GROUNDED) { const citation_ids = item.citation_ids || []; return ( <span key={i} className="grounded-text"> - <ReactMarkdown>{item.text}</ReactMarkdown> + {item.text} {citation_ids.map((id, idx) => { const citation = message.citations?.find(c => c.citation_id === id); if (!citation) return null; return ( <button key={i + idx} className="citation-button" onClick={() => onCitationClick(citation)}> - [{idx + 1}] + {i + idx + 1} </button> ); })} + <br /> </span> ); - } else if (item.type === TEXT_TYPE.NORMAL) { + } + + // Handle normal text + else if (item.type === TEXT_TYPE.NORMAL) { return ( <span key={i} className="normal-text"> <ReactMarkdown>{item.text}</ReactMarkdown> </span> ); - } else if ('query' in item) { + } + + // Handle query type content + else if ('query' in item) { return ( <span key={i} className="query-text"> <ReactMarkdown>{JSON.stringify(item.query)}</ReactMarkdown> </span> ); - } else { + } + + // Fallback for any other content type + else { return ( <span key={i}> <ReactMarkdown>{JSON.stringify(item)}</ReactMarkdown> @@ -76,18 +93,24 @@ const MessageComponentBox: React.FC<MessageComponentProps> = ({ message, onFollo } }; + // Check if the message contains processing information (thoughts/actions) const hasProcessingInfo = message.processing_info && message.processing_info.length > 0; + /** + * Renders processing information such as thoughts or actions during message handling. + * @param {ProcessingInfo} info - The processing information to render. + * @returns {JSX.Element | null} JSX element rendering the processing info or null. + */ const renderProcessingInfo = (info: ProcessingInfo) => { if (info.type === PROCESSING_TYPE.THOUGHT) { return ( - <div key={info.index} className="processing-item"> + <div key={info.index} className="dropdown-item"> <strong>Thought:</strong> {info.content} </div> ); } else if (info.type === PROCESSING_TYPE.ACTION) { return ( - <div key={info.index} className="processing-item"> + <div key={info.index} className="dropdown-item"> <strong>Action:</strong> {info.content} </div> ); @@ -97,8 +120,6 @@ const MessageComponentBox: React.FC<MessageComponentProps> = ({ message, onFollo return ( <div className={`message ${message.role}`}> - <div className="message-content">{message.content && message.content.map(messageFragment => <React.Fragment key={messageFragment.index}>{renderContent(messageFragment)}</React.Fragment>)}</div> - {/* Processing Information Dropdown */} {hasProcessingInfo && ( <div className="processing-info"> @@ -106,9 +127,13 @@ const MessageComponentBox: React.FC<MessageComponentProps> = ({ message, onFollo {dropdownOpen ? 'Hide Agent Thoughts/Actions' : 'Show Agent Thoughts/Actions'} </button> {dropdownOpen && <div className="info-content">{message.processing_info.map(renderProcessingInfo)}</div>} + <br /> </div> )} + {/* Message Content */} + <div className="message-content">{message.content && message.content.map(messageFragment => <React.Fragment key={messageFragment.index}>{renderContent(messageFragment)}</React.Fragment>)}</div> + {/* Follow-up Questions Section */} {message.follow_up_questions && message.follow_up_questions.length > 0 && ( <div className="follow-up-questions"> |