fix: Migrate SQL editor and Log explrorer to use ShadCN Resizable (#21454)

* Add resizable component to ui package.

* Migrate the LogExplorer to use the new resizable component.

* Migrate the SQL editor to use the new component.

* Remove react-split.
This commit is contained in:
Ivan Vasilov
2024-02-26 09:39:23 +01:00
committed by GitHub
parent dcdc3cd230
commit b4e768b74f
11 changed files with 92 additions and 70 deletions

View File

@@ -4,7 +4,6 @@ import { AnimatePresence, motion } from 'framer-motion'
import dynamic from 'next/dynamic'
import { useRouter } from 'next/router'
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'
import Split from 'react-split'
import { format } from 'sql-formatter'
import ConfirmModal from 'components/ui/Dialogs/ConfirmDialog'
@@ -20,7 +19,6 @@ import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-que
import { isError } from 'data/utils/error-check'
import {
useFlag,
useLocalStorage,
useLocalStorageQuery,
useSelectedOrganization,
useSelectedProject,
@@ -50,6 +48,9 @@ import {
IconSettings,
IconX,
Input_Shadcn_,
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
cn,
} from 'ui'
import { subscriptionHasHipaaAddon } from '../Billing/Subscription/Subscription.utils'
@@ -178,13 +179,6 @@ const SQLEditor = () => {
const isDiffOpen = !!sqlDiff
const [savedSplitSize, setSavedSplitSize] = useLocalStorage(
LOCAL_STORAGE_KEYS.SQL_EDITOR_SPLIT_SIZE,
`[50, 50]`
)
const splitSize = savedSplitSize ? JSON.parse(savedSplitSize) : undefined
const { mutate: execute, isLoading: isExecuting } = useExecuteSqlMutation({
onSuccess(data) {
if (id) snap.addResult(id, data.result)
@@ -230,20 +224,10 @@ const SQLEditor = () => {
},
})
const minSize = 44
const snippet = id ? snap.snippets[id] : null
const snapOffset = 50
const isLoading = urlId === 'new' ? false : !(id && ref && snap.loaded[ref])
const onDragEnd = useCallback(
(sizes: number[]) => {
if (id) snap.setSplitSizes(id, sizes)
setSavedSplitSize(JSON.stringify(sizes))
},
[id]
)
const editorRef = useRef<IStandaloneCodeEditor | null>(null)
const monacoRef = useRef<Monaco | null>(null)
const diffEditorRef = useRef<IStandaloneDiffEditor | null>(null)
@@ -866,19 +850,12 @@ const SQLEditor = () => {
</motion.div>
</AISchemaSuggestionPopover>
)}
<Split
style={{ height: '100%' }}
<ResizablePanelGroup
className="h-full"
direction="vertical"
gutterSize={2}
sizes={
(splitSize ? splitSize : (snippet?.splitSizes as number[] | undefined)) ?? [50, 50]
}
minSize={minSize}
snapOffset={snapOffset}
expandToMin={true}
onDragEnd={onDragEnd}
autoSaveId={LOCAL_STORAGE_KEYS.SQL_EDITOR_SPLIT_SIZE}
>
<div className="flex-grow overflow-y-auto border-b">
<ResizablePanel collapsible collapsedSize={10} minSize={20}>
{!isAiOpen && (
<motion.button
layoutId="ask-ai-input-icon"
@@ -1006,8 +983,9 @@ const SQLEditor = () => {
</motion.div>
</>
)}
</div>
<div className="flex flex-col">
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel collapsible collapsedSize={10} minSize={20}>
{isLoading ? (
<div className="flex h-full w-full items-center justify-center">Loading...</div>
) : (
@@ -1020,8 +998,8 @@ const SQLEditor = () => {
executeQuery={executeQuery}
/>
)}
</div>
</Split>
</ResizablePanel>
</ResizablePanelGroup>
</div>
</SQLEditorContext.Provider>
)

View File

@@ -36,6 +36,7 @@ export const LOCAL_STORAGE_KEYS = {
UI_PREVIEW_CLS: 'supabase-ui-cls',
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',
CLS_DIFF_WARNING: 'cls-diff-warning-dismissed',
CLS_SELECT_STAR_WARNING: 'cls-select-star-warning-dismissed',

View File

@@ -87,7 +87,6 @@
"react-intersection-observer": "^9.5.3",
"react-markdown": "^8.0.3",
"react-simple-maps": "4.0.0-beta.6",
"react-split": "^2.0.13",
"react-tracked": "^1.7.11",
"react-virtualized-auto-sizer": "^1.0.20",
"react-window": "^1.8.6",

View File

@@ -1,20 +1,28 @@
import { useParams } from 'common/hooks'
import dayjs from 'dayjs'
import { observer } from 'mobx-react-lite'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import { Button, Form, Input, Modal } from 'ui'
import Split from 'react-split'
import { useParams } from 'common/hooks'
import {
Button,
Form,
Input,
Modal,
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from 'ui'
import {
DatePickerToFrom,
LogsQueryPanel,
LogsTableName,
LogsWarning,
LOGS_LARGE_DATE_RANGE_DAYS_THRESHOLD,
LogTable,
LogTemplate,
maybeShowUpgradePrompt,
LogsQueryPanel,
LogsTableName,
LogsWarning,
TEMPLATES,
maybeShowUpgradePrompt,
useEditorHints,
} from 'components/interfaces/Settings/Logs'
import UpgradePrompt from 'components/interfaces/Settings/Logs/UpgradePrompt'
@@ -23,12 +31,13 @@ import CodeEditor from 'components/ui/CodeEditor'
import LoadingOpacity from 'components/ui/LoadingOpacity'
import ShimmerLine from 'components/ui/ShimmerLine'
import { useContentInsertMutation } from 'data/content/content-insert-mutation'
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
import { useLocalStorage, useSelectedOrganization, useStore } from 'hooks'
import useLogsQuery from 'hooks/analytics/useLogsQuery'
import { useUpgradePrompt } from 'hooks/misc/useUpgradePrompt'
import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { uuidv4 } from 'lib/helpers'
import { LogSqlSnippets, NextPageWithLayout } from 'types'
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
const PLACEHOLDER_QUERY =
'select\n cast(timestamp as datetime) as timestamp,\n event_message, metadata \nfrom edge_logs \nlimit 5'
@@ -187,17 +196,12 @@ export const LogsExplorerPage: NextPageWithLayout = () => {
return (
<div className="w-full h-full mx-auto">
<Split
className="w-full"
style={{ height: '100%' }}
<ResizablePanelGroup
className="w-full h-full"
direction="vertical"
gutterSize={2}
sizes={[50, 50]}
minSize={44}
snapOffset={50}
expandToMin={true}
autoSaveId={LOCAL_STORAGE_KEYS.LOG_EXPLORER_SPLIT_SIZE}
>
<div className="flex-grow overflow-y-auto border-b">
<ResizablePanel collapsible minSize={5}>
<LogsQueryPanel
defaultFrom={params.iso_timestamp_start || ''}
defaultTo={params.iso_timestamp_end || ''}
@@ -220,8 +224,9 @@ export const LogsExplorerPage: NextPageWithLayout = () => {
onInputChange={(v) => setEditorValue(v || '')}
onInputRun={handleRun}
/>
</div>
<div className="flex flex-col flex-grow">
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel collapsible minSize={5} className="flex flex-col flex-grow">
<LoadingOpacity active={isLoading}>
<div className="flex flex-grow">
<LogTable
@@ -238,8 +243,8 @@ export const LogsExplorerPage: NextPageWithLayout = () => {
<div className="flex flex-row justify-end mt-2">
<UpgradePrompt show={showUpgradePrompt} setShowUpgradePrompt={setShowUpgradePrompt} />
</div>
</div>
</Split>
</ResizablePanel>
</ResizablePanelGroup>
<Modal
size="medium"

View File

@@ -126,7 +126,7 @@ const SqlEditor: NextPageWithLayout = () => {
}, [isPgInfoReady])
return (
<div className="SQLTabContainer flex-1">
<div className="flex-1">
<SQLEditor />
</div>
)

View File

@@ -3,11 +3,6 @@
-webkit-text-size-adjust: 100%;
}
.gutter {
@apply bg-border-control;
cursor: row-resize;
}
.grid-monaco-editor,
.monaco-editor p,
label,

View File

@@ -349,14 +349,6 @@
scrollbar-width: none; // auto | thin | none | <length>;
}
.SQLTabContainer {
height: calc(100vh - 3rem);
min-height: calc(100vh - 3rem);
.gutter {
cursor: row-resize;
}
}
.radix-tooltip-arrow {
polygon {
@apply fill-background-alternative [[data-theme*=dark]_&]:fill-background-alternative;

10
package-lock.json generated
View File

@@ -30149,6 +30149,15 @@
"react": ">= 16.3"
}
},
"node_modules/react-resizable-panels": {
"version": "2.0.9",
"resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.0.9.tgz",
"integrity": "sha512-ZylBvs7oG7Y/INWw3oYGolqgpFvoPW8MPeg9l1fURDeKpxrmUuCHBUmPj47BdZ11MODImu3kZYXG85rbySab7w==",
"peerDependencies": {
"react": "^16.14.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-resize-detector": {
"version": "8.1.0",
"license": "MIT",
@@ -37364,6 +37373,7 @@
"react-hook-form": "^7.45.0",
"react-hot-toast": "^2.4.1",
"react-markdown": "^8.0.3",
"react-resizable-panels": "^2.0.9",
"react-syntax-highlighter": "^15.5.0",
"react-tooltip": "^4.2.17",
"reactflow": "^11.10.1",

View File

@@ -206,6 +206,8 @@ export { ScrollArea, ScrollBar } from './src/components/shadcn/ui/scroll-area'
export { Separator } from './src/components/shadcn/ui/separator'
export * from './src/components/shadcn/ui/resizable'
// links
export * from './src/components/TextLink'

View File

@@ -74,6 +74,7 @@
"react-hook-form": "^7.45.0",
"react-hot-toast": "^2.4.1",
"react-markdown": "^8.0.3",
"react-resizable-panels": "^2.0.9",
"react-syntax-highlighter": "^15.5.0",
"react-tooltip": "^4.2.17",
"reactflow": "^11.10.1",

View File

@@ -0,0 +1,39 @@
import { GripVertical } from 'lucide-react'
import * as ResizablePrimitive from 'react-resizable-panels'
import { cn } from '../../../lib/utils/cn'
const ResizablePanelGroup = ({
className,
...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
<ResizablePrimitive.PanelGroup
className={cn('flex h-full w-full data-[panel-group-direction=vertical]:flex-col', className)}
{...props}
/>
)
const ResizablePanel = ResizablePrimitive.Panel
const ResizableHandle = ({
withHandle,
className,
...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
withHandle?: boolean
}) => (
<ResizablePrimitive.PanelResizeHandle
className={cn(
'relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90',
className
)}
{...props}
>
{withHandle && (
<div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
<GripVertical className="h-2.5 w-2.5" />
</div>
)}
</ResizablePrimitive.PanelResizeHandle>
)
export { ResizableHandle, ResizablePanel, ResizablePanelGroup }