1
1
import React from 'react' ;
2
2
3
- import NiceModal from '@ebay/nice-modal-react' ;
4
3
import { isEqual } from 'lodash' ;
5
- import throttle from 'lodash/throttle' ;
6
- import type Monaco from 'monaco-editor' ;
7
4
import { v4 as uuidv4 } from 'uuid' ;
8
5
9
- import { MonacoEditor } from '../../../../components/MonacoEditor/MonacoEditor' ;
10
6
import SplitPane from '../../../../components/SplitPane' ;
11
7
import { useTracingLevelOptionAvailable } from '../../../../store/reducers/capabilities/hooks' ;
12
8
import {
13
- goToNextQuery ,
14
- goToPreviousQuery ,
15
9
queryApi ,
16
10
saveQueryToHistory ,
17
11
selectQueriesHistory ,
18
12
selectQueriesHistoryCurrentIndex ,
19
13
selectResult ,
20
14
selectTenantPath ,
21
- selectUserInput ,
22
15
setTenantPath ,
23
16
} from '../../../../store/reducers/query/query' ;
24
17
import type { QueryResult } from '../../../../store/reducers/query/types' ;
@@ -41,8 +34,6 @@ import {
41
34
} from '../../../../utils/hooks' ;
42
35
import { useChangedQuerySettings } from '../../../../utils/hooks/useChangedQuerySettings' ;
43
36
import { useLastQueryExecutionSettings } from '../../../../utils/hooks/useLastQueryExecutionSettings' ;
44
- import { YQL_LANGUAGE_ID } from '../../../../utils/monaco/constats' ;
45
- import { useUpdateErrorsHighlighting } from '../../../../utils/monaco/highlightErrors' ;
46
37
import { QUERY_ACTIONS } from '../../../../utils/query' ;
47
38
import type { InitialPaneState } from '../../utils/paneVisibilityToggleHelpers' ;
48
39
import {
@@ -53,16 +44,11 @@ import {Preview} from '../Preview/Preview';
53
44
import { QueryEditorControls } from '../QueryEditorControls/QueryEditorControls' ;
54
45
import { QueryResultViewer } from '../QueryResult/QueryResultViewer' ;
55
46
import { QuerySettingsDialog } from '../QuerySettingsDialog/QuerySettingsDialog' ;
56
- import { SAVE_QUERY_DIALOG } from '../SaveQuery/SaveQuery' ;
57
- import i18n from '../i18n' ;
58
47
59
- import { useEditorOptions } from './helpers' ;
60
- import { getKeyBindings } from './keybindings' ;
48
+ import { YqlEditor } from './YqlEditor' ;
61
49
62
50
import './QueryEditor.scss' ;
63
51
64
- const CONTEXT_MENU_GROUP_ID = 'navigation' ;
65
-
66
52
const b = cn ( 'query-editor' ) ;
67
53
68
54
const initialTenantCommonInfoState = {
@@ -80,18 +66,14 @@ interface QueryEditorProps {
80
66
}
81
67
82
68
export default function QueryEditor ( props : QueryEditorProps ) {
83
- const editorOptions = useEditorOptions ( ) ;
84
69
const dispatch = useTypedDispatch ( ) ;
85
70
const { tenantName, path, type, theme, changeUserInput} = props ;
86
71
const savedPath = useTypedSelector ( selectTenantPath ) ;
87
72
const result = useTypedSelector ( selectResult ) ;
88
73
const historyQueries = useTypedSelector ( selectQueriesHistory ) ;
89
74
const historyCurrentIndex = useTypedSelector ( selectQueriesHistoryCurrentIndex ) ;
90
- const input = useTypedSelector ( selectUserInput ) ;
91
75
const showPreview = useTypedSelector ( selectShowPreview ) ;
92
76
93
- const updateErrorsHighlighting = useUpdateErrorsHighlighting ( ) ;
94
-
95
77
const isResultLoaded = Boolean ( result ) ;
96
78
97
79
const [ querySettings ] = useQueryExecutionSettings ( ) ;
@@ -130,18 +112,9 @@ export default function QueryEditor(props: QueryEditorProps) {
130
112
}
131
113
} , [ showPreview , isResultLoaded ] ) ;
132
114
133
- const getLastQueryText = useEventHandler ( ( ) => {
134
- if ( ! historyQueries || historyQueries . length === 0 ) {
135
- return '' ;
136
- }
137
- return historyQueries [ historyQueries . length - 1 ] . queryText ;
138
- } ) ;
139
-
140
- const handleSendExecuteClick = useEventHandler ( ( text ?: string ) => {
141
- const query = text ?? input ;
142
-
115
+ const handleSendExecuteClick = useEventHandler ( ( text : string , partial ?: boolean ) => {
143
116
setLastUsedQueryAction ( QUERY_ACTIONS . execute ) ;
144
- setLastExecutedQueryText ( query ) ;
117
+ setLastExecutedQueryText ( text ) ;
145
118
if ( ! isEqual ( lastQueryExecutionSettings , querySettings ) ) {
146
119
resetBanner ( ) ;
147
120
setLastQueryExecutionSettings ( querySettings ) ;
@@ -150,7 +123,7 @@ export default function QueryEditor(props: QueryEditorProps) {
150
123
151
124
sendQuery ( {
152
125
actionType : 'execute' ,
153
- query,
126
+ query : text ,
154
127
database : tenantName ,
155
128
querySettings,
156
129
enableTracingLevel,
@@ -160,9 +133,9 @@ export default function QueryEditor(props: QueryEditorProps) {
160
133
dispatch ( setShowPreview ( false ) ) ;
161
134
162
135
// Don't save partial queries in history
163
- if ( ! text ) {
164
- if ( query !== historyQueries [ historyCurrentIndex ] ?. queryText ) {
165
- dispatch ( saveQueryToHistory ( { queryText : input , queryId} ) ) ;
136
+ if ( ! partial ) {
137
+ if ( text !== historyQueries [ historyCurrentIndex ] ?. queryText ) {
138
+ dispatch ( saveQueryToHistory ( { queryText : text , queryId} ) ) ;
166
139
}
167
140
}
168
141
dispatchResultVisibilityState ( PaneVisibilityActionTypes . triggerExpand ) ;
@@ -172,9 +145,9 @@ export default function QueryEditor(props: QueryEditorProps) {
172
145
dispatch ( setQueryAction ( 'settings' ) ) ;
173
146
} ;
174
147
175
- const handleGetExplainQueryClick = useEventHandler ( ( ) => {
148
+ const handleGetExplainQueryClick = useEventHandler ( ( text : string ) => {
176
149
setLastUsedQueryAction ( QUERY_ACTIONS . explain ) ;
177
- setLastExecutedQueryText ( input ) ;
150
+ setLastExecutedQueryText ( text ) ;
178
151
if ( ! isEqual ( lastQueryExecutionSettings , querySettings ) ) {
179
152
resetBanner ( ) ;
180
153
setLastQueryExecutionSettings ( querySettings ) ;
@@ -184,7 +157,7 @@ export default function QueryEditor(props: QueryEditorProps) {
184
157
185
158
sendQuery ( {
186
159
actionType : 'explain' ,
187
- query : input ,
160
+ query : text ,
188
161
database : tenantName ,
189
162
querySettings,
190
163
enableTracingLevel,
@@ -196,113 +169,6 @@ export default function QueryEditor(props: QueryEditorProps) {
196
169
dispatchResultVisibilityState ( PaneVisibilityActionTypes . triggerExpand ) ;
197
170
} ) ;
198
171
199
- const handleSendQuery = useEventHandler ( ( ) => {
200
- if ( lastUsedQueryAction === QUERY_ACTIONS . explain ) {
201
- handleGetExplainQueryClick ( ) ;
202
- } else {
203
- handleSendExecuteClick ( ) ;
204
- }
205
- } ) ;
206
-
207
- const editorWillUnmount = ( ) => {
208
- window . ydbEditor = undefined ;
209
- } ;
210
-
211
- const editorDidMount = ( editor : Monaco . editor . IStandaloneCodeEditor , monaco : typeof Monaco ) => {
212
- window . ydbEditor = editor ;
213
- const keybindings = getKeyBindings ( monaco ) ;
214
- monaco . editor . registerCommand ( 'insertSnippetToEditor' , ( _asessor , input : string ) => {
215
- //suggestController is not properly typed yet in monaco-editor package
216
- const contribution = editor . getContribution < any > ( 'snippetController2' ) ;
217
- if ( contribution ) {
218
- editor . focus ( ) ;
219
- editor . setValue ( '' ) ;
220
- contribution . insert ( input ) ;
221
- }
222
- } ) ;
223
- initResizeHandler ( editor ) ;
224
- initUserPrompt ( editor , getLastQueryText ) ;
225
- editor . focus ( ) ;
226
- editor . addAction ( {
227
- id : 'sendQuery' ,
228
- label : i18n ( 'action.send-query' ) ,
229
- keybindings : [ keybindings . sendQuery ] ,
230
- // A precondition for this action.
231
- precondition : undefined ,
232
- // A rule to evaluate on top of the precondition in order to dispatch the keybindings.
233
- keybindingContext : undefined ,
234
- contextMenuGroupId : CONTEXT_MENU_GROUP_ID ,
235
- contextMenuOrder : 1 ,
236
- // Method that will be executed when the action is triggered.
237
- // @param editor The editor instance is passed in as a convenience
238
- run : ( ) => handleSendQuery ( ) ,
239
- } ) ;
240
-
241
- const canSendSelectedText = editor . createContextKey < boolean > ( 'canSendSelectedText' , false ) ;
242
- editor . onDidChangeCursorSelection ( ( { selection, secondarySelections} ) => {
243
- const notEmpty =
244
- selection . selectionStartLineNumber !== selection . positionLineNumber ||
245
- selection . selectionStartColumn !== selection . positionColumn ;
246
- const hasMultipleSelections = secondarySelections . length > 0 ;
247
- canSendSelectedText . set ( notEmpty && ! hasMultipleSelections ) ;
248
- } ) ;
249
- editor . addAction ( {
250
- id : 'sendSelectedQuery' ,
251
- label : i18n ( 'action.send-selected-query' ) ,
252
- keybindings : [ keybindings . sendSelectedQuery ] ,
253
- precondition : 'canSendSelectedText' ,
254
- contextMenuGroupId : CONTEXT_MENU_GROUP_ID ,
255
- contextMenuOrder : 1 ,
256
- run : ( e ) => {
257
- const selection = e . getSelection ( ) ;
258
- const model = e . getModel ( ) ;
259
- if ( selection && model ) {
260
- const text = model . getValueInRange ( {
261
- startLineNumber : selection . getSelectionStart ( ) . lineNumber ,
262
- startColumn : selection . getSelectionStart ( ) . column ,
263
- endLineNumber : selection . getPosition ( ) . lineNumber ,
264
- endColumn : selection . getPosition ( ) . column ,
265
- } ) ;
266
- handleSendExecuteClick ( text ) ;
267
- }
268
- } ,
269
- } ) ;
270
-
271
- editor . addAction ( {
272
- id : 'previous-query' ,
273
- label : i18n ( 'action.previous-query' ) ,
274
- keybindings : [ keybindings . selectPreviousQuery ] ,
275
- contextMenuGroupId : CONTEXT_MENU_GROUP_ID ,
276
- contextMenuOrder : 2 ,
277
- run : ( ) => {
278
- dispatch ( goToPreviousQuery ( ) ) ;
279
- } ,
280
- } ) ;
281
- editor . addAction ( {
282
- id : 'next-query' ,
283
- label : i18n ( 'action.next-query' ) ,
284
- keybindings : [ keybindings . selectNextQuery ] ,
285
- contextMenuGroupId : CONTEXT_MENU_GROUP_ID ,
286
- contextMenuOrder : 3 ,
287
- run : ( ) => {
288
- dispatch ( goToNextQuery ( ) ) ;
289
- } ,
290
- } ) ;
291
- editor . addAction ( {
292
- id : 'save-query' ,
293
- label : i18n ( 'action.save-query' ) ,
294
- keybindings : [ keybindings . saveQuery ] ,
295
- run : ( ) => {
296
- NiceModal . show ( SAVE_QUERY_DIALOG ) ;
297
- } ,
298
- } ) ;
299
- } ;
300
-
301
- const onChange = ( newValue : string ) => {
302
- updateErrorsHighlighting ( ) ;
303
- changeUserInput ( { input : newValue } ) ;
304
- } ;
305
-
306
172
const onCollapseResultHandler = ( ) => {
307
173
dispatchResultVisibilityState ( PaneVisibilityActionTypes . triggerCollapse ) ;
308
174
} ;
@@ -321,7 +187,6 @@ export default function QueryEditor(props: QueryEditorProps) {
321
187
onSettingsButtonClick = { handleSettingsClick }
322
188
isLoading = { Boolean ( result ?. isLoading ) }
323
189
handleGetExplainQueryClick = { handleGetExplainQueryClick }
324
- disabled = { ! input }
325
190
highlightedAction = { lastUsedQueryAction }
326
191
/>
327
192
) ;
@@ -345,14 +210,11 @@ export default function QueryEditor(props: QueryEditorProps) {
345
210
>
346
211
< div className = { b ( 'monaco-wrapper' ) } >
347
212
< div className = { b ( 'monaco' ) } >
348
- < MonacoEditor
349
- language = { YQL_LANGUAGE_ID }
350
- value = { input }
351
- options = { editorOptions }
352
- onChange = { onChange }
353
- editorDidMount = { editorDidMount }
354
- theme = { `vs-${ theme } ` }
355
- editorWillUnmount = { editorWillUnmount }
213
+ < YqlEditor
214
+ changeUserInput = { changeUserInput }
215
+ theme = { theme }
216
+ handleSendExecuteClick = { handleSendExecuteClick }
217
+ handleGetExplainQueryClick = { handleGetExplainQueryClick }
356
218
/>
357
219
</ div >
358
220
</ div >
@@ -424,40 +286,3 @@ function Result({
424
286
425
287
return null ;
426
288
}
427
-
428
- function initResizeHandler ( editor : Monaco . editor . IStandaloneCodeEditor ) {
429
- const layoutEditor = throttle ( ( ) => {
430
- editor . layout ( ) ;
431
- } , 100 ) ;
432
-
433
- editor . layout ( ) ;
434
-
435
- window . addEventListener ( 'resize' , layoutEditor ) ;
436
- editor . onDidDispose ( ( ) => {
437
- window . removeEventListener ( 'resize' , layoutEditor ) ;
438
- } ) ;
439
- }
440
-
441
- function initUserPrompt ( editor : Monaco . editor . IStandaloneCodeEditor , getInitialText : ( ) => string ) {
442
- setUserPrompt ( editor . getValue ( ) , getInitialText ( ) ) ;
443
- editor . onDidChangeModelContent ( ( ) => {
444
- setUserPrompt ( editor . getValue ( ) , getInitialText ( ) ) ;
445
- } ) ;
446
- editor . onDidDispose ( ( ) => {
447
- window . onbeforeunload = null ;
448
- } ) ;
449
- }
450
-
451
- function setUserPrompt ( text : string , initialText : string ) {
452
- const hasUnsavedInput = text ? text !== initialText : false ;
453
-
454
- if ( hasUnsavedInput ) {
455
- window . onbeforeunload = ( e ) => {
456
- e . preventDefault ( ) ;
457
- // Chrome requires returnValue to be set
458
- e . returnValue = '' ;
459
- } ;
460
- } else {
461
- window . onbeforeunload = null ;
462
- }
463
- }
0 commit comments