Skip to content

Conversation

davemarco
Copy link
Contributor

@davemarco davemarco commented Aug 20, 2025

Description

PR does a few things.

  1. Adds a disabled theme, and disables pointer events on editor when query in progress.
  2. Exposes focus method to parent editor component, to focus editor on page load and query termination. This was much more complicated than antd input, but overall it does work. Part of issue is that you can't call focus, until after the editor loads which is not when it is rendered
  3. I removed autocomplete, the behaviour is a bit strange with enter, and the dialect is slightly off from presto

Checklist

  • The PR satisfies the contribution guidelines.
  • This is a breaking change and that has been indicated in the PR title, OR this isn't a
    breaking change.
  • Necessary docs have been updated, OR no docs need to be updated.

Validation performed

Focuses correctly. Theme changes during query.

Summary by CodeRabbit

  • New Features

    • SQL editor auto-focuses when ready in applicable states.
    • Editor is temporarily disabled during running queries and displays a disabled theme.
    • Editor exposes a public focus API so parent screens can programmatically focus it.
  • Chores

    • Added a new colour utility dependency to support UI updates.
    • Cleaned up editor integrations, removed legacy completion/dynamic sizing, and reduced loaded editor contributions.

Copy link
Contributor

coderabbitai bot commented Aug 20, 2025

Walkthrough

Added a color dependency; introduced an imperative SqlEditorRef with focus and onEditorReady hook; added disabled theme and pointer-events blocking; removed several Monaco contributions and a custom SQL typings file; wired editor readiness and disabled state into Presto SqlQueryInput.

Changes

Cohort / File(s) Summary of changes
Client dependency
components/webui/client/package.json
Added dependency: color ^5.0.0.
SqlEditor component
components/webui/client/src/components/SqlEditor/index.tsx
Added SqlEditorRef type and export; exposed ref via useImperativeHandle to provide focus(); added disabled prop and onEditorReady callback; created and applied disabled-theme; block pointer events when disabled; replaced mount handling with handleEditorDidMount; removed SQL keyword completion provider and dynamic height/folding logic.
Monaco loader contributions
components/webui/client/src/components/SqlEditor/monaco-loader.ts
Removed several Monaco contribution imports (clipboard, contextmenu, findController, wordHighlighter, suggestController, placeholderText.contribution). SQL language import retained.
Removed SQL typings
components/webui/client/src/components/SqlEditor/monaco-sql.d.ts
Deleted custom module declaration and SqlLanguageDefinition interface and language export for the Monaco SQL file.
Presto SQL input integration
components/webui/client/src/pages/SearchPage/SearchControls/Presto/SqlQueryInput/index.tsx
Added editor ref and isEditorReady state; wired handleEditorReady; auto-focus when ready for UI states DEFAULT/DONE/FAILED; disable editor when UI state is QUERY_ID_PENDING or QUERYING; forward onChange and onEditorReady to SqlEditor.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Page as SearchPage.SqlQueryInput
  participant Editor as SqlEditor
  participant Monaco as Monaco Editor

  Note over Page,Editor: Render with props (disabled by UI state, onEditorReady, ref)
  Page->>Editor: render SqlEditor(disabled, onEditorReady, ref)
  Editor->>Monaco: create editor instance (mount)
  Monaco-->>Editor: editor mounted
  Editor->>Page: call onEditorReady()
  Editor->>Page: expose ref.focus()

  alt Page decides to focus
    Page->>Page: if isEditorReady && UI state ∈ {DEFAULT,DONE,FAILED}
    Page->>Editor: ref.focus()
  end

  Note over Editor,Monaco: Disabled handling
  Editor->>Monaco: setTheme(disabled-theme or light)
  Editor-->>Page: pointer-events blocked when disabled
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • junhaoliao

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@davemarco davemarco requested a review from hoophalab August 20, 2025 18:36
@davemarco davemarco marked this pull request as ready for review August 21, 2025 13:35
@davemarco davemarco requested a review from a team as a code owner August 21, 2025 13:35
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
components/webui/client/src/components/SqlEditor/index.tsx (1)

85-102: Make the “Current” suggestion reliably first; mark list complete.

Comment says “make current input the first suggestion,” but it’s appended, so sorting is undefined. Use sortText and preselect to ensure it’s first, and return incomplete: false to avoid re-queries.

