From e5c7819586c7864dc0bceed2cf1a41f8ce32e856 Mon Sep 17 00:00:00 2001 From: Deluan Date: Thu, 26 Nov 2020 17:00:53 -0500 Subject: [PATCH] Fix playlists --- ui/src/album/AlbumSongs.js | 3 +- ui/src/dataProvider/wrapperDataProvider.js | 1 - ui/src/playlist/PlaylistShow.js | 73 ++++---- ui/src/playlist/PlaylistSongBulkActions.js | 19 ++- ui/src/playlist/PlaylistSongs.js | 190 +++++++++++---------- 5 files changed, 155 insertions(+), 131 deletions(-) diff --git a/ui/src/album/AlbumSongs.js b/ui/src/album/AlbumSongs.js index 1530934dc..b32f3ae9e 100644 --- a/ui/src/album/AlbumSongs.js +++ b/ui/src/album/AlbumSongs.js @@ -72,17 +72,16 @@ const useStyles = makeStyles( const AlbumSongs = (props) => { const classes = useStyles(props) + const { data, ids } = props const dispatch = useDispatch() const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs')) const isDesktop = useMediaQuery((theme) => theme.breakpoints.up('md')) - const { id: album_id, data, ids } = props const version = useVersion() return ( <>
diff --git a/ui/src/dataProvider/wrapperDataProvider.js b/ui/src/dataProvider/wrapperDataProvider.js index 827ed1c85..7c83a099f 100644 --- a/ui/src/dataProvider/wrapperDataProvider.js +++ b/ui/src/dataProvider/wrapperDataProvider.js @@ -14,7 +14,6 @@ const mapResource = (resource, params) => { let plsId = '0' if (params.filter) { plsId = params.filter.playlist_id - delete params.filter.playlist_id } return [`playlist/${plsId}/tracks`, params] diff --git a/ui/src/playlist/PlaylistShow.js b/ui/src/playlist/PlaylistShow.js index e533816c5..676792934 100644 --- a/ui/src/playlist/PlaylistShow.js +++ b/ui/src/playlist/PlaylistShow.js @@ -1,43 +1,54 @@ import React from 'react' -import { useSelector } from 'react-redux' -import { useGetOne } from 'react-admin' +import { + ReferenceManyField, + ShowContextProvider, + useShowContext, + useShowController, +} from 'react-admin' import PlaylistDetails from './PlaylistDetails' -import { Title } from '../common' import PlaylistSongs from './PlaylistSongs' import PlaylistActions from './PlaylistActions' -import PlaylistSongBulkActions from './PlaylistSongBulkActions' -import { isReadOnly } from '../common/Writable' - -const PlaylistShow = (props) => { - const viewVersion = useSelector((s) => s.admin.ui && s.admin.ui.viewVersion) - const { data: record, error } = useGetOne('playlist', props.id, { - v: viewVersion, - }) - - if (error) { - return

ERROR: {error}

- } +import { Title, isReadOnly } from '../common' +const PlaylistShowLayout = (props) => { + const { loading, ...context } = useShowContext(props) + const { record } = context return ( <> - - } - actions={} - filter={{ playlist_id: props.id }} - resource={'playlistTrack'} - exporter={false} - perPage={0} - pagination={null} - bulkActionButtons={ - - } - /> + {record && } + {record && ( + + } + actions={} + resource={'playlistTrack'} + exporter={false} + perPage={0} + pagination={null} + /> + + )} ) } +const PlaylistShow = (props) => { + const controllerProps = useShowController(props) + return ( + + + + ) +} + export default PlaylistShow diff --git a/ui/src/playlist/PlaylistSongBulkActions.js b/ui/src/playlist/PlaylistSongBulkActions.js index 391adbabe..8265554a1 100644 --- a/ui/src/playlist/PlaylistSongBulkActions.js +++ b/ui/src/playlist/PlaylistSongBulkActions.js @@ -1,17 +1,26 @@ import React, { Fragment, useEffect } from 'react' -import { BulkDeleteButton, useUnselectAll } from 'react-admin' +import { + BulkDeleteButton, + useUnselectAll, + ResourceContextProvider, +} from 'react-admin' import PropTypes from 'prop-types' -const PlaylistSongBulkActions = ({ playlistId, ...rest }) => { +// Replace original resource with "fake" one for removing tracks from playlist +const PlaylistSongBulkActions = ({ playlistId, resource, ...rest }) => { const unselectAll = useUnselectAll() useEffect(() => { unselectAll('playlistTrack') // eslint-disable-next-line }, []) + + const mappedResource = `playlist/${playlistId}/tracks` return ( - - - + + + + + ) } diff --git a/ui/src/playlist/PlaylistSongs.js b/ui/src/playlist/PlaylistSongs.js index 58154515f..b04968921 100644 --- a/ui/src/playlist/PlaylistSongs.js +++ b/ui/src/playlist/PlaylistSongs.js @@ -1,13 +1,13 @@ -import React from 'react' +import React, { useCallback } from 'react' import { BulkActionsToolbar, - DatagridLoading, ListToolbar, TextField, - useListController, useRefresh, useDataProvider, useNotify, + useVersion, + useListContext, } from 'react-admin' import classnames from 'classnames' import { useDispatch } from 'react-redux' @@ -24,6 +24,7 @@ import { import AddToPlaylistDialog from '../dialogs/AddToPlaylistDialog' import { AlbumLinkField } from '../song/AlbumLinkField' import { playTracks } from '../actions' +import PlaylistSongBulkActions from './PlaylistSongBulkActions' const useStyles = makeStyles( (theme) => ({ @@ -51,16 +52,23 @@ const useStyles = makeStyles( flexWrap: 'wrap', }, noResults: { padding: 20 }, + toolbar: { + justifyContent: 'flex-start', + }, + row: { + '&:hover': { + '& $contextMenu': { + visibility: 'visible', + }, + }, + }, + contextMenu: { + visibility: 'hidden', + }, }), { name: 'RaList' } ) -const useStylesListToolbar = makeStyles({ - toolbar: { - justifyContent: 'flex-start', - }, -}) - const ReorderableList = ({ readOnly, children, ...rest }) => { if (readOnly) { return children @@ -68,113 +76,96 @@ const ReorderableList = ({ readOnly, children, ...rest }) => { return {children} } -const PlaylistSongs = (props) => { +const PlaylistSongs = ({ playlistId, readOnly, ...props }) => { + const { data, ids } = props const classes = useStyles(props) - const classesToolbar = useStylesListToolbar(props) const dispatch = useDispatch() const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs')) const isDesktop = useMediaQuery((theme) => theme.breakpoints.up('md')) - const controllerProps = useListController(props) const dataProvider = useDataProvider() const refresh = useRefresh() const notify = useNotify() - const { bulkActionButtons, expand, className, playlistId, readOnly } = props - const { data, ids, version, total } = controllerProps + const version = useVersion() - if (total === 0) { - return null - } - - const anySong = data[ids[0]] - const showPlaceholder = !anySong || anySong.playlistId !== playlistId - const hasBulkActions = props.bulkActionButtons !== false - - const reorder = (playlistId, id, newPos) => { - dataProvider - .update('playlistTrack', { - id, - data: { insert_before: newPos }, - filter: { playlist_id: playlistId }, - }) - .then(() => { + const onAddToPlaylist = useCallback( + (pls) => { + if (pls.id === playlistId) { refresh() - }) - .catch(() => { - notify('ra.page.error', 'warning') - }) - } + } + }, + [playlistId, refresh] + ) - const onAddToPlaylist = (pls) => { - if (pls.id === props.id) { - refresh() - } - } + const reorder = useCallback( + (playlistId, id, newPos) => { + dataProvider + .update('playlistTrack', { + id, + data: { insert_before: newPos }, + filter: { playlist_id: playlistId }, + }) + .then(() => { + refresh() + }) + .catch(() => { + notify('ra.page.error', 'warning') + }) + }, + [dataProvider, notify, refresh] + ) - const handleDragEnd = (from, to) => { - const toId = ids[to] - const fromId = ids[from] - reorder(playlistId, fromId, toId) - } + const handleDragEnd = useCallback( + (from, to) => { + const toId = ids[to] + const fromId = ids[from] + reorder(playlistId, fromId, toId) + }, + [playlistId, reorder, ids] + ) return ( <>
0, + [classes.bulkActionsDisplayed]: props.selectedIds.length > 0, })} key={version} > - {bulkActionButtons !== false && bulkActionButtons && ( - - {bulkActionButtons} - - )} - {showPlaceholder ? ( - - ) : ( - + + + + } + rowClick={(id) => dispatch(playTracks(data, ids, id))} + {...props} + hasBulkActions={true} + contextAlwaysVisible={!isDesktop} + classes={{ row: classes.row }} > - } - rowClick={(id) => dispatch(playTracks(data, ids, id))} - {...controllerProps} - hasBulkActions={hasBulkActions} - contextAlwaysVisible={!isDesktop} - > - {isDesktop && } - - {isDesktop && } - {isDesktop && } - - - - - )} + {isDesktop && } + + {isDesktop && } + {isDesktop && } + + + +
@@ -182,4 +173,19 @@ const PlaylistSongs = (props) => { ) } -export default PlaylistSongs +const SanitizedPlaylistSongs = (props) => { + const { loaded, loading, total, ...rest } = useListContext(props) + return ( + <> + {loaded && ( + + )} + + ) +} + +export default SanitizedPlaylistSongs