diff options
Diffstat (limited to 'src/client/views/nodes/ChatBox/MessageComponent.tsx')
-rw-r--r-- | src/client/views/nodes/ChatBox/MessageComponent.tsx | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/src/client/views/nodes/ChatBox/MessageComponent.tsx b/src/client/views/nodes/ChatBox/MessageComponent.tsx new file mode 100644 index 000000000..fced0b4d5 --- /dev/null +++ b/src/client/views/nodes/ChatBox/MessageComponent.tsx @@ -0,0 +1,116 @@ +/* eslint-disable react/require-default-props */ +import React from 'react'; +import { observer } from 'mobx-react'; +import { MathJax, MathJaxContext } from 'better-react-mathjax'; +import ReactMarkdown from 'react-markdown'; +import { TbCircle0Filled, TbCircle1Filled, TbCircle2Filled, TbCircle3Filled, TbCircle4Filled, TbCircle5Filled, TbCircle6Filled, TbCircle7Filled, TbCircle8Filled, TbCircle9Filled } from 'react-icons/tb'; +import { AssistantMessage } from './types'; + +interface MessageComponentProps { + message: AssistantMessage; + toggleToolLogs: (index: number) => void; + expandedLogIndex: number | null; + index: number; + showModal: () => void; + goToLinkedDoc: (url: string) => void; + setCurrentFile: (file: { url: string }) => void; + isCurrent?: boolean; +} + +const MessageComponent: React.FC<MessageComponentProps> = function ({ message, toggleToolLogs, expandedLogIndex, goToLinkedDoc, index, showModal, setCurrentFile, isCurrent = false }) { + // const messageClass = `${message.role} ${isCurrent ? 'current-message' : ''}`; + + const LinkRenderer = ({ href, children }: { href: string; children: React.ReactNode }) => { + // console.log(href + " " + children) + const regex = /([a-zA-Z0-9_.!-]+)~~~(citation|file_path)/; + const matches = href.match(regex); + // console.log(href) + // console.log(matches) + const url = matches ? matches[1] : href; + const linkType = matches ? matches[2] : null; + if (linkType === 'citation') { + switch (children) { + case '0': + children = <TbCircle0Filled />; + break; + case '1': + children = <TbCircle1Filled />; + break; + case '2': + children = <TbCircle2Filled />; + break; + case '3': + children = <TbCircle3Filled />; + break; + case '4': + children = <TbCircle4Filled />; + break; + case '5': + children = <TbCircle5Filled />; + break; + case '6': + children = <TbCircle6Filled />; + break; + case '7': + children = <TbCircle7Filled />; + break; + case '8': + children = <TbCircle8Filled />; + break; + case '9': + children = <TbCircle9Filled />; + break; + default: + break; + } + } + // console.log(linkType) + const style = { + color: 'lightblue', + verticalAlign: linkType === 'citation' ? 'super' : 'baseline', + fontSize: linkType === 'citation' ? 'smaller' : 'inherit', + }; + + return ( + <a + href="#" + onClick={e => { + e.preventDefault(); + if (linkType === 'citation') { + goToLinkedDoc(url); + } else if (linkType === 'file_path') { + showModal(); + setCurrentFile({ url }); + } + }} + style={style}> + {children} + </a> + ); + }; + + return ( + <div className={`message ${message.role}`}> + <MathJaxContext> + <MathJax dynamic hideUntilTypeset="every"> + <ReactMarkdown components={{ a: LinkRenderer }}>{message.text ? message.text : ''}</ReactMarkdown> + </MathJax> + </MathJaxContext> + {message.image && <img src={message.image} alt="" />} + <div className="message-footer"> + {message.tool_logs && ( + <button className="toggle-logs-button" onClick={() => toggleToolLogs(index)}> + {expandedLogIndex === index ? 'Hide Code Interpreter Logs' : 'Show Code Interpreter Logs'} + </button> + )} + {expandedLogIndex === index && ( + <div className="tool-logs"> + <pre>{message.tool_logs}</pre> + </div> + )} + </div> + </div> + ); +}; + +export default observer(MessageComponent); |