From 377cb2dc7cf0a5c0e3a05ab7ddab5a517373f66c Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Thu, 29 Feb 2024 08:49:33 -0330 Subject: [PATCH] Add a toggle for intellisense to the sql editor (#21643) * Add a toggle for intellisense to the sql editor * Cleanup * Ensure that we dont load suggestions in browser unless intellisense is enabled * Small fix * Lol spelling --------- Co-authored-by: Joshen Lim --- .../interfaces/SQLEditor/MonacoEditor.tsx | 40 ++++++++- .../SQLEditor/UtilityPanel/FavoriteButton.tsx | 47 +++++++---- .../SQLEditor/UtilityPanel/UtilityActions.tsx | 82 +++++++++++++------ .../SQLEditor/UtilityPanel/UtilityPanel.tsx | 19 ++--- apps/studio/lib/constants/index.ts | 1 + apps/studio/pages/project/[ref]/sql/[id].tsx | 64 ++++++++++----- packages/ui/index.tsx | 2 + .../ui/src/components/shadcn/ui/toggle.tsx | 2 +- 8 files changed, 181 insertions(+), 76 deletions(-) diff --git a/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx b/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx index 28bd9cc7f9f..2dde1cb9b66 100644 --- a/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx +++ b/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx @@ -2,16 +2,17 @@ import Editor, { Monaco, OnMount } from '@monaco-editor/react' import { useParams } from 'common' import { debounce } from 'lodash' import { useRouter } from 'next/router' -import { MutableRefObject, useEffect, useRef } from 'react' +import { MutableRefObject, useEffect, useRef, useState } from 'react' import { cn } from 'ui' import { SqlSnippet } from 'data/content/sql-snippets-query' -import { useSelectedProject } from 'hooks' +import { useLocalStorageQuery, useSelectedProject } from 'hooks' import { useProfile } from 'lib/profile' import { useSqlEditorStateSnapshot } from 'state/sql-editor' import { untitledSnippetTitle } from './SQLEditor.constants' import { IStandaloneCodeEditor } from './SQLEditor.types' import { createSqlSnippetSkeleton } from './SQLEditor.utils' +import { LOCAL_STORAGE_KEYS } from 'lib/constants' export type MonacoEditorProps = { id: string @@ -37,6 +38,11 @@ const MonacoEditor = ({ const { profile } = useProfile() const project = useSelectedProject() + const [intellisenseEnabled] = useLocalStorageQuery( + LOCAL_STORAGE_KEYS.SQL_EDITOR_INTELLISENSE, + typeof window !== 'undefined' ? false : true + ) + const snap = useSqlEditorStateSnapshot({ sync: true }) const snippet = snap.snippets[id] @@ -138,6 +144,36 @@ const MonacoEditor = ({ // - https://github.com/microsoft/monaco-editor/issues/2229 // - https://github.com/microsoft/monaco-editor/issues/2503 // fixedOverflowWidgets: true, + suggest: { + showMethods: intellisenseEnabled, + showFunctions: intellisenseEnabled, + showConstructors: intellisenseEnabled, + showDeprecated: intellisenseEnabled, + showFields: intellisenseEnabled, + showVariables: intellisenseEnabled, + showClasses: intellisenseEnabled, + showStructs: intellisenseEnabled, + showInterfaces: intellisenseEnabled, + showModules: intellisenseEnabled, + showProperties: intellisenseEnabled, + showEvents: intellisenseEnabled, + showOperators: intellisenseEnabled, + showUnits: intellisenseEnabled, + showValues: intellisenseEnabled, + showConstants: intellisenseEnabled, + showEnums: intellisenseEnabled, + showEnumMembers: intellisenseEnabled, + showKeywords: intellisenseEnabled, + showWords: intellisenseEnabled, + showColors: intellisenseEnabled, + showFiles: intellisenseEnabled, + showReferences: intellisenseEnabled, + showFolders: intellisenseEnabled, + showTypeParameters: intellisenseEnabled, + showIssues: intellisenseEnabled, + showUsers: intellisenseEnabled, + showSnippets: intellisenseEnabled, + }, }} /> ) diff --git a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/FavoriteButton.tsx b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/FavoriteButton.tsx index d1ee247b66c..9e5dc5b4a84 100644 --- a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/FavoriteButton.tsx +++ b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/FavoriteButton.tsx @@ -1,4 +1,10 @@ -import { Button, IconHeart } from 'ui' +import { + Button, + IconHeart, + TooltipContent_Shadcn_, + TooltipTrigger_Shadcn_, + Tooltip_Shadcn_, +} from 'ui' import { useQueryClient } from '@tanstack/react-query' import { contentKeys } from 'data/content/keys' import { Content, ContentData } from 'data/content/content-query' @@ -75,23 +81,28 @@ const FavoriteButton = ({ id }: FavoriteButtonProps) => { } return ( - <> - {isFavorite ? ( - - + ) } diff --git a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx index 37cfa3ce024..e6c9821552d 100644 --- a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx +++ b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx @@ -23,17 +23,14 @@ const UtilityPanel = ({ <>
- -
- -
+
diff --git a/apps/studio/lib/constants/index.ts b/apps/studio/lib/constants/index.ts index 7ea1d43dc97..7646cc7b481 100644 --- a/apps/studio/lib/constants/index.ts +++ b/apps/studio/lib/constants/index.ts @@ -35,6 +35,7 @@ export const LOCAL_STORAGE_KEYS = { DASHBOARD_HISTORY: (ref: string) => `dashboard-history-${ref}`, UI_PREVIEW_CLS: 'supabase-ui-cls', + SQL_EDITOR_INTELLISENSE: 'supabase_sql-editor-intellisense-enabled', SQL_EDITOR_SPLIT_SIZE: 'supabase_sql-editor-split-size', LOG_EXPLORER_SPLIT_SIZE: 'supabase_log-explorer-split-size', GRAPHIQL_RLS_BYPASS_WARNING: 'graphiql-rls-bypass-warning-dismissed', diff --git a/apps/studio/pages/project/[ref]/sql/[id].tsx b/apps/studio/pages/project/[ref]/sql/[id].tsx index 8e074519a07..48af796d0b3 100644 --- a/apps/studio/pages/project/[ref]/sql/[id].tsx +++ b/apps/studio/pages/project/[ref]/sql/[id].tsx @@ -1,8 +1,8 @@ -import { useRouter } from 'next/router' import { useMonaco } from '@monaco-editor/react' -import { observer } from 'mobx-react-lite' -import { useEffect, useRef } from 'react' import { useParams } from 'common' +import { observer } from 'mobx-react-lite' +import { useRouter } from 'next/router' +import { useEffect, useRef } from 'react' import { useFunctionsQuery } from 'data/database/functions-query' import { useKeywordsQuery } from 'data/database/keywords-query' @@ -16,6 +16,8 @@ import { SQLEditorLayout } from 'components/layouts' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import getPgsqlCompletionProvider from 'components/ui/CodeEditor/Providers/PgSQLCompletionProvider' import getPgsqlSignatureHelpProvider from 'components/ui/CodeEditor/Providers/PgSQLSignatureHelpProvider' +import { useLocalStorageQuery } from 'hooks' +import { LOCAL_STORAGE_KEYS } from 'lib/constants' import { useAppStateSnapshot } from 'state/app-state' import { useSnippets, useSqlEditorStateSnapshot } from 'state/sql-editor' @@ -31,6 +33,11 @@ const SqlEditor: NextPageWithLayout = () => { const snippets = useSnippets(ref) const { mutateAsync: formatQuery } = useFormatQueryMutation() + const [intellisenseEnabled] = useLocalStorageQuery( + LOCAL_STORAGE_KEYS.SQL_EDITOR_INTELLISENSE, + typeof window !== 'undefined' ? false : true + ) + async function formatPgsql(value: string) { try { if (!project) throw new Error('No project') @@ -46,29 +53,46 @@ const SqlEditor: NextPageWithLayout = () => { } } - const { data: keywords, isSuccess: isKeywordsSuccess } = useKeywordsQuery({ - projectRef: project?.ref, - connectionString: project?.connectionString, - }) - const { data: functions, isSuccess: isFunctionsSuccess } = useFunctionsQuery({ - projectRef: project?.ref, - connectionString: project?.connectionString, - }) - const { data: schemas, isSuccess: isSchemasSuccess } = useSchemasQuery({ - projectRef: project?.ref, - connectionString: project?.connectionString, - }) - const { data: tableColumns, isSuccess: isTableColumnsSuccess } = useTableColumnsQuery({ - projectRef: project?.ref, - connectionString: project?.connectionString, - }) + const { data: keywords, isSuccess: isKeywordsSuccess } = useKeywordsQuery( + { + projectRef: project?.ref, + connectionString: project?.connectionString, + }, + { enabled: intellisenseEnabled } + ) + const { data: functions, isSuccess: isFunctionsSuccess } = useFunctionsQuery( + { + projectRef: project?.ref, + connectionString: project?.connectionString, + }, + { enabled: intellisenseEnabled } + ) + const { data: schemas, isSuccess: isSchemasSuccess } = useSchemasQuery( + { + projectRef: project?.ref, + connectionString: project?.connectionString, + }, + { enabled: intellisenseEnabled } + ) + const { data: tableColumns, isSuccess: isTableColumnsSuccess } = useTableColumnsQuery( + { + projectRef: project?.ref, + connectionString: project?.connectionString, + }, + { enabled: intellisenseEnabled } + ) const pgInfoRef = useRef(null) const formatPgsqlRef = useRef(formatPgsql) formatPgsqlRef.current = formatPgsql const isPgInfoReady = - isTableColumnsSuccess && isSchemasSuccess && isKeywordsSuccess && isFunctionsSuccess + intellisenseEnabled && + isTableColumnsSuccess && + isSchemasSuccess && + isKeywordsSuccess && + isFunctionsSuccess + if (isPgInfoReady) { if (pgInfoRef.current === null) { pgInfoRef.current = {} diff --git a/packages/ui/index.tsx b/packages/ui/index.tsx index 0c5d85b1f4f..770a53b4e08 100644 --- a/packages/ui/index.tsx +++ b/packages/ui/index.tsx @@ -207,6 +207,8 @@ export { TooltipContent as TooltipContent_Shadcn_, } from './src/components/shadcn/ui/tooltip' +export { Toggle as Toggle_Shadcn } from './src/components/shadcn/ui/toggle' + export { ScrollArea, ScrollBar } from './src/components/shadcn/ui/scroll-area' export { Separator } from './src/components/shadcn/ui/separator' diff --git a/packages/ui/src/components/shadcn/ui/toggle.tsx b/packages/ui/src/components/shadcn/ui/toggle.tsx index a64f158ec2f..a74a089e6c3 100644 --- a/packages/ui/src/components/shadcn/ui/toggle.tsx +++ b/packages/ui/src/components/shadcn/ui/toggle.tsx @@ -7,7 +7,7 @@ import * as React from 'react' import { cn } from '../../../lib/utils/cn' const toggleVariants = cva( - 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors data-[state=on]:bg-accent data-[state=on]:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background hover:bg-muted hover:text-foreground-muted', + 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors data-[state=on]:bg-accent data-[state=on]:bg-surface-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background bg-surface-200 hover:bg-surface-300 px-3 py-1 h-auto text-foreground transition-all', { variants: { variant: {