@@ -2,18 +2,17 @@ import { isEmpty } from 'lodash'
22import { useMemo , useState } from 'react'
33import { toast } from 'sonner'
44
5- import SchemaEditor from 'components/interfaces/TableGridEditor/SidePanelEditor/SchemaEditor'
65import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
76import { FormSection , FormSectionContent , FormSectionLabel } from 'components/ui/Forms/FormSection'
8- import SchemaSelector from 'components/ui/SchemaSelector '
7+ import { useSchemaCreateMutation } from 'data/database/schema-create-mutation '
98import { useSchemasQuery } from 'data/database/schemas-query'
109import { useFDWCreateMutation } from 'data/fdw/fdw-create-mutation'
1110import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
11+ import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
1212import {
1313 Button ,
1414 Form ,
1515 Input ,
16- Label_Shadcn_ ,
1716 RadioGroupStacked ,
1817 RadioGroupStackedItem ,
1918 Separator ,
@@ -25,7 +24,6 @@ import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
2524import { CreateWrapperSheetProps } from './CreateWrapperSheet'
2625import InputField from './InputField'
2726import { makeValidateRequired } from './Wrappers.utils'
28- import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
2927
3028const FORM_ID = 'create-wrapper-form'
3129
@@ -68,12 +66,11 @@ export const CreateIcebergWrapperSheet = ({
6866 const org = useSelectedOrganization ( )
6967 const { mutate : sendEvent } = useSendEventMutation ( )
7068
71- const [ createSchemaSheetOpen , setCreateSchemaSheetOpen ] = useState ( false )
7269 const [ selectedTarget , setSelectedTarget ] = useState < Target > ( 'S3Tables' )
7370
7471 const [ formErrors , setFormErrors ] = useState < { [ k : string ] : string } > ( { } )
7572
76- const { mutate : createFDW , isLoading : isCreating } = useFDWCreateMutation ( {
73+ const { mutateAsync : createFDW , isLoading : isCreatingWrapper } = useFDWCreateMutation ( {
7774 onSuccess : ( ) => {
7875 toast . success ( `Successfully created ${ wrapperMeta ?. label } foreign data wrapper` )
7976 onClose ( )
@@ -100,8 +97,10 @@ export const CreateIcebergWrapperSheet = ({
10097 }
10198 } , [ wrapperMetaOriginal , selectedTarget ] )
10299
103- // prefetch schemas to make sure the schema selector is populated
104- useSchemasQuery ( { projectRef : project ?. ref , connectionString : project ?. connectionString } )
100+ const { data : schemas } = useSchemasQuery ( {
101+ projectRef : project ?. ref ! ,
102+ connectionString : project ?. connectionString ,
103+ } )
105104
106105 const initialValues = {
107106 wrapper_name : '' ,
@@ -113,41 +112,72 @@ export const CreateIcebergWrapperSheet = ({
113112 ) ,
114113 }
115114
115+ const { mutateAsync : createSchema , isLoading : isCreatingSchema } = useSchemaCreateMutation ( )
116+
116117 const onSubmit = async ( values : any ) => {
117118 const validate = makeValidateRequired ( wrapperMeta . server . options )
118119 const errors : any = validate ( values )
119120
120121 if ( values . source_schema . length === 0 ) {
121- errors . source_schema = 'Please provide a source schema '
122+ errors . source_schema = 'Please provide a namespace name '
122123 }
123124 if ( values . wrapper_name . length === 0 ) {
124125 errors . wrapper_name = 'Please provide a name for your wrapper'
125126 }
126- if ( ! isEmpty ( errors ) ) return setFormErrors ( errors )
127127
128- createFDW ( {
129- projectRef : project ?. ref ,
130- connectionString : project ?. connectionString ,
131- wrapperMeta,
132- formState : { ...values , server_name : `${ values . wrapper_name } _server` } ,
133- mode : 'schema' ,
134- tables : [ ] ,
135- sourceSchema : values . source_schema ,
136- targetSchema : values . target_schema ,
137- } )
128+ if ( values . target_schema . length === 0 ) {
129+ errors . target_schema = 'Please provide an unique target schema'
130+ }
131+ const foundSchema = schemas ?. find ( ( s ) => s . name === values . target_schema )
132+ if ( foundSchema ) {
133+ errors . target_schema = 'This schema already exists. Please specify a unique schema name.'
134+ }
138135
139- sendEvent ( {
140- action : 'foreign_data_wrapper_created' ,
141- properties : {
142- wrapperType : wrapperMeta . label ,
143- } ,
144- groups : {
145- project : project ?. ref ?? 'Unknown' ,
146- organization : org ?. slug ?? 'Unknown' ,
147- } ,
148- } )
136+ setFormErrors ( errors )
137+ if ( ! isEmpty ( errors ) ) {
138+ return
139+ }
140+
141+ try {
142+ await createSchema ( {
143+ projectRef : project ?. ref ,
144+ connectionString : project ?. connectionString ,
145+ name : values . target_schema ,
146+ } )
147+
148+ await createFDW ( {
149+ projectRef : project ?. ref ,
150+ connectionString : project ?. connectionString ,
151+ wrapperMeta,
152+ formState : {
153+ ...values ,
154+ server_name : `${ values . wrapper_name } _server` ,
155+ supabase_target_schema : values . target_schema ,
156+ } ,
157+ mode : 'schema' ,
158+ tables : [ ] ,
159+ sourceSchema : values . source_schema ,
160+ targetSchema : values . target_schema ,
161+ } )
162+
163+ sendEvent ( {
164+ action : 'foreign_data_wrapper_created' ,
165+ properties : {
166+ wrapperType : wrapperMeta . label ,
167+ } ,
168+ groups : {
169+ project : project ?. ref ?? 'Unknown' ,
170+ organization : org ?. slug ?? 'Unknown' ,
171+ } ,
172+ } )
173+ } catch ( error ) {
174+ console . error ( error )
175+ // The error will be handled by the mutation onError callback (toast.error)
176+ }
149177 }
150178
179+ const isLoading = isCreatingWrapper || isCreatingSchema
180+
151181 return (
152182 < >
153183 < div className = "h-full" tabIndex = { - 1 } >
@@ -272,7 +302,8 @@ export const CreateIcebergWrapperSheet = ({
272302 < FormSectionLabel >
273303 < p > Foreign Schema</ p >
274304 < p className = "text-foreground-light mt-2 w-[90%]" >
275- All wrapper tables will be created in the specified target schema.
305+ You can query your data from the foreign tables in the specified schema
306+ after the wrapper is created.
276307 </ p >
277308 </ FormSectionLabel >
278309 }
@@ -292,18 +323,21 @@ export const CreateIcebergWrapperSheet = ({
292323 </ div >
293324 ) }
294325 < div className = "flex flex-col gap-2" >
295- < Label_Shadcn_ className = "text-foreground-light" >
296- Target Schema
297- </ Label_Shadcn_ >
298- < SchemaSelector
299- portal = { false }
300- size = "small"
301- selectedSchemaName = { values . target_schema }
302- onSelectSchema = { ( schema ) => setFieldValue ( 'target_schema' , schema ) }
303- onSelectCreateSchema = { ( ) => setCreateSchemaSheetOpen ( true ) }
326+ < InputField
327+ key = "target_schema"
328+ option = { {
329+ name : 'target_schema' ,
330+ label : 'Specify a new schema to create all wrapper tables in' ,
331+ required : true ,
332+ encrypted : false ,
333+ secureEntry : false ,
334+ } }
335+ loading = { false }
336+ error = { formErrors [ 'target_schema' ] }
304337 />
305338 < p className = "text-foreground-lighter text-sm" >
306- Be careful not to use an API exposed schema.
339+ A new schema will be created. For security purposes, the wrapper tables
340+ from the foreign schema cannot be created within an existing schema
307341 </ p >
308342 </ div >
309343 </ FormSectionContent >
@@ -316,7 +350,7 @@ export const CreateIcebergWrapperSheet = ({
316350 type = "default"
317351 htmlType = "button"
318352 onClick = { onClosePanel }
319- disabled = { isCreating }
353+ disabled = { isLoading }
320354 >
321355 Cancel
322356 </ Button >
@@ -325,20 +359,11 @@ export const CreateIcebergWrapperSheet = ({
325359 type = "primary"
326360 form = { FORM_ID }
327361 htmlType = "submit"
328- disabled = { isCreating }
329- loading = { isCreating }
362+ loading = { isLoading }
330363 >
331364 Create wrapper
332365 </ Button >
333366 </ SheetFooter >
334- < SchemaEditor
335- visible = { createSchemaSheetOpen }
336- closePanel = { ( ) => setCreateSchemaSheetOpen ( false ) }
337- onSuccess = { ( schema ) => {
338- setFieldValue ( 'target_schema' , schema )
339- setCreateSchemaSheetOpen ( false )
340- } }
341- />
342367 </ >
343368 )
344369 } }
0 commit comments