@@ -31,7 +31,7 @@ import {
31
31
LAST_USED_QUERY_ACTION_KEY ,
32
32
QUERY_USE_MULTI_SCHEMA_KEY ,
33
33
} from '../../../../utils/constants' ;
34
- import { useQueryExecutionSettings , useSetting } from '../../../../utils/hooks' ;
34
+ import { useEventHandler , useQueryExecutionSettings , useSetting } from '../../../../utils/hooks' ;
35
35
import { useChangedQuerySettings } from '../../../../utils/hooks/useChangedQuerySettings' ;
36
36
import { useLastQueryExecutionSettings } from '../../../../utils/hooks/useLastQueryExecutionSettings' ;
37
37
import { YQL_LANGUAGE_ID } from '../../../../utils/monaco/constats' ;
@@ -59,10 +59,6 @@ const RESULT_TYPES = {
59
59
EXECUTE : 'execute' ,
60
60
EXPLAIN : 'explain' ,
61
61
} ;
62
- const MONACO_HOT_KEY_ACTIONS = {
63
- sendQuery : 'sendQuery' ,
64
- sendSelectedQuery : 'sendSelectedQuery' ,
65
- } ;
66
62
67
63
const b = cn ( 'query-editor' ) ;
68
64
@@ -94,9 +90,6 @@ function QueryEditor(props: QueryEditorProps) {
94
90
tenantName,
95
91
path,
96
92
setTenantPath : setPath ,
97
- setQueryAction,
98
- saveQueryToHistory,
99
- setShowPreview,
100
93
executeQuery,
101
94
type,
102
95
theme,
@@ -117,9 +110,6 @@ function QueryEditor(props: QueryEditorProps) {
117
110
const [ lastUsedQueryAction , setLastUsedQueryAction ] = useSetting < QueryAction > (
118
111
LAST_USED_QUERY_ACTION_KEY ,
119
112
) ;
120
- const [ monacoHotKey , setMonacoHotKey ] = React . useState < ValueOf <
121
- typeof MONACO_HOT_KEY_ACTIONS
122
- > | null > ( null ) ;
123
113
124
114
const [ sendExecuteQuery , executeQueryResult ] = executeQueryApi . useExecuteQueryMutation ( ) ;
125
115
const [ sendExplainQuery , explainQueryResult ] = explainQueryApi . useExplainQueryMutation ( ) ;
@@ -138,27 +128,6 @@ function QueryEditor(props: QueryEditorProps) {
138
128
initialTenantCommonInfoState ,
139
129
) ;
140
130
141
- const editorRef = React . useRef < Monaco . editor . IStandaloneCodeEditor > ( ) ;
142
-
143
- React . useEffect ( ( ) => {
144
- const updateEditor = ( ) => {
145
- if ( editorRef . current ) {
146
- editorRef . current . layout ( ) ;
147
- }
148
- } ;
149
-
150
- const onChangeWindow = throttle ( ( ) => {
151
- updateEditor ( ) ;
152
- } , 100 ) ;
153
-
154
- updateEditor ( ) ;
155
-
156
- window . addEventListener ( 'resize' , onChangeWindow ) ;
157
- return ( ) => {
158
- window . removeEventListener ( 'resize' , onChangeWindow ) ;
159
- } ;
160
- } , [ ] ) ;
161
-
162
131
React . useEffect ( ( ) => {
163
132
dispatchResultVisibilityState ( PaneVisibilityActionTypes . triggerCollapse ) ;
164
133
} , [ ] ) ;
@@ -171,83 +140,51 @@ function QueryEditor(props: QueryEditorProps) {
171
140
}
172
141
} , [ props . showPreview , isResultLoaded ] ) ;
173
142
174
- React . useEffect ( ( ) => {
175
- const { input, history} = executeQuery ;
143
+ const getLastQueryText = useEventHandler ( ( ) => {
144
+ const { history} = executeQuery ;
145
+ return history . queries [ history . queries . length - 1 ] ?. queryText || '' ;
146
+ } ) ;
176
147
177
- const hasUnsavedInput = input
178
- ? input !== history . queries [ history . queries . length - 1 ] ?. queryText
179
- : false ;
180
-
181
- if ( hasUnsavedInput ) {
182
- window . onbeforeunload = ( e ) => {
183
- e . preventDefault ( ) ;
184
- // Chrome requires returnValue to be set
185
- e . returnValue = '' ;
186
- } ;
187
- } else {
188
- window . onbeforeunload = null ;
189
- }
190
- return ( ) => {
191
- window . onbeforeunload = null ;
192
- } ;
193
- } , [ executeQuery ] ) ;
148
+ const handleSendExecuteClick = useEventHandler ( ( text ?: string ) => {
149
+ const { input, history} = executeQuery ;
194
150
195
- const handleSendExecuteClick = React . useCallback (
196
- ( text ?: string ) => {
197
- const { input, history} = executeQuery ;
151
+ const schema = useMultiSchema ? 'multi' : 'modern' ;
198
152
199
- const schema = useMultiSchema ? 'multi' : 'modern' ;
153
+ const query = text && typeof text === 'string' ? text : input ;
200
154
201
- const query = text && typeof text === 'string' ? text : input ;
155
+ setLastUsedQueryAction ( QUERY_ACTIONS . execute ) ;
156
+ if ( ! isEqual ( lastQueryExecutionSettings , querySettings ) ) {
157
+ resetBanner ( ) ;
158
+ setLastQueryExecutionSettings ( querySettings ) ;
159
+ }
202
160
203
- setLastUsedQueryAction ( QUERY_ACTIONS . execute ) ;
204
- if ( ! isEqual ( lastQueryExecutionSettings , querySettings ) ) {
205
- resetBanner ( ) ;
206
- setLastQueryExecutionSettings ( querySettings ) ;
207
- }
161
+ setResultType ( RESULT_TYPES . EXECUTE ) ;
162
+ sendExecuteQuery ( {
163
+ query,
164
+ database : tenantName ,
165
+ querySettings,
166
+ schema,
167
+ enableTracingLevel,
168
+ } ) ;
169
+ setIsResultLoaded ( true ) ;
170
+ props . setShowPreview ( false ) ;
208
171
209
- setResultType ( RESULT_TYPES . EXECUTE ) ;
210
- sendExecuteQuery ( {
211
- query,
212
- database : tenantName ,
213
- querySettings,
214
- schema,
215
- enableTracingLevel,
216
- } ) ;
217
- setIsResultLoaded ( true ) ;
218
- setShowPreview ( false ) ;
219
-
220
- // Don't save partial queries in history
221
- if ( ! text ) {
222
- const { queries, currentIndex} = history ;
223
- if ( query !== queries [ currentIndex ] ?. queryText ) {
224
- saveQueryToHistory ( input ) ;
225
- }
172
+ // Don't save partial queries in history
173
+ if ( ! text ) {
174
+ const { queries, currentIndex} = history ;
175
+ if ( query !== queries [ currentIndex ] ?. queryText ) {
176
+ props . saveQueryToHistory ( input ) ;
226
177
}
227
- dispatchResultVisibilityState ( PaneVisibilityActionTypes . triggerExpand ) ;
228
- } ,
229
- [
230
- executeQuery ,
231
- enableTracingLevel ,
232
- useMultiSchema ,
233
- setLastUsedQueryAction ,
234
- lastQueryExecutionSettings ,
235
- querySettings ,
236
- sendExecuteQuery ,
237
- saveQueryToHistory ,
238
- setShowPreview ,
239
- tenantName ,
240
- resetBanner ,
241
- setLastQueryExecutionSettings ,
242
- ] ,
243
- ) ;
178
+ }
179
+ dispatchResultVisibilityState ( PaneVisibilityActionTypes . triggerExpand ) ;
180
+ } ) ;
244
181
245
182
const handleSettingsClick = ( ) => {
246
- setQueryAction ( 'settings' ) ;
183
+ props . setQueryAction ( 'settings' ) ;
247
184
props . setShowPreview ( false ) ;
248
185
} ;
249
186
250
- const handleGetExplainQueryClick = React . useCallback ( ( ) => {
187
+ const handleGetExplainQueryClick = useEventHandler ( ( ) => {
251
188
const { input} = executeQuery ;
252
189
253
190
setLastUsedQueryAction ( QUERY_ACTIONS . explain ) ;
@@ -265,56 +202,22 @@ function QueryEditor(props: QueryEditorProps) {
265
202
enableTracingLevel,
266
203
} ) ;
267
204
setIsResultLoaded ( true ) ;
268
- setShowPreview ( false ) ;
205
+ props . setShowPreview ( false ) ;
269
206
dispatchResultVisibilityState ( PaneVisibilityActionTypes . triggerExpand ) ;
270
- } , [
271
- executeQuery ,
272
- lastQueryExecutionSettings ,
273
- querySettings ,
274
- resetBanner ,
275
- enableTracingLevel ,
276
- sendExplainQuery ,
277
- setLastQueryExecutionSettings ,
278
- setLastUsedQueryAction ,
279
- setShowPreview ,
280
- tenantName ,
281
- ] ) ;
207
+ } ) ;
282
208
283
- React . useEffect ( ( ) => {
284
- if ( monacoHotKey === null ) {
285
- return ;
286
- }
287
- setMonacoHotKey ( null ) ;
288
- switch ( monacoHotKey ) {
289
- case MONACO_HOT_KEY_ACTIONS . sendQuery : {
290
- if ( lastUsedQueryAction === QUERY_ACTIONS . explain ) {
291
- handleGetExplainQueryClick ( ) ;
292
- } else {
293
- handleSendExecuteClick ( ) ;
294
- }
295
- break ;
296
- }
297
- case MONACO_HOT_KEY_ACTIONS . sendSelectedQuery : {
298
- const selection = editorRef . current ?. getSelection ( ) ;
299
- const model = editorRef . current ?. getModel ( ) ;
300
- if ( selection && model ) {
301
- const text = model . getValueInRange ( {
302
- startLineNumber : selection . getSelectionStart ( ) . lineNumber ,
303
- startColumn : selection . getSelectionStart ( ) . column ,
304
- endLineNumber : selection . getPosition ( ) . lineNumber ,
305
- endColumn : selection . getPosition ( ) . column ,
306
- } ) ;
307
- handleSendExecuteClick ( text ) ;
308
- }
309
- break ;
310
- }
209
+ const handleSendQuery = useEventHandler ( ( ) => {
210
+ if ( lastUsedQueryAction === QUERY_ACTIONS . explain ) {
211
+ handleGetExplainQueryClick ( ) ;
212
+ } else {
213
+ handleSendExecuteClick ( ) ;
311
214
}
312
- // eslint-disable-next-line react-hooks/exhaustive-deps
313
- } , [ monacoHotKey , handleSendExecuteClick , handleGetExplainQueryClick ] ) ;
215
+ } ) ;
314
216
315
217
const editorDidMount = ( editor : Monaco . editor . IStandaloneCodeEditor , monaco : typeof Monaco ) => {
316
218
const keybindings = getKeyBindings ( monaco ) ;
317
- editorRef . current = editor ;
219
+ initResizeHandler ( editor ) ;
220
+ initUserPrompt ( editor , getLastQueryText ) ;
318
221
editor . focus ( ) ;
319
222
editor . addAction ( {
320
223
id : 'sendQuery' ,
@@ -328,7 +231,7 @@ function QueryEditor(props: QueryEditorProps) {
328
231
contextMenuOrder : 1 ,
329
232
// Method that will be executed when the action is triggered.
330
233
// @param editor The editor instance is passed in as a convenience
331
- run : ( ) => setMonacoHotKey ( MONACO_HOT_KEY_ACTIONS . sendQuery ) ,
234
+ run : ( ) => handleSendQuery ( ) ,
332
235
} ) ;
333
236
334
237
const canSendSelectedText = editor . createContextKey < boolean > ( 'canSendSelectedText' , false ) ;
@@ -346,7 +249,19 @@ function QueryEditor(props: QueryEditorProps) {
346
249
precondition : 'canSendSelectedText' ,
347
250
contextMenuGroupId : CONTEXT_MENU_GROUP_ID ,
348
251
contextMenuOrder : 1 ,
349
- run : ( ) => setMonacoHotKey ( MONACO_HOT_KEY_ACTIONS . sendSelectedQuery ) ,
252
+ run : ( e ) => {
253
+ const selection = e . getSelection ( ) ;
254
+ const model = e . getModel ( ) ;
255
+ if ( selection && model ) {
256
+ const text = model . getValueInRange ( {
257
+ startLineNumber : selection . getSelectionStart ( ) . lineNumber ,
258
+ startColumn : selection . getSelectionStart ( ) . column ,
259
+ endLineNumber : selection . getPosition ( ) . lineNumber ,
260
+ endColumn : selection . getPosition ( ) . column ,
261
+ } ) ;
262
+ handleSendExecuteClick ( text ) ;
263
+ }
264
+ } ,
350
265
} ) ;
351
266
352
267
editor . addAction ( {
@@ -374,7 +289,7 @@ function QueryEditor(props: QueryEditorProps) {
374
289
label : i18n ( 'action.save-query' ) ,
375
290
keybindings : [ keybindings . saveQuery ] ,
376
291
run : ( ) => {
377
- setQueryAction ( 'save' ) ;
292
+ props . setQueryAction ( 'save' ) ;
378
293
} ,
379
294
} ) ;
380
295
} ;
@@ -554,3 +469,40 @@ function Result({
554
469
555
470
return null ;
556
471
}
472
+
473
+ function initResizeHandler ( editor : Monaco . editor . IStandaloneCodeEditor ) {
474
+ const layoutEditor = throttle ( ( ) => {
475
+ editor . layout ( ) ;
476
+ } , 100 ) ;
477
+
478
+ editor . layout ( ) ;
479
+
480
+ window . addEventListener ( 'resize' , layoutEditor ) ;
481
+ editor . onDidDispose ( ( ) => {
482
+ window . removeEventListener ( 'resize' , layoutEditor ) ;
483
+ } ) ;
484
+ }
485
+
486
+ function initUserPrompt ( editor : Monaco . editor . IStandaloneCodeEditor , getInitialText : ( ) => string ) {
487
+ setUserPrompt ( editor . getValue ( ) , getInitialText ( ) ) ;
488
+ editor . onDidChangeModelContent ( ( ) => {
489
+ setUserPrompt ( editor . getValue ( ) , getInitialText ( ) ) ;
490
+ } ) ;
491
+ editor . onDidDispose ( ( ) => {
492
+ window . onbeforeunload = null ;
493
+ } ) ;
494
+ }
495
+
496
+ function setUserPrompt ( text : string , initialText : string ) {
497
+ const hasUnsavedInput = text ? text !== initialText : false ;
498
+
499
+ if ( hasUnsavedInput ) {
500
+ window . onbeforeunload = ( e ) => {
501
+ e . preventDefault ( ) ;
502
+ // Chrome requires returnValue to be set
503
+ e . returnValue = '' ;
504
+ } ;
505
+ } else {
506
+ window . onbeforeunload = null ;
507
+ }
508
+ }
0 commit comments