mirror of
https://github.com/supabase/supabase.git
synced 2026-10-15 14:19:11 +03:00
* Migrate the CreateBucketModal to use RHF. * Minor fixes for the create bucket modal. * Use the bucket type from the API everywhere. * Improve the types on some functions. Add "skip" mode to FDWCreateMutation. * Expand the CreateBucketModal to explain what will happen when creating an iceberg bucket. * Add a page for iceberg buckets. * Add error states to the iceberg explorer. * Fix the names for the FDWs. * Add a dialog for setting up namespace. * Restructure the new files. * Add a download env button. * Add warning to install the wrappers extension when creating an iceberg bucket. * Add failover details when the FDW is not setup. * Fix a lint error. * Fix a type error. * Minor fixes. * Fix the server name. * Add an icon for iceberg buckets. * Fix the import foreign schema dialog. * Make the setup wrapper button functional. * Fix a bad useMemo dependency. * Small changes to the iceberg bucket page. * Minor fix for the edit wrapper sheet. * Rename the files from kebab-case to PascalCase. * Rename the files again to include Analytic instead of Iceberg. * Rename Iceberg type to Analytic. * Add a switch for creating namespace in the import foreign schema dialog. * Fix the CreateBucketModal. * Fix the delete modal feature. * Fix the S3 keys in the FDW. * Only create a namespace if the switch is true. * Regenerate and fix the types. * Fix the FDW create mutation to handle numbers in the FDW names. * Make the icon smaller. * Check whether the namespace exists, if it doesn't create it. * Hide action from the analytic bucket which don't work. * Invalidate namespaces when creating them. * Add small explanation for the creation of namespaces. * Minor fixes. * Tons of changes to make the namespace feature work. * Fix type errors. * Fix bad import. * Minor copy fixes. * Replace the multiple cards with a table of namespaces. * update copy icon * tiny copy update * Fix the empty state for foreign tables. * Hide the analytics bucket option for self-hosted. * Minor copy fixes. * Expand the CTA on no namespaces state. * More minor fixes. * More small fixes. --------- Co-authored-by: Alaister Young <a@alaisteryoung.com>
168 lines
5.1 KiB
TypeScript
168 lines
5.1 KiB
TypeScript
import { zodResolver } from '@hookform/resolvers/zod'
|
|
import { snakeCase } from 'lodash'
|
|
import { useEffect, useState } from 'react'
|
|
import { SubmitHandler, useForm } from 'react-hook-form'
|
|
import { toast } from 'sonner'
|
|
import z from 'zod'
|
|
|
|
import { useParams } from 'common'
|
|
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
|
|
import SchemaSelector from 'components/ui/SchemaSelector'
|
|
import { useFDWImportForeignSchemaMutation } from 'data/fdw/fdw-import-foreign-schema-mutation'
|
|
import {
|
|
Button,
|
|
Form_Shadcn_,
|
|
FormControl_Shadcn_,
|
|
FormField_Shadcn_,
|
|
Input_Shadcn_,
|
|
Modal,
|
|
} from 'ui'
|
|
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
|
|
import SchemaEditor from '../TableGridEditor/SidePanelEditor/SchemaEditor'
|
|
|
|
export interface ImportForeignSchemaDialogProps {
|
|
bucketName: string
|
|
namespace: string
|
|
excludedSchemas: string[]
|
|
wrapperValues: Record<string, string>
|
|
visible: boolean
|
|
onClose: () => void
|
|
}
|
|
|
|
const FormSchema = z.object({
|
|
bucketName: z.string().trim(),
|
|
sourceNamespace: z.string().trim(),
|
|
targetSchema: z.string().trim(),
|
|
})
|
|
|
|
export type ImportForeignSchemaForm = z.infer<typeof FormSchema>
|
|
|
|
export const ImportForeignSchemaDialog = ({
|
|
bucketName,
|
|
namespace,
|
|
excludedSchemas,
|
|
wrapperValues,
|
|
visible,
|
|
onClose,
|
|
}: ImportForeignSchemaDialogProps) => {
|
|
const { project } = useProjectContext()
|
|
const { ref } = useParams()
|
|
const [loading, setLoading] = useState(false)
|
|
const [createSchemaSheetOpen, setCreateSchemaSheetOpen] = useState(false)
|
|
|
|
const { mutateAsync: importForeignSchema } = useFDWImportForeignSchemaMutation({
|
|
onSuccess: () => {
|
|
toast.success(`Successfully connected ${bucketName} to the database.`)
|
|
onClose()
|
|
},
|
|
})
|
|
|
|
const form = useForm<ImportForeignSchemaForm>({
|
|
resolver: zodResolver(FormSchema),
|
|
defaultValues: {
|
|
bucketName,
|
|
sourceNamespace: namespace,
|
|
targetSchema: '',
|
|
},
|
|
})
|
|
|
|
const onSubmit: SubmitHandler<ImportForeignSchemaForm> = async (values) => {
|
|
if (!ref) return console.error('Project ref is required')
|
|
setLoading(true)
|
|
|
|
try {
|
|
await importForeignSchema({
|
|
projectRef: ref,
|
|
connectionString: project?.connectionString,
|
|
serverName: `${snakeCase(values.bucketName)}_fdw_server`,
|
|
sourceSchema: values.sourceNamespace,
|
|
targetSchema: values.targetSchema,
|
|
})
|
|
} catch (error: any) {
|
|
// error will be handled by the mutation onError callback
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (visible) {
|
|
form.reset({
|
|
bucketName,
|
|
sourceNamespace: namespace,
|
|
targetSchema: '',
|
|
})
|
|
}
|
|
}, [visible, form, bucketName, namespace])
|
|
|
|
return (
|
|
<Modal
|
|
hideFooter
|
|
visible={visible}
|
|
size="medium"
|
|
header={
|
|
<span>
|
|
Connect namespace <span className="text-brand">{namespace}</span>
|
|
</span>
|
|
}
|
|
onCancel={() => onClose()}
|
|
>
|
|
<Form_Shadcn_ {...form}>
|
|
<form onSubmit={form.handleSubmit(onSubmit)}>
|
|
<Modal.Content className="flex flex-col gap-y-4">
|
|
<FormField_Shadcn_
|
|
control={form.control}
|
|
name="sourceNamespace"
|
|
render={({ field }) => (
|
|
<FormItemLayout label="Namespace" layout="vertical">
|
|
<FormControl_Shadcn_>
|
|
<Input_Shadcn_ {...field} placeholder="Enter namespace name" disabled />
|
|
</FormControl_Shadcn_>
|
|
</FormItemLayout>
|
|
)}
|
|
/>
|
|
|
|
<FormField_Shadcn_
|
|
control={form.control}
|
|
name="targetSchema"
|
|
render={({ field }) => (
|
|
<FormItemLayout
|
|
label="Target Schema"
|
|
description="Select the database schema where the Iceberg data will be accessible. Each schema can only be connected to one namespace."
|
|
layout="vertical"
|
|
>
|
|
<SchemaSelector
|
|
portal={false}
|
|
size="small"
|
|
selectedSchemaName={field.value}
|
|
excludedSchemas={excludedSchemas}
|
|
onSelectSchema={(schema) => field.onChange(schema)}
|
|
onSelectCreateSchema={() => setCreateSchemaSheetOpen(true)}
|
|
/>
|
|
</FormItemLayout>
|
|
)}
|
|
/>
|
|
</Modal.Content>
|
|
<Modal.Separator />
|
|
<Modal.Content className="flex items-center space-x-2 justify-end">
|
|
<Button type="default" htmlType="button" disabled={loading} onClick={onClose}>
|
|
Cancel
|
|
</Button>
|
|
<Button type="primary" htmlType="submit" loading={loading}>
|
|
Save
|
|
</Button>
|
|
</Modal.Content>
|
|
</form>
|
|
</Form_Shadcn_>
|
|
<SchemaEditor
|
|
visible={createSchemaSheetOpen}
|
|
closePanel={() => setCreateSchemaSheetOpen(false)}
|
|
onSuccess={(schema) => {
|
|
form.setValue('targetSchema', schema)
|
|
setCreateSchemaSheetOpen(false)
|
|
}}
|
|
/>
|
|
</Modal>
|
|
)
|
|
}
|