diff --git a/packages/web-console/src/scenes/Editor/Monaco/index.tsx b/packages/web-console/src/scenes/Editor/Monaco/index.tsx index 6e15f15af..fc709a259 100644 --- a/packages/web-console/src/scenes/Editor/Monaco/index.tsx +++ b/packages/web-console/src/scenes/Editor/Monaco/index.tsx @@ -1,23 +1,23 @@ -import React, { useContext, useEffect, useRef, useState } from "react" import type { BaseSyntheticEvent } from "react" -import Editor, { Monaco, loader } from "@monaco-editor/react" +import React, { useContext, useEffect, useRef, useState } from "react" +import Editor, { loader, Monaco } from "@monaco-editor/react" import dracula from "./dracula" -import { editor } from "monaco-editor" import type { IDisposable, IRange } from "monaco-editor" +import { editor } from "monaco-editor" import { theme } from "../../../theme" import { QuestContext, useEditor } from "../../../providers" +import type { Request } from "./utils" import { appendQuery, + clearModelMarkers, + findMatches, getErrorRange, + getQueryFromCursor, getQueryRequestFromEditor, getQueryRequestFromLastExecutedQuery, QuestDBLanguageName, setErrorMarker, - clearModelMarkers, - getQueryFromCursor, - findMatches, } from "./utils" -import type { Request } from "./utils" import { registerEditorActions, registerLanguageAddons } from "./editor-addons" import { registerLegacyEventBusEvents } from "./legacy-event-bus" import { PaneContent, Text } from "../../../components" @@ -67,11 +67,11 @@ const Content = styled(PaneContent)` cursor: pointer; &:after { - content: "◃"; - font-size: 1.6rem; - font-weight: 600; - transform: rotate(180deg) scaleX(0.8); - color: ${color("green")}; + display: block; + content: ""; + background-image: url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIGhlaWdodD0iMThweCIgd2lkdGg9IjE4cHgiIGFyaWEtaGlkZGVuPSJ0cnVlIiBmb2N1c2FibGU9ImZhbHNlIiBmaWxsPSIjNTBmYTdiIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJTdHlsZWRJY29uQmFzZS1zYy1lYTl1bGotMCBrZkRiTmwiPjxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0wIDBoMjR2MjRIMHoiPjwvcGF0aD48cGF0aCBkPSJNMTYuMzk0IDEyIDEwIDcuNzM3djguNTI2TDE2LjM5NCAxMnptMi45ODIuNDE2TDguNzc3IDE5LjQ4MkEuNS41IDAgMCAxIDggMTkuMDY2VjQuOTM0YS41LjUgMCAwIDEgLjc3Ny0uNDE2bDEwLjU5OSA3LjA2NmEuNS41IDAgMCAxIDAgLjgzMnoiPjwvcGF0aD48L3N2Zz4K"); + width: 18px; + height: 18px; } } @@ -86,6 +86,8 @@ const Content = styled(PaneContent)` } ` +const DEFAULT_LINE_CHARS = 5 + const MonacoEditor = () => { const editorContext = useEditor() const { @@ -110,6 +112,13 @@ const MonacoEditor = () => { const errorRef = useRef() const errorRangeRef = useRef() + // Set the initial line number width in chars based on the number of lines in the active buffer + const [lineNumbersMinChars, setLineNumbersMinChars] = useState( + DEFAULT_LINE_CHARS + + activeBuffer.value.split("\n").length.toString().length - + 1, + ) + const toggleRunning = (isRefresh: boolean = false) => { dispatch(actions.query.toggleRunning(isRefresh)) } @@ -120,6 +129,17 @@ const MonacoEditor = () => { monaco.editor.defineTheme("dracula", dracula) } + // To ensure the fixed position of the "run query" glyph we adjust the width of the line count element. + // This width is represented in char numbers. + const setLineCharsWidth = () => { + const lineCount = editorRef.current?.getModel()?.getLineCount() + if (lineCount) { + setLineNumbersMinChars( + DEFAULT_LINE_CHARS + (lineCount.toString().length - 1), + ) + } + } + const handleEditorClick = (e: BaseSyntheticEvent) => { if (e.target.classList.contains("cursorQueryGlyph")) { editorRef?.current?.focus() @@ -201,7 +221,6 @@ const MonacoEditor = () => { editor.setModel( monaco.editor.createModel(activeBuffer.value, QuestDBLanguageName), ) - setEditorReady(true) editorReadyTrigger(editor) @@ -216,6 +235,14 @@ const MonacoEditor = () => { }) editor.onDidChangeCursorPosition(() => { + // To ensure the fixed position of the "run query" glyph we adjust the width of the line count element. + // This width is represented in char numbers. + const lineCount = editorRef.current?.getModel()?.getLineCount() + if (lineCount) { + setLineNumbersMinChars( + DEFAULT_LINE_CHARS + (lineCount.toString().length - 1), + ) + } renderLineMarkings(monaco, editor) }) @@ -403,6 +430,7 @@ const MonacoEditor = () => { selectOnLineNumbers: false, scrollBeyondLastLine: false, tabSize: 2, + lineNumbersMinChars: lineNumbersMinChars, }} theme="vs-dark" /> diff --git a/packages/web-console/src/scenes/Editor/Monaco/questdb-sql/createSchemaCompletionProvider.ts b/packages/web-console/src/scenes/Editor/Monaco/questdb-sql/createSchemaCompletionProvider.ts index fdfb0db68..6ff612869 100644 --- a/packages/web-console/src/scenes/Editor/Monaco/questdb-sql/createSchemaCompletionProvider.ts +++ b/packages/web-console/src/scenes/Editor/Monaco/questdb-sql/createSchemaCompletionProvider.ts @@ -8,6 +8,10 @@ import { getTableCompletions } from "./getTableCompletions" import { getColumnCompletions } from "./getColumnCompletions" import { getLanguageCompletions } from "./getLanguageCompletions" +const trimQuotesFromTableName = (tableName: string) => { + return tableName.replace(/(^")|("$)/g, "") +} + export const createSchemaCompletionProvider = ( editor: IStandaloneCodeEditor, tables: Table[] = [], @@ -44,6 +48,8 @@ export const createSchemaCompletionProvider = ( tableContext.push(joinMatch[2]) } + tableContext = tableContext.map(trimQuotesFromTableName) + const textUntilPosition = model.getValueInRange({ startLineNumber: cursorMatch?.range.startLineNumber ?? 1, startColumn: cursorMatch?.range.startColumn ?? 1, @@ -86,11 +92,21 @@ export const createSchemaCompletionProvider = ( } } + // get text value in the current line + const textInLine = model.getValueInRange({ + startLineNumber: position.lineNumber, + startColumn: 1, + endLineNumber: position.lineNumber, + endColumn: position.column, + }) + // check if `textInLine` contains whitespaces only + const isWhitespaceOnly = /^\s*$/.test(textInLine) + if ( /(?:(SELECT|UPDATE).*?(?:(?:,(?:COLUMN )?)|(?:ALTER COLUMN ))?(?:WHERE )?(?: BY )?(?: ON )?(?: SET )?$|ALTER COLUMN )/gim.test( textUntilPosition, ) && - position.column !== 1 + !isWhitespaceOnly ) { if (tableContext.length > 0) { const withTableName =