Add pagination to playlists (#969)
* add pagination * prettier applied * perPage_bug_fixed * pagination_component_changed * getAllSongs function added * pagination component updated * catch_error from data provider * getAllSongsAndDispatch added * remove ids from action function
This commit is contained in:
@@ -5,6 +5,8 @@ import {
|
|||||||
sanitizeListRestProps,
|
sanitizeListRestProps,
|
||||||
TopToolbar,
|
TopToolbar,
|
||||||
useTranslate,
|
useTranslate,
|
||||||
|
useDataProvider,
|
||||||
|
useNotify,
|
||||||
} from 'react-admin'
|
} from 'react-admin'
|
||||||
import PlayArrowIcon from '@material-ui/icons/PlayArrow'
|
import PlayArrowIcon from '@material-ui/icons/PlayArrow'
|
||||||
import ShuffleIcon from '@material-ui/icons/Shuffle'
|
import ShuffleIcon from '@material-ui/icons/Shuffle'
|
||||||
@@ -23,23 +25,51 @@ import config from '../config'
|
|||||||
const PlaylistActions = ({ className, ids, data, record, ...rest }) => {
|
const PlaylistActions = ({ className, ids, data, record, ...rest }) => {
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
const translate = useTranslate()
|
const translate = useTranslate()
|
||||||
|
const dataProvider = useDataProvider()
|
||||||
|
const notify = useNotify()
|
||||||
const isDesktop = useMediaQuery((theme) => theme.breakpoints.up('md'))
|
const isDesktop = useMediaQuery((theme) => theme.breakpoints.up('md'))
|
||||||
|
|
||||||
|
const getAllSongsAndDispatch = React.useCallback(
|
||||||
|
(action) => {
|
||||||
|
if (ids.length === record.songCount) {
|
||||||
|
return dispatch(action(data, ids))
|
||||||
|
}
|
||||||
|
|
||||||
|
dataProvider
|
||||||
|
.getList('playlistTrack', {
|
||||||
|
pagination: { page: 1, perPage: 0 },
|
||||||
|
sort: { field: 'id', order: 'ASC' },
|
||||||
|
filter: { playlist_id: record.id },
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
const data = res.data.reduce(
|
||||||
|
(acc, curr) => ({ ...acc, [curr.id]: curr }),
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
dispatch(action(data))
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
notify('ra.page.error', 'warning')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
[dataProvider, dispatch, record, data, ids, notify]
|
||||||
|
)
|
||||||
|
|
||||||
const handlePlay = React.useCallback(() => {
|
const handlePlay = React.useCallback(() => {
|
||||||
dispatch(playTracks(data, ids))
|
getAllSongsAndDispatch(playTracks)
|
||||||
}, [dispatch, data, ids])
|
}, [getAllSongsAndDispatch])
|
||||||
|
|
||||||
const handlePlayNext = React.useCallback(() => {
|
const handlePlayNext = React.useCallback(() => {
|
||||||
dispatch(playNext(data, ids))
|
getAllSongsAndDispatch(playNext)
|
||||||
}, [dispatch, data, ids])
|
}, [getAllSongsAndDispatch])
|
||||||
|
|
||||||
const handlePlayLater = React.useCallback(() => {
|
const handlePlayLater = React.useCallback(() => {
|
||||||
dispatch(addTracks(data, ids))
|
getAllSongsAndDispatch(addTracks)
|
||||||
}, [dispatch, data, ids])
|
}, [getAllSongsAndDispatch])
|
||||||
|
|
||||||
const handleShuffle = React.useCallback(() => {
|
const handleShuffle = React.useCallback(() => {
|
||||||
dispatch(shuffleTracks(data, ids))
|
getAllSongsAndDispatch(shuffleTracks)
|
||||||
}, [dispatch, data, ids])
|
}, [getAllSongsAndDispatch])
|
||||||
|
|
||||||
const handleDownload = React.useCallback(() => {
|
const handleDownload = React.useCallback(() => {
|
||||||
subsonic.download(record.id)
|
subsonic.download(record.id)
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import {
|
|||||||
ShowContextProvider,
|
ShowContextProvider,
|
||||||
useShowContext,
|
useShowContext,
|
||||||
useShowController,
|
useShowController,
|
||||||
|
Pagination as RaPagination,
|
||||||
} from 'react-admin'
|
} from 'react-admin'
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import PlaylistDetails from './PlaylistDetails'
|
import PlaylistDetails from './PlaylistDetails'
|
||||||
import PlaylistSongs from './PlaylistSongs'
|
import PlaylistSongs from './PlaylistSongs'
|
||||||
import PlaylistActions from './PlaylistActions'
|
import PlaylistActions from './PlaylistActions'
|
||||||
import { Title, isReadOnly } from '../common'
|
import { Title, isReadOnly } from '../common'
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
(theme) => ({
|
(theme) => ({
|
||||||
playlistActions: {},
|
playlistActions: {},
|
||||||
@@ -35,7 +35,7 @@ const PlaylistShowLayout = (props) => {
|
|||||||
reference="playlistTrack"
|
reference="playlistTrack"
|
||||||
target="playlist_id"
|
target="playlist_id"
|
||||||
sort={{ field: 'id', order: 'ASC' }}
|
sort={{ field: 'id', order: 'ASC' }}
|
||||||
perPage={0}
|
perPage={100}
|
||||||
filter={{ playlist_id: props.id }}
|
filter={{ playlist_id: props.id }}
|
||||||
>
|
>
|
||||||
<PlaylistSongs
|
<PlaylistSongs
|
||||||
@@ -50,8 +50,7 @@ const PlaylistShowLayout = (props) => {
|
|||||||
}
|
}
|
||||||
resource={'playlistTrack'}
|
resource={'playlistTrack'}
|
||||||
exporter={false}
|
exporter={false}
|
||||||
perPage={0}
|
pagination={<RaPagination rowsPerPageOptions={[100, 250, 500]} />}
|
||||||
pagination={null}
|
|
||||||
/>
|
/>
|
||||||
</ReferenceManyField>
|
</ReferenceManyField>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
useNotify,
|
useNotify,
|
||||||
useVersion,
|
useVersion,
|
||||||
useListContext,
|
useListContext,
|
||||||
|
ListBase,
|
||||||
} from 'react-admin'
|
} from 'react-admin'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import { useDispatch } from 'react-redux'
|
import { useDispatch } from 'react-redux'
|
||||||
@@ -76,8 +77,9 @@ const ReorderableList = ({ readOnly, children, ...rest }) => {
|
|||||||
return <ReactDragListView {...rest}>{children}</ReactDragListView>
|
return <ReactDragListView {...rest}>{children}</ReactDragListView>
|
||||||
}
|
}
|
||||||
|
|
||||||
const PlaylistSongs = ({ playlistId, readOnly, ...props }) => {
|
const PlaylistSongs = ({ playlistId, readOnly, actions, ...props }) => {
|
||||||
const { data, ids, onUnselectItems } = props
|
const listContext = useListContext()
|
||||||
|
const { data, ids, onUnselectItems } = listContext
|
||||||
const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs'))
|
const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs'))
|
||||||
const isDesktop = useMediaQuery((theme) => theme.breakpoints.up('md'))
|
const isDesktop = useMediaQuery((theme) => theme.breakpoints.up('md'))
|
||||||
const classes = useStyles({ isDesktop })
|
const classes = useStyles({ isDesktop })
|
||||||
@@ -128,17 +130,17 @@ const PlaylistSongs = ({ playlistId, readOnly, ...props }) => {
|
|||||||
<ListToolbar
|
<ListToolbar
|
||||||
classes={{ toolbar: classes.toolbar }}
|
classes={{ toolbar: classes.toolbar }}
|
||||||
filters={props.filters}
|
filters={props.filters}
|
||||||
actions={props.actions}
|
actions={actions}
|
||||||
{...props}
|
{...listContext}
|
||||||
/>
|
/>
|
||||||
<div className={classes.main}>
|
<div className={classes.main}>
|
||||||
<Card
|
<Card
|
||||||
className={clsx(classes.content, {
|
className={clsx(classes.content, {
|
||||||
[classes.bulkActionsDisplayed]: props.selectedIds.length > 0,
|
[classes.bulkActionsDisplayed]: listContext.selectedIds.length > 0,
|
||||||
})}
|
})}
|
||||||
key={version}
|
key={version}
|
||||||
>
|
>
|
||||||
<BulkActionsToolbar {...props}>
|
<BulkActionsToolbar {...listContext}>
|
||||||
<PlaylistSongBulkActions
|
<PlaylistSongBulkActions
|
||||||
playlistId={playlistId}
|
playlistId={playlistId}
|
||||||
onUnselectItems={onUnselectItems}
|
onUnselectItems={onUnselectItems}
|
||||||
@@ -152,7 +154,7 @@ const PlaylistSongs = ({ playlistId, readOnly, ...props }) => {
|
|||||||
<SongDatagrid
|
<SongDatagrid
|
||||||
expand={!isXsmall && <SongDetails />}
|
expand={!isXsmall && <SongDetails />}
|
||||||
rowClick={(id) => dispatch(playTracks(data, ids, id))}
|
rowClick={(id) => dispatch(playTracks(data, ids, id))}
|
||||||
{...props}
|
{...listContext}
|
||||||
hasBulkActions={true}
|
hasBulkActions={true}
|
||||||
contextAlwaysVisible={!isDesktop}
|
contextAlwaysVisible={!isDesktop}
|
||||||
classes={{ row: classes.row }}
|
classes={{ row: classes.row }}
|
||||||
@@ -172,20 +174,26 @@ const PlaylistSongs = ({ playlistId, readOnly, ...props }) => {
|
|||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
<AddToPlaylistDialog />
|
<AddToPlaylistDialog />
|
||||||
|
{React.cloneElement(props.pagination, listContext)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const SanitizedPlaylistSongs = (props) => {
|
const SanitizedPlaylistSongs = (props) => {
|
||||||
const { loaded, loading, total, ...rest } = useListContext(props)
|
const { loaded, ...rest } = props
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{loaded && (
|
{loaded && (
|
||||||
<PlaylistSongs
|
<>
|
||||||
{...rest}
|
<ListBase {...props}>
|
||||||
playlistId={props.id}
|
<PlaylistSongs
|
||||||
actions={props.actions}
|
playlistId={props.id}
|
||||||
/>
|
actions={props.actions}
|
||||||
|
pagination={props.pagination}
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
|
</ListBase>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user