Files
supabase/studio/components/layouts/ProjectLayout/ConnectingState.tsx
Jonathan Summers-Muir 8f74b500d8 Update ConnectingState.tsx
2022-07-21 09:54:47 +08:00

150 lines
5.5 KiB
TypeScript

import Link from 'next/link'
import { FC, useEffect, useRef, useState } from 'react'
import { observer } from 'mobx-react-lite'
import { Badge, Button, IconLoader, IconMonitor, IconServer, Modal } from '@supabase/ui'
import { Project } from 'types'
import { useStore } from 'hooks'
import ShimmerLine from 'components/ui/ShimmerLine'
import pingPostgrest from 'lib/pingPostgrest'
interface Props {
project: Project
}
const ConnectingState: FC<Props> = ({ project }) => {
const { app } = useStore()
const checkProjectConnectionIntervalRef = useRef<number>()
const [showHelperButton, setShowHelperButton] = useState(false)
const [showModal, setShowModal] = useState(false)
// Show helper button if still connecting after 30 seconds
useEffect(() => {
const timer = setTimeout(() => setShowHelperButton(true), 30000)
return () => clearTimeout(timer)
}, [])
useEffect(() => {
if (!project.restUrl) return
// Check project connection status every 4 seconds
// pingPostgrest timeouts in 2s, wait for another 2s before checking again
checkProjectConnectionIntervalRef.current = window.setInterval(testProjectConnection, 4000)
return () => {
clearInterval(checkProjectConnectionIntervalRef.current)
}
}, [project])
const testProjectConnection = async () => {
const result = await pingPostgrest(project.restUrl!, project.ref, {
kpsVersion: project.kpsVersion,
})
if (result) {
clearInterval(checkProjectConnectionIntervalRef.current)
app.onProjectPostgrestStatusUpdated(project.id, 'ONLINE')
}
}
return (
<>
<div className="mx-auto my-16 w-full max-w-7xl space-y-16">
<div className="mx-6 space-y-16">
<div className="flex flex-col space-y-4 lg:flex-row lg:items-center lg:space-y-0 lg:space-x-6">
<h1 className="text-3xl">{project.name}</h1>
<div>
<Badge color="brand">
<div className="flex items-center gap-2">
<IconLoader className="animate-spin" size={12} />
<span>Connecting to project</span>
</div>
</Badge>
</div>
</div>
<div className="bg-scale-300 border-scale-400 flex h-[500px] items-center justify-center rounded border p-8">
<div className="w-[420px] space-y-4">
<div className="mx-auto flex max-w-[300px] items-center justify-center space-x-4 lg:space-x-8">
<IconMonitor className="text-scale-1100" size={50} strokeWidth={1.5} />
<ShimmerLine active />
<IconServer className="text-scale-1100" size={50} strokeWidth={1.5} />
</div>
<div className="space-y-1">
<p className="text-center">Connecting to {project.name}</p>
<p
className="text-scale-1100 cursor-pointer text-center text-sm opacity-60 transition hover:opacity-100"
onClick={() => setShowModal(true)}
>
This may take a few minutes
</p>
</div>
<div className="flex flex-col items-center">
{showHelperButton && (
<Button type="default" onClick={() => setShowModal(true)}>
Still connecting?
</Button>
)}
</div>
</div>
</div>
</div>
</div>
<Modal
visible={showModal}
onCancel={() => setShowModal(false)}
header={
<div className="flex items-baseline gap-2">
<h5 className="text-scale-1200 text-sm">Checking the health of your database</h5>
</div>
}
size="medium"
hideFooter
closable
>
<div className="py-4">
<Modal.Content>
<div className="space-y-4">
<p className="text-scale-1200 text-sm">
Your project might be facing resource constraints and hence is having trouble
connecting. You can verify this by checking your{' '}
<span className="text-brand-1000">
<Link href={`/project/${project.ref}/settings/database`}>
<a>database's health</a>
</Link>
</span>{' '}
or your remaining daily disk IO budget via a{' '}
<span className="text-brand-1000">
<Link href={`/project/${project.ref}/reports`}>
<a>customizable project report</a>
</Link>
</span>
.
</p>
<p className="text-scale-1200 text-sm">
If your project is facing resource constraints, you can{' '}
<span className="text-brand-1000">
<Link href={`/project/${project.ref}/reports`}>
<a>upgrade</a>
</Link>
</span>{' '}
your project's subscription to a Pro for access to larger compute sizes.
</p>
<p className="text-scale-1200 text-sm">
However, if your project still fails to connect thereafter, you can open a support
ticket{' '}
<span className="text-brand-1000">
<Link href={`/support/new?ref=${project.ref}`}>here</Link>
</span>
.
</p>
</div>
</Modal.Content>
</div>
</Modal>
</>
)
}
export default observer(ConnectingState)