Add restoration failure state

This commit is contained in:
Joshen Lim committed 2022-11-21 16:10:20 +08:00
1 parent 1bf5aea50e
commit 1925955fe2
4 files changed
+67 -38

No files matched your search

@@ -39,7 +39,7 @@ interface Props {
const SupportForm: FC<Props> = ({ setSentCategory }) => {
const { ui, app } = useStore()
const router = useRouter()
const { ref, category } = router.query
const { ref, subject, category } = router.query
const uploadButtonRef = useRef()
const enableFreeSupport = useFlag('enableFreeSupport')
@@ -82,7 +82,7 @@ const SupportForm: FC<Props> = ({ setSentCategory }) => {
const selectedProject = sortedProjects.find((project) => project.ref === ref)
const selectedCategory = CATEGORY_OPTIONS.find((option) => {
if (option.value.toLowerCase() === category) return option
if (option.value.toLowerCase() === ((category as string) ?? '').toLowerCase()) return option
})
const initialValues = {
category: selectedCategory !== undefined ? selectedCategory.value : CATEGORY_OPTIONS[0].value,
@@ -94,7 +94,7 @@ const SupportForm: FC<Props> = ({ setSentCategory }) => {
? sortedProjects[0].ref
: 'no-project',
library: 'no-library',
subject: '',
subject: subject ?? '',
message: '',
}
@@ -1,5 +1,6 @@
import Link from 'next/link'
import { FC, useEffect, useRef, useState } from 'react'
import { Button, IconCheckCircle, IconLoader } from 'ui'
import { Button, IconAlertCircle, IconCheckCircle, IconLoader } from 'ui'
import { useStore } from 'hooks'
import { API_URL, PROJECT_STATUS } from 'lib/constants'
@@ -13,6 +14,7 @@ const RestoringState: FC<Props> = ({}) => {
const checkServerInterval = useRef<number>()
const [loading, setLoading] = useState(false)
const [isFailed, setIsFailed] = useState(false)
const [isCompleted, setIsCompleted] = useState(false)
useEffect(() => {
@@ -28,7 +30,10 @@ const RestoringState: FC<Props> = ({}) => {
})
if (projectStatus && !projectStatus.error) {
const { status } = projectStatus
if (status === PROJECT_STATUS.ACTIVE_HEALTHY) {
if (status === PROJECT_STATUS.RESTORATION_FAILED) {
clearInterval(checkServerInterval.current)
setIsFailed(true)
} else if (status === PROJECT_STATUS.ACTIVE_HEALTHY) {
clearInterval(checkServerInterval.current)
setIsCompleted(true)
}
@@ -42,43 +47,66 @@ const RestoringState: FC<Props> = ({}) => {
return (
<div className="flex items-center justify-center h-full">
<div
className={[
'grid grid-cols-12 gap-4',
'bg-scale-300 border border-scale-400 rounded-md w-3/4 lg:w-1/2 px-8 py-6',
].join(' ')}
>
<div className="bg-scale-300 border border-scale-400 rounded-md w-3/4 lg:w-1/2">
{isCompleted ? (
<>
<div className="col-span-1">
<IconCheckCircle className="text-brand-900" strokeWidth={2} />
<div className="space-y-6 pt-6">
<div className="flex px-8 space-x-8">
<div className="mt-1">
<IconCheckCircle className="text-brand-900" size={18} strokeWidth={2} />
</div>
<div className="space-y-1">
<p>Restoration complete!</p>
<p className="text-sm text-scale-1100">
Your project has been successfully restored and is now back online.
</p>
</div>
</div>
<div className="col-span-11 space-y-1">
<p>Restoration complete!</p>
<p className="text-sm text-scale-1100">
Your project has been successfully restored and is now back online.
</p>
<div className="border-t border-scale-400 flex items-center justify-end py-4 px-8">
<Button disabled={loading} loading={loading} onClick={onConfirm}>
Return to project
</Button>
</div>
</>
</div>
) : isFailed ? (
<div className="space-y-6 pt-6">
<div className="flex px-8 space-x-8">
<div className="mt-1">
<IconAlertCircle size={18} strokeWidth={2} />
</div>
<div className="space-y-1">
<p>Something went wrong while restoring your project</p>
<p className="text-sm text-scale-1100">
Our engineers have already been notified of this, do hang tight while we are
investigating into the issue.
</p>
</div>
</div>
{isFailed && (
<div className="border-t border-scale-400 flex items-center justify-end py-4 px-8">
<Link
href={`/support/new?category=Database_unresponsive&ref=${project?.ref}&subject=Restoration%20failed%20for%20project`}
>
<a>
<Button type="default">Contact support</Button>
</a>
</Link>
</div>
)}
</div>
) : (
<>
<div className="col-span-1">
<IconLoader className="animate-spin" />
<div className="space-y-6 py-6">
<div className="flex px-8 space-x-8">
<div className="mt-1">
<IconLoader className="animate-spin" size={18} />
</div>
<div className="space-y-1">
<p>Restoration in progress</p>
<p className="text-sm text-scale-1100">
Restoration can take from a few minutes up to several hours depending on the size
of your database. Your project will be offline while the restoration is running.
</p>
</div>
</div>
<div className="col-span-11 space-y-1">
<p>Restoration in progress</p>
<p className="text-sm text-scale-1100">
Restoration can take from a few minutes up to several hours depending on the size of
your database. Your project will be offline while the restoration is running.
</p>
</div>
</>
)}
{isCompleted && (
<div className="col-start-2 col-span-11">
<Button disabled={loading} loading={loading} onClick={onConfirm}>
Return to project
</Button>
</div>
)}
</div>
+1
View File
@@ -105,6 +105,7 @@ export const PROJECT_STATUS = {
INIT_FAILED: 'INIT_FAILED',
REMOVED: 'REMOVED',
RESTORING: 'RESTORING',
RESTORATION_FAILED: 'RESTORATION_FAILED',
}
export const STRIPE_PRODUCT_IDS: { [x: string]: string } = {
+1 -1
View File
@@ -78,7 +78,7 @@ export default class ProjectStore extends PostgresMetaInterface<Project> {
async fetchSubscriptionTier(project: Project) {
const { id: projectId, ref: projectRef, status } = project
if (status === PROJECT_STATUS.ACTIVE_HEALTHY) {
if (status !== PROJECT_STATUS.REMOVED) {
const url = `${this.url}/${projectRef}/subscription`
const headers = constructHeaders(this.headers)
const response = await get(url, { headers })