Files
supabase/apps/studio/components/interfaces/UnifiedLogs/ServiceFlowPanel.tsx
Joshen Lim abe7e87bba Remove unified logs related dead code (#46459)
## Context

Just removing unified logs related dead code (Not used, not imported)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Refactor**
* Streamlined the Service Flow view by removing legacy timeline,
collapsible sections, and some detailed step UI for a cleaner
visualization.
* Simplified the Unified Logs surface by reducing exposed types,
consolidating query logic, and removing an internal event bus.
* Removed legacy list/detail and sheet UI pieces to tighten the logs
interface and public API surface.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46459?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-28 23:03:56 +08:00

263 lines
9.5 KiB
TypeScript

import { useParams } from 'common'
import { Check, Clock, Copy } from 'lucide-react'
import { useEffect, useRef, useState } from 'react'
import {
Button,
copyToClipboard,
ResizableHandle,
ResizablePanel,
Skeleton,
Tabs_Shadcn_ as Tabs,
TabsContent_Shadcn_ as TabsContent,
TabsList_Shadcn_ as TabsList,
TabsTrigger_Shadcn_ as TabsTrigger,
} from 'ui'
import { CodeBlock } from 'ui-patterns/CodeBlock'
import { PostgresFlowDetail } from './ServiceFlow/components/PostgresFlowDetail'
import {
MemoizedEdgeFunctionBlock,
MemoizedGoTrueBlock,
MemoizedNetworkBlock,
MemoizedPostgresBlock,
MemoizedPostgRESTBlock,
MemoizedStorageBlock,
} from './ServiceFlow/components/ServiceBlocks'
import { ServiceFlowPanelControls } from './ServiceFlow/components/ServiceFlowPanelControls'
import { DetailSectionHeader } from './ServiceFlow/components/shared/DetailSection'
import { ColumnSchema } from './UnifiedLogs.schema'
import { QuerySearchParamsType } from './UnifiedLogs.types'
import { getRowTimestampMs } from './UnifiedLogs.utils'
import { useDataTable } from '@/components/ui/DataTable/providers/DataTableProvider'
import {
ServiceFlowType,
useUnifiedLogInspectionQuery,
} from '@/data/logs/unified-log-inspection-query'
import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
interface ServiceFlowPanelProps {
dock: 'bottom' | 'right'
setDock: (value: 'bottom' | 'right') => void
selectedRow?: ColumnSchema
selectedRowKey: string
searchParameters: QuerySearchParamsType
}
export function ServiceFlowPanel({
dock,
setDock,
selectedRow,
selectedRowKey,
searchParameters,
}: ServiceFlowPanelProps) {
const { table, filterFields } = useDataTable()
const { ref: projectRef } = useParams()
const [activeTab, setActiveTab] = useState('overview')
const [jsonCopied, setJsonCopied] = useState(false)
const overviewScrollRef = useRef<HTMLDivElement>(null)
const jsonScrollRef = useRef<HTMLDivElement>(null)
useEffect(() => {
overviewScrollRef.current?.scrollTo({ top: 0 })
jsonScrollRef.current?.scrollTo({ top: 0 })
}, [selectedRowKey])
const logType = selectedRow?.log_type
const serviceFlowType: ServiceFlowType | undefined =
logType === 'edge function' ? 'edge-function' : (logType as ServiceFlowType)
const shouldShowServiceFlow = !!serviceFlowType
useEffect(() => {
if (!shouldShowServiceFlow && activeTab === 'overview') {
setActiveTab('raw-json')
}
}, [shouldShowServiceFlow, activeTab])
const { logsMetadata } = useIsFeatureEnabled(['logs:metadata'])
// Query the logs API directly
const {
data: serviceFlowData,
isPending: isLoading,
error,
} = useUnifiedLogInspectionQuery(
{
projectRef: projectRef,
logId: selectedRow?.id,
type: serviceFlowType,
search: searchParameters,
},
{ enabled: Boolean(selectedRow?.id) && Boolean(serviceFlowType) }
)
if (!selectedRowKey || !selectedRow) return null
const timestampMs = getRowTimestampMs(selectedRow)
const formattedTime = timestampMs ? new Date(timestampMs).toLocaleString() : null
// Prepare JSON data for Raw JSON tab
const jsonData =
shouldShowServiceFlow && serviceFlowData?.result?.[0] ? serviceFlowData.result[0] : selectedRow
const formattedJsonData =
!logsMetadata && 'raw_log_data' in jsonData && 'metadata' in jsonData.raw_log_data
? {
...jsonData,
raw_log_data: { ...jsonData.raw_log_data, metadata: undefined },
}
: jsonData
return (
<>
<ResizableHandle withHandle />
<ResizablePanel
id="log-sidepanel"
defaultSize={400}
minSize={dock === 'bottom' ? 300 : 400}
className="bg-dash-sidebar"
>
<div className="flex h-full flex-col overflow-hidden">
<Tabs
defaultValue={shouldShowServiceFlow ? 'overview' : 'raw-json'}
value={activeTab}
onValueChange={setActiveTab}
className="flex h-full w-full flex-col"
>
<div className="flex items-center justify-between px-4 border-b border-border">
<TabsList className="flex h-auto gap-x-4 rounded-none border-none!">
{shouldShowServiceFlow && (
<TabsTrigger
value="overview"
className="border-b py-3 font-mono text-xs uppercase"
>
Overview
</TabsTrigger>
)}
<TabsTrigger value="raw-json" className="border-b py-3 font-mono text-xs uppercase">
Raw JSON
</TabsTrigger>
</TabsList>
<ServiceFlowPanelControls dock={dock} setDock={setDock} />
</div>
{shouldShowServiceFlow && (
<TabsContent
ref={overviewScrollRef}
value="overview"
className="mt-0 grow overflow-auto py-2"
>
{error ? (
<div className="py-8 text-center text-destructive">Error: {error.toString()}</div>
) : serviceFlowType === 'postgres' ? (
<PostgresFlowDetail
data={selectedRow}
enrichedData={serviceFlowData?.result?.[0]}
isLoading={isLoading}
filterFields={filterFields}
table={table}
/>
) : (
<div>
<DetailSectionHeader
title="Request started"
icon={Clock}
summary={formattedTime ?? undefined}
/>
<MemoizedNetworkBlock
data={selectedRow}
enrichedData={serviceFlowData?.result?.[0]}
isLoading={isLoading}
filterFields={filterFields}
table={table}
/>
{serviceFlowType === 'auth' ? (
<MemoizedGoTrueBlock
data={selectedRow}
enrichedData={serviceFlowData?.result?.[0]}
isLoading={isLoading}
filterFields={filterFields}
table={table}
/>
) : serviceFlowType === 'edge-function' ? (
<MemoizedEdgeFunctionBlock
data={selectedRow}
enrichedData={serviceFlowData?.result?.[0]}
isLoading={isLoading}
filterFields={filterFields}
table={table}
/>
) : serviceFlowType === 'storage' ? (
<MemoizedStorageBlock
data={selectedRow}
enrichedData={serviceFlowData?.result?.[0]}
isLoading={isLoading}
filterFields={filterFields}
table={table}
/>
) : (
<>
<MemoizedPostgRESTBlock
data={selectedRow}
enrichedData={serviceFlowData?.result?.[0]}
isLoading={isLoading}
filterFields={filterFields}
table={table}
/>
<MemoizedPostgresBlock
data={selectedRow}
enrichedData={serviceFlowData?.result?.[0]}
isLoading={isLoading}
filterFields={filterFields}
table={table}
/>
</>
)}
</div>
)}
</TabsContent>
)}
<TabsContent
ref={jsonScrollRef}
value="raw-json"
className="mt-0 grow overflow-auto bg-surface-100/50"
>
{isLoading && shouldShowServiceFlow && (
<div className="flex items-center gap-3 border-b border-border bg-surface-100 p-3 text-foreground-light">
<Skeleton className="h-4 w-4 animate-pulse rounded-full" />
<span className="text-sm">Enriching log...</span>
</div>
)}
<div className="sticky top-2 z-10 flex justify-end px-2 -mb-9 pointer-events-none">
<Button
size="tiny"
type="default"
className="pointer-events-auto px-1.5"
icon={jsonCopied ? <Check size={12} /> : <Copy size={12} />}
onClick={() => {
copyToClipboard(JSON.stringify(formattedJsonData, null, 2))
setJsonCopied(true)
setTimeout(() => setJsonCopied(false), 1000)
}}
>
{jsonCopied ? 'Copied' : ''}
</Button>
</div>
<CodeBlock
language="json"
hideCopy
wrapperClassName="!overflow-visible bg-surface-100/50 [&_pre]:!bg-surface-100/50"
className="rounded-none border-none [&_code]:!leading-tight [&_pre]:!leading-tight"
>
{JSON.stringify(formattedJsonData, null, 2)}
</CodeBlock>
</TabsContent>
</Tabs>
</div>
</ResizablePanel>
</>
)
}