diff --git a/src/components/Dashboard/common/ObjectCard.jsx b/src/components/Dashboard/common/ObjectCard.jsx
index 8ebdb47..1959aab 100644
--- a/src/components/Dashboard/common/ObjectCard.jsx
+++ b/src/components/Dashboard/common/ObjectCard.jsx
@@ -1,10 +1,11 @@
-import { Descriptions, Card, Flex, Divider } from 'antd'
+import { Descriptions, Card, Flex, Divider, Skeleton } from 'antd'
import PropTypes from 'prop-types'
import ObjectProperty from './ObjectProperty'
import { createElement } from 'react'
import Thumbnail from './Thumbnail'
const ObjectCard = ({
+ isSkeleton = false,
model,
modelProperties,
visibleColumns = {},
@@ -40,7 +41,9 @@ const ObjectCard = ({
key: prop.name,
label: prop.label,
span: 2,
- children: (
+ children: isSkeleton ? (
+
+ ) : (
)
}
- disabled={disabled}
+ disabled={disabled || objectData?.isSkeleton}
type={'text'}
size={'small'}
onClick={() => {
@@ -304,6 +304,21 @@ const ObjectTable = forwardRef(
return SKELETON_HEIGHT * pageSize
}, [pageSize])
+ const skeletonBoundaryIds = useMemo(() => {
+ const firstPage = pages[0]
+ const lastPage = pages[pages.length - 1]
+ return {
+ previous:
+ firstPage?.isSkeletonPage && firstPage.items.length > 0
+ ? firstPage.items[firstPage.items.length - 1]._id
+ : null,
+ next:
+ lastPage?.isSkeletonPage && lastPage.items[0]
+ ? lastPage.items[0]._id
+ : null
+ }
+ }, [pages])
+
const createPageWindow = useCallback(
(loadedPages, direction) => {
const sortedPages = [...loadedPages].sort(
@@ -1101,37 +1116,39 @@ const ObjectTable = forwardRef(
return () => cardsResizeObserverRef.current?.disconnect()
}, [])
- // Card view scroll handler
- useEffect(() => {
+ // Card view: load when the leading skeleton card in a boundary page enters view
+ useLayoutEffect(() => {
if (!cards) return
const container = cardsContainerNodeRef.current
if (!container) return
const scrollEl = container.querySelector('.simplebar-content-wrapper')
if (!scrollEl) return
- const handleCardsScroll = (e) => {
- const { scrollTop, scrollHeight, clientHeight } = e.target
- const firstPage = pagesRef.current[0]
- const lastPage = pagesRef.current[pagesRef.current.length - 1]
-
- if (
- lastPage?.isSkeletonPage &&
- scrollHeight - scrollTop - clientHeight < 100 &&
- !lazyLoading
- ) {
- loadNextPage(scrollEl)
- } else if (
- firstPage?.isSkeletonPage &&
- scrollTop < 100 &&
- !lazyLoading
- ) {
- loadPreviousPage(scrollEl)
+ const observer = new IntersectionObserver(
+ (entries) => {
+ for (const entry of entries) {
+ if (!entry.isIntersecting) continue
+ const boundary = entry.target.dataset.skeletonBoundary
+ if (boundary === 'next') {
+ loadNextPage(scrollEl)
+ } else if (boundary === 'previous') {
+ loadPreviousPage(scrollEl)
+ }
+ }
+ },
+ {
+ root: scrollEl,
+ rootMargin: `${SCROLL_THRESHOLD}px`,
+ threshold: 0
}
- }
+ )
- scrollEl.addEventListener('scroll', handleCardsScroll)
- return () => scrollEl.removeEventListener('scroll', handleCardsScroll)
- }, [cards, pages, lazyLoading, loadNextPage, loadPreviousPage])
+ container
+ .querySelectorAll('[data-skeleton-boundary]')
+ .forEach((el) => observer.observe(el))
+
+ return () => observer.disconnect()
+ }, [cards, skeletonBoundaryIds, loadNextPage, loadPreviousPage])
const renderCards = () => {
return (
@@ -1146,9 +1163,20 @@ const ObjectTable = forwardRef(
if (record?._id == undefined) {
return null
}
+
+ const skeletonBoundary =
+ record._id === skeletonBoundaryIds.next
+ ? 'next'
+ : record._id === skeletonBoundaryIds.previous
+ ? 'previous'
+ : undefined
+
return (
-