This commit is contained in:
Jonathan Summers-Muir committed 2025-04-19 19:02:35 +08:00
1 parent 013bc63765
commit 8a268d7343
2 files changed
+93 -1

No files matched your search

@@ -1,10 +1,13 @@
import { ChevronDown, Edit, Lock, Trash, Unlock } from 'lucide-react'
import type { Sort } from 'components/grid/types'
import { ArrowDown, ArrowUp, ChevronDown, Edit, Lock, Trash, Unlock } from 'lucide-react'
import type { CalculatedColumn } from 'react-data-grid'
import { useTableSort } from 'components/grid/hooks/useTableSort'
import { useTableEditorStateSnapshot } from 'state/table-editor'
import { useTableEditorTableStateSnapshot } from 'state/table-editor-table'
import {
Button,
cn,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
@@ -23,8 +26,10 @@ interface ColumnMenuProps {
const ColumnMenu = ({ column, isEncrypted }: ColumnMenuProps) => {
const tableEditorSnap = useTableEditorStateSnapshot()
const snap = useTableEditorTableStateSnapshot()
const { sorts, addOrUpdateSort, removeSort } = useTableSort()
const columnKey = column.key
const columnName = column.name as string
function onFreezeColumn() {
snap.freezeColumn(columnKey)
@@ -48,7 +53,22 @@ const ColumnMenu = ({ column, isEncrypted }: ColumnMenuProps) => {
}
}
function onSortColumn(ascending: boolean) {
if (!columnKey) return
const currentSort = sorts.find((s) => s.column === columnKey)
if (currentSort && currentSort.ascending === ascending) {
// Clicked the currently active sort: Remove it
removeSort(columnKey)
} else {
// Clicked the inactive sort or column wasn't sorted: Add or update it
addOrUpdateSort(columnKey, ascending)
}
}
function renderMenu() {
const currentSort: Sort | undefined = sorts.find((s) => s.column === columnKey)
return (
<>
{snap.editable && (
@@ -80,6 +100,29 @@ const ColumnMenu = ({ column, isEncrypted }: ColumnMenuProps) => {
</>
)}
</DropdownMenuItem>
<Separator />
<DropdownMenuItem
className={cn(
'space-x-2',
currentSort?.ascending && 'bg-surface-200 dark:bg-surface-400 text-foreground'
)}
onClick={() => onSortColumn(true)}
>
<ArrowUp size={14} strokeWidth={currentSort?.ascending ? 3 : 1} />
<p>Sort Ascending</p>
</DropdownMenuItem>
<DropdownMenuItem
className={cn(
'space-x-2',
currentSort &&
!currentSort.ascending &&
'bg-surface-200 dark:bg-surface-400 text-foreground'
)}
onClick={() => onSortColumn(false)}
>
<ArrowDown size={14} strokeWidth={currentSort && !currentSort.ascending ? 3 : 1} />
<p>Sort Descending</p>
</DropdownMenuItem>
{snap.editable && (
<>
<Separator />
@@ -44,9 +44,58 @@ export function useTableSort() {
[snap, setParams, saveSortsAndTriggerSideEffects]
)
/**
* Adds a new sort for a column or updates the direction of an existing one.
* New sorts are added to the beginning of the array (highest precedence).
* If the column already exists, its `ascending` direction is updated.
* Calls `onApplySorts` to update URL parameters and trigger side effects.
*
* @param columnKey The key/name of the column to sort.
* @param ascending The sort direction (true for ascending, false for descending).
*/
const addOrUpdateSort = useCallback(
(columnKey: string, ascending: boolean) => {
if (!tableName || !columnKey) return
// Use the derived 'sorts' state from the hook
const existingSortIndex = sorts.findIndex((s) => s.column === columnKey)
let newSorts = [...sorts] // Create a mutable copy
if (existingSortIndex !== -1) {
// Column already exists in sorts: Update the existing sort (toggle handled by removeSort)
newSorts[existingSortIndex] = { ...newSorts[existingSortIndex], ascending: ascending }
} else {
// Column doesn't exist in sorts: Add it to the beginning
newSorts.unshift({ table: tableName, column: columnKey, ascending: ascending })
}
onApplySorts(newSorts)
},
[tableName, sorts, onApplySorts] // Depend on derived sorts and callback
)
/**
* Removes a sort criterion for a specific column.
* Calls `onApplySorts` with the filtered array to update URL parameters and trigger side effects.
*
* @param columnKey The key/name of the column to remove from sorting.
*/
const removeSort = useCallback(
(columnKey: string) => {
if (!tableName || !columnKey) return
// Use the derived 'sorts' state from the hook
const newSorts = sorts.filter((s) => s.column !== columnKey)
onApplySorts(newSorts)
},
[tableName, sorts, onApplySorts] // Depend on derived sorts and callback
)
return {
sorts,
urlSorts,
onApplySorts,
addOrUpdateSort,
removeSort,
}
}