fix(ui): propagates sort change events through list query provider (#7968)

This commit is contained in:
Jacob Fletcher
2024-08-29 13:18:05 -04:00
committed by GitHub
parent 6893f404ac
commit c0728220ff
2 changed files with 29 additions and 24 deletions

View File

@@ -1,8 +1,7 @@
'use client' 'use client'
import type { FieldBase } from 'payload' import type { FieldBase } from 'payload'
// TODO: abstract the `next/navigation` dependency out from this component import React from 'react'
import React, { useCallback } from 'react'
import { ChevronIcon } from '../../icons/Chevron/index.js' import { ChevronIcon } from '../../icons/Chevron/index.js'
import { useListQuery } from '../../providers/ListQuery/index.js' import { useListQuery } from '../../providers/ListQuery/index.js'
@@ -11,10 +10,10 @@ import { useTranslation } from '../../providers/Translation/index.js'
import './index.scss' import './index.scss'
export type SortColumnProps = { export type SortColumnProps = {
Label: React.ReactNode readonly Label: React.ReactNode
disable?: boolean readonly disable?: boolean
label?: FieldBase['label'] readonly label?: FieldBase['label']
name: string readonly name: string
} }
const baseClass = 'sort-column' const baseClass = 'sort-column'
@@ -22,7 +21,7 @@ const baseClass = 'sort-column'
export const SortColumn: React.FC<SortColumnProps> = (props) => { export const SortColumn: React.FC<SortColumnProps> = (props) => {
const { name, Label, disable = false, label } = props const { name, Label, disable = false, label } = props
const { searchParams } = useSearchParams() const { searchParams } = useSearchParams()
const { refineListData } = useListQuery() const { handleSortChange } = useListQuery()
const { t } = useTranslation() const { t } = useTranslation()
const { sort } = searchParams const { sort } = searchParams
@@ -40,15 +39,6 @@ export const SortColumn: React.FC<SortColumnProps> = (props) => {
descClasses.push(`${baseClass}--active`) descClasses.push(`${baseClass}--active`)
} }
const setSort = useCallback(
async (newSort: string) => {
await refineListData({
sort: newSort,
})
},
[refineListData],
)
return ( return (
<div className={baseClass}> <div className={baseClass}>
<span className={`${baseClass}__label`}>{Label}</span> <span className={`${baseClass}__label`}>{Label}</span>
@@ -60,7 +50,7 @@ export const SortColumn: React.FC<SortColumnProps> = (props) => {
label, label,
})} })}
className={[...ascClasses, `${baseClass}__button`].filter(Boolean).join(' ')} className={[...ascClasses, `${baseClass}__button`].filter(Boolean).join(' ')}
onClick={() => void setSort(asc)} onClick={() => void handleSortChange(asc)}
type="button" type="button"
> >
<ChevronIcon direction="up" /> <ChevronIcon direction="up" />
@@ -71,7 +61,7 @@ export const SortColumn: React.FC<SortColumnProps> = (props) => {
label, label,
})} })}
className={[...descClasses, `${baseClass}__button`].filter(Boolean).join(' ')} className={[...descClasses, `${baseClass}__button`].filter(Boolean).join(' ')}
onClick={() => void setSort(desc)} onClick={() => void handleSortChange(desc)}
type="button" type="button"
> >
<ChevronIcon /> <ChevronIcon />

View File

