mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
Use CodeEditor in AIEditor (#47297)
## Context More clean up / housekeeping - to use `CodeEditor` in `AIEditor` and remove duplicated logic <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Expanded supported editor file types, including CSS, CSV, and JavaScript (with improved syntax highlighting). * The updated editor experience now provides a readily available “run query” action. * **UI Improvements** * Tightened editor panel spacing and adjusted padding for a cleaner layout. * **Bug Fixes** * Improved file-to-language detection so files open with the correct syntax highlighting more consistently. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
1 parent
5cb81123ae
commit
f6afd8b2e4
4 files changed
+38
-52
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import Editor, { Monaco, OnMount } from '@monaco-editor/react'
|
||||
import { Monaco, OnMount } from '@monaco-editor/react'
|
||||
import { AnimatePresence, motion } from 'framer-motion'
|
||||
import type { editor as monacoEditor } from 'monaco-editor'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
@@ -6,18 +6,20 @@ import { toast } from 'sonner'
|
||||
import { KeyboardShortcut } from 'ui'
|
||||
import { useSetCommandMenuOpen } from 'ui-patterns'
|
||||
|
||||
import { CodeEditor, type ValidLanguages } from '../CodeEditor/CodeEditor'
|
||||
import { DiffEditor } from '../DiffEditor'
|
||||
import ResizableAIWidget from './ResizableAIWidget'
|
||||
import { getEditorSelectionParts } from './utils'
|
||||
import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider'
|
||||
import { constructHeaders } from '@/data/fetchers'
|
||||
import { useLatest } from '@/hooks/misc/useLatest'
|
||||
import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
|
||||
import { useIsShortcutEnabled } from '@/state/shortcuts/useIsShortcutEnabled'
|
||||
import { useSidebarManagerSnapshot } from '@/state/sidebar-manager-state'
|
||||
|
||||
interface AIEditorProps {
|
||||
id?: string
|
||||
language?: string
|
||||
language: ValidLanguages
|
||||
value?: string
|
||||
defaultValue?: string
|
||||
aiEndpoint?: string
|
||||
@@ -71,14 +73,9 @@ export const AIEditor = ({
|
||||
const isCommandMenuHotkeyEnabled = useIsShortcutEnabled(SHORTCUT_IDS.COMMAND_MENU_OPEN)
|
||||
const setCommandMenuOpen = useSetCommandMenuOpen()
|
||||
|
||||
const executeQueryRef = useRef(executeQuery)
|
||||
executeQueryRef.current = executeQuery
|
||||
|
||||
const commandMenuHotkeyEnabledRef = useRef(isCommandMenuHotkeyEnabled)
|
||||
commandMenuHotkeyEnabledRef.current = isCommandMenuHotkeyEnabled
|
||||
|
||||
const setCommandMenuOpenRef = useRef(setCommandMenuOpen)
|
||||
setCommandMenuOpenRef.current = setCommandMenuOpen
|
||||
const executeQueryRef = useLatest(executeQuery)
|
||||
const commandMenuHotkeyEnabledRef = useLatest(isCommandMenuHotkeyEnabled)
|
||||
const setCommandMenuOpenRef = useLatest(setCommandMenuOpen)
|
||||
|
||||
const [currentValue, setCurrentValue] = useState(value || defaultValue)
|
||||
const [isDiffMode, setIsDiffMode] = useState(false)
|
||||
@@ -237,17 +234,6 @@ export const AIEditor = ({
|
||||
})
|
||||
}
|
||||
|
||||
if (!!executeQueryRef.current) {
|
||||
editor.addAction({
|
||||
id: 'run-query',
|
||||
label: 'Run Query',
|
||||
keybindings: [monaco.KeyMod.CtrlCmd + monaco.KeyCode.Enter],
|
||||
contextMenuGroupId: 'operation',
|
||||
contextMenuOrder: 0,
|
||||
run: () => executeQueryRef.current?.(),
|
||||
})
|
||||
}
|
||||
|
||||
refreshCloseAction()
|
||||
|
||||
// Add AI Assistant toggle keybinding (Cmd+I)
|
||||
@@ -281,11 +267,6 @@ export const AIEditor = ({
|
||||
setCommandMenuOpenRef.current(true)
|
||||
}
|
||||
})
|
||||
|
||||
if (autoFocus) {
|
||||
if (editor.getValue().length === 1) editor.setPosition({ lineNumber: 1, column: 2 })
|
||||
editor.focus()
|
||||
}
|
||||
}
|
||||
|
||||
const handlePrompt = async (
|
||||
@@ -325,19 +306,6 @@ export const AIEditor = ({
|
||||
}
|
||||
}
|
||||
|
||||
const defaultOptions: monacoEditor.IStandaloneEditorConstructionOptions = {
|
||||
tabSize: 2,
|
||||
fontSize: 13,
|
||||
readOnly,
|
||||
minimap: { enabled: false },
|
||||
wordWrap: 'on',
|
||||
lineNumbers: 'on',
|
||||
folding: false,
|
||||
padding: { top: 4 },
|
||||
lineNumbersMinChars: 3,
|
||||
...options,
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setCurrentValue(value || defaultValue)
|
||||
}, [value, defaultValue])
|
||||
@@ -414,19 +382,20 @@ export const AIEditor = ({
|
||||
</div>
|
||||
) : (
|
||||
<div className="w-full h-full relative">
|
||||
{/* [Joshen] Refactor: Use CodeEditor.tsx instead, reduce duplicate declaration of Editor */}
|
||||
<Editor
|
||||
theme="supabase"
|
||||
<CodeEditor
|
||||
language={language}
|
||||
autofocus={autoFocus}
|
||||
className={className}
|
||||
isReadOnly={readOnly}
|
||||
options={options}
|
||||
value={currentValue}
|
||||
options={defaultOptions}
|
||||
onChange={(value: string | undefined) => {
|
||||
onInputChange={(value) => {
|
||||
const newValue = value || ''
|
||||
setCurrentValue(newValue)
|
||||
onChange?.(newValue)
|
||||
}}
|
||||
onMount={handleEditorOnMount}
|
||||
className={className}
|
||||
actions={{ runQuery: { enabled: true, callback: () => executeQueryRef.current?.() } }}
|
||||
/>
|
||||
{promptState.isOpen && editorRef.current && (
|
||||
<ResizableAIWidget
|
||||
|
||||
@@ -22,9 +22,20 @@ const DEFAULT_ACTIONS = {
|
||||
placeholderFill: { enabled: true },
|
||||
}
|
||||
|
||||
export type ValidLanguages =
|
||||
| 'pgsql'
|
||||
| 'json'
|
||||
| 'html'
|
||||
| 'typescript'
|
||||
| 'javascript'
|
||||
| 'css'
|
||||
| 'csv'
|
||||
| 'plaintext'
|
||||
| 'markdown'
|
||||
|
||||
interface CodeEditorProps {
|
||||
id?: string
|
||||
language: 'pgsql' | 'json' | 'html' | 'typescript' | 'plaintext' | 'markdown'
|
||||
language: ValidLanguages
|
||||
autofocus?: boolean
|
||||
defaultValue?: string
|
||||
isReadOnly?: boolean
|
||||
|
||||
@@ -507,7 +507,7 @@ export const EditorPanel = () => {
|
||||
wordWrap: 'on',
|
||||
lineNumbers: 'on',
|
||||
folding: false,
|
||||
padding: { top: 16 },
|
||||
padding: { top: 12 },
|
||||
lineNumbersMinChars: 3,
|
||||
}}
|
||||
executeQuery={onExecuteSql}
|
||||
@@ -516,7 +516,6 @@ export const EditorPanel = () => {
|
||||
openAIAssistantShortcutEnabled={isAIAssistantHotkeyEnabled}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{error !== undefined && (
|
||||
<div className="shrink-0">
|
||||
<Admonition
|
||||
@@ -539,7 +538,6 @@ export const EditorPanel = () => {
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showWarning && (
|
||||
<SqlWarningAdmonition
|
||||
className="border-t"
|
||||
@@ -557,7 +555,6 @@ export const EditorPanel = () => {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{results !== undefined && results.length > 0 && (
|
||||
<div
|
||||
className={cn(
|
||||
@@ -593,7 +590,6 @@ export const EditorPanel = () => {
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="relative shrink-0 flex items-center gap-2 justify-end px-5 py-4 w-full border-t">
|
||||
{(isUpserting || saveStatus !== 'idle') && (
|
||||
<div
|
||||
|
||||
@@ -38,7 +38,17 @@ export const isBinaryFile = (fileName: string): boolean => {
|
||||
return binaryExtensions.includes(extension || '')
|
||||
}
|
||||
|
||||
export const getLanguageFromFileName = (fileName: string): string => {
|
||||
type EditorLanguage =
|
||||
| 'typescript'
|
||||
| 'javascript'
|
||||
| 'json'
|
||||
| 'html'
|
||||
| 'css'
|
||||
| 'markdown'
|
||||
| 'csv'
|
||||
| 'plaintext'
|
||||
|
||||
export const getLanguageFromFileName = (fileName: string): EditorLanguage => {
|
||||
const extension = fileName.split('.').pop()?.toLowerCase()
|
||||
switch (extension) {
|
||||
case 'ts':
|
||||
|
||||
Reference in new issue
Block a user