-                const suggestions = sqlLanguage.keywords.map((keyword: string) => ({
+                const suggestions = sqlLanguage.keywords.map((keyword: string) => ({
                     detail: "Presto SQL (CLP)",
                     insertText: `${keyword} `,
                     kind: monacoEditor.languages.CompletionItemKind.Keyword,
                     label: keyword,
                     range: range,
+                    sortText: "1",
                 }));
@@
-                // we make the current input the first suggestion. Users can then use arrow keys
+                // we explicitly make the current input the first suggestion. Users can then use arrow keys
                 // to select a keyword if needed.
@@
-                    suggestions.push({
+                    suggestions.unshift({
                         detail: "Current",
                         insertText: `${typedWord}\n`,
-                        kind: monaco.languages.CompletionItemKind.Text,
+                        kind: monacoEditor.languages.CompletionItemKind.Text,
                         label: typedWord,
                         range: range,
+                        sortText: "0",
+                        preselect: true,
                     });
                 }
@@
-                return {
-                    suggestions: suggestions,
-                    incomplete: true,
-                };
+                return {
+                    suggestions,
+                    incomplete: false,
+                };
@@
             triggerCharacters: [
                 " ",
             ],

Note: also switched the kind reference to the same Monaco instance for consistency.

Also applies to: 103-117, 119-122, 124-127

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3c45e12 and 205f29f.

⛔ Files ignored due to path filters (1)
  • components/webui/client/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • components/webui/client/package.json (1 hunks)
  • components/webui/client/src/components/SqlEditor/index.tsx (4 hunks)
  • components/webui/client/src/pages/SearchPage/SearchControls/Presto/SqlQueryInput/index.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}

⚙️ CodeRabbit configuration file

  • Prefer false == <expression> rather than !<expression>.

Files:

  • components/webui/client/src/pages/SearchPage/SearchControls/Presto/SqlQueryInput/index.tsx
  • components/webui/client/src/components/SqlEditor/index.tsx
🧬 Code graph analysis (1)
components/webui/client/src/pages/SearchPage/SearchControls/Presto/SqlQueryInput/index.tsx (2)
components/webui/client/src/components/SqlEditor/index.tsx (1)
  • SqlEditorRef (174-174)
components/webui/client/src/pages/SearchPage/SearchState/typings.ts (1)
  • SEARCH_UI_STATE (31-31)
🔇 Additional comments (3)
components/webui/client/package.json (1)

29-29: Reevaluate color dependency in SqlEditor

We confirmed that:

  • color@5.0.0 is published as an ESM module (type: "module"), so it will load under Vite/React 19 without transpilation issues.
  • The only usages are in components/webui/client/src/components/SqlEditor/index.tsx at lines 67–68 converting AntD token colours via .hexa().
  • Monaco’s theming API accepts any valid CSS colour string (including hex and rgba()), so you can feed the raw AntD tokens directly without the extra conversion.

Recommendations:

  • Drop the color dependency and use the tokens straight in your theme definition, for example:
    monaco.editor.defineTheme("myTheme", {
      inherit: true,
      rules: [],
      colors: {
        "editor.background": token.colorBgContainerDisabled,
        "editor.foreground": token.colorTextDisabled,
        // …
      },
    });
  • If you still need to normalise RGBA to 8-digit hex, consider a tiny helper function instead of the full color library.
  • If you choose to keep color, you’ve already verified v5’s ESM support and its permissive MIT licence—no further action required.

[optional_refactors_recommended】

components/webui/client/src/components/SqlEditor/index.tsx (1)

124-127: LGTM: removing newline as a trigger is the right call.

This avoids accidental accept-on-Enter surprises while still allowing explicit invocation via space or Ctrl/Cmd+Space.

components/webui/client/src/pages/SearchPage/SearchControls/Presto/SqlQueryInput/index.tsx (1)

52-54: LGTM: height, onChange wiring, and onEditorReady handshake.

This wiring aligns with the new SqlEditor API and the focus-after-ready requirement.

Also applies to: 59-59

Comment on lines 13 to 15
import {theme} from "antd";
import color from "color";
import {language as sqlLanguage} from "monaco-editor/esm/vs/basic-languages/sql/sql.js";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Unify Monaco instance usage and naming.

You both import monaco and use const monacoEditor = useMonaco(). Mixing the two can lead to confusion and hard-to-debug mismatches. Pick one (prefer the useMonaco() instance) and name it monaco or monacoApi to avoid misleading “Editor” terminology.

I can send a follow-up diff to rename monacoEditor -> monaco and remove the top-level import * as monaco if you want.

Also applies to: 41-43, 85-87, 113-114

🤖 Prompt for AI Agents
In components/webui/client/src/components/SqlEditor/index.tsx around lines 13-15
(and also apply changes at 41-43, 85-87, 113-114), the file mixes a top-level
monaco import with the useMonaco() hook variable named monacoEditor which is
confusing; remove the top-level import of monaco, rename the hook variable
monacoEditor to monaco (or monacoApi) across the file, and update all references
to use this single instance so the component consistently uses the useMonaco()
instance and avoids misleading “Editor” naming.

Comment on lines 57 to 77
// Define disabled theme for monaco editor
useEffect(() => {
if (null === monacoEditor) {
return;
}
monacoEditor.editor.defineTheme("disabled-theme", {
base: "vs",
inherit: true,
rules: [],
colors: {
"editor.background": color(token.colorBgContainerDisabled).hexa(),
"editor.foreground": color(token.colorTextDisabled).hexa(),

// transparent
"focusBorder": "#00000000",
},
});
}, [
monacoEditor,
token
]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Avoid the color lib if tokens are already valid CSS; Monaco accepts rgba().

If token.colorBgContainerDisabled and token.colorTextDisabled are valid CSS colour strings (often hex or rgba), you can pass them directly. This would let you remove the color dependency.

-                "editor.background": color(token.colorBgContainerDisabled).hexa(),
-                "editor.foreground": color(token.colorTextDisabled).hexa(),
+                "editor.background": token.colorBgContainerDisabled,
+                "editor.foreground": token.colorTextDisabled,

If you’ve seen cases where tokens are in non-standard formats, keep the dependency and ignore this comment.

Also applies to: 67-69

🤖 Prompt for AI Agents
components/webui/client/src/components/SqlEditor/index.tsx around lines 57 to 77
(and specifically lines 67-69): the code wraps token.colorBgContainerDisabled
and token.colorTextDisabled with the external color(...) library to call
.hexa(), but Monaco accepts standard CSS color strings (hex, rgba) directly; if
these token values are already valid CSS colors, remove the color(...) wrapper
and pass token.colorBgContainerDisabled and token.colorTextDisabled directly to
the theme colors, and then remove the unused import of the color library; if
tokens can be nonstandard, leave the wrapper and add a short defensive comment
explaining why it’s required.

Copy link
Contributor

@hoophalab hoophalab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me. I made a few nitpicking changes.

  1. I vaguely remember taht we wanted the regular fontSize.
  2. How about making the height dynamic instead of having the component user specify it?
  3. I've removed the white space on the left by setting folding: false.
@@ -40,6 +43,7 @@ const SqlEditor = (props: SqlEditorProps) => {
     const editorRef = useRef<monaco.editor.IStandaloneCodeEditor>(null);
     const monacoEditor = useMonaco();
     const {token} = theme.useToken();
+    const [lineHeight, setLineHeight] = useState<Nullable<number>>(null);
 
     useImperativeHandle(ref, () => ({
         focus: () => {
@@ -52,6 +56,8 @@ const SqlEditor = (props: SqlEditorProps) => {
     ) => {
         editorRef.current = editor;
         onEditorReady?.();
+
+        setLineHeight(editor.getOption(monaco.editor.EditorOption.lineHeight))
     }, [onEditorReady]);
 
     // Define disabled theme for monaco editor
@@ -71,6 +77,7 @@ const SqlEditor = (props: SqlEditorProps) => {
                 "focusBorder": "#00000000",
             },
         });
+
     }, [
         monacoEditor,
         token
@@ -140,6 +147,7 @@ const SqlEditor = (props: SqlEditorProps) => {
             }
         >
             <Editor
+                height={null === lineHeight ? "" : 5*lineHeight}
                 language={"sql"}
                 loading={
                     <div
@@ -151,9 +159,8 @@ const SqlEditor = (props: SqlEditorProps) => {
                 }
                 options={{
                     automaticLayout: true,
-                    fontSize: 20,
-                    lineHeight: 30,
                     lineNumbers: "off",
+                    folding: false,
                     minimap: {enabled: false},
                     overviewRulerBorder: false,
                     placeholder: "Enter your SQL query",

@davemarco davemarco changed the title feat(webui): Add disabled state/theme to SQL editor; Focus SQL editor on page load and query termination. feat(webui): Add disabled state/theme to SQL editor; Focus SQL editor on page load and query termination. Remove autocomplete. Aug 25, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (8)
components/webui/client/src/components/SqlEditor/index.tsx (6)

1-6: Critical: ref forwarding is broken; focus() is never exposed to parents

Function components don’t receive a ref prop. Without forwardRef, useImperativeHandle(ref, …) is a no-op and the public focus() API won’t work. This blocks the PR’s focus-on-load/termination objective. Fix by wrapping the component with forwardRef and removing React.RefAttributes from props.

Apply this diff:

@@
-import {
-    useCallback,
-    useEffect,
-    useImperativeHandle,
-    useRef,
-} from "react";
+import {
+    forwardRef,
+    useCallback,
+    useEffect,
+    useImperativeHandle,
+    useRef,
+} from "react";
@@
-type SqlEditorProps = Omit<EditorProps, "language"> & React.RefAttributes<SqlEditorRef> & {
+type SqlEditorProps = Omit<EditorProps, "language"> & {
     disabled: boolean;
     /** Callback when the editor is mounted and ref is ready to use. */
     onEditorReady?: () => void;
 };
@@
-const SqlEditor = (props: SqlEditorProps) => {
-    const {ref, disabled, onEditorReady, ...editorProps} = props;
+const SqlEditor = forwardRef<SqlEditorRef, SqlEditorProps>((props, ref) => {
+    const {disabled, onEditorReady, ...editorProps} = props;
     const editorRef = useRef<monaco.editor.IStandaloneCodeEditor>(null);
@@
-    useImperativeHandle(ref, () => ({
+    useImperativeHandle(ref, () => ({
         focus: () => {
             editorRef.current?.focus();
         },
     }), []);
@@
-    return (
+    return (
         <div
             style={
                 disabled ?
                     {pointerEvents: "none"} :
                     {}
             }
         >
             <Editor
                 onMount={handleEditorDidMount}
                 {...editorProps}/>
         </div>
-    );
-};
+    );
+});

Also applies to: 24-29, 37-48


8-16: Unify Monaco usage: remove runtime import, use type-only import, and rename hook variable

You mix a direct monaco import with useMonaco(). Keep one runtime source (prefer useMonaco()), and import types only to avoid bundle bloat. Also rename monacoEditor to monaco (or monacoApi) for clarity.

Apply this diff:

@@
-import {theme} from "antd";
-import color from "color";
-import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";
+import {theme} from "antd";
+import color from "color";
+import type * as Monaco from "monaco-editor";
@@
-    const editorRef = useRef<monaco.editor.IStandaloneCodeEditor>(null);
-    const monacoEditor = useMonaco();
+    const editorRef = useRef<Monaco.editor.IStandaloneCodeEditor>(null);
+    const monaco = useMonaco();
@@
-    useEffect(() => {
-        if (null === monacoEditor) {
+    useEffect(() => {
+        if (null === monaco) {
             return;
         }
-        monacoEditor.editor.defineTheme("disabled-theme", {
+        monaco.editor.defineTheme("disabled-theme", {
             base: "vs",
             inherit: true,
             rules: [],
             colors: {
                 "editor.background": color(token.colorBgContainerDisabled).hexa(),
                 "editor.foreground": color(token.colorTextDisabled).hexa(),
                 // transparent
                 "focusBorder": "#00000000",
             },
         });
-    }, [
-        monacoEditor,
-        token
-    ]);
+    }, [monaco, token]);

If you’d rather avoid using the same identifier for the hook variable, rename to monacoApi consistently.

Also applies to: 40-41, 56-76


108-110: Use Monaco’s canonical light theme id (vs)

Monaco’s built-in light theme id is vs. Some wrappers alias "light", some don’t. Use vs to avoid surprises.

Apply this diff:

-                theme={disabled ?
-                    "disabled-theme" :
-                    "light"}
+                theme={disabled ? "disabled-theme" : "vs"}

79-85: A11y: add aria-disabled to convey the disabled state semantically

Pointer-events and visuals aren’t sufficient for assistive tech. Add aria-disabled={disabled} to the wrapper.

Apply this diff:

-        <div
+        <div
+            aria-disabled={disabled}
             style={
                 disabled ?
                     {pointerEvents: "none"} :
                     {}
             }
         >

96-107: Make the editor truly non-editable when disabled

If the editor already has focus, keyboard input can still modify content despite pointer-events: "none". Set Monaco’s readOnly (and optionally domReadOnly) based on disabled.

Apply this diff:

                 options={{
                     automaticLayout: true,
                     folding: false,
                     fontSize: 16,
                     lineNumbers: "off",
                     minimap: {enabled: false},
                     overviewRulerBorder: false,
                     placeholder: "Enter your SQL query",
                     renderLineHighlightOnlyWhenFocus: true,
                     scrollBeyondLastLine: false,
                     wordWrap: "on",
+                    readOnly: disabled,
+                    // If your Monaco version supports it, also:
+                    // domReadOnly: disabled,
                 }}

66-67: Consider removing the color dependency if tokens are already valid CSS

Monaco accepts standard CSS colours (hex/rgba). If your Ant Design tokens are already valid CSS strings, pass them directly and drop the color lib.

Apply this diff:

-                "editor.background": color(token.colorBgContainerDisabled).hexa(),
-                "editor.foreground": color(token.colorTextDisabled).hexa(),
+                "editor.background": token.colorBgContainerDisabled,
+                "editor.foreground": token.colorTextDisabled,

And, if fully removed:

-import color from "color";

Retain color if your tokens can be non-standard; otherwise, this simplifies the bundle.

Also applies to: 14-14

components/webui/client/src/pages/SearchPage/SearchControls/Presto/SqlQueryInput/index.tsx (2)

35-47: Tidy focus effect: compute a boolean and early-return

Condense the condition into a shouldFocus boolean for readability and maintainability.

Apply this diff:

     useEffect(() => {
-        if (
-            isEditorReady &&
-            (searchUiState === SEARCH_UI_STATE.DEFAULT ||
-            searchUiState === SEARCH_UI_STATE.DONE ||
-            searchUiState === SEARCH_UI_STATE.FAILED)
-        ) {
-            editorRef.current?.focus();
-        }
+        const shouldFocus =
+            isEditorReady &&
+            (searchUiState === SEARCH_UI_STATE.DEFAULT ||
+             searchUiState === SEARCH_UI_STATE.DONE ||
+             searchUiState === SEARCH_UI_STATE.FAILED);
+        if (false == shouldFocus) { return; }
+        editorRef.current?.focus();
     }, [
         searchUiState,
         isEditorReady
     ]);

52-59: Extract isQuerying to centralize the disabled condition

Keeps the intent clear and the state check in one place.

Apply this diff:

-            <SqlEditor
+            <SqlEditor
                 height={"120px"}
                 ref={editorRef}
-                disabled={
-                    searchUiState === SEARCH_UI_STATE.QUERY_ID_PENDING ||
-                    searchUiState === SEARCH_UI_STATE.QUERYING
-                }
+                disabled={(() => {
+                    const isQuerying =
+                        searchUiState === SEARCH_UI_STATE.QUERY_ID_PENDING ||
+                        searchUiState === SEARCH_UI_STATE.QUERYING;
+                    return isQuerying;
+                })()}
                 onChange={handleChange}
                 onEditorReady={handleEditorReady}/>

Alternatively, define above JSX:

const isQuerying =
    searchUiState === SEARCH_UI_STATE.QUERY_ID_PENDING ||
    searchUiState === SEARCH_UI_STATE.QUERYING;

Then pass disabled={isQuerying}.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 205f29f and 066e389.

📒 Files selected for processing (2)
  • components/webui/client/src/components/SqlEditor/index.tsx (1 hunks)
  • components/webui/client/src/pages/SearchPage/SearchControls/Presto/SqlQueryInput/index.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}

⚙️ CodeRabbit configuration file

  • Prefer false == <expression> rather than !<expression>.

Files:

  • components/webui/client/src/pages/SearchPage/SearchControls/Presto/SqlQueryInput/index.tsx
  • components/webui/client/src/components/SqlEditor/index.tsx
🧬 Code graph analysis (1)
components/webui/client/src/pages/SearchPage/SearchControls/Presto/SqlQueryInput/index.tsx (2)
components/webui/client/src/components/SqlEditor/index.tsx (1)
  • SqlEditorRef (118-118)
components/webui/client/src/pages/SearchPage/SearchState/typings.ts (1)
  • SEARCH_UI_STATE (31-31)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: lint-check (macos-15)

@davemarco
Copy link
Contributor Author

I vaguely remember taht we wanted the regular fontSize.

I tested with regular and compromised to 16px from 20px. Now it is the same as run button

How about making the height dynamic instead of having the component user specify it?

The code just looked a bit confusing. I lowered size to 120px.

I've removed the white space on the left by setting folding: false.

sure this looks great

Note i also removed the auto complete stuff. It was a bit annoying, and was slightly innacurate. maybe we will add back later with a better design

@davemarco davemarco requested a review from hoophalab August 25, 2025 21:26
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (11)
components/webui/client/src/pages/SearchPage/SearchControls/Presto/SqlQueryInput/index.tsx (3)

22-24: Focus ref won’t work until SqlEditor forwards the ref (blocker in child).

editorRef.current?.focus() depends on the child exposing an imperative focus() via forwardRef. The current SqlEditor implementation does not forward the ref, so this ref will remain null and focus calls will be a no‑op. See my blocking comment in SqlEditor/index.tsx with a concrete fix.

Run to verify the child has proper ref forwarding:

#!/bin/bash
set -euo pipefail
rg -nP 'forwardRef<\s*SqlEditorRef' components/webui/client/src/components/SqlEditor/index.tsx || { echo "Missing forwardRef<SqlEditorRef>"; exit 1; }
rg -n 'useImperativeHandle\(' components/webui/client/src/components/SqlEditor/index.tsx || { echo "Missing useImperativeHandle(ref, …)"; exit 1; }

35-47: Nit: compute shouldFocus once and early-return for clarity.

This reduces nesting and duplication of the condition.

     useEffect(() => {
-        if (
-            isEditorReady &&
-            (searchUiState === SEARCH_UI_STATE.DEFAULT ||
-            searchUiState === SEARCH_UI_STATE.DONE ||
-            searchUiState === SEARCH_UI_STATE.FAILED)
-        ) {
-            editorRef.current?.focus();
-        }
+        const shouldFocus =
+            isEditorReady &&
+            (searchUiState === SEARCH_UI_STATE.DEFAULT ||
+             searchUiState === SEARCH_UI_STATE.DONE ||
+             searchUiState === SEARCH_UI_STATE.FAILED);
+        if (false == shouldFocus) { return; }
+        editorRef.current?.focus();
     }, [
         searchUiState,
         isEditorReady,
     ]);

55-57: Nit: extract an isQuerying boolean and reuse.

Keeps the disabled condition in one place and reads better in JSX.

-                disabled={
-                    searchUiState === SEARCH_UI_STATE.QUERY_ID_PENDING ||
-                    searchUiState === SEARCH_UI_STATE.QUERYING
-                }
+                disabled={(() => {
+                    const isQuerying =
+                        searchUiState === SEARCH_UI_STATE.QUERY_ID_PENDING ||
+                        searchUiState === SEARCH_UI_STATE.QUERYING;
+                    return isQuerying;
+                })()}

Or define const isQuerying = … above and pass disabled={isQuerying}.

components/webui/client/src/components/SqlEditor/index.tsx (8)

1-6: Blocker: missing forwardRef import (required for exposing focus).

You call useImperativeHandle, but without forwardRef wrapping the component, the ref never reaches the function component.

-import {
-    useCallback,
-    useEffect,
-    useImperativeHandle,
-    useRef,
-} from "react";
+import {
+    forwardRef,
+    useCallback,
+    useEffect,
+    useImperativeHandle,
+    useRef,
+} from "react";

24-29: Ref types belong on forwardRef, not in props.

Including React.RefAttributes<SqlEditorRef> in props implies the ref is passed as a prop, which is not how React refs work for function components. Remove it and rely on forwardRef’s generic instead.

-type SqlEditorProps = Omit<EditorProps, "language"> & React.RefAttributes<SqlEditorRef> & {
+type SqlEditorProps = Omit<EditorProps, "language"> & {
     disabled: boolean;
     /** Callback when the editor is mounted and ref is ready to use. */
     onEditorReady?: () => void;
 };

37-47: Critical: ref is read from props; focus() will never be exposed.

Function components don’t receive ref via props. Wrap with forwardRef and use the forwarded ref when calling useImperativeHandle.

-const SqlEditor = (props: SqlEditorProps) => {
-    const {ref, disabled, onEditorReady, ...editorProps} = props;
+const SqlEditor = forwardRef<SqlEditorRef, SqlEditorProps>((props, ref) => {
+    const {disabled, onEditorReady, ...editorProps} = props;
     const editorRef = useRef<monaco.editor.IStandaloneCodeEditor>(null);
     const monacoEditor = useMonaco();
     const {token} = theme.useToken();
 
-    useImperativeHandle(ref, () => ({
+    useImperativeHandle(ref, () => ({
         focus: () => {
             editorRef.current?.focus();
         },
     }), []);

Remember to close the component with }); at the bottom.


78-86: A11y: advertise disabled state semantically.

Add aria-disabled={disabled} on the wrapper so assistive tech can detect the disabled state; visuals and pointer-events alone aren’t sufficient.

-        <div
+        <div
+            aria-disabled={disabled}
             style={
                 disabled ?
                     {pointerEvents: "none"} :
                     {}
             }
         >

96-107: Disabled via CSS still allows keyboard edits; set Monaco readOnly.

If the editor is already focused, pointer-events: none doesn’t stop typing. Add readOnly (and optionally domReadOnly) to harden the disabled state.

                 options={{
                     automaticLayout: true,
                     folding: false,
                     fontSize: 16,
                     lineNumbers: "off",
                     minimap: {enabled: false},
                     overviewRulerBorder: false,
                     placeholder: "Enter your SQL query",
                     renderLineHighlightOnlyWhenFocus: true,
                     scrollBeyondLastLine: false,
                     wordWrap: "on",
+                    readOnly: disabled,
+                    domReadOnly: disabled,
                 }}

108-110: Use Monaco’s canonical light theme id (vs).

"light" isn’t Monaco’s standard id; use "vs" for the default light theme.

-                theme={disabled ?
-                    "disabled-theme" :
-                    "light"}
+                theme={disabled ? "disabled-theme" : "vs"}

61-76: Optional: drop color dependency if tokens are valid CSS colours.

If token.colorBgContainerDisabled/token.colorTextDisabled are already valid CSS strings, pass them directly and remove the color package usage.

-            colors: {
-                "editor.background": color(token.colorBgContainerDisabled).hexa(),
-                "editor.foreground": color(token.colorTextDisabled).hexa(),
+            colors: {
+                "editor.background": token.colorBgContainerDisabled,
+                "editor.foreground": token.colorTextDisabled,

And remove the import if unused:

-import color from "color";

If tokens can be non-standard, keep color(...) and add a short comment explaining why.


15-16: Avoid mixing the top-level monaco import with useMonaco(); unify on one.

Using both sources is confusing. Prefer the instance from useMonaco() for runtime API calls, and import types only for typing.

-import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";
+import type * as Monaco from "monaco-editor";
@@
-    const editorRef = useRef<monaco.editor.IStandaloneCodeEditor>(null);
+    const editorRef = useRef<Monaco.editor.IStandaloneCodeEditor>(null);

Optionally rename monacoEditor to monaco for clarity:

-    const monacoEditor = useMonaco();
+    const monaco = useMonaco();
@@
-        if (null === monacoEditor) {
+        if (null === monaco) {
             return;
         }
-        monacoEditor.editor.defineTheme("disabled-theme", {
+        monaco.editor.defineTheme("disabled-theme", {

Also applies to: 40-40

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 066e389 and a95af1f.

📒 Files selected for processing (4)
  • components/webui/client/src/components/SqlEditor/index.tsx (1 hunks)
  • components/webui/client/src/components/SqlEditor/monaco-loader.ts (0 hunks)
  • components/webui/client/src/components/SqlEditor/monaco-sql.d.ts (0 hunks)
  • components/webui/client/src/pages/SearchPage/SearchControls/Presto/SqlQueryInput/index.tsx (2 hunks)
💤 Files with no reviewable changes (2)
  • components/webui/client/src/components/SqlEditor/monaco-sql.d.ts
  • components/webui/client/src/components/SqlEditor/monaco-loader.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}

⚙️ CodeRabbit configuration file

  • Prefer false == <expression> rather than !<expression>.

Files:

  • components/webui/client/src/pages/SearchPage/SearchControls/Presto/SqlQueryInput/index.tsx
  • components/webui/client/src/components/SqlEditor/index.tsx
🧠 Learnings (1)
📓 Common learnings
Learnt from: davemarco
PR: y-scope/clp#1108
File: components/webui/client/src/components/SqlEditor/monaco-config.ts:6-8
Timestamp: 2025-07-21T14:37:57.648Z
Learning: In Monaco Editor configurations for SQL editing, the import of "monaco-editor/esm/vs/editor/editor.all.js" is required for SQL autocomplete functionality to work properly, even when using "editor.api" and "sql.contribution.js". Removing "editor.all.js" breaks the autocomplete feature.
🧬 Code graph analysis (1)
components/webui/client/src/pages/SearchPage/SearchControls/Presto/SqlQueryInput/index.tsx (2)
components/webui/client/src/components/SqlEditor/index.tsx (1)
  • SqlEditorRef (118-118)
components/webui/client/src/pages/SearchPage/SearchState/typings.ts (1)
  • SEARCH_UI_STATE (31-31)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: lint-check (macos-15)
🔇 Additional comments (2)
components/webui/client/src/pages/SearchPage/SearchControls/Presto/SqlQueryInput/index.tsx (1)

31-33: LGTM: readiness gate is correct.

Calling the focus logic only after the editor signals readiness is the right guard.

components/webui/client/src/components/SqlEditor/index.tsx (1)

49-55: LGTM: onEditorReady dispatch after onMount is correct.

Capturing the editor instance and then invoking the user callback ensures the parent’s isEditorReady state reflects a usable editor.

import color from "color";
import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";

import "./monaco-loader";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Sanity-check: ensure SQL language contributions remain loaded.

Using our retrieved learnings: we previously broke autocomplete when editor.all.js wasn’t imported in the Monaco setup. Since this PR removes some Monaco contributions/custom SQL declarations, please verify the loader still pulls in the required language and completion contributions (or that you explicitly set the options to achieve the same).


🏁 Script executed:

#!/bin/bash
# Look for language contributions and editor.all.js usage
rg -nP 'editor\.all\.js|sql\.contribution|monaco-editor/esm/vs/editor/editor\.all\.js|basic-languages/sql' -S
# Confirm we still use @monaco-editor/react loader
rg -n 'monaco-loader' components/webui/client/src/components/SqlEditor

Length of output: 409


Add missing editor.all.js import in Monaco loader

The loader currently only brings in the SQL contribution, but our previous findings show that without editor.all.js the SQL autocomplete will break. Please update monaco-loader.ts to import the full editor API before the SQL contribution:

• File: components/webui/client/src/components/SqlEditor/monaco-loader.ts

 // ensure the full editor API is loaded first
+import "monaco-editor/esm/vs/editor/editor.all.js";
 // then register SQL language support
 import "monaco-editor/esm/vs/basic-languages/sql/sql.contribution.js";

This will restore the required SQL autocomplete capabilities.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import "./monaco-loader";
// ensure the full editor API is loaded first
import "monaco-editor/esm/vs/editor/editor.all.js";
// then register SQL language support
import "monaco-editor/esm/vs/basic-languages/sql/sql.contribution.js";
🤖 Prompt for AI Agents
In components/webui/client/src/components/SqlEditor/index.tsx around line 17 and
in components/webui/client/src/components/SqlEditor/monaco-loader.ts, the Monaco
loader currently only imports the SQL contribution which causes SQL autocomplete
to break; update monaco-loader.ts to import the full Monaco editor API
(editor.all) before importing the SQL contribution so the complete editor
runtime is available for SQL autocomplete to work correctly. Ensure the editor
all import appears earlier than any vs/language or SQL contribution imports and
keep module resolution consistent with the project’s Monaco import style.

Comment on lines 78 to +86
return (
<Editor
language={"sql"}

// Use white background while loading (default is grey) so transition to editor with
// white background is less jarring.
loading={<div style={{backgroundColor: "white", height: "100%", width: "100%"}}/>}
options={{
automaticLayout: true,
folding: isContentMultiline,
fontSize: 20,
lineHeight: 30,
lineNumbers: isContentMultiline ?
"on" :
"off",
lineNumbersMinChars: 2,
minimap: {enabled: false},
overviewRulerBorder: false,
placeholder: "Enter your SQL query",
renderLineHighlightOnlyWhenFocus: true,
scrollBeyondLastLine: false,
wordWrap: "on",
}}
onMount={handleMonacoMount}
{...props}/>
<div
style={
disabled ?
{pointerEvents: "none"} :
{}
}
>
<Editor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

UX consideration: pointer-events disables scrolling; verify that’s desired.

While querying, users cannot scroll or select text with the mouse. If read-only is sufficient, consider dropping pointerEvents: "none" to keep scrolling/selecting available.

🤖 Prompt for AI Agents
In components/webui/client/src/components/SqlEditor/index.tsx around lines 78 to
86, the current use of style { pointerEvents: "none" } when disabled prevents
scrolling and selection; replace this approach by removing pointerEvents and
instead pass a readOnly (or disabled) prop to the Editor component when
disabled, and if you need to prevent editing but allow selection/scrolling
ensure the wrapper does not set pointerEvents:none and use editor config
(readOnly: true) or CSS (e.g., user-select, overflow) to preserve scrolling and
selection while disabling edits.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a95af1f and e15cb5e.

⛔ Files ignored due to path filters (1)
  • components/webui/client/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (1)
  • components/webui/client/package.json (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: davemarco
PR: y-scope/clp#1108
File: components/webui/client/src/components/SqlEditor/monaco-config.ts:6-8
Timestamp: 2025-07-21T14:37:57.648Z
Learning: In Monaco Editor configurations for SQL editing, the import of "monaco-editor/esm/vs/editor/editor.all.js" is required for SQL autocomplete functionality to work properly, even when using "editor.api" and "sql.contribution.js". Removing "editor.all.js" breaks the autocomplete feature.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: lint-check (macos-15)
🔇 Additional comments (1)
components/webui/client/package.json (1)

29-29: Supply chain hygiene verified for “color” package

Lockfiles are present and committed across the repo, and the “color” dependency metadata aligns with expectations:

  • Lockfiles found at:
    • /components/webui/client/package-lock.json
    • /components/webui/package-lock.json
    • /components/webui/server/package-lock.json
  • “color” version ^5.0.0 corresponds to the latest 5.0.0 release
  • License: MIT; Engines requirement: Node >= 18

No further changes are needed.

Copy link
Contributor

@hoophalab hoophalab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm
The height isn't quite accurate, but let's merge this and address those UI touch-ups in a single pr later.

@hoophalab
Copy link
Contributor

hoophalab commented Aug 25, 2025

how about this title:

feat(webui): Add disabled state and theme to `SqlEditor`; Focus `SqlEditor` on page load and after query termination; Remove autocomplete.

@davemarco davemarco changed the title feat(webui): Add disabled state/theme to SQL editor; Focus SQL editor on page load and query termination. Remove autocomplete. feat(webui): Add disabled state and theme to SqlEditor; Focus SqlEditor on page load and after query termination; Remove autocomplete. Aug 26, 2025
@davemarco
Copy link
Contributor Author

@junhaoliao for approval

Copy link
Member

@kirkrodrigues kirkrodrigues left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deferring to @hoophalab's review & commit message discussed offline.

@hoophalab
Copy link
Contributor

Please hold off on merging this. We need to add a multiline commit message.

@hoophalab hoophalab merged commit 9b4c1c1 into y-scope:main Aug 26, 2025
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants