11import React from 'react' ;
22
3- import NiceModal from '@ebay/nice-modal-react' ;
43import { isEqual } from 'lodash' ;
5- import throttle from 'lodash/throttle' ;
6- import type Monaco from 'monaco-editor' ;
74import { v4 as uuidv4 } from 'uuid' ;
85
9- import { MonacoEditor } from '../../../../components/MonacoEditor/MonacoEditor' ;
106import SplitPane from '../../../../components/SplitPane' ;
117import { useTracingLevelOptionAvailable } from '../../../../store/reducers/capabilities/hooks' ;
128import {
13- goToNextQuery ,
14- goToPreviousQuery ,
159 queryApi ,
1610 saveQueryToHistory ,
1711 selectQueriesHistory ,
1812 selectQueriesHistoryCurrentIndex ,
1913 selectResult ,
2014 selectTenantPath ,
21- selectUserInput ,
2215 setTenantPath ,
2316} from '../../../../store/reducers/query/query' ;
2417import type { QueryResult } from '../../../../store/reducers/query/types' ;
@@ -41,8 +34,6 @@ import {
4134} from '../../../../utils/hooks' ;
4235import { useChangedQuerySettings } from '../../../../utils/hooks/useChangedQuerySettings' ;
4336import { useLastQueryExecutionSettings } from '../../../../utils/hooks/useLastQueryExecutionSettings' ;
44- import { YQL_LANGUAGE_ID } from '../../../../utils/monaco/constats' ;
45- import { useUpdateErrorsHighlighting } from '../../../../utils/monaco/highlightErrors' ;
4637import { QUERY_ACTIONS } from '../../../../utils/query' ;
4738import type { InitialPaneState } from '../../utils/paneVisibilityToggleHelpers' ;
4839import {
@@ -53,16 +44,11 @@ import {Preview} from '../Preview/Preview';
5344import { QueryEditorControls } from '../QueryEditorControls/QueryEditorControls' ;
5445import { QueryResultViewer } from '../QueryResult/QueryResultViewer' ;
5546import { QuerySettingsDialog } from '../QuerySettingsDialog/QuerySettingsDialog' ;
56- import { SAVE_QUERY_DIALOG } from '../SaveQuery/SaveQuery' ;
57- import i18n from '../i18n' ;
5847
59- import { useEditorOptions } from './helpers' ;
60- import { getKeyBindings } from './keybindings' ;
48+ import { YqlEditor } from './YqlEditor' ;
6149
6250import './QueryEditor.scss' ;
6351
64- const CONTEXT_MENU_GROUP_ID = 'navigation' ;
65-
6652const b = cn ( 'query-editor' ) ;
6753
6854const initialTenantCommonInfoState = {
@@ -80,18 +66,14 @@ interface QueryEditorProps {
8066}
8167
8268export default function QueryEditor ( props : QueryEditorProps ) {
83- const editorOptions = useEditorOptions ( ) ;
8469 const dispatch = useTypedDispatch ( ) ;
8570 const { tenantName, path, type, theme, changeUserInput} = props ;
8671 const savedPath = useTypedSelector ( selectTenantPath ) ;
8772 const result = useTypedSelector ( selectResult ) ;
8873 const historyQueries = useTypedSelector ( selectQueriesHistory ) ;
8974 const historyCurrentIndex = useTypedSelector ( selectQueriesHistoryCurrentIndex ) ;
90- const input = useTypedSelector ( selectUserInput ) ;
9175 const showPreview = useTypedSelector ( selectShowPreview ) ;
9276
93- const updateErrorsHighlighting = useUpdateErrorsHighlighting ( ) ;
94-
9577 const isResultLoaded = Boolean ( result ) ;
9678
9779 const [ querySettings ] = useQueryExecutionSettings ( ) ;
@@ -130,18 +112,9 @@ export default function QueryEditor(props: QueryEditorProps) {
130112 }
131113 } , [ showPreview , isResultLoaded ] ) ;
132114
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 ) => {
143116 setLastUsedQueryAction ( QUERY_ACTIONS . execute ) ;
144- setLastExecutedQueryText ( query ) ;
117+ setLastExecutedQueryText ( text ) ;
145118 if ( ! isEqual ( lastQueryExecutionSettings , querySettings ) ) {
146119 resetBanner ( ) ;
147120 setLastQueryExecutionSettings ( querySettings ) ;
@@ -150,7 +123,7 @@ export default function QueryEditor(props: QueryEditorProps) {
150123
151124 sendQuery ( {
152125 actionType : 'execute' ,
153- query,
126+ query : text ,
154127 database : tenantName ,
155128 querySettings,
156129 enableTracingLevel,
@@ -160,9 +133,9 @@ export default function QueryEditor(props: QueryEditorProps) {
160133 dispatch ( setShowPreview ( false ) ) ;
161134
162135 // 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} ) ) ;
166139 }
167140 }
168141 dispatchResultVisibilityState ( PaneVisibilityActionTypes . triggerExpand ) ;
@@ -172,9 +145,9 @@ export default function QueryEditor(props: QueryEditorProps) {
172145 dispatch ( setQueryAction ( 'settings' ) ) ;
173146 } ;
174147
175- const handleGetExplainQueryClick = useEventHandler ( ( ) => {
148+ const handleGetExplainQueryClick = useEventHandler ( ( text : string ) => {
176149 setLastUsedQueryAction ( QUERY_ACTIONS . explain ) ;
177- setLastExecutedQueryText ( input ) ;
150+ setLastExecutedQueryText ( text ) ;
178151 if ( ! isEqual ( lastQueryExecutionSettings , querySettings ) ) {
179152 resetBanner ( ) ;
180153 setLastQueryExecutionSettings ( querySettings ) ;
@@ -184,7 +157,7 @@ export default function QueryEditor(props: QueryEditorProps) {
184157
185158 sendQuery ( {
186159 actionType : 'explain' ,
187- query : input ,
160+ query : text ,
188161 database : tenantName ,
189162 querySettings,
190163 enableTracingLevel,
@@ -196,113 +169,6 @@ export default function QueryEditor(props: QueryEditorProps) {
196169 dispatchResultVisibilityState ( PaneVisibilityActionTypes . triggerExpand ) ;
197170 } ) ;
198171
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-
306172 const onCollapseResultHandler = ( ) => {
307173 dispatchResultVisibilityState ( PaneVisibilityActionTypes . triggerCollapse ) ;
308174 } ;
@@ -321,7 +187,6 @@ export default function QueryEditor(props: QueryEditorProps) {
321187 onSettingsButtonClick = { handleSettingsClick }
322188 isLoading = { Boolean ( result ?. isLoading ) }
323189 handleGetExplainQueryClick = { handleGetExplainQueryClick }
324- disabled = { ! input }
325190 highlightedAction = { lastUsedQueryAction }
326191 />
327192 ) ;
@@ -345,14 +210,11 @@ export default function QueryEditor(props: QueryEditorProps) {
345210 >
346211 < div className = { b ( 'monaco-wrapper' ) } >
347212 < 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 }
356218 />
357219 </ div >
358220 </ div >
@@ -424,40 +286,3 @@ function Result({
424286
425287 return null ;
426288}
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