import { useParams } from 'common' import dayjs from 'dayjs' import { CircleCheck, CircleX, Loader } from 'lucide-react' import { useMemo } from 'react' import DataGrid, { Column, Row } from 'react-data-grid' import { cn, LoadingLine, Tooltip, TooltipContent, TooltipTrigger } from 'ui' import { TimestampInfo } from 'ui-patterns' import { CodeBlock } from 'ui-patterns/CodeBlock' import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader' import { calculateDuration, formatDate } from './CronJobs.utils' import CronJobsEmptyState from './CronJobsEmptyState' import { CronJobRun, useCronJobRunsInfiniteQuery, } from '@/data/database-cron-jobs/database-cron-jobs-runs-infinite-query' import { useInfiniteScroll } from '@/hooks/misc/useInfiniteScroll' import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject' const cronJobColumns = [ { id: 'runid', name: 'RunID', minWidth: 30, width: 30, value: (row: CronJobRun) => (

{row.runid}

), }, { id: 'message', name: 'Message', minWidth: 200, value: (row: CronJobRun) => (
{row.return_message ? ( {row.return_message}

Message

code]:m-0 [&>code>span]:flex [&>code>span]:flex-wrap min-h-11', '[&>code]:text-xs' )} />
) : ( - )}
), }, { id: 'status', name: 'Status', minWidth: 75, value: (row: CronJobRun) => , }, { id: 'start_time', name: 'Start Time', minWidth: 120, value: (row: CronJobRun) =>
{formatDate(row.start_time)}
, }, { id: 'end_time', name: 'End Time', minWidth: 120, value: (row: CronJobRun) => (
{row.end_time ? formatDate(row.end_time) : '-'}
), }, { id: 'duration', name: 'Duration', minWidth: 100, value: (row: CronJobRun) => (
{row.start_time && row.end_time ? calculateDuration(row.start_time, row.end_time) : ''}
), }, ] const columns = cronJobColumns.map((col) => { const result: Column = { key: col.id, name: col.name, resizable: true, minWidth: col.minWidth ?? 120, headerCellClass: undefined, renderHeaderCell: () => { return (

{col.name}

) }, renderCell: (props) => { const value = col.value(props.row) if (['start_time', 'end_time'].includes(col.id)) { const rawValue = (props.row as any)[(col as any).id] if (rawValue) { const formattedValue = dayjs(rawValue).valueOf() return (
) } } return value }, } return result }) export const PreviousRunsTab = () => { const { childId } = useParams() const { data: project } = useSelectedProjectQuery() const jobId = Number(childId) const { data, isPending: isLoadingCronJobRuns, isFetching, isFetchingNextPage, hasNextPage, fetchNextPage, } = useCronJobRunsInfiniteQuery( { projectRef: project?.ref, connectionString: project?.connectionString, jobId: jobId, }, { enabled: !!jobId, staleTime: 30000 } ) const cronJobRuns = useMemo(() => data?.pages.flatMap((p) => p) || [], [data?.pages]) const handleScroll = useInfiniteScroll({ isLoading: isLoadingCronJobRuns, isFetchingNextPage, hasNextPage, fetchNextPage, }) return (
{ return cn( 'cursor-pointer', '[&>.rdg-cell]:border-box [&>.rdg-cell]:outline-hidden [&>.rdg-cell]:shadow-none', '[&>.rdg-cell:first-child>div]:ml-8' ) }} renderers={{ renderRow(_idx, props) { return }, noRowsFallback: isLoadingCronJobRuns ? (
) : (
), }} />
) } interface StatusBadgeProps { status: string } function StatusBadge({ status }: StatusBadgeProps) { if (status === 'succeeded') { return ( Succeeded ) } if (status === 'failed') { return ( Failed ) } if (['running', 'starting', 'sending', 'connecting'].includes(status)) { return ( Running ) } return null }