@@ -25,6 +25,7 @@ import { toastQueue } from '@keystar/ui/toast'
2525import { TooltipTrigger , Tooltip } from '@keystar/ui/tooltip'
2626import { Heading , Text } from '@keystar/ui/typography'
2727
28+ import type { TypedDocumentNode } from '../../../../admin-ui/apollo'
2829import { gql , useMutation , useQuery } from '../../../../admin-ui/apollo'
2930import { PageContainer } from '../../../../admin-ui/components/PageContainer'
3031import { useList } from '../../../../admin-ui/context'
@@ -39,6 +40,7 @@ import { useFilters } from './useFilters'
3940import { useSearchFilter } from '../../../../fields/types/relationship/views/useFilter'
4041import { useSelectedFields } from './useSelectedFields'
4142import { useSort } from './useSort'
43+ import { ProgressCircle } from '@keystar/ui/progress'
4244
4345type ListPageProps = { listKey : string }
4446type SelectedKeys = 'all' | Set < number | string >
@@ -103,8 +105,11 @@ function ListPage({ listKey }: ListPageProps) {
103105 const search = useSearchFilter ( searchParam , list , list . initialSearchFields )
104106
105107 const selectedFields = useSelectedFields ( list )
106- const { data, error, refetch } = useQuery (
107- useMemo ( ( ) => {
108+ const { data, error, refetch, loading } = useQuery (
109+ useMemo ( ( ) : TypedDocumentNode < {
110+ items : Record < string , unknown > [ ] | null
111+ count : number | null
112+ } > => {
108113 const selectedGqlFields = [ ...selectedFields ]
109114 . map ( fieldPath => list . fields [ fieldPath ] . controller . graphqlSelection )
110115 . join ( '\n' )
@@ -156,6 +161,11 @@ function ListPage({ listKey }: ListPageProps) {
156161 }
157162 }
158163
164+ const [ dataWithPevious , setDataWithPrevious ] = useState < typeof data > ( data )
165+ if ( ! loading && data !== dataWithPevious ) {
166+ setDataWithPrevious ( data )
167+ }
168+
159169 const allowCreate = ! ( list . hideCreate ?? true )
160170 const allowDelete = ! ( list . hideDelete ?? true )
161171 const isConstrained = Boolean ( filters . filters . length || query . search )
@@ -194,6 +204,7 @@ function ListPage({ listKey }: ListPageProps) {
194204 < Tooltip > Reset to defaults</ Tooltip >
195205 </ TooltipTrigger >
196206 ) }
207+ { ! ! dataWithPevious && loading && < ProgressCircle size = "small" isIndeterminate /> }
197208 </ HStack >
198209
199210 { filters . filters . length ? < FilterList filters = { filters . filters } list = { list } /> : null }
@@ -203,13 +214,13 @@ function ListPage({ listKey }: ListPageProps) {
203214 < ListTable
204215 listKey = { listKey }
205216 allowDelete = { allowDelete }
206- count = { data ?. count ?? 0 }
217+ data = { dataWithPevious }
207218 currentPage = { currentPage }
208219 isConstrained = { isConstrained }
209220 pageSize = { pageSize }
210221 refetch = { refetch }
211- items = { data ?. items ?? [ ] }
212222 selectedFields = { selectedFields }
223+ loading = { loading }
213224 />
214225 </ VStack >
215226 </ PageContainer >
@@ -236,24 +247,24 @@ function ListPageHeader({ listKey, showCreate }: { listKey: string; showCreate?:
236247
237248function ListTable ( {
238249 allowDelete,
239- count ,
250+ data ,
240251 currentPage,
241252 isConstrained,
242253 listKey,
243- items,
244254 pageSize,
245255 refetch,
246256 selectedFields,
257+ loading,
247258} : {
248259 allowDelete : boolean
249- count : number
250260 currentPage : number
251261 isConstrained : boolean
252262 listKey : string
253263 pageSize : number
254264 refetch : ( ) => void
255265 selectedFields : ReturnType < typeof useSelectedFields >
256- items : Record < string , unknown > [ ]
266+ data : { items : Record < string , unknown > [ ] | null ; count : number | null } | undefined
267+ loading : boolean
257268} ) {
258269 const list = useList ( listKey )
259270 const router = useRouter ( )
@@ -271,7 +282,7 @@ function ListTable({
271282 return {
272283 id : path ,
273284 label : field . label ,
274- allowsSorting : ! isConstrained && ! items . length ? false : field . isOrderable ,
285+ allowsSorting : ! isConstrained && ! data ?. items ? .length ? false : field . isOrderable ,
275286 }
276287 } )
277288
@@ -288,7 +299,9 @@ function ListTable({
288299 onSelectionChange = { setSelectedKeys }
289300 selectedKeys = { selectedKeys }
290301 renderEmptyState = { ( ) =>
291- isConstrained ? (
302+ loading ? (
303+ < ProgressCircle isIndeterminate />
304+ ) : isConstrained ? (
292305 < EmptyState
293306 icon = { searchXIcon }
294307 title = "No results"
@@ -303,6 +316,9 @@ function ListTable({
303316 )
304317 }
305318 flex
319+ UNSAFE_style = { {
320+ opacity : loading && ! ! data ? 0.5 : undefined ,
321+ } }
306322 >
307323 < TableHeader columns = { columns } >
308324 { ( { label, id, ...options } ) => (
@@ -311,7 +327,7 @@ function ListTable({
311327 </ Column >
312328 ) }
313329 </ TableHeader >
314- < TableBody items = { items } >
330+ < TableBody items = { data ?. items ?? [ ] } >
315331 { row => {
316332 return (
317333 < Row href = { `/${ list . path } /${ row ?. id } ` } >
@@ -352,7 +368,7 @@ function ListTable({
352368 switch ( key ) {
353369 case 'delete' :
354370 if ( selectedKeys === 'all' ) {
355- const ids = items . filter ( x => x . id != null ) . map ( x => `${ x . id } ` )
371+ const ids = data ?. items ? .filter ( x => x . id != null ) . map ( x => `${ x . id } ` )
356372 setIdsForDeletion ( new Set ( ids ) )
357373 } else {
358374 setIdsForDeletion ( selectedKeys )
@@ -370,13 +386,13 @@ function ListTable({
370386 </ ActionBar >
371387 </ ActionBarContainer >
372388
373- { count > 0 && (
389+ { ! ! data ?. count && (
374390 < Pagination
375391 currentPage = { currentPage }
376392 pageSize = { pageSize }
377393 plural = { list . plural }
378394 singular = { list . singular }
379- total = { count }
395+ total = { data . count }
380396 />
381397 ) }
382398
0 commit comments