fix: Fix the sort feature in the Table editor (#26865)

* Expand the Sort type with a table property.

* Add a qualifier for the sort when sending a fetch table query.

* Fix the tests.
This commit is contained in:
Ivan Vasilov authored and GitHub committed 2024-05-29 17:02:54 -02:30
1 parent 3deeeb4988
commit e1cf9d61ae
8 files changed
+36 -39

No files matched your search

+1 -1
View File
@@ -133,7 +133,7 @@ const SupabaseGridLayout = (props: SupabaseGridProps) => {
const [{ sort, filter }, setParams] = useUrlState({
arrayKeys: ['sort', 'filter'],
})
const sorts = formatSortURLParams(sort as string[])
const sorts = formatSortURLParams(props.table.name, sort as string[] | undefined)
const filters = formatFilterURLParams(filter as string[])
const roleImpersonationState = useRoleImpersonationStateSnapshot()
@@ -1,10 +1,11 @@
import AwesomeDebouncePromise from 'awesome-debounce-promise'
import type { Filter } from 'components/grid/types'
import { compact } from 'lodash'
import type { Dictionary } from 'types'
import { FilterOperatorOptions } from './components/header/filter'
import { STORAGE_KEY_PREFIX } from './constants'
import { InitialStateType } from './store/reducers'
import type { Sort, SupabaseGridProps, SupaColumn, SupaTable } from './types'
import type { Dictionary } from 'types'
import { FilterOperatorOptions } from './components/header/filter'
import type { Filter } from 'components/grid/types'
/**
* Ensure that if editable is false, we should remove all editing actions
@@ -26,19 +27,18 @@ export function cleanupProps(props: SupabaseGridProps) {
}
}
export function formatSortURLParams(sort?: string[]) {
return (
Array.isArray(sort)
? sort
.map((s) => {
const [column, order] = s.split(':')
// Reject any possible malformed sort param
if (!column || !order) return undefined
else return { column, ascending: order === 'asc' }
})
.filter((s) => s !== undefined)
: []
) as Sort[]
export function formatSortURLParams(tableName: string, sort?: string[]): Sort[] {
if (Array.isArray(sort)) {
return compact(
sort.map((s) => {
const [column, order] = s.split(':')
// Reject any possible malformed sort param
if (!column || !order) return undefined
else return { table: tableName, column, ascending: order === 'asc' }
})
)
}
return []
}
export function formatFilterURLParams(filter?: string[]): Filter[] {
@@ -66,8 +66,8 @@ export interface SortOverlayProps {
const SortOverlay = ({ table, sorts: sortsFromUrl, onApplySorts }: SortOverlayProps) => {
const initialSorts = useMemo(
() => formatSortURLParams((sortsFromUrl as string[]) ?? []),
[sortsFromUrl]
() => formatSortURLParams(table.name, sortsFromUrl ?? []),
[table.name, sortsFromUrl]
)
const [sorts, setSorts] = useState<Sort[]>(initialSorts)
@@ -82,7 +82,7 @@ const SortOverlay = ({ table, sorts: sortsFromUrl, onApplySorts }: SortOverlayPr
}) || []
function onAddSort(columnName: string | number) {
setSorts([...sorts, { column: columnName as string, ascending: true }])
setSorts([...sorts, { table: table.name, column: columnName as string, ascending: true }])
}
const onDeleteSort = useCallback((column: string) => {
@@ -1,6 +1,6 @@
import { ident, literal, format } from '@scaleleap/pg-format'
import type { Filter, QueryPagination, QueryTable, Sort } from '../types'
import { format, ident, literal } from '@scaleleap/pg-format'
import type { Dictionary } from 'types'
import type { Filter, QueryPagination, QueryTable, Sort } from '../types'
export function countQuery(
table: QueryTable,
@@ -223,7 +223,7 @@ function applySorts(query: string, sorts: Sort[]) {
.map((x) => {
const order = x.ascending ? 'asc' : 'desc'
const nullOrder = x.nullsFirst ? 'nulls first' : 'nulls last'
return `${ident(x.column)} ${order} ${nullOrder}`
return `${ident(x.table)}.${ident(x.column)} ${order} ${nullOrder}`
})
.join(', ')}`
return query
@@ -1,11 +1,11 @@
import type { Filter, FilterOperator, QueryTable, Sort } from '../types'
import type { Dictionary } from 'types'
import type { Filter, FilterOperator, QueryTable, Sort } from '../types'
import { IQueryModifier, QueryModifier } from './QueryModifier'
export interface IQueryFilter {
filter: (column: string, operator: FilterOperator, value: string) => IQueryFilter
match: (criteria: Dictionary<any>) => IQueryFilter
order: (column: string, ascending?: boolean, nullsFirst?: boolean) => IQueryFilter
order: (table: string, column: string, ascending?: boolean, nullsFirst?: boolean) => IQueryFilter
}
export class QueryFilter implements IQueryFilter, IQueryModifier {
@@ -31,8 +31,9 @@ export class QueryFilter implements IQueryFilter, IQueryModifier {
return this
}
order(column: string, ascending = true, nullsFirst = false) {
order(table: string, column: string, ascending = true, nullsFirst = false) {
this.sorts.push({
table: table,
column: column,
ascending,
nullsFirst,
@@ -1,6 +1,7 @@
import { CalculatedColumn, RenderHeaderCellProps } from 'react-data-grid'
export interface Sort {
table: string
column: string
ascending?: boolean
nullsFirst?: boolean
@@ -60,7 +60,7 @@ export const fetchAllTableRows = async ({
queryChains = queryChains.filter(filter.column, filter.operator, value)
})
sorts.forEach((sort) => {
queryChains = queryChains.order(sort.column, sort.ascending, sort.nullsFirst)
queryChains = queryChains.order(sort.table, sort.column, sort.ascending, sort.nullsFirst)
})
// Starting from page 0, fetch 500 records per call
@@ -134,7 +134,7 @@ export const getTableRowsSqlQuery = ({
queryChains = queryChains.filter(x.column, x.operator, value)
})
sorts.forEach((x) => {
queryChains = queryChains.order(x.column, x.ascending, x.nullsFirst)
queryChains = queryChains.order(x.table, x.column, x.ascending, x.nullsFirst)
})
// getPagination is expecting to start from 0
@@ -1,26 +1,21 @@
import { formatSortURLParams, formatFilterURLParams } from 'components/grid/SupabaseGrid.utils'
import { formatFilterURLParams, formatSortURLParams } from 'components/grid/SupabaseGrid.utils'
// Sort URL syntax: `column:order`
describe('SupabaseGrid.utils: formatSortURLParams', () => {
test('should return an array of sort options based on URL params', () => {
const mockInput = ['id:asc', 'name:desc']
const output = formatSortURLParams(mockInput)
const output = formatSortURLParams('fakeTable', mockInput)
expect(output).toStrictEqual([
{
column: 'id',
ascending: true,
},
{
column: 'name',
ascending: false,
},
{ table: 'fakeTable', column: 'id', ascending: true },
{ table: 'fakeTable', column: 'name', ascending: false },
])
})
test('should reject any malformed sort options based on URL params', () => {
const mockInput = ['id', 'name:asc', ':asc']
const output = formatSortURLParams(mockInput)
const output = formatSortURLParams('fakeTable', mockInput)
expect(output).toStrictEqual([
{
table: 'fakeTable',
column: 'name',
ascending: true,
},