From 54d4526b734b313890aca10d5b20cb1ece527673 Mon Sep 17 00:00:00 2001 From: pablodanswer Date: Fri, 9 Aug 2024 18:54:31 -0700 Subject: [PATCH] (Minor) Add cleaner search, feedback model, and connector view (#2098) * add cleaner search, feedback model, and connector view * Update ChatPage.tsx --- .../status/CCPairIndexingStatusTable.tsx | 154 +++++++-------- web/src/app/chat/ChatPage.tsx | 4 - web/src/app/chat/modal/FeedbackModal.tsx | 9 +- web/src/components/icons/icons.tsx | 23 +++ web/src/components/search/SearchAnswer.tsx | 174 +++++++++++++++++ web/src/components/search/SearchSection.tsx | 180 ++---------------- 6 files changed, 291 insertions(+), 253 deletions(-) create mode 100644 web/src/components/search/SearchAnswer.tsx diff --git a/web/src/app/admin/indexing/status/CCPairIndexingStatusTable.tsx b/web/src/app/admin/indexing/status/CCPairIndexingStatusTable.tsx index 004a79f3f9e3..da2d2c50b7f6 100644 --- a/web/src/app/admin/indexing/status/CCPairIndexingStatusTable.tsx +++ b/web/src/app/admin/indexing/status/CCPairIndexingStatusTable.tsx @@ -417,83 +417,85 @@ export function CCPairIndexingStatusTable({ {!shouldExpand ? "Collapse All" : "Expand All"} - {sortedSources.map((source, ind) => { - const sourceMatches = source - .toLowerCase() - .includes(searchTerm.toLowerCase()); - const matchingConnectors = groupedStatuses[source].filter( - (status) => - (status.name || "") - .toLowerCase() - .includes(searchTerm.toLowerCase()) - ); - if (sourceMatches || matchingConnectors.length > 0) { - return ( - -
- - toggleSource(source)} - /> - - {connectorsToggled[source] && ( - <> - - - Name - - - Last Indexed - - - Activity - - {isPaidEnterpriseFeaturesEnabled && ( - - Public - - )} - - Total Docs - - - Last Status - - - - {(sourceMatches - ? groupedStatuses[source] - : matchingConnectors - ).map((ccPairsIndexingStatus) => ( - - ))} - - )} - + {sortedSources + .filter((source) => source != "not_applicable") + .map((source, ind) => { + const sourceMatches = source + .toLowerCase() + .includes(searchTerm.toLowerCase()); + const matchingConnectors = groupedStatuses[source].filter( + (status) => + (status.name || "") + .toLowerCase() + .includes(searchTerm.toLowerCase()) ); - } - return null; - })} + if (sourceMatches || matchingConnectors.length > 0) { + return ( + +
+ + toggleSource(source)} + /> + + {connectorsToggled[source] && ( + <> + + + Name + + + Last Indexed + + + Activity + + {isPaidEnterpriseFeaturesEnabled && ( + + Public + + )} + + Total Docs + + + Last Status + + + + {(sourceMatches + ? groupedStatuses[source] + : matchingConnectors + ).map((ccPairsIndexingStatus) => ( + + ))} + + )} + + ); + } + return null; + })}
diff --git a/web/src/app/chat/ChatPage.tsx b/web/src/app/chat/ChatPage.tsx index cb6041b05c87..b1f79f9d0d7e 100644 --- a/web/src/app/chat/ChatPage.tsx +++ b/web/src/app/chat/ChatPage.tsx @@ -76,10 +76,6 @@ import { useSidebarVisibility } from "@/components/chat_search/hooks"; import { SIDEBAR_TOGGLED_COOKIE_NAME } from "@/components/resizable/constants"; import FixedLogo from "./shared_chat_search/FixedLogo"; import { getSecondsUntilExpiration } from "@/lib/time"; -import { - FullLLMProvider, - LLMProviderDescriptor, -} from "../admin/models/llm/interfaces"; const TEMP_USER_MESSAGE_ID = -1; const TEMP_ASSISTANT_MESSAGE_ID = -2; diff --git a/web/src/app/chat/modal/FeedbackModal.tsx b/web/src/app/chat/modal/FeedbackModal.tsx index fb3b21c15696..908af25f6b4c 100644 --- a/web/src/app/chat/modal/FeedbackModal.tsx +++ b/web/src/app/chat/modal/FeedbackModal.tsx @@ -6,6 +6,7 @@ import { FiThumbsDown, FiThumbsUp } from "react-icons/fi"; import { ModalWrapper } from "./ModalWrapper"; import { DislikeFeedbackIcon, + FilledLikeIcon, LikeFeedbackIcon, } from "@/components/icons/icons"; @@ -53,19 +54,19 @@ export const FeedbackModal = ({ : predefinedNegativeFeedbackOptions; return ( - + <>

{feedbackType === "like" ? ( - ) : ( - )}
diff --git a/web/src/components/icons/icons.tsx b/web/src/components/icons/icons.tsx index a36b0a344b29..709ca94671ca 100644 --- a/web/src/components/icons/icons.tsx +++ b/web/src/components/icons/icons.tsx @@ -1695,6 +1695,29 @@ export const ThumbsUpIconSkeleton = ({ ); }; +export const FilledLikeIcon = ({ + size = 16, + className = defaultTailwindCSS, +}: IconProps) => { + return ( + + + + ); +}; + export const LikeFeedbackIcon = ({ size = 16, className = defaultTailwindCSS, diff --git a/web/src/components/search/SearchAnswer.tsx b/web/src/components/search/SearchAnswer.tsx new file mode 100644 index 000000000000..ce2bb1f85ae0 --- /dev/null +++ b/web/src/components/search/SearchAnswer.tsx @@ -0,0 +1,174 @@ +"use client"; + +import { + Dispatch, + SetStateAction, + useContext, + useEffect, + useRef, + useState, +} from "react"; +import { HoverableIcon } from "../Hoverable"; +import { + DislikeFeedbackIcon, + LikeFeedbackIcon, + ToggleDown, +} from "../icons/icons"; +import { FeedbackType } from "@/app/chat/types"; +import { searchState } from "./SearchSection"; +import { SettingsContext } from "../settings/SettingsProvider"; +import { AnswerSection } from "./results/AnswerSection"; +import { Quote, SearchResponse } from "@/lib/search/interfaces"; +import { QuotesSection } from "./results/QuotesSection"; + +export default function SearchAnswer({ + searchAnswerExpanded, + setSearchAnswerExpanded, + isFetching, + dedupedQuotes, + searchResponse, + setCurrentFeedback, + searchState, +}: { + searchAnswerExpanded: boolean; + setSearchAnswerExpanded: Dispatch>; + isFetching: boolean; + dedupedQuotes: Quote[]; + searchResponse: SearchResponse; + searchState: searchState; + setCurrentFeedback: Dispatch>; +}) { + const [searchAnswerOverflowing, setSearchAnswerOverflowing] = useState(false); + + const { quotes, answer, error } = searchResponse; + const answerContainerRef = useRef(null); + + const handleFeedback = (feedbackType: FeedbackType, messageId: number) => { + setCurrentFeedback([feedbackType, messageId]); + }; + + const settings = useContext(SettingsContext); + + useEffect(() => { + const checkOverflow = () => { + if (answerContainerRef.current) { + const isOverflowing = + answerContainerRef.current.scrollHeight > + answerContainerRef.current.clientHeight; + setSearchAnswerOverflowing(isOverflowing); + } + }; + + checkOverflow(); + window.addEventListener("resize", checkOverflow); + + return () => { + window.removeEventListener("resize", checkOverflow); + }; + }, [answer]); + + return ( +
+
+
+

AI Answer

+ + {searchState == "generating" && ( +
+ Generating response... +
+ )} + + {searchState == "citing" && ( +
+ Creating citations... +
+ )} + + {searchState == "searching" && ( +
+ Searching... +
+ )} + + {searchState == "reading" && ( +
+ + Reading{settings?.isMobile ? "" : " Documents"} + ... + +
+ )} + + {searchState == "analyzing" && ( +
+ + Running + {settings?.isMobile ? "" : " Analysis"}... + +
+ )} +
+ +
+ +
+ + {searchAnswerExpanded || + (!searchAnswerOverflowing && ( +
+ {quotes !== null && quotes.length > 0 && answer && ( + + )} + + {searchResponse.messageId !== null && ( +
+ } + onClick={() => + handleFeedback( + "like", + searchResponse?.messageId as number + ) + } + /> + } + onClick={() => + handleFeedback( + "dislike", + searchResponse?.messageId as number + ) + } + /> +
+ )} +
+ ))} +
+ {!searchAnswerExpanded && searchAnswerOverflowing && ( +
+ )} + + {!searchAnswerExpanded && searchAnswerOverflowing && ( +
+ +
+ )} +
+ ); +} diff --git a/web/src/components/search/SearchSection.tsx b/web/src/components/search/SearchSection.tsx index 523fcdd3c579..1bd0cab3fe11 100644 --- a/web/src/components/search/SearchSection.tsx +++ b/web/src/components/search/SearchSection.tsx @@ -31,22 +31,11 @@ import { SIDEBAR_TOGGLED_COOKIE_NAME } from "../resizable/constants"; import { AGENTIC_SEARCH_TYPE_COOKIE_NAME } from "@/lib/constants"; import Cookies from "js-cookie"; import FixedLogo from "@/app/chat/shared_chat_search/FixedLogo"; -import { AnswerSection } from "./results/AnswerSection"; -import { QuotesSection } from "./results/QuotesSection"; -import { QAFeedbackBlock } from "./QAFeedback"; import { usePopup } from "../admin/connectors/Popup"; -import { ToggleRight } from "@phosphor-icons/react"; -import { - DislikeFeedbackIcon, - LikeFeedbackIcon, - ToggleDown, - ToggleUp, -} from "../icons/icons"; -import { CustomTooltip, TooltipGroup } from "../tooltip/CustomTooltip"; -import { HoverableIcon } from "../Hoverable"; import { FeedbackType } from "@/app/chat/types"; import { FeedbackModal } from "@/app/chat/modal/FeedbackModal"; import { handleChatFeedback } from "@/app/chat/lib"; +import SearchAnswer from "./SearchAnswer"; export type searchState = | "input" @@ -111,7 +100,6 @@ export const SearchSection = ({ }); const [agentic, setAgentic] = useState(agenticSearchEnabled); - const [searchAnswerExpanded, setSearchAnswerExpanded] = useState(false); const toggleAgentic = () => { Cookies.set( @@ -376,6 +364,7 @@ export const SearchSection = ({ setSearchState("input"); } }; + const [searchAnswerExpanded, setSearchAnswerExpanded] = useState(false); const resetInput = (finalized?: boolean) => { setSweep(false); @@ -546,32 +535,6 @@ export const SearchSection = ({ [FeedbackType, number] | null >(null); - // - const [searchAnswerOverflowing, setSearchAnswerOverflowing] = useState(false); - const answerContainerRef = useRef(null); - - const handleFeedback = (feedbackType: FeedbackType, messageId: number) => { - setCurrentFeedback([feedbackType, messageId]); - }; - - useEffect(() => { - const checkOverflow = () => { - if (answerContainerRef.current) { - const isOverflowing = - answerContainerRef.current.scrollHeight > - answerContainerRef.current.clientHeight; - setSearchAnswerOverflowing(isOverflowing); - } - }; - - checkOverflow(); - window.addEventListener("resize", checkOverflow); - - return () => { - window.removeEventListener("resize", checkOverflow); - }; - }, [answer]); - const onFeedback = async ( messageId: number, feedbackType: FeedbackType, @@ -758,136 +721,15 @@ export const SearchSection = ({ />

{!firstSearch && ( -
-
-
-

- AI Answer -

- - {searchState == "generating" && ( -
- - Generating response... - -
- )} - - {searchState == "citing" && ( -
- - Creating citations... - -
- )} - - {searchState == "searching" && ( -
- Searching... -
- )} - - {searchState == "reading" && ( -
- - Reading{settings?.isMobile ? "" : " Documents"} - ... - -
- )} - - {searchState == "analyzing" && ( -
- - Running - {settings?.isMobile ? "" : " Analysis"}... - -
- )} -
- -
- -
- - {searchAnswerExpanded || - (!searchAnswerOverflowing && ( -
- {quotes !== null && - quotes.length > 0 && - answer && ( - - )} - - {searchResponse.messageId !== null && ( -
- } - onClick={() => - handleFeedback( - "like", - searchResponse?.messageId as number - ) - } - /> - } - onClick={() => - handleFeedback( - "dislike", - searchResponse?.messageId as number - ) - } - /> -
- )} -
- ))} -
- {!searchAnswerExpanded && searchAnswerOverflowing && ( -
- )} - - {!searchAnswerExpanded && searchAnswerOverflowing && ( -
- -
- )} -
+ )} {!settings?.isMobile && (