diff --git a/ui/src/album/AlbumActions.js b/ui/src/album/AlbumActions.js index 18261f659..70cb28d38 100644 --- a/ui/src/album/AlbumActions.js +++ b/ui/src/album/AlbumActions.js @@ -10,7 +10,7 @@ import React from 'react' import { useDispatch } from 'react-redux' import { playAlbum, shuffleAlbum } from '../audioplayer' -export const AlbumActions = ({ +const AlbumActions = ({ className, ids, data, @@ -47,3 +47,5 @@ AlbumActions.defaultProps = { selectedIds: [], onUnselectItems: () => null, } + +export default AlbumActions diff --git a/ui/src/album/AlbumShow.js b/ui/src/album/AlbumShow.js index a8b7c21cd..62b307b65 100644 --- a/ui/src/album/AlbumShow.js +++ b/ui/src/album/AlbumShow.js @@ -3,8 +3,8 @@ import { useGetOne } from 'react-admin' import AlbumDetails from './AlbumDetails' import { Title } from '../common' import { useStyles } from './styles' -import { AlbumActions } from './AlbumActions' import { AlbumSongBulkActions } from './AlbumSongBulkActions' +import AlbumActions from './AlbumActions' import AlbumSongs from './AlbumSongs' const AlbumShow = (props) => { diff --git a/ui/src/album/AlbumSongs.js b/ui/src/album/AlbumSongs.js index 96afe70c7..71ac13684 100644 --- a/ui/src/album/AlbumSongs.js +++ b/ui/src/album/AlbumSongs.js @@ -2,28 +2,19 @@ import React from 'react' import { BulkActionsToolbar, Datagrid, + DatagridBody, + DatagridLoading, FunctionField, ListToolbar, TextField, useListController, - useTranslate, - DatagridLoading, - DatagridBody, - DatagridRow, } from 'react-admin' import classnames from 'classnames' import { useDispatch } from 'react-redux' -import { - Card, - useMediaQuery, - TableRow, - TableCell, - Typography, -} from '@material-ui/core' +import { Card, useMediaQuery } from '@material-ui/core' import { makeStyles } from '@material-ui/core/styles' import { playAlbum } from '../audioplayer' -import { DurationField } from '../common' -import { SongDetails } from '../common' +import { DurationField, SongDetails, SongDatagridRow } from '../common' const useStyles = makeStyles( (theme) => ({ @@ -72,7 +63,6 @@ const trackName = (r) => { const AlbumSongs = (props) => { const classes = useStyles(props) const classesToolbar = useStylesListToolbar(props) - const translate = useTranslate() const dispatch = useDispatch() const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs')) const isDesktop = useMediaQuery((theme) => theme.breakpoints.up('md')) @@ -93,35 +83,8 @@ const AlbumSongs = (props) => { const showPlaceholder = !anySong || anySong.albumId !== albumId const hasBulkActions = props.bulkActionButtons !== false - const SongDatagridRow = (props) => { - const { record, children } = props - return ( - <> - {multiDisc && ( - - {record.trackNumber === 1 && ( - - - {record.discSubtitle - ? translate('message.discSubtitle', { - subtitle: record.discSubtitle, - number: record.discNumber, - }) - : translate('message.discWithoutSubtitle', { - number: record.discNumber, - })} - - - )} - - )} - - - ) - } - const SongsDatagridBody = (props) => ( - } /> + } /> ) const SongsDatagrid = (props) => ( } /> @@ -164,7 +127,6 @@ const AlbumSongs = (props) => { rowClick={(id) => dispatch(playAlbum(data, ids, id))} {...controllerProps} hasBulkActions={hasBulkActions} - multiDisc={multiDisc} > {isDesktop && ( { + const translate = useTranslate() + return ( + <> + {multiDisc && ( + + {record.trackNumber === 1 && ( + + + {record.discSubtitle + ? translate('message.discSubtitle', { + subtitle: record.discSubtitle, + number: record.discNumber, + }) + : translate('message.discWithoutSubtitle', { + number: record.discNumber, + })} + + + )} + + )} + + {children} + + + ) +} + +RangeField.propTypes = { + record: PropTypes.object, + children: PropTypes.node, + multiDisc: PropTypes.bool, +} + +export default SongDatagridRow diff --git a/ui/src/common/index.js b/ui/src/common/index.js index 2b9bb28c3..b74fb3e94 100644 --- a/ui/src/common/index.js +++ b/ui/src/common/index.js @@ -10,6 +10,7 @@ import SongDetails from './SongDetails' import SizeField from './SizeField' import DocLink from './DocLink' import List from './List' +import SongDatagridRow from './SongDatagridRow' export { Title, @@ -22,6 +23,7 @@ export { SimpleList, RangeField, SongDetails, + SongDatagridRow, DocLink, formatRange, ArtistLinkField, diff --git a/ui/src/playlist/PlaylistDetails.js b/ui/src/playlist/PlaylistDetails.js new file mode 100644 index 000000000..7aaed0342 --- /dev/null +++ b/ui/src/playlist/PlaylistDetails.js @@ -0,0 +1,59 @@ +import React from 'react' +import { Card, CardContent, Typography } from '@material-ui/core' +import { makeStyles } from '@material-ui/core/styles' +import { useTranslate } from 'react-admin' +import { DurationField } from '../common' + +const useStyles = makeStyles((theme) => ({ + container: { + [theme.breakpoints.down('xs')]: { + padding: '0.7em', + minWidth: '24em', + }, + [theme.breakpoints.up('sm')]: { + padding: '1em', + minWidth: '32em', + }, + }, + details: { + display: 'inline-block', + verticalAlign: 'top', + [theme.breakpoints.down('xs')]: { + width: '14em', + }, + [theme.breakpoints.up('sm')]: { + width: '26em', + }, + [theme.breakpoints.up('lg')]: { + width: '38em', + }, + }, + title: { + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', + }, +})) + +const PlaylistDetails = ({ record }) => { + const translate = useTranslate() + const classes = useStyles() + + return ( + + + + {record.name} + + {record.comment} + + {record.songCount}{' '} + {translate('resources.song.name', { smart_count: record.songCount })}{' '} + ยท + + + + ) +} + +export default PlaylistDetails diff --git a/ui/src/playlist/PlaylistList.js b/ui/src/playlist/PlaylistList.js index 6b4b2f56e..31defa481 100644 --- a/ui/src/playlist/PlaylistList.js +++ b/ui/src/playlist/PlaylistList.js @@ -10,7 +10,7 @@ import { DurationField, List } from '../common' const PlaylistList = (props) => ( - + diff --git a/ui/src/playlist/PlaylistShow.js b/ui/src/playlist/PlaylistShow.js new file mode 100644 index 000000000..830571927 --- /dev/null +++ b/ui/src/playlist/PlaylistShow.js @@ -0,0 +1,38 @@ +import React from 'react' +import { useGetOne } from 'react-admin' +import PlaylistDetails from './PlaylistDetails' +import { Title } from '../common' +import PlaylistSongs from './PlaylistSongs' + +const PlaylistShow = (props) => { + const { data: record, loading, error } = useGetOne('playlist', props.id) + + if (loading) { + return null + } + + if (error) { + return

ERROR: {error}

+ } + + return ( + <> + + } + // actions={} + filter={{ playlist_id: props.id }} + resource={'playlistTrack'} + exporter={false} + perPage={-1} + pagination={null} + bulkActionButtons={false} + // bulkActionButtons={} + /> + + ) +} + +export default PlaylistShow diff --git a/ui/src/playlist/PlaylistSongs.js b/ui/src/playlist/PlaylistSongs.js new file mode 100644 index 000000000..eb2e50e91 --- /dev/null +++ b/ui/src/playlist/PlaylistSongs.js @@ -0,0 +1,113 @@ +import React from 'react' +import { + BulkActionsToolbar, + Datagrid, + DatagridLoading, + ListToolbar, + TextField, + useListController, +} from 'react-admin' +import classnames from 'classnames' +import { Card, useMediaQuery } from '@material-ui/core' +import { makeStyles } from '@material-ui/core/styles' +import { DurationField, SongDetails } from '../common' + +const useStyles = makeStyles( + (theme) => ({ + root: {}, + main: { + display: 'flex', + }, + content: { + marginTop: 0, + transition: theme.transitions.create('margin-top'), + position: 'relative', + flex: '1 1 auto', + [theme.breakpoints.down('xs')]: { + boxShadow: 'none', + }, + }, + bulkActionsDisplayed: { + marginTop: -theme.spacing(8), + transition: theme.transitions.create('margin-top'), + }, + actions: { + zIndex: 2, + display: 'flex', + justifyContent: 'flex-end', + flexWrap: 'wrap', + }, + noResults: { padding: 20 }, + }), + { name: 'RaList' } +) + +const useStylesListToolbar = makeStyles({ + toolbar: { + justifyContent: 'flex-start', + }, +}) + +const PlaylistSongs = (props) => { + const classes = useStyles(props) + const classesToolbar = useStylesListToolbar(props) + const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs')) + // const isDesktop = useMediaQuery((theme) => theme.breakpoints.up('md')) + const controllerProps = useListController(props) + const { bulkActionButtons, expand, className } = props + const { data, ids, version } = controllerProps + + const anySong = data[ids[0]] + const showPlaceholder = !anySong + const hasBulkActions = props.bulkActionButtons !== false + + return ( + <> + +
+ 0, + })} + key={version} + > + {bulkActionButtons !== false && bulkActionButtons && ( + + {bulkActionButtons} + + )} + {showPlaceholder ? ( + + ) : ( + } + rowClick={null} + {...controllerProps} + hasBulkActions={hasBulkActions} + > + + + + + )} + +
+ + ) +} + +export default PlaylistSongs diff --git a/ui/src/playlist/index.js b/ui/src/playlist/index.js index d97692910..19530f8e8 100644 --- a/ui/src/playlist/index.js +++ b/ui/src/playlist/index.js @@ -2,10 +2,12 @@ import PlaylistIcon from '../icons/Playlist' import PlaylistList from './PlaylistList' import PlaylistEdit from './PlaylistEdit' import PlaylistCreate from './PlaylistCreate' +import PlaylistShow from './PlaylistShow' export default { icon: PlaylistIcon, list: PlaylistList, create: PlaylistCreate, edit: PlaylistEdit, + show: PlaylistShow, } diff --git a/ui/src/playlist/styles.js b/ui/src/playlist/styles.js new file mode 100644 index 000000000..0881fdabe --- /dev/null +++ b/ui/src/playlist/styles.js @@ -0,0 +1,47 @@ +import { makeStyles } from '@material-ui/core/styles' + +export const useStyles = makeStyles((theme) => ({ + container: { + [theme.breakpoints.down('xs')]: { + padding: '0.7em', + minWidth: '24em', + }, + [theme.breakpoints.up('sm')]: { + padding: '1em', + minWidth: '32em', + }, + }, + albumCover: { + display: 'inline-block', + [theme.breakpoints.down('xs')]: { + height: '8em', + width: '8em', + }, + [theme.breakpoints.up('sm')]: { + height: '10em', + width: '10em', + }, + [theme.breakpoints.up('lg')]: { + height: '15em', + width: '15em', + }, + }, + albumDetails: { + display: 'inline-block', + verticalAlign: 'top', + [theme.breakpoints.down('xs')]: { + width: '14em', + }, + [theme.breakpoints.up('sm')]: { + width: '26em', + }, + [theme.breakpoints.up('lg')]: { + width: '38em', + }, + }, + albumTitle: { + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', + }, +}))