All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
- Integrated InfoActionButtons into multiple components across the Finance and Inventory sections, enhancing user interaction and providing contextual actions for invoices, payment policies, payments, tax records, and various inventory items. - Updated the respective components to include the new buttons with appropriate object types and list mode settings, improving the overall functionality and user experience in the dashboard.
750 lines
21 KiB
JavaScript
750 lines
21 KiB
JavaScript
import {
|
|
createContext,
|
|
useCallback,
|
|
useContext,
|
|
useEffect,
|
|
useMemo,
|
|
useRef,
|
|
useState
|
|
} from 'react'
|
|
import { useSearchParams } from 'react-router-dom'
|
|
import PropTypes from 'prop-types'
|
|
|
|
const TableStateContext = createContext(null)
|
|
|
|
// eslint-disable-next-line react-refresh/only-export-components
|
|
export { TableStateContext }
|
|
|
|
export const FILTER_URL_PARAM = 'filter'
|
|
export const SORT_URL_PARAM = 'sort'
|
|
export const VIEW_URL_PARAM = 'viewId'
|
|
|
|
const getSessionFilterKey = (scope) => `tableState:${scope}:filter`
|
|
const getSessionSortKey = (scope) => `tableState:${scope}:sort`
|
|
const getSessionListFilterKey = (scope) => `tableState:${scope}:listFilter`
|
|
const getSessionListSortKey = (scope) => `tableState:${scope}:listSort`
|
|
const getSessionListViewKey = (scope) => `tableState:${scope}:listView`
|
|
|
|
// eslint-disable-next-line react-refresh/only-export-components
|
|
export const getActiveFilterValues = (filterState) => {
|
|
const active = {}
|
|
Object.entries(filterState || {}).forEach(([k, v]) => {
|
|
if (v !== '' && v !== undefined) active[k] = v
|
|
})
|
|
return active
|
|
}
|
|
|
|
const parseJsonParam = (raw) => {
|
|
if (!raw) return null
|
|
try {
|
|
const parsed = JSON.parse(raw)
|
|
return typeof parsed === 'object' && parsed !== null ? parsed : null
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
const readFilterFromUrl = (searchParams) =>
|
|
parseJsonParam(searchParams.get(FILTER_URL_PARAM))
|
|
|
|
const readSortFromUrl = (searchParams) => {
|
|
const parsed = parseJsonParam(searchParams.get(SORT_URL_PARAM))
|
|
if (!parsed?.field || !parsed?.order) return null
|
|
return { field: parsed.field, order: parsed.order }
|
|
}
|
|
|
|
const readViewFromUrl = (searchParams) => searchParams.get(VIEW_URL_PARAM) || null
|
|
|
|
const readFilterFromSession = (scope) => {
|
|
try {
|
|
return parseJsonParam(sessionStorage.getItem(getSessionFilterKey(scope)))
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
// eslint-disable-next-line react-refresh/only-export-components
|
|
export const hasStoredSessionFilter = (scope) => {
|
|
if (!scope) return false
|
|
return Object.keys(getActiveFilterValues(readFilterFromSession(scope) || {})).length > 0
|
|
}
|
|
|
|
const readSortFromSession = (scope) => {
|
|
try {
|
|
const parsed = parseJsonParam(sessionStorage.getItem(getSessionSortKey(scope)))
|
|
if (!parsed?.field || !parsed?.order) return null
|
|
return { field: parsed.field, order: parsed.order }
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
const writeFilterToSession = (scope, filter) => {
|
|
const key = getSessionFilterKey(scope)
|
|
if (Object.keys(filter).length > 0) {
|
|
sessionStorage.setItem(key, JSON.stringify(filter))
|
|
} else {
|
|
sessionStorage.removeItem(key)
|
|
}
|
|
}
|
|
|
|
const writeSortToSession = (scope, sorter) => {
|
|
const key = getSessionSortKey(scope)
|
|
if (sorter?.field && sorter?.order) {
|
|
sessionStorage.setItem(key, JSON.stringify(sorter))
|
|
} else {
|
|
sessionStorage.removeItem(key)
|
|
}
|
|
}
|
|
|
|
const readListFilterFromSession = (scope) => {
|
|
try {
|
|
return parseJsonParam(sessionStorage.getItem(getSessionListFilterKey(scope)))
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
const readListSortFromSession = (scope) => {
|
|
try {
|
|
const parsed = parseJsonParam(sessionStorage.getItem(getSessionListSortKey(scope)))
|
|
if (!parsed?.field || !parsed?.order) return null
|
|
return { field: parsed.field, order: parsed.order }
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
const writeListFilterToSession = (scope, filter) => {
|
|
const key = getSessionListFilterKey(scope)
|
|
if (Object.keys(filter).length > 0) {
|
|
sessionStorage.setItem(key, JSON.stringify(filter))
|
|
} else {
|
|
sessionStorage.removeItem(key)
|
|
}
|
|
}
|
|
|
|
const writeListSortToSession = (scope, sorter) => {
|
|
const key = getSessionListSortKey(scope)
|
|
if (sorter?.field && sorter?.order) {
|
|
sessionStorage.setItem(key, JSON.stringify(sorter))
|
|
} else {
|
|
sessionStorage.removeItem(key)
|
|
}
|
|
}
|
|
|
|
const readListViewFromSession = (scope) => {
|
|
try {
|
|
const parsed = parseJsonParam(sessionStorage.getItem(getSessionListViewKey(scope)))
|
|
if (!parsed?.id) return null
|
|
return {
|
|
id: String(parsed.id),
|
|
name: parsed.name || null
|
|
}
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
const writeListViewToSession = (scope, view) => {
|
|
const key = getSessionListViewKey(scope)
|
|
if (view?.id) {
|
|
sessionStorage.setItem(
|
|
key,
|
|
JSON.stringify({ id: String(view.id), name: view.name || null })
|
|
)
|
|
} else {
|
|
sessionStorage.removeItem(key)
|
|
}
|
|
}
|
|
|
|
const normalizeSorter = (sorter) => {
|
|
if (sorter?.field && sorter?.order) {
|
|
return { field: sorter.field, order: sorter.order }
|
|
}
|
|
return {}
|
|
}
|
|
|
|
export const TableStateProvider = ({ children }) => {
|
|
const [searchParams, setSearchParams] = useSearchParams()
|
|
const [pageFilters, setPageFilters] = useState({})
|
|
const [pageSorters, setPageSorters] = useState({})
|
|
// Effective list filters (view filter + user filters). Survives navigating
|
|
// from the list page to an info page so breadcrumb/neighbors keep working.
|
|
const [objectListFilters, setObjectListFilters] = useState({})
|
|
const [objectListSorters, setObjectListSorters] = useState({})
|
|
// Active list view (id + name) per object type — same survival pattern as filters.
|
|
const [objectListViews, setObjectListViews] = useState({})
|
|
const searchParamsRef = useRef(searchParams)
|
|
// Tracks an in-flight optimistic URL write so a render with stale router
|
|
// searchParams cannot clobber searchParamsRef and resurrect deleted params
|
|
// (e.g. viewId briefly cleared on All, then written back by persistTableState).
|
|
const pendingSearchParamsRef = useRef(null)
|
|
const previousSearchParamsRef = useRef(searchParams.toString())
|
|
|
|
useEffect(() => {
|
|
const current = searchParams.toString()
|
|
if (pendingSearchParamsRef.current != null) {
|
|
if (current === pendingSearchParamsRef.current) {
|
|
pendingSearchParamsRef.current = null
|
|
} else if (current === previousSearchParamsRef.current) {
|
|
// Stale snapshot from before our write — keep the optimistic ref.
|
|
return
|
|
} else {
|
|
// External navigation while a write was pending — accept it.
|
|
pendingSearchParamsRef.current = null
|
|
}
|
|
}
|
|
previousSearchParamsRef.current = current
|
|
searchParamsRef.current = searchParams
|
|
}, [searchParams])
|
|
|
|
// Keep sequential URL writes in the same tick from clobbering each other
|
|
// (e.g. persistView then persistTableState both calling setSearchParams).
|
|
const updateSearchParams = useCallback(
|
|
(mutator) => {
|
|
const previous = searchParamsRef.current.toString()
|
|
const next = new URLSearchParams(searchParamsRef.current)
|
|
mutator(next)
|
|
previousSearchParamsRef.current = previous
|
|
searchParamsRef.current = next
|
|
pendingSearchParamsRef.current = next.toString()
|
|
setSearchParams(next, { replace: true })
|
|
},
|
|
[setSearchParams]
|
|
)
|
|
|
|
const getPersistedFilter = useCallback(
|
|
(scope, { useFilterInUrl = false, useFilterInSession = false } = {}) => {
|
|
if (useFilterInUrl) {
|
|
const fromUrl = readFilterFromUrl(searchParams)
|
|
if (fromUrl) return fromUrl
|
|
}
|
|
if (useFilterInSession) {
|
|
const fromSession = readFilterFromSession(scope)
|
|
if (fromSession) return fromSession
|
|
}
|
|
return {}
|
|
},
|
|
[searchParams]
|
|
)
|
|
|
|
const getPersistedSorter = useCallback(
|
|
(scope, { useSortInUrl = false, useSortInSession = false } = {}) => {
|
|
if (useSortInUrl) {
|
|
const fromUrl = readSortFromUrl(searchParams)
|
|
if (fromUrl) return fromUrl
|
|
}
|
|
if (useSortInSession) {
|
|
const fromSession = readSortFromSession(scope)
|
|
if (fromSession) return fromSession
|
|
}
|
|
return {}
|
|
},
|
|
[searchParams]
|
|
)
|
|
|
|
const getViewFromUrl = useCallback(
|
|
() => readViewFromUrl(searchParams),
|
|
[searchParams]
|
|
)
|
|
|
|
const persistView = useCallback(
|
|
(viewId, { clearFilterSort = Boolean(viewId) } = {}) => {
|
|
updateSearchParams((next) => {
|
|
// Drop legacy `view` param that previously stored `_reference`
|
|
next.delete('view')
|
|
if (viewId) {
|
|
next.set(VIEW_URL_PARAM, String(viewId))
|
|
} else {
|
|
next.delete(VIEW_URL_PARAM)
|
|
}
|
|
// View filter/sort live on the view object — never in the URL
|
|
if (clearFilterSort) {
|
|
next.delete(FILTER_URL_PARAM)
|
|
next.delete(SORT_URL_PARAM)
|
|
}
|
|
})
|
|
},
|
|
[updateSearchParams]
|
|
)
|
|
|
|
const persistFilter = useCallback(
|
|
(
|
|
scope,
|
|
filterState,
|
|
{ saveFilterInSession = false, saveFilterInUrl = false } = {}
|
|
) => {
|
|
const active = getActiveFilterValues(filterState)
|
|
if (saveFilterInSession) {
|
|
writeFilterToSession(scope, active)
|
|
}
|
|
if (saveFilterInUrl) {
|
|
updateSearchParams((next) => {
|
|
if (Object.keys(active).length > 0) {
|
|
next.set(FILTER_URL_PARAM, JSON.stringify(active))
|
|
} else {
|
|
next.delete(FILTER_URL_PARAM)
|
|
}
|
|
})
|
|
}
|
|
},
|
|
[updateSearchParams]
|
|
)
|
|
|
|
const persistSort = useCallback(
|
|
(
|
|
scope,
|
|
sorter,
|
|
{ saveSortInSession = false, saveSortInUrl = false } = {}
|
|
) => {
|
|
const nextSorter = normalizeSorter(sorter)
|
|
if (saveSortInSession) {
|
|
writeSortToSession(scope, nextSorter)
|
|
}
|
|
if (saveSortInUrl) {
|
|
updateSearchParams((next) => {
|
|
if (nextSorter.field && nextSorter.order) {
|
|
next.set(SORT_URL_PARAM, JSON.stringify(nextSorter))
|
|
} else {
|
|
next.delete(SORT_URL_PARAM)
|
|
}
|
|
})
|
|
}
|
|
},
|
|
[updateSearchParams]
|
|
)
|
|
|
|
const persistTableState = useCallback(
|
|
(
|
|
scope,
|
|
filterState,
|
|
sorter,
|
|
{
|
|
saveFilterInSession = false,
|
|
saveFilterInUrl = false,
|
|
saveSortInSession = false,
|
|
saveSortInUrl = false
|
|
} = {}
|
|
) => {
|
|
const active = getActiveFilterValues(filterState)
|
|
const nextSorter = normalizeSorter(sorter)
|
|
|
|
if (saveFilterInSession) {
|
|
writeFilterToSession(scope, active)
|
|
}
|
|
if (saveSortInSession) {
|
|
writeSortToSession(scope, nextSorter)
|
|
}
|
|
|
|
if (saveFilterInUrl || saveSortInUrl) {
|
|
updateSearchParams((next) => {
|
|
if (saveFilterInUrl) {
|
|
if (Object.keys(active).length > 0) {
|
|
next.set(FILTER_URL_PARAM, JSON.stringify(active))
|
|
} else {
|
|
next.delete(FILTER_URL_PARAM)
|
|
}
|
|
}
|
|
if (saveSortInUrl) {
|
|
if (nextSorter.field && nextSorter.order) {
|
|
next.set(SORT_URL_PARAM, JSON.stringify(nextSorter))
|
|
} else {
|
|
next.delete(SORT_URL_PARAM)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
},
|
|
[updateSearchParams]
|
|
)
|
|
|
|
const setPageFilter = useCallback((path, filter) => {
|
|
const active = getActiveFilterValues(filter)
|
|
setPageFilters((prev) => {
|
|
const hasActive = Object.keys(active).length > 0
|
|
if (!hasActive) {
|
|
if (!(path in prev)) return prev
|
|
const next = { ...prev }
|
|
delete next[path]
|
|
return next
|
|
}
|
|
return { ...prev, [path]: active }
|
|
})
|
|
}, [])
|
|
|
|
const setPageSorter = useCallback((path, sorter) => {
|
|
const hasSort = sorter?.field && sorter?.order
|
|
setPageSorters((prev) => {
|
|
if (!hasSort) {
|
|
if (!(path in prev)) return prev
|
|
const next = { ...prev }
|
|
delete next[path]
|
|
return next
|
|
}
|
|
return { ...prev, [path]: { field: sorter.field, order: sorter.order } }
|
|
})
|
|
}, [])
|
|
|
|
const setObjectListFilter = useCallback((objectType, filter) => {
|
|
if (!objectType) return
|
|
const active = getActiveFilterValues(filter)
|
|
writeListFilterToSession(objectType, active)
|
|
setObjectListFilters((prev) => {
|
|
const hasActive = Object.keys(active).length > 0
|
|
if (!hasActive) {
|
|
if (!(objectType in prev)) return prev
|
|
const next = { ...prev }
|
|
delete next[objectType]
|
|
return next
|
|
}
|
|
return { ...prev, [objectType]: active }
|
|
})
|
|
}, [])
|
|
|
|
const setObjectListSorter = useCallback((objectType, sorter) => {
|
|
if (!objectType) return
|
|
const nextSorter = normalizeSorter(sorter)
|
|
writeListSortToSession(objectType, nextSorter)
|
|
setObjectListSorters((prev) => {
|
|
const hasSort = nextSorter?.field && nextSorter?.order
|
|
if (!hasSort) {
|
|
if (!(objectType in prev)) return prev
|
|
const next = { ...prev }
|
|
delete next[objectType]
|
|
return next
|
|
}
|
|
return { ...prev, [objectType]: nextSorter }
|
|
})
|
|
}, [])
|
|
|
|
const setObjectListView = useCallback((objectType, view) => {
|
|
if (!objectType) return
|
|
const nextView =
|
|
view?.id != null
|
|
? { id: String(view.id), name: view.name || null }
|
|
: null
|
|
writeListViewToSession(objectType, nextView)
|
|
setObjectListViews((prev) => {
|
|
if (!nextView) {
|
|
if (!(objectType in prev)) return prev
|
|
const next = { ...prev }
|
|
delete next[objectType]
|
|
return next
|
|
}
|
|
const existing = prev[objectType]
|
|
if (
|
|
existing &&
|
|
existing.id === nextView.id &&
|
|
existing.name === nextView.name
|
|
) {
|
|
return prev
|
|
}
|
|
return { ...prev, [objectType]: nextView }
|
|
})
|
|
}, [])
|
|
|
|
const getObjectListFilter = useCallback(
|
|
(objectType) => {
|
|
if (!objectType) return {}
|
|
if (objectListFilters[objectType]) {
|
|
return objectListFilters[objectType]
|
|
}
|
|
return getActiveFilterValues(readListFilterFromSession(objectType) || {})
|
|
},
|
|
[objectListFilters]
|
|
)
|
|
|
|
const getObjectListSorter = useCallback(
|
|
(objectType) => {
|
|
if (!objectType) return {}
|
|
if (objectListSorters[objectType]) {
|
|
return objectListSorters[objectType]
|
|
}
|
|
return readListSortFromSession(objectType) || {}
|
|
},
|
|
[objectListSorters]
|
|
)
|
|
|
|
const getObjectListView = useCallback(
|
|
(objectType) => {
|
|
if (!objectType) return null
|
|
if (objectListViews[objectType]) {
|
|
return objectListViews[objectType]
|
|
}
|
|
return readListViewFromSession(objectType)
|
|
},
|
|
[objectListViews]
|
|
)
|
|
|
|
const hasPageFilter = useCallback(
|
|
(path) => Object.keys(pageFilters[path] || {}).length > 0,
|
|
[pageFilters]
|
|
)
|
|
|
|
const hasStoredFilter = useCallback((scope) => {
|
|
if (!scope) return false
|
|
// When a view is active, only report the effective list filter (which
|
|
// already accounts for the view). Don't fall back to the All-tab session
|
|
// filter — that belongs to a different context.
|
|
if (objectListViews[scope]) {
|
|
return Object.keys(objectListFilters[scope] || {}).length > 0
|
|
}
|
|
if (hasStoredSessionFilter(scope)) return true
|
|
if (Object.keys(objectListFilters[scope] || {}).length > 0) return true
|
|
return Object.keys(getActiveFilterValues(readListFilterFromSession(scope) || {})).length > 0
|
|
}, [objectListFilters, objectListViews])
|
|
|
|
const value = useMemo(
|
|
() => ({
|
|
getPersistedFilter,
|
|
getPersistedSorter,
|
|
getViewFromUrl,
|
|
persistView,
|
|
persistFilter,
|
|
persistSort,
|
|
persistTableState,
|
|
setPageFilter,
|
|
setPageSorter,
|
|
setObjectListFilter,
|
|
setObjectListSorter,
|
|
setObjectListView,
|
|
getObjectListFilter,
|
|
getObjectListSorter,
|
|
getObjectListView,
|
|
hasPageFilter,
|
|
hasStoredFilter,
|
|
pageFilters,
|
|
pageSorters,
|
|
objectListFilters,
|
|
objectListSorters,
|
|
objectListViews
|
|
}),
|
|
[
|
|
getPersistedFilter,
|
|
getPersistedSorter,
|
|
getViewFromUrl,
|
|
persistView,
|
|
persistFilter,
|
|
persistSort,
|
|
persistTableState,
|
|
setPageFilter,
|
|
setPageSorter,
|
|
setObjectListFilter,
|
|
setObjectListSorter,
|
|
setObjectListView,
|
|
getObjectListFilter,
|
|
getObjectListSorter,
|
|
getObjectListView,
|
|
hasPageFilter,
|
|
hasStoredFilter,
|
|
pageFilters,
|
|
pageSorters,
|
|
objectListFilters,
|
|
objectListSorters,
|
|
objectListViews
|
|
]
|
|
)
|
|
|
|
return (
|
|
<TableStateContext.Provider value={value}>
|
|
{children}
|
|
</TableStateContext.Provider>
|
|
)
|
|
}
|
|
|
|
// eslint-disable-next-line react-refresh/only-export-components
|
|
export const useTableState = () => {
|
|
const context = useContext(TableStateContext)
|
|
if (!context) {
|
|
throw new Error('useTableState must be used within a TableStateProvider')
|
|
}
|
|
return context
|
|
}
|
|
|
|
// eslint-disable-next-line react-refresh/only-export-components
|
|
export const useTableStatePersistence = ({
|
|
scope,
|
|
viewId = null,
|
|
pagePath,
|
|
saveFilterInSession = false,
|
|
saveFilterInUrl = false,
|
|
useFilterInSession = false,
|
|
useFilterInUrl = false,
|
|
saveSortInSession = false,
|
|
saveSortInUrl = false,
|
|
useSortInSession = false,
|
|
useSortInUrl = false
|
|
}) => {
|
|
const {
|
|
getPersistedFilter: getPersistedFilterCtx,
|
|
getPersistedSorter: getPersistedSorterCtx,
|
|
persistFilter: persistFilterCtx,
|
|
persistSort: persistSortCtx,
|
|
persistTableState: persistTableStateCtx,
|
|
setPageFilter,
|
|
setPageSorter,
|
|
setObjectListFilter,
|
|
setObjectListSorter
|
|
} = useTableState()
|
|
|
|
// View filter/sort belong to the view object — never read/write them via
|
|
// the shared filter/sort URL or session keys used by the "All" tab.
|
|
const isViewScope = Boolean(viewId)
|
|
|
|
const readOptions = useMemo(
|
|
() => ({
|
|
useFilterInUrl: isViewScope ? false : useFilterInUrl,
|
|
useFilterInSession: isViewScope ? false : useFilterInSession,
|
|
useSortInUrl: isViewScope ? false : useSortInUrl,
|
|
useSortInSession: isViewScope ? false : useSortInSession
|
|
}),
|
|
[
|
|
isViewScope,
|
|
useFilterInUrl,
|
|
useFilterInSession,
|
|
useSortInUrl,
|
|
useSortInSession
|
|
]
|
|
)
|
|
|
|
const saveOptions = useMemo(
|
|
() => ({
|
|
saveFilterInSession: isViewScope ? false : saveFilterInSession,
|
|
saveFilterInUrl: isViewScope ? false : saveFilterInUrl,
|
|
saveSortInSession: isViewScope ? false : saveSortInSession,
|
|
saveSortInUrl: isViewScope ? false : saveSortInUrl
|
|
}),
|
|
[
|
|
isViewScope,
|
|
saveFilterInSession,
|
|
saveFilterInUrl,
|
|
saveSortInSession,
|
|
saveSortInUrl
|
|
]
|
|
)
|
|
|
|
const allTabReadOptions = useMemo(
|
|
() => ({
|
|
useFilterInUrl,
|
|
useFilterInSession,
|
|
useSortInUrl,
|
|
useSortInSession
|
|
}),
|
|
[useFilterInUrl, useFilterInSession, useSortInUrl, useSortInSession]
|
|
)
|
|
|
|
const allTabSaveOptions = useMemo(
|
|
() => ({
|
|
saveFilterInSession,
|
|
saveFilterInUrl,
|
|
saveSortInSession,
|
|
saveSortInUrl
|
|
}),
|
|
[saveFilterInSession, saveFilterInUrl, saveSortInSession, saveSortInUrl]
|
|
)
|
|
|
|
const getPersistedFilter = useCallback(
|
|
() => getPersistedFilterCtx(scope, readOptions),
|
|
[getPersistedFilterCtx, scope, readOptions]
|
|
)
|
|
|
|
const getPersistedSorter = useCallback(
|
|
() => getPersistedSorterCtx(scope, readOptions),
|
|
[getPersistedSorterCtx, scope, readOptions]
|
|
)
|
|
|
|
// Always reads the All-tab filter/sort, even while a view is still selected
|
|
// (used when switching back to All before listViewId has cleared).
|
|
const getAllTabPersistedFilter = useCallback(
|
|
() => getPersistedFilterCtx(scope, allTabReadOptions),
|
|
[getPersistedFilterCtx, scope, allTabReadOptions]
|
|
)
|
|
|
|
const getAllTabPersistedSorter = useCallback(
|
|
() => getPersistedSorterCtx(scope, allTabReadOptions),
|
|
[getPersistedSorterCtx, scope, allTabReadOptions]
|
|
)
|
|
|
|
const persistFilter = useCallback(
|
|
(filterState) => persistFilterCtx(scope, filterState, saveOptions),
|
|
[persistFilterCtx, scope, saveOptions]
|
|
)
|
|
|
|
const persistSort = useCallback(
|
|
(sorter) => persistSortCtx(scope, sorter, saveOptions),
|
|
[persistSortCtx, scope, saveOptions]
|
|
)
|
|
|
|
const persistTableState = useCallback(
|
|
(filterState, sorter) =>
|
|
persistTableStateCtx(scope, filterState, sorter, saveOptions),
|
|
[persistTableStateCtx, scope, saveOptions]
|
|
)
|
|
|
|
const persistAllTabTableState = useCallback(
|
|
(filterState, sorter) =>
|
|
persistTableStateCtx(scope, filterState, sorter, allTabSaveOptions),
|
|
[persistTableStateCtx, scope, allTabSaveOptions]
|
|
)
|
|
|
|
const registerPageFilter = useCallback(
|
|
(filterState) => {
|
|
if (pagePath) {
|
|
setPageFilter(pagePath, filterState)
|
|
}
|
|
},
|
|
[pagePath, setPageFilter]
|
|
)
|
|
|
|
const registerPageSorter = useCallback(
|
|
(sorter) => {
|
|
if (pagePath) {
|
|
setPageSorter(pagePath, sorter)
|
|
}
|
|
},
|
|
[pagePath, setPageSorter]
|
|
)
|
|
|
|
const registerObjectListFilter = useCallback(
|
|
(filterState) => {
|
|
if (scope) {
|
|
setObjectListFilter(scope, filterState)
|
|
}
|
|
},
|
|
[scope, setObjectListFilter]
|
|
)
|
|
|
|
const registerObjectListSorter = useCallback(
|
|
(sorter) => {
|
|
if (scope) {
|
|
setObjectListSorter(scope, sorter)
|
|
}
|
|
},
|
|
[scope, setObjectListSorter]
|
|
)
|
|
|
|
return {
|
|
persistenceScope: scope,
|
|
getPersistedFilter,
|
|
getPersistedSorter,
|
|
getAllTabPersistedFilter,
|
|
getAllTabPersistedSorter,
|
|
persistFilter,
|
|
persistSort,
|
|
persistTableState,
|
|
persistAllTabTableState,
|
|
registerPageFilter,
|
|
registerPageSorter,
|
|
registerObjectListFilter,
|
|
registerObjectListSorter,
|
|
getActiveFilterValues
|
|
}
|
|
}
|
|
|
|
TableStateProvider.propTypes = {
|
|
children: PropTypes.node.isRequired
|
|
}
|
|
|
|
export default TableStateContext
|