[Query Copilot v2] Implementing output bubble (#1587)
* Implementing output bubble * Fix lint * Run prettier
3
images/CopilotCopy.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="19" height="17" viewBox="0 0 19 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7 0C5.89543 0 5 0.895431 5 2V12C5 13.1046 5.89543 14 7 14H13C14.1046 14 15 13.1046 15 12V2C15 0.89543 14.1046 0 13 0H7ZM6 2C6 1.44772 6.44772 1 7 1H13C13.5523 1 14 1.44772 14 2V12C14 12.5523 13.5523 13 13 13H7C6.44772 13 6 12.5523 6 12V2ZM3 4.00001C3 3.25973 3.4022 2.61339 4 2.26758V12.5C4 13.8807 5.11929 15 6.5 15H12.7324C12.3866 15.5978 11.7403 16 11 16H6.5C4.567 16 3 14.433 3 12.5V4.00001Z" fill="#242424"/>
|
||||
</svg>
|
After Width: | Height: | Size: 527 B |
3
images/CopilotExplain.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.25028 7.30723C9.08872 7.49072 9.00001 7.74463 9.00001 8C9.00001 8.27614 8.77615 8.5 8.50001 8.5C8.22387 8.5 8.00001 8.27614 8.00001 8C8.00001 7.52689 8.1613 7.0308 8.49974 6.64641C8.84684 6.25219 9.3597 6 10 6C10.6403 6 11.1532 6.25219 11.5003 6.64641C11.8387 7.0308 12 7.52689 12 8C12 8.48947 11.8839 8.86964 11.6976 9.18921C11.5347 9.46855 11.3225 9.68963 11.1528 9.86652L11.1115 9.90956C10.9247 10.1051 10.7821 10.2639 10.6773 10.4641C10.5773 10.6551 10.5 10.9085 10.5 11.2929C10.5 11.5691 10.2762 11.7929 10 11.7929C9.72387 11.7929 9.50001 11.5691 9.50001 11.2929C9.50001 10.7611 9.61018 10.3464 9.79143 10.0002C9.96788 9.66319 10.2003 9.41576 10.3885 9.21878L10.4106 9.19559C10.5985 8.99908 10.7328 8.85858 10.8337 8.68547C10.9286 8.52273 11 8.31707 11 8C11 7.74463 10.9113 7.49072 10.7497 7.30723C10.5968 7.13358 10.3597 7 10 7C9.64033 7 9.40318 7.13358 9.25028 7.30723ZM9.99991 14.2122C10.3863 14.2122 10.6995 13.899 10.6995 13.5126C10.6995 13.1262 10.3863 12.813 9.99991 12.813C9.61353 12.813 9.3003 13.1262 9.3003 13.5126C9.3003 13.899 9.61353 14.2122 9.99991 14.2122ZM2.00001 10C2.00001 5.58172 5.58173 2 10 2C14.4183 2 18 5.58172 18 10C18 14.4183 14.4183 18 10 18C8.65078 18 7.37829 17.6656 6.26225 17.0748L2.62128 17.9851C2.45089 18.0277 2.27065 17.9777 2.14646 17.8536C2.02227 17.7294 1.97234 17.5491 2.01494 17.3787L2.92518 13.7378C2.33442 12.6217 2.00001 11.3492 2.00001 10ZM10 3C6.13402 3 3.00001 6.13401 3.00001 10C3.00001 11.245 3.32462 12.4128 3.89345 13.4247C3.95602 13.536 3.97363 13.6671 3.94266 13.791L3.18719 16.8128L6.20904 16.0574C6.33294 16.0264 6.46399 16.044 6.57531 16.1066C7.58726 16.6754 8.75497 17 10 17C13.866 17 17 13.866 17 10C17 6.13401 13.866 3 10 3Z" fill="#424242"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
3
images/CopilotInsert.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 4C4.89543 4 4 4.89543 4 6V7C4 8.10457 4.89543 9 6 9H14C15.1046 9 16 8.10457 16 7V6C16 4.89543 15.1046 4 14 4H6ZM5 6C5 5.44772 5.44772 5 6 5H14C14.5523 5 15 5.44772 15 6V7C15 7.55228 14.5523 8 14 8H6C5.44772 8 5 7.55228 5 7V6ZM6 11C4.89543 11 4 11.8954 4 13V14C4 15.1046 4.89543 16 6 16H14C15.1046 16 16 15.1046 16 14V13C16 11.8954 15.1046 11 14 11H6ZM5 13C5 12.4477 5.44772 12 6 12H14C14.5523 12 15 12.4477 15 13V14C15 14.5523 14.5523 15 14 15H6C5.44772 15 5 14.5523 5 14V13Z" fill="#242424"/>
|
||||
</svg>
|
After Width: | Height: | Size: 609 B |
3
images/CopilotLikeHover.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="16" height="18" viewBox="0 0 16 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.4829 0.703737C9.68406 -0.133389 8.39129 0.316883 8.05198 1.29418C7.77205 2.10043 7.4084 3.06594 7.05406 3.77684C5.99442 5.90276 5.37583 7.11234 3.66974 8.62586C3.44337 8.82668 3.15163 8.9885 2.82905 9.11601C1.69991 9.56233 0.638089 10.7321 0.915812 12.1207L1.26885 13.8859C1.45455 14.8144 2.14894 15.5583 3.06251 15.8075L8.66224 17.3347C11.2078 18.0289 13.8017 16.3942 14.2737 13.7983L14.9576 10.0365C15.2924 8.19503 13.8777 6.49989 12.006 6.49989H11.1225L11.1328 6.44766C11.2129 6.03948 11.3093 5.47735 11.3738 4.86473C11.438 4.25446 11.4721 3.58034 11.4218 2.9522C11.3725 2.33584 11.2379 1.70305 10.9176 1.22254C10.8081 1.05832 10.6455 0.874161 10.4829 0.703737Z" fill="#605E5C"/>
|
||||
</svg>
|
After Width: | Height: | Size: 799 B |
3
images/CopilotLikePressed.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="16" height="18" viewBox="0 0 16 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.4829 0.703737C9.68406 -0.133389 8.39129 0.316883 8.05198 1.29418C7.77205 2.10043 7.4084 3.06594 7.05406 3.77684C5.99442 5.90276 5.37583 7.11234 3.66974 8.62586C3.44337 8.82668 3.15163 8.9885 2.82905 9.11601C1.69991 9.56233 0.638089 10.7321 0.915812 12.1207L1.26885 13.8859C1.45455 14.8144 2.14894 15.5583 3.06251 15.8075L8.66224 17.3347C11.2078 18.0289 13.8017 16.3942 14.2737 13.7983L14.9576 10.0365C15.2924 8.19503 13.8777 6.49989 12.006 6.49989H11.1225L11.1328 6.44766C11.2129 6.03948 11.3093 5.47735 11.3738 4.86473C11.438 4.25446 11.4721 3.58034 11.4218 2.9522C11.3725 2.33584 11.2379 1.70305 10.9176 1.22254C10.8081 1.05832 10.6455 0.874161 10.4829 0.703737Z" fill="#0078D4"/>
|
||||
</svg>
|
After Width: | Height: | Size: 799 B |
3
images/CopilotLikeRest.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="15" height="18" viewBox="0 0 15 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.55198 1.29418C7.89129 0.316883 9.18406 -0.133389 9.98289 0.703737C10.1455 0.874162 10.3081 1.05832 10.4176 1.22254C10.7379 1.70305 10.8725 2.33584 10.9218 2.9522C10.9721 3.58034 10.938 4.25446 10.8738 4.86473C10.8093 5.47735 10.7129 6.03948 10.6328 6.44766C10.6294 6.46535 10.6259 6.48277 10.6225 6.49989H11.506C13.3777 6.49989 14.7924 8.19503 14.4576 10.0365L13.7737 13.7983C13.3017 16.3942 10.7078 18.0289 8.16224 17.3347L2.56251 15.8075C1.64894 15.5583 0.954555 14.8144 0.768846 13.8859L0.415812 12.1207C0.138089 10.7321 1.19991 9.56233 2.32905 9.11601C2.65163 8.9885 2.94337 8.82668 3.16974 8.62586C4.87583 7.11234 5.49442 5.90276 6.55406 3.77684C6.9084 3.06594 7.27205 2.10043 7.55198 1.29418ZM9.51651 6.87851L9.51689 6.87696L9.51869 6.86962L9.5262 6.83852C9.53284 6.81068 9.54264 6.76892 9.55487 6.71482C9.57935 6.60658 9.61349 6.44919 9.65152 6.25525C9.72773 5.86655 9.81878 5.33493 9.8793 4.76005C9.94006 4.18282 9.96852 3.57569 9.92502 3.03195C9.88058 2.47644 9.76518 2.04673 9.58552 1.77724C9.52643 1.68859 9.41385 1.55593 9.25942 1.3941C9.06051 1.18565 8.63137 1.23417 8.49666 1.62217C8.21411 2.43598 7.83339 3.45183 7.44904 4.22294C6.38216 6.36338 5.69326 7.72396 3.83336 9.37392C3.49304 9.67583 3.08878 9.89099 2.69665 10.046C1.81631 10.394 1.25035 11.1944 1.39639 11.9246L1.74943 13.6898C1.86085 14.2469 2.27748 14.6932 2.82562 14.8427L8.42536 16.3699C10.4052 16.9099 12.4227 15.6384 12.7898 13.6194L13.4738 9.85766C13.697 8.62998 12.7538 7.49989 11.506 7.49989H10.0015C9.84758 7.49989 9.7022 7.42895 9.60745 7.3076C9.51272 7.18627 9.47921 7.02785 9.51651 6.87851C9.51651 6.87847 9.5165 6.87855 9.51651 6.87851Z" fill="#424242"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
3
images/CopilotOptimize.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5 2.5C5 2.22386 4.77614 2 4.5 2C4.22386 2 4 2.22386 4 2.5V4H2.5C2.22386 4 2 4.22386 2 4.5C2 4.77614 2.22386 5 2.5 5H4.5C4.77614 5 5 4.77614 5 4.5V2.5ZM16 2.5C16 2.22386 15.7761 2 15.5 2C15.2239 2 15 2.22386 15 2.5V4.5C15 4.77614 15.2239 5 15.5 5H17.5C17.7761 5 18 4.77614 18 4.5C18 4.22386 17.7761 4 17.5 4H16V2.5ZM7 5C6.44771 5 6 5.44772 6 6V14C6 14.5523 6.44772 15 7 15H13C13.5523 15 14 14.5523 14 14V6C14 5.44772 13.5523 5 13 5H7ZM7 6H13V14H7V6ZM4.5 18C4.77614 18 5 17.7761 5 17.5V15.5C5 15.2239 4.77614 15 4.5 15H2.5C2.22386 15 2 15.2239 2 15.5C2 15.7761 2.22386 16 2.5 16H4V17.5C4 17.7761 4.22386 18 4.5 18ZM15.5 18C15.7761 18 16 17.7761 16 17.5V16H17.5C17.7761 16 18 15.7761 18 15.5C18 15.2239 17.7761 15 17.5 15H15.5C15.2239 15 15 15.2239 15 15.5V17.5C15 17.7761 15.2239 18 15.5 18ZM8.5 8C8.22386 8 8 8.22386 8 8.5C8 8.77614 8.22386 9 8.5 9H11.5C11.7761 9 12 8.77614 12 8.5C12 8.22386 11.7761 8 11.5 8H8.5ZM8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11H10.5C10.7761 11 11 10.7761 11 10.5C11 10.2239 10.7761 10 10.5 10H8.5Z" fill="#424242"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
3
images/CopilotRegenerate.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.14645 2.64645C9.34171 2.45118 9.65829 2.45118 9.85355 2.64645L11.3536 4.14645C11.5488 4.34171 11.5488 4.65829 11.3536 4.85355L9.85355 6.35355C9.65829 6.54882 9.34171 6.54882 9.14645 6.35355C8.95118 6.15829 8.95118 5.84171 9.14645 5.64645L9.7885 5.00439C7.12517 5.11522 5 7.30943 5 10C5 11.568 5.72118 12.9672 6.85185 13.8847C7.06627 14.0587 7.09904 14.3736 6.92503 14.588C6.75103 14.8024 6.43615 14.8352 6.22172 14.6612C4.86712 13.5619 4 11.882 4 10C4 6.75447 6.57689 4.1108 9.79629 4.00339L9.14645 3.35355C8.95118 3.15829 8.95118 2.84171 9.14645 2.64645ZM13.075 5.41199C13.249 5.19756 13.5639 5.1648 13.7783 5.3388C15.1329 6.43806 16 8.11795 16 10C16 13.2455 13.4231 15.8892 10.2037 15.9966L10.8536 16.6464C11.0488 16.8417 11.0488 17.1583 10.8536 17.3536C10.6583 17.5488 10.3417 17.5488 10.1464 17.3536L8.64645 15.8536C8.55268 15.7598 8.5 15.6326 8.5 15.5C8.5 15.3674 8.55268 15.2402 8.64645 15.1464L10.1464 13.6464C10.3417 13.4512 10.6583 13.4512 10.8536 13.6464C11.0488 13.8417 11.0488 14.1583 10.8536 14.3536L10.2115 14.9956C12.8748 14.8848 15 12.6906 15 10C15 8.43201 14.2788 7.03283 13.1482 6.1153C12.9337 5.94129 12.901 5.62641 13.075 5.41199Z" fill="#242424"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
3
images/CopilotSimplify.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.5 4C4.67157 4 4 4.67157 4 5.5V6.5C4 6.77614 3.77614 7 3.5 7C3.22386 7 3 6.77614 3 6.5V5.5C3 4.11929 4.11929 3 5.5 3H6.5C6.77614 3 7 3.22386 7 3.5C7 3.77614 6.77614 4 6.5 4H5.5ZM16 5.5C16 4.67157 15.3284 4 14.5 4H13.5C13.2239 4 13 3.77614 13 3.5C13 3.22386 13.2239 3 13.5 3H14.5C15.8807 3 17 4.11929 17 5.5V6.5C17 6.77614 16.7761 7 16.5 7C16.2239 7 16 6.77614 16 6.5V5.5ZM16 14.5C16 15.3284 15.3284 16 14.5 16H13.5C13.2239 16 13 16.2239 13 16.5C13 16.7761 13.2239 17 13.5 17H14.5C15.8807 17 17 15.8807 17 14.5V13.5C17 13.2239 16.7761 13 16.5 13C16.2239 13 16 13.2239 16 13.5V14.5ZM4 14.5C4 15.3284 4.67157 16 5.5 16H6.75C7.02614 16 7.25 16.2239 7.25 16.5C7.25 16.7761 7.02614 17 6.75 17H5.5C4.11929 17 3 15.8807 3 14.5V13.25C3 12.9739 3.22386 12.75 3.5 12.75C3.77614 12.75 4 12.9739 4 13.25V14.5ZM8.5 7C7.67157 7 7 7.67157 7 8.5V11.5C7 12.3284 7.67157 13 8.5 13H11.5C12.3284 13 13 12.3284 13 11.5V8.5C13 7.67157 12.3284 7 11.5 7H8.5ZM8 8.5C8 8.22386 8.22386 8 8.5 8H11.5C11.7761 8 12 8.22386 12 8.5V11.5C12 11.7761 11.7761 12 11.5 12H8.5C8.22386 12 8 11.7761 8 11.5V8.5Z" fill="#424242"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
@ -68,7 +68,8 @@ module.exports = {
|
||||
|
||||
// A map from regular expressions to module names that allow to stub out resources with a single module
|
||||
moduleNameMapper: {
|
||||
"^.*[.](svg|png|gif|less|css)$": "<rootDir>/mockModule",
|
||||
"^.*[.](png|gif|less|css)$": "<rootDir>/mockModule",
|
||||
"(.*)$[.](svg)": "<rootDir>/mockModule/$1",
|
||||
"@nteract/stateful-components/(.*)$": "<rootDir>/mockModule",
|
||||
"@fluentui/react/lib/(.*)$": "@fluentui/react/lib-commonjs/$1", // https://github.com/microsoft/fluentui/wiki/Version-8-release-notes
|
||||
"monaco-editor/(.*)$": "<rootDir>/__mocks__/monaco-editor",
|
||||
@ -165,6 +166,7 @@ module.exports = {
|
||||
transform: {
|
||||
"^.+\\.html?$": "html-loader-jest",
|
||||
"^.+\\.[t|j]sx?$": "babel-jest",
|
||||
"^.+\\.svg$": "<rootDir>/svgTransform.js",
|
||||
},
|
||||
|
||||
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
|
||||
|
@ -13,8 +13,14 @@ export interface EditorReactProps {
|
||||
ariaLabel: string; // Sets what will be read to the user to define the control
|
||||
onContentSelected?: (selectedContent: string) => void; // Called when text is selected
|
||||
onContentChanged?: (newContent: string) => void; // Called when text is changed
|
||||
lineNumbers?: monaco.editor.IEditorOptions["lineNumbers"];
|
||||
theme?: string; // Monaco editor theme
|
||||
wordWrap?: monaco.editor.IEditorOptions["wordWrap"];
|
||||
lineNumbers?: monaco.editor.IEditorOptions["lineNumbers"];
|
||||
lineNumbersMinChars?: monaco.editor.IEditorOptions["lineNumbersMinChars"];
|
||||
lineDecorationsWidth?: monaco.editor.IEditorOptions["lineDecorationsWidth"];
|
||||
minimap?: monaco.editor.IEditorOptions["minimap"];
|
||||
scrollBeyondLastLine?: monaco.editor.IEditorOptions["scrollBeyondLastLine"];
|
||||
monacoContainerStyles?: React.CSSProperties;
|
||||
}
|
||||
|
||||
export class EditorReact extends React.Component<EditorReactProps, EditorReactStates> {
|
||||
@ -54,7 +60,11 @@ export class EditorReact extends React.Component<EditorReactProps, EditorReactSt
|
||||
return (
|
||||
<React.Fragment>
|
||||
{!this.state.showEditor && <Spinner size={SpinnerSize.large} className="spinner" />}
|
||||
<div className="jsonEditor" ref={(elt: HTMLElement) => this.setRef(elt)} />
|
||||
<div
|
||||
className="jsonEditor"
|
||||
style={this.props.monacoContainerStyles}
|
||||
ref={(elt: HTMLElement) => this.setRef(elt)}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
@ -84,14 +94,19 @@ export class EditorReact extends React.Component<EditorReactProps, EditorReactSt
|
||||
*/
|
||||
private async createEditor(createCallback: (e: monaco.editor.IStandaloneCodeEditor) => void) {
|
||||
const options: monaco.editor.IEditorConstructionOptions = {
|
||||
value: this.props.content,
|
||||
language: this.props.language,
|
||||
value: this.props.content,
|
||||
readOnly: this.props.isReadOnly,
|
||||
lineNumbers: this.props.lineNumbers || "off",
|
||||
fontSize: 12,
|
||||
ariaLabel: this.props.ariaLabel,
|
||||
theme: this.props.theme,
|
||||
fontSize: 12,
|
||||
automaticLayout: true,
|
||||
theme: this.props.theme,
|
||||
wordWrap: this.props.wordWrap || "off",
|
||||
lineNumbers: this.props.lineNumbers || "off",
|
||||
lineNumbersMinChars: this.props.lineNumbersMinChars,
|
||||
lineDecorationsWidth: this.props.lineDecorationsWidth,
|
||||
minimap: this.props.minimap,
|
||||
scrollBeyondLastLine: this.props.scrollBeyondLastLine,
|
||||
};
|
||||
|
||||
this.rootNode.innerHTML = "";
|
||||
|
@ -55,7 +55,7 @@ exports[`TreeNodeComponent does not render children by default 1`] = `
|
||||
className="expandCollapseIcon"
|
||||
onKeyPress={[Function]}
|
||||
role="button"
|
||||
src=""
|
||||
src={Object {}}
|
||||
tabIndex={0}
|
||||
/>
|
||||
<span
|
||||
@ -158,7 +158,7 @@ exports[`TreeNodeComponent renders a simple node (sorted children, expanded) 1`]
|
||||
className="expandCollapseIcon"
|
||||
onKeyPress={[Function]}
|
||||
role="button"
|
||||
src=""
|
||||
src={Object {}}
|
||||
tabIndex={0}
|
||||
/>
|
||||
<span
|
||||
@ -309,7 +309,7 @@ exports[`TreeNodeComponent renders loading icon 1`] = `
|
||||
className="expandCollapseIcon"
|
||||
onKeyPress={[Function]}
|
||||
role="button"
|
||||
src=""
|
||||
src={Object {}}
|
||||
tabIndex={0}
|
||||
/>
|
||||
<span
|
||||
@ -383,7 +383,7 @@ exports[`TreeNodeComponent renders sorted children, expanded, leaves and parents
|
||||
className="expandCollapseIcon"
|
||||
onKeyPress={[Function]}
|
||||
role="button"
|
||||
src=""
|
||||
src={Object {}}
|
||||
tabIndex={0}
|
||||
/>
|
||||
<span
|
||||
@ -553,7 +553,7 @@ exports[`TreeNodeComponent renders unsorted children by default 1`] = `
|
||||
className="expandCollapseIcon"
|
||||
onKeyPress={[Function]}
|
||||
role="button"
|
||||
src=""
|
||||
src={Object {}}
|
||||
tabIndex={0}
|
||||
/>
|
||||
<span
|
||||
|
@ -128,7 +128,7 @@ exports[`<EditorNodePropertiesComponent /> renders component 1`] = `
|
||||
>
|
||||
<img
|
||||
alt="Delete"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
</AccessibleElement>
|
||||
</td>
|
||||
@ -185,7 +185,7 @@ exports[`<EditorNodePropertiesComponent /> renders component 1`] = `
|
||||
>
|
||||
<img
|
||||
alt="Delete"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
</AccessibleElement>
|
||||
</td>
|
||||
@ -203,7 +203,7 @@ exports[`<EditorNodePropertiesComponent /> renders component 1`] = `
|
||||
>
|
||||
<img
|
||||
alt="Add"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
Add Property
|
||||
</AccessibleElement>
|
||||
@ -317,7 +317,7 @@ exports[`<EditorNodePropertiesComponent /> renders proper unicode 1`] = `
|
||||
>
|
||||
<img
|
||||
alt="Delete"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
</AccessibleElement>
|
||||
</td>
|
||||
@ -379,7 +379,7 @@ exports[`<EditorNodePropertiesComponent /> renders proper unicode 1`] = `
|
||||
>
|
||||
<img
|
||||
alt="Delete"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
</AccessibleElement>
|
||||
</td>
|
||||
@ -397,7 +397,7 @@ exports[`<EditorNodePropertiesComponent /> renders proper unicode 1`] = `
|
||||
>
|
||||
<img
|
||||
alt="Add"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
Add Property
|
||||
</AccessibleElement>
|
||||
|
@ -22,7 +22,7 @@ exports[`NotificationConsoleComponent renders the console 1`] = `
|
||||
>
|
||||
<img
|
||||
alt="in progress items"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
<span
|
||||
className="numInProgress"
|
||||
@ -35,7 +35,7 @@ exports[`NotificationConsoleComponent renders the console 1`] = `
|
||||
>
|
||||
<img
|
||||
alt="error items"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
<span
|
||||
className="numErroredItems"
|
||||
@ -48,7 +48,7 @@ exports[`NotificationConsoleComponent renders the console 1`] = `
|
||||
>
|
||||
<img
|
||||
alt="info items"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
<span
|
||||
className="numInfoItems"
|
||||
@ -150,7 +150,7 @@ exports[`NotificationConsoleComponent renders the console 1`] = `
|
||||
>
|
||||
<img
|
||||
alt="clear notifications image"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
Clear Notifications
|
||||
</span>
|
||||
@ -185,7 +185,7 @@ exports[`NotificationConsoleComponent renders the console 2`] = `
|
||||
>
|
||||
<img
|
||||
alt="in progress items"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
<span
|
||||
className="numInProgress"
|
||||
@ -198,7 +198,7 @@ exports[`NotificationConsoleComponent renders the console 2`] = `
|
||||
>
|
||||
<img
|
||||
alt="error items"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
<span
|
||||
className="numErroredItems"
|
||||
@ -211,7 +211,7 @@ exports[`NotificationConsoleComponent renders the console 2`] = `
|
||||
>
|
||||
<img
|
||||
alt="info items"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
<span
|
||||
className="numInfoItems"
|
||||
@ -315,7 +315,7 @@ exports[`NotificationConsoleComponent renders the console 2`] = `
|
||||
>
|
||||
<img
|
||||
alt="clear notifications image"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
Clear Notifications
|
||||
</span>
|
||||
@ -330,7 +330,7 @@ exports[`NotificationConsoleComponent renders the console 2`] = `
|
||||
<img
|
||||
alt="info"
|
||||
className="infoIcon"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
<span
|
||||
className="date"
|
||||
|
@ -4340,7 +4340,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
id="deleteparam"
|
||||
onClick={[Function]}
|
||||
role="button"
|
||||
src=""
|
||||
src={Object {}}
|
||||
width={20}
|
||||
>
|
||||
<ImageBase
|
||||
@ -4350,7 +4350,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
id="deleteparam"
|
||||
onClick={[Function]}
|
||||
role="button"
|
||||
src=""
|
||||
src={Object {}}
|
||||
styles={[Function]}
|
||||
theme={
|
||||
Object {
|
||||
@ -4640,12 +4640,12 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
alt="Delete param"
|
||||
className="ms-Image-image ms-Image-image--portrait is-notLoaded is-fadeIn image-87"
|
||||
id="deleteparam"
|
||||
key="fabricImage"
|
||||
key="fabricImage[object Object]"
|
||||
onClick={[Function]}
|
||||
onError={[Function]}
|
||||
onLoad={[Function]}
|
||||
role="button"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
</div>
|
||||
</ImageBase>
|
||||
@ -4661,7 +4661,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
id="addparam"
|
||||
onClick={[Function]}
|
||||
role="button"
|
||||
src=""
|
||||
src={Object {}}
|
||||
width={20}
|
||||
>
|
||||
<ImageBase
|
||||
@ -4671,7 +4671,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
id="addparam"
|
||||
onClick={[Function]}
|
||||
role="button"
|
||||
src=""
|
||||
src={Object {}}
|
||||
styles={[Function]}
|
||||
theme={
|
||||
Object {
|
||||
@ -4961,12 +4961,12 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
alt="Add param"
|
||||
className="ms-Image-image ms-Image-image--portrait is-notLoaded is-fadeIn image-87"
|
||||
id="addparam"
|
||||
key="fabricImage"
|
||||
key="fabricImage[object Object]"
|
||||
onClick={[Function]}
|
||||
onError={[Function]}
|
||||
onLoad={[Function]}
|
||||
role="button"
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
</div>
|
||||
</ImageBase>
|
||||
@ -4989,13 +4989,13 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
alt="Add param"
|
||||
height={30}
|
||||
key=".0:$.0"
|
||||
src=""
|
||||
src={Object {}}
|
||||
width={20}
|
||||
>
|
||||
<ImageBase
|
||||
alt="Add param"
|
||||
height={30}
|
||||
src=""
|
||||
src={Object {}}
|
||||
styles={[Function]}
|
||||
theme={
|
||||
Object {
|
||||
@ -5284,10 +5284,10 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
<img
|
||||
alt="Add param"
|
||||
className="ms-Image-image ms-Image-image--portrait is-notLoaded is-fadeIn image-87"
|
||||
key="fabricImage"
|
||||
key="fabricImage[object Object]"
|
||||
onError={[Function]}
|
||||
onLoad={[Function]}
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
</div>
|
||||
</ImageBase>
|
||||
|
@ -39,7 +39,7 @@ exports[`Load Query Pane should render Default properly 1`] = `
|
||||
className="fileIcon"
|
||||
height={20}
|
||||
imageFit={4}
|
||||
src=""
|
||||
src={Object {}}
|
||||
width={20}
|
||||
/>
|
||||
<input
|
||||
|
@ -44,13 +44,13 @@ exports[`Excute Add Table Entity Pane should render Default properly 1`] = `
|
||||
alt="Add Property"
|
||||
height={30}
|
||||
key=".0:$.0"
|
||||
src=""
|
||||
src={Object {}}
|
||||
width={16}
|
||||
>
|
||||
<ImageBase
|
||||
alt="Add Property"
|
||||
height={30}
|
||||
src=""
|
||||
src={Object {}}
|
||||
styles={[Function]}
|
||||
theme={
|
||||
Object {
|
||||
@ -339,10 +339,10 @@ exports[`Excute Add Table Entity Pane should render Default properly 1`] = `
|
||||
<img
|
||||
alt="Add Property"
|
||||
className="ms-Image-image ms-Image-image--portrait is-notLoaded is-fadeIn image-55"
|
||||
key="fabricImage"
|
||||
key="fabricImage[object Object]"
|
||||
onError={[Function]}
|
||||
onLoad={[Function]}
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
</div>
|
||||
</ImageBase>
|
||||
|
@ -39,13 +39,13 @@ exports[`Excute Edit Table Entity Pane should render Default properly 1`] = `
|
||||
alt="Add Entity"
|
||||
height={30}
|
||||
key=".0:$.0"
|
||||
src=""
|
||||
src={Object {}}
|
||||
width={16}
|
||||
>
|
||||
<ImageBase
|
||||
alt="Add Entity"
|
||||
height={30}
|
||||
src=""
|
||||
src={Object {}}
|
||||
styles={[Function]}
|
||||
theme={
|
||||
Object {
|
||||
@ -334,10 +334,10 @@ exports[`Excute Edit Table Entity Pane should render Default properly 1`] = `
|
||||
<img
|
||||
alt="Add Entity"
|
||||
className="ms-Image-image ms-Image-image--portrait is-notLoaded is-fadeIn image-55"
|
||||
key="fabricImage"
|
||||
key="fabricImage[object Object]"
|
||||
onError={[Function]}
|
||||
onLoad={[Function]}
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
</div>
|
||||
</ImageBase>
|
||||
|
@ -20,7 +20,7 @@ exports[`Query Copilot Welcome Modal snapshot test should render when isOpen is
|
||||
>
|
||||
<StackItem>
|
||||
<Image
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
</StackItem>
|
||||
</Stack>
|
||||
@ -84,7 +84,7 @@ exports[`Query Copilot Welcome Modal snapshot test should render when isOpen is
|
||||
className="imageTextPadding"
|
||||
>
|
||||
<Image
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
</StackItem>
|
||||
<StackItem
|
||||
@ -120,7 +120,7 @@ exports[`Query Copilot Welcome Modal snapshot test should render when isOpen is
|
||||
className="imageTextPadding"
|
||||
>
|
||||
<Image
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
</StackItem>
|
||||
<StackItem
|
||||
@ -156,7 +156,7 @@ exports[`Query Copilot Welcome Modal snapshot test should render when isOpen is
|
||||
className="imageTextPadding"
|
||||
>
|
||||
<Image
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
</StackItem>
|
||||
<StackItem
|
||||
|
@ -40,7 +40,7 @@ exports[`Copy Popup snapshot test should render when showCopyPopup is true 1`] =
|
||||
verticalAlign="center"
|
||||
>
|
||||
<Image
|
||||
src=""
|
||||
src={Object {}}
|
||||
style={
|
||||
Object {
|
||||
"height": 15,
|
||||
|
@ -87,7 +87,7 @@ exports[`Sample Prompts snapshot test should render properly if isSamplePromptsO
|
||||
verticalAlign="center"
|
||||
>
|
||||
<Image
|
||||
src=""
|
||||
src={Object {}}
|
||||
style={
|
||||
Object {
|
||||
"height": 25,
|
||||
@ -191,7 +191,7 @@ exports[`Sample Prompts snapshot test should render properly if isSamplePromptsO
|
||||
verticalAlign="center"
|
||||
>
|
||||
<Image
|
||||
src=""
|
||||
src={Object {}}
|
||||
style={
|
||||
Object {
|
||||
"height": 25,
|
||||
@ -295,7 +295,7 @@ exports[`Sample Prompts snapshot test should render properly if isSamplePromptsO
|
||||
verticalAlign="center"
|
||||
>
|
||||
<Image
|
||||
src=""
|
||||
src={Object {}}
|
||||
style={
|
||||
Object {
|
||||
"height": 25,
|
||||
@ -477,7 +477,7 @@ exports[`Sample Prompts snapshot test should render properly if isSamplePromptsO
|
||||
verticalAlign="center"
|
||||
>
|
||||
<Image
|
||||
src=""
|
||||
src={Object {}}
|
||||
style={
|
||||
Object {
|
||||
"height": 25,
|
||||
@ -581,7 +581,7 @@ exports[`Sample Prompts snapshot test should render properly if isSamplePromptsO
|
||||
verticalAlign="center"
|
||||
>
|
||||
<Image
|
||||
src=""
|
||||
src={Object {}}
|
||||
style={
|
||||
Object {
|
||||
"height": 25,
|
||||
@ -685,7 +685,7 @@ exports[`Sample Prompts snapshot test should render properly if isSamplePromptsO
|
||||
verticalAlign="center"
|
||||
>
|
||||
<Image
|
||||
src=""
|
||||
src={Object {}}
|
||||
style={
|
||||
Object {
|
||||
"height": 25,
|
||||
|
@ -0,0 +1,21 @@
|
||||
import { IconButton } from "@fluentui/react";
|
||||
import { CopyButton } from "Explorer/QueryCopilot/V2/Bubbles/Output/Buttons/Copy/CopyButton";
|
||||
import { shallow } from "enzyme";
|
||||
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
||||
import React from "react";
|
||||
|
||||
document.execCommand = jest.fn();
|
||||
|
||||
describe("Copy button snapshot tests", () => {
|
||||
it("should render and click copy", async () => {
|
||||
const testInput = "test input query";
|
||||
useQueryCopilot.getState().setGeneratedQuery(testInput);
|
||||
const wrapper = shallow(<CopyButton />);
|
||||
|
||||
const button = wrapper.find(IconButton).first();
|
||||
button.simulate("click", {});
|
||||
|
||||
expect(document.execCommand).toHaveBeenCalledWith("copy");
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,23 @@
|
||||
import { IconButton } from "@fluentui/react";
|
||||
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
||||
import React from "react";
|
||||
import CopilotCopy from "../../../../../../../../images/CopilotCopy.svg";
|
||||
|
||||
export const CopyButton: React.FC = (): JSX.Element => {
|
||||
const copyGeneratedCode = (): void => {
|
||||
const queryElement = document.createElement("textarea");
|
||||
queryElement.value = useQueryCopilot.getState().generatedQuery;
|
||||
document.body.appendChild(queryElement);
|
||||
queryElement.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(queryElement);
|
||||
};
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
iconProps={{ imageProps: { src: CopilotCopy } }}
|
||||
ariaLabel="Copy"
|
||||
onClick={copyGeneratedCode}
|
||||
></IconButton>
|
||||
);
|
||||
};
|
@ -0,0 +1,15 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Copy button snapshot tests should render and click copy 1`] = `
|
||||
<CustomizedIconButton
|
||||
ariaLabel="Copy"
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": Object {},
|
||||
},
|
||||
}
|
||||
}
|
||||
onClick={[Function]}
|
||||
/>
|
||||
`;
|
@ -0,0 +1,205 @@
|
||||
import { Callout, IconButton, Link } from "@fluentui/react";
|
||||
import { useId } from "@fluentui/react-hooks";
|
||||
import { FeedbackButtons } from "Explorer/QueryCopilot/V2/Bubbles/Output/Buttons/Feedback/FeedbackButtons";
|
||||
import { shallow } from "enzyme";
|
||||
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
||||
import React from "react";
|
||||
import LikeHover from "../../../../../../../../images/CopilotLikeHover.svg";
|
||||
import LikePressed from "../../../../../../../../images/CopilotLikePressed.svg";
|
||||
import LikeRest from "../../../../../../../../images/CopilotLikeRest.svg";
|
||||
|
||||
useId as jest.Mock;
|
||||
|
||||
jest.mock("../../../../../../../../images/CopilotLikeHover.svg", () => "LikeHover");
|
||||
jest.mock("../../../../../../../../images/CopilotLikePressed.svg", () => "LikePressed");
|
||||
jest.mock("../../../../../../../../images/CopilotLikeRest.svg", () => "LikeRest");
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
describe("Feedback buttons snapshot tests", () => {
|
||||
it("should click like and show callout", () => {
|
||||
const wrapper = shallow(<FeedbackButtons />);
|
||||
|
||||
let likeButton = wrapper.find(IconButton).first();
|
||||
const dislikeButton = wrapper.find(IconButton).last();
|
||||
likeButton.simulate("click");
|
||||
likeButton = wrapper.find(IconButton).first();
|
||||
const callout = wrapper.find(Callout).first();
|
||||
|
||||
expect(likeButton.props().iconProps.imageProps.src).toEqual(LikePressed);
|
||||
expect(dislikeButton.props().iconProps.imageProps.src).toEqual(LikeRest);
|
||||
expect(callout.exists()).toBeTruthy();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should click like and dismiss callout", () => {
|
||||
const wrapper = shallow(<FeedbackButtons />);
|
||||
|
||||
const likeButton = wrapper.find(IconButton).first();
|
||||
likeButton.simulate("click");
|
||||
let callout = wrapper.find(Callout).first();
|
||||
callout.simulate("dismiss");
|
||||
callout = wrapper.find(Callout).first();
|
||||
|
||||
expect(callout.exists()).toBeFalsy();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should click like and submit feedback", () => {
|
||||
const spy = jest.spyOn(useQueryCopilot.getState(), "openFeedbackModal");
|
||||
const wrapper = shallow(<FeedbackButtons />);
|
||||
|
||||
const likeButton = wrapper.find(IconButton).first();
|
||||
likeButton.simulate("click");
|
||||
const link = wrapper.find(Link).first();
|
||||
link.simulate("click");
|
||||
|
||||
expect(spy).toHaveBeenNthCalledWith(1, "", true, "");
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should hover over like", () => {
|
||||
const wrapper = shallow(<FeedbackButtons />);
|
||||
|
||||
let likeButton = wrapper.find(IconButton).first();
|
||||
likeButton.simulate("mouseover");
|
||||
likeButton = wrapper.find(IconButton).first();
|
||||
|
||||
expect(likeButton.props().iconProps.imageProps.src).toEqual(LikeHover);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should hover over rest like and leave", () => {
|
||||
const wrapper = shallow(<FeedbackButtons />);
|
||||
|
||||
let likeButton = wrapper.find(IconButton).first();
|
||||
likeButton.simulate("mouseover");
|
||||
likeButton.simulate("mouseleave");
|
||||
likeButton = wrapper.find(IconButton).first();
|
||||
|
||||
expect(likeButton.props().iconProps.imageProps.src).toEqual(LikeRest);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should hover over pressed like and leave", () => {
|
||||
const wrapper = shallow(<FeedbackButtons />);
|
||||
|
||||
let likeButton = wrapper.find(IconButton).first();
|
||||
likeButton.simulate("click");
|
||||
likeButton = wrapper.find(IconButton).first();
|
||||
likeButton.simulate("mouseover");
|
||||
likeButton.simulate("mouseleave");
|
||||
|
||||
expect(likeButton.props().iconProps.imageProps.src).toEqual(LikePressed);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should hover over like and click", () => {
|
||||
const wrapper = shallow(<FeedbackButtons />);
|
||||
|
||||
let likeButton = wrapper.find(IconButton).first();
|
||||
likeButton.simulate("mouseover");
|
||||
likeButton.simulate("click");
|
||||
likeButton = wrapper.find(IconButton).first();
|
||||
|
||||
expect(likeButton.props().iconProps.imageProps.src).toEqual(LikePressed);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should dobule click on like", () => {
|
||||
const wrapper = shallow(<FeedbackButtons />);
|
||||
|
||||
let likeButton = wrapper.find(IconButton).first();
|
||||
likeButton.simulate("click");
|
||||
likeButton = wrapper.find(IconButton).first();
|
||||
expect(likeButton.props().iconProps.imageProps.src).toEqual(LikePressed);
|
||||
|
||||
likeButton.simulate("click");
|
||||
likeButton = wrapper.find(IconButton).first();
|
||||
expect(likeButton.props().iconProps.imageProps.src).toEqual(LikeRest);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should click dislike and show popup", () => {
|
||||
const spy = jest.spyOn(useQueryCopilot.getState(), "openFeedbackModal");
|
||||
const wrapper = shallow(<FeedbackButtons />);
|
||||
|
||||
const likeButton = wrapper.find(IconButton).first();
|
||||
let dislikeButton = wrapper.find(IconButton).last();
|
||||
dislikeButton.simulate("click");
|
||||
const callout = wrapper.find(Callout).first();
|
||||
dislikeButton = wrapper.find(IconButton).last();
|
||||
|
||||
expect(likeButton.props().iconProps.imageProps.src).toEqual(LikeRest);
|
||||
expect(dislikeButton.props().iconProps.imageProps.src).toEqual(LikePressed);
|
||||
expect(spy).toHaveBeenNthCalledWith(1, "", false, "");
|
||||
expect(callout.exists()).toBeFalsy();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should hover over dislike", () => {
|
||||
const wrapper = shallow(<FeedbackButtons />);
|
||||
|
||||
let dislikeButton = wrapper.find(IconButton).last();
|
||||
dislikeButton.simulate("mouseover");
|
||||
dislikeButton = wrapper.find(IconButton).last();
|
||||
|
||||
expect(dislikeButton.props().iconProps.imageProps.src).toEqual(LikeHover);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should hover over rest dislike and leave", () => {
|
||||
const wrapper = shallow(<FeedbackButtons />);
|
||||
|
||||
let dislikeButton = wrapper.find(IconButton).last();
|
||||
dislikeButton.simulate("mouseover");
|
||||
dislikeButton.simulate("mouseleave");
|
||||
dislikeButton = wrapper.find(IconButton).last();
|
||||
|
||||
expect(dislikeButton.props().iconProps.imageProps.src).toEqual(LikeRest);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should hover over pressed dislike and leave", () => {
|
||||
const wrapper = shallow(<FeedbackButtons />);
|
||||
|
||||
let dislikeButton = wrapper.find(IconButton).last();
|
||||
dislikeButton.simulate("click");
|
||||
dislikeButton = wrapper.find(IconButton).last();
|
||||
expect(dislikeButton.props().iconProps.imageProps.src).toEqual(LikePressed);
|
||||
dislikeButton.simulate("mouseover");
|
||||
dislikeButton.simulate("mouseleave");
|
||||
dislikeButton = wrapper.find(IconButton).last();
|
||||
|
||||
expect(dislikeButton.props().iconProps.imageProps.src).toEqual(LikePressed);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should hover over dislike and click", () => {
|
||||
const wrapper = shallow(<FeedbackButtons />);
|
||||
|
||||
let dislikeButton = wrapper.find(IconButton).last();
|
||||
dislikeButton.simulate("mouseover");
|
||||
dislikeButton.simulate("click");
|
||||
dislikeButton = wrapper.find(IconButton).last();
|
||||
|
||||
expect(dislikeButton.props().iconProps.imageProps.src).toEqual(LikePressed);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should dobule click on dislike", () => {
|
||||
const wrapper = shallow(<FeedbackButtons />);
|
||||
|
||||
let dislikeButton = wrapper.find(IconButton).last();
|
||||
dislikeButton.simulate("click");
|
||||
dislikeButton = wrapper.find(IconButton).last();
|
||||
expect(dislikeButton.props().iconProps.imageProps.src).toEqual(LikePressed);
|
||||
|
||||
dislikeButton.simulate("click");
|
||||
dislikeButton = wrapper.find(IconButton).last();
|
||||
expect(dislikeButton.props().iconProps.imageProps.src).toEqual(LikeRest);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,93 @@
|
||||
import { Callout, DirectionalHint, IconButton, Link, Stack, Text } from "@fluentui/react";
|
||||
import { useId } from "@fluentui/react-hooks";
|
||||
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
||||
import React, { useState } from "react";
|
||||
import LikeHover from "../../../../../../../../images/CopilotLikeHover.svg";
|
||||
import LikePressed from "../../../../../../../../images/CopilotLikePressed.svg";
|
||||
import LikeRest from "../../../../../../../../images/CopilotLikeRest.svg";
|
||||
|
||||
export const FeedbackButtons: React.FC = (): JSX.Element => {
|
||||
const { generatedQuery, userPrompt } = useQueryCopilot();
|
||||
|
||||
const [likeQuery, setLikeQuery] = useState<boolean>(false);
|
||||
const [dislikeQuery, setDislikeQuery] = useState<boolean>(false);
|
||||
const [likeImageLink, setLikeImageLink] = useState<string>(LikeRest);
|
||||
const [dislikeImageLink, setDislikeImageLink] = useState<string>(LikeRest);
|
||||
const [calloutVisible, setCalloutVisible] = useState<boolean>(false);
|
||||
const likeBtnId = useId("likeBtn");
|
||||
const dislikeBtnId = useId("dislikeBtn");
|
||||
|
||||
return (
|
||||
<Stack horizontal>
|
||||
{calloutVisible && (
|
||||
<Callout
|
||||
target={`#${likeBtnId}`}
|
||||
onDismiss={() => setCalloutVisible(false)}
|
||||
directionalHint={DirectionalHint.topCenter}
|
||||
role="dialog"
|
||||
style={{ padding: "5px 12px 5px 12px", borderRadius: "4px" }}
|
||||
styles={{ beakCurtain: { borderRadius: "4px" }, root: { borderRadius: "4px" } }}
|
||||
>
|
||||
<Text>
|
||||
{" "}
|
||||
<Text>
|
||||
Thank you. Need to give{" "}
|
||||
<Link
|
||||
onClick={() => {
|
||||
setCalloutVisible(false);
|
||||
useQueryCopilot.getState().openFeedbackModal(generatedQuery, true, userPrompt);
|
||||
}}
|
||||
>
|
||||
more feedback?
|
||||
</Link>
|
||||
</Text>
|
||||
</Text>
|
||||
</Callout>
|
||||
)}
|
||||
|
||||
<IconButton
|
||||
id={likeBtnId}
|
||||
iconProps={{
|
||||
imageProps: { src: likeImageLink },
|
||||
style: { minHeight: "18px" },
|
||||
}}
|
||||
onClick={() => {
|
||||
if (likeQuery) {
|
||||
setLikeQuery(false);
|
||||
setLikeImageLink(LikeRest);
|
||||
setCalloutVisible(false);
|
||||
} else {
|
||||
setLikeQuery(true);
|
||||
setDislikeQuery(false);
|
||||
setLikeImageLink(LikePressed);
|
||||
setDislikeImageLink(LikeRest);
|
||||
setCalloutVisible(true);
|
||||
}
|
||||
}}
|
||||
onMouseOver={() => setLikeImageLink(LikeHover)}
|
||||
onMouseLeave={() => setLikeImageLink(likeQuery ? LikePressed : LikeRest)}
|
||||
/>
|
||||
<IconButton
|
||||
id={dislikeBtnId}
|
||||
iconProps={{
|
||||
imageProps: { src: dislikeImageLink },
|
||||
style: { minHeight: "18px", transform: "rotate(180deg)" },
|
||||
}}
|
||||
onClick={() => {
|
||||
if (dislikeQuery) {
|
||||
setDislikeQuery(false);
|
||||
setDislikeImageLink(LikeRest);
|
||||
} else {
|
||||
setDislikeQuery(true);
|
||||
setLikeQuery(false);
|
||||
setDislikeImageLink(LikePressed);
|
||||
setLikeImageLink(LikeRest);
|
||||
useQueryCopilot.getState().openFeedbackModal(generatedQuery, false, userPrompt);
|
||||
}
|
||||
}}
|
||||
onMouseOver={() => setDislikeImageLink(LikeHover)}
|
||||
onMouseLeave={() => setDislikeImageLink(dislikeQuery ? LikePressed : LikeRest)}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
@ -0,0 +1,666 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Feedback buttons snapshot tests should click dislike and show popup 1`] = `
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="likeBtn16"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikePressed",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
"transform": "rotate(180deg)",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="dislikeBtn17"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
||||
exports[`Feedback buttons snapshot tests should click like and dismiss callout 1`] = `
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikePressed",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="likeBtn2"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
"transform": "rotate(180deg)",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="dislikeBtn3"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
||||
exports[`Feedback buttons snapshot tests should click like and show callout 1`] = `
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<Callout
|
||||
directionalHint={1}
|
||||
onDismiss={[Function]}
|
||||
role="dialog"
|
||||
style={
|
||||
Object {
|
||||
"borderRadius": "4px",
|
||||
"padding": "5px 12px 5px 12px",
|
||||
}
|
||||
}
|
||||
styles={
|
||||
Object {
|
||||
"beakCurtain": Object {
|
||||
"borderRadius": "4px",
|
||||
},
|
||||
"root": Object {
|
||||
"borderRadius": "4px",
|
||||
},
|
||||
}
|
||||
}
|
||||
target="#likeBtn0"
|
||||
>
|
||||
<Text>
|
||||
|
||||
<Text>
|
||||
Thank you. Need to give
|
||||
|
||||
<StyledLinkBase
|
||||
onClick={[Function]}
|
||||
>
|
||||
more feedback?
|
||||
</StyledLinkBase>
|
||||
</Text>
|
||||
</Text>
|
||||
</Callout>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikePressed",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="likeBtn0"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
"transform": "rotate(180deg)",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="dislikeBtn1"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
||||
exports[`Feedback buttons snapshot tests should click like and submit feedback 1`] = `
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikePressed",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="likeBtn4"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
"transform": "rotate(180deg)",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="dislikeBtn5"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
||||
exports[`Feedback buttons snapshot tests should dobule click on dislike 1`] = `
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="likeBtn26"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
"transform": "rotate(180deg)",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="dislikeBtn27"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
||||
exports[`Feedback buttons snapshot tests should dobule click on like 1`] = `
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="likeBtn14"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
"transform": "rotate(180deg)",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="dislikeBtn15"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
||||
exports[`Feedback buttons snapshot tests should hover over dislike 1`] = `
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="likeBtn18"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeHover",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
"transform": "rotate(180deg)",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="dislikeBtn19"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
||||
exports[`Feedback buttons snapshot tests should hover over dislike and click 1`] = `
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="likeBtn24"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikePressed",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
"transform": "rotate(180deg)",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="dislikeBtn25"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
||||
exports[`Feedback buttons snapshot tests should hover over like 1`] = `
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeHover",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="likeBtn6"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
"transform": "rotate(180deg)",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="dislikeBtn7"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
||||
exports[`Feedback buttons snapshot tests should hover over like and click 1`] = `
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<Callout
|
||||
directionalHint={1}
|
||||
onDismiss={[Function]}
|
||||
role="dialog"
|
||||
style={
|
||||
Object {
|
||||
"borderRadius": "4px",
|
||||
"padding": "5px 12px 5px 12px",
|
||||
}
|
||||
}
|
||||
styles={
|
||||
Object {
|
||||
"beakCurtain": Object {
|
||||
"borderRadius": "4px",
|
||||
},
|
||||
"root": Object {
|
||||
"borderRadius": "4px",
|
||||
},
|
||||
}
|
||||
}
|
||||
target="#likeBtn12"
|
||||
>
|
||||
<Text>
|
||||
|
||||
<Text>
|
||||
Thank you. Need to give
|
||||
|
||||
<StyledLinkBase
|
||||
onClick={[Function]}
|
||||
>
|
||||
more feedback?
|
||||
</StyledLinkBase>
|
||||
</Text>
|
||||
</Text>
|
||||
</Callout>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikePressed",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="likeBtn12"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
"transform": "rotate(180deg)",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="dislikeBtn13"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
||||
exports[`Feedback buttons snapshot tests should hover over pressed dislike and leave 1`] = `
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="likeBtn22"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikePressed",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
"transform": "rotate(180deg)",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="dislikeBtn23"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
||||
exports[`Feedback buttons snapshot tests should hover over pressed like and leave 1`] = `
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<Callout
|
||||
directionalHint={1}
|
||||
onDismiss={[Function]}
|
||||
role="dialog"
|
||||
style={
|
||||
Object {
|
||||
"borderRadius": "4px",
|
||||
"padding": "5px 12px 5px 12px",
|
||||
}
|
||||
}
|
||||
styles={
|
||||
Object {
|
||||
"beakCurtain": Object {
|
||||
"borderRadius": "4px",
|
||||
},
|
||||
"root": Object {
|
||||
"borderRadius": "4px",
|
||||
},
|
||||
}
|
||||
}
|
||||
target="#likeBtn10"
|
||||
>
|
||||
<Text>
|
||||
|
||||
<Text>
|
||||
Thank you. Need to give
|
||||
|
||||
<StyledLinkBase
|
||||
onClick={[Function]}
|
||||
>
|
||||
more feedback?
|
||||
</StyledLinkBase>
|
||||
</Text>
|
||||
</Text>
|
||||
</Callout>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikePressed",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="likeBtn10"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
"transform": "rotate(180deg)",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="dislikeBtn11"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
||||
exports[`Feedback buttons snapshot tests should hover over rest dislike and leave 1`] = `
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="likeBtn20"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
"transform": "rotate(180deg)",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="dislikeBtn21"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
||||
exports[`Feedback buttons snapshot tests should hover over rest like and leave 1`] = `
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="likeBtn8"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": "LikeRest",
|
||||
},
|
||||
"style": Object {
|
||||
"minHeight": "18px",
|
||||
"transform": "rotate(180deg)",
|
||||
},
|
||||
}
|
||||
}
|
||||
id="dislikeBtn9"
|
||||
onClick={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
@ -0,0 +1,19 @@
|
||||
import { ActionButton } from "@fluentui/react";
|
||||
import { InsertButton } from "Explorer/QueryCopilot/V2/Bubbles/Output/Buttons/Insert/InsertButton";
|
||||
import { shallow } from "enzyme";
|
||||
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
||||
import React from "react";
|
||||
|
||||
describe("Insert button snapshot tests", () => {
|
||||
it("should click and update state", () => {
|
||||
const testQuery = "test query";
|
||||
useQueryCopilot.getState().setGeneratedQuery(testQuery);
|
||||
const wrapper = shallow(<InsertButton />);
|
||||
|
||||
const button = wrapper.find(ActionButton).first();
|
||||
button.simulate("click");
|
||||
|
||||
expect(useQueryCopilot.getState().query).toEqual(testQuery);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,16 @@
|
||||
import { ActionButton } from "@fluentui/react";
|
||||
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
||||
import React from "react";
|
||||
import CopilotInsert from "../../../../../../../../images/CopilotInsert.svg";
|
||||
|
||||
export const InsertButton: React.FC = (): JSX.Element => {
|
||||
return (
|
||||
<ActionButton
|
||||
iconProps={{ imageProps: { src: CopilotInsert } }}
|
||||
style={{ borderRadius: "4px", borderWidth: "1px", borderColor: "#D1D1D1", height: "24px", paddingBottom: "2px" }}
|
||||
onClick={() => useQueryCopilot.getState().setQuery(useQueryCopilot.getState().generatedQuery)}
|
||||
>
|
||||
Insert
|
||||
</ActionButton>
|
||||
);
|
||||
};
|
@ -0,0 +1,25 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Insert button snapshot tests should click and update state 1`] = `
|
||||
<CustomizedActionButton
|
||||
iconProps={
|
||||
Object {
|
||||
"imageProps": Object {
|
||||
"src": Object {},
|
||||
},
|
||||
}
|
||||
}
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"borderColor": "#D1D1D1",
|
||||
"borderRadius": "4px",
|
||||
"borderWidth": "1px",
|
||||
"height": "24px",
|
||||
"paddingBottom": "2px",
|
||||
}
|
||||
}
|
||||
>
|
||||
Insert
|
||||
</CustomizedActionButton>
|
||||
`;
|
@ -0,0 +1,11 @@
|
||||
import { MoreButton } from "Explorer/QueryCopilot/V2/Bubbles/Output/Buttons/More/MoreButton";
|
||||
import { shallow } from "enzyme";
|
||||
import React from "react";
|
||||
|
||||
describe("More button snapshot tests", () => {
|
||||
it("should render", () => {
|
||||
const wrapper = shallow(<MoreButton />);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,41 @@
|
||||
import { DirectionalHint, IContextualMenuProps, IconButton } from "@fluentui/react";
|
||||
import React from "react";
|
||||
import ExplainIcon from "../../../../../../../../images/CopilotExplain.svg";
|
||||
import OptimizeIcon from "../../../../../../../../images/CopilotOptimize.svg";
|
||||
import RegenerateIcon from "../../../../../../../../images/CopilotRegenerate.svg";
|
||||
import SimplifyIcon from "../../../../../../../../images/CopilotSimplify.svg";
|
||||
|
||||
export const MoreButton: React.FC = (): JSX.Element => {
|
||||
const menuProps: IContextualMenuProps = {
|
||||
items: [
|
||||
{
|
||||
key: "regenerate",
|
||||
text: "Regenerate code",
|
||||
iconProps: { imageProps: { src: RegenerateIcon } },
|
||||
},
|
||||
{
|
||||
key: "explain",
|
||||
text: "Explain code",
|
||||
iconProps: { imageProps: { src: ExplainIcon } },
|
||||
},
|
||||
{
|
||||
key: "optimize",
|
||||
text: "Optimize",
|
||||
iconProps: { imageProps: { src: OptimizeIcon } },
|
||||
},
|
||||
{
|
||||
key: "simplify",
|
||||
text: "Simplify",
|
||||
iconProps: { imageProps: { src: SimplifyIcon } },
|
||||
},
|
||||
],
|
||||
directionalHint: DirectionalHint.topRightEdge,
|
||||
calloutProps: {
|
||||
styles: { calloutMain: { borderRadius: "4px" }, root: { borderRadius: "4px" } },
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<IconButton iconProps={{ iconName: "More" }} menuProps={menuProps} menuIconProps={{ hidden: true }}></IconButton>
|
||||
);
|
||||
};
|
@ -0,0 +1,69 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`More button snapshot tests should render 1`] = `
|
||||
<CustomizedIconButton
|
||||
iconProps={
|
||||
Object {
|
||||
"iconName": "More",
|
||||
}
|
||||
}
|
||||
menuIconProps={
|
||||
Object {
|
||||
"hidden": true,
|
||||
}
|
||||
}
|
||||
menuProps={
|
||||
Object {
|
||||
"calloutProps": Object {
|
||||
"styles": Object {
|
||||
"calloutMain": Object {
|
||||
"borderRadius": "4px",
|
||||
},
|
||||
"root": Object {
|
||||
"borderRadius": "4px",
|
||||
},
|
||||
},
|
||||
},
|
||||
"directionalHint": 2,
|
||||
"items": Array [
|
||||
Object {
|
||||
"iconProps": Object {
|
||||
"imageProps": Object {
|
||||
"src": Object {},
|
||||
},
|
||||
},
|
||||
"key": "regenerate",
|
||||
"text": "Regenerate code",
|
||||
},
|
||||
Object {
|
||||
"iconProps": Object {
|
||||
"imageProps": Object {
|
||||
"src": Object {},
|
||||
},
|
||||
},
|
||||
"key": "explain",
|
||||
"text": "Explain code",
|
||||
},
|
||||
Object {
|
||||
"iconProps": Object {
|
||||
"imageProps": Object {
|
||||
"src": Object {},
|
||||
},
|
||||
},
|
||||
"key": "optimize",
|
||||
"text": "Optimize",
|
||||
},
|
||||
Object {
|
||||
"iconProps": Object {
|
||||
"imageProps": Object {
|
||||
"src": Object {},
|
||||
},
|
||||
},
|
||||
"key": "simplify",
|
||||
"text": "Simplify",
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
/>
|
||||
`;
|
@ -0,0 +1,11 @@
|
||||
import { OutputBubbleButtons } from "Explorer/QueryCopilot/V2/Bubbles/Output/Buttons/OutputBubbleButtons";
|
||||
import { shallow } from "enzyme";
|
||||
import React from "react";
|
||||
|
||||
describe("Output Bubble Buttons snapshot tests", () => {
|
||||
it("should render", () => {
|
||||
const wrapper = shallow(<OutputBubbleButtons />);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,25 @@
|
||||
import { Stack } from "@fluentui/react";
|
||||
import { CopyButton } from "Explorer/QueryCopilot/V2/Bubbles/Output/Buttons/Copy/CopyButton";
|
||||
import { FeedbackButtons } from "Explorer/QueryCopilot/V2/Bubbles/Output/Buttons/Feedback/FeedbackButtons";
|
||||
import { InsertButton } from "Explorer/QueryCopilot/V2/Bubbles/Output/Buttons/Insert/InsertButton";
|
||||
import { MoreButton } from "Explorer/QueryCopilot/V2/Bubbles/Output/Buttons/More/MoreButton";
|
||||
import React from "react";
|
||||
|
||||
export const OutputBubbleButtons: React.FC = (): JSX.Element => {
|
||||
return (
|
||||
<Stack horizontal>
|
||||
<Stack.Item style={{ paddingTop: "5px" }}>
|
||||
<InsertButton />
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<CopyButton />
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<FeedbackButtons />
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<MoreButton />
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
);
|
||||
};
|
@ -0,0 +1,26 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Output Bubble Buttons snapshot tests should render 1`] = `
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<StackItem
|
||||
style={
|
||||
Object {
|
||||
"paddingTop": "5px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<InsertButton />
|
||||
</StackItem>
|
||||
<StackItem>
|
||||
<CopyButton />
|
||||
</StackItem>
|
||||
<StackItem>
|
||||
<FeedbackButtons />
|
||||
</StackItem>
|
||||
<StackItem>
|
||||
<MoreButton />
|
||||
</StackItem>
|
||||
</Stack>
|
||||
`;
|
@ -0,0 +1,21 @@
|
||||
import { EditorReact } from "Explorer/Controls/Editor/EditorReact";
|
||||
import { OutputBubble } from "Explorer/QueryCopilot/V2/Bubbles/Output/OutputBubble";
|
||||
import { shallow } from "enzyme";
|
||||
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
||||
import { withHooks } from "jest-react-hooks-shallow";
|
||||
import React from "react";
|
||||
|
||||
describe("Output Bubble snapshot tests", () => {
|
||||
it("should render and update height", () => {
|
||||
withHooks(() => {
|
||||
useQueryCopilot.getState().setGeneratedQuery("test query");
|
||||
useQueryCopilot.getState().setGeneratedQueryComments("test comments");
|
||||
const wrapper = shallow(<OutputBubble />);
|
||||
|
||||
const editor = wrapper.find(EditorReact).first();
|
||||
|
||||
expect(editor.props().monacoContainerStyles).not.toHaveProperty("height", undefined);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
60
src/Explorer/QueryCopilot/V2/Bubbles/Output/OutputBubble.tsx
Normal file
@ -0,0 +1,60 @@
|
||||
import { Stack, Text } from "@fluentui/react";
|
||||
import { EditorReact } from "Explorer/Controls/Editor/EditorReact";
|
||||
import { OutputBubbleButtons } from "Explorer/QueryCopilot/V2/Bubbles/Output/Buttons/OutputBubbleButtons";
|
||||
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
||||
import React, { useState } from "react";
|
||||
|
||||
export const OutputBubble: React.FC = (): JSX.Element => {
|
||||
const [windowHeight, setWindowHeight] = useState<string>();
|
||||
|
||||
const calculateQueryWindowHeight = (): string => {
|
||||
const calculatedHeight = document.getElementById("outputBubble")?.clientHeight * (3 / 5);
|
||||
return `${calculatedHeight}px`;
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
setWindowHeight(calculateQueryWindowHeight());
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Stack
|
||||
id="outputBubble"
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
padding: "10px",
|
||||
margin: "10px",
|
||||
backgroundColor: "white",
|
||||
borderRadius: "8px",
|
||||
}}
|
||||
tokens={{ padding: 8, childrenGap: 8 }}
|
||||
>
|
||||
<Stack.Item style={{ alignSelf: "flex-start", paddingLeft: "2px" }}>
|
||||
{useQueryCopilot.getState()?.generatedQueryComments}
|
||||
</Stack.Item>
|
||||
<Stack.Item style={{ alignSelf: "stretch", flexGrow: 4 }}>
|
||||
<EditorReact
|
||||
language={"sql"}
|
||||
content={useQueryCopilot.getState()?.generatedQuery}
|
||||
isReadOnly={true}
|
||||
ariaLabel={"AI Response"}
|
||||
wordWrap="on"
|
||||
lineNumbers="on"
|
||||
lineNumbersMinChars={2}
|
||||
lineDecorationsWidth={0}
|
||||
minimap={{ enabled: false }}
|
||||
scrollBeyondLastLine={false}
|
||||
monacoContainerStyles={{ height: windowHeight, borderRadius: "4px" }}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item style={{ alignSelf: "flex-start" }}>
|
||||
<OutputBubbleButtons />
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Text style={{ fontWeight: 400, fontSize: "10px", lineHeight: "14px" }}>
|
||||
AI-generated content may be incorrect
|
||||
</Text>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
);
|
||||
};
|
@ -0,0 +1,87 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Output Bubble snapshot tests should render and update height 1`] = `
|
||||
<Stack
|
||||
id="outputBubble"
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "white",
|
||||
"borderRadius": "8px",
|
||||
"display": "flex",
|
||||
"margin": "10px",
|
||||
"padding": "10px",
|
||||
}
|
||||
}
|
||||
tokens={
|
||||
Object {
|
||||
"childrenGap": 8,
|
||||
"padding": 8,
|
||||
}
|
||||
}
|
||||
>
|
||||
<StackItem
|
||||
style={
|
||||
Object {
|
||||
"alignSelf": "flex-start",
|
||||
"paddingLeft": "2px",
|
||||
}
|
||||
}
|
||||
>
|
||||
test comments
|
||||
</StackItem>
|
||||
<StackItem
|
||||
style={
|
||||
Object {
|
||||
"alignSelf": "stretch",
|
||||
"flexGrow": 4,
|
||||
}
|
||||
}
|
||||
>
|
||||
<EditorReact
|
||||
ariaLabel="AI Response"
|
||||
content="test query"
|
||||
isReadOnly={true}
|
||||
language="sql"
|
||||
lineDecorationsWidth={0}
|
||||
lineNumbers="on"
|
||||
lineNumbersMinChars={2}
|
||||
minimap={
|
||||
Object {
|
||||
"enabled": false,
|
||||
}
|
||||
}
|
||||
monacoContainerStyles={
|
||||
Object {
|
||||
"borderRadius": "4px",
|
||||
"height": "NaNpx",
|
||||
}
|
||||
}
|
||||
scrollBeyondLastLine={false}
|
||||
wordWrap="on"
|
||||
/>
|
||||
</StackItem>
|
||||
<StackItem
|
||||
style={
|
||||
Object {
|
||||
"alignSelf": "flex-start",
|
||||
}
|
||||
}
|
||||
>
|
||||
<OutputBubbleButtons />
|
||||
</StackItem>
|
||||
<StackItem>
|
||||
<Text
|
||||
style={
|
||||
Object {
|
||||
"fontSize": "10px",
|
||||
"fontWeight": 400,
|
||||
"lineHeight": "14px",
|
||||
}
|
||||
}
|
||||
>
|
||||
AI-generated content may be incorrect
|
||||
</Text>
|
||||
</StackItem>
|
||||
</Stack>
|
||||
`;
|
@ -19,7 +19,7 @@ exports[`Footer snapshot test should not pass if no text 1`] = `
|
||||
<Stack>
|
||||
<Image
|
||||
onClick={[Function]}
|
||||
src=""
|
||||
src={Object {}}
|
||||
styles={
|
||||
Object {
|
||||
"label": Object {
|
||||
@ -104,7 +104,7 @@ exports[`Footer snapshot test should not pass text with non enter key 1`] = `
|
||||
<Stack>
|
||||
<Image
|
||||
onClick={[Function]}
|
||||
src=""
|
||||
src={Object {}}
|
||||
styles={
|
||||
Object {
|
||||
"label": Object {
|
||||
@ -189,7 +189,7 @@ exports[`Footer snapshot test should open sample prompts on button click 1`] = `
|
||||
<Stack>
|
||||
<Image
|
||||
onClick={[Function]}
|
||||
src=""
|
||||
src={Object {}}
|
||||
styles={
|
||||
Object {
|
||||
"label": Object {
|
||||
@ -274,7 +274,7 @@ exports[`Footer snapshot test should pass text with enter key 1`] = `
|
||||
<Stack>
|
||||
<Image
|
||||
onClick={[Function]}
|
||||
src=""
|
||||
src={Object {}}
|
||||
styles={
|
||||
Object {
|
||||
"label": Object {
|
||||
@ -359,7 +359,7 @@ exports[`Footer snapshot test should pass text with icon button 1`] = `
|
||||
<Stack>
|
||||
<Image
|
||||
onClick={[Function]}
|
||||
src=""
|
||||
src={Object {}}
|
||||
styles={
|
||||
Object {
|
||||
"label": Object {
|
||||
@ -444,7 +444,7 @@ exports[`Footer snapshot test should update user input 1`] = `
|
||||
<Stack>
|
||||
<Image
|
||||
onClick={[Function]}
|
||||
src=""
|
||||
src={Object {}}
|
||||
styles={
|
||||
Object {
|
||||
"label": Object {
|
||||
|
@ -18,7 +18,7 @@ exports[`Header snapshot test should close on button click 1`] = `
|
||||
verticalAlign="center"
|
||||
>
|
||||
<Image
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
<Text
|
||||
style={
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Stack } from "@fluentui/react";
|
||||
import { QueryCopilotProps } from "Explorer/QueryCopilot/Shared/QueryCopilotInterfaces";
|
||||
import { OutputBubble } from "Explorer/QueryCopilot/V2/Bubbles/Output/OutputBubble";
|
||||
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";
|
||||
@ -10,13 +11,7 @@ import React from "react";
|
||||
import { WelcomeSidebarModal } from "../Modal/WelcomeSidebarModal";
|
||||
|
||||
export const QueryCopilotSidebar: React.FC<QueryCopilotProps> = ({ explorer }: QueryCopilotProps): JSX.Element => {
|
||||
const {
|
||||
setWasCopilotUsed,
|
||||
showCopilotSidebar,
|
||||
chatMessages,
|
||||
showWelcomeSidebar,
|
||||
isGeneratingQuery,
|
||||
} = useQueryCopilot();
|
||||
const { setWasCopilotUsed, showCopilotSidebar, chatMessages, isGeneratingQuery } = useQueryCopilot();
|
||||
|
||||
React.useEffect(() => {
|
||||
if (showCopilotSidebar) {
|
||||
@ -27,58 +22,36 @@ export const QueryCopilotSidebar: React.FC<QueryCopilotProps> = ({ explorer }: Q
|
||||
return (
|
||||
<Stack style={{ width: "100%", height: "100%", backgroundColor: "#FAFAFA" }}>
|
||||
<Header />
|
||||
{showWelcomeSidebar ? (
|
||||
<WelcomeSidebarModal />
|
||||
) : (
|
||||
<>
|
||||
<WelcomeSidebarModal />
|
||||
<Stack
|
||||
style={{
|
||||
flexGrow: 1,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
overflowY: "auto",
|
||||
}}
|
||||
>
|
||||
<WelcomeBubble />
|
||||
{chatMessages.map((message, index) => (
|
||||
<Stack
|
||||
key={index}
|
||||
horizontalAlign="center"
|
||||
tokens={{ padding: 8, childrenGap: 8 }}
|
||||
style={{
|
||||
flexGrow: 1,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
overflowY: "auto",
|
||||
backgroundColor: "#E0E7FF",
|
||||
borderRadius: "8px",
|
||||
margin: "5px 10px",
|
||||
textAlign: "start",
|
||||
}}
|
||||
>
|
||||
<WelcomeBubble />
|
||||
{chatMessages.map((message, index) =>
|
||||
message.source === 0 ? (
|
||||
<Stack
|
||||
key={index}
|
||||
horizontalAlign="center"
|
||||
tokens={{ padding: 8, childrenGap: 8 }}
|
||||
style={{
|
||||
backgroundColor: "#E0E7FF",
|
||||
borderRadius: "8px",
|
||||
margin: "5px 10px",
|
||||
textAlign: "start",
|
||||
}}
|
||||
>
|
||||
{message.message}
|
||||
</Stack>
|
||||
) : (
|
||||
<Stack
|
||||
key={index}
|
||||
horizontalAlign="center"
|
||||
tokens={{ padding: 8, childrenGap: 8 }}
|
||||
style={{
|
||||
backgroundColor: "white",
|
||||
borderRadius: "8px",
|
||||
margin: "5px 10px",
|
||||
textAlign: "start",
|
||||
}}
|
||||
>
|
||||
{message.message}
|
||||
</Stack>
|
||||
)
|
||||
)}
|
||||
|
||||
<RetrievingBubble />
|
||||
|
||||
{chatMessages.length === 0 && !isGeneratingQuery && <SampleBubble />}
|
||||
{message}
|
||||
</Stack>
|
||||
<Footer explorer={explorer} />
|
||||
</>
|
||||
)}
|
||||
))}
|
||||
<OutputBubble />
|
||||
<RetrievingBubble />
|
||||
{chatMessages.length === 0 && !isGeneratingQuery && <SampleBubble />}
|
||||
</Stack>
|
||||
<Footer explorer={explorer} />
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
@ -12,6 +12,51 @@ exports[`Query Copilot Sidebar snapshot test should render and not set copilot u
|
||||
>
|
||||
<Header />
|
||||
<WelcomeSidebarModal />
|
||||
<Stack
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"flexDirection": "column",
|
||||
"flexGrow": 1,
|
||||
"overflowY": "auto",
|
||||
}
|
||||
}
|
||||
>
|
||||
<WelcomeBubble />
|
||||
<OutputBubble />
|
||||
<RetrievingBubble />
|
||||
<SampleBubble />
|
||||
</Stack>
|
||||
<Footer
|
||||
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],
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
||||
@ -27,6 +72,51 @@ exports[`Query Copilot Sidebar snapshot test should render and set copilot used
|
||||
>
|
||||
<Header />
|
||||
<WelcomeSidebarModal />
|
||||
<Stack
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"flexDirection": "column",
|
||||
"flexGrow": 1,
|
||||
"overflowY": "auto",
|
||||
}
|
||||
}
|
||||
>
|
||||
<WelcomeBubble />
|
||||
<OutputBubble />
|
||||
<RetrievingBubble />
|
||||
<SampleBubble />
|
||||
</Stack>
|
||||
<Footer
|
||||
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],
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
||||
@ -42,6 +132,51 @@ exports[`Query Copilot Sidebar snapshot test should render samples without messa
|
||||
>
|
||||
<Header />
|
||||
<WelcomeSidebarModal />
|
||||
<Stack
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"flexDirection": "column",
|
||||
"flexGrow": 1,
|
||||
"overflowY": "auto",
|
||||
}
|
||||
}
|
||||
>
|
||||
<WelcomeBubble />
|
||||
<OutputBubble />
|
||||
<RetrievingBubble />
|
||||
<SampleBubble />
|
||||
</Stack>
|
||||
<Footer
|
||||
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],
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
||||
@ -57,5 +192,69 @@ exports[`Query Copilot Sidebar snapshot test should render with chat messages 1`
|
||||
>
|
||||
<Header />
|
||||
<WelcomeSidebarModal />
|
||||
<Stack
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"flexDirection": "column",
|
||||
"flexGrow": 1,
|
||||
"overflowY": "auto",
|
||||
}
|
||||
}
|
||||
>
|
||||
<WelcomeBubble />
|
||||
<Stack
|
||||
horizontalAlign="center"
|
||||
key="0"
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#E0E7FF",
|
||||
"borderRadius": "8px",
|
||||
"margin": "5px 10px",
|
||||
"textAlign": "start",
|
||||
}
|
||||
}
|
||||
tokens={
|
||||
Object {
|
||||
"childrenGap": 8,
|
||||
"padding": 8,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Component />
|
||||
</Stack>
|
||||
<OutputBubble />
|
||||
<RetrievingBubble />
|
||||
</Stack>
|
||||
<Footer
|
||||
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],
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
`;
|
||||
|
@ -74,7 +74,7 @@ exports[`Query Copilot Carousel snapshot test should render when isOpen is true
|
||||
To generate queries , just describe the query you want and copilot will generate the query for you.Watch this video to learn more about how to use copilot.
|
||||
</Text>
|
||||
<Image
|
||||
src=""
|
||||
src={Object {}}
|
||||
style={
|
||||
Object {
|
||||
"margin": "16px auto",
|
||||
|
@ -23,7 +23,7 @@ exports[`Query copilot tab snapshot test should render with initial input 1`] =
|
||||
verticalAlign="center"
|
||||
>
|
||||
<Image
|
||||
src=""
|
||||
src={Object {}}
|
||||
/>
|
||||
<Text
|
||||
style={
|
||||
|
@ -76,6 +76,7 @@ interface IQueryTabStates {
|
||||
isExecutionError: boolean;
|
||||
isExecuting: boolean;
|
||||
showCopilotSidebar: boolean;
|
||||
queryCopilotGeneratedQuery: string;
|
||||
}
|
||||
|
||||
export default class QueryTabComponent extends React.Component<IQueryTabComponentProps, IQueryTabStates> {
|
||||
@ -101,6 +102,7 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
|
||||
isExecutionError: this.props.isExecutionError,
|
||||
isExecuting: false,
|
||||
showCopilotSidebar: useQueryCopilot.getState().showCopilotSidebar,
|
||||
queryCopilotGeneratedQuery: useQueryCopilot.getState().query,
|
||||
};
|
||||
this.isCloseClicked = false;
|
||||
this.splitterId = this.props.tabId + "_splitter";
|
||||
@ -334,6 +336,7 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
|
||||
public onChangeContent(newContent: string): void {
|
||||
this.setState({
|
||||
sqlQueryEditorContent: newContent,
|
||||
queryCopilotGeneratedQuery: "",
|
||||
});
|
||||
if (this.isPreferredApiMongoDB) {
|
||||
if (newContent.length > 0) {
|
||||
@ -365,6 +368,14 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
|
||||
useCommandBar.getState().setContextButtons(this.getTabsButtons());
|
||||
}
|
||||
|
||||
public setEditorContent(): string {
|
||||
if (this.state.queryCopilotGeneratedQuery) {
|
||||
return this.state.queryCopilotGeneratedQuery;
|
||||
}
|
||||
|
||||
return this.state.sqlQueryEditorContent;
|
||||
}
|
||||
|
||||
private unsubscribeCopilotSidebar: () => void;
|
||||
|
||||
componentDidMount(): void {
|
||||
@ -372,6 +383,9 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
|
||||
if (this.state.showCopilotSidebar !== state.showCopilotSidebar) {
|
||||
this.setState({ showCopilotSidebar: state.showCopilotSidebar });
|
||||
}
|
||||
if (this.state.queryCopilotGeneratedQuery !== state.query) {
|
||||
this.setState({ queryCopilotGeneratedQuery: state.query });
|
||||
}
|
||||
});
|
||||
|
||||
useCommandBar.getState().setContextButtons(this.getTabsButtons());
|
||||
@ -393,7 +407,7 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
|
||||
<div className="queryEditor" style={{ height: "100%" }}>
|
||||
<EditorReact
|
||||
language={"sql"}
|
||||
content={this.state.sqlQueryEditorContent}
|
||||
content={this.setEditorContent()}
|
||||
isReadOnly={false}
|
||||
ariaLabel={"Editing Query"}
|
||||
lineNumbers={"on"}
|
||||
|
11
svgTransform.js
Normal file
@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
process() {
|
||||
return {
|
||||
code: `module.exports = {};`,
|
||||
};
|
||||
},
|
||||
getCacheKey() {
|
||||
// The output is always the same.
|
||||
return "svgTransform";
|
||||
},
|
||||
};
|