DeleteCronJob.tsx108 lines · main
1import { parseAsString, useQueryState } from 'nuqs'
2import { useEffect } from 'react'
3import { toast } from 'sonner'
4import { ConfirmationModal } from 'ui-patterns/Dialogs/ConfirmationModal'
5
6import { parseCronJobCommand } from './CronJobs.utils'
7import { useCronJobsData } from './CronJobsTab.useCronJobsData'
8import { TextConfirmModal } from '@/components/ui/TextConfirmModalWrapper'
9import { useDatabaseCronJobDeleteMutation } from '@/data/database-cron-jobs/database-cron-jobs-delete-mutation'
10import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
11import { cleanPointerEventsNoneOnBody } from '@/lib/helpers'
12import { useTrack } from '@/lib/telemetry/track'
13
14export const DeleteCronJob = () => {
15 const { data: project } = useSelectedProjectQuery()
16
17 const [searchQuery] = useQueryState('search', parseAsString.withDefault(''))
18 const [cronJobIdForDeletion, setCronJobForDeletion] = useQueryState('delete', parseAsString)
19
20 const { grid } = useCronJobsData({
21 projectRef: project?.ref,
22 connectionString: project?.connectionString,
23 searchQuery,
24 })
25 const cronJob = grid.rows.find((j) => j.jobid.toString() === cronJobIdForDeletion)
26
27 const track = useTrack()
28 const {
29 mutate: deleteDatabaseCronJob,
30 isPending,
31 isSuccess: isSuccessDelete,
32 } = useDatabaseCronJobDeleteMutation({
33 onSuccess: () => {
34 if (cronJob && project) {
35 const { type } = parseCronJobCommand(cronJob.command, project.ref)
36 track('cron_job_removed', { type })
37 }
38 toast.success(`Successfully removed cron job`)
39 setCronJobForDeletion(null)
40 },
41 })
42
43 async function handleDelete() {
44 if (!project) return console.error('Project is required')
45 if (!cronJob) return console.error('Cron job is missing')
46
47 deleteDatabaseCronJob({
48 jobId: cronJob.jobid,
49 projectRef: project.ref,
50 connectionString: project.connectionString,
51 searchTerm: searchQuery,
52 })
53 }
54
55 useEffect(() => {
56 if (grid.isSuccess && !!cronJobIdForDeletion && !cronJob && !isSuccessDelete) {
57 toast('Cron job not found')
58 setCronJobForDeletion(null)
59 }
60 }, [cronJob, cronJobIdForDeletion, grid.isSuccess, isSuccessDelete, setCronJobForDeletion])
61
62 if (!cronJob) {
63 return null
64 }
65
66 // Cron job name is optional. If the cron job has no name, show a simplified modal which doesn't require the user to input the name.
67 if (!cronJob.jobname) {
68 return (
69 <ConfirmationModal
70 variant="destructive"
71 visible={!!cronJob}
72 onCancel={() => {
73 setCronJobForDeletion(null)
74 cleanPointerEventsNoneOnBody()
75 }}
76 onConfirm={handleDelete}
77 title={`Delete the cron job`}
78 loading={isPending}
79 confirmLabel={`Delete`}
80 alert={{ title: 'You cannot recover this cron job once deleted.' }}
81 />
82 )
83 }
84
85 return (
86 <TextConfirmModal
87 variant="destructive"
88 visible={!!cronJob}
89 onConfirm={handleDelete}
90 onCancel={() => {
91 setCronJobForDeletion(null)
92 cleanPointerEventsNoneOnBody()
93 }}
94 title="Delete this cron job"
95 loading={isPending}
96 confirmLabel={`Delete cron job ${cronJob.jobname}`}
97 confirmPlaceholder="Type in name of cron job"
98 confirmString={cronJob.jobname ?? 'Unknown'}
99 text={
100 <>
101 <span>This will delete the cron job</span>{' '}
102 <span className="text-bold text-foreground">{cronJob.jobname}</span>
103 </>
104 }
105 alert={{ title: 'You cannot recover this cron job once deleted.' }}
106 />
107 )
108}