Home / Function/ ReportBlock() — supabase Function Reference

ReportBlock() — supabase Function Reference

Architecture documentation for the ReportBlock() function in ReportBlock.tsx from the supabase codebase.

Entity Profile

Relationship Graph

Source Code

apps/studio/components/interfaces/Reports/ReportBlock/ReportBlock.tsx lines 38–216

export const ReportBlock = ({
  item,
  startDate,
  endDate,
  interval,
  disableUpdate,
  isRefreshing,
  onRemoveChart,
  onUpdateChart,
}: ReportBlockProps) => {
  const { ref: projectRef } = useParams()
  const state = useDatabaseSelectorStateSnapshot()

  const [isWriteQuery, setIsWriteQuery] = useState(false)

  const isSnippet = item.attribute.startsWith('snippet_')

  const {
    data,
    error: contentError,
    isPending: isLoadingContent,
  } = useContentIdQuery(
    { projectRef, id: item.id },
    {
      enabled: isSnippet && !!item.id,
      refetchOnWindowFocus: false,
      refetchOnMount: false,
      refetchIntervalInBackground: false,
      retry: (failureCount: number) => {
        if (failureCount >= 2) return false
        return true
      },
    }
  )

  const sql = isSnippet ? (data?.content as SqlSnippets.Content)?.sql : undefined
  const chartConfig = { ...DEFAULT_CHART_CONFIG, ...(item.chartConfig ?? {}) }
  const isDeprecatedChart = DEPRECATED_REPORTS.includes(item.attribute)
  const snippetMissing = contentError?.message.includes('Content not found')

  const { database: primaryDatabase } = usePrimaryDatabase({ projectRef })
  const readOnlyConnectionString = primaryDatabase?.connection_string_read_only
  const postgresConnectionString = primaryDatabase?.connectionString

  const {
    data: queryResult,
    error: executeSqlError,
    isPending: executeSqlLoading,
    refetch,
  } = useQuery({
    queryKey: sqlKeys.query(projectRef, [
      item.id,
      sql,
      readOnlyConnectionString,
      postgresConnectionString,
    ]),
    queryFn: async () => {
      if (!projectRef || !sql) return null

      const connectionString = readOnlyConnectionString ?? postgresConnectionString

      if (!connectionString) {
        toast.error('Unable to establish a database connection for this project.')
        return null
      }

      return executeSql({
        projectRef,
        connectionString,
        sql,
      })
    },
    enabled: !isLoadingContent && contentError == null,
    refetchOnWindowFocus: false,
  })

  const rows = queryResult?.result

  useEffect(() => {
    if (executeSqlError) {
      const errorMessage = String(executeSqlError).toLowerCase()
      const isReadOnlyError =
        errorMessage.includes('read-only transaction') ||
        errorMessage.includes('permission denied') ||
        errorMessage.includes('must be owner')

      if (isReadOnlyError) {
        setIsWriteQuery(true)
      }
    }
  }, [executeSqlError])

  useEffect(() => {
    if (isRefreshing) {
      refetch()
    }
  }, [isRefreshing, refetch])

  return (
    <>
      {isSnippet ? (
        <QueryBlock
          blockWriteQueries
          id={item.id}
          label={item.label}
          chartConfig={chartConfig}
          sql={sql}
          results={rows}
          initialHideSql={true}
          errorText={
            snippetMissing
              ? 'SQL snippet not found'
              : executeSqlError
                ? String(executeSqlError)
                : undefined
          }
          isExecuting={executeSqlLoading}
          isWriteQuery={isWriteQuery}
          actions={
            !isLoadingContent && (
              <ButtonTooltip
                type="text"
                icon={<X />}
                className="w-7 h-7"
                onClick={() => onRemoveChart({ metric: { key: item.attribute } })}
                tooltip={{ content: { side: 'bottom', text: 'Remove chart' } }}
              />
            )
          }
          onExecute={(queryType) => {
            refetch()
          }}
          onUpdateChartConfig={onUpdateChart}
          onRemoveChart={() => onRemoveChart({ metric: { key: item.attribute } })}
          disabled={isLoadingContent || snippetMissing || !sql}
        />
      ) : isDeprecatedChart ? (
        <DeprecatedChartBlock
          attribute={item.attribute}
          label={`${item.label}${projectRef !== state.selectedDatabaseId ? (item.provider === 'infra-monitoring' ? ' of replica' : ' on project') : ''}`}
          actions={
            !disableUpdate ? (
              <ButtonTooltip
                type="text"
                icon={<X />}
                className="w-7 h-7"
                onClick={() => onRemoveChart({ metric: { key: item.attribute } })}
                tooltip={{ content: { side: 'bottom', text: 'Remove chart' } }}
              />
            ) : null
          }
        />
      ) : (
        <ChartBlock
          startDate={startDate}
          endDate={endDate}
          interval={interval}
          attribute={item.attribute}
          provider={item.provider}
          defaultChartStyle={item.chart_type}
          maxHeight={176}
          label={`${item.label}${projectRef !== state.selectedDatabaseId ? (item.provider === 'infra-monitoring' ? ' of replica' : ' on project') : ''}`}
          actions={
            !disableUpdate ? (
              <ButtonTooltip
                type="text"
                icon={<X />}
                className="w-7 h-7"
                onClick={() => onRemoveChart({ metric: { key: item.attribute } })}
                tooltip={{ content: { side: 'bottom', text: 'Remove chart' } }}
              />
            ) : null
          }
          onUpdateChartConfig={onUpdateChart}
        />
      )}
    </>
  )
}

Subdomains

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free