` | Multi-value chips |
**Edit Flow**:
1. Click cell → Enter edit mode
2. Show appropriate editor component
3. Type/select new value
4. Press Enter to save OR Escape to cancel
5. Optimistic update → DB save → Rollback on error
6. Visual feedback: Yellow (editing) → Green (saved) → Red (error)
**Validation**:
- Check NOT NULL constraints
- Validate data type compatibility
- Verify foreign key references exist
- Check max length for strings
- Validate JSON syntax
- Custom validation rules per table
**Implementation**:
```tsx
const EditableCell = ({ getValue, row, column, table }) => {
const initialValue = getValue()
const [value, setValue] = useState(initialValue)
const [isEditing, setIsEditing] = useState(false)
const handleSave = async () => {
const meta = table.options.meta
await meta?.updateData(row.index, column.id, value)
setIsEditing(false)
}
return (
setIsEditing(true)}>
{isEditing ? (
setValue(e.target.value)}
onBlur={handleSave}
onKeyDown={(e) => {
if (e.key === 'Enter') handleSave()
if (e.key === 'Escape') setIsEditing(false)
}}
/>
) : (
{value}
)}
)
}
```
#### 2.3 Advanced Filtering
**Filter Panel** (collapsible left sidebar):
**Filter Builder UI**:
- Add filter button
- Each filter row contains:
- Column selector dropdown
- Operator selector (based on column type)
- Value input (type-appropriate)
- Remove filter button
- AND/OR logic toggle between filters
- Clear all filters button
- Save filter preset (with name)
- Load saved preset
**Filter Types by Data Type**
**Text Columns**:
- Contains
- Equals
- Starts with
- Ends with
- Regex match
- Is empty / Is not empty
**Number Columns**:
- Equals
- Greater than (>)
- Less than (<)
- Greater than or equal (>=)
- Less than or equal (<=)
- Between (min, max)
- Is null / Is not null
**Date Columns**:
- Before
- After
- Between (start, end)
- Is null
- Last N days
- Next N days
**Boolean Columns**:
- Is true
- Is false
- Is null
**UUID Columns**:
- Equals
- In list (comma-separated)
- Is null
**JSON Columns**:
- Path exists
- Path equals value
- Contains key
**Quick Filters Bar** (above table):
- Chips showing active filters
- Click chip to edit filter
- X to remove filter
- "5 filters active" counter
**Implementation**:
```tsx
interface ColumnFilter {
id: string; // column name
operator: FilterOperator;
value: any;
logicGate?: 'AND' | 'OR';
}
const filterFunctions = {
text: {
contains: (row, id, filterValue) =>
row.getValue(id)?.toLowerCase().includes(filterValue.toLowerCase()),
equals: (row, id, filterValue) =>
row.getValue(id) === filterValue,
startsWith: (row, id, filterValue) =>
row.getValue(id)?.startsWith(filterValue),
// ... more
},
number: {
equals: (row, id, filterValue) => row.getValue(id) === filterValue,
gt: (row, id, filterValue) => row.getValue(id) > filterValue,
// ... more
}
}
```
#### 2.4 Sorting & Pagination
**Sorting**:
- Click column header to sort ascending
- Click again to sort descending
- Click third time to remove sort
- Shift+Click to add multi-column sort
- Sort indicators: ↑ (asc), ↓ (desc)
- Multi-sort shows order numbers (1, 2, 3)
- Custom sort functions for complex types (JSON, arrays)
**Pagination**:
- Rows per page selector: 25, 50, 100, 500, 1000
- Page navigation: First, Prev, Next, Last
- Page input: "Jump to page X"
- Display: "Showing 1-25 of 1,234 rows"
- "Load all" button (with warning for tables > 1000 rows)
- Virtual scrolling for large datasets
**Implementation**:
```tsx
const [pagination, setPagination] = useState({
pageIndex: 0,
pageSize: 50
})
const table = useReactTable({
// ...
getPaginationRowModel: getPaginationRowModel(),
onPaginationChange: setPagination,
state: { pagination }
})
// Pagination controls
table.setPageIndex(Number(e.target.value) - 1)}
/>
of {table.getPageCount()}
```
#### 2.5 Column Management
**Column Config Panel** (collapsible right sidebar):
**Features**:
- **Column Visibility**:
- Checkbox list of all columns
- Toggle individual columns on/off
- "Show all" / "Hide all" buttons
- Search column names
- **Column Reordering**:
- Drag-drop list to reorder columns
- Visual drag handle icon
- Smooth reorder animation
- **Column Pinning**:
- Pin columns to left (e.g., ID, name)
- Pin columns to right (e.g., actions)
- Unpin button
- **Column Presets**:
- Save current column layout with name
- Load saved layouts
- Default layouts per table:
- "Essential" (ID, name, status, dates)
- "All" (show everything)
- "Metadata" (created_at, updated_at, created_by)
- **Reset to Default**:
- Restore original column order/visibility
**Implementation**:
```tsx
const [columnVisibility, setColumnVisibility] = useState({})
const [columnOrder, setColumnOrder] = useState([])
const [columnPinning, setColumnPinning] = useState({ left: ['id'], right: [] })
const table = useReactTable({
// ...
state: {
columnVisibility,
columnOrder,
columnPinning
},
onColumnVisibilityChange: setColumnVisibility,
onColumnOrderChange: setColumnOrder,
onColumnPinningChange: setColumnPinning
})
```
#### 2.6 Search & Navigation
**Global Search**:
- Search input above table
- Searches all visible columns
- Highlight matching text in cells
- "X matches found" counter
- Next/Prev navigation between matches
- Clear search button
**Quick Jump**:
- "Jump to row by ID" input
- Autofocus and scroll to row
- Highlight target row
**Keyboard Navigation**:
- Arrow keys: Navigate cells
- Tab: Move to next editable cell
- Enter: Edit current cell / Save edit
- Escape: Cancel edit
- Page Up/Down: Scroll page
- Home/End: Jump to first/last row
- Ctrl+F: Focus search
- Ctrl+C: Copy cell value
- Del: Delete selected rows (with confirmation)
---
### Phase 3: Advanced Features
#### 3.1 Bulk Operations (DatabaseBulkActions)
**Features**:
- **Row Selection**: Checkboxes in first column
- **Selection Actions**:
- Select all on page
- Select all matching filter
- Deselect all
- Invert selection
- **Bulk Edit**:
- Select column to edit
- Set value for all selected rows
- Preview changes before applying
- Apply button with confirmation
- **Bulk Delete**:
- Delete all selected rows
- Show count: "Delete 23 rows?"
- Confirmation dialog with row preview
- Cannot be undone warning
- **Batch Update**:
- Apply formula/function to column
- Examples:
- Set status to 'approved' for all pending
- Increment version number by 1
- Update timestamps to NOW()
- **Action History**:
- Show last 10 bulk operations
- Display: operation, row count, timestamp, user
- Undo last operation (if safe and within 5 minutes)
**UI**:
```tsx
{selectedRows.length} rows selected
```
#### 3.2 Export/Import (DatabaseExportImport)
**Export Features**:
- **Export Formats**:
- CSV (with headers)
- JSON (array of objects)
- SQL INSERT statements
- **Export Scope**:
- All rows
- Filtered rows only
- Selected rows only
- Visible columns only
- **Export Options**:
- Include/exclude NULL values
- Date format selection
- JSON pretty print
- SQL: Include CREATE TABLE statement
- **Batch Export**:
- Export all tables as ZIP file
- Progress indicator for large exports
**Import Features**:
- **Import Formats**:
- CSV (with column mapping UI)
- JSON (validate schema first)
- **Import Modes**:
- Insert (add new rows)
- Update (match by ID)
- Upsert (insert or update)
- **Import Validation**:
- Dry-run preview
- Show errors before import
- Skip invalid rows option
- **Import Progress**:
- Progress bar for large files
- Success/error counts
- Download error log
**Implementation**:
```tsx
const exportToCSV = (data: any[], columns: Column[]) => {
const headers = columns.map(col => col.header).join(',')
const rows = data.map(row =>
columns.map(col => JSON.stringify(row[col.id] ?? '')).join(',')
).join('\n')
const csv = `${headers}\n${rows}`
downloadFile(csv, 'table_export.csv', 'text/csv')
}
const importFromCSV = async (file: File) => {
const parsed = Papa.parse(file, { header: true })
// Validate schema
const validationErrors = validateImportData(parsed.data, tableSchema)
if (validationErrors.length > 0) {
showErrorDialog(validationErrors)
return
}
// Insert rows
for (const row of parsed.data) {
await supabase.from(tableName).insert(row)
}
}
```
#### 3.3 Schema Viewer (DatabaseSchemaViewer)
**Features**:
- **Table Structure Display**:
- Column list with details:
- Name
- Data type
- Nullable (✓/✗)
- Default value
- Max length (for text)
- Primary key indicator (🔑)
- Foreign key indicators (→ target_table)
- Unique constraint indicators
- Index indicators (📊)
- **Relationships View**:
- Visual diagram (ERD style)
- Show foreign key relationships
- Click table to navigate
- Zoom/pan controls
- **Constraints**:
- Primary keys
- Foreign keys (with ON DELETE/UPDATE actions)
- Unique constraints
- Check constraints
- Indexes (btree, gin, gist)
- **RLS Policies** (read-only):
- List all policies for table
- Show policy name, operation, USING clause
- Syntax highlighting for SQL
- **SQL DDL View**:
- Show CREATE TABLE statement
- Show CREATE INDEX statements
- Show RLS policies
- Copy to clipboard button
- Syntax highlighting
**Implementation**:
```tsx
const SchemaViewer = ({ tableName }: { tableName: string }) => {
const { data: schema } = useTableSchema(tableName)
return (
Columns
Relationships
Constraints
RLS Policies
SQL DDL
Name
Type
Nullable
Default
{schema.columns.map(col => (
{col.isPrimaryKey && '🔑 '}
{col.name}
{col.type}
{col.isNullable ? '✓' : '✗'}
{col.default}
))}
{/* Other tabs */}
)
}
```
#### 3.4 Row Editor Dialog (DatabaseRowEditor)
**Purpose**: Detailed form-based editor for complex edits
**Features**:
- **Trigger**: Double-click row to open
- **Layout**: Vertical form with all columns
- **Field Types**:
- Text: `