adds double click to foreign keys on grid

This commit is contained in:
Alaister Young authored and Joshen Lim committed 2023-03-15 15:24:16 +08:00
1 parent 831b0eff2f
commit be4c29de5a
8 files changed
+163 -31

No files matched your search

+7 -1
View File
@@ -198,7 +198,13 @@ const SupabaseGridLayout = forwardRef<SupabaseGridRef, SupabaseGridProps>((props
onAddColumn={editable ? props.onAddColumn : undefined}
headerActions={headerActions}
/>
<Grid ref={gridRef} {...gridProps} rows={data?.rows ?? []} updateRow={props.updateTableRow} />
<Grid
ref={gridRef}
{...gridProps}
rows={data?.rows ?? []}
updateRow={props.updateTableRow}
onEditForeignKeyColumnValue={props.onEditForeignKeyColumnValue}
/>
<Footer isLoading={isLoading || isRefetching} />
<Shortcuts gridRef={gridRef} />
{mounted &&
@@ -6,6 +6,7 @@ import { GridProps, SupaRow } from '../../types'
import { useDispatch, useTrackedState } from '../../store'
import RowRenderer from './RowRenderer'
import AwesomeDebouncePromise from 'awesome-debounce-promise'
import { ForeignRowSelectorProps } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector'
function rowKeyGetter(row: SupaRow) {
return row?.idx ?? -1
@@ -14,13 +15,27 @@ function rowKeyGetter(row: SupaRow) {
interface IGrid extends GridProps {
rows: any[]
updateRow: (previousRow: any, updatedData: any) => void
onEditForeignKeyColumnValue: (args: {
foreignKey: NonNullable<ForeignRowSelectorProps['foreignKey']>
row: any
column: any
}) => void
}
// [Joshen] Just for visibility this is causing some hook errors in the browser
export const Grid = memo(
forwardRef<DataGridHandle, IGrid>(
(
{ width, height, containerClass, gridClass, rowClass, rows, updateRow },
{
width,
height,
containerClass,
gridClass,
rowClass,
rows,
updateRow,
onEditForeignKeyColumnValue,
},
ref: React.Ref<DataGridHandle> | undefined
) => {
const dispatch = useDispatch()
@@ -60,6 +75,34 @@ export const Grid = memo(
})
}
const table = state.table
function getColumnForeignKey(columnName: string) {
const foreignKey = table?.columns.find((x) => x.name == columnName)?.foreignKey ?? {}
return Boolean(
foreignKey.targetTableSchema && foreignKey.targetTableName && foreignKey.targetColumnName
)
? foreignKey
: undefined
}
function onRowDoubleClick(row: any, column: any) {
const foreignKey = getColumnForeignKey(column.name)
if (foreignKey) {
onEditForeignKeyColumnValue({
foreignKey: {
target_column_name: foreignKey.targetColumnName!,
target_table_name: foreignKey.targetTableName!,
target_table_schema: foreignKey.targetTableSchema!,
},
row,
column,
})
}
}
if (!columnHeaders || columnHeaders.length == 0) {
return (
<div
@@ -92,6 +135,7 @@ export const Grid = memo(
onRowsChange={onRowsChange}
onSelectedCellChange={onSelectedCellChange}
onSelectedRowsChange={onSelectedRowsChange}
onRowDoubleClick={onRowDoubleClick}
className={gridClass}
rowClass={rowClass}
style={{ height: '100%' }}
+6
View File
@@ -1,3 +1,4 @@
import { ForeignRowSelectorProps } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector'
import React from 'react'
import { Dictionary } from './base'
import { SupaRow, SupaTable } from './table'
@@ -75,6 +76,11 @@ export interface SupabaseGridProps {
refreshDocs: () => void
onExpandJSONEditor: (column: string, row: SupaRow) => void
updateTableRow: (previousRow: any, updatedData: any) => void
onEditForeignKeyColumnValue: (args: {
foreignKey: NonNullable<ForeignRowSelectorProps['foreignKey']>
row: any
column: any
}) => void
}
export interface SupabaseGridRef {
@@ -12,7 +12,6 @@ import { useStore } from 'hooks'
import { IconLoader, SidePanel } from 'ui'
import ActionBar from '../../ActionBar'
import { RowField } from '../RowEditor.types'
import { useEncryptedColumns } from './ForeignRowSelector.utils'
import SelectorGrid from './SelectorGrid'
import { useState } from 'react'
@@ -20,14 +19,18 @@ import Pagination from './Pagination'
export interface ForeignRowSelectorProps {
visible: boolean
referenceRow?: RowField
foreignKey?: {
target_table_schema: string
target_table_name: string
target_column_name: string
}
onSelect: (value: any) => void
closePanel: () => void
}
const ForeignRowSelector = ({
visible,
referenceRow,
foreignKey,
onSelect,
closePanel,
}: ForeignRowSelectorProps) => {
@@ -38,7 +41,7 @@ const ForeignRowSelector = ({
target_table_schema: schemaName,
target_table_name: tableName,
target_column_name: columnName,
} = referenceRow?.foreignKey ?? {}
} = foreignKey ?? {}
const tables = meta.tables.list()
const table = tables.find((table) => table.schema === schemaName && table.name === tableName)
@@ -202,7 +202,7 @@ const RowEditor = ({
<ForeignRowSelector
visible={isSelectingForeignKey}
referenceRow={referenceRow}
foreignKey={referenceRow?.foreignKey}
onSelect={onSelectForeignRowValue}
closePanel={() => {
setIsSelectingForeignKey(false)
@@ -1,5 +1,6 @@
import { FC, useState } from 'react'
import { find, isEmpty, isUndefined } from 'lodash'
import { useState } from 'react'
import { useQueryClient } from '@tanstack/react-query'
import { find, isEmpty, isUndefined, noop } from 'lodash'
import { Dictionary } from 'components/grid'
import { Modal } from 'ui'
import type { PostgresTable, PostgresColumn } from '@supabase/postgres-meta'
@@ -19,17 +20,24 @@ import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectConte
import ConfirmationModal from 'components/ui/ConfirmationModal'
import JsonEdit from './RowEditor/JsonEditor/JsonEditor'
import { JsonEditValue } from './RowEditor/RowEditor.types'
import { useQueryClient } from '@tanstack/react-query'
import { sqlKeys } from 'data/sql/keys'
import ForeignRowSelector, {
ForeignRowSelectorProps,
} from './RowEditor/ForeignRowSelector/ForeignRowSelector'
interface Props {
export interface SidePanelEditorProps {
selectedSchema: string
selectedTable?: PostgresTable
selectedRowToEdit?: Dictionary<any>
selectedColumnToEdit?: PostgresColumn
selectedTableToEdit?: PostgresTable
selectedValueForJsonEdit?: JsonEditValue
sidePanelKey?: 'row' | 'column' | 'table' | 'json'
selectedForeignKeyToEdit?: {
foreignKey: NonNullable<ForeignRowSelectorProps['foreignKey']>
row: any
column: any
}
sidePanelKey?: 'row' | 'column' | 'table' | 'json' | 'foreign-row-selector'
isDuplicating?: boolean
closePanel: () => void
onRowCreated?: (row: Dictionary<any>) => void
@@ -41,21 +49,22 @@ interface Props {
onColumnSaved?: (hasEncryptedColumns?: boolean) => void
}
const SidePanelEditor: FC<Props> = ({
const SidePanelEditor = ({
selectedSchema,
selectedTable,
selectedRowToEdit,
selectedColumnToEdit,
selectedTableToEdit,
selectedValueForJsonEdit,
selectedForeignKeyToEdit,
sidePanelKey,
isDuplicating = false,
closePanel,
onRowCreated = () => {},
onRowUpdated = () => {},
onTableCreated = () => {},
onColumnSaved = () => {},
}) => {
onRowCreated = noop,
onRowUpdated = noop,
onTableCreated = noop,
onColumnSaved = noop,
}: SidePanelEditorProps) => {
const { meta, ui } = useStore()
const queryClient = useQueryClient()
@@ -156,6 +165,22 @@ const SidePanelEditor: FC<Props> = ({
} catch (error: any) {}
}
const onSaveForeignRow = async (value: any) => {
if (selectedTable === undefined || selectedForeignKeyToEdit === undefined) return
try {
const { row, column } = selectedForeignKeyToEdit
const payload = { [column.name]: value }
const identifiers = {} as Dictionary<any>
selectedTable.primary_keys.forEach((column) => (identifiers[column.name] = row![column.name]))
const isNewRecord = false
const configuration = { identifiers, rowIdx: row.idx }
saveRow(payload, isNewRecord, configuration, () => {})
} catch (error) {}
}
const saveColumn = async (
payload: CreateColumnPayload | UpdateColumnPayload,
foreignKey: ExtendedPostgresRelationship | undefined,
@@ -340,6 +365,12 @@ const SidePanelEditor: FC<Props> = ({
closePanel={onClosePanel}
onSaveJSON={onSaveJSON}
/>
<ForeignRowSelector
visible={sidePanelKey === 'foreign-row-selector'}
foreignKey={selectedForeignKeyToEdit?.foreignKey}
closePanel={onClosePanel}
onSelect={onSaveForeignRow}
/>
<ConfirmationModal
visible={isClosingPanel}
header="Confirm to close"
@@ -1,7 +1,7 @@
import { FC, useRef, useEffect, useState } from 'react'
import { observer } from 'mobx-react-lite'
import { useRouter } from 'next/router'
import { find, isUndefined } from 'lodash'
import { find, isUndefined, noop } from 'lodash'
import type { PostgresColumn, PostgresRelationship, PostgresTable } from '@supabase/postgres-meta'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { QueryKey, useQueryClient } from '@tanstack/react-query'
@@ -35,8 +35,9 @@ import {
useForeignKeyConstraintsQuery,
} from 'data/database/foreign-key-constraints-query'
import { FOREIGN_KEY_DELETION_ACTION } from 'data/database/database-query-constants'
import { ForeignRowSelectorProps } from './SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector'
interface Props {
export interface TableGridEditorProps {
/** Theme for the editor */
theme?: 'dark' | 'light'
@@ -44,7 +45,7 @@ interface Props {
selectedTable: any // PostgresTable | SchemaView
/** Determines what side panel editor to show */
sidePanelKey?: 'row' | 'column' | 'table' | 'json'
sidePanelKey?: 'row' | 'column' | 'table' | 'json' | 'foreign-row-selector'
/** Toggles if we're duplicating a table */
isDuplicating: boolean
/** Selected entities if we're editing a row, column or table */
@@ -52,6 +53,11 @@ interface Props {
selectedColumnToEdit?: PostgresColumn
selectedTableToEdit?: PostgresTable
selectedValueForJsonEdit?: JsonEditValue
selectedForeignKeyToEdit?: {
foreignKey: NonNullable<ForeignRowSelectorProps['foreignKey']>
row: any
column: any
}
onAddRow: () => void
onEditRow: (row: Dictionary<any>) => void
@@ -59,10 +65,15 @@ interface Props {
onEditColumn: (column: PostgresColumn) => void
onDeleteColumn: (column: PostgresColumn) => void
onExpandJSONEditor: (column: string, row: any) => void
onEditForeignKeyColumnValue: (args: {
foreignKey: NonNullable<ForeignRowSelectorProps['foreignKey']>
row: any
column: any
}) => void
onClosePanel: () => void
}
const TableGridEditor: FC<Props> = ({
const TableGridEditor = ({
theme = 'dark',
selectedSchema,
@@ -73,15 +84,17 @@ const TableGridEditor: FC<Props> = ({
selectedColumnToEdit,
selectedTableToEdit,
selectedValueForJsonEdit,
selectedForeignKeyToEdit,
onAddRow = () => {},
onEditRow = () => {},
onAddColumn = () => {},
onEditColumn = () => {},
onDeleteColumn = () => {},
onExpandJSONEditor = () => {},
onClosePanel = () => {},
}) => {
onAddRow = noop,
onEditRow = noop,
onAddColumn = noop,
onEditColumn = noop,
onDeleteColumn = noop,
onExpandJSONEditor = noop,
onEditForeignKeyColumnValue = noop,
onClosePanel = noop,
}: TableGridEditorProps) => {
const { project } = useProjectContext()
const { meta, ui, vault } = useStore()
const router = useRouter()
@@ -382,6 +395,7 @@ const TableGridEditor: FC<Props> = ({
onError={onError}
onSqlQuery={onSqlQuery}
onExpandJSONEditor={onExpandJSONEditor}
onEditForeignKeyColumnValue={onEditForeignKeyColumnValue}
/>
{!isUndefined(selectedSchema) && (
<SidePanelEditor
@@ -392,6 +406,7 @@ const TableGridEditor: FC<Props> = ({
selectedColumnToEdit={selectedColumnToEdit}
selectedTableToEdit={selectedTableToEdit}
selectedValueForJsonEdit={selectedValueForJsonEdit}
selectedForeignKeyToEdit={selectedForeignKeyToEdit}
sidePanelKey={sidePanelKey}
onRowCreated={onRowCreated}
onRowUpdated={onRowUpdated}
+28 -1
View File
@@ -14,6 +14,7 @@ import ConfirmationModal from 'components/ui/ConfirmationModal'
import { NextPageWithLayout, SchemaView } from 'types'
import { JsonEditValue } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.types'
import { ProjectContextFromParamsProvider } from 'components/layouts/ProjectLayout/ProjectContext'
import { ForeignRowSelectorProps } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector'
const TableEditorPage: NextPageWithLayout = () => {
const router = useRouter()
@@ -30,11 +31,18 @@ const TableEditorPage: NextPageWithLayout = () => {
const [selectedColumnToDelete, setSelectedColumnToDelete] = useState<PostgresColumn>()
const [selectedTableToDelete, setSelectedTableToDelete] = useState<PostgresTable>()
const [sidePanelKey, setSidePanelKey] = useState<'row' | 'column' | 'table' | 'json'>()
const [sidePanelKey, setSidePanelKey] = useState<
'row' | 'column' | 'table' | 'json' | 'foreign-row-selector'
>()
const [selectedRowToEdit, setSelectedRowToEdit] = useState<Dictionary<any>>()
const [selectedColumnToEdit, setSelectedColumnToEdit] = useState<PostgresColumn>()
const [selectedTableToEdit, setSelectedTableToEdit] = useState<PostgresTable>()
const [selectedValueForJsonEdit, setSelectedValueForJsonEdit] = useState<JsonEditValue>()
const [selectedForeignKeyToEdit, setSelectedForeignKeyToEdit] = useState<{
foreignKey: NonNullable<ForeignRowSelectorProps['foreignKey']>
row: any
column: any
}>()
const tables: PostgresTable[] = meta.tables.list()
const views: SchemaView[] = meta.views.list()
@@ -111,6 +119,23 @@ const TableEditorPage: NextPageWithLayout = () => {
setSelectedValueForJsonEdit({ column, row, jsonString: JSON.stringify(row[column]) || '' })
}
const onEditForeignKeyColumnValue = ({
foreignKey,
row,
column,
}: {
foreignKey: NonNullable<ForeignRowSelectorProps['foreignKey']>
row: any
column: any
}) => {
setSidePanelKey('foreign-row-selector')
setSelectedForeignKeyToEdit({
foreignKey,
row,
column,
})
}
const onClosePanel = () => {
setSidePanelKey(undefined)
}
@@ -211,12 +236,14 @@ const TableEditorPage: NextPageWithLayout = () => {
selectedColumnToEdit={selectedColumnToEdit}
selectedTableToEdit={selectedTableToEdit}
selectedValueForJsonEdit={selectedValueForJsonEdit}
selectedForeignKeyToEdit={selectedForeignKeyToEdit}
onAddRow={onAddRow}
onEditRow={onEditRow}
onAddColumn={onAddColumn}
onEditColumn={onEditColumn}
onDeleteColumn={onDeleteColumn}
onExpandJSONEditor={onExpandJSONEditor}
onEditForeignKeyColumnValue={onEditForeignKeyColumnValue}
onClosePanel={onClosePanel}
theme={ui.themeOption == 'dark' ? 'dark' : 'light'}
/>