1
- import { useEffect , useState } from "react" ;
1
+ import { useEffect , useState } from "react" ;
2
2
import Editor from "@monaco-editor/react" ;
3
3
import { Button } from "@/components/ui/button" ;
4
4
import { Input } from "@/components/ui/input" ;
@@ -31,6 +31,7 @@ export default function QueryTabContent({ tab }) {
31
31
const { theme } = useTheme ( ) ;
32
32
const { saveTab, updateQueryTab, runQuery, isLoadingQuery } = useTabState ( ) ;
33
33
const [ monacoEditorContent , setMonacoEditorContent ] = useState ( "" ) ;
34
+ const [ editorInstance , setEditorInstance ] = useState ( null ) ;
34
35
35
36
useEffect ( ( ) => {
36
37
setMonacoEditorContent ( tab . tab_content ) ;
@@ -39,7 +40,7 @@ export default function QueryTabContent({ tab }) {
39
40
useEffect ( ( ) => {
40
41
const handleRunQueryShortCut = ( event ) => {
41
42
if ( event . metaKey && event . key === "Enter" ) {
42
- const query = tab . tab_content ;
43
+ const query = getSelectedText ( editorInstance ) || tab . tab_content ;
43
44
runQuery ( tab . tab_id , query ) ;
44
45
}
45
46
} ;
@@ -57,7 +58,7 @@ export default function QueryTabContent({ tab }) {
57
58
document . removeEventListener ( "keydown" , handleRunQueryShortCut ) ;
58
59
document . removeEventListener ( "keydown" , handleSaveQueryShortCut ) ;
59
60
} ;
60
- } , [ tab ] ) ;
61
+ } , [ tab , editorInstance ] ) ;
61
62
62
63
function formatBytes ( bytes , decimals = 2 ) {
63
64
if ( bytes === 0 ) return "0 Bytes" ;
@@ -75,6 +76,8 @@ export default function QueryTabContent({ tab }) {
75
76
window . sqlCompletionProviderRegistered || false ;
76
77
77
78
const handleEditorDidMount = ( editor , monaco ) => {
79
+ setEditorInstance ( editor ) ;
80
+
78
81
editor . addAction ( {
79
82
id : "format-sql" ,
80
83
label : "Format SQL" ,
@@ -95,6 +98,7 @@ export default function QueryTabContent({ tab }) {
95
98
] ;
96
99
} ,
97
100
} ) ;
101
+
98
102
if ( ! window . sqlCompletionProviderRegistered ) {
99
103
monaco . languages . registerCompletionItemProvider ( "sql" , {
100
104
provideCompletionItems : ( model , position ) => {
@@ -124,7 +128,7 @@ export default function QueryTabContent({ tab }) {
124
128
contextMenuGroupId : "navigation" ,
125
129
contextMenuOrder : 1.5 ,
126
130
run : function ( ed ) {
127
- const query = ed . getValue ( ) ;
131
+ const query = getSelectedText ( ed ) || ed . getValue ( ) ;
128
132
runQuery ( tab . tab_id , query ) ;
129
133
} ,
130
134
} ) ;
@@ -135,6 +139,12 @@ export default function QueryTabContent({ tab }) {
135
139
} ) ;
136
140
} ;
137
141
142
+ const getSelectedText = ( editor ) => {
143
+ if ( ! editor ) return "" ;
144
+ const selection = editor . getSelection ( ) ;
145
+ return editor . getModel ( ) . getValueInRange ( selection ) ;
146
+ } ;
147
+
138
148
return (
139
149
< >
140
150
< div className = "flex flex-col border p-4 rounded-md" >
@@ -161,7 +171,8 @@ export default function QueryTabContent({ tab }) {
161
171
< Button
162
172
variant = ""
163
173
onClick = { ( ) => {
164
- runQuery ( tab . tab_id , tab . tab_content ) ;
174
+ const query = getSelectedText ( editorInstance ) || tab . tab_content ;
175
+ runQuery ( tab . tab_id , query ) ;
165
176
} }
166
177
className = "h-8 hover:bg-secondary hover:text-white"
167
178
disabled = { isLoadingQuery }
@@ -217,8 +228,8 @@ export default function QueryTabContent({ tab }) {
217
228
< div className = "w-full p-2 overflow-auto flex flex-col" >
218
229
< div
219
230
className = { `${ theme === "dark"
220
- ? "ag-theme-alpine-dark"
221
- : "ag-theme-alpine"
231
+ ? "ag-theme-alpine-dark"
232
+ : "ag-theme-alpine"
222
233
} w-full flex-grow`}
223
234
>
224
235
{ isLoadingQuery ? (
0 commit comments