Skip to content

Commit

Permalink
Merge pull request #330 from nulib/4740-new-chat-request-flow
Browse files Browse the repository at this point in the history
Split chat responses and legacy responses on `/search` screen
  • Loading branch information
mathewjordan authored Jun 14, 2024
2 parents a968069 + 4c136af commit 0230848
Show file tree
Hide file tree
Showing 20 changed files with 610 additions and 150 deletions.
39 changes: 25 additions & 14 deletions components/Chat/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,26 @@ import { Work } from "@nulib/dcapi-types";
import { prepareQuestion } from "@/lib/chat-helpers";
import useChatSocket from "@/hooks/useChatSocket";
import useQueryParams from "@/hooks/useQueryParams";
import { useSearchState } from "@/context/search-context";

const Chat = () => {
const { searchTerm: question } = useQueryParams();
const { searchTerm = "" } = useQueryParams();
const { authToken, isConnected, message, sendMessage } = useChatSocket();
const { searchDispatch, searchState } = useSearchState();
const { chat } = searchState;
const { answer, documents = [], question } = chat;

const sameQuestionExists = !!question && searchTerm === question;

const [isStreamingComplete, setIsStreamingComplete] = useState(false);
const [sourceDocuments, setSourceDocuments] = useState<Work[]>([]);
const [streamedAnswer, setStreamedAnswer] = useState("");

useEffect(() => {
if (question && isConnected && authToken) {
const preparedQuestion = prepareQuestion(question, authToken);
if (!sameQuestionExists && isConnected && authToken) {
const preparedQuestion = prepareQuestion(searchTerm, authToken);
sendMessage(preparedQuestion);
}
}, [authToken, isConnected, question, sendMessage]);
}, [authToken, isConnected, sameQuestionExists, searchTerm, sendMessage]);

useEffect(() => {
if (!message) return;
Expand All @@ -31,21 +36,27 @@ const Chat = () => {
return prev + message.token;
});
} else if (message.answer) {
setStreamedAnswer(message.answer);
setIsStreamingComplete(true);
searchDispatch({
chat: {
answer: message.answer,
documents: sourceDocuments,
question: searchTerm || "",
},
type: "updateChat",
});
}
}, [message]);
}, [message, searchTerm, sourceDocuments, searchDispatch]);

if (!question) return null;
if (!searchTerm) return null;

return (
<ChatResponse
isStreamingComplete={isStreamingComplete}
question={question}
sourceDocuments={sourceDocuments}
streamedAnswer={streamedAnswer}
isStreamingComplete={!!answer}
searchTerm={searchTerm}
sourceDocuments={sameQuestionExists ? documents : sourceDocuments}
streamedAnswer={sameQuestionExists ? answer : streamedAnswer}
/>
);
};

export default Chat;
export default React.memo(Chat);
15 changes: 13 additions & 2 deletions components/Chat/Response/Images.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,29 @@ import GridItem from "@/components/Grid/Item";
import { StyledImages } from "@/components/Chat/Response/Response.styled";
import { Work } from "@nulib/dcapi-types";

const ResponseImages = ({ sourceDocuments }: { sourceDocuments: Work[] }) => {
const ResponseImages = ({
isStreamingComplete,
sourceDocuments,
}: {
isStreamingComplete: boolean;
sourceDocuments: Work[];
}) => {
const [nextIndex, setNextIndex] = useState(0);

useEffect(() => {
if (isStreamingComplete) {
setNextIndex(sourceDocuments.length);
return;
}

if (nextIndex < sourceDocuments.length) {
const timer = setTimeout(() => {
setNextIndex(nextIndex + 1);
}, 382);

return () => clearTimeout(timer);
}
}, [nextIndex, sourceDocuments.length]);
}, [isStreamingComplete, nextIndex, sourceDocuments.length]);

