import dayjs from 'dayjs' import { Clipboard, Edit, MoreVertical, Play, Trash } from 'lucide-react' import { parseAsString, useQueryState } from 'nuqs' import { useState } from 'react' import { toast } from 'sonner' import { useDatabaseCronJobRunCommandMutation } from 'data/database-cron-jobs/database-cron-job-run-mutation' import { CronJob } from 'data/database-cron-jobs/database-cron-jobs-infinite-query' import { useDatabaseCronJobToggleMutation } from 'data/database-cron-jobs/database-cron-jobs-toggle-mutation' import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Badge, Button, cn, CodeBlock, ContextMenu_Shadcn_, ContextMenuContent_Shadcn_, ContextMenuItem_Shadcn_, ContextMenuSeparator_Shadcn_, ContextMenuTrigger_Shadcn_, copyToClipboard, Dialog, DialogContent, DialogFooter, DialogHeader, DialogSection, DialogSectionSeparator, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, HoverCard, HoverCardContent, HoverCardTrigger, Switch, Tooltip, TooltipContent, TooltipTrigger, } from 'ui' import { TimestampInfo } from 'ui-patterns' import { getNextRun } from './CronJobs.utils' interface CronJobTableCellProps { col: any row: any onSelectEdit: (job: CronJob) => void onSelectDelete: (job: CronJob) => void } export const CronJobTableCell = ({ col, row, onSelectEdit, onSelectDelete, }: CronJobTableCellProps) => { const { data: project } = useSelectedProjectQuery() const [searchQuery] = useQueryState('search', parseAsString.withDefault('')) const [showToggleModal, setShowToggleModal] = useState(false) const value = row?.[col.id] const { jobid, schedule, latest_run, status, active, jobname } = row const formattedValue = col.id === 'jobname' && !jobname ? 'No name provided' : col.id === 'lastest_run' ? !!value ? dayjs(value).valueOf() : undefined : col.id === 'next_run' ? getNextRun(schedule, latest_run) : value const { mutate: runCronJob, isLoading: isRunning } = useDatabaseCronJobRunCommandMutation({ onSuccess: () => { toast.success(`Command from "${jobname}" ran successfully`) }, }) const { mutate: toggleDatabaseCronJob, isLoading: isToggling } = useDatabaseCronJobToggleMutation( { onSuccess: (_, vars) => { toast.success(`Successfully ${vars.active ? 'enabled' : 'disabled'} "${jobname}"`) setShowToggleModal(false) }, } ) const onRunCronJob = () => { runCronJob({ projectRef: project?.ref!, connectionString: project?.connectionString, jobId: jobid, }) } const onConfirmToggle = () => { toggleDatabaseCronJob({ projectRef: project?.ref!, connectionString: project?.connectionString, jobId: jobid, active: !active, searchTerm: searchQuery, }) } if (col.id === 'actions') { return (
) } if (col.id === 'active') { return ( e.stopPropagation()}> e.stopPropagation()} dialogOverlayProps={{ onClick: (e) => e.stopPropagation() }} > {active ? 'Disable' : 'Enable'} cron job

Are you sure you want to {active ? 'disable' : 'enable'} the cron job "{jobname}"?{' '}

) } return (
{['latest_run', 'next_run'].includes(col.id) ? ( col.id === 'latest_run' && formattedValue === null ? (

Job has not been run yet

) : col.id === 'next_run' && !formattedValue ? (

Unable to parse next run for job

) : ( ) ) : col.id === 'command' ? (
{formattedValue}
e.stopPropagation()} >

Command

code]:m-0 [&>code>span]:flex [&>code>span]:flex-wrap min-h-11', '[&>code]:text-xs' )} />
) : (

{formattedValue}

)} {col.id === 'latest_run' && !!status && ( {status} )}
e.stopPropagation()}> e.stopPropagation()} onSelect={() => copyToClipboard(formattedValue)} > Copy {col.name.toLowerCase()} e.stopPropagation()} onSelect={() => onSelectEdit(row)} >
Edit job
{!jobname && ( This cron job doesn’t have a name and can’t be edited. Create a new one and delete this job. )}
e.stopPropagation()} onSelect={() => onSelectDelete(row)} > Delete job
) }