tinker with an "Execute Query" action in Monaco

This commit is contained in:
Ashley Stanton-Nurse 2024-03-28 13:08:15 -07:00
parent 44d886b4a0
commit 2598760a11
5 changed files with 53 additions and 18 deletions

View File

@ -1,6 +1,6 @@
import { Spinner, SpinnerSize } from "@fluentui/react";
import * as React from "react";
import { loadMonaco, monaco } from "../../LazyMonaco";
import { MonacoNamespace, loadMonaco, monaco } from "../../LazyMonaco";
// import "./EditorReact.less";
interface EditorReactStates {
@ -21,6 +21,7 @@ export interface EditorReactProps {
minimap?: monaco.editor.IEditorOptions["minimap"];
scrollBeyondLastLine?: monaco.editor.IEditorOptions["scrollBeyondLastLine"];
monacoContainerStyles?: React.CSSProperties;
configureEditor?: (monaco: MonacoNamespace, editor: monaco.editor.IStandaloneCodeEditor) => void;
}
export class EditorReact extends React.Component<EditorReactProps, EditorReactStates> {
@ -69,7 +70,7 @@ export class EditorReact extends React.Component<EditorReactProps, EditorReactSt
);
}
protected configureEditor(editor: monaco.editor.IStandaloneCodeEditor) {
protected configureEditor(monaco: MonacoNamespace, editor: monaco.editor.IStandaloneCodeEditor) {
this.editor = editor;
const queryEditorModel = this.editor.getModel();
if (!this.props.isReadOnly && this.props.onContentChanged) {
@ -87,12 +88,16 @@ export class EditorReact extends React.Component<EditorReactProps, EditorReactSt
},
);
}
if (this.props.configureEditor) {
this.props.configureEditor(monaco, this.editor);
}
}
/**
* Create the monaco editor and attach to DOM
*/
private async createEditor(createCallback: (e: monaco.editor.IStandaloneCodeEditor) => void) {
private async createEditor(createCallback: (monaco: MonacoNamespace, e: monaco.editor.IStandaloneCodeEditor) => void) {
const options: monaco.editor.IStandaloneEditorConstructionOptions = {
language: this.props.language,
value: this.props.content,
@ -111,7 +116,7 @@ export class EditorReact extends React.Component<EditorReactProps, EditorReactSt
this.rootNode.innerHTML = "";
const monaco = await loadMonaco();
createCallback(monaco?.editor?.create(this.rootNode, options));
createCallback(monaco, monaco?.editor?.create(this.rootNode, options));
if (this.rootNode.innerHTML) {
this.setState({

View File

@ -0,0 +1,37 @@
import { EditorReact } from "Explorer/Controls/Editor/EditorReact";
import { MonacoNamespace, monaco } from "Explorer/LazyMonaco";
import React from "react";
export type QueryEditorProps = {
content: string
onContentChanged: (newContent: string) => void;
onContentSelected: (selectedContent: string) => void;
/**
* Callback that will run when the "Execute Query" command is invoked.
*/
onExecuteQuery: () => void;
};
export const QueryEditor: React.FunctionComponent<QueryEditorProps> = (props) => {
const configureEditor = (monaco: MonacoNamespace, editor: monaco.editor.IStandaloneCodeEditor) => {
editor.addAction({
id: "execute-query",
label: "Execute Query",
keybindings: [monaco.KeyMod.Shift | monaco.KeyCode.Enter],
run: props.onExecuteQuery,
});
}
return <EditorReact
language={"sql"}
content={props.content}
isReadOnly={false}
wordWrap={"on"}
ariaLabel={"Editing Query"}
lineNumbers={"on"}
onContentChanged={props.onContentChanged}
onContentSelected={props.onContentSelected}
configureEditor={configureEditor}
/>;
}

View File

@ -3,3 +3,4 @@ export type { monaco };
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const loadMonaco = () => import(/* webpackChunkName: "lazy-monaco" */ "monaco-editor/esm/vs/editor/editor.api");
export type MonacoNamespace = Awaited<ReturnType<typeof loadMonaco>>;

View File

@ -2,7 +2,7 @@
import { Stack } from "@fluentui/react";
import { QueryCopilotSampleContainerId, QueryCopilotSampleDatabaseId } from "Common/Constants";
import { CommandButtonComponentProps } from "Explorer/Controls/CommandButton/CommandButtonComponent";
import { EditorReact } from "Explorer/Controls/Editor/EditorReact";
import { QueryEditor } from "Explorer/Controls/Editor/QueryEditor";
import { useCommandBar } from "Explorer/Menus/CommandBar/CommandBarComponentAdapter";
import { SaveQueryPane } from "Explorer/Panes/SaveQueryPane/SaveQueryPane";
import { QueryCopilotPromptbar } from "Explorer/QueryCopilot/QueryCopilotPromptbar";
@ -104,15 +104,11 @@ export const QueryCopilotTab: React.FC<QueryCopilotProps> = ({ explorer }: Query
)}
<Stack className="tabPaneContentContainer">
<SplitterLayout percentage={true} vertical={true} primaryIndex={0} primaryMinSize={30} secondaryMinSize={70}>
<EditorReact
language={"sql"}
<QueryEditor
content={query}
isReadOnly={false}
wordWrap={"on"}
ariaLabel={"Editing Query"}
lineNumbers={"on"}
onContentChanged={(newQuery: string) => setQuery(newQuery)}
onContentSelected={(selectedQuery: string) => setSelectedQuery(selectedQuery)}
onExecuteQuery={() => OnExecuteQueryClick(useQueryCopilot as Partial<QueryCopilotState>)}
/>
<QueryCopilotResults />
</SplitterLayout>

View File

@ -3,6 +3,7 @@
import { FeedOptions, QueryOperationOptions } from "@azure/cosmos";
import { Platform, configContext } from "ConfigContext";
import { useDialog } from "Explorer/Controls/Dialog";
import { QueryEditor } from "Explorer/Controls/Editor/QueryEditor";
import { QueryCopilotFeedbackModal } from "Explorer/QueryCopilot/Modal/QueryCopilotFeedbackModal";
import { useCopilotStore } from "Explorer/QueryCopilot/QueryCopilotContext";
import { QueryCopilotPromptbar } from "Explorer/QueryCopilot/QueryCopilotPromptbar";
@ -39,7 +40,6 @@ import { userContext } from "../../../UserContext";
import * as QueryUtils from "../../../Utils/QueryUtils";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
import { EditorReact } from "../../Controls/Editor/EditorReact";
import Explorer from "../../Explorer";
import { useCommandBar } from "../../Menus/CommandBar/CommandBarComponentAdapter";
import { BrowseQueriesPane } from "../../Panes/BrowseQueriesPane/BrowseQueriesPane";
@ -599,15 +599,11 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
<SplitterLayout vertical={true} primaryIndex={0} primaryMinSize={100} secondaryMinSize={200}>
<Fragment>
<div className="queryEditor" style={{ height: "100%" }}>
<EditorReact
language={"sql"}
<QueryEditor
content={this.setEditorContent()}
isReadOnly={false}
wordWrap={"on"}
ariaLabel={"Editing Query"}
lineNumbers={"on"}
onContentChanged={(newContent: string) => this.onChangeContent(newContent)}
onContentSelected={(selectedContent: string) => this.onSelectedContent(selectedContent)}
onExecuteQuery={() => this.onExecuteQueryClick()}
/>
</div>
</Fragment>