diff --git a/apps/studio/components/interfaces/QueryInsights/hooks/useQueryInsightsTableColumns.tsx b/apps/studio/components/interfaces/QueryInsights/hooks/useQueryInsightsTableColumns.tsx
index 44ab6291afd..17708d338ce 100644
--- a/apps/studio/components/interfaces/QueryInsights/hooks/useQueryInsightsTableColumns.tsx
+++ b/apps/studio/components/interfaces/QueryInsights/hooks/useQueryInsightsTableColumns.tsx
@@ -8,7 +8,6 @@ import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
- DropdownMenuSeparator,
DropdownMenuTrigger,
Tooltip,
TooltipContent,
@@ -556,27 +555,25 @@ export function useQueryInsightsTableColumns({
buildPrompt={() => buildQueryInsightFixPrompt(row).prompt}
onOpenAssistant={() => handleAiSuggestedFix(row)}
copyLabel="Copy Markdown"
- extraDropdownItems={
- <>
- handleGoToLogs()} className="gap-2">
-
- Go to Logs
-
- {row.issueType === 'slow' && (
- {
- setSelectedTriageRow(props.rowIdx)
- setSheetView('explain')
- }}
- className="gap-2"
- >
-
- Explain
-
- )}
-
- >
- }
+ additionalDropdownItems={[
+ {
+ label: 'Go to Logs',
+ icon: ,
+ onClick: () => handleGoToLogs(),
+ },
+ ...(row.issueType === 'slow'
+ ? [
+ {
+ label: 'Explain',
+ icon: ,
+ onClick: () => {
+ setSelectedTriageRow(props.rowIdx)
+ setSheetView('explain')
+ },
+ },
+ ]
+ : []),
+ ]}
/>
)}
diff --git a/apps/studio/components/interfaces/UnifiedLogs/RowSelectionHeader.tsx b/apps/studio/components/interfaces/UnifiedLogs/RowSelectionHeader.tsx
new file mode 100644
index 00000000000..2edf080d685
--- /dev/null
+++ b/apps/studio/components/interfaces/UnifiedLogs/RowSelectionHeader.tsx
@@ -0,0 +1,114 @@
+import { AnimatePresence, motion } from 'framer-motion'
+import { Copy, X } from 'lucide-react'
+import { toast } from 'sonner'
+import {
+ copyToClipboard,
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from 'ui'
+
+import { type LogData } from '../Settings/Logs/Logs.types'
+import {
+ buildLogsPrompt,
+ formatLogsAsJson,
+ formatLogsAsMarkdown,
+} from '../Settings/Logs/Logs.utils'
+import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider'
+import { AiAssistantDropdown } from '@/components/ui/AiAssistantDropdown'
+import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
+import { useDataTable } from '@/components/ui/DataTable/providers/DataTableProvider'
+import { useAiAssistantStateSnapshot } from '@/state/ai-assistant-state'
+import { useSidebarManagerSnapshot } from '@/state/sidebar-manager-state'
+
+// TODO - format Logs as JSON, as markdown, and as prompt
+
+export const RowSelectionHeader = () => {
+ const { openSidebar } = useSidebarManagerSnapshot()
+ const aiSnap = useAiAssistantStateSnapshot()
+
+ const { table } = useDataTable()
+ const selectedRows = table.getSelectedRowModel().rows.map((x) => x.original) as LogData[]
+
+ const handleOpenAiAssistant = () => {
+ const prompt = buildLogsPrompt(selectedRows)
+ openSidebar(SIDEBAR_KEYS.AI_ASSISTANT)
+ aiSnap.newChat({ initialMessage: prompt })
+ }
+
+ const onCopy = (format: 'json' | 'markdown') => {
+ const text =
+ format === 'json' ? formatLogsAsJson(selectedRows) : formatLogsAsMarkdown(selectedRows)
+ copyToClipboard(text, () => {
+ toast.success(
+ `Copied ${selectedRows.length} log${selectedRows.length !== 1 ? 's' : ''} as ${format.toUpperCase()}`
+ )
+ })
+ }
+
+ return (
+
+
+ {selectedRows.length > 0 && (
+
+
+ {selectedRows.length} row{selectedRows.length > 1 ? 's' : ''} selected
+
+
+
+
+
+ }
+ className="w-7"
+ tooltip={{ content: { side: 'bottom', text: 'Copy selected logs' } }}
+ />
+
+
+ onCopy('json')} className="gap-2 text-xs">
+
+ Copy as JSON
+
+ onCopy('markdown')} className="gap-2 text-xs">
+
+ Copy as Markdown
+
+
+
+
+
buildLogsPrompt(selectedRows)}
+ onOpenAssistant={handleOpenAiAssistant}
+ telemetrySource="log_explorer"
+ />
+
+ }
+ className="px-1"
+ onClick={() => table.resetRowSelection()}
+ tooltip={{ content: { side: 'bottom', text: 'Clear selection' } }}
+ />
+
+
+ )}
+
+
+ )
+}
diff --git a/apps/studio/components/interfaces/UnifiedLogs/ServiceFlow/components/ServiceFlowPanelControls.tsx b/apps/studio/components/interfaces/UnifiedLogs/ServiceFlow/components/ServiceFlowPanelControls.tsx
index 07088400a03..cd421eee538 100644
--- a/apps/studio/components/interfaces/UnifiedLogs/ServiceFlow/components/ServiceFlowPanelControls.tsx
+++ b/apps/studio/components/interfaces/UnifiedLogs/ServiceFlow/components/ServiceFlowPanelControls.tsx
@@ -25,14 +25,12 @@ export const ServiceFlowPanelControls = ({
dock = 'bottom',
setDock,
}: ServiceFlowPanelControlsProps) => {
- const { table, rowSelection, isLoading } = useDataTable()
-
- const selectedRowKey = Object.keys(rowSelection)?.[0]
+ const { table, openRowId, setOpenRowId, isLoading } = useDataTable()
const selectedRowData = useMemo(() => {
- if (isLoading && !selectedRowKey) return
- return table.getCoreRowModel().flatRows.find((row) => row.id === selectedRowKey)
- }, [selectedRowKey, isLoading, table])
+ if (isLoading && !openRowId) return
+ return table.getCoreRowModel().flatRows.find((row) => row.id === openRowId)
+ }, [openRowId, isLoading, table])
const index = table.getCoreRowModel().flatRows.findIndex((row) => row.id === selectedRowData?.id)
@@ -49,20 +47,20 @@ export const ServiceFlowPanelControls = ({
)
const onPrev = useCallback(() => {
- if (prevId) table.setRowSelection({ [prevId]: true })
- }, [prevId, table])
+ if (prevId) setOpenRowId(prevId)
+ }, [prevId, setOpenRowId])
const onNext = useCallback(() => {
- if (nextId) table.setRowSelection({ [nextId]: true })
- }, [nextId, table])
+ if (nextId) setOpenRowId(nextId)
+ }, [nextId, setOpenRowId])
const onClose = useCallback(() => {
- table.resetRowSelection()
- }, [table])
+ setOpenRowId(undefined)
+ }, [setOpenRowId])
useEffect(() => {
const down = (e: KeyboardEvent) => {
- if (!selectedRowKey) return
+ if (!openRowId) return
const activeElement = document.activeElement
if (activeElement?.closest('[role="menu"]')) return
@@ -87,7 +85,7 @@ export const ServiceFlowPanelControls = ({
document.addEventListener('keydown', down)
return () => document.removeEventListener('keydown', down)
- }, [selectedRowKey, onNext, onPrev])
+ }, [openRowId, onNext, onPrev])
return (
diff --git a/apps/studio/components/interfaces/UnifiedLogs/UnifiedLogs.tsx b/apps/studio/components/interfaces/UnifiedLogs/UnifiedLogs.tsx
index ae1abc01f5b..a06406666aa 100644
--- a/apps/studio/components/interfaces/UnifiedLogs/UnifiedLogs.tsx
+++ b/apps/studio/components/interfaces/UnifiedLogs/UnifiedLogs.tsx
@@ -33,6 +33,7 @@ import { DownloadLogsButton } from './components/DownloadLogsButton'
import { LogsFilterBar } from './components/LogsFilterBar'
import { LogsListPanel } from './components/LogsListPanel'
import { TooltipLabel } from './components/TooltipLabel'
+import { RowSelectionHeader } from './RowSelectionHeader'
import { ServiceFlowPanel } from './ServiceFlowPanel'
import { SEARCH_PARAMS_PARSER } from './UnifiedLogs.constants'
import { filterFields as defaultFilterFields } from './UnifiedLogs.fields'
@@ -85,7 +86,6 @@ export const UnifiedLogs = () => {
const { sort, start, size, id, cursor, direction, live, ...filter } = search
const defaultColumnSorting = sort ? [sort] : []
const defaultColumnVisibility = { uuid: false }
- const defaultRowSelection = search.id ? { [search.id]: true } : {}
const defaultColumnFilters = Object.entries(filter)
.map(([key, value]) => ({ id: key, value }))
.filter(({ value }) => value ?? undefined)
@@ -106,7 +106,8 @@ export const UnifiedLogs = () => {
const [sorting, setSorting] = useState(defaultColumnSorting)
const [columnFilters, setColumnFilters] = useState(defaultColumnFilters)
- const [rowSelection, setRowSelection] = useState(defaultRowSelection)
+ const [rowSelection, setRowSelection] = useState({})
+ const [openRowId, setOpenRowId] = useState(search.id ?? undefined)
const [dock, setDock] = useLocalStorageQuery<'bottom' | 'right'>(
LOCAL_STORAGE_KEYS.UNIFIED_LOGS_DOCK,
@@ -222,7 +223,7 @@ export const UnifiedLogs = () => {
// Generate dynamic columns based on current data
const { columns: dynamicColumns, columnVisibility: dynamicColumnVisibility } = useMemo(() => {
- return generateDynamicColumns(flatData)
+ return generateDynamicColumns({ data: flatData })
}, [flatData])
const table: Table = useReactTable({
@@ -235,7 +236,7 @@ export const UnifiedLogs = () => {
rowSelection,
columnOrder,
},
- enableMultiRowSelection: false,
+ enableMultiRowSelection: true,
columnResizeMode: 'onChange',
filterFns: { inDateRange, arrSome },
meta: { getRowClassName },
@@ -253,12 +254,10 @@ export const UnifiedLogs = () => {
getFacetedMinMaxValues: getTTableFacetedMinMaxValues(),
})
- const selectedRowKey = Object.keys(rowSelection)?.[0]
const selectedRow = useMemo(() => {
if ((isLoading || isFetching) && !flatData.length) return
-
- return table.getCoreRowModel().flatRows.find((row) => row.id === selectedRowKey)
- }, [isLoading, isFetching, flatData.length, table, selectedRowKey])
+ return table.getCoreRowModel().flatRows.find((row) => row.id === openRowId)
+ }, [isLoading, isFetching, flatData.length, table, openRowId])
// REMINDER: this is currently needed for the cmdk search
// [Joshen] This is where facets are getting dynamically loaded
@@ -321,24 +320,20 @@ export const UnifiedLogs = () => {
useEffect(() => {
if (isLoading || isFetching) return
- const selectedRowId = Object.keys(rowSelection)?.[0]
- if (selectedRowId && !selectedRow) {
- // Clear both uuid and logId when no row is selected
+ if (openRowId && !selectedRow) {
+ // Clear both uuid and logId when the open row no longer exists in data
setSearch({ id: null })
- setRowSelection({})
- } else if (selectedRowId && selectedRow) {
- setSearch({
- id: selectedRowId,
- })
+ setOpenRowId(undefined)
+ } else if (openRowId && selectedRow) {
+ setSearch({ id: openRowId })
track('unified_logs_row_clicked', { logType: selectedRow.original.log_type })
- // Don't clear rowSelection here - let it persist to maintain the selection
- } else if (!selectedRowId && search.id) {
- // Clear the URL parameter when no row is selected
+ } else if (!openRowId && search.id) {
+ // Clear the URL parameter when no row is open
setSearch({ id: null })
}
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [rowSelection, selectedRow, isLoading, isFetching])
+ }, [openRowId, selectedRow, isLoading, isFetching])
const isMobile = useIsMobile()
const [isFilterBarOpen, setIsFilterBarOpen] = useState(!isMobile)
@@ -353,6 +348,10 @@ export const UnifiedLogs = () => {
}
}, [isMobile])
+ useEffect(() => {
+ table.resetRowSelection()
+ }, [searchParameters, table])
+
return (
{
columnFilters={columnFilters}
sorting={sorting}
rowSelection={rowSelection}
+ openRowId={openRowId}
+ setOpenRowId={setOpenRowId}
columnOrder={columnOrder}
columnVisibility={columnVisibility}
searchParameters={searchParameters}
@@ -431,6 +432,8 @@ export const UnifiedLogs = () => {
/>
+
+
{
- {!!selectedRow && (
+ {!!openRowId && !!selectedRow && (
<>
>
diff --git a/apps/studio/components/interfaces/UnifiedLogs/components/Columns.tsx b/apps/studio/components/interfaces/UnifiedLogs/components/Columns.tsx
index 165712c5587..98574cd488d 100644
--- a/apps/studio/components/interfaces/UnifiedLogs/components/Columns.tsx
+++ b/apps/studio/components/interfaces/UnifiedLogs/components/Columns.tsx
@@ -1,5 +1,5 @@
import { ColumnDef } from '@tanstack/react-table'
-import { Tooltip, TooltipContent, TooltipTrigger } from 'ui'
+import { Checkbox, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
import { STATUS_CODE_LABELS } from '../UnifiedLogs.constants'
import { ColumnFilterSchema, ColumnSchema } from '../UnifiedLogs.schema'
@@ -30,7 +30,7 @@ function shouldHideColumn(data: ColumnSchema[], columnKey: keyof ColumnSchema):
}
// Generate dynamic columns based on data
-export function generateDynamicColumns(data: ColumnSchema[]): {
+export function generateDynamicColumns({ data }: { data: ColumnSchema[] }): {
columns: ColumnDef[]
columnVisibility: Record
} {
@@ -39,6 +39,32 @@ export function generateDynamicColumns(data: ColumnSchema[]): {
const hideEventMessage = shouldHideColumn(data, 'event_message')
const columns: ColumnDef[] = [
+ {
+ accessorKey: 'select',
+ header: '',
+ cell: ({ row }) => {
+ return (
+
+ row.toggleSelected(!!value)}
+ onClick={(e) => e.stopPropagation()}
+ />
+
+ )
+ },
+ enableHiding: false,
+ enableResizing: false,
+ enableSorting: false,
+ filterFn: (_row, _columnId, _filterValue) => true,
+ size: 48,
+ minSize: 48,
+ maxSize: 48,
+ meta: {
+ cellClassName: 'w-[32px]',
+ headerClassName: 'w-[32px]',
+ },
+ },
// Level column - always visible
{
accessorKey: 'level',
@@ -243,4 +269,6 @@ export function generateDynamicColumns(data: ColumnSchema[]): {
}
// Static fallback columns
-export const UNIFIED_LOGS_COLUMNS: ColumnDef[] = generateDynamicColumns([]).columns
+export const UNIFIED_LOGS_COLUMNS: ColumnDef[] = generateDynamicColumns({
+ data: [],
+}).columns
diff --git a/apps/studio/components/ui/AiAssistantDropdown.tsx b/apps/studio/components/ui/AiAssistantDropdown.tsx
index e3652414c00..da2c95264fd 100644
--- a/apps/studio/components/ui/AiAssistantDropdown.tsx
+++ b/apps/studio/components/ui/AiAssistantDropdown.tsx
@@ -1,6 +1,7 @@
import { AiAssistantSource } from 'common/telemetry-constants'
import { Chatgpt, Claude } from 'icons'
import { Check, ChevronDown, Copy } from 'lucide-react'
+import Link from 'next/link'
import { ComponentProps, ReactNode, useEffect, useState } from 'react'
import {
AiIconAnimation,
@@ -41,7 +42,8 @@ const EXTERNAL_AI_TOOLS = [
export interface AiAssistantDropdownItem {
label: string
icon?: ReactNode
- onClick: () => void
+ href?: string
+ onClick?: () => void
}
export interface AiAssistantDropdownProps {
@@ -59,7 +61,6 @@ export interface AiAssistantDropdownProps {
tooltip?: string
copyLabel?: string
showExternalAI?: boolean
- extraDropdownItems?: ReactNode
additionalDropdownItems?: AiAssistantDropdownItem[]
}
@@ -78,7 +79,6 @@ export function AiAssistantDropdown({
tooltip,
copyLabel = 'Copy prompt',
showExternalAI = false,
- extraDropdownItems,
additionalDropdownItems,
}: AiAssistantDropdownProps) {
const track = useTrack()
@@ -150,11 +150,11 @@ export function AiAssistantDropdown({
/>
- {extraDropdownItems}
{showCopied ? : }
{showCopied ? 'Copied!' : copyLabel}
+
{showExternalAI && (
<>
@@ -170,13 +170,23 @@ export function AiAssistantDropdown({
))}
>
)}
+
{additionalDropdownItems && additionalDropdownItems.length > 0 && (
<>
{additionalDropdownItems.map((item, i) => (
- {item.icon}
- {item.label}
+ {item.href ? (
+
+ {item.icon}
+ {item.label}
+
+ ) : (
+ <>
+ {item.icon}
+ {item.label}
+ >
+ )}
))}
>
diff --git a/apps/studio/components/ui/DataTable/DataTable.utils.ts b/apps/studio/components/ui/DataTable/DataTable.utils.ts
index deec18fab97..5443a55599a 100644
--- a/apps/studio/components/ui/DataTable/DataTable.utils.ts
+++ b/apps/studio/components/ui/DataTable/DataTable.utils.ts
@@ -86,43 +86,3 @@ export function getLevelColor(
}
}
}
-
-export function getStatusColor(value?: number | string): Record<'text' | 'bg' | 'border', string> {
- switch (value) {
- case '1':
- case 'info':
- return {
- text: 'text-blue-500',
- bg: '',
- border: 'border-blue-200 dark:border-blue-800',
- }
- case '2':
- case 'success':
- return {
- text: 'text-foreground',
- bg: '',
- border: 'border-green-200 dark:border-green-800',
- }
- case '4':
- case 'warning':
- case 'redirect':
- return {
- text: 'text-warning',
- bg: 'bg-warning-300 dark:bg-warning-200',
- border: 'border border-warning-400/50 dark:border-warning-400/50',
- }
- case '5':
- case 'error':
- return {
- text: 'text-destructive',
- bg: 'bg-destructive-300 dark:bg-destructive-300/50',
- border: 'border border-destructive-400/50 dark:border-destructive-400/50',
- }
- default:
- return {
- text: 'text-foreground',
- bg: '',
- border: '',
- }
- }
-}
diff --git a/apps/studio/components/ui/DataTable/DataTableColumn/DataTableColumnLevelIndicator.tsx b/apps/studio/components/ui/DataTable/DataTableColumn/DataTableColumnLevelIndicator.tsx
index dde560e82d9..a4b8ed3ebcf 100644
--- a/apps/studio/components/ui/DataTable/DataTableColumn/DataTableColumnLevelIndicator.tsx
+++ b/apps/studio/components/ui/DataTable/DataTableColumn/DataTableColumnLevelIndicator.tsx
@@ -16,7 +16,7 @@ export const DataTableColumnLevelIndicator = ({
{
- const colors = getStatusColor(level)
+ const colorClassName = getStatusColor(level)
+
+ function getStatusColor(value?: number | string): string {
+ switch (value) {
+ case '1':
+ case 'info':
+ return 'text-blue-500'
+ case '2':
+ case 'success':
+ return 'text-foreground'
+ case '4':
+ case 'warning':
+ case 'redirect':
+ return 'text-warning'
+ case '5':
+ case 'error':
+ return 'text-destructive'
+ default:
+ return 'text-foreground'
+ }
+ }
+
if (!value) {
return
}
return (
-
diff --git a/apps/studio/components/ui/DataTable/DataTableInfinite.tsx b/apps/studio/components/ui/DataTable/DataTableInfinite.tsx
index e190f9d6dee..221466617b0 100644
--- a/apps/studio/components/ui/DataTable/DataTableInfinite.tsx
+++ b/apps/studio/components/ui/DataTable/DataTableInfinite.tsx
@@ -45,8 +45,8 @@ export function DataTableInfinite
({
setColumnVisibility,
searchParamsParser,
}: DataTableInfiniteProps) {
- const { table, error, isError, isLoading, isFetching } = useDataTable()
const tableRef = useRef(null)
+ const { table, error, isError, isLoading, isFetching, openRowId, setOpenRowId } = useDataTable()
const headerGroups = table.getHeaderGroups()
const headers = headerGroups[0].headers
@@ -128,7 +128,8 @@ export function DataTableInfinite({
row={row}
table={table}
searchParamsParser={searchParamsParser}
- selected={row.getIsSelected()}
+ selected={row.id === openRowId}
+ onSelect={() => setOpenRowId(row.id === openRowId ? undefined : row.id)}
/>
))
) : isLoading ? (
@@ -229,11 +230,13 @@ function DataTableRow({
table,
selected,
searchParamsParser,
+ onSelect,
}: {
row: Row
table: TTable
selected?: boolean
searchParamsParser: any
+ onSelect: () => void
}) {
useQueryState('live', searchParamsParser.live)
const rowClassName = (table.options.meta as any)?.getRowClassName?.(row)
@@ -244,11 +247,11 @@ function DataTableRow({
id={row.id}
tabIndex={0}
data-state={selected && 'selected'}
- onClick={() => row.toggleSelected()}
+ onClick={onSelect}
onKeyDown={(event) => {
if (event.key === 'Enter') {
event.preventDefault()
- row.toggleSelected()
+ onSelect()
}
}}
className={cn(rowClassName)}
diff --git a/apps/studio/components/ui/DataTable/Table.tsx b/apps/studio/components/ui/DataTable/Table.tsx
index 7b5c3d8798c..9f81520bbfe 100644
--- a/apps/studio/components/ui/DataTable/Table.tsx
+++ b/apps/studio/components/ui/DataTable/Table.tsx
@@ -79,7 +79,7 @@ export const TableHead = forwardRef<
className={cn(
'text-xs! font-normal! text-foreground-lighter font-mono',
'relative select-none truncate [&>.cursor-col-resize]:last:opacity-0',
- 'text-muted-foreground h-8 px-2 text-left align-middle [&:has([role=checkbox])]:pr-0 *:[[role=checkbox]]:translate-y-[2px]',
+ 'text-muted-foreground h-9 px-2 text-left align-middle [&:has([role=checkbox])]:pr-0 *:[[role=checkbox]]:translate-y-[2px]',
className
)}
{...props}
diff --git a/apps/studio/components/ui/DataTable/providers/DataTableProvider.tsx b/apps/studio/components/ui/DataTable/providers/DataTableProvider.tsx
index 9dfd396da82..b60950fe331 100644
--- a/apps/studio/components/ui/DataTable/providers/DataTableProvider.tsx
+++ b/apps/studio/components/ui/DataTable/providers/DataTableProvider.tsx
@@ -25,6 +25,8 @@ interface DataTableStateContextType {
pagination: PaginationState
enableColumnOrdering: boolean
searchParameters: QuerySearchParamsType
+ openRowId: string | undefined
+ setOpenRowId: (id: string | undefined) => void
}
interface DataTableBaseContextType {
@@ -63,6 +65,8 @@ export function DataTableProvider({
pagination: props.pagination ?? { pageIndex: 0, pageSize: 10 },
enableColumnOrdering: props.enableColumnOrdering ?? false,
searchParameters: props.searchParameters ?? ({} as any),
+ openRowId: props.openRowId,
+ setOpenRowId: props.setOpenRowId ?? (() => {}),
}),
[props]
)
diff --git a/apps/studio/components/ui/ErrorCodeTooltip/ErrorCodeTooltip.tsx b/apps/studio/components/ui/ErrorCodeTooltip/ErrorCodeTooltip.tsx
index 13fd2f4f850..83e5125a06f 100644
--- a/apps/studio/components/ui/ErrorCodeTooltip/ErrorCodeTooltip.tsx
+++ b/apps/studio/components/ui/ErrorCodeTooltip/ErrorCodeTooltip.tsx
@@ -1,17 +1,8 @@
import { ExternalLink } from 'lucide-react'
import { useTheme } from 'next-themes'
import Image from 'next/image'
-import Link from 'next/link'
import { useState } from 'react'
-import {
- cn,
- DropdownMenuItem,
- DropdownMenuSeparator,
- HoverCard,
- HoverCardContent,
- HoverCardTrigger,
- InfoIcon,
-} from 'ui'
+import { cn, HoverCard, HoverCardContent, HoverCardTrigger, InfoIcon } from 'ui'
import { ShimmeringLoader } from 'ui-patterns/ShimmeringLoader'
import { getErrorCodeInfo } from './ErrorCodeTooltip.utils'
@@ -117,25 +108,19 @@ export const ErrorCodeTooltip = ({ errorCode, service, children }: ErrorCodeTool
)}
-
-
-
- Go to Docs
-
-
-
- >
- ) : undefined
- }
+ additionalDropdownItems={[
+ {
+ label: 'Go to Docs',
+ icon: ,
+ href: docsUrl,
+ },
+ ]}
/>