mirror of
https://github.com/supabase/supabase.git
synced 2026-10-09 03:15:06 +03:00
Merge branch 'feat/fdw' of github.com:supabase/supabase into feat/fdw
This commit is contained in:
commit
388f2fcbca
4 files changed
+89
-15
No files matched your search
@@ -132,7 +132,6 @@ const WrapperRow: FC<Props> = ({ wrapper, isLoading, isEnabled, isOpen, onOpen }
|
||||
category: 'success',
|
||||
message: `Successfully created ${wrapper.label} foreign data wrapper`,
|
||||
})
|
||||
onOpen('')
|
||||
setNewTables([])
|
||||
setFormState(getInitialFormState)
|
||||
} catch (error: any) {
|
||||
@@ -296,7 +295,9 @@ const WrapperRow: FC<Props> = ({ wrapper, isLoading, isEnabled, isOpen, onOpen }
|
||||
{newTables.map((table, i) => (
|
||||
<div className="border border-scale-600 px-4 py-2 rounded-md space-y-1 flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm">{table.table_name}</p>
|
||||
<p className="text-sm">
|
||||
{table.schema_name}.{table.table_name}
|
||||
</p>
|
||||
<p className="text-sm text-scale-1000">
|
||||
{wrapper.tables[table.index].label}: {table.columns.join(', ')}
|
||||
</p>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Form, Input, Listbox, SidePanel } from 'ui'
|
||||
import { Form, IconDatabase, Input, Listbox, SidePanel, Modal, IconPlus } from 'ui'
|
||||
import { useStore } from 'hooks'
|
||||
import { Table, TableOption } from './Wrappers.types'
|
||||
import { makeValidateRequired } from './Wrappers.utils'
|
||||
import MultiSelect from 'components/ui/MultiSelect'
|
||||
@@ -39,7 +40,12 @@ const WrapperTableEditor = ({
|
||||
}
|
||||
|
||||
const onSubmit: OnSubmitFn = (values, { resetForm }) => {
|
||||
onSave({ ...values, index: parseInt(selectedTableIndex) })
|
||||
onSave({
|
||||
...values,
|
||||
index: parseInt(selectedTableIndex),
|
||||
schema_name: values.schema === 'custom' ? values.schema_name : values.schema,
|
||||
is_new_schema: values.schema === 'custom',
|
||||
})
|
||||
resetForm()
|
||||
setSelectedTableIndex('')
|
||||
}
|
||||
@@ -121,6 +127,9 @@ const TableForm = ({
|
||||
onSubmit: OnSubmitFn
|
||||
initialData: any
|
||||
}) => {
|
||||
const { meta } = useStore()
|
||||
const schemas = meta.schemas.list()
|
||||
|
||||
const requiredOptions =
|
||||
table.options.filter((option) => option.editable && option.required && !option.defaultValue) ??
|
||||
[]
|
||||
@@ -133,6 +142,8 @@ const TableForm = ({
|
||||
table_name: '',
|
||||
columns: table.availableColumns.map((column) => column.name),
|
||||
...Object.fromEntries(table.options.map((option) => [option.name, option.defaultValue ?? ''])),
|
||||
schema: 'public',
|
||||
schema_name: '',
|
||||
}
|
||||
|
||||
const validate = makeValidateRequired([
|
||||
@@ -152,17 +163,44 @@ const TableForm = ({
|
||||
{({ errors, values, resetForm }: any) => {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<Listbox size="small" name="schema" label="Select a schema for the foreign table">
|
||||
<Listbox.Option
|
||||
key="custom"
|
||||
id="custom"
|
||||
label={`Create a new schema`}
|
||||
value="custom"
|
||||
addOnBefore={() => <IconPlus size={16} strokeWidth={1.5} />}
|
||||
>
|
||||
Create a new schema
|
||||
</Listbox.Option>
|
||||
<Modal.Separator />
|
||||
{/* @ts-ignore */}
|
||||
{schemas.map((schema: PostgresSchema) => {
|
||||
return (
|
||||
<Listbox.Option
|
||||
key={schema.id}
|
||||
id={schema.name}
|
||||
label={schema.name}
|
||||
value={schema.name}
|
||||
addOnBefore={() => <IconDatabase size={16} strokeWidth={1.5} />}
|
||||
>
|
||||
{schema.name}
|
||||
</Listbox.Option>
|
||||
)
|
||||
})}
|
||||
</Listbox>
|
||||
{values.schema === 'custom' && (
|
||||
<Input id="schema_name" name="schema_name" label="Schema name" />
|
||||
)}
|
||||
<Input
|
||||
id="table_name"
|
||||
name="table_name"
|
||||
label="Table name"
|
||||
descriptionText="You can query from this table after the wrapper is enabled."
|
||||
/>
|
||||
|
||||
{requiredOptions.map((option) => (
|
||||
<Option key={option.name} option={option} />
|
||||
))}
|
||||
|
||||
<MultiSelect
|
||||
label="Columns"
|
||||
options={table.availableColumns.map((column) => {
|
||||
@@ -182,7 +220,6 @@ const TableForm = ({
|
||||
resetForm({ values: { ...values, columns } })
|
||||
}}
|
||||
/>
|
||||
|
||||
{optionalOptions.map((option) => (
|
||||
<Option key={option.name} option={option} />
|
||||
))}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Wrapper } from './Wrappers.types'
|
||||
|
||||
export const wrappers: Wrapper[] = [
|
||||
export const WRAPPERS: Wrapper[] = [
|
||||
{
|
||||
name: 'stripe_wrapper',
|
||||
handlerName: 'stripe_fdw_handler',
|
||||
|
||||
@@ -7,9 +7,8 @@ import { PermissionAction } from '@supabase/shared-types/out/constants'
|
||||
|
||||
import { checkPermissions, useStore } from 'hooks'
|
||||
import { useFDWsQuery } from 'data/fdw/fdws-query'
|
||||
import { wrappers } from './Wrappers.constants'
|
||||
import { WRAPPERS } from './Wrappers.constants'
|
||||
import WrapperRow from './WrapperRow'
|
||||
import { FormHeader } from 'components/ui/Forms'
|
||||
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
|
||||
|
||||
const Wrappers = () => {
|
||||
@@ -77,14 +76,51 @@ const Wrappers = () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FormHeader
|
||||
title="Foreign Data Wrappers"
|
||||
description="Query your data warehouse directly from your database, or third-party APIs using SQL."
|
||||
/>
|
||||
<div className="mb-6 flex items-center justify-between">
|
||||
<div>
|
||||
<h3 className="text-scale-1200 mb-2 text-xl">Foreign Data Wrappers</h3>
|
||||
<div className="text-scale-900 text-sm">
|
||||
Query your data warehouse directly from your database, or third-party APIs using SQL.
|
||||
</div>
|
||||
</div>
|
||||
{/* [Joshen TODO] For when we support multiple instances per wrapper */}
|
||||
{/* <div>
|
||||
<Dropdown
|
||||
side="bottom"
|
||||
align="end"
|
||||
size="small"
|
||||
overlay={
|
||||
<>
|
||||
{WRAPPERS.map((wrapper, idx) => (
|
||||
<>
|
||||
<Dropdown.Item
|
||||
key={wrapper.name}
|
||||
icon={
|
||||
<Image
|
||||
src={wrapper.icon}
|
||||
width={20}
|
||||
height={20}
|
||||
alt={`${wrapper.name} wrapper icon`}
|
||||
/>
|
||||
}
|
||||
onClick={() => {}}
|
||||
>
|
||||
{wrapper.label}
|
||||
</Dropdown.Item>
|
||||
{idx !== WRAPPERS.length - 1 && <Dropdown.Separator />}
|
||||
</>
|
||||
))}
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Button type="primary">Add wrapper</Button>
|
||||
</Dropdown>
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
{isWrappersEnabled ? (
|
||||
<div>
|
||||
{wrappers.map((wrapper) => {
|
||||
{WRAPPERS.map((wrapper) => {
|
||||
return (
|
||||
<WrapperRow
|
||||
wrapper={wrapper}
|
||||
|
||||
Reference in new issue
Block a user