fix(studio): project resume dialog (#41300)

* move desc to body

* better copy

* loading label

* smol gap change

* nit

* Nit

* NIt

* Attemt

* fix

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
This commit is contained in:
Danny WhiteandJoshen Lim authored and GitHub committed 2025-12-15 11:15:24 +11:00
1 parent 3a41846044
commit ad2ac05d7d
5 files changed
+67 -52

No files matched your search

@@ -19,7 +19,7 @@ import {
DropdownMenuItem,
DropdownMenuTrigger,
} from 'ui'
import { Admonition } from 'ui-patterns'
import { Admonition, TimestampInfo } from 'ui-patterns'
export const PauseDisabledState = () => {
const { ref } = useParams()
@@ -121,10 +121,10 @@ export const PauseDisabledState = () => {
<Admonition
showIcon={false}
type="warning"
className="rounded-none border-0 px-6"
className="rounded-none border-0 px-6 [&>div>div>div]:flex [&>div>div>div]:flex-col [&>div>div>div]:gap-y-3"
title="Project can no longer be restored through the dashboard"
>
<p className="!leading-normal !mb-3">
<p className="!leading-normal">
This project has been paused for over{' '}
<span className="text-foreground">
{pauseStatus?.max_days_till_restore_disabled ?? 90} days
@@ -133,6 +133,17 @@ export const PauseDisabledState = () => {
downloaded as a backup.
</p>
{!!pauseStatus?.last_paused_on && (
<p className="text-foreground-lighter text-sm">
Project last paused on{' '}
<TimestampInfo
className="text-sm"
labelFormat="DD MMM YYYY"
utcTimestamp={pauseStatus.last_paused_on}
/>
</p>
)}
<div>
<p className="!leading-normal !mb-1">Recovery options:</p>
<ul className="flex flex-col gap-y-0.5">
@@ -93,7 +93,7 @@ export const ProjectPausedState = ({ product }: ProjectPausedStateProps) => {
const { mutate: restoreProject, isPending: isRestoring } = useProjectRestoreMutation({
onSuccess: (_, variables) => {
setProjectStatus({ ref: variables.ref, status: PROJECT_STATUS.RESTORING })
toast.success('Restoring project')
toast.success('Restoring project, project will be ready in a few minutes')
},
})
@@ -185,11 +185,21 @@ export const ProjectPausedState = ({ product }: ProjectPausedStateProps) => {
). After that, this project will not be resumable, but data will still be
available for download.
</p>
<p className="text-sm text-foreground-lighter mt-4">
<p className="text-sm mt-4">
{enableProBenefitWording === 'variant-a'
? 'Upgrade to Pro to prevent pauses and unlock features like branching, compute upgrades, and daily backups.'
: 'To prevent future pauses, consider upgrading to Pro.'}
</p>
{!!pauseStatus.last_paused_on && (
<p className="text-foreground-lighter text-sm">
Project last paused on{' '}
<TimestampInfo
className="text-sm"
labelFormat="DD MMM YYYY"
utcTimestamp={pauseStatus.last_paused_on}
/>
</p>
)}
</>
) : (
<p className="text-sm">
@@ -264,43 +274,46 @@ export const ProjectPausedState = ({ product }: ProjectPausedStateProps) => {
<ConfirmationModal
visible={showConfirmRestore}
size="medium"
size="small"
title="Resume this project"
description={
isFreePlan
? "Your project's data will be restored to when it was initially paused."
: "Your project's data will be restored and billing will resume based on compute size and hours active."
}
onCancel={() => setShowConfirmRestore(false)}
onConfirm={() => form.handleSubmit(onConfirmRestore)()}
loading={isRestoring}
confirmLabel="Confirm resume"
confirmLabel="Resume"
confirmLabelLoading="Resuming"
cancelLabel="Cancel"
>
<Form_Shadcn_ {...form}>
<form onSubmit={form.handleSubmit(onConfirmRestore)}>
{showPostgresVersionSelector && (
<div className="space-y-2">
<FormField_Shadcn_
control={form.control}
name="postgresVersionSelection"
render={({ field }) => (
<PostgresVersionSelector
field={field}
form={form}
type="unpause"
label="Select the version of Postgres to resume to"
layout="vertical"
dbRegion={region?.displayName ?? ''}
cloudProvider={(project?.cloud_provider ?? 'AWS') as CloudProvider}
organizationSlug={selectedOrganization?.slug}
/>
)}
/>
</div>
)}
</form>
</Form_Shadcn_>
<div className={cn(showPostgresVersionSelector && 'flex flex-col gap-y-4')}>
<p className="text-sm">
{isFreePlan
? 'Your project’s data will be restored to when it was initially paused.'
: 'Your project’s data will be restored and billing will resume based on compute size and hours active.'}
</p>
<Form_Shadcn_ {...form}>
<form onSubmit={form.handleSubmit(onConfirmRestore)}>
{showPostgresVersionSelector && (
<div className="space-y-2">
<FormField_Shadcn_
control={form.control}
name="postgresVersionSelection"
render={({ field }) => (
<PostgresVersionSelector
field={field}
form={form}
type="unpause"
label="Postgres version"
layout="vertical"
dbRegion={region?.displayName ?? ''}
cloudProvider={(project?.cloud_provider ?? 'AWS') as CloudProvider}
organizationSlug={selectedOrganization?.slug}
/>
)}
/>
</div>
)}
</form>
</Form_Shadcn_>
</div>
</ConfirmationModal>
<Dialog
@@ -1,18 +1,18 @@
import { useParams } from 'common'
import { Badge } from 'ui'
import { Circle, Loader } from 'lucide-react'
import { useEffect, useState } from 'react'
import { useParams } from 'common'
import { useInvalidateProjectsInfiniteQuery } from 'data/projects/org-projects-infinite-query'
import { Project, useInvalidateProjectDetailsQuery } from 'data/projects/project-detail-query'
import { useProjectStatusQuery } from 'data/projects/project-status-query'
import { PROJECT_STATUS } from 'lib/constants'
import { Circle, Loader } from 'lucide-react'
import { useEffect, useState } from 'react'
import { Badge } from 'ui'
export interface PausingStateProps {
project: Project
}
const PausingState = ({ project }: PausingStateProps) => {
export const PausingState = ({ project }: PausingStateProps) => {
const { ref } = useParams()
const [startPolling, setStartPolling] = useState(false)
@@ -33,9 +33,7 @@ const PausingState = ({ project }: PausingStateProps) => {
useEffect(() => {
if (!isProjectStatusSuccess) return
if (projectStatusData?.status === PROJECT_STATUS.INACTIVE) {
if (ref) {
invalidateProjectDetailsQuery(ref)
}
if (ref) invalidateProjectDetailsQuery(ref)
invalidateProjectsQuery()
}
}, [
@@ -85,5 +83,3 @@ const PausingState = ({ project }: PausingStateProps) => {
</div>
)
}
export default PausingState
@@ -41,10 +41,6 @@ const RestoringState = () => {
if (!isProjectStatusSuccess) return
if (projectStatusData.status === PROJECT_STATUS.ACTIVE_HEALTHY) {
setIsCompleted(true)
} else {
if (ref) {
invalidateProjectDetailsQuery(ref)
}
}
}, [isProjectStatusSuccess, projectStatusData, ref, invalidateProjectDetailsQuery])
@@ -70,7 +66,6 @@ const RestoringState = () => {
const onConfirm = async () => {
if (!project) return console.error('Project is required')
setLoading(true)
if (ref) await invalidateProjectDetailsQuery(ref)
}
@@ -23,7 +23,7 @@ import ConnectingState from './ConnectingState'
import { LoadingState } from './LoadingState'
import { ProjectPausedState } from './PausedState/ProjectPausedState'
import { PauseFailedState } from './PauseFailedState'
import PausingState from './PausingState'
import { PausingState } from './PausingState'
import ProductMenuBar from './ProductMenuBar'
import { ResizingState } from './ResizingState'
import RestartingState from './RestartingState'