diff --git a/components/Chat/Chat.test.tsx b/components/Chat/Chat.test.tsx
index d0758c9a..44964a48 100644
--- a/components/Chat/Chat.test.tsx
+++ b/components/Chat/Chat.test.tsx
@@ -72,18 +72,21 @@ describe("Chat component", () => {
,
);
+ const uuidRegex =
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
const el = screen.getByTestId("mock-chat-response");
expect(el).toBeInTheDocument();
const dataProps = el.getAttribute("data-props");
- expect(JSON.parse(dataProps!)).toEqual({
- isStreamingComplete: false,
- searchTerm: "tell me about boats",
- message: {
- answer: "fake-answer-1",
- end: "stop",
- },
+ const dataPropsObj = JSON.parse(dataProps!);
+ expect(dataPropsObj.question).toEqual("tell me about boats");
+ expect(dataPropsObj.isStreamingComplete).toEqual(false);
+ expect(dataPropsObj.message).toEqual({
+ answer: "fake-answer-1",
+ end: "stop",
});
+ expect(typeof dataPropsObj.conversationRef).toBe("string");
+ expect(uuidRegex.test(dataPropsObj.conversationRef)).toBe(true);
});
it("sends a websocket message when the search term changes", () => {
diff --git a/components/Chat/Chat.tsx b/components/Chat/Chat.tsx
index 96a2deab..0666c194 100644
--- a/components/Chat/Chat.tsx
+++ b/components/Chat/Chat.tsx
@@ -15,12 +15,11 @@ import Container from "@/components/Shared/Container";
import { prepareQuestion } from "@/lib/chat-helpers";
import useChatSocket from "@/hooks/useChatSocket";
import useQueryParams from "@/hooks/useQueryParams";
+import { v4 as uuidv4 } from "uuid";
const Chat = ({
- totalResults,
viewResultsCallback,
}: {
- totalResults?: number;
viewResultsCallback?: () => void;
}) => {
const { searchTerm = "" } = useQueryParams();
@@ -37,35 +36,42 @@ const Chat = ({
searchState: { chat },
searchDispatch,
} = useSearchState();
- const { question } = chat;
+ const { question, answer } = chat;
const [isStreamingComplete, setIsStreamingComplete] = useState(false);
useEffect(() => {
- if (!isStreamingComplete && isConnected && authToken && searchTerm) {
+ if (
+ !isStreamingComplete &&
+ isConnected &&
+ authToken &&
+ searchTerm &&
+ conversationRef
+ ) {
resetChat();
- const preparedQuestion = prepareQuestion(searchTerm, authToken);
- setConversationRef(preparedQuestion.ref);
+ const preparedQuestion = prepareQuestion(
+ searchTerm,
+ authToken,
+ conversationRef,
+ );
sendMessage(preparedQuestion);
}
- }, [authToken, isStreamingComplete, isConnected, searchTerm, sendMessage]);
+ }, [
+ authToken,
+ isStreamingComplete,
+ isConnected,
+ searchTerm,
+ conversationRef,
+ sendMessage,
+ ]);
useEffect(() => {
- if (!message) return;
-
- // const updateChat = () => {
- // searchDispatch({
- // chat: {
- // answer: message.answer || "",
- // documents: sourceDocuments,
- // question: searchTerm || "",
- // ref: message.ref,
- // },
- // type: "updateChat",
- // });
- // };
-
- if (message.type === "final_message") setIsStreamingComplete(true);
+ setIsStreamingComplete(false);
+ setConversationRef(uuidv4());
+ }, [searchTerm]);
+
+ useEffect(() => {
+ if (!message || !conversationRef) return;
}, [message]);
function handleNewQuestion() {
@@ -90,13 +96,42 @@ const Chat = ({
);
+ const handleResponseCallback = (content: any) => {
+ if (!conversationRef) return;
+
+ setIsStreamingComplete(true);
+ searchDispatch({
+ chat: {
+ // content here is now a react element
+ // once continued conversations ar e in place
+ // see note below for question refactor
+ answer: content,
+
+ // documents should be eventually removed as
+ // they are now integrated into content
+ // doing so will require some careful refactoring
+ // as the documents are used in feedback form
+ documents: [],
+
+ // question should become an entry[] with
+ // entry[n].question and entry[n].content
+ question: searchTerm || "",
+
+ ref: conversationRef,
+ },
+ type: "updateChat",
+ });
+ };
+
return (
<>
{streamingError && (
diff --git a/components/Chat/Response/Interstitial.styled.tsx b/components/Chat/Response/Interstitial.styled.tsx
index 9af3de0d..acde30d4 100644
--- a/components/Chat/Response/Interstitial.styled.tsx
+++ b/components/Chat/Response/Interstitial.styled.tsx
@@ -43,10 +43,14 @@ const StyledInterstitialIcon = styled("div", {
const StyledInterstitial = styled("div", {
color: "$black",
fontFamily: "$northwesternSansBold",
- fontSize: "$gr3",
+ fontSize: "$gr4",
display: "flex",
alignItems: "center",
gap: "$gr2",
+
+ em: {
+ color: "$purple",
+ },
});
export { StyledInterstitial, StyledInterstitialIcon };
diff --git a/components/Chat/Response/Interstitial.tsx b/components/Chat/Response/Interstitial.tsx
index 168c90bf..da0447e7 100644
--- a/components/Chat/Response/Interstitial.tsx
+++ b/components/Chat/Response/Interstitial.tsx
@@ -15,17 +15,25 @@ const ResponseInterstitial: React.FC = ({
message,
}) => {
const { tool, input } = message;
- let text = "";
+ let text: React.ReactElement = <>>;
switch (tool) {
case "aggregate":
- text = `Aggregating ${input.agg_field} by ${input.term_field} ${input.term}`;
+ text = (
+ <>
+ Aggregating {input.agg_field} by {input.term_field} {input.term}
+ >
+ );
break;
case "discover_fields":
- text = "Discovering fields";
+ text = <>Discovering fields>;
break;
case "search":
- text = `Searching for: ${input.query}`;
+ text = (
+ <>
+ Searching for {input.query}
+ >
+ );
break;
default:
console.warn("Unknown tool_start message", message);
diff --git a/components/Chat/Response/Response.styled.tsx b/components/Chat/Response/Response.styled.tsx
index 62100316..1083c9e9 100644
--- a/components/Chat/Response/Response.styled.tsx
+++ b/components/Chat/Response/Response.styled.tsx
@@ -79,7 +79,7 @@ const StyledQuestion = styled("h3", {
fontSize: "$gr6",
letterSpacing: "-0.012em",
lineHeight: "1.35em",
- margin: "0",
+ margin: "0 0 $gr4",
padding: "0",
color: "$black",
});
diff --git a/components/Chat/Response/Response.tsx b/components/Chat/Response/Response.tsx
index 39b852fa..11454628 100644
--- a/components/Chat/Response/Response.tsx
+++ b/components/Chat/Response/Response.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from "react";
+import React, { use, useEffect, useState } from "react";
import {
StyledQuestion,
StyledResponse,
@@ -14,16 +14,18 @@ import { StreamingMessage } from "@/types/components/chat";
interface ChatResponseProps {
conversationRef?: string;
- message?: StreamingMessage;
- searchTerm: string;
isStreamingComplete: boolean;
+ message?: StreamingMessage;
+ question: string;
+ responseCallback?: (renderedMessage: any) => void;
}
const ChatResponse: React.FC = ({
conversationRef,
- message,
- searchTerm,
isStreamingComplete,
+ message,
+ question,
+ responseCallback,
}) => {
const [renderedMessage, setRenderedMessage] = useState();
const [streamedMessage, setStreamedMessage] = useState("");
@@ -83,17 +85,35 @@ const ChatResponse: React.FC = ({
>
));
}
+
+ /**
+ * Final message is the last message in the response
+ * and is used to trigger the responseCallback
+ * to store this response.
+ */
+ if (type === "final_message") {
+ if (responseCallback) responseCallback(renderedMessage);
+ }
}, [message]);
+ useEffect(() => {
+ resetRenderedMessage();
+ resetStreamedMessage();
+ }, [conversationRef]);
+
function resetStreamedMessage() {
setStreamedMessage("");
}
+ function resetRenderedMessage() {
+ setRenderedMessage(undefined);
+ }
+
return (
- {searchTerm}
+ {question}
{renderedMessage}
{streamedMessage && }
{!isStreamingComplete && }
@@ -103,4 +123,4 @@ const ChatResponse: React.FC = ({
);
};
-export default React.memo(ChatResponse);
+export default ChatResponse;
diff --git a/lib/chat-helpers.ts b/lib/chat-helpers.ts
index 87cec0b4..467d3f52 100644
--- a/lib/chat-helpers.ts
+++ b/lib/chat-helpers.ts
@@ -1,14 +1,17 @@
import axios, { AxiosError } from "axios";
import { DCAPI_CHAT_FEEDBACK } from "./constants/endpoints";
-import { v4 as uuidv4 } from "uuid";
-const prepareQuestion = (questionString: string, authToken: string) => {
+const prepareQuestion = (
+ questionString: string,
+ authToken: string,
+ conversationRef: string,
+) => {
return {
auth: authToken,
message: "chat",
question: questionString,
- ref: uuidv4(),
+ ref: conversationRef,
};
};
diff --git a/pages/search.tsx b/pages/search.tsx
index 568886cb..b27958b7 100644
--- a/pages/search.tsx
+++ b/pages/search.tsx
@@ -254,10 +254,7 @@ const SearchPage: NextPage = () => {
renderTabList={showStreamedResponse}
/>
-
+