mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-04-22 17:44:58 +01:00
[Query Copilot] Scrollable Copilot tab, improved history and minor fixes (#1536)
Co-authored-by: Predrag Klepic <v-prklepic@microsoft.com>
This commit is contained in:
parent
de3e56bb99
commit
7375cc717c
@ -44,7 +44,6 @@ import ExecuteQueryIcon from "../../../images/ExecuteQuery.svg";
|
|||||||
import HintIcon from "../../../images/Hint.svg";
|
import HintIcon from "../../../images/Hint.svg";
|
||||||
import CopilotIcon from "../../../images/QueryCopilotNewLogo.svg";
|
import CopilotIcon from "../../../images/QueryCopilotNewLogo.svg";
|
||||||
import RecentIcon from "../../../images/Recent.svg";
|
import RecentIcon from "../../../images/Recent.svg";
|
||||||
import SamplePromptsIcon from "../../../images/SamplePromptsIcon.svg";
|
|
||||||
import XErrorMessage from "../../../images/X-errorMessage.svg";
|
import XErrorMessage from "../../../images/X-errorMessage.svg";
|
||||||
import SaveQueryIcon from "../../../images/save-cosmos.svg";
|
import SaveQueryIcon from "../../../images/save-cosmos.svg";
|
||||||
import { useTabs } from "../../hooks/useTabs";
|
import { useTabs } from "../../hooks/useTabs";
|
||||||
@ -122,12 +121,12 @@ export const QueryCopilotTab: React.FC<QueryCopilotTabProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const cachedHistoriesString = localStorage.getItem(`${userContext.databaseAccount?.id}-queryCopilotHistories`);
|
const cachedHistoriesString = localStorage.getItem(`${userContext.databaseAccount?.id}-queryCopilotHistories`);
|
||||||
const cachedHistories = cachedHistoriesString?.split(",");
|
const cachedHistories = cachedHistoriesString?.split("|");
|
||||||
const [histories, setHistories] = useState<string[]>(cachedHistories || []);
|
const [histories, setHistories] = useState<string[]>(cachedHistories || []);
|
||||||
const suggestedPrompts: SuggestedPrompt[] = [
|
const suggestedPrompts: SuggestedPrompt[] = [
|
||||||
{ id: 1, text: "Give me all customers whose names start with C" },
|
{ id: 1, text: 'Show all products that have the word "ultra" in the name or description' },
|
||||||
{ id: 2, text: "Show me all customers" },
|
{ id: 2, text: "What are all of the possible categories for the products, and their counts?" },
|
||||||
{ id: 3, text: "Show me all customers who bought a bike in 2019" },
|
{ id: 3, text: 'Show me all products that have been reviewed by someone with a username that contains "bob"' },
|
||||||
];
|
];
|
||||||
const [filteredHistories, setFilteredHistories] = useState<string[]>(histories);
|
const [filteredHistories, setFilteredHistories] = useState<string[]>(histories);
|
||||||
const [filteredSuggestedPrompts, setFilteredSuggestedPrompts] = useState<SuggestedPrompt[]>(suggestedPrompts);
|
const [filteredSuggestedPrompts, setFilteredSuggestedPrompts] = useState<SuggestedPrompt[]>(suggestedPrompts);
|
||||||
@ -149,9 +148,16 @@ export const QueryCopilotTab: React.FC<QueryCopilotTabProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateHistories = (): void => {
|
const updateHistories = (): void => {
|
||||||
const newHistories = histories.length < 3 ? [userPrompt, ...histories] : [userPrompt, histories[1], histories[2]];
|
const formattedUserPrompt = userPrompt.replace(/\s+/g, " ").trim();
|
||||||
|
const existingHistories = histories.map((history) => history.replace(/\s+/g, " ").trim());
|
||||||
|
|
||||||
|
const updatedHistories = existingHistories.filter(
|
||||||
|
(history) => history.toLowerCase() !== formattedUserPrompt.toLowerCase()
|
||||||
|
);
|
||||||
|
const newHistories = [formattedUserPrompt, ...updatedHistories.slice(0, 2)];
|
||||||
|
|
||||||
setHistories(newHistories);
|
setHistories(newHistories);
|
||||||
localStorage.setItem(`${userContext.databaseAccount.id}-queryCopilotHistories`, newHistories.join(","));
|
localStorage.setItem(`${userContext.databaseAccount.id}-queryCopilotHistories`, newHistories.join("|"));
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateSQLQuery = async (): Promise<void> => {
|
const generateSQLQuery = async (): Promise<void> => {
|
||||||
@ -260,16 +266,17 @@ export const QueryCopilotTab: React.FC<QueryCopilotTabProps> = ({
|
|||||||
disabled: query?.trim() === "",
|
disabled: query?.trim() === "",
|
||||||
};
|
};
|
||||||
|
|
||||||
const samplePromptsBtn = {
|
// Sample Prompts temporary disabled due current design
|
||||||
iconSrc: SamplePromptsIcon,
|
// const samplePromptsBtn = {
|
||||||
iconAlt: "Sample Prompts",
|
// iconSrc: SamplePromptsIcon,
|
||||||
onCommandClick: () => setIsSamplePromptsOpen(true),
|
// iconAlt: "Sample Prompts",
|
||||||
commandButtonLabel: "Sample Prompts",
|
// onCommandClick: () => setIsSamplePromptsOpen(true),
|
||||||
ariaLabel: "Sample Prompts",
|
// commandButtonLabel: "Sample Prompts",
|
||||||
hasPopup: false,
|
// ariaLabel: "Sample Prompts",
|
||||||
};
|
// hasPopup: false,
|
||||||
|
// };
|
||||||
|
|
||||||
return [executeQueryBtn, saveQueryBtn, samplePromptsBtn];
|
return [executeQueryBtn, saveQueryBtn];
|
||||||
};
|
};
|
||||||
const showTeachingBubble = (): void => {
|
const showTeachingBubble = (): void => {
|
||||||
if (!inputEdited.current) {
|
if (!inputEdited.current) {
|
||||||
@ -301,277 +308,283 @@ export const QueryCopilotTab: React.FC<QueryCopilotTabProps> = ({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack className="tab-pane" style={{ padding: 24, width: "100%", height: "100%" }}>
|
<Stack className="tab-pane" style={{ padding: 24, width: "100%" }}>
|
||||||
<Stack horizontal verticalAlign="center">
|
<div style={{ overflowY: "auto", height: "100%" }}>
|
||||||
<Image src={CopilotIcon} />
|
<Stack horizontal verticalAlign="center">
|
||||||
<Text style={{ marginLeft: 8, fontWeight: 600, fontSize: 16 }}>Copilot</Text>
|
<Image src={CopilotIcon} />
|
||||||
</Stack>
|
<Text style={{ marginLeft: 8, fontWeight: 600, fontSize: 16 }}>Copilot</Text>
|
||||||
<Stack horizontal verticalAlign="center" style={{ marginTop: 16, width: "100%", position: "relative" }}>
|
</Stack>
|
||||||
<TextField
|
<Stack horizontal verticalAlign="center" style={{ marginTop: 16, width: "100%", position: "relative" }}>
|
||||||
id="naturalLanguageInput"
|
<TextField
|
||||||
value={userPrompt}
|
id="naturalLanguageInput"
|
||||||
onChange={handleUserPromptChange}
|
value={userPrompt}
|
||||||
onClick={() => {
|
onChange={handleUserPromptChange}
|
||||||
inputEdited.current = true;
|
onClick={() => {
|
||||||
setShowSamplePrompts(true);
|
inputEdited.current = true;
|
||||||
}}
|
setShowSamplePrompts(true);
|
||||||
style={{ lineHeight: 30 }}
|
}}
|
||||||
styles={{ root: { width: "95%" } }}
|
style={{ lineHeight: 30 }}
|
||||||
disabled={isGeneratingQuery}
|
styles={{ root: { width: "95%" } }}
|
||||||
autoComplete="off"
|
disabled={isGeneratingQuery}
|
||||||
/>
|
autoComplete="off"
|
||||||
{copilotTeachingBubbleVisible && (
|
/>
|
||||||
<TeachingBubble
|
{copilotTeachingBubbleVisible && (
|
||||||
calloutProps={{ directionalHint: DirectionalHint.bottomCenter }}
|
<TeachingBubble
|
||||||
target="#naturalLanguageInput"
|
calloutProps={{ directionalHint: DirectionalHint.bottomCenter }}
|
||||||
hasCloseButton={true}
|
target="#naturalLanguageInput"
|
||||||
closeButtonAriaLabel="Close"
|
hasCloseButton={true}
|
||||||
onDismiss={toggleCopilotTeachingBubbleVisible}
|
closeButtonAriaLabel="Close"
|
||||||
hasSmallHeadline={true}
|
onDismiss={toggleCopilotTeachingBubbleVisible}
|
||||||
headline="Write a prompt"
|
hasSmallHeadline={true}
|
||||||
>
|
headline="Write a prompt"
|
||||||
Write a prompt here and Copilot will generate the query for you. You can also choose from our{" "}
|
|
||||||
<Link
|
|
||||||
onClick={() => {
|
|
||||||
setShowSamplePrompts(true);
|
|
||||||
toggleCopilotTeachingBubbleVisible();
|
|
||||||
}}
|
|
||||||
style={{ color: "white", fontWeight: 600 }}
|
|
||||||
>
|
>
|
||||||
sample prompts
|
Write a prompt here and Copilot will generate the query for you. You can also choose from our{" "}
|
||||||
</Link>{" "}
|
<Link
|
||||||
or write your own query
|
onClick={() => {
|
||||||
</TeachingBubble>
|
setShowSamplePrompts(true);
|
||||||
)}
|
toggleCopilotTeachingBubbleVisible();
|
||||||
<IconButton
|
}}
|
||||||
iconProps={{ iconName: "Send" }}
|
style={{ color: "white", fontWeight: 600 }}
|
||||||
disabled={isGeneratingQuery || !userPrompt.trim()}
|
>
|
||||||
style={{ marginLeft: 8 }}
|
sample prompts
|
||||||
onClick={() => {
|
</Link>{" "}
|
||||||
updateHistories();
|
or write your own query
|
||||||
generateSQLQuery();
|
</TeachingBubble>
|
||||||
resetButtonState();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{isGeneratingQuery && <Spinner style={{ marginLeft: 8 }} />}
|
|
||||||
{showSamplePrompts && (
|
|
||||||
<Callout
|
|
||||||
styles={{ root: { minWidth: 400 } }}
|
|
||||||
target="#naturalLanguageInput"
|
|
||||||
isBeakVisible={false}
|
|
||||||
onDismiss={() => setShowSamplePrompts(false)}
|
|
||||||
directionalHintFixed={true}
|
|
||||||
directionalHint={DirectionalHint.bottomLeftEdge}
|
|
||||||
alignTargetEdge={true}
|
|
||||||
gapSpace={4}
|
|
||||||
>
|
|
||||||
<Stack>
|
|
||||||
{filteredHistories?.length > 0 && (
|
|
||||||
<Stack>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
width: "100%",
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: 600,
|
|
||||||
color: "#0078D4",
|
|
||||||
marginLeft: 16,
|
|
||||||
padding: "4px 0",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Recent
|
|
||||||
</Text>
|
|
||||||
{filteredHistories.map((history, i) => (
|
|
||||||
<DefaultButton
|
|
||||||
key={i}
|
|
||||||
onClick={() => {
|
|
||||||
setUserPrompt(history);
|
|
||||||
setShowSamplePrompts(false);
|
|
||||||
}}
|
|
||||||
onRenderIcon={() => <Image src={RecentIcon} />}
|
|
||||||
styles={promptStyles}
|
|
||||||
>
|
|
||||||
{history}
|
|
||||||
</DefaultButton>
|
|
||||||
))}
|
|
||||||
</Stack>
|
|
||||||
)}
|
|
||||||
{filteredSuggestedPrompts?.length > 0 && (
|
|
||||||
<Stack>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
width: "100%",
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: 600,
|
|
||||||
color: "#0078D4",
|
|
||||||
marginLeft: 16,
|
|
||||||
padding: "4px 0",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Suggested Prompts
|
|
||||||
</Text>
|
|
||||||
{filteredSuggestedPrompts.map((prompt) => (
|
|
||||||
<DefaultButton
|
|
||||||
key={prompt.id}
|
|
||||||
onClick={() => {
|
|
||||||
setUserPrompt(prompt.text);
|
|
||||||
setShowSamplePrompts(false);
|
|
||||||
}}
|
|
||||||
onRenderIcon={() => <Image src={HintIcon} />}
|
|
||||||
styles={promptStyles}
|
|
||||||
>
|
|
||||||
{prompt.text}
|
|
||||||
</DefaultButton>
|
|
||||||
))}
|
|
||||||
</Stack>
|
|
||||||
)}
|
|
||||||
{(filteredHistories?.length > 0 || filteredSuggestedPrompts?.length > 0) && (
|
|
||||||
<Stack>
|
|
||||||
<Separator
|
|
||||||
styles={{
|
|
||||||
root: {
|
|
||||||
selectors: { "::before": { background: "#E1DFDD" } },
|
|
||||||
padding: 0,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
width: "100%",
|
|
||||||
fontSize: 14,
|
|
||||||
marginLeft: 16,
|
|
||||||
padding: "4px 0",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Learn about{" "}
|
|
||||||
<Link target="_blank" href="">
|
|
||||||
writing effective prompts
|
|
||||||
</Link>
|
|
||||||
</Text>
|
|
||||||
</Stack>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Callout>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<Text style={{ marginTop: 8, marginBottom: 24, fontSize: 12 }}>
|
|
||||||
AI-generated content can have mistakes. Make sure it's accurate and appropriate before using it.{" "}
|
|
||||||
<Link href="" target="_blank">
|
|
||||||
Read preview terms
|
|
||||||
</Link>
|
|
||||||
{showErrorMessageBar && (
|
|
||||||
<Stack style={{ backgroundColor: "#FEF0F1", padding: "4px 8px" }} horizontal verticalAlign="center">
|
|
||||||
<Image src={XErrorMessage} style={{ marginRight: "8px" }} />
|
|
||||||
<Text style={{ fontSize: 12 }}>
|
|
||||||
We ran into an error and were not able to execute query. Please try again after sometime
|
|
||||||
</Text>
|
|
||||||
</Stack>
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
{showFeedbackBar && (
|
|
||||||
<Stack style={{ backgroundColor: "#FFF8F0", padding: "2px 8px" }} horizontal verticalAlign="center">
|
|
||||||
<Text style={{ fontWeight: 600, fontSize: 12 }}>Provide feedback on the query generated</Text>
|
|
||||||
{showCallout && !hideFeedbackModalForLikedQueries && (
|
|
||||||
<Callout
|
|
||||||
style={{ padding: 8 }}
|
|
||||||
target="#likeBtn"
|
|
||||||
onDismiss={() => {
|
|
||||||
setShowCallout(false);
|
|
||||||
submitFeedback({ generatedQuery, likeQuery, description: "", userPrompt: userPrompt });
|
|
||||||
}}
|
|
||||||
directionalHint={DirectionalHint.topCenter}
|
|
||||||
>
|
|
||||||
<Text>
|
|
||||||
Thank you. Need to give{" "}
|
|
||||||
<Link
|
|
||||||
onClick={() => {
|
|
||||||
setShowCallout(false);
|
|
||||||
useQueryCopilot.getState().openFeedbackModal(generatedQuery, true, userPrompt);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
more feedback?
|
|
||||||
</Link>
|
|
||||||
</Text>
|
|
||||||
</Callout>
|
|
||||||
)}
|
)}
|
||||||
<IconButton
|
<IconButton
|
||||||
id="likeBtn"
|
iconProps={{ iconName: "Send" }}
|
||||||
style={{ marginLeft: 20 }}
|
disabled={isGeneratingQuery || !userPrompt.trim()}
|
||||||
iconProps={{ iconName: likeQuery === true ? "LikeSolid" : "Like" }}
|
style={{ marginLeft: 8 }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setShowCallout(!likeQuery);
|
updateHistories();
|
||||||
setLikeQuery(!likeQuery);
|
generateSQLQuery();
|
||||||
if (dislikeQuery) {
|
resetButtonState();
|
||||||
setDislikeQuery(!dislikeQuery);
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<IconButton
|
{isGeneratingQuery && <Spinner style={{ marginLeft: 8 }} />}
|
||||||
style={{ margin: "0 10px" }}
|
{showSamplePrompts && (
|
||||||
iconProps={{ iconName: dislikeQuery === true ? "DislikeSolid" : "Dislike" }}
|
<Callout
|
||||||
onClick={() => {
|
styles={{ root: { minWidth: 400 } }}
|
||||||
if (!dislikeQuery) {
|
target="#naturalLanguageInput"
|
||||||
useQueryCopilot.getState().openFeedbackModal(generatedQuery, false, userPrompt);
|
isBeakVisible={false}
|
||||||
setLikeQuery(false);
|
onDismiss={() => setShowSamplePrompts(false)}
|
||||||
}
|
directionalHintFixed={true}
|
||||||
setDislikeQuery(!dislikeQuery);
|
directionalHint={DirectionalHint.bottomLeftEdge}
|
||||||
setShowCallout(false);
|
alignTargetEdge={true}
|
||||||
}}
|
gapSpace={4}
|
||||||
/>
|
>
|
||||||
<Separator vertical style={{ color: "#EDEBE9" }} />
|
<Stack>
|
||||||
<CommandBarButton
|
{filteredHistories?.length > 0 && (
|
||||||
onClick={copyGeneratedCode}
|
<Stack>
|
||||||
iconProps={{ iconName: "Copy" }}
|
<Text
|
||||||
style={{ margin: "0 10px", backgroundColor: "#FFF8F0", transition: "background-color 0.3s ease" }}
|
style={{
|
||||||
>
|
width: "100%",
|
||||||
Copy code
|
fontSize: 14,
|
||||||
</CommandBarButton>
|
fontWeight: 600,
|
||||||
<CommandBarButton
|
color: "#0078D4",
|
||||||
onClick={() => {
|
marginLeft: 16,
|
||||||
setShowDeletePopup(true);
|
padding: "4px 0",
|
||||||
}}
|
}}
|
||||||
iconProps={{ iconName: "Delete" }}
|
>
|
||||||
style={{ margin: "0 10px", backgroundColor: "#FFF8F0", transition: "background-color 0.3s ease" }}
|
Recent
|
||||||
>
|
</Text>
|
||||||
Delete code
|
{filteredHistories.map((history, i) => (
|
||||||
</CommandBarButton>
|
<DefaultButton
|
||||||
|
key={i}
|
||||||
|
onClick={() => {
|
||||||
|
setUserPrompt(history);
|
||||||
|
setShowSamplePrompts(false);
|
||||||
|
}}
|
||||||
|
onRenderIcon={() => <Image src={RecentIcon} />}
|
||||||
|
styles={promptStyles}
|
||||||
|
>
|
||||||
|
{history}
|
||||||
|
</DefaultButton>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
{filteredSuggestedPrompts?.length > 0 && (
|
||||||
|
<Stack>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: 600,
|
||||||
|
color: "#0078D4",
|
||||||
|
marginLeft: 16,
|
||||||
|
padding: "4px 0",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Suggested Prompts
|
||||||
|
</Text>
|
||||||
|
{filteredSuggestedPrompts.map((prompt) => (
|
||||||
|
<DefaultButton
|
||||||
|
key={prompt.id}
|
||||||
|
onClick={() => {
|
||||||
|
setUserPrompt(prompt.text);
|
||||||
|
setShowSamplePrompts(false);
|
||||||
|
}}
|
||||||
|
onRenderIcon={() => <Image src={HintIcon} />}
|
||||||
|
styles={promptStyles}
|
||||||
|
>
|
||||||
|
{prompt.text}
|
||||||
|
</DefaultButton>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
{(filteredHistories?.length > 0 || filteredSuggestedPrompts?.length > 0) && (
|
||||||
|
<Stack>
|
||||||
|
<Separator
|
||||||
|
styles={{
|
||||||
|
root: {
|
||||||
|
selectors: { "::before": { background: "#E1DFDD" } },
|
||||||
|
padding: 0,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
fontSize: 14,
|
||||||
|
marginLeft: 16,
|
||||||
|
padding: "4px 0",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Learn about{" "}
|
||||||
|
<Link target="_blank" href="">
|
||||||
|
writing effective prompts
|
||||||
|
</Link>
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Callout>
|
||||||
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
|
||||||
|
|
||||||
<Stack className="tabPaneContentContainer">
|
<Stack style={{ marginTop: 8, marginBottom: 24 }}>
|
||||||
<SplitterLayout vertical={true} primaryIndex={0} primaryMinSize={100} secondaryMinSize={200}>
|
<Text style={{ fontSize: 12 }}>
|
||||||
<EditorReact
|
AI-generated content can have mistakes. Make sure it's accurate and appropriate before using it.{" "}
|
||||||
language={"sql"}
|
<Link href="" target="_blank">
|
||||||
content={query}
|
Read preview terms
|
||||||
isReadOnly={false}
|
</Link>
|
||||||
ariaLabel={"Editing Query"}
|
{showErrorMessageBar && (
|
||||||
lineNumbers={"on"}
|
<Stack style={{ backgroundColor: "#FEF0F1", padding: "4px 8px" }} horizontal verticalAlign="center">
|
||||||
onContentChanged={(newQuery: string) => setQuery(newQuery)}
|
<Image src={XErrorMessage} style={{ marginRight: "8px" }} />
|
||||||
onContentSelected={(selectedQuery: string) => setSelectedQuery(selectedQuery)}
|
<Text style={{ fontSize: 12 }}>
|
||||||
|
We ran into an error and were not able to execute query. Please try again after sometime
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
{showFeedbackBar && (
|
||||||
|
<Stack style={{ backgroundColor: "#FFF8F0", padding: "2px 8px" }} horizontal verticalAlign="center">
|
||||||
|
<Text style={{ fontWeight: 600, fontSize: 12 }}>Provide feedback on the query generated</Text>
|
||||||
|
{showCallout && !hideFeedbackModalForLikedQueries && (
|
||||||
|
<Callout
|
||||||
|
style={{ padding: 8 }}
|
||||||
|
target="#likeBtn"
|
||||||
|
onDismiss={() => {
|
||||||
|
setShowCallout(false);
|
||||||
|
submitFeedback({ generatedQuery, likeQuery, description: "", userPrompt: userPrompt });
|
||||||
|
}}
|
||||||
|
directionalHint={DirectionalHint.topCenter}
|
||||||
|
>
|
||||||
|
<Text>
|
||||||
|
Thank you. Need to give{" "}
|
||||||
|
<Link
|
||||||
|
onClick={() => {
|
||||||
|
setShowCallout(false);
|
||||||
|
useQueryCopilot.getState().openFeedbackModal(generatedQuery, true, userPrompt);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
more feedback?
|
||||||
|
</Link>
|
||||||
|
</Text>
|
||||||
|
</Callout>
|
||||||
|
)}
|
||||||
|
<IconButton
|
||||||
|
id="likeBtn"
|
||||||
|
style={{ marginLeft: 20 }}
|
||||||
|
iconProps={{ iconName: likeQuery === true ? "LikeSolid" : "Like" }}
|
||||||
|
onClick={() => {
|
||||||
|
setShowCallout(!likeQuery);
|
||||||
|
setLikeQuery(!likeQuery);
|
||||||
|
if (dislikeQuery) {
|
||||||
|
setDislikeQuery(!dislikeQuery);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<IconButton
|
||||||
|
style={{ margin: "0 10px" }}
|
||||||
|
iconProps={{ iconName: dislikeQuery === true ? "DislikeSolid" : "Dislike" }}
|
||||||
|
onClick={() => {
|
||||||
|
if (!dislikeQuery) {
|
||||||
|
useQueryCopilot.getState().openFeedbackModal(generatedQuery, false, userPrompt);
|
||||||
|
setLikeQuery(false);
|
||||||
|
}
|
||||||
|
setDislikeQuery(!dislikeQuery);
|
||||||
|
setShowCallout(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Separator vertical style={{ color: "#EDEBE9" }} />
|
||||||
|
<CommandBarButton
|
||||||
|
onClick={copyGeneratedCode}
|
||||||
|
iconProps={{ iconName: "Copy" }}
|
||||||
|
style={{ margin: "0 10px", backgroundColor: "#FFF8F0", transition: "background-color 0.3s ease" }}
|
||||||
|
>
|
||||||
|
Copy code
|
||||||
|
</CommandBarButton>
|
||||||
|
<CommandBarButton
|
||||||
|
onClick={() => {
|
||||||
|
setShowDeletePopup(true);
|
||||||
|
}}
|
||||||
|
iconProps={{ iconName: "Delete" }}
|
||||||
|
style={{ margin: "0 10px", backgroundColor: "#FFF8F0", transition: "background-color 0.3s ease" }}
|
||||||
|
>
|
||||||
|
Delete code
|
||||||
|
</CommandBarButton>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Stack className="tabPaneContentContainer">
|
||||||
|
<SplitterLayout vertical={true} primaryIndex={0} primaryMinSize={100} secondaryMinSize={200}>
|
||||||
|
<EditorReact
|
||||||
|
language={"sql"}
|
||||||
|
content={query}
|
||||||
|
isReadOnly={false}
|
||||||
|
ariaLabel={"Editing Query"}
|
||||||
|
lineNumbers={"on"}
|
||||||
|
onContentChanged={(newQuery: string) => setQuery(newQuery)}
|
||||||
|
onContentSelected={(selectedQuery: string) => setSelectedQuery(selectedQuery)}
|
||||||
|
/>
|
||||||
|
<QueryResultSection
|
||||||
|
isMongoDB={false}
|
||||||
|
queryEditorContent={selectedQuery || query}
|
||||||
|
error={errorMessage}
|
||||||
|
queryResults={queryResults}
|
||||||
|
isExecuting={isExecuting}
|
||||||
|
executeQueryDocumentsPage={(firstItemIndex: number) =>
|
||||||
|
queryDocumentsPerPage(firstItemIndex, queryIterator)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</SplitterLayout>
|
||||||
|
</Stack>
|
||||||
|
<WelcomeModal visible={localStorage.getItem("hideWelcomeModal") !== "true"} />
|
||||||
|
{isSamplePromptsOpen && <SamplePrompts sampleProps={sampleProps} />}
|
||||||
|
{query !== "" && query.trim().length !== 0 && (
|
||||||
|
<DeletePopup
|
||||||
|
showDeletePopup={showDeletePopup}
|
||||||
|
setShowDeletePopup={setShowDeletePopup}
|
||||||
|
setQuery={setQuery}
|
||||||
|
clearFeedback={resetButtonState}
|
||||||
|
showFeedbackBar={setShowFeedbackBar}
|
||||||
/>
|
/>
|
||||||
<QueryResultSection
|
)}
|
||||||
isMongoDB={false}
|
<CopyPopup showCopyPopup={showCopyPopup} setShowCopyPopup={setshowCopyPopup} />
|
||||||
queryEditorContent={selectedQuery || query}
|
</div>
|
||||||
error={errorMessage}
|
|
||||||
queryResults={queryResults}
|
|
||||||
isExecuting={isExecuting}
|
|
||||||
executeQueryDocumentsPage={(firstItemIndex: number) => queryDocumentsPerPage(firstItemIndex, queryIterator)}
|
|
||||||
/>
|
|
||||||
</SplitterLayout>
|
|
||||||
</Stack>
|
|
||||||
<WelcomeModal visible={localStorage.getItem("hideWelcomeModal") !== "true"} />
|
|
||||||
{isSamplePromptsOpen && <SamplePrompts sampleProps={sampleProps} />}
|
|
||||||
{query !== "" && query.trim().length !== 0 && (
|
|
||||||
<DeletePopup
|
|
||||||
showDeletePopup={showDeletePopup}
|
|
||||||
setShowDeletePopup={setShowDeletePopup}
|
|
||||||
setQuery={setQuery}
|
|
||||||
clearFeedback={resetButtonState}
|
|
||||||
showFeedbackBar={setShowFeedbackBar}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<CopyPopup showCopyPopup={showCopyPopup} setShowCopyPopup={setshowCopyPopup} />
|
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -5,133 +5,148 @@ exports[`Query copilot tab snapshot test should render with initial input 1`] =
|
|||||||
className="tab-pane"
|
className="tab-pane"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"height": "100%",
|
|
||||||
"padding": 24,
|
"padding": 24,
|
||||||
"width": "100%",
|
"width": "100%",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Stack
|
<div
|
||||||
horizontal={true}
|
style={
|
||||||
verticalAlign="center"
|
Object {
|
||||||
|
"height": "100%",
|
||||||
|
"overflowY": "auto",
|
||||||
|
}
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<Image
|
<Stack
|
||||||
src=""
|
horizontal={true}
|
||||||
/>
|
verticalAlign="center"
|
||||||
<Text
|
>
|
||||||
|
<Image
|
||||||
|
src=""
|
||||||
|
/>
|
||||||
|
<Text
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"fontSize": 16,
|
||||||
|
"fontWeight": 600,
|
||||||
|
"marginLeft": 8,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Copilot
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
<Stack
|
||||||
|
horizontal={true}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"fontSize": 16,
|
"marginTop": 16,
|
||||||
"fontWeight": 600,
|
"position": "relative",
|
||||||
"marginLeft": 8,
|
"width": "100%",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
verticalAlign="center"
|
||||||
|
>
|
||||||
|
<StyledTextFieldBase
|
||||||
|
autoComplete="off"
|
||||||
|
disabled={false}
|
||||||
|
id="naturalLanguageInput"
|
||||||
|
onChange={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"lineHeight": 30,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
styles={
|
||||||
|
Object {
|
||||||
|
"root": Object {
|
||||||
|
"width": "95%",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value="Write a query to return all records in this table"
|
||||||
|
/>
|
||||||
|
<CustomizedIconButton
|
||||||
|
disabled={false}
|
||||||
|
iconProps={
|
||||||
|
Object {
|
||||||
|
"iconName": "Send",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClick={[Function]}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"marginLeft": 8,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
<Stack
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"marginBottom": 24,
|
||||||
|
"marginTop": 8,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Copilot
|
<Text
|
||||||
</Text>
|
style={
|
||||||
</Stack>
|
Object {
|
||||||
<Stack
|
"fontSize": 12,
|
||||||
horizontal={true}
|
}
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"marginTop": 16,
|
|
||||||
"position": "relative",
|
|
||||||
"width": "100%",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
verticalAlign="center"
|
|
||||||
>
|
|
||||||
<StyledTextFieldBase
|
|
||||||
autoComplete="off"
|
|
||||||
disabled={false}
|
|
||||||
id="naturalLanguageInput"
|
|
||||||
onChange={[Function]}
|
|
||||||
onClick={[Function]}
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"lineHeight": 30,
|
|
||||||
}
|
}
|
||||||
}
|
>
|
||||||
styles={
|
AI-generated content can have mistakes. Make sure it's accurate and appropriate before using it.
|
||||||
Object {
|
|
||||||
"root": Object {
|
|
||||||
"width": "95%",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
value="Write a query to return all records in this table"
|
|
||||||
/>
|
|
||||||
<CustomizedIconButton
|
|
||||||
disabled={false}
|
|
||||||
iconProps={
|
|
||||||
Object {
|
|
||||||
"iconName": "Send",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onClick={[Function]}
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"marginLeft": 8,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"fontSize": 12,
|
|
||||||
"marginBottom": 24,
|
|
||||||
"marginTop": 8,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
AI-generated content can have mistakes. Make sure it's accurate and appropriate before using it.
|
|
||||||
|
|
||||||
<StyledLinkBase
|
<StyledLinkBase
|
||||||
href=""
|
href=""
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
>
|
||||||
|
Read preview terms
|
||||||
|
</StyledLinkBase>
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
<Stack
|
||||||
|
className="tabPaneContentContainer"
|
||||||
>
|
>
|
||||||
Read preview terms
|
<t
|
||||||
</StyledLinkBase>
|
customClassName=""
|
||||||
</Text>
|
onDragEnd={null}
|
||||||
<Stack
|
onDragStart={null}
|
||||||
className="tabPaneContentContainer"
|
onSecondaryPaneSizeChange={null}
|
||||||
>
|
percentage={false}
|
||||||
<t
|
primaryIndex={0}
|
||||||
customClassName=""
|
primaryMinSize={100}
|
||||||
onDragEnd={null}
|
secondaryMinSize={200}
|
||||||
onDragStart={null}
|
vertical={true}
|
||||||
onSecondaryPaneSizeChange={null}
|
>
|
||||||
percentage={false}
|
<EditorReact
|
||||||
primaryIndex={0}
|
ariaLabel="Editing Query"
|
||||||
primaryMinSize={100}
|
content=""
|
||||||
secondaryMinSize={200}
|
isReadOnly={false}
|
||||||
vertical={true}
|
language="sql"
|
||||||
>
|
lineNumbers="on"
|
||||||
<EditorReact
|
onContentChanged={[Function]}
|
||||||
ariaLabel="Editing Query"
|
onContentSelected={[Function]}
|
||||||
content=""
|
/>
|
||||||
isReadOnly={false}
|
<QueryResultSection
|
||||||
language="sql"
|
error=""
|
||||||
lineNumbers="on"
|
executeQueryDocumentsPage={[Function]}
|
||||||
onContentChanged={[Function]}
|
isExecuting={false}
|
||||||
onContentSelected={[Function]}
|
isMongoDB={false}
|
||||||
/>
|
queryEditorContent=""
|
||||||
<QueryResultSection
|
/>
|
||||||
error=""
|
</t>
|
||||||
executeQueryDocumentsPage={[Function]}
|
</Stack>
|
||||||
isExecuting={false}
|
<WelcomeModal
|
||||||
isMongoDB={false}
|
visible={true}
|
||||||
queryEditorContent=""
|
/>
|
||||||
/>
|
<CopyPopup
|
||||||
</t>
|
setShowCopyPopup={[Function]}
|
||||||
</Stack>
|
showCopyPopup={false}
|
||||||
<WelcomeModal
|
/>
|
||||||
visible={true}
|
</div>
|
||||||
/>
|
|
||||||
<CopyPopup
|
|
||||||
setShowCopyPopup={[Function]}
|
|
||||||
showCopyPopup={false}
|
|
||||||
/>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
`;
|
`;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user