mirror of
https://github.com/supabase/supabase.git
synced 2026-10-15 14:19:11 +03:00
added hidden init columns
This commit is contained in:
1 parent
013bc63765
commit
8a43fac91b
6 files changed
+199
-2
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { forwardRef, memo, useRef } from 'react'
|
||||
import { forwardRef, memo, useRef, useMemo } from 'react'
|
||||
import DataGrid, { CalculatedColumn, DataGridHandle } from 'react-data-grid'
|
||||
|
||||
import { handleCopyCell } from 'components/grid/SupabaseGrid.utils'
|
||||
@@ -10,6 +10,7 @@ import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
|
||||
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
|
||||
import { useTableEditorStateSnapshot } from 'state/table-editor'
|
||||
import { useTableEditorTableStateSnapshot } from 'state/table-editor-table'
|
||||
import { useTableColumnVisibility } from 'components/grid/hooks/useTableColumnVisibility'
|
||||
import { Button, cn } from 'ui'
|
||||
import { GenericSkeletonLoader } from 'ui-patterns'
|
||||
import type { Filter, GridProps, SupaRow } from '../../types'
|
||||
@@ -52,6 +53,12 @@ export const Grid = memo(
|
||||
) => {
|
||||
const tableEditorSnap = useTableEditorStateSnapshot()
|
||||
const snap = useTableEditorTableStateSnapshot()
|
||||
const { hiddenColumns } = useTableColumnVisibility()
|
||||
|
||||
const visibleColumns = useMemo(() => {
|
||||
if (!snap.gridColumns) return []
|
||||
return snap.gridColumns.filter((col) => !hiddenColumns.has(col.key))
|
||||
}, [snap.gridColumns, hiddenColumns])
|
||||
|
||||
const onRowsChange = useOnRowsChange(rows)
|
||||
|
||||
@@ -182,7 +189,7 @@ export const Grid = memo(
|
||||
ref={ref}
|
||||
className={`${gridClass} flex-grow`}
|
||||
rowClass={rowClass}
|
||||
columns={snap.gridColumns as CalculatedColumn<any, any>[]}
|
||||
columns={visibleColumns as CalculatedColumn<any, any>[]}
|
||||
rows={rows ?? []}
|
||||
renderers={{ renderRow: RowRenderer }}
|
||||
rowKeyGetter={rowKeyGetter}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import { useParams } from 'common'
|
||||
import { Settings2 } from 'lucide-react'
|
||||
import {
|
||||
Button,
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuTrigger,
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from 'ui'
|
||||
|
||||
import { useTableColumnVisibility } from 'components/grid/hooks/useTableColumnVisibility'
|
||||
import { useTableEditorTableStateSnapshot } from 'state/table-editor-table'
|
||||
|
||||
export const ColumnVisibility = () => {
|
||||
const snap = useTableEditorTableStateSnapshot()
|
||||
|
||||
const { hiddenColumns, hideColumn, showColumn } = useTableColumnVisibility()
|
||||
|
||||
const handleToggleColumnVisibility = (columnKey: string, isVisible: boolean) => {
|
||||
if (isVisible) {
|
||||
showColumn(columnKey)
|
||||
} else {
|
||||
hideColumn(columnKey)
|
||||
}
|
||||
}
|
||||
|
||||
const columns = snap.table?.columns ?? []
|
||||
|
||||
if (columns.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<Settings2 size={14} strokeWidth={1.5} />}
|
||||
className="rounded px-1.5"
|
||||
/>
|
||||
</DropdownMenuTrigger>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom">Show/hide columns</TooltipContent>
|
||||
</Tooltip>
|
||||
<DropdownMenuContent side="bottom" align="start" className="max-h-[300px] overflow-y-auto">
|
||||
{columns.map((column) => {
|
||||
const columnKey = column.name
|
||||
const isVisible = !hiddenColumns.has(columnKey)
|
||||
return (
|
||||
<DropdownMenuCheckboxItem
|
||||
key={columnKey}
|
||||
checked={isVisible}
|
||||
onSelect={(e) => e.preventDefault()}
|
||||
onCheckedChange={() => handleToggleColumnVisibility(columnKey, !isVisible)}
|
||||
>
|
||||
{column.name}
|
||||
</DropdownMenuCheckboxItem>
|
||||
)
|
||||
})}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
}
|
||||
@@ -36,6 +36,7 @@ import {
|
||||
Separator,
|
||||
SonnerProgress,
|
||||
} from 'ui'
|
||||
import { ColumnVisibility } from './ColumnVisibility'
|
||||
import FilterPopover from './filter/FilterPopover'
|
||||
import { SortPopover } from './sort'
|
||||
// [Joshen] CSV exports require this guard as a fail-safe if the table is
|
||||
@@ -110,6 +111,7 @@ const DefaultHeader = () => {
|
||||
<div className="flex items-center gap-2">
|
||||
<FilterPopover filters={urlFilters} onApplyFilters={onApplyFilters} />
|
||||
<SortPopover sorts={urlSorts} onApplySorts={onApplySorts} />
|
||||
<ColumnVisibility />
|
||||
</div>
|
||||
{canAddNew && (
|
||||
<>
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { useCallback } from 'react'
|
||||
import { useParams } from 'common'
|
||||
import { getTabsStore, updateTabHiddenColumns } from 'state/tabs'
|
||||
|
||||
export function useSaveColumnVisibilityToTabs() {
|
||||
const { ref: projectRef } = useParams()
|
||||
|
||||
const saveHiddenColumnsToTab = useCallback(
|
||||
(hiddenColumnsSet: Set<string>) => {
|
||||
if (!projectRef) {
|
||||
console.warn('[useSaveColumnVisibilityToTabs] Missing projectRef, cannot save state.')
|
||||
return
|
||||
}
|
||||
|
||||
// Get the current active tab ID directly within the callback
|
||||
// This ensures we use the latest active tab when the save occurs
|
||||
const tabsState = getTabsStore(projectRef)
|
||||
const activeTabId = tabsState.activeTab
|
||||
|
||||
if (activeTabId) {
|
||||
const hiddenColumnsArray = Array.from(hiddenColumnsSet).sort()
|
||||
updateTabHiddenColumns(projectRef, activeTabId, hiddenColumnsArray)
|
||||
} else {
|
||||
console.warn(
|
||||
'[useSaveColumnVisibilityToTabs] No active tab found, cannot save hidden columns state.'
|
||||
)
|
||||
}
|
||||
},
|
||||
[projectRef] // Dependency on projectRef
|
||||
)
|
||||
|
||||
return { saveHiddenColumnsToTab }
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useUrlState } from 'hooks/ui/useUrlState'
|
||||
// Import the hook for saving to tabs store
|
||||
import { useSaveColumnVisibilityToTabs } from './useSaveColumnVisibilityToTabs'
|
||||
|
||||
// Comma-separated string in URL, Set<string> in hook
|
||||
const URL_PARAM_KEY = 'hidden_cols'
|
||||
|
||||
export function useTableColumnVisibility() {
|
||||
const [params, setParams] = useUrlState()
|
||||
// Get the function to save to tabs store
|
||||
const { saveHiddenColumnsToTab } = useSaveColumnVisibilityToTabs()
|
||||
|
||||
const urlHiddenColumnsString = useMemo(() => {
|
||||
const val = params[URL_PARAM_KEY]
|
||||
return typeof val === 'string' ? val : ''
|
||||
}, [params])
|
||||
|
||||
const hiddenColumnsSet = useMemo(() => {
|
||||
return new Set<string>(urlHiddenColumnsString ? urlHiddenColumnsString.split(',') : [])
|
||||
}, [urlHiddenColumnsString])
|
||||
|
||||
const setHiddenColumnsUrl = useCallback(
|
||||
(newHiddenColumns: Set<string>) => {
|
||||
const newUrlString = Array.from(newHiddenColumns).sort().join(',')
|
||||
setParams((prevParams) => ({
|
||||
...prevParams,
|
||||
[URL_PARAM_KEY]: newUrlString || undefined, // Remove param if empty
|
||||
}))
|
||||
// Call save to tabs store whenever the whole set changes via URL
|
||||
saveHiddenColumnsToTab(newHiddenColumns)
|
||||
},
|
||||
[setParams, saveHiddenColumnsToTab] // Add saveHiddenColumnsToTab dependency
|
||||
)
|
||||
|
||||
// Function to conveniently hide a single column
|
||||
const hideColumnUrl = useCallback(
|
||||
(columnName: string) => {
|
||||
const newSet = new Set(hiddenColumnsSet)
|
||||
newSet.add(columnName)
|
||||
setHiddenColumnsUrl(newSet) // This will now also trigger saveHiddenColumnsToTab
|
||||
},
|
||||
[hiddenColumnsSet, setHiddenColumnsUrl]
|
||||
)
|
||||
|
||||
// Function to conveniently show a single column
|
||||
const showColumnUrl = useCallback(
|
||||
(columnName: string) => {
|
||||
const newSet = new Set(hiddenColumnsSet)
|
||||
newSet.delete(columnName)
|
||||
setHiddenColumnsUrl(newSet) // This will now also trigger saveHiddenColumnsToTab
|
||||
},
|
||||
[hiddenColumnsSet, setHiddenColumnsUrl]
|
||||
)
|
||||
|
||||
return {
|
||||
hiddenColumns: hiddenColumnsSet, // The current Set<string> of hidden columns from URL
|
||||
setHiddenColumnsUrl, // Function to update the URL param with a full Set
|
||||
hideColumn: hideColumnUrl, // Function to hide a specific column (updates URL)
|
||||
showColumn: showColumnUrl, // Function to show a specific column (updates URL)
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,8 @@ export interface Tab {
|
||||
isPreview?: boolean // Optional flag indicating if the tab is in preview mode
|
||||
createdAt?: Date // Optional timestamp for when the tab was created
|
||||
updatedAt?: Date // Optional timestamp for when the tab was last updated
|
||||
// Stores the names of columns hidden by the user for this specific tab (session state)
|
||||
hiddenColumns?: string[]
|
||||
}
|
||||
|
||||
// Interface representing the state of tabs
|
||||
@@ -390,3 +392,26 @@ export function removeTabsByEditor(ref: string | undefined, type: 'table' | 'sql
|
||||
|
||||
removeTabs(ref, tabIdsToRemove)
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to update hidden columns for a specific tab in the tabs store.
|
||||
*
|
||||
* @param ref Project ref.
|
||||
* @param tabId ID of the tab to update.
|
||||
* @param hiddenColumns Array of column names to be marked as hidden.
|
||||
* @returns {void}
|
||||
*/
|
||||
export const updateTabHiddenColumns = (
|
||||
ref: string | undefined,
|
||||
tabId: string,
|
||||
hiddenColumns: string[]
|
||||
) => {
|
||||
if (!ref) return
|
||||
const store = getTabsStore(ref)
|
||||
if (store.tabsMap[tabId]) {
|
||||
// Update the hiddenColumns array for the specified tab
|
||||
store.tabsMap[tabId].hiddenColumns = hiddenColumns
|
||||
// Update the timestamp to reflect the change
|
||||
store.tabsMap[tabId].updatedAt = new Date()
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user