P1, P2 bug fixes for private preview (#1657)

* P1 bug fix for private preview

* Add updated snapshot files

* Fix failing unit test

* Fix unit tests and update snapshot
This commit is contained in:
sunghyunkang1111 2023-10-12 21:54:01 -05:00 committed by GitHub
parent 9669301d14
commit d376a7463c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 1373 additions and 1269 deletions

View File

@ -102,7 +102,7 @@ describe("Query Copilot Feedback Modal snapshot test", () => {
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
it("should submit submission", () => { it("should not submit submission if required description field is null", () => {
const explorer = new Explorer(); const explorer = new Explorer();
const wrapper = shallow(<QueryCopilotFeedbackModal explorer={explorer} />); const wrapper = shallow(<QueryCopilotFeedbackModal explorer={explorer} />);
@ -110,12 +110,24 @@ describe("Query Copilot Feedback Modal snapshot test", () => {
submitButton.simulate("click"); submitButton.simulate("click");
wrapper.setProps({}); wrapper.setProps({});
expect(SubmitFeedback).toHaveBeenCalledTimes(0);
});
it("should submit submission", () => {
useQueryCopilot.getState().openFeedbackModal("test query", false, "test prompt");
const explorer = new Explorer();
const wrapper = shallow(<QueryCopilotFeedbackModal explorer={explorer} />);
const submitButton = wrapper.find("form");
submitButton.simulate("submit");
wrapper.setProps({});
expect(SubmitFeedback).toHaveBeenCalledTimes(1); expect(SubmitFeedback).toHaveBeenCalledTimes(1);
expect(SubmitFeedback).toHaveBeenCalledWith({ expect(SubmitFeedback).toHaveBeenCalledWith({
params: { params: {
likeQuery: false, likeQuery: false,
generatedQuery: "", generatedQuery: "test query",
userPrompt: "", userPrompt: "test prompt",
description: "", description: "",
contact: getUserEmail(), contact: getUserEmail(),
}, },

View File

@ -25,93 +25,94 @@ export const QueryCopilotFeedbackModal = ({ explorer }: { explorer: Explorer }):
closeFeedbackModal, closeFeedbackModal,
setHideFeedbackModalForLikedQueries, setHideFeedbackModalForLikedQueries,
} = useQueryCopilot(); } = useQueryCopilot();
const [isContactAllowed, setIsContactAllowed] = React.useState<boolean>(true); const [isContactAllowed, setIsContactAllowed] = React.useState<boolean>(false);
const [description, setDescription] = React.useState<string>(""); const [description, setDescription] = React.useState<string>("");
const [doNotShowAgainChecked, setDoNotShowAgainChecked] = React.useState<boolean>(false); const [doNotShowAgainChecked, setDoNotShowAgainChecked] = React.useState<boolean>(false);
const [contact, setContact] = React.useState<string>(getUserEmail()); const [contact, setContact] = React.useState<string>(getUserEmail());
const handleSubmit = () => {
closeFeedbackModal();
setHideFeedbackModalForLikedQueries(doNotShowAgainChecked);
SubmitFeedback({
params: { generatedQuery, likeQuery, description, userPrompt, contact },
explorer: explorer,
});
};
return ( return (
<Modal isOpen={showFeedbackModal}> <Modal isOpen={showFeedbackModal}>
<Stack style={{ padding: 24 }}> <form onSubmit={handleSubmit}>
<Stack horizontal horizontalAlign="space-between"> <Stack style={{ padding: 24 }}>
<Text style={{ fontSize: 20, fontWeight: 600, marginBottom: 20 }}>Send feedback to Microsoft</Text> <Stack horizontal horizontalAlign="space-between">
<IconButton iconProps={{ iconName: "Cancel" }} onClick={() => closeFeedbackModal()} /> <Text style={{ fontSize: 20, fontWeight: 600, marginBottom: 20 }}>Send feedback to Microsoft</Text>
</Stack> <IconButton iconProps={{ iconName: "Cancel" }} onClick={() => closeFeedbackModal()} />
<Text style={{ fontSize: 14, marginBottom: 14 }}>Your feedback will help improve the experience.</Text> </Stack>
<TextField <Text style={{ fontSize: 14, marginBottom: 14 }}>Your feedback will help improve the experience.</Text>
styles={{ root: { marginBottom: 14 } }} <TextField
label="Description" styles={{ root: { marginBottom: 14 } }}
required label="Description"
placeholder="Provide more details" required
value={description} placeholder="Provide more details"
onChange={(_, newValue) => setDescription(newValue)} value={description}
multiline onChange={(_, newValue) => setDescription(newValue)}
rows={3} multiline
/> rows={3}
<TextField
styles={{ root: { marginBottom: 14 } }}
label="Query generated"
defaultValue={generatedQuery}
readOnly
/>
<ChoiceGroup
styles={{
root: {
marginBottom: 14,
},
flexContainer: {
selectors: {
".ms-ChoiceField-field::before": { marginTop: 4 },
".ms-ChoiceField-field::after": { marginTop: 4 },
".ms-ChoiceFieldLabel": { paddingLeft: 6 },
},
},
}}
label="May we contact you about your feedback?"
options={[
{ key: "yes", text: "Yes, you may contact me." },
{ key: "no", text: "No, do not contact me." },
]}
selectedKey={isContactAllowed ? "yes" : "no"}
onChange={(_, option) => {
setIsContactAllowed(option.key === "yes");
setContact(option.key === "yes" ? getUserEmail() : "");
}}
></ChoiceGroup>
<Text style={{ fontSize: 12, marginBottom: 14 }}>
By pressing submit, your feedback will be used to improve Microsoft products and services. Please see the{" "}
{
<Link href="https://privacy.microsoft.com/privacystatement" target="_blank">
Privacy statement
</Link>
}{" "}
for more information.
</Text>
{likeQuery && (
<Checkbox
styles={{ label: { paddingLeft: 0 }, root: { marginBottom: 14 } }}
label="Don't show me this next time"
checked={doNotShowAgainChecked}
onChange={(_, checked) => setDoNotShowAgainChecked(checked)}
/> />
)} <TextField
<Stack horizontal horizontalAlign="end"> styles={{ root: { marginBottom: 14 } }}
<PrimaryButton label="Query generated"
styles={{ root: { marginRight: 8 } }} defaultValue={generatedQuery}
onClick={() => { readOnly
closeFeedbackModal(); />
setHideFeedbackModalForLikedQueries(doNotShowAgainChecked); <ChoiceGroup
SubmitFeedback({ styles={{
params: { generatedQuery, likeQuery, description, userPrompt, contact }, root: {
explorer: explorer, marginBottom: 14,
}); },
flexContainer: {
selectors: {
".ms-ChoiceField-field::before": { marginTop: 4 },
".ms-ChoiceField-field::after": { marginTop: 4 },
".ms-ChoiceFieldLabel": { paddingLeft: 6 },
},
},
}} }}
> label="May we contact you about your feedback?"
Submit options={[
</PrimaryButton> { key: "yes", text: "Yes, you may contact me." },
<DefaultButton onClick={() => closeFeedbackModal()}>Cancel</DefaultButton> { key: "no", text: "No, do not contact me." },
]}
selectedKey={isContactAllowed ? "yes" : "no"}
onChange={(_, option) => {
setIsContactAllowed(option.key === "yes");
setContact(option.key === "yes" ? getUserEmail() : "");
}}
></ChoiceGroup>
<Text style={{ fontSize: 12, marginBottom: 14 }}>
By pressing submit, your feedback will be used to improve Microsoft products and services. Please see the{" "}
{
<Link href="https://privacy.microsoft.com/privacystatement" target="_blank">
Privacy statement
</Link>
}{" "}
for more information.
</Text>
{likeQuery && (
<Checkbox
styles={{ label: { paddingLeft: 0 }, root: { marginBottom: 14 } }}
label="Don't show me this next time"
checked={doNotShowAgainChecked}
onChange={(_, checked) => setDoNotShowAgainChecked(checked)}
/>
)}
<Stack horizontal horizontalAlign="end">
<PrimaryButton styles={{ root: { marginRight: 8 } }} type="submit">
Submit
</PrimaryButton>
<DefaultButton onClick={() => closeFeedbackModal()}>Cancel</DefaultButton>
</Stack>
</Stack> </Stack>
</Stack> </form>
</Modal> </Modal>
); );
}; };

View File

@ -237,7 +237,7 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
const showTeachingBubble = (): void => { const showTeachingBubble = (): void => {
if (!inputEdited.current) { if (!inputEdited.current) {
setTimeout(() => { setTimeout(() => {
if (!inputEdited.current) { if (!inputEdited.current && !isWelcomModalVisible()) {
toggleCopilotTeachingBubbleVisible(); toggleCopilotTeachingBubbleVisible();
inputEdited.current = true; inputEdited.current = true;
} }
@ -245,6 +245,10 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
} }
}; };
const isWelcomModalVisible = (): boolean => {
return localStorage.getItem("hideWelcomeModal") !== "true";
};
const clearFeedback = () => { const clearFeedback = () => {
resetButtonState(); resetButtonState();
resetQueryResults(); resetQueryResults();
@ -297,7 +301,7 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
setShowSamplePrompts(true); setShowSamplePrompts(true);
}} }}
onKeyDown={(e) => { onKeyDown={(e) => {
if (e.key === "Enter") { if (e.key === "Enter" && userPrompt) {
inputEdited.current = true; inputEdited.current = true;
startGenerateQueryProcess(); startGenerateQueryProcess();
} }
@ -533,7 +537,7 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
iconProps={{ iconName: "Copy" }} iconProps={{ iconName: "Copy" }}
style={{ margin: "0 10px", backgroundColor: "#FFF8F0", transition: "background-color 0.3s ease" }} style={{ margin: "0 10px", backgroundColor: "#FFF8F0", transition: "background-color 0.3s ease" }}
> >
Copy code Copy query
</CommandBarButton> </CommandBarButton>
<CommandBarButton <CommandBarButton
onClick={() => { onClick={() => {
@ -542,11 +546,11 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
iconProps={{ iconName: "Delete" }} iconProps={{ iconName: "Delete" }}
style={{ margin: "0 10px", backgroundColor: "#FFF8F0", transition: "background-color 0.3s ease" }} style={{ margin: "0 10px", backgroundColor: "#FFF8F0", transition: "background-color 0.3s ease" }}
> >
Delete code Delete query
</CommandBarButton> </CommandBarButton>
</Stack> </Stack>
)} )}
<WelcomeModal visible={localStorage.getItem("hideWelcomeModal") !== "true"} /> <WelcomeModal visible={isWelcomModalVisible()} />
{isSamplePromptsOpen && <SamplePrompts sampleProps={sampleProps} />} {isSamplePromptsOpen && <SamplePrompts sampleProps={sampleProps} />}
{query !== "" && query.trim().length !== 0 && ( {query !== "" && query.trim().length !== 0 && (
<DeletePopup <DeletePopup

View File

@ -21,8 +21,13 @@ import * as StringUtility from "../../Shared/StringUtility";
export const QueryCopilotTab: React.FC<QueryCopilotProps> = ({ explorer }: QueryCopilotProps): JSX.Element => { export const QueryCopilotTab: React.FC<QueryCopilotProps> = ({ explorer }: QueryCopilotProps): JSX.Element => {
const { query, setQuery, selectedQuery, setSelectedQuery, isGeneratingQuery } = useQueryCopilot(); const { query, setQuery, selectedQuery, setSelectedQuery, isGeneratingQuery } = useQueryCopilot();
const cachedCopilotToggleStatus = localStorage.getItem(`${userContext.databaseAccount?.id}-queryCopilotToggleStatus`); const cachedCopilotToggleStatus: string = localStorage.getItem(
const [copilotActive, setCopilotActive] = useState<boolean>(StringUtility.toBoolean(cachedCopilotToggleStatus)); `${userContext.databaseAccount?.id}-queryCopilotToggleStatus`,
);
const copilotInitialActive: boolean = cachedCopilotToggleStatus
? StringUtility.toBoolean(cachedCopilotToggleStatus)
: true;
const [copilotActive, setCopilotActive] = useState<boolean>(copilotInitialActive);
const getCommandbarButtons = (): CommandButtonComponentProps[] => { const getCommandbarButtons = (): CommandButtonComponentProps[] => {
const executeQueryBtnLabel = selectedQuery ? "Execute Selection" : "Execute Query"; const executeQueryBtnLabel = selectedQuery ? "Execute Selection" : "Execute Query";
@ -87,7 +92,7 @@ export const QueryCopilotTab: React.FC<QueryCopilotProps> = ({ explorer }: Query
<QueryCopilotPromptbar explorer={explorer} toggleCopilot={toggleCopilot}></QueryCopilotPromptbar> <QueryCopilotPromptbar explorer={explorer} toggleCopilot={toggleCopilot}></QueryCopilotPromptbar>
)} )}
<Stack className="tabPaneContentContainer"> <Stack className="tabPaneContentContainer">
<SplitterLayout vertical={true} primaryIndex={0} primaryMinSize={100} secondaryMinSize={200}> <SplitterLayout percentage={true} vertical={true} primaryIndex={0} primaryMinSize={30} secondaryMinSize={70}>
<EditorReact <EditorReact
language={"sql"} language={"sql"}
content={query} content={query}

View File

@ -17,6 +17,37 @@ exports[`Query copilot tab snapshot test should render with initial input 1`] =
} }
} }
> >
<QueryCopilotPromptbar
explorer={
Explorer {
"_isInitializingNotebooks": false,
"_resetNotebookWorkspace": [Function],
"isFixedCollectionWithSharedThroughputSupported": [Function],
"isTabsContentExpanded": [Function],
"onRefreshDatabasesKeyPress": [Function],
"onRefreshResourcesClick": [Function],
"phoenixClient": PhoenixClient {
"armResourceId": undefined,
"retryOptions": Object {
"maxTimeout": 5000,
"minTimeout": 5000,
"retries": 3,
},
},
"provideFeedbackEmail": [Function],
"queriesClient": QueriesClient {
"container": [Circular],
},
"refreshNotebookList": [Function],
"resourceTree": ResourceTreeAdapter {
"container": [Circular],
"copyNotebook": [Function],
"parameters": [Function],
},
}
}
toggleCopilot={[Function]}
/>
<Stack <Stack
className="tabPaneContentContainer" className="tabPaneContentContainer"
> >
@ -25,10 +56,10 @@ exports[`Query copilot tab snapshot test should render with initial input 1`] =
onDragEnd={null} onDragEnd={null}
onDragStart={null} onDragStart={null}
onSecondaryPaneSizeChange={null} onSecondaryPaneSizeChange={null}
percentage={false} percentage={true}
primaryIndex={0} primaryIndex={0}
primaryMinSize={100} primaryMinSize={30}
secondaryMinSize={200} secondaryMinSize={70}
vertical={true} vertical={true}
> >
<EditorReact <EditorReact

View File

@ -128,7 +128,7 @@ export const useQueryCopilot: QueryCopilotStore = create((set) => ({
openFeedbackModal: (generatedQuery: string, likeQuery: boolean, userPrompt: string) => openFeedbackModal: (generatedQuery: string, likeQuery: boolean, userPrompt: string) =>
set({ generatedQuery, likeQuery, userPrompt, showFeedbackModal: true }), set({ generatedQuery, likeQuery, userPrompt, showFeedbackModal: true }),
closeFeedbackModal: () => set({ generatedQuery: "", likeQuery: false, userPrompt: "", showFeedbackModal: false }), closeFeedbackModal: () => set({ showFeedbackModal: false }),
setHideFeedbackModalForLikedQueries: (hideFeedbackModalForLikedQueries: boolean) => setHideFeedbackModalForLikedQueries: (hideFeedbackModalForLikedQueries: boolean) =>
set({ hideFeedbackModalForLikedQueries }), set({ hideFeedbackModalForLikedQueries }),
refreshCorrelationId: () => set({ correlationId: guid() }), refreshCorrelationId: () => set({ correlationId: guid() }),