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',
+ },
+}))