From 143f7d8f2cda4343caa465d4f818e0e3e04bbadd Mon Sep 17 00:00:00 2001 From: Predrag Klepic <60631598+Klepic95@users.noreply.github.com> Date: Mon, 21 Aug 2023 11:19:04 +0200 Subject: [PATCH] [Query Copilot] Copilot V2 Retrieving bubble (#1579) * Changing order of the features * test name changed * updates snapshots * Bubble implementation * Bubble tests implemented * Correction for CopilotSampleDB implementation * rollback to previous query tab changes --------- Co-authored-by: Predrag Klepic --- images/StopGenerating.svg | 3 + .../Bubbles/Retriveing/RetrievingBubble.css | 8 + .../Retriveing/RetrievingBubble.test.tsx | 62 ++++++ .../Bubbles/Retriveing/RetrievingBubble.tsx | 98 ++++++++++ .../RetrievingBubble.test.tsx.snap | 183 ++++++++++++++++++ .../QueryCopilot/V2/Footer/Footer.tsx | 2 + .../V2/Modal/WelcomeSidebarModal.test.tsx | 2 +- .../WelcomeSidebarModal.test.tsx.snap | 2 +- .../V2/Sidebar/QueryCopilotSidebar.test.tsx | 2 +- .../V2/Sidebar/QueryCopilotSidebar.tsx | 4 + .../QueryCopilotSidebar.test.tsx.snap | 2 +- src/Platform/Hosted/extractFeatures.ts | 2 +- src/hooks/useQueryCopilot.ts | 10 + 13 files changed, 375 insertions(+), 5 deletions(-) create mode 100644 images/StopGenerating.svg create mode 100644 src/Explorer/QueryCopilot/V2/Bubbles/Retriveing/RetrievingBubble.css create mode 100644 src/Explorer/QueryCopilot/V2/Bubbles/Retriveing/RetrievingBubble.test.tsx create mode 100644 src/Explorer/QueryCopilot/V2/Bubbles/Retriveing/RetrievingBubble.tsx create mode 100644 src/Explorer/QueryCopilot/V2/Bubbles/Retriveing/__snapshots__/RetrievingBubble.test.tsx.snap diff --git a/images/StopGenerating.svg b/images/StopGenerating.svg new file mode 100644 index 000000000..7509c6c1a --- /dev/null +++ b/images/StopGenerating.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/Explorer/QueryCopilot/V2/Bubbles/Retriveing/RetrievingBubble.css b/src/Explorer/QueryCopilot/V2/Bubbles/Retriveing/RetrievingBubble.css new file mode 100644 index 000000000..88b05da64 --- /dev/null +++ b/src/Explorer/QueryCopilot/V2/Bubbles/Retriveing/RetrievingBubble.css @@ -0,0 +1,8 @@ +@keyframes loadingAnimation { + 0% { + transform: translateX(-100%); + } + 100% { + transform: translateX(100%); + } +} diff --git a/src/Explorer/QueryCopilot/V2/Bubbles/Retriveing/RetrievingBubble.test.tsx b/src/Explorer/QueryCopilot/V2/Bubbles/Retriveing/RetrievingBubble.test.tsx new file mode 100644 index 000000000..a3356d045 --- /dev/null +++ b/src/Explorer/QueryCopilot/V2/Bubbles/Retriveing/RetrievingBubble.test.tsx @@ -0,0 +1,62 @@ +import { DefaultButton } from "@fluentui/react"; +import { shallow } from "enzyme"; +import React from "react"; +import { RetrievingBubble } from "./RetrievingBubble"; + +const mockUseQueryCopilot = { + isGeneratingQuery: false, + setIsGeneratingQuery: jest.fn(), + isGeneratingExplanation: false, + setIsGeneratingExplanation: jest.fn(), + shouldIncludeInMessages: true, + setShouldIncludeInMessages: jest.fn(), +}; + +jest.mock("hooks/useQueryCopilot", () => ({ + useQueryCopilot: jest.fn(() => mockUseQueryCopilot), +})); + +describe("RetrievingBubble", () => { + beforeEach(() => { + jest.clearAllMocks(); + mockUseQueryCopilot.isGeneratingQuery = false; + mockUseQueryCopilot.isGeneratingExplanation = false; + mockUseQueryCopilot.setIsGeneratingQuery.mockClear(); + mockUseQueryCopilot.setIsGeneratingExplanation.mockClear(); + mockUseQueryCopilot.setShouldIncludeInMessages.mockClear(); + }); + + it("should render properly when isGeneratingQuery is true", () => { + mockUseQueryCopilot.isGeneratingQuery = true; + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); + }); + + it("should render properly when isGeneratingExplanation is true", () => { + mockUseQueryCopilot.isGeneratingExplanation = true; + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); + }); + + it("when isGeneratingQuery is true clicking stop generating button invokes the correct callbacks", () => { + mockUseQueryCopilot.isGeneratingQuery = true; + + const wrapper = shallow(); + wrapper.find(DefaultButton).at(0).simulate("click"); + + expect(mockUseQueryCopilot.setIsGeneratingQuery).toHaveBeenCalledWith(false); + expect(mockUseQueryCopilot.setIsGeneratingExplanation).toHaveBeenCalledTimes(0); + expect(mockUseQueryCopilot.setShouldIncludeInMessages).toHaveBeenCalledWith(false); + }); + + it("when isGeneratingExplanation is true clicking stop generating button invokes the correct callbacks", () => { + mockUseQueryCopilot.isGeneratingExplanation = true; + + const wrapper = shallow(); + wrapper.find(DefaultButton).at(0).simulate("click"); + + expect(mockUseQueryCopilot.setIsGeneratingQuery).toHaveBeenCalledTimes(0); + expect(mockUseQueryCopilot.setIsGeneratingExplanation).toHaveBeenCalledWith(false); + expect(mockUseQueryCopilot.setShouldIncludeInMessages).toHaveBeenCalledWith(false); + }); +}); diff --git a/src/Explorer/QueryCopilot/V2/Bubbles/Retriveing/RetrievingBubble.tsx b/src/Explorer/QueryCopilot/V2/Bubbles/Retriveing/RetrievingBubble.tsx new file mode 100644 index 000000000..92c3c734a --- /dev/null +++ b/src/Explorer/QueryCopilot/V2/Bubbles/Retriveing/RetrievingBubble.tsx @@ -0,0 +1,98 @@ +import { DefaultButton, Image, Stack, Text } from "@fluentui/react"; +import { useQueryCopilot } from "hooks/useQueryCopilot"; +import React from "react"; +import StopGeneratingIcon from "../../../../../../images/StopGenerating.svg"; +import "./RetrievingBubble.css"; + +export const RetrievingBubble = (): JSX.Element => { + const { + isGeneratingQuery, + setIsGeneratingQuery, + isGeneratingExplanation, + setIsGeneratingExplanation, + shouldIncludeInMessages, + setShouldIncludeInMessages, + } = useQueryCopilot(); + + const stopGenerating = () => { + if (isGeneratingQuery) { + setIsGeneratingQuery(false); + } + if (isGeneratingExplanation) { + setIsGeneratingExplanation(false); + } + if (shouldIncludeInMessages) { + setShouldIncludeInMessages(false); + } + }; + + const bubbleContent = (bubbleType: string) => { + return ( + + + Retriveing {bubbleType} + +
+
+
+ + } + > + Stop generating + + +
+ ); + }; + + return ( + <> + {isGeneratingQuery && bubbleContent("queries")} + {isGeneratingExplanation && bubbleContent("explanation")} + + ); +}; diff --git a/src/Explorer/QueryCopilot/V2/Bubbles/Retriveing/__snapshots__/RetrievingBubble.test.tsx.snap b/src/Explorer/QueryCopilot/V2/Bubbles/Retriveing/__snapshots__/RetrievingBubble.test.tsx.snap new file mode 100644 index 000000000..04be145d4 --- /dev/null +++ b/src/Explorer/QueryCopilot/V2/Bubbles/Retriveing/__snapshots__/RetrievingBubble.test.tsx.snap @@ -0,0 +1,183 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`RetrievingBubble should render properly when isGeneratingExplanation is true 1`] = ` + + + + Retriveing + explanation + +
+
+
+ + + Stop generating + + + + +`; + +exports[`RetrievingBubble should render properly when isGeneratingQuery is true 1`] = ` + + + + Retriveing + queries + +
+
+
+ + + Stop generating + + + + +`; diff --git a/src/Explorer/QueryCopilot/V2/Footer/Footer.tsx b/src/Explorer/QueryCopilot/V2/Footer/Footer.tsx index 8afb93424..f8da7c56d 100644 --- a/src/Explorer/QueryCopilot/V2/Footer/Footer.tsx +++ b/src/Explorer/QueryCopilot/V2/Footer/Footer.tsx @@ -12,6 +12,7 @@ export const Footer: React.FC = (): JSX.Element => { setChatMessages, isSamplePromptsOpen, setIsSamplePromptsOpen, + setIsGeneratingQuery, } = useQueryCopilot(); const promptStyles: IButtonStyles = { @@ -36,6 +37,7 @@ export const Footer: React.FC = (): JSX.Element => { if (userPrompt.trim() !== "") { setChatMessages([...chatMessages, userPrompt]); setUserPrompt(""); + setIsGeneratingQuery(true); } }; diff --git a/src/Explorer/QueryCopilot/V2/Modal/WelcomeSidebarModal.test.tsx b/src/Explorer/QueryCopilot/V2/Modal/WelcomeSidebarModal.test.tsx index 2762c784e..8576d34ca 100644 --- a/src/Explorer/QueryCopilot/V2/Modal/WelcomeSidebarModal.test.tsx +++ b/src/Explorer/QueryCopilot/V2/Modal/WelcomeSidebarModal.test.tsx @@ -2,7 +2,7 @@ import { shallow } from "enzyme"; import React from "react"; import { WelcomeSidebarModal } from "./WelcomeSidebarModal"; -describe("Footer snapshot test", () => { +describe("WelcomeSidebarModal snapshot test", () => { it("should render ", () => { const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); diff --git a/src/Explorer/QueryCopilot/V2/Modal/__snapshots__/WelcomeSidebarModal.test.tsx.snap b/src/Explorer/QueryCopilot/V2/Modal/__snapshots__/WelcomeSidebarModal.test.tsx.snap index 20153612c..77711e7a2 100644 --- a/src/Explorer/QueryCopilot/V2/Modal/__snapshots__/WelcomeSidebarModal.test.tsx.snap +++ b/src/Explorer/QueryCopilot/V2/Modal/__snapshots__/WelcomeSidebarModal.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Footer snapshot test should render 1`] = ` +exports[`WelcomeSidebarModal snapshot test should render 1`] = ` { +describe("QueryCopilotSidebar snapshot test", () => { it("should render ", () => { const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); diff --git a/src/Explorer/QueryCopilot/V2/Sidebar/QueryCopilotSidebar.tsx b/src/Explorer/QueryCopilot/V2/Sidebar/QueryCopilotSidebar.tsx index f773d100f..613cce57d 100644 --- a/src/Explorer/QueryCopilot/V2/Sidebar/QueryCopilotSidebar.tsx +++ b/src/Explorer/QueryCopilot/V2/Sidebar/QueryCopilotSidebar.tsx @@ -1,4 +1,5 @@ import { Stack } from "@fluentui/react"; +import { RetrievingBubble } from "Explorer/QueryCopilot/V2/Bubbles/Retriveing/RetrievingBubble"; import { SampleBubble } from "Explorer/QueryCopilot/V2/Bubbles/Sample/SampleBubble"; import { WelcomeBubble } from "Explorer/QueryCopilot/V2/Bubbles/Welcome/WelcomeBubble"; import { Footer } from "Explorer/QueryCopilot/V2/Footer/Footer"; @@ -47,6 +48,9 @@ export const QueryCopilotSidebar: React.FC = (): JSX.Element => { {message} ))} + + + {chatMessages.length === 0 && }