diff --git a/package-lock.json b/package-lock.json index 2622a26..01e9913 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@patternfly/react-core": "^6.0.0", "@patternfly/react-icons": "^6.0.0", "@patternfly/react-styles": "^6.0.0", - "@patternfly/virtual-assistant": "^2.1.0-prerelease.8", + "@patternfly/virtual-assistant": "^2.1.0-prerelease.11", "react": "^18.3.1", "react-dom": "^18.3.1", "sirv-cli": "^2.0.2" @@ -3191,9 +3191,9 @@ "license": "MIT" }, "node_modules/@patternfly/virtual-assistant": { - "version": "2.1.0-prerelease.8", - "resolved": "https://registry.npmjs.org/@patternfly/virtual-assistant/-/virtual-assistant-2.1.0-prerelease.8.tgz", - "integrity": "sha512-VbU/BluxZfn4aY58dBi0tQQZK1upGrj5JtfrqgRi64K4JCAT4NGaRghEtRdPgI1HHE6OPQtXam/e+2EeaU8vOQ==", + "version": "2.1.0-prerelease.11", + "resolved": "https://registry.npmjs.org/@patternfly/virtual-assistant/-/virtual-assistant-2.1.0-prerelease.11.tgz", + "integrity": "sha512-36CazQIWgQgF2oHZpi3a7HjVf2eCvk8svBxq+9sjHuxnbG9q16l5KWXa88ZlyO0ag1YNsiaHAl+Fl8qWo2WfDg==", "license": "MIT", "dependencies": { "@patternfly/react-code-editor": "^6.0.0", diff --git a/package.json b/package.json index f234796..eaf89ee 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "@patternfly/react-core": "^6.0.0", "@patternfly/react-icons": "^6.0.0", "@patternfly/react-styles": "^6.0.0", - "@patternfly/virtual-assistant": "^2.1.0-prerelease.8", + "@patternfly/virtual-assistant": "^2.1.0-prerelease.11", "react": "^18.3.1", "react-dom": "^18.3.1", "sirv-cli": "^2.0.2" diff --git a/src/app/BaseChatbot/BaseChatbot.tsx b/src/app/BaseChatbot/BaseChatbot.tsx index 666b17e..dd4a6cf 100644 --- a/src/app/BaseChatbot/BaseChatbot.tsx +++ b/src/app/BaseChatbot/BaseChatbot.tsx @@ -19,16 +19,19 @@ import { CannedChatbot } from '../types/CannedChatbot'; import { HeaderDropdown } from '@app/HeaderDropdown/HeaderDropdown'; import { ERROR_TITLE, getId } from '@app/utils/utils'; import { Button } from '@patternfly/react-core'; +import botAvatar from '@app/bgimages/RHCAI-studio-avatar.svg'; +import userAvatar from '@app/bgimages/avatarImg.svg'; + interface Source { link: string; } const BaseChatbot: React.FunctionComponent = () => { const { chatbots } = useLoaderData() as { chatbots: CannedChatbot[] }; + const [isSendButtonDisabled, setIsSendButtonDisabled] = React.useState(true); const [messages, setMessages] = React.useState([]); const [currentMessage, setCurrentMessage] = React.useState([]); const [currentSources, setCurrentSources] = React.useState(); - const [isSendButtonDisabled, setIsSendButtonDisabled] = React.useState(false); const scrollToBottomRef = React.useRef(null); const [error, setError] = React.useState<{ title: string; body: string }>(); const [announcement, setAnnouncement] = React.useState(); @@ -170,6 +173,7 @@ const BaseChatbot: React.FunctionComponent = () => { const newMessages = structuredClone(messages); if (currentMessage.length > 0) { newMessages.push({ + avatar: botAvatar, id: getId(), name: currentChatbot?.displayName, role: 'bot', @@ -184,6 +188,7 @@ const BaseChatbot: React.FunctionComponent = () => { setCurrentDate(undefined); } newMessages.push({ + avatar: userAvatar, id: getId(), name: 'You', role: 'user', @@ -201,7 +206,6 @@ const BaseChatbot: React.FunctionComponent = () => { } // make announcement to assistive devices that new message has been added currentMessage.length > 0 && setAnnouncement(`Message from Chatbot: ${currentMessage.join('')}`); - setIsSendButtonDisabled(false); setHasStopButton(false); }; @@ -218,7 +222,6 @@ const BaseChatbot: React.FunctionComponent = () => { setCurrentSources(undefined); setError(undefined); setAnnouncement(undefined); - setIsSendButtonDisabled(false); }; const handleStopButton = () => { @@ -228,6 +231,14 @@ const BaseChatbot: React.FunctionComponent = () => { setHasStopButton(false); }; + const handleChange = (event: React.ChangeEvent, value: string) => { + if (value !== '') { + setIsSendButtonDisabled(false); + return; + } + setIsSendButtonDisabled(true); + }; + return ( @@ -260,6 +271,7 @@ const BaseChatbot: React.FunctionComponent = () => { ))} {currentMessage.length > 0 && ( { onSendMessage={handleSend} hasMicrophoneButton hasAttachButton={false} - isSendButtonDisabled={isSendButtonDisabled} hasStopButton={hasStopButton} handleStopButton={handleStopButton} + alwayShowSendButton + onChange={handleChange} + isSendButtonDisabled={isSendButtonDisabled} /> diff --git a/src/app/Compare/CompareChild.tsx b/src/app/Compare/CompareChild.tsx index 208ef99..5d3aee4 100644 --- a/src/app/Compare/CompareChild.tsx +++ b/src/app/Compare/CompareChild.tsx @@ -15,6 +15,9 @@ import { CannedChatbot } from '../types/CannedChatbot'; import { HeaderDropdown } from '@app/HeaderDropdown/HeaderDropdown'; import { ERROR_TITLE, getId } from '@app/utils/utils'; import { useChildStatus } from './ChildStatusProvider'; +import botAvatar from '@app/bgimages/RHCAI-studio-avatar.svg'; +import userAvatar from '@app/bgimages/avatarImg.svg'; + interface Source { link: string; } @@ -22,7 +25,6 @@ interface Source { interface CompareChildProps { chatbot: CannedChatbot; allChatbots: CannedChatbot[]; - setIsSendButtonDisabled: (bool: boolean) => void; controller?: AbortController; setController: (controller: AbortController | undefined) => void; input?: string; @@ -35,7 +37,6 @@ interface CompareChildProps { const CompareChild: React.FunctionComponent = ({ chatbot, allChatbots, - setIsSendButtonDisabled, controller, setController, input, @@ -57,12 +58,12 @@ const CompareChild: React.FunctionComponent = ({ const displayMode = ChatbotDisplayMode.embedded; const handleSend = async (input: string) => { - setIsSendButtonDisabled(true); const date = new Date(); const newMessages = structuredClone(messages); // when a new message comes in, we add the last streaming message to the array and reset it if (currentMessage.length > 0) { newMessages.push({ + avatar: botAvatar, id: getId(), name: currentChatbot?.displayName, role: 'bot', @@ -76,6 +77,7 @@ const CompareChild: React.FunctionComponent = ({ setCurrentSources(undefined); } newMessages.push({ + avatar: userAvatar, id: getId(), name: 'You', role: 'user', @@ -94,7 +96,6 @@ const CompareChild: React.FunctionComponent = ({ } // make announcement to assistive devices that new message has been added currentMessage.length > 0 && setAnnouncement(`Message from Chatbot: ${currentMessage.join('')}`); - setIsSendButtonDisabled(false); // this is used to control state of stop button updateStatus(order === 'first' ? 'child1' : 'child2', { isMessageStreaming: false }); }; @@ -136,6 +137,7 @@ const CompareChild: React.FunctionComponent = ({ // fixme this is getting too large; we should refactor async function fetchData(userMessage: string) { + updateStatus(order === 'first' ? 'child1' : 'child2', { isMessageStreaming: true }); if (controller) { controller.abort(); } @@ -168,7 +170,6 @@ const CompareChild: React.FunctionComponent = ({ throw new Error('Other'); } } - updateStatus(order === 'first' ? 'child1' : 'child2', { isMessageStreaming: true }); // start reading the streaming message const reader = response.body.getReader(); @@ -232,7 +233,6 @@ const CompareChild: React.FunctionComponent = ({ setCurrentSources(undefined); setError(undefined); setAnnouncement(undefined); - setIsSendButtonDisabled(false); setChatbot(value); setSearchParams(_event, value.name, order); updateStatus(order === 'first' ? 'child1' : 'child2', { @@ -267,6 +267,7 @@ const CompareChild: React.FunctionComponent = ({ ))} {currentMessage.length > 0 && ( { const { chatbots } = useLoaderData() as { chatbots: CannedChatbot[] }; // state - const [isSendButtonDisabled, setIsSendButtonDisabled] = React.useState(false); + const [isSendButtonDisabled, setIsSendButtonDisabled] = React.useState(true); const [input, setInput] = React.useState(); const [hasNewInput, setHasNewInput] = React.useState(false); const [firstController, setFirstController] = React.useState(); @@ -97,6 +97,7 @@ export const CompareLayout: React.FunctionComponent = () => { const handleSend = (value: string) => { setInput(value); setHasNewInput(!hasNewInput); + setIsSendButtonDisabled(true); }; const changeSearchParams = (_event, value: string, order: string) => { @@ -118,6 +119,14 @@ export const CompareLayout: React.FunctionComponent = () => { setHasStopButton(false); }; + const handleChange = (event: React.ChangeEvent, value: string) => { + if (value !== '') { + setIsSendButtonDisabled(false); + return; + } + setIsSendButtonDisabled(true); + }; + return ( firstChatbot && secondChatbot && ( @@ -147,7 +156,6 @@ export const CompareLayout: React.FunctionComponent = () => { allChatbots={chatbots} controller={firstController} setController={setFirstController} - setIsSendButtonDisabled={setIsSendButtonDisabled} input={input} setChatbot={setFirstChatbot} hasNewInput={hasNewInput} @@ -161,7 +169,6 @@ export const CompareLayout: React.FunctionComponent = () => { allChatbots={chatbots} controller={secondController} setController={setSecondController} - setIsSendButtonDisabled={setIsSendButtonDisabled} input={input} setChatbot={setSecondChatbot} hasNewInput={hasNewInput} @@ -175,9 +182,11 @@ export const CompareLayout: React.FunctionComponent = () => { onSendMessage={handleSend} hasMicrophoneButton hasAttachButton={false} - isSendButtonDisabled={isSendButtonDisabled} hasStopButton={hasStopButton} handleStopButton={handleStopButton} + alwayShowSendButton + onChange={handleChange} + isSendButtonDisabled={isSendButtonDisabled} /> diff --git a/src/app/app.css b/src/app/app.css index 89ad26f..24aac13 100644 --- a/src/app/app.css +++ b/src/app/app.css @@ -127,3 +127,9 @@ pf-v6-c-page__main-container.pf-m-fill { } } } + +.pf-chatbot__message.pf-chatbot__message--user { + img { + border: 1px solid var(--pf-t--global--border--color--default); + } +} diff --git a/src/app/bgimages/RHCAI-studio-avatar.svg b/src/app/bgimages/RHCAI-studio-avatar.svg new file mode 100644 index 0000000..89bad8b --- /dev/null +++ b/src/app/bgimages/RHCAI-studio-avatar.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/app/bgimages/avatarImg.svg b/src/app/bgimages/avatarImg.svg new file mode 100644 index 0000000..73726f9 --- /dev/null +++ b/src/app/bgimages/avatarImg.svg @@ -0,0 +1,18 @@ + + + + + + + + + +