mirror of
https://github.com/navidrome/navidrome.git
synced 2025-05-06 05:11:07 +03:00
Add a sortable Starred column and a Starred filter to Song List
This commit is contained in:
parent
3632608de0
commit
ec0002e77a
@ -29,12 +29,13 @@ func NewMediaFileRepository(ctx context.Context, o orm.Ormer) *mediaFileReposito
|
|||||||
}
|
}
|
||||||
r.filterMappings = map[string]filterFunc{
|
r.filterMappings = map[string]filterFunc{
|
||||||
"title": fullTextFilter,
|
"title": fullTextFilter,
|
||||||
|
"starred": booleanFilter,
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r mediaFileRepository) CountAll(options ...model.QueryOptions) (int64, error) {
|
func (r mediaFileRepository) CountAll(options ...model.QueryOptions) (int64, error) {
|
||||||
return r.count(Select(), options...)
|
return r.count(r.newSelectWithAnnotation("id", options...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r mediaFileRepository) Exists(id string) (bool, error) {
|
func (r mediaFileRepository) Exists(id string) (bool, error) {
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
ListToolbar,
|
ListToolbar,
|
||||||
TextField,
|
TextField,
|
||||||
useListController,
|
useListController,
|
||||||
|
useTranslate,
|
||||||
} from 'react-admin'
|
} from 'react-admin'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import { useDispatch } from 'react-redux'
|
import { useDispatch } from 'react-redux'
|
||||||
@ -65,6 +66,7 @@ const trackName = (r) => {
|
|||||||
|
|
||||||
const AlbumSongs = (props) => {
|
const AlbumSongs = (props) => {
|
||||||
const classes = useStyles(props)
|
const classes = useStyles(props)
|
||||||
|
const translate = useTranslate()
|
||||||
const classesToolbar = useStylesListToolbar(props)
|
const classesToolbar = useStylesListToolbar(props)
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs'))
|
const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs'))
|
||||||
@ -144,7 +146,9 @@ const AlbumSongs = (props) => {
|
|||||||
)}
|
)}
|
||||||
{isDesktop && <TextField source="artist" sortable={false} />}
|
{isDesktop && <TextField source="artist" sortable={false} />}
|
||||||
<DurationField source="duration" sortable={false} />
|
<DurationField source="duration" sortable={false} />
|
||||||
<SongContextMenu />
|
<SongContextMenu
|
||||||
|
label={translate('resources.song.fields.starred')}
|
||||||
|
/>
|
||||||
</SongDatagrid>
|
</SongDatagrid>
|
||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
"size": "File size",
|
"size": "File size",
|
||||||
"bitRate": "Bit rate",
|
"bitRate": "Bit rate",
|
||||||
"updatedAt": "Uploaded at",
|
"updatedAt": "Uploaded at",
|
||||||
"discSubtitle": "Disc Subtitle"
|
"discSubtitle": "Disc Subtitle",
|
||||||
|
"starred": "Starred"
|
||||||
},
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
"addToQueue": "Play Later",
|
"addToQueue": "Play Later",
|
||||||
|
@ -2,11 +2,14 @@ import React from 'react'
|
|||||||
import {
|
import {
|
||||||
Filter,
|
Filter,
|
||||||
FunctionField,
|
FunctionField,
|
||||||
|
NullableBooleanInput,
|
||||||
NumberField,
|
NumberField,
|
||||||
SearchInput,
|
SearchInput,
|
||||||
TextField,
|
TextField,
|
||||||
|
useTranslate,
|
||||||
} from 'react-admin'
|
} from 'react-admin'
|
||||||
import { useMediaQuery } from '@material-ui/core'
|
import { useMediaQuery } from '@material-ui/core'
|
||||||
|
import StarBorderIcon from '@material-ui/icons/StarBorder'
|
||||||
import {
|
import {
|
||||||
DurationField,
|
DurationField,
|
||||||
SimpleList,
|
SimpleList,
|
||||||
@ -23,11 +26,13 @@ import { AlbumLinkField } from './AlbumLinkField'
|
|||||||
const SongFilter = (props) => (
|
const SongFilter = (props) => (
|
||||||
<Filter {...props}>
|
<Filter {...props}>
|
||||||
<SearchInput source="title" alwaysOn />
|
<SearchInput source="title" alwaysOn />
|
||||||
|
<NullableBooleanInput source="starred" />
|
||||||
</Filter>
|
</Filter>
|
||||||
)
|
)
|
||||||
|
|
||||||
const SongList = (props) => {
|
const SongList = (props) => {
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
|
const translate = useTranslate()
|
||||||
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'))
|
||||||
return (
|
return (
|
||||||
@ -66,7 +71,10 @@ const SongList = (props) => {
|
|||||||
<FunctionField source="year" render={(r) => r.year || ''} />
|
<FunctionField source="year" render={(r) => r.year || ''} />
|
||||||
)}
|
)}
|
||||||
<DurationField source="duration" />
|
<DurationField source="duration" />
|
||||||
<SongContextMenu />
|
<SongContextMenu
|
||||||
|
label={translate('resources.song.fields.starred')}
|
||||||
|
sortBy={'starred DESC, starredAt ASC'}
|
||||||
|
/>
|
||||||
</SongDatagrid>
|
</SongDatagrid>
|
||||||
)}
|
)}
|
||||||
</List>
|
</List>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user