// @ts-nocheck import { useParams } from 'common' import { Loader2 } from 'lucide-react' import { useRouter } from 'next/router' import { parseAsBoolean, parseAsString, useQueryState } from 'nuqs' import { MouseEvent, useEffect, useMemo, useState } from 'react' import { toast } from 'sonner' import { LoadingLine } from 'ui' import { formatCronJobColumns } from './CronJobs.utils' import { CronJobRunDetailsOverflowNotice } from './CronJobsTab.CleanupNotice' import { CronJobsTabDataGrid } from './CronJobsTab.DataGrid' import { CronJobsTabHeader } from './CronJobsTab.Header' import { useCronJobsData } from './CronJobsTab.useCronJobsData' import { DeleteCronJob } from './DeleteCronJob' import { CreateCronJobSheet } from '@/components/interfaces/Integrations/CronJobs/CreateCronJobSheet/CreateCronJobSheet' import { CronJob } from '@/data/database-cron-jobs/database-cron-jobs-infinite-query' import { useSendEventMutation } from '@/data/telemetry/send-event-mutation' import { useInfiniteScroll } from '@/hooks/misc/useInfiniteScroll' import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization' import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject' import { cleanPointerEventsNoneOnBody } from '@/lib/helpers' import { createNavigationHandler } from '@/lib/navigation' const EMPTY_CRON_JOB = { jobname: '', schedule: '', active: true, command: '' } export const CronjobsTab = () => { const router = useRouter() const { ref } = useParams() const { data: project } = useSelectedProjectQuery() const { data: org } = useSelectedOrganizationQuery() const [searchQuery, setSearchQuery] = useQueryState('search', parseAsString.withDefault('')) const [search, setSearch] = useState(searchQuery) const handleSearchSubmit = () => { const trimmed = search.trim() setSearchQuery(trimmed.length > 0 ? trimmed : null) } const handleClearSearch = () => { setSearch('') setSearchQuery(null) } const { grid, count } = useCronJobsData({ projectRef: project?.ref, connectionString: project?.connectionString, searchQuery, }) const [createCronJobSheetShown, setCreateCronJobSheetShown] = useQueryState( 'new', parseAsBoolean.withDefault(false).withOptions({ clearOnDefault: true }) ) const [cronJobIdForEditing, setCronJobForEditing] = useQueryState('edit', parseAsString) const cronJobForEditing = grid.rows.find((j) => j.jobid.toString() === cronJobIdForEditing) const [, setCronJobForDeletion] = useQueryState('delete', parseAsString) const { mutate: sendEvent } = useSendEventMutation() const columns = useMemo( () => formatCronJobColumns({ onSelectEdit: (job: CronJob) => { sendEvent({ action: 'cron_job_update_clicked', groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' }, }) setCronJobForEditing(job.jobid.toString()) }, onSelectDelete: (job: CronJob) => { sendEvent({ action: 'cron_job_delete_clicked', groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' }, }) setCronJobForDeletion(job.jobid.toString()) }, }), [org?.slug, ref, sendEvent, setCronJobForEditing, setCronJobForDeletion] ) const handleScroll = useInfiniteScroll({ isLoading: grid.isLoading, isFetchingNextPage: grid.isFetchingNextPage, hasNextPage: grid.hasNextPage, fetchNextPage: grid.fetchNextPage, }) const onOpenCreateJobSheet = () => { sendEvent({ action: 'cron_job_create_clicked', groups: { project: project?.ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' }, }) setCreateCronJobSheetShown(true) } // Row click handler const handleRowClick = (row: CronJob, event: MouseEvent) => { const { jobid, jobname } = row const url = `/project/${ref}/integrations/cron/jobs/${jobid}?child-label=${encodeURIComponent( jobname || `Job #${jobid}` )}` sendEvent({ action: 'cron_job_history_clicked', groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' }, }) createNavigationHandler(url, router)(event) } const onClose = () => { setCronJobForEditing(null) setCreateCronJobSheetShown(false) cleanPointerEventsNoneOnBody(500) } useEffect(() => { if (grid.isSuccess && !!cronJobIdForEditing && !cronJobForEditing) { toast('Cron job not found') setCronJobForEditing(null) } }, [cronJobForEditing, cronJobIdForEditing, grid.isSuccess, setCronJobForEditing]) return ( <>
{grid.isMinimal && ( )}
) } // Footer component for displaying job count interface CronJobsFooterProps { count: { value: number | undefined isEstimate: boolean isLoading: boolean } } const CronJobsFooter = ({ count }: CronJobsFooterProps) => (
{count.isLoading ? ( Loading... ) : ( `Total: ${count.value ?? 0} jobs${count.isEstimate ? ' (estimate)' : ''}` )}
)