mirror of
https://github.com/supabase/supabase.git
synced 2026-10-13 05:09:12 +03:00
202 lines
7.4 KiB
TypeScript
202 lines
7.4 KiB
TypeScript
import { PermissionAction } from '@supabase/shared-types/out/constants'
|
|
import { BarChart2 } from 'lucide-react'
|
|
import Link from 'next/link'
|
|
import { useState } from 'react'
|
|
import { toast } from 'sonner'
|
|
|
|
import { FormActions } from 'components/ui/Forms/FormActions'
|
|
import { FormPanel } from 'components/ui/Forms/FormPanel'
|
|
import { FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms/FormSection'
|
|
import Panel from 'components/ui/Panel'
|
|
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
|
|
import { useProjectDetailQuery } from 'data/projects/project-detail-query'
|
|
import { useProjectUpdateMutation } from 'data/projects/project-update-mutation'
|
|
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
|
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
|
|
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
|
|
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
|
import {
|
|
AlertDescription_Shadcn_,
|
|
AlertTitle_Shadcn_,
|
|
Alert_Shadcn_,
|
|
Button,
|
|
Form,
|
|
Input,
|
|
WarningIcon,
|
|
} from 'ui'
|
|
import PauseProjectButton from './Infrastructure/PauseProjectButton'
|
|
import RestartServerButton from './Infrastructure/RestartServerButton'
|
|
|
|
export const General = () => {
|
|
const { data: project } = useSelectedProjectQuery()
|
|
const { data: organization } = useSelectedOrganizationQuery()
|
|
|
|
// [Joshen] Need to refactor to use RHF so we don't need manual error handlers like this
|
|
const [nameError, setNameError] = useState<string>()
|
|
|
|
const isBranch = Boolean(project?.parent_project_ref)
|
|
|
|
const { projectSettingsRestartProject } = useIsFeatureEnabled([
|
|
'project_settings:restart_project',
|
|
])
|
|
|
|
const formId = 'project-general-settings'
|
|
const initialValues = { name: project?.name ?? '', ref: project?.ref ?? '' }
|
|
const { can: canUpdateProject } = useAsyncCheckPermissions(PermissionAction.UPDATE, 'projects', {
|
|
resource: {
|
|
project_id: project?.id,
|
|
},
|
|
})
|
|
|
|
const { mutate: updateProject, isPending: isUpdating } = useProjectUpdateMutation()
|
|
|
|
const onSubmit = async (values: any, { resetForm }: any) => {
|
|
if (!project?.ref) return console.error('Ref is required')
|
|
|
|
if (values.name.length < 3) {
|
|
setNameError('Project name must be at least 3 characters long')
|
|
return
|
|
}
|
|
|
|
updateProject(
|
|
{ ref: project.ref, name: values.name.trim() },
|
|
{
|
|
onSuccess: ({ name }) => {
|
|
resetForm({ values: { name }, initialValues: { name } })
|
|
toast.success('Successfully saved settings')
|
|
},
|
|
}
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
{isBranch && (
|
|
<Alert_Shadcn_ variant="default" className="mb-6">
|
|
<WarningIcon />
|
|
<AlertTitle_Shadcn_>
|
|
You are currently on a preview branch of your project
|
|
</AlertTitle_Shadcn_>
|
|
<AlertDescription_Shadcn_>
|
|
Certain settings are not available while you're on a preview branch. To adjust your
|
|
project settings, you may return to your{' '}
|
|
<Link
|
|
href={`/project/${project?.parent_project_ref}/settings/general`}
|
|
className="text-brand"
|
|
>
|
|
main branch
|
|
</Link>
|
|
.
|
|
</AlertDescription_Shadcn_>
|
|
</Alert_Shadcn_>
|
|
)}
|
|
|
|
{project === undefined ? (
|
|
<GenericSkeletonLoader />
|
|
) : (
|
|
<Form id={formId} initialValues={initialValues} onSubmit={onSubmit}>
|
|
{({ handleReset, values, initialValues }: any) => {
|
|
const hasChanges = JSON.stringify(values) !== JSON.stringify(initialValues)
|
|
return (
|
|
<FormPanel
|
|
disabled={!canUpdateProject}
|
|
footer={
|
|
<div className="flex py-4 px-[var(--card-padding-x)]">
|
|
<FormActions
|
|
form={formId}
|
|
isSubmitting={isUpdating}
|
|
hasChanges={hasChanges}
|
|
handleReset={() => {
|
|
handleReset()
|
|
setNameError(undefined)
|
|
}}
|
|
helper={
|
|
!canUpdateProject
|
|
? "You need additional permissions to manage this project's settings"
|
|
: undefined
|
|
}
|
|
/>
|
|
</div>
|
|
}
|
|
>
|
|
<FormSection header={<FormSectionLabel>General settings</FormSectionLabel>}>
|
|
<FormSectionContent loading={false}>
|
|
<Input
|
|
id="name"
|
|
size="small"
|
|
label="Project name"
|
|
disabled={isBranch || !canUpdateProject}
|
|
onChange={() => setNameError(undefined)}
|
|
error={nameError}
|
|
/>
|
|
<Input copy disabled id="ref" size="small" label="Project ID" />
|
|
</FormSectionContent>
|
|
</FormSection>
|
|
</FormPanel>
|
|
)
|
|
}}
|
|
</Form>
|
|
)}
|
|
<div className="mt-6" id="restart-project">
|
|
<FormPanel>
|
|
<div className="flex flex-col py-4 px-[var(--card-padding-x)]">
|
|
<div className="flex flex-col @lg:flex-row @lg:justify-between @lg:items-center gap-4">
|
|
<div>
|
|
<p className="text-sm">
|
|
{projectSettingsRestartProject ? 'Restart project' : 'Restart database'}
|
|
</p>
|
|
<div className="max-w-[420px]">
|
|
<p className="text-sm text-foreground-light">
|
|
Your project will not be available for a few minutes.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<RestartServerButton />
|
|
</div>
|
|
</div>
|
|
<div
|
|
className="flex w-full flex-col @lg:flex-row @lg:justify-between @lg:items-center gap-4 px-[var(--card-padding-x)] py-4"
|
|
id="pause-project"
|
|
>
|
|
<div>
|
|
<p className="text-sm">Pause project</p>
|
|
<div className="max-w-[420px]">
|
|
<p className="text-sm text-foreground-light">
|
|
Your project will not be accessible while it is paused.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<PauseProjectButton />
|
|
</div>
|
|
</FormPanel>
|
|
</div>
|
|
{!isBranch && (
|
|
<div className="mt-6">
|
|
<Panel>
|
|
<Panel.Content>
|
|
<div className="flex flex-col @lg:flex-row @lg:justify-between @lg:items-center gap-4">
|
|
<div className="flex space-x-4">
|
|
<BarChart2 strokeWidth={2} />
|
|
<div>
|
|
<p className="text-sm">Project usage statistics have been moved</p>
|
|
<p className="text-foreground-light text-sm">
|
|
You may view your project's usage under your organization's settings
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<Button asChild type="default">
|
|
<Link href={`/org/${organization?.slug}/usage?projectRef=${project?.ref}`}>
|
|
View project usage
|
|
</Link>
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</Panel.Content>
|
|
</Panel>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|