return (
<StyledImages>
Expand Down
23 changes: 12 additions & 11 deletions components/Chat/Response/Response.styled.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,9 @@ const StyledResponse = styled("section", {
position: "relative",
gap: "$gr5",
zIndex: "0",
margin: "0 $gr4",

"@xl": {
margin: "0 $gr4",
},

"@lg": {
margin: "0",
"h1, h2, h3, h4, h5, h6, strong": {
fontFamily: "$northwesternSansBold",
},
});

Expand All @@ -39,9 +34,7 @@ const StyledResponseContent = styled("div", {
});

const StyledResponseWrapper = styled("div", {
background:
"linear-gradient(0deg, $white calc(100% - 100px), $brightBlueB calc(100% + 100px))",
padding: "$gr6 0 $gr4",
padding: "0",
});

const StyledImages = styled("div", {
Expand Down Expand Up @@ -78,9 +71,10 @@ const StyledImages = styled("div", {
});

const StyledQuestion = styled("h3", {
fontFamily: "$northwesternDisplayBold",
fontFamily: "$northwesternSansBold",
fontWeight: "400",
fontSize: "$gr6",
letterSpacing: "-0.012em",
lineHeight: "1.35em",
margin: "0",
padding: "0 0 $gr3 0",
Expand Down Expand Up @@ -112,8 +106,15 @@ const StyledStreamedAnswer = styled("article", {
},
});

const StyledResponseActions = styled("div", {
display: "flex",
gap: "$gr2",
padding: "$gr5 0 0",
});

export {
StyledResponse,
StyledResponseActions,
StyledResponseAside,
StyledResponseContent,
StyledResponseWrapper,
Expand Down
13 changes: 8 additions & 5 deletions components/Chat/Response/Response.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,23 @@ import { Work } from "@nulib/dcapi-types";

interface ChatResponseProps {
isStreamingComplete: boolean;
question: string;
searchTerm: string;
sourceDocuments: Work[];
streamedAnswer?: string;
}

const ChatResponse: React.FC<ChatResponseProps> = ({
isStreamingComplete,
question,
searchTerm,
sourceDocuments,
streamedAnswer,
}) => {
return (
<StyledResponseWrapper>
<Container containerType="wide">
<Container>
<StyledResponse>
<StyledResponseContent>
<StyledQuestion>{question}</StyledQuestion>
<StyledQuestion>{searchTerm}</StyledQuestion>
{streamedAnswer ? (
<ResponseStreamedAnswer
isStreamingComplete={isStreamingComplete}
Expand All @@ -43,7 +43,10 @@ const ChatResponse: React.FC<ChatResponseProps> = ({
</StyledResponseContent>
{sourceDocuments.length > 0 && (
<StyledResponseAside>
<ResponseImages sourceDocuments={sourceDocuments} />
<ResponseImages
isStreamingComplete={isStreamingComplete}
sourceDocuments={sourceDocuments}
/>
</StyledResponseAside>
)}
</StyledResponse>
Expand Down
2 changes: 1 addition & 1 deletion components/Facets/Filter/Clear.styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { styled } from "@/stitches.config";
/* eslint sort-keys: 0 */

const FilterClearStyled = styled("button", {
background: "$white",
background: "transparent",
border: "none",
borderRadius: "50px",
color: "$black50",
Expand Down
2 changes: 1 addition & 1 deletion components/Facets/Filter/Clear.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const FilterClear: React.FC<FilterClearProps> = ({ isModal = false }) => {
isFixed={searchFixed}
isModal={isModal}
>
Clear All
Reset
</FilterClearStyled>
);
};
Expand Down
13 changes: 3 additions & 10 deletions components/Facets/Filter/Filter.styled.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as Dialog from "@radix-ui/react-dialog";

import { IconStyled } from "@/components/Shared/Icon";
import { ValueWrapper } from "@/components/Facets/UserFacets/UserFacets.styled";
import { styled } from "@/stitches.config";
Expand All @@ -15,11 +16,12 @@ const FilterActivate = styled(Dialog.Trigger, {
backgroundColor: "$purple",
border: "0",
color: "$white",
fontFamily: "$northwesternSansBold",
fontFamily: "$northwesternSansRegular",
fontSize: "$gr3",
borderRadius: "50px",
transition: "$dcAll",
padding: "0 $gr3 0 $gr1",
boxShadow: "0px 3px 15px #0002",

[`& ${IconStyled}`]: {
color: "$purple60",
Expand All @@ -29,7 +31,6 @@ const FilterActivate = styled(Dialog.Trigger, {
"&:hover": {
backgroundColor: "$purple120",
color: "$white",
boxShadow: "2px 2px 2px #0002",

[`& ${IconStyled}`]: {
color: "$white",
Expand All @@ -46,14 +47,6 @@ const FilterFloating = styled("div", {
boxShadow: "2px 2px 5px #0002",
borderRadius: "50px",
transition: "$dcAll",

[`& ${FilterActivate}`]: {
boxShadow: "2px 2px 5px #0002",
},

"&:hover": {
boxShadow: "2px 2px 5px #0004",
},
});

const FilterClose = styled(Dialog.Close, {});
Expand Down
12 changes: 12 additions & 0 deletions components/Facets/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import FacetsFilter from "@/components/Facets/Filter/Filter";
import { FilterProvider } from "@/context/filter-context";

const Facets: React.FC = () => {
return (
<FilterProvider>
<FacetsFilter />
</FilterProvider>
);
};

export default Facets;
Loading

0 comments on commit 0230848

Please sign in to comment.