Initial support for song browsing from UI
This commit is contained in:
@@ -5,6 +5,7 @@ import dataProvider from './dataProvider'
|
||||
import authProvider from './authProvider'
|
||||
import { Login } from './layout'
|
||||
import user from './user'
|
||||
import song from './song'
|
||||
|
||||
const App = () => (
|
||||
<Admin
|
||||
@@ -12,6 +13,7 @@ const App = () => (
|
||||
authProvider={authProvider}
|
||||
loginPage={Login}
|
||||
>
|
||||
<Resource name="song" {...song} />
|
||||
<Resource name="user" {...user} />
|
||||
</Admin>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
const BitrateField = ({ record = {}, source }) => {
|
||||
return <span>{`${record[source]} kbps`}</span>
|
||||
}
|
||||
|
||||
BitrateField.propTypes = {
|
||||
label: PropTypes.string,
|
||||
record: PropTypes.object,
|
||||
source: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
BitrateField.defaultProps = {
|
||||
addLabel: true
|
||||
}
|
||||
|
||||
export default BitrateField
|
||||
@@ -0,0 +1,25 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
const DurationField = ({ record = {}, source }) => {
|
||||
return <span>{format(record[source])}</span>
|
||||
}
|
||||
|
||||
const format = (d) => {
|
||||
const date = new Date(null)
|
||||
date.setSeconds(d)
|
||||
const fmt = date.toISOString().substr(11, 8)
|
||||
return fmt.replace(/^00:/, '')
|
||||
}
|
||||
|
||||
DurationField.propTypes = {
|
||||
label: PropTypes.string,
|
||||
record: PropTypes.object,
|
||||
source: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
DurationField.defaultProps = {
|
||||
addLabel: true
|
||||
}
|
||||
|
||||
export default DurationField
|
||||
@@ -0,0 +1,7 @@
|
||||
import React from 'react'
|
||||
|
||||
const Title = ({ subTitle }) => {
|
||||
return <span>CloudSonic {subTitle ? ` - ${subTitle}` : ''}</span>
|
||||
}
|
||||
|
||||
export default Title
|
||||
@@ -0,0 +1,5 @@
|
||||
import Title from './Title'
|
||||
import DurationField from './DurationField'
|
||||
import BitrateField from './BitrateField'
|
||||
|
||||
export { Title, DurationField, BitrateField }
|
||||
@@ -0,0 +1,59 @@
|
||||
import React from 'react'
|
||||
import {
|
||||
BooleanField,
|
||||
Datagrid,
|
||||
DateField,
|
||||
Filter,
|
||||
List,
|
||||
NumberField,
|
||||
SearchInput,
|
||||
Show,
|
||||
SimpleShowLayout,
|
||||
TextField
|
||||
} from 'react-admin'
|
||||
import { BitrateField, DurationField, Title } from '../common'
|
||||
|
||||
const SongFilter = (props) => (
|
||||
<Filter {...props}>
|
||||
<SearchInput source="title" alwaysOn />
|
||||
</Filter>
|
||||
)
|
||||
|
||||
const SongDetails = (props) => {
|
||||
return (
|
||||
<Show {...props} title=" ">
|
||||
<SimpleShowLayout>
|
||||
<TextField source="path" />
|
||||
<TextField label="Album Artist" source="albumArtist" />
|
||||
<TextField source="genre" />
|
||||
<BooleanField source="compilation" />
|
||||
<BitrateField source="bitRate" />
|
||||
<DateField source="updatedAt" showTime />
|
||||
</SimpleShowLayout>
|
||||
</Show>
|
||||
)
|
||||
}
|
||||
|
||||
const SongList = (props) => (
|
||||
<List
|
||||
{...props}
|
||||
title={<Title subTitle={'Songs'} />}
|
||||
sort={{ field: 'title', order: 'ASC' }}
|
||||
exporter={false}
|
||||
bulkActionButtons={false}
|
||||
filters={<SongFilter />}
|
||||
perPage={15}
|
||||
>
|
||||
<Datagrid rowClick="expand" expand={<SongDetails />}>
|
||||
<TextField source="title" />
|
||||
<TextField source="album" />
|
||||
<TextField source="artist" />
|
||||
<NumberField label="Track #" source="trackNumber" />
|
||||
<NumberField label="Disc #" source="discNumber" />
|
||||
<TextField source="year" />
|
||||
<DurationField label="Time" source="duration" />
|
||||
</Datagrid>
|
||||
</List>
|
||||
)
|
||||
|
||||
export default SongList
|
||||
@@ -0,0 +1,7 @@
|
||||
import MusicNote from '@material-ui/icons/MusicNote'
|
||||
import SongList from './SongList'
|
||||
|
||||
export default {
|
||||
list: SongList,
|
||||
icon: MusicNote
|
||||
}
|
||||
@@ -8,9 +8,10 @@ import {
|
||||
email,
|
||||
SimpleForm
|
||||
} from 'react-admin'
|
||||
import { Title } from '../common'
|
||||
|
||||
const UserCreate = (props) => (
|
||||
<Create {...props}>
|
||||
<Create title={<Title subTitle={'Create User'} />} {...props}>
|
||||
<SimpleForm redirect="list">
|
||||
<TextInput source="userName" validate={[required()]} />
|
||||
<TextInput source="name" validate={[required()]} />
|
||||
|
||||
@@ -9,9 +9,10 @@ import {
|
||||
email,
|
||||
SimpleForm
|
||||
} from 'react-admin'
|
||||
import { Title } from '../common'
|
||||
|
||||
const UserTitle = ({ record }) => {
|
||||
return <span>User {record ? record.name : ''}</span>
|
||||
return <Title subTitle={`User ${record ? record.name : ''}`} />
|
||||
}
|
||||
const UserEdit = (props) => (
|
||||
<Edit title={<UserTitle />} {...props}>
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
TextField
|
||||
} from 'react-admin'
|
||||
import { useMediaQuery } from '@material-ui/core'
|
||||
import { Title } from '../common'
|
||||
|
||||
const UserFilter = (props) => (
|
||||
<Filter {...props}>
|
||||
@@ -23,6 +24,7 @@ const UserList = (props) => {
|
||||
return (
|
||||
<List
|
||||
{...props}
|
||||
title={<Title subTitle={'Users'} />}
|
||||
sort={{ field: 'userName', order: 'ASC' }}
|
||||
exporter={false}
|
||||
filters={<UserFilter />}
|
||||
|
||||
Reference in New Issue
Block a user