import dayjs from 'dayjs' import { BookOpen, Check, ChevronDown, Clipboard, ExternalLink, X } from 'lucide-react' import Link from 'next/link' import { ReactNode, useState } from 'react' import { IS_PLATFORM } from 'common' import Table from 'components/to-be-cleaned/Table' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' import { useFlag } from 'hooks/ui/useFlag' import { logConstants } from 'shared-data' import { Badge, Button, copyToClipboard, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, SidePanel, Tabs, Tooltip, TooltipContent, TooltipTrigger, } from 'ui' import { EXPLORER_DATEPICKER_HELPERS, LOGS_SOURCE_DESCRIPTION, LogsTableName, } from './Logs.constants' import { DatePickerValue, LogsDatePicker } from './Logs.DatePickers' import { LogsWarning, LogTemplate, WarehouseCollection } from './Logs.types' import { WarehouseQueryTemplate } from './Warehouse.utils' export type SourceType = 'logs' | 'warehouse' export interface LogsQueryPanelProps { templates?: LogTemplate[] warehouseTemplates?: WarehouseQueryTemplate[] defaultFrom: string defaultTo: string warnings: LogsWarning[] warehouseCollections: WarehouseCollection[] dataSource: SourceType onSelectTemplate: (template: LogTemplate) => void onSelectWarehouseTemplate: (template: WarehouseQueryTemplate) => void onSelectSource: (source: string) => void onDateChange: (value: DatePickerValue) => void onDataSourceChange: (sourceType: SourceType) => void } function DropdownMenuItemContent({ name, desc }: { name: ReactNode; desc?: string }) { return (
{name}
{desc &&
{desc}
}
) } const LogsQueryPanel = ({ templates = [], warehouseTemplates = [], defaultFrom, defaultTo, warnings, warehouseCollections, dataSource, onSelectTemplate, onSelectWarehouseTemplate, onSelectSource, onDateChange, onDataSourceChange, }: LogsQueryPanelProps) => { const [showReference, setShowReference] = useState(false) const { projectAuthAll: authEnabled, projectStorageAll: storageEnabled, projectEdgeFunctionAll: edgeFunctionsEnabled, } = useIsFeatureEnabled(['project_auth:all', 'project_storage:all', 'project_edge_function:all']) const warehouseEnabled = useFlag('warehouse') const logsTableNames = Object.entries(LogsTableName) .filter(([key]) => { if (key === 'AUTH') return authEnabled if (key === 'STORAGE') return storageEnabled if (key === 'FN_EDGE') return edgeFunctionsEnabled if (key === 'PG_CRON') return false if (key === 'WAREHOUSE') return false return true }) .map(([, value]) => value) function getDefaultDatePickerValue() { if (defaultFrom && defaultTo) { return { to: defaultTo, from: defaultFrom, text: `${dayjs(defaultFrom).format('DD MMM, HH:mm')} - ${dayjs(defaultTo).format('DD MMM, HH:mm')}`, isHelper: false, } } return { to: EXPLORER_DATEPICKER_HELPERS[0].calcTo(), from: EXPLORER_DATEPICKER_HELPERS[0].calcFrom(), text: EXPLORER_DATEPICKER_HELPERS[0].text, isHelper: true, } } const [selectedDatePickerValue, setSelectedDatePickerValue] = useState( getDefaultDatePickerValue() ) return (
{warehouseEnabled && ( onDataSourceChange('logs')}> onDataSourceChange('warehouse')}> Collections NEW } desc="Query your collections" /> )} {dataSource === 'warehouse' && ( {warehouseTemplates.map((template) => ( onSelectWarehouseTemplate(template)} > ))} {warehouseCollections.length === 0 && ( )} )} {dataSource === 'logs' && ( {dataSource === 'logs' && logsTableNames .sort((a, b) => a.localeCompare(b)) .map((source) => ( onSelectSource(source)}> ))} )} {dataSource === 'logs' && IS_PLATFORM && ( {templates .sort((a, b) => a.label!.localeCompare(b.label!)) .map((template) => ( onSelectTemplate(template)} >

{template.label}

))}
)} {dataSource === 'logs' && ( { setSelectedDatePickerValue(value) onDateChange(value) }} helpers={EXPLORER_DATEPICKER_HELPERS} /> )}
0 ? 'opacity-100' : 'invisible h-0 w-0 opacity-0' }`} > {warnings.length} {warnings.length > 1 ? 'warnings' : 'warning'} {warnings.map((warning, index) => (

{warning.text}{' '} {warning.link && ( {warning.linkText || 'View'} )}

))}
{dataSource === 'logs' && (

Field Reference

} visible={showReference} cancelText="Close" onCancel={() => setShowReference(false)} hideFooter triggerElement={ } >

The following table shows all the available paths that can be queried from each respective source. Do note that to access nested keys, you would need to perform the necessary{' '} unnesting joins

{logConstants.schemas.map((schema) => ( Path , Type , ]} body={schema.fields .sort((a: any, b: any) => a.path - b.path) .map((field) => ( ))} /> ))} )} ) } const Field = ({ field, }: { field: { path: string type: string } }) => { const [isCopied, setIsCopied] = useState(false) return ( copyToClipboard(field.path, () => { setIsCopied(true) setTimeout(() => setIsCopied(false), 3000) }) } > {field.path} {isCopied ? ( Copied ) : ( Copy value )} {field.type} ) } export default LogsQueryPanel