Enhance ObjectTable component by adding support for action handling with new props for row actions and visibility of action buttons. Refactor skeleton data creation and improve loading logic for better performance and user experience during data fetching.

This commit is contained in:
Tom Butcher 2026-07-20 02:07:10 +01:00
parent 46fd3b0c8e
commit 8dc74f1a8e

View File

@ -106,7 +106,9 @@ const ObjectTable = forwardRef(
size = 'middle',
onStateChange,
showFilterSidebar = false,
expandHeight = false
expandHeight = false,
showActions = true,
onRowAction
},
ref
) => {
@ -186,14 +188,17 @@ const ObjectTable = forwardRef(
const rowActions =
model.actions?.filter((action) => action.row == true) || []
const createSkeletonData = useCallback((pageNum) => {
return Array(pageSize)
.fill(null)
.map((_, index) => ({
_id: `skeleton-${pageNum}-${index}`,
isSkeleton: true
}))
}, [pageSize])
const createSkeletonData = useCallback(
(pageNum) => {
return Array(pageSize)
.fill(null)
.map((_, index) => ({
_id: `skeleton-${pageNum}-${index}`,
isSkeleton: true
}))
},
[pageSize]
)
const createSkeletonPage = useCallback(
(pageNum) => ({
@ -236,6 +241,12 @@ const ObjectTable = forwardRef(
type={'text'}
size={'small'}
onClick={() => {
if (
onRowAction &&
onRowAction(action, objectData) !== false
) {
return
}
if (action.url) {
navigate(action.url(objectData._id))
}
@ -314,9 +325,7 @@ const ObjectTable = forwardRef(
hasMore: result.hasMore
}
setPages((prev) =>
prev.map((page) =>
page.pageNum === pageNum ? loadedPage : page
)
prev.map((page) => (page.pageNum === pageNum ? loadedPage : page))
)
setLoading(false)
return result.data || []
@ -330,9 +339,9 @@ const ObjectTable = forwardRef(
const findRenderedRow = useCallback((scrollTarget, id) => {
if (!scrollTarget || id == null) return null
return Array.from(
scrollTarget.querySelectorAll('tr[data-row-key]')
).find((row) => row.getAttribute('data-row-key') === String(id))
return Array.from(scrollTarget.querySelectorAll('tr[data-row-key]')).find(
(row) => row.getAttribute('data-row-key') === String(id)
)
}, [])
const captureScrollAnchor = useCallback(
@ -360,9 +369,7 @@ const ObjectTable = forwardRef(
}
const placeholderAnchor = closestRow(placeholderPage.items)
const loadedPages = currentPages.filter(
(page) => !page.isSkeletonPage
)
const loadedPages = currentPages.filter((page) => !page.isSkeletonPage)
const retainedPage =
direction === 'previous'
? loadedPages[0]
@ -380,8 +387,7 @@ const ObjectTable = forwardRef(
(scrollTarget, anchor, loadedPage) => {
if (!scrollTarget || !anchor) return
const loadedItem =
loadedPage.items[anchor.placeholderAnchor?.index]
const loadedItem = loadedPage.items[anchor.placeholderAnchor?.index]
const anchorId = loadedItem?._id ?? anchor.fallbackAnchor?.id
const previousTop = loadedItem
? anchor.placeholderAnchor?.top
@ -463,11 +469,7 @@ const ObjectTable = forwardRef(
}
}
},
[
captureScrollAnchor,
createPageWindow,
fetchPage
]
[captureScrollAnchor, createPageWindow, fetchPage]
)
const loadNextPage = useCallback(
@ -726,10 +728,7 @@ const ObjectTable = forwardRef(
]
if (firstResult.hasMore) {
setPages([
...loadedPages,
createSkeletonPage(pageNum + 1)
])
setPages([...loadedPages, createSkeletonPage(pageNum + 1)])
const secondResult = await fetchPage(pageNum + 1)
loadedPages.push({
pageNum: pageNum + 1,
@ -1004,7 +1003,11 @@ const ObjectTable = forwardRef(
}
})
if (rowActions.length > 0 && tableData.some((item) => !item?.isSkeleton)) {
if (
showActions &&
rowActions.length > 0 &&
tableData.some((item) => !item?.isSkeleton)
) {
columnsWithSkeleton.push({
title: (
<Flex gap='small' align='center' justify='center'>
@ -1185,7 +1188,9 @@ ObjectTable.propTypes = {
size: PropTypes.string,
onStateChange: PropTypes.func,
showFilterSidebar: PropTypes.bool,
expandHeight: PropTypes.bool
expandHeight: PropTypes.bool,
showActions: PropTypes.bool,
onRowAction: PropTypes.func
}
export default ObjectTable