mirror of
https://github.com/supabase/supabase.git
synced 2026-10-19 16:19:10 +03:00
refactor: simplify DisplayBlockRenderer state
This commit is contained in:
1 parent
2bff4ee8b8
commit
2b8c73b0e3
3 files changed
+70
-55
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useState } from 'react'
|
||||
import { X } from 'lucide-react'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
import { useParams } from 'common'
|
||||
@@ -9,13 +9,13 @@ import { DEFAULT_CHART_CONFIG, QueryBlock } from 'components/ui/QueryBlock/Query
|
||||
import { AnalyticsInterval } from 'data/analytics/constants'
|
||||
import { useContentIdQuery } from 'data/content/content-id-query'
|
||||
import { usePrimaryDatabase } from 'data/read-replicas/replicas-query'
|
||||
import { useExecuteSqlMutation, type QueryResponseError } from 'data/sql/execute-sql-mutation'
|
||||
import { useChanged } from 'hooks/misc/useChanged'
|
||||
import { useExecuteSqlMutation } from 'data/sql/execute-sql-mutation'
|
||||
import { useChangedSync } from 'hooks/misc/useChanged'
|
||||
import { useDatabaseSelectorStateSnapshot } from 'state/database-selector'
|
||||
import { Dashboards, SqlSnippets } from 'types'
|
||||
import type { Dashboards, SqlSnippets } from 'types'
|
||||
import { DEPRECATED_REPORTS } from '../Reports.constants'
|
||||
import { ChartBlock } from './ChartBlock'
|
||||
import { DeprecatedChartBlock } from './DeprecatedChartBlock'
|
||||
import { DEPRECATED_REPORTS } from '../Reports.constants'
|
||||
|
||||
interface ReportBlockProps {
|
||||
item: Dashboards.Chart
|
||||
@@ -131,8 +131,8 @@ export const ReportBlock = ({
|
||||
[projectRef, readOnlyConnectionString, postgresConnectionString, executeSql]
|
||||
)
|
||||
|
||||
const sqlHasChanged = useChanged(sql)
|
||||
const isRefreshingChanged = useChanged(isRefreshing)
|
||||
const sqlHasChanged = useChangedSync(sql)
|
||||
const isRefreshingChanged = useChangedSync(isRefreshing)
|
||||
if (sqlHasChanged || (isRefreshingChanged && isRefreshing)) {
|
||||
runQuery('select', sql)
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import { PermissionAction } from '@supabase/shared-types/out/constants'
|
||||
import { useRouter } from 'next/router'
|
||||
import { DragEvent, PropsWithChildren, useEffect, useRef, useState } from 'react'
|
||||
import { type DragEvent, type PropsWithChildren, useRef, useState } from 'react'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import { ChartConfig } from 'components/interfaces/SQLEditor/UtilityPanel/ChartConfig'
|
||||
import { usePrimaryDatabase } from 'data/read-replicas/replicas-query'
|
||||
import { useExecuteSqlMutation } from 'data/sql/execute-sql-mutation'
|
||||
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
|
||||
import { useChangedSync } from 'hooks/misc/useChanged'
|
||||
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
|
||||
import { useProfile } from 'lib/profile'
|
||||
|
||||
import { ConfirmFooter } from './ConfirmFooter'
|
||||
import { DEFAULT_CHART_CONFIG, QueryBlock } from '../QueryBlock/QueryBlock'
|
||||
import { identifyQueryType } from './AIAssistant.utils'
|
||||
import { ConfirmFooter } from './ConfirmFooter'
|
||||
|
||||
interface DisplayBlockRendererProps {
|
||||
messageId: string
|
||||
@@ -51,6 +51,15 @@ export const DisplayBlockRenderer = ({
|
||||
onChartConfigChange,
|
||||
onQueryRun,
|
||||
}: PropsWithChildren<DisplayBlockRendererProps>) => {
|
||||
const savedInitialArgs = useRef(initialArgs)
|
||||
const savedInitialResults = useRef(initialResults)
|
||||
const savedInitialConfig = useRef<ChartConfig>({
|
||||
...DEFAULT_CHART_CONFIG,
|
||||
view: initialArgs.view === 'chart' ? 'chart' : 'table',
|
||||
xKey: initialArgs.xAxis ?? '',
|
||||
yKey: initialArgs.yAxis ?? '',
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
const { ref } = useParams()
|
||||
const { profile } = useProfile()
|
||||
@@ -86,57 +95,31 @@ export const DisplayBlockRenderer = ({
|
||||
const readOnlyConnectionString = primaryDatabase?.connection_string_read_only
|
||||
const postgresConnectionString = primaryDatabase?.connectionString
|
||||
|
||||
const lastQueryType = useRef<'select' | 'mutation'>('select')
|
||||
|
||||
useEffect(() => {
|
||||
const initialConfig: ChartConfig = {
|
||||
...DEFAULT_CHART_CONFIG,
|
||||
view: initialArgs.view === 'chart' ? 'chart' : 'table',
|
||||
xKey: initialArgs.xAxis ?? '',
|
||||
yKey: initialArgs.yAxis ?? '',
|
||||
}
|
||||
setChartConfig(initialConfig)
|
||||
onChartConfigChange?.(initialConfig)
|
||||
setIsWriteQuery(initialArgs.isWriteQuery || false)
|
||||
setRows(Array.isArray(initialResults) ? initialResults : undefined)
|
||||
lastQueryType.current = initialArgs.isWriteQuery ? 'mutation' : 'select'
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [toolCallId])
|
||||
|
||||
useEffect(() => {
|
||||
const normalized = Array.isArray(initialResults) ? initialResults : undefined
|
||||
if (!normalized || normalized === rows) return
|
||||
setRows(normalized)
|
||||
}, [initialResults, rows])
|
||||
|
||||
const {
|
||||
mutate: executeSql,
|
||||
error: executeSqlError,
|
||||
isLoading: executeSqlLoading,
|
||||
} = useExecuteSqlMutation({
|
||||
onSuccess: (data) => {
|
||||
setRows(Array.isArray(data.result) ? data.result : undefined)
|
||||
setIsWriteQuery(lastQueryType.current === 'mutation' || initialArgs.isWriteQuery || false)
|
||||
onResults?.({
|
||||
messageId,
|
||||
results: Array.isArray(data.result) ? data.result : undefined,
|
||||
})
|
||||
},
|
||||
onError: (error) => {
|
||||
const lowerMessage = error.message.toLowerCase()
|
||||
const isReadOnlyError =
|
||||
lowerMessage.includes('read-only transaction') ||
|
||||
lowerMessage.includes('permission denied') ||
|
||||
lowerMessage.includes('must be owner')
|
||||
|
||||
if (lastQueryType.current === 'select' && isReadOnlyError) {
|
||||
setIsWriteQuery(true)
|
||||
}
|
||||
|
||||
onError?.({ messageId, errorText: error.message })
|
||||
onError: () => {
|
||||
// Suppress toast because error message is displayed inline
|
||||
},
|
||||
})
|
||||
|
||||
const toolCallIdChanged = useChangedSync(toolCallId)
|
||||
if (toolCallIdChanged) {
|
||||
setChartConfig(savedInitialConfig.current)
|
||||
onChartConfigChange?.(savedInitialConfig.current)
|
||||
setIsWriteQuery(savedInitialArgs.current.isWriteQuery || false)
|
||||
setRows(Array.isArray(savedInitialResults.current) ? savedInitialResults.current : undefined)
|
||||
}
|
||||
|
||||
const initialResultsChanged = useChangedSync(initialResults)
|
||||
if (initialResultsChanged) {
|
||||
const normalized = Array.isArray(initialResults) ? initialResults : undefined
|
||||
if (!normalized || normalized === rows) return
|
||||
setRows(normalized)
|
||||
}
|
||||
|
||||
const handleRunQuery = (queryType: 'select' | 'mutation') => {
|
||||
if (!sqlQuery) return
|
||||
|
||||
@@ -169,11 +152,35 @@ export const DisplayBlockRenderer = ({
|
||||
return
|
||||
}
|
||||
|
||||
lastQueryType.current = queryType
|
||||
if (queryType === 'mutation') {
|
||||
setIsWriteQuery(true)
|
||||
}
|
||||
executeSql({ projectRef: ref, connectionString, sql: sqlQuery })
|
||||
executeSql(
|
||||
{ projectRef: ref, connectionString, sql: sqlQuery },
|
||||
{
|
||||
onSuccess: (data) => {
|
||||
setRows(Array.isArray(data.result) ? data.result : undefined)
|
||||
setIsWriteQuery(queryType === 'mutation' || initialArgs.isWriteQuery || false)
|
||||
onResults?.({
|
||||
messageId,
|
||||
results: Array.isArray(data.result) ? data.result : undefined,
|
||||
})
|
||||
},
|
||||
onError: (error) => {
|
||||
const lowerMessage = error.message.toLowerCase()
|
||||
const isReadOnlyError =
|
||||
lowerMessage.includes('read-only transaction') ||
|
||||
lowerMessage.includes('permission denied') ||
|
||||
lowerMessage.includes('must be owner')
|
||||
|
||||
if (queryType === 'select' && isReadOnlyError) {
|
||||
setIsWriteQuery(true)
|
||||
}
|
||||
|
||||
onError?.({ messageId, errorText: error.message })
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const handleExecute = (queryType: 'select' | 'mutation') => {
|
||||
|
||||
@@ -10,3 +10,11 @@ export function useChanged<T>(value: T): boolean {
|
||||
|
||||
return changed
|
||||
}
|
||||
|
||||
export function useChangedSync<T>(value: T): boolean {
|
||||
const prev = useRef<T>()
|
||||
const changed = prev.current !== value
|
||||
prev.current = value
|
||||
|
||||
return changed
|
||||
}
|
||||
Reference in new issue
Block a user