@@ -20,6 +20,7 @@ type PropHandlers = {
handleSortChange?: (sort: string) => Promise<void> | void handleSortChange?: (sort: string) => Promise<void> | void
handleWhereChange?: (where: Where) => Promise<void> | void handleWhereChange?: (where: Where) => Promise<void> | void
} }
type ContextHandlers = { type ContextHandlers = {
handlePageChange?: (page: number) => Promise<void> handlePageChange?: (page: number) => Promise<void>
handlePerPageChange?: (limit: number) => Promise<void> handlePerPageChange?: (limit: number) => Promise<void>
@@ -29,12 +30,12 @@ type ContextHandlers = {
} }
export type ListQueryProps = { export type ListQueryProps = {
children: React.ReactNode readonly children: React.ReactNode
data: PaginatedDocs readonly data: PaginatedDocs
defaultLimit?: number readonly defaultLimit?: number
defaultSort?: string readonly defaultSort?: string
modifySearchParams?: boolean readonly modifySearchParams?: boolean
preferenceKey?: string readonly preferenceKey?: string
} & PropHandlers } & PropHandlers
export type ListQueryContext = { export type ListQueryContext = {
@@ -81,6 +82,7 @@ export const ListQueryProvider: React.FC<ListQueryProps> = ({
} }
let pageQuery = 'page' in query ? query.page : currentQuery?.page let pageQuery = 'page' in query ? query.page : currentQuery?.page
if ('where' in query || 'search' in query) { if ('where' in query || 'search' in query) {
pageQuery = '1' pageQuery = '1'
} }
@@ -92,10 +94,12 @@ export const ListQueryProvider: React.FC<ListQueryProps> = ({
updatedPreferences.limit = query.limit updatedPreferences.limit = query.limit
updatePreferences = true updatePreferences = true
} }
if ('sort' in query) { if ('sort' in query) {
updatedPreferences.sort = query.sort updatedPreferences.sort = query.sort
updatePreferences = true updatePreferences = true
} }
if (updatePreferences && preferenceKey) { if (updatePreferences && preferenceKey) {
await setPreference(preferenceKey, updatedPreferences) await setPreference(preferenceKey, updatedPreferences)
} }
@@ -118,42 +122,51 @@ export const ListQueryProvider: React.FC<ListQueryProps> = ({
if (typeof handlePageChangeFromProps === 'function') { if (typeof handlePageChangeFromProps === 'function') {
await handlePageChangeFromProps(arg) await handlePageChangeFromProps(arg)
} }
await refineListData({ page: String(arg) }) await refineListData({ page: String(arg) })
}, },
[refineListData, handlePageChangeFromProps], [refineListData, handlePageChangeFromProps],
) )
const handlePerPageChange = React.useCallback( const handlePerPageChange = React.useCallback(
async (arg: number) => { async (arg: number) => {
if (typeof handlePerPageChangeFromProps === 'function') { if (typeof handlePerPageChangeFromProps === 'function') {
await handlePerPageChangeFromProps(arg) await handlePerPageChangeFromProps(arg)
} }
await refineListData({ limit: String(arg) }) await refineListData({ limit: String(arg) })
}, },
[refineListData, handlePerPageChangeFromProps], [refineListData, handlePerPageChangeFromProps],
) )
const handleSearchChange = React.useCallback( const handleSearchChange = React.useCallback(
async (arg: string) => { async (arg: string) => {
if (typeof handleSearchChangeFromProps === 'function') { if (typeof handleSearchChangeFromProps === 'function') {
await handleSearchChangeFromProps(arg) await handleSearchChangeFromProps(arg)
} }
await refineListData({ search: arg }) await refineListData({ search: arg })
}, },
[refineListData, handleSearchChangeFromProps], [refineListData, handleSearchChangeFromProps],
) )
const handleSortChange = React.useCallback( const handleSortChange = React.useCallback(
async (arg: string) => { async (arg: string) => {
if (typeof handleSortChangeFromProps === 'function') { if (typeof handleSortChangeFromProps === 'function') {
await handleSortChangeFromProps(arg) await handleSortChangeFromProps(arg)
} }
await refineListData({ sort: arg }) await refineListData({ sort: arg })
}, },
[refineListData, handleSortChangeFromProps], [refineListData, handleSortChangeFromProps],
) )
const handleWhereChange = React.useCallback( const handleWhereChange = React.useCallback(
async (arg: Where) => { async (arg: Where) => {
if (typeof handleWhereChangeFromProps === 'function') { if (typeof handleWhereChangeFromProps === 'function') {
await handleWhereChangeFromProps(arg) await handleWhereChangeFromProps(arg)
} }
await refineListData({ where: arg }) await refineListData({ where: arg })
}, },
[refineListData, handleWhereChangeFromProps], [refineListData, handleWhereChangeFromProps],
@@ -168,10 +181,12 @@ export const ListQueryProvider: React.FC<ListQueryProps> = ({
currentQuery.limit = String(defaultLimit) currentQuery.limit = String(defaultLimit)
shouldUpdateQueryString = true shouldUpdateQueryString = true
} }
if (defaultSort && !('sort' in currentQuery)) { if (defaultSort && !('sort' in currentQuery)) {
currentQuery.sort = defaultSort currentQuery.sort = defaultSort
shouldUpdateQueryString = true shouldUpdateQueryString = true
} }
if (shouldUpdateQueryString) { if (shouldUpdateQueryString) {
router.replace(`?${qs.stringify(currentQuery)}`) router.replace(`?${qs.stringify(currentQuery)}`)
} }