Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions apps/docs/content/_partials/migration_warnings.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

- If you're planning to migrate a database larger than 6 GB, we recommend [upgrading to at least a Large compute add-on](/docs/guides/platform/compute-add-ons). This will ensure you have the necessary resources to handle the migration efficiently.

- For databases smaller than 150 GB, you can increase the size of the disk on paid projects by navigating to the [Compute and Disk Settings](dashboard/project/_/settings/compute-and-disk) page.

- If you're dealing with a database larger than 150 GB, we strongly advise you to [contact our support team](/dashboard/support/new) for assistance in provisioning the required resources and ensuring a smooth migration process.
- We strongly advise you to pre-provision the disk space you will need for your migration. On paid projects, you can do this by navigating to the [Compute and Disk Settings](https://supabase.com/dashboard/project/_/settings/compute-and-disk) page. For more information on disk scaling and disk limits, check out our [disk settings](https://supabase.com/docs/guides/platform/compute-and-disk#disk) documentation.

</Admonition>
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { PropsWithChildren, ReactNode } from 'react'
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
import ShimmeringLoader from 'components/ui/ShimmeringLoader'
import type { Branch } from 'data/branches/branches-query'
import { BASE_PATH } from 'lib/constants'
import { Tooltip, TooltipContent, TooltipTrigger } from 'ui'
import { WorkflowLogs } from './WorkflowLogs'

Expand Down Expand Up @@ -87,7 +88,7 @@ export const BranchRow = ({

const handleRowClick = () => {
if (external) {
window.open(navigateUrl, '_blank', 'noopener noreferrer')
window.open(`${BASE_PATH}/${navigateUrl}`, '_blank', 'noopener noreferrer')
} else {
router.push(navigateUrl)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const ProjectTableRow = ({
className="cursor-pointer hover:bg-surface-200"
onClick={(event) => {
if (event.metaKey) {
window.open(url, '_blank')
window.open(`${BASE_PATH}/${url}`, '_blank')
} else {
router.push(url)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { toast } from 'sonner'
import z from 'zod'

import { useWatch } from '@ui/components/shadcn/ui/form'
import { useParams } from 'common'
import { urlRegex } from 'components/interfaces/Auth/Auth.constants'
import EnableExtensionModal from 'components/interfaces/Database/Extensions/EnableExtensionModal'
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
Expand Down Expand Up @@ -201,11 +202,13 @@ export const CreateCronJobSheet = ({
setIsClosing,
onClose,
}: CreateCronJobSheetProps) => {
const { childId } = useParams()
const { data: project } = useSelectedProjectQuery()
const { data: org } = useSelectedOrganizationQuery()
const [searchQuery] = useQueryState('search', parseAsString.withDefault(''))
const [isLoadingGetCronJob, setIsLoadingGetCronJob] = useState(false)

const jobId = Number(childId)
const isEditing = !!selectedCronJob?.jobname
const [showEnableExtensionModal, setShowEnableExtensionModal] = useState(false)

Expand Down Expand Up @@ -340,6 +343,8 @@ export const CreateCronJobSheet = ({
connectionString: project?.connectionString,
query,
searchTerm: searchQuery,
// [Joshen] Only need to invalidate a specific cron job if in the job's previous run tab
identifier: !!jobId ? jobId : undefined,
},
{
onSuccess: () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import { toString as CronToString } from 'cronstrue'
import { Edit3, List } from 'lucide-react'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useState } from 'react'

import { useParams } from 'common'
import { NavigationItem, PageLayout } from 'components/layouts/PageLayout/PageLayout'
import { useCronJobQuery } from 'data/database-cron-jobs/database-cron-job-query'
import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import {
Button,
cn,
CodeBlock,
Sheet,
SheetContent,
Tooltip,
TooltipContent,
TooltipTrigger,
} from 'ui'
import ShimmeringLoader from 'ui-patterns/ShimmeringLoader'
import { CreateCronJobSheet } from './CreateCronJobSheet'
import { isSecondsFormat, parseCronJobCommand } from './CronJobs.utils'
import { PreviousRunsTab } from './PreviousRunsTab'

export const CronJobPage = () => {
const router = useRouter()
const { ref, id, pageId, childId } = useParams()
const childLabel = router?.query?.['child-label'] as string
const { data: project } = useSelectedProjectQuery()

const [isEditSheetOpen, setIsEditSheetOpen] = useState(false)
const [isClosing, setIsClosing] = useState(false)

const jobId = Number(childId)

const { data: job, isLoading } = useCronJobQuery({
projectRef: project?.ref,
connectionString: project?.connectionString,
id: jobId,
})

const { data: edgeFunctions = [] } = useEdgeFunctionsQuery({ projectRef: project?.ref })

// Parse the cron job command to check if it's an edge function
const cronJobValues = parseCronJobCommand(job?.command || '', project?.ref!)
const edgeFunction =
cronJobValues.type === 'edge_function' ? cronJobValues.edgeFunctionName : undefined
const edgeFunctionSlug = edgeFunction?.split('/functions/v1/').pop()
const isValidEdgeFunction = edgeFunctions.some((x) => x.slug === edgeFunctionSlug)

const breadcrumbItems = [
{
label: 'Integrations',
href: `/project/${ref}/integrations`,
},
{
label: 'Cron',
href: pageId
? `/project/${ref}/integrations/${id}/${pageId}`
: `/project/${ref}/integrations/${id}`,
},
{
label: childLabel ?? job?.jobname ?? '',
},
]

const navigationItems: NavigationItem[] = []

const pageTitle = childLabel || childId || 'Cron Job'

const pageSubtitle = job ? (
<div className="text-sm text-foreground-light">
Running{' '}
<Tooltip>
<TooltipTrigger asChild>
<span className="cursor-pointer underline decoration-dotted lowercase">
{isSecondsFormat(job.schedule)
? job.schedule.toLowerCase()
: CronToString(job.schedule.toLowerCase())}
</span>
</TooltipTrigger>
<TooltipContent side="bottom" align="center">
<div className="text-xs">
<p className="font-mono mb-1">{job.schedule.toLowerCase()}</p>
{!isSecondsFormat(job.schedule) && (
<p className="text-foreground-light">{CronToString(job.schedule.toLowerCase())}</p>
)}
</div>
</TooltipContent>
</Tooltip>{' '}
with command{' '}
<Tooltip>
<TooltipTrigger asChild>
<code className="text-xs font-mono bg-surface-200 px-1 py-0.5 rounded max-w-[200px] inline-block truncate align-bottom cursor-pointer">
{job.command}
</code>
</TooltipTrigger>
<TooltipContent
side="bottom"
align="center"
className="min-w-[200px] max-w-[400px] text-wrap p-0"
>
<p className="text-xs font-mono px-2 py-1 border-b bg-surface-100">Command</p>
<CodeBlock
hideLineNumbers
language="sql"
value={job.command.trim()}
className={cn(
'py-0 px-3.5 max-w-full prose dark:prose-dark border-0 rounded-t-none',
'[&>code]:m-0 [&>code>span]:flex [&>code>span]:flex-wrap min-h-11',
'[&>code]:text-xs'
)}
/>
</TooltipContent>
</Tooltip>
</div>
) : null

// Secondary actions
const secondaryActions = [
<Button
key="edit"
type="outline"
icon={<Edit3 strokeWidth={1.5} size="14" />}
onClick={() => setIsEditSheetOpen(true)}
>
Edit
</Button>,
<Button key="view-logs" asChild type="outline" icon={<List strokeWidth={1.5} size="14" />}>
<Link
target="_blank"
rel="noopener noreferrer"
href={`/project/${project?.ref}/logs/pgcron-logs/`}
>
View Cron logs
</Link>
</Button>,
...(isValidEdgeFunction
? [
<Button key="view-edge-logs" asChild type="outline">
<Link
target="_blank"
rel="noopener noreferrer"
href={`/project/${project?.ref}/functions/${edgeFunctionSlug}/logs`}
>
View Edge Function logs
</Link>
</Button>,
]
: []),
]

return (
<>
<PageLayout
title={pageTitle}
size="full"
breadcrumbs={breadcrumbItems}
navigationItems={navigationItems}
secondaryActions={secondaryActions}
subtitle={isLoading ? <ShimmeringLoader className="py-0 h-[20px] w-96" /> : pageSubtitle}
className="border-b-0"
>
<PreviousRunsTab />
</PageLayout>

<Sheet open={isEditSheetOpen} onOpenChange={setIsEditSheetOpen}>
<SheetContent size="lg">
{job && (
<CreateCronJobSheet
selectedCronJob={{
jobname: job.jobname,
schedule: job.schedule,
active: job.active,
command: job.command,
}}
supportsSeconds={true}
isClosing={isClosing}
setIsClosing={setIsClosing}
onClose={() => {
setIsEditSheetOpen(false)
setIsClosing(false)
}}
/>
)}
</SheetContent>
</Sheet>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-ex
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { BASE_PATH } from 'lib/constants'
import { isAtBottom } from 'lib/helpers'
import { Button, cn, LoadingLine, Sheet, SheetContent } from 'ui'
import { Input } from 'ui-patterns/DataInputs/Input'
Expand Down Expand Up @@ -211,7 +212,7 @@ export const CronjobsTab = () => {
})

if (e.metaKey) {
window.open(url, '_blank')
window.open(`${BASE_PATH}/${url}`, '_blank')
} else {
router.push(url)
}
Expand Down
Loading
Loading