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 -->
This commit is contained in:
Joshen Lim
2026-05-28 23:03:56 +08:00
committed by GitHub
parent ef613f2068
commit abe7e87bba
15 changed files with 11 additions and 680 deletions

View File

@@ -3,12 +3,12 @@ import { Cable, ChevronDown, Clock, Database } from 'lucide-react'
import { memo } from 'react'
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from 'ui'
import { ColumnSchema } from '../../../UnifiedLogs.schema'
import { getRowTimestampMs } from '../../../UnifiedLogs.utils'
import { postgresDetailsFields, postgresPrimaryFields } from '../../config/serviceFlowFields'
import { BlockFieldConfig } from '../../types'
import { DetailRow } from '../shared/DetailRow'
import { DetailSectionHeader } from '../shared/DetailSection'
import { ColumnSchema } from '../../UnifiedLogs.schema'
import { getRowTimestampMs } from '../../UnifiedLogs.utils'
import { postgresDetailsFields, postgresPrimaryFields } from '../config/serviceFlowFields'
import { BlockFieldConfig } from '../types'
import { DetailRow } from './shared/DetailRow'
import { DetailSectionHeader } from './shared/DetailSection'
import { DataTableFilterField } from '@/components/ui/DataTable/DataTable.types'
interface PostgresFlowDetailProps {

View File

@@ -1,38 +0,0 @@
import { Clock } from 'lucide-react'
import { memo } from 'react'
import { ColumnSchema } from '../../../UnifiedLogs.schema'
import { StyledIcon } from '../shared/TimelineStep'
// Request Started - Simple header component with connecting line
export const MemoizedRequestStartedBlock = memo(function RequestStartedBlock({
data,
}: {
data: ColumnSchema
}) {
// Convert microseconds to milliseconds for JavaScript Date
const timestampMs = data?.timestamp
? data.timestamp / 1000
: data?.date
? data.date.getTime()
: null
const formattedTime = timestampMs ? new Date(timestampMs).toLocaleString() : null
return (
<div>
<div className="flex items-center justify-between py-0 px-2">
<div className="flex items-center gap-2 text-sm text-foreground-light">
<StyledIcon icon={Clock} title="Request started" />
<span>Request started</span>
</div>
{formattedTime && (
<span className="text-sm font-mono text-foreground-light">{formattedTime}</span>
)}
</div>
{/* Connecting line to first timeline block */}
<div className="border-l h-4 ml-5"></div>
</div>
)
})
MemoizedRequestStartedBlock.displayName = 'MemoizedRequestStartedBlock'

View File

@@ -1,103 +0,0 @@
import { Clock } from 'lucide-react'
import { memo } from 'react'
import { ColumnSchema } from '../../../UnifiedLogs.schema'
import { EventMessage } from '../shared/EventMessage'
import { StyledIcon } from '../shared/TimelineStep'
interface ResponseCompletedBlockProps {
data: ColumnSchema
enrichedData?: Record<string, any>
}
// Response (final step) - Shows completion details for HTTP or database operations
export const MemoizedResponseCompletedBlock = memo(function ResponseCompletedBlock({
data,
enrichedData,
}: ResponseCompletedBlockProps) {
// Check if this is a postgres log
const isPostgresLog = (enrichedData?.log_type || data?.log_type) === 'postgres'
// HTTP response handling
const hasError = data?.status && Number(data.status) >= 400
const responseTime = enrichedData?.response_time_ms || enrichedData?.duration_ms
const status = Number(data?.status)
// Postgres operation handling
const eventMessage = enrichedData?.event_message || data?.event_message
const severity = enrichedData?.error_severity
const hasPostgresError = severity && ['error', 'fatal'].includes(severity.toLowerCase())
return (
<div>
<div className="flex items-center justify-between py-0 px-2">
<div className="flex items-center gap-2 text-sm text-foreground-light">
<StyledIcon icon={Clock} title="Response" />
<span>{isPostgresLog ? 'Operation Result' : 'Response'}</span>
</div>
{/* Status display */}
{isPostgresLog
? // Postgres status
severity && (
<span
className={`text-sm font-mono ${
hasPostgresError ? 'text-destructive' : 'text-foreground-light'
}`}
>
{hasPostgresError ? `${severity.toUpperCase()} Error` : `${severity.toUpperCase()}`}
</span>
)
: // HTTP status
data?.status && (
<span className="text-sm font-mono text-foreground-light">
{hasError ? `${data.status} Error` : `${data.status} Success`}
</span>
)}
</div>
{/* Completion message */}
{isPostgresLog ? (
// Postgres completion message
<div className="text-xs text-foreground-light px-2 py-1">
{hasPostgresError
? 'Database operation completed with error'
: 'Database operation completed successfully'}
</div>
) : (
// HTTP completion message
responseTime && (
<div className="text-xs text-foreground-light px-2 py-1">
{hasError
? `Error response sent to client in ${responseTime}ms`
: `Response sent to client in ${responseTime}ms`}
</div>
)
)}
{/* Error/Event details */}
{isPostgresLog
? // Show postgres event message
eventMessage && (
<div className="px-2">
<EventMessage message={eventMessage} severity={severity} />
</div>
)
: // Show HTTP error details
hasError && (
<div className="px-2 py-1 mt-1">
<div className="text-xs font-medium text-destructive mb-1">Error Details</div>
<div className="text-xs text-foreground-light">
{status >= 500
? 'Server error occurred during request processing'
: status >= 400
? 'Client error - check request parameters and authentication'
: 'Request completed with error status'}
</div>
</div>
)}
</div>
)
})
MemoizedResponseCompletedBlock.displayName = 'MemoizedResponseCompletedBlock'

View File

@@ -7,14 +7,14 @@ import { BlockFieldConfig, BlockFieldProps, ServiceFlowBlockProps } from '../../
import { DetailRow } from './DetailRow'
import { DetailSectionHeader } from './DetailSection'
export interface BlockSection {
interface BlockSection {
title: string
icon?: LucideIcon
fields: BlockFieldConfig[]
collapsible?: boolean
}
export interface FieldWithSeeMoreSection {
interface FieldWithSeeMoreSection {
type: 'fieldWithSeeMore'
primaryField: BlockFieldConfig
additionalFields: BlockFieldConfig[]

View File

@@ -1,64 +0,0 @@
import { Table } from '@tanstack/react-table'
import { ChevronDown, ChevronRight } from 'lucide-react'
import { useState } from 'react'
import { Button, Collapsible, CollapsibleContent, CollapsibleTrigger } from 'ui'
import { BlockFieldConfig } from '../../types'
import { BlockField } from './BlockField'
import { DataTableFilterField } from '@/components/ui/DataTable/DataTable.types'
interface CollapsibleSectionProps {
title: string
fields: BlockFieldConfig[]
data: any
enrichedData?: any
isLoading?: boolean
filterFields: DataTableFilterField<any>[]
table: Table<any>
defaultOpen?: boolean
}
export const CollapsibleSection = ({
title,
fields,
data,
enrichedData,
isLoading,
filterFields,
table,
defaultOpen = false,
}: CollapsibleSectionProps) => {
const [isOpen, setIsOpen] = useState(defaultOpen)
return (
<div className="border-t border-border">
<Collapsible open={isOpen} onOpenChange={setIsOpen}>
<CollapsibleTrigger asChild>
<Button
type="text"
size="tiny"
className="w-full justify-start py-1 px-2 h-auto text-xs font-medium text-foreground-light hover:text-foreground"
>
<div className="flex items-center gap-1">
{isOpen ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
<span>{title}</span>
</div>
</Button>
</CollapsibleTrigger>
<CollapsibleContent className="transition-all data-closed:animate-collapsible-up data-open:animate-collapsible-down pt-1">
{fields.map((field) => (
<BlockField
key={field.id}
config={field}
data={data}
enrichedData={enrichedData}
isLoading={isLoading}
filterFields={filterFields}
table={table}
/>
))}
</CollapsibleContent>
</Collapsible>
</div>
)
}

View File

@@ -1,64 +0,0 @@
import { Database, LucideIcon } from 'lucide-react'
import { Badge } from 'ui'
import { LOG_TYPES } from '../../../UnifiedLogs.constants'
import { formatServiceTypeForDisplay } from '../../../UnifiedLogs.utils'
import { LEVELS } from '@/components/ui/DataTable/DataTable.constants'
type LogType = (typeof LOG_TYPES)[number]
type Level = (typeof LEVELS)[number]
export interface EventMessageProps {
message: string
severity?: Level
icon?: LucideIcon
serviceType?: LogType
}
export const EventMessage = ({
message,
severity,
icon: Icon = Database,
serviceType = 'postgres',
}: EventMessageProps) => {
const getSeverityIcon = (severity?: Level) => {
switch (severity) {
case 'error':
return 'text-destructive'
case 'warning':
return 'text-warning'
default:
return 'text-foreground-light'
}
}
return (
<div className="mt-3 border-t border-border pt-3">
<div className="flex items-center gap-2 mb-2">
<Icon size={14} className={getSeverityIcon(severity)} />
<span className="text-xs font-medium text-foreground-light">
{formatServiceTypeForDisplay(serviceType)} Event
{severity && (
<Badge
variant={
severity === 'error'
? 'destructive'
: severity === 'warning'
? 'warning'
: 'default'
}
className="ml-2"
>
{severity}
</Badge>
)}
</span>
</div>
<div className="p-3 rounded-lg border border-border bg-surface-100">
<div className="text-xs font-mono break-all whitespace-pre-wrap leading-relaxed max-h-32 overflow-y-auto">
{message}
</div>
</div>
</div>
)
}

View File

@@ -1,77 +0,0 @@
import { Auth, EdgeFunctions, Storage } from 'icons'
import { Clock, Database, Globe, LucideIcon, Server } from 'lucide-react'
import { getStatusLevel } from '../../../UnifiedLogs.utils'
import { DataTableColumnStatusCode } from '@/components/ui/DataTable/DataTableColumn/DataTableColumnStatusCode'
// Type for icon components (covers both lucide-react and our icon library)
type IconComponent = LucideIcon | React.ComponentType<any>
// Reusable styled icon component
export const StyledIcon = ({
icon: Icon,
title: _title,
}: {
icon: IconComponent
title: string
}) => (
<div className="flex items-center gap-2 bg-surface-300 rounded-sm p-0.5 border justify-center border-foreground-muted">
<Icon className="w-4 h-4 text-foreground-lighter" strokeWidth={1} />
</div>
)
export const TimelineStep = ({
title,
status,
statusText,
children,
isLast = false,
}: {
title: string
status?: number | string
statusText?: string
children: React.ReactNode
isLast?: boolean
}) => (
<>
<div className="relative">
{/* Timeline dot - positioned on the left timeline line */}
<div className="py-1 bg-surface-100/50 border-r border-t border-l rounded-t px-2">
<div>
<div className="flex flex-row justify-between">
<div className="flex items-center gap-2">
{title === 'Request started' && <StyledIcon icon={Clock} title={title} />}
{title === 'Network' && <StyledIcon icon={Globe} title={title} />}
{title === 'Data API' && <StyledIcon icon={Server} title={title} />}
{title === 'Authentication' && <StyledIcon icon={Auth} title={title} />}
{title === 'Edge Function' && <StyledIcon icon={EdgeFunctions} title={title} />}
{title === 'Storage' && <StyledIcon icon={Storage} title={title} />}
{title === 'Postgres' && <StyledIcon icon={Database} title={title} />}
{title === 'Response' && <StyledIcon icon={Clock} title={title} />}
<h3 className="text-sm text-foreground tracking-wide">{title}</h3>
</div>
{statusText && (
<span className="text-xs text-foreground-light tracking-wide">{statusText}</span>
)}
{status && (
<DataTableColumnStatusCode
value={status}
level={getStatusLevel(status)}
className="text-xs"
/>
)}
</div>
</div>
</div>
{/* Main section box */}
<div className="border rounded-b border-border">
{/* Content */}
<dl className="space-y-0 divide-y px-1 py-1 bg-surface-100/50">{children}</dl>
</div>
{!isLast && <div className="border-l h-3 ml-5"></div>}
</div>
</>
)

View File

@@ -24,23 +24,6 @@ const formatStorageDate = (dateString: string): string => {
// NETWORK FIELDS
// =============================================================================
// Field configurations - using filterable field IDs where possible
export const originFields: BlockFieldConfig[] = [
{
id: 'date', // Matches filterFields 'date' (timerange) - FILTERABLE
label: 'Time',
getValue: (data) => {
if (!data?.timestamp && !data?.date) return null
try {
const timestamp = data?.timestamp || data?.date
return new Date(timestamp).toLocaleString()
} catch {
return 'Invalid date'
}
},
},
]
// Primary Network Fields (Always Visible) - FILTERABLE
export const networkPrimaryFields: BlockFieldConfig[] = [
{

View File

@@ -14,7 +14,7 @@ import {
} from 'ui'
import { CodeBlock } from 'ui-patterns/CodeBlock'
import { PostgresFlowDetail } from './ServiceFlow/components/blocks/PostgresFlowDetail'
import { PostgresFlowDetail } from './ServiceFlow/components/PostgresFlowDetail'
import {
MemoizedEdgeFunctionBlock,
MemoizedGoTrueBlock,

View File

@@ -1,34 +1,11 @@
import { User } from 'lucide-react'
import { cn } from 'ui'
import { LOG_TYPES, METHODS, STATUS_CODE_LABELS } from './UnifiedLogs.constants'
import { ColumnSchema } from './UnifiedLogs.schema'
import { LogsMeta, SheetField } from './UnifiedLogs.types'
import { getLevelLabel } from './UnifiedLogs.utils'
import { LEVELS } from '@/components/ui/DataTable/DataTable.constants'
import { DataTableFilterField, Option } from '@/components/ui/DataTable/DataTable.types'
import { getLevelColor } from '@/components/ui/DataTable/DataTable.utils'
import { useFormatDateTime } from '@/lib/datetime'
const DateCell = (props: { date: ColumnSchema['date'] }) => {
const formatDateTime = useFormatDateTime()
const month = formatDateTime(props.date, 'MMM')
const day = formatDateTime(props.date, 'DD')
const year = formatDateTime(props.date, 'YYYY')
const time = formatDateTime(props.date, 'HH:mm:ss')
return (
<div className="font-mono whitespace-nowrap flex items-center gap-1 justify-end">
<span>{month}</span>
<span className="text-foreground/50">·</span>
<span>{day}</span>
<span className="text-foreground/50">·</span>
<span>{year}</span>
<span className="text-foreground/50">·</span>
<span>{time}</span>
</div>
)
}
// instead of filterFields, maybe just 'fields' with a filterDisabled prop?
// that way, we could have 'message' or 'headers' field with label and value as well as type!
@@ -152,38 +129,3 @@ export const filterFields = [
},
},
] satisfies DataTableFilterField<ColumnSchema>[]
export const sheetFields = [
{
id: 'id',
label: 'Request ID',
type: 'readonly',
skeletonClassName: 'w-64',
},
{
id: 'date',
label: 'Date',
type: 'timerange',
component: DateCell,
skeletonClassName: 'w-36',
},
{
id: 'auth_user',
label: 'Auth User',
type: 'readonly',
condition: (props) => Boolean(props.auth_user),
component: (props) => (
<div className="flex items-center gap-2">
<User size={14} className="text-foreground-lighter" />
<span className="font-mono">{props.auth_user}</span>
</div>
),
skeletonClassName: 'w-56',
},
{
id: 'pathname',
label: 'Pathname',
type: 'input',
skeletonClassName: 'w-56',
},
] satisfies SheetField<ColumnSchema, LogsMeta>[]

View File

@@ -445,99 +445,6 @@ ${cteName} AS (
`
}
export const getUnifiedLogsCountCTE = (): SafeLogSqlFragment => safeSql`
WITH unified_logs AS (
-- Single scan of edge_logs covering edge gateway, postgrest, and storage
select
id,
CASE
WHEN edge_logs_request.path LIKE '%/rest/%' THEN 'postgrest'
WHEN edge_logs_request.path LIKE '%/storage/%' THEN 'storage'
ELSE 'edge'
END as log_type,
CAST(edge_logs_response.status_code AS STRING) as status,
CASE
WHEN edge_logs_response.status_code BETWEEN 200 AND 299 THEN 'success'
WHEN edge_logs_response.status_code BETWEEN 400 AND 499 THEN 'warning'
WHEN edge_logs_response.status_code >= 500 THEN 'error'
ELSE 'success'
END as level,
edge_logs_request.path as pathname,
edge_logs_request.method as method
from edge_logs as el
cross join unnest(metadata) as edge_logs_metadata
cross join unnest(edge_logs_metadata.request) as edge_logs_request
cross join unnest(edge_logs_metadata.response) as edge_logs_response
union all
-- Postgres logs
select
id,
'postgres' as log_type,
CAST(pgl_parsed.sql_state_code AS STRING) as status,
CASE
WHEN pgl_parsed.error_severity = 'LOG' THEN 'success'
WHEN pgl_parsed.error_severity = 'WARNING' THEN 'warning'
WHEN pgl_parsed.error_severity = 'FATAL' THEN 'error'
WHEN pgl_parsed.error_severity = 'ERROR' THEN 'error'
ELSE null
END as level,
null as pathname,
null as method
from postgres_logs as pgl
cross join unnest(pgl.metadata) as pgl_metadata
cross join unnest(pgl_metadata.parsed) as pgl_parsed
union all
-- Edge function logs
select
fel.id,
'edge function' as log_type,
CAST(fel_response.status_code AS STRING) as status,
CASE
WHEN fel_response.status_code BETWEEN 200 AND 299 THEN 'success'
WHEN fel_response.status_code BETWEEN 400 AND 499 THEN 'warning'
WHEN fel_response.status_code >= 500 THEN 'error'
ELSE 'success'
END as level,
fel_request.pathname as pathname,
fel_request.method as method
from function_edge_logs as fel
cross join unnest(metadata) as fel_metadata
cross join unnest(fel_metadata.response) as fel_response
cross join unnest(fel_metadata.request) as fel_request
union all
-- Auth logs
select
el_in_al.id as id,
'auth' as log_type,
CAST(el_in_al_response.status_code AS STRING) as status,
CASE
WHEN el_in_al_response.status_code BETWEEN 200 AND 299 THEN 'success'
WHEN el_in_al_response.status_code BETWEEN 400 AND 499 THEN 'warning'
WHEN el_in_al_response.status_code >= 500 THEN 'error'
ELSE 'success'
END as level,
el_in_al_request.path as pathname,
el_in_al_request.method as method
from auth_logs as al
cross join unnest(metadata) as al_metadata
left join (
edge_logs as el_in_al
cross join unnest(metadata) as el_in_al_metadata
cross join unnest(el_in_al_metadata.response) as el_in_al_response
cross join unnest(el_in_al_response.headers) as el_in_al_response_headers
cross join unnest(el_in_al_metadata.request) as el_in_al_request
)
on al_metadata.request_id = el_in_al_response_headers.cf_ray
WHERE al_metadata.request_id is not null
)
`
export const getLogsCountQuery = (search: QuerySearchParamsType): SafeLogSqlFragment => {
const effectiveLogTypes = getEffectiveLogTypes(search)
const logTypeConditions = buildConditions(search, 'log_type')

View File

@@ -1,25 +1,10 @@
import type { inferParserType } from 'nuqs'
import type { ReactNode } from 'react'
import { LOG_TYPES, SEARCH_PARAMS_PARSER } from './UnifiedLogs.constants'
import { SEARCH_PARAMS_PARSER } from './UnifiedLogs.constants'
type Percentile = 50 | 75 | 90 | 95 | 99
export type LogType = (typeof LOG_TYPES)[number]
export type UnifiedLogSchema = {
id: string
timestamp: Date
log_type: LogType
code: string
level: string
path: string | null
event_message: string
method: string
api_role: string
auth_user: string | null
}
export type LogsMeta = {
currentPercentiles: Record<Percentile, number>
}
@@ -29,10 +14,6 @@ export type PageParam = { cursor: number; direction: 'next' | 'prev' } | undefin
export type SearchParamsType = inferParserType<typeof SEARCH_PARAMS_PARSER>
export type QuerySearchParamsType = Omit<SearchParamsType, 'uuid' | 'live'>
export type SearchParams = {
[key: string]: string | string[] | undefined
}
/** ----------------------------------------- */
export type SheetField<TData, TMeta = Record<string, unknown>> = {

View File

@@ -4,22 +4,6 @@ import { cn } from 'ui'
import { FacetMetadataSchema } from './UnifiedLogs.schema'
import { LEVELS } from '@/components/ui/DataTable/DataTable.constants'
export const logEventBus = {
listeners: new Map<string, Set<(rowId: string) => void>>(),
on(event: 'selectTraceTab', callback: (rowId: string) => void) {
if (!this.listeners.has(event)) {
this.listeners.set(event, new Set())
}
this.listeners.get(event)?.add(callback)
return () => this.listeners.get(event)?.delete(callback)
},
emit(event: 'selectTraceTab', rowId: string) {
this.listeners.get(event)?.forEach((callback) => callback(rowId))
},
}
export const getFacetedUniqueValues = <TData>(facets?: Record<string, FacetMetadataSchema>) => {
return (_table: TTable<TData>, columnId: string) => {
return new Map(facets?.[columnId]?.rows?.map(({ value, total }) => [value, total]) || [])

View File

@@ -1,106 +0,0 @@
import { Table } from '@tanstack/react-table'
import { HTMLAttributes, memo } from 'react'
import { cn, Skeleton } from 'ui'
import { SheetField } from '../UnifiedLogs.types'
import { DataTableFilterField } from '@/components/ui/DataTable/DataTable.types'
import { DataTableSheetRowAction } from '@/components/ui/DataTable/DataTableSheetRowAction'
interface SheetDetailsContentSkeletonProps<TData, TMeta> {
fields: SheetField<TData, TMeta>[]
}
const SheetDetailsContentSkeleton = <TData, TMeta>({
fields,
}: SheetDetailsContentSkeletonProps<TData, TMeta>) => {
return (
<dl className="divide-y">
{fields.map((field) => (
<div
key={field.id.toString()}
className="flex gap-4 py-2 text-sm justify-between items-center"
>
<dt className="shrink-0 text-muted-foreground">{field.label}</dt>
<div>
<Skeleton className={cn('h-5 w-52', field.skeletonClassName)} />
</div>
</div>
))}
</dl>
)
}
interface DataTableSheetContentProps<TData, TMeta> extends HTMLAttributes<HTMLDListElement> {
data?: TData
table: Table<TData>
fields: SheetField<TData, TMeta>[]
filterFields: DataTableFilterField<TData>[]
metadata?: TMeta & {
totalRows: number
filterRows: number
totalRowsFetched: number
}
}
export function DataTableSheetContent<TData, TMeta>({
data,
table,
className,
fields,
filterFields,
metadata,
...props
}: DataTableSheetContentProps<TData, TMeta>) {
if (!data) return <SheetDetailsContentSkeleton fields={fields} />
return (
<dl className={cn('divide-y', className)} {...props}>
{fields.map((field) => {
if (field.condition && !field.condition(data)) return null
const Component = field.component
const value = String(data[field.id])
return (
<div key={field.id.toString()}>
{field.type === 'readonly' ? (
<div
className={cn(
'flex gap-4 my-1 py-1 text-sm justify-between items-center w-full',
field.className
)}
>
<dt className="shrink-0 text-muted-foreground">{field.label}</dt>
<dd className="font-mono w-full text-right truncate">
{Component ? <Component {...data} metadata={metadata} /> : value}
</dd>
</div>
) : (
<DataTableSheetRowAction
fieldValue={field.id}
filterFields={filterFields}
value={value}
table={table}
className={cn(
'flex gap-4 my-1 py-1 text-sm justify-between items-center w-full',
field.className
)}
label={field.label}
>
<dt className="shrink-0 text-muted-foreground">{field.label}</dt>
<dd className="font-mono w-full text-right truncate">
{Component ? <Component {...data} metadata={metadata} /> : value}
</dd>
</DataTableSheetRowAction>
)}
</div>
)
})}
</dl>
)
}
export const MemoizedDataTableSheetContent = memo(DataTableSheetContent, (prev, next) => {
// REMINDER: only check if data is the same, rest is useless
return prev.data === next.data
}) as typeof DataTableSheetContent

View File

@@ -1,6 +1,6 @@
import { Auth, EdgeFunctions, Storage } from 'icons'
import { Box, Code2, Database } from 'lucide-react'
import { cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
import { Tooltip, TooltipContent, TooltipTrigger } from 'ui'
import { type LOG_TYPES } from '../UnifiedLogs.constants'
@@ -50,17 +50,3 @@ export const LogTypeIcon = ({
</Tooltip>
)
}
export const LogTypeIconWithText = ({
type,
size = 16,
strokeWidth = 1.5,
className,
}: LogTypeIconProps) => {
return (
<div className={cn('flex items-center gap-2', className)}>
<LogTypeIcon type={type} size={size} strokeWidth={strokeWidth} />
<span>{type}</span>
</div>
)
}