Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions src/core/components/Pagination-without-number.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Packages
import React from 'react'
import { useListContext } from 'react-admin'
import { Button, Toolbar, Box, Typography } from '@material-ui/core'

// Icons
import { ChevronLeft as ChevronLeftIcon, ChevronRight as ChevronRightIcon } from '@material-ui/icons'

interface Props {
next: () => void
back: () => void
backAll: () => void
page: number
}

const PaginationWithoutNumber = (props: Props) => {
const { page, perPage, setPage, ids, loading, total } = useListContext()
const isLastPage = page * perPage >= total
const listLength = ids.length

// console.log({ ids })

return (
<Toolbar>
<Box width="100%">
<Box display="flex" alignItems="center" justifyContent="flex-end">
<Box pr={3}>
<Typography variant="body2">{`Resultados por página: ${listLength} `}</Typography>
</Box>
<Box pr={3}>
<Typography variant="body2">{`Página: ${props.page} `}</Typography>
</Box>
{props.page > 1 && (
<>
<Button size="small" color="primary" key="prevAll" disabled={loading} onClick={() => props.backAll()}>
<ChevronLeftIcon />
<ChevronLeftIcon />
</Button>
<Button size="small" color="primary" key="prev" disabled={loading} onClick={() => props.back()}>
<ChevronLeftIcon />
Anterior
</Button>
</>
)}
{total > perPage && !isLastPage && (
<Box>
<Button size="small" color="primary" key="next" disabled={loading} onClick={() => props.next()}>
Próximo
<ChevronRightIcon />
</Button>
</Box>
)}
</Box>
</Box>
</Toolbar>
)
}

export default PaginationWithoutNumber
128 changes: 119 additions & 9 deletions src/core/components/local-list.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
// Packages
import React, { ReactElement, cloneElement, useEffect } from 'react'
import { Box, Button } from '@material-ui/core'
import React, { ReactElement, cloneElement, useEffect, useState, useCallback } from 'react'
import { Box, Button, TablePagination } from '@material-ui/core'
import { Config } from 'final-form'
import { ListContextProvider, Pagination, useList, useVersion, SortPayload, FilterPayload } from 'react-admin'
import {
ListContextProvider,
Pagination,
useList,
useVersion,
SortPayload,
FilterPayload,
useTranslate
} from 'react-admin'
import { Form } from 'react-final-form'
import PaginationWithoutNumber from './Pagination-without-number'

