mirror of
https://github.com/supabase/supabase.git
synced 2026-10-08 10:55:06 +03:00
Shift views to store and improve tce decsription
This commit is contained in:
1 parent
6d23225aeb
commit
40de9a3da0
6 files changed
+63
-35
No files matched your search
+1
-1
@@ -322,7 +322,7 @@ const ColumnEditor: FC<Props> = ({
|
||||
<FormSectionContent loading={false} className="lg:!col-span-8">
|
||||
<Toggle
|
||||
label="Encrypt Column"
|
||||
descriptionText="Encrypt the column's data with pgsodium's Transparent Column Encryption (TCE)"
|
||||
descriptionText={`Encrypt the column's data with pgsodium's Transparent Column Encryption (TCE). Decrypted values will be stored within the "decrypted_${selectedTable.name}" view.`}
|
||||
checked={columnFields.isEncrypted}
|
||||
onChange={() => onUpdateField({ isEncrypted: !columnFields.isEncrypted })}
|
||||
/>
|
||||
|
||||
@@ -149,6 +149,10 @@ const SidePanelEditor: FC<Props> = ({
|
||||
closePanel()
|
||||
}
|
||||
|
||||
if (configuration.isEncrypted) {
|
||||
await meta.schemas.loadViews(selectedTable?.schema ?? '')
|
||||
}
|
||||
|
||||
resolve()
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,8 @@ import { FC, useEffect, useState } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import Link from 'next/link'
|
||||
import { partition } from 'lodash'
|
||||
// import { Button } from 'ui'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
Dropdown,
|
||||
IconChevronDown,
|
||||
@@ -60,7 +59,6 @@ const TableEditorMenu: FC<Props> = ({
|
||||
const canCreateTables = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables')
|
||||
|
||||
const [searchText, setSearchText] = useState<string>('')
|
||||
const [schemaViews, setSchemaViews] = useState<SchemaView[]>([])
|
||||
const [isRefreshing, setIsRefreshing] = useState<boolean>(false)
|
||||
|
||||
// We may need to shift this to the schema store and do something like meta.schema.loadViews()
|
||||
@@ -68,12 +66,10 @@ const TableEditorMenu: FC<Props> = ({
|
||||
useEffect(() => {
|
||||
let cancel = false
|
||||
const fetchViews = async (selectedSchema: string) => {
|
||||
const views: SchemaView[] = await meta.schemas.getViews(selectedSchema)
|
||||
if (!cancel) setSchemaViews(views)
|
||||
}
|
||||
if (selectedSchema) {
|
||||
fetchViews(selectedSchema)
|
||||
await meta.schemas.loadViews(selectedSchema)
|
||||
}
|
||||
if (selectedSchema) fetchViews(selectedSchema)
|
||||
|
||||
return () => {
|
||||
cancel = true
|
||||
}
|
||||
@@ -93,8 +89,8 @@ const TableEditorMenu: FC<Props> = ({
|
||||
|
||||
const filteredSchemaViews =
|
||||
searchText.length === 0
|
||||
? schemaViews
|
||||
: schemaViews.filter((view) => view.name.includes(searchText))
|
||||
? meta.schemas.views
|
||||
: meta.schemas.views.filter((view) => view.name.includes(searchText))
|
||||
|
||||
const [protectedSchemas, openSchemas] = partition(schemas, (schema) =>
|
||||
meta.excludedSchemas.includes(schema?.name ?? '')
|
||||
@@ -117,7 +113,6 @@ const TableEditorMenu: FC<Props> = ({
|
||||
// @ts-ignore
|
||||
onChange={(name: string) => {
|
||||
setSearchText('')
|
||||
setSchemaViews([])
|
||||
onSelectSchema(name)
|
||||
}}
|
||||
>
|
||||
@@ -296,24 +291,24 @@ const TableEditorMenu: FC<Props> = ({
|
||||
<Menu.Group
|
||||
// @ts-ignore
|
||||
title={
|
||||
<>
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<span>All views</span>
|
||||
</div>
|
||||
</>
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<span>All views</span>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
||||
{schemaViews.map((view: SchemaView) => {
|
||||
{meta.schemas.views.map((view: SchemaView) => {
|
||||
const viewId = Base64.encode(JSON.stringify(view))
|
||||
const isActive = id === viewId
|
||||
return (
|
||||
<Link key={viewId} href={`/project/${projectRef}/editor/${viewId}`}>
|
||||
<Menu.Item key={viewId} rounded active={isActive}>
|
||||
<div className="flex justify-between">
|
||||
<p className="truncate">{view.name}</p>
|
||||
</div>
|
||||
</Menu.Item>
|
||||
<a>
|
||||
<Menu.Item key={viewId} rounded active={isActive}>
|
||||
<div className="flex justify-between">
|
||||
<p className="truncate">{view.name}</p>
|
||||
</div>
|
||||
</Menu.Item>
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
@@ -339,4 +334,4 @@ const TableEditorMenu: FC<Props> = ({
|
||||
)
|
||||
}
|
||||
|
||||
export default TableEditorMenu
|
||||
export default observer(TableEditorMenu)
|
||||
@@ -3,7 +3,7 @@ import { NextPage } from 'next'
|
||||
import { useRouter } from 'next/router'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { isUndefined, isNaN } from 'lodash'
|
||||
import { Modal } from 'ui'
|
||||
import { Checkbox, Modal } from 'ui'
|
||||
import { PostgresTable, PostgresColumn } from '@supabase/postgres-meta'
|
||||
|
||||
import Base64 from 'lib/base64'
|
||||
@@ -24,6 +24,8 @@ const TableEditorPage: NextPage = () => {
|
||||
|
||||
const [isDeleting, setIsDeleting] = useState<boolean>(false)
|
||||
const [isDuplicating, setIsDuplicating] = useState<boolean>(false)
|
||||
const [isDeleteWithCascade, setIsDeleteWithCascade] = useState(false)
|
||||
|
||||
const [selectedColumnToDelete, setSelectedColumnToDelete] = useState<PostgresColumn>()
|
||||
const [selectedTableToDelete, setSelectedTableToDelete] = useState<PostgresTable>()
|
||||
|
||||
@@ -70,6 +72,7 @@ const TableEditorPage: NextPage = () => {
|
||||
const onDeleteColumn = (column: PostgresColumn) => {
|
||||
setIsDeleting(true)
|
||||
setSelectedColumnToDelete(column)
|
||||
setIsDeleteWithCascade(false)
|
||||
}
|
||||
|
||||
const onAddTable = () => {
|
||||
@@ -87,6 +90,7 @@ const TableEditorPage: NextPage = () => {
|
||||
const onDeleteTable = (table: PostgresTable) => {
|
||||
setIsDeleting(true)
|
||||
setSelectedTableToDelete(table)
|
||||
setIsDeleteWithCascade(false)
|
||||
}
|
||||
|
||||
const onDuplicateTable = (table: PostgresTable) => {
|
||||
@@ -141,7 +145,9 @@ const TableEditorPage: NextPage = () => {
|
||||
try {
|
||||
if (isUndefined(selectedTableToDelete)) return
|
||||
|
||||
const response: any = await meta.tables.del(selectedTableToDelete.id)
|
||||
const response: any = await meta.tables.del(selectedTableToDelete.id, {
|
||||
cascade: isDeleteWithCascade,
|
||||
})
|
||||
if (response.error) throw response.error
|
||||
|
||||
const tables = meta.tables.list((table: PostgresTable) => table.schema === selectedSchema)
|
||||
@@ -217,9 +223,17 @@ const TableEditorPage: NextPage = () => {
|
||||
}
|
||||
children={
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-scale-1100">
|
||||
Are you sure you want to delete the selected table? This action cannot be undone.
|
||||
</p>
|
||||
<div className="py-4 space-y-4">
|
||||
<p className="text-sm text-scale-1100">
|
||||
Are you sure you want to delete the selected table? This action cannot be undone.
|
||||
</p>
|
||||
<Checkbox
|
||||
label="Drop with cascade?"
|
||||
description="Deletes the table and its dependent objects"
|
||||
checked={isDeleteWithCascade}
|
||||
onChange={() => setIsDeleteWithCascade(!isDeleteWithCascade)}
|
||||
/>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
}
|
||||
buttonLabel="Delete"
|
||||
|
||||
@@ -17,7 +17,7 @@ export interface IPostgresMetaInterface<T> {
|
||||
load: () => void
|
||||
create: (payload: any) => Promise<T | { error: ResponseError }>
|
||||
update: (id: number | string, updates: any) => Promise<T | { error: ResponseError }>
|
||||
del: (id: number | string) => Promise<boolean | { error: ResponseError }>
|
||||
del: (id: number | string, payload?: any) => Promise<boolean | { error: ResponseError }>
|
||||
list: (filter?: any) => T[]
|
||||
find: (filter?: any) => T | undefined
|
||||
byId: (id: number | string) => T | undefined
|
||||
@@ -187,11 +187,11 @@ export default class PostgresMetaInterface<T> implements IPostgresMetaInterface<
|
||||
}
|
||||
}
|
||||
|
||||
async del(id: number | string) {
|
||||
async del(id: number | string, payload: any = {}) {
|
||||
try {
|
||||
const headers = { 'Content-Type': 'application/json', ...this.headers }
|
||||
const url = `${this.url}?id=${id}`
|
||||
const response = await delete_<T>(url, {}, { headers })
|
||||
const response = await delete_<T>(url, payload, { headers })
|
||||
if (response.error) throw response.error
|
||||
|
||||
delete this.data[id]
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
import { observable, makeObservable } from 'mobx'
|
||||
import { PostgresSchema } from '@supabase/postgres-meta'
|
||||
|
||||
import PostgresMetaInterface, { IPostgresMetaInterface } from '../common/PostgresMetaInterface'
|
||||
import { IRootStore } from '../RootStore'
|
||||
import { ResponseError } from 'types'
|
||||
|
||||
interface SchemaView {
|
||||
schema: string
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface ISchemaStore extends IPostgresMetaInterface<PostgresSchema> {
|
||||
getViews: (schema: string) => Promise<any | { error: ResponseError }>
|
||||
views: SchemaView[]
|
||||
loadViews: (schema: string) => Promise<any | { error: ResponseError }>
|
||||
}
|
||||
export default class SchemaStore extends PostgresMetaInterface<PostgresSchema> {
|
||||
views: SchemaView[]
|
||||
|
||||
constructor(
|
||||
rootStore: IRootStore,
|
||||
dataUrl: string,
|
||||
@@ -17,14 +26,20 @@ export default class SchemaStore extends PostgresMetaInterface<PostgresSchema> {
|
||||
options?: { identifier: string }
|
||||
) {
|
||||
super(rootStore, dataUrl, headers, options)
|
||||
makeObservable(this, {
|
||||
views: observable,
|
||||
})
|
||||
this.views = []
|
||||
}
|
||||
|
||||
async getViews(schema: string) {
|
||||
async loadViews(schema: string) {
|
||||
const query = `
|
||||
select schemaname as schema, viewname as name from pg_catalog.pg_views
|
||||
where schemaname = '${schema}'
|
||||
order by schemaname, viewname;
|
||||
`
|
||||
return await this.rootStore.meta.query(query)
|
||||
const views = await this.rootStore.meta.query(query)
|
||||
this.views = views
|
||||
return views
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user