interface RaRecord {
id: string | number
Expand All @@ -14,19 +23,56 @@ interface EssentialParams extends Pick<Config, 'onSubmit'> {
onRefresh?: () => void
data?: Array<RaRecord>
filters?: ReactElement | Array<ReactElement>
perPage?: 5 | 10 | 25
sort?: SortPayload
perPage?: number
sort: SortPayload
filter?: FilterPayload
isLoading?: boolean
paginationStrategy?: 'local'
}

interface Props extends EssentialParams {
interface EssentialParams2 extends Omit<EssentialParams, 'paginationStrategy'> {
paginationStrategy?: 'api-without-total'
onPageChange?: (value: number) => void
onSortChange?: (value: SortPayload) => void
onPerPageChange?: (value: number) => void
}

interface EssentialParams3 extends Omit<EssentialParams, 'paginationStrategy'> {
paginationStrategy?: 'api-with-total'
onPageChange?: (value: number) => void
onSortChange?: (value: SortPayload) => void
onPerPageChange?: (value: number) => void
total: number
}

interface Props {
children: ReactElement
}

const LocalList = (props: Props) => {
const { children, onRefresh, data, isLoading, filters, onSubmit = () => undefined, perPage = 5, sort, filter } = props
const LocalList = (props: (Props & EssentialParams) | (Props & EssentialParams2) | (Props & EssentialParams3)) => {
const {
children,
onRefresh,
data,
isLoading,
filters,
onSubmit = () => undefined,
perPage = 5,
sort,
filter,
paginationStrategy = 'local',
// @ts-ignore
total,
// @ts-ignore
onPageChange = () => undefined,
// @ts-ignore
onSortChange = () => undefined,
// @ts-ignore
onPerPageChange = () => undefined
} = props
const translate = useTranslate()
const filtersToRender = Array.isArray(filters) ? filters : filters === undefined ? [] : [filters]
const [page, setPage] = useState(1)
const version = useVersion()
const listContext = useList({
ids: [],
Expand All @@ -38,12 +84,56 @@ const LocalList = (props: Props) => {
filter
})

useEffect(() => {
onPageChange(page)
}, [page, onPageChange])

useEffect(() => {
onSortChange(listContext.currentSort)
}, [listContext.currentSort, onSortChange])

const handleNextPage = () => {
setPage(state => state + 1)
}

const handleBackAllPage = () => {
setPage(1)
}

const handleBackPage = () => {
setPage(state => state - 1)
}

useEffect(() => {
if (onRefresh) {
onRefresh()
}
}, [onRefresh, version])

const handlePageChange = useCallback(
(_, page) => {
setPage(page + 1)
},
[setPage]
)

const labelDisplayedRows = useCallback(
({ from, to, count }) =>
translate('ra.navigation.page_range_info', {
offsetBegin: from,
offsetEnd: to,
total: count
}),
[translate]
)

const handlePerPageChange = useCallback(
event => {
onPerPageChange(event.target.value)
},
[onPerPageChange]
)

return (
<Box>
{filtersToRender && (
Expand All @@ -67,7 +157,27 @@ const LocalList = (props: Props) => {
)}
<ListContextProvider value={listContext}>
{children}
<Pagination />
{paginationStrategy === 'api-without-total' ? (
<PaginationWithoutNumber
page={page}
next={handleNextPage}
back={handleBackPage}
backAll={handleBackAllPage}
/>
) : paginationStrategy === 'api-with-total' ? (
<TablePagination
count={total}
rowsPerPage={perPage}
page={page - 1}
rowsPerPageOptions={[5, 10, 25]}
component="span"
onChangePage={handlePageChange}
onChangeRowsPerPage={handlePerPageChange}
labelDisplayedRows={labelDisplayedRows}
/>
) : (
<Pagination />
)}
</ListContextProvider>
</Box>
)
Expand Down
5 changes: 5 additions & 0 deletions src/resources/custom/custom-list.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { TabResource } from './tab-resource.component'
import { TabHealth } from './tab-health.component'
import { Whatshot as WhatshotIcon } from '@material-ui/icons'
import { TabLocalList } from './tab-local-list'
import { TabLocalListWithApiPagination } from './tab-local-list-with-api-pagination'

const InfinitDatagrid = () => {
const infiniteList = useMemo(() => {
Expand Down Expand Up @@ -328,6 +329,7 @@ const CustomList: FC<any> = () => {
<Tab label="RTK Query Api Health" />
</Locker>
<Tab label="Local List" value="4" />
<Tab label="Local List + RTK + API pagination" value="5" />
</TabList>
</AppBar>
<TabPanel value="1">
Expand All @@ -347,6 +349,9 @@ const CustomList: FC<any> = () => {
<TabPanel value="4">
<TabLocalList />
</TabPanel>
<TabPanel value="5">
<TabLocalListWithApiPagination />
</TabPanel>
</TabContext>
)
}
Expand Down
44 changes: 44 additions & 0 deletions src/resources/custom/tab-local-list-with-api-pagination.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Packages
import React, { FC, useState } from 'react'
import { TextField, Datagrid, TextInput, required } from 'react-admin'
import { useGetUsersQuery } from 'store/api/users-api'
import LocalList from 'core/components/local-list'

export const TabLocalListWithApiPagination: FC = () => {
const [page, setPage] = useState({})
const [perPage, setPerPage] = useState(6)
const [sort, setSort] = useState({ field: 'created_at', order: 'ASC' })
const { isFetching, data, refetch } = useGetUsersQuery({
filter: {},
pagination: { page, perPage },
sort: sort
})

return (
<LocalList
perPage={perPage}
isLoading={isFetching}
data={data?.data}
onRefresh={refetch}
onPageChange={value => {
setPage(value)
}}
onSortChange={value => {
setSort(value)
}}
onPerPageChange={value => {
setPerPage(value)
}}
total={data?.total || 0}
sort={sort}
onSubmit={() => {}}
paginationStrategy="api-with-total"
filters={[<TextInput source="email" validate={required()} />]}
>
<Datagrid>
<TextField source="id" label="Id" />
<TextField source="email" label="E-mail" />
</Datagrid>
</LocalList>
)
}