diff --git a/persistence/artist_repository.go b/persistence/artist_repository.go
index 9ba4788c6..443cd41ec 100644
--- a/persistence/artist_repository.go
+++ b/persistence/artist_repository.go
@@ -30,7 +30,8 @@ func NewArtistRepository(ctx context.Context, o orm.Ormer) model.ArtistRepositor
"name": "order_artist_name",
}
r.filterMappings = map[string]filterFunc{
- "name": fullTextFilter,
+ "name": fullTextFilter,
+ "starred": booleanFilter,
}
return r
}
@@ -40,7 +41,7 @@ func (r *artistRepository) selectArtist(options ...model.QueryOptions) SelectBui
}
func (r *artistRepository) CountAll(options ...model.QueryOptions) (int64, error) {
- return r.count(Select(), options...)
+ return r.count(r.newSelectWithAnnotation("artist.id"), options...)
}
func (r *artistRepository) Exists(id string) (bool, error) {
@@ -197,6 +198,21 @@ func (r *artistRepository) NewInstance() interface{} {
return &model.Artist{}
}
-var _ model.ArtistRepository = (*artistRepository)(nil)
+func (r artistRepository) Delete(id string) error {
+ return r.delete(Eq{"id": id})
+}
+
+func (r artistRepository) Save(entity interface{}) (string, error) {
+ mf := entity.(*model.Artist)
+ err := r.Put(mf)
+ return mf.ID, err
+}
+
+func (r artistRepository) Update(entity interface{}, cols ...string) error {
+ mf := entity.(*model.Artist)
+ return r.Put(mf)
+}
+
var _ model.ArtistRepository = (*artistRepository)(nil)
var _ model.ResourceRepository = (*artistRepository)(nil)
+var _ rest.Persistable = (*artistRepository)(nil)
diff --git a/ui/src/artist/ArtistList.js b/ui/src/artist/ArtistList.js
index 9329a371c..4f44e98b4 100644
--- a/ui/src/artist/ArtistList.js
+++ b/ui/src/artist/ArtistList.js
@@ -9,10 +9,12 @@ import {
TextField,
} from 'react-admin'
import { useMediaQuery, withWidth } from '@material-ui/core'
+import StarIcon from '@material-ui/icons/Star'
import AddToPlaylistDialog from '../dialogs/AddToPlaylistDialog'
import {
ArtistContextMenu,
List,
+ QuickFilter,
SimpleList,
useGetHandleArtistClick,
} from '../common'
@@ -20,6 +22,11 @@ import {
const ArtistFilter = (props) => (
+ }
+ defaultValue={true}
+ />
)
diff --git a/ui/src/common/ContextMenus.js b/ui/src/common/ContextMenus.js
index e082c9b31..7089ec20f 100644
--- a/ui/src/common/ContextMenus.js
+++ b/ui/src/common/ContextMenus.js
@@ -6,8 +6,15 @@ import Menu from '@material-ui/core/Menu'
import MenuItem from '@material-ui/core/MenuItem'
import MoreVertIcon from '@material-ui/icons/MoreVert'
import StarIcon from '@material-ui/icons/Star'
+import StarBorderIcon from '@material-ui/icons/StarBorder'
import { makeStyles } from '@material-ui/core/styles'
-import { useDataProvider, useNotify, useTranslate } from 'react-admin'
+import {
+ useDataProvider,
+ useNotify,
+ useRefresh,
+ useTranslate,
+ useUpdate,
+} from 'react-admin'
import { addTracks, playTracks, shuffleTracks } from '../audioplayer'
import { openAddToPlaylist } from '../dialogs/dialogState'
import subsonic from '../subsonic'
@@ -21,16 +28,25 @@ const useStyles = makeStyles({
visibility: (props) => (props.visible ? 'visible' : 'hidden'),
},
star: {
- visibility: 'hidden', // TODO: Invisible for now
+ visibility: (props) =>
+ props.visible || props.starred ? 'visible' : 'hidden',
},
})
-const ContextMenu = ({ record, color, visible, songQueryParams }) => {
- const classes = useStyles({ color, visible })
+const ContextMenu = ({
+ resource,
+ showStar,
+ record,
+ color,
+ visible,
+ songQueryParams,
+}) => {
+ const classes = useStyles({ color, visible, starred: record.starred })
const dataProvider = useDataProvider()
const dispatch = useDispatch()
const translate = useTranslate()
const notify = useNotify()
+ const refresh = useRefresh()
const [anchorEl, setAnchorEl] = useState(null)
const options = {
@@ -102,13 +118,46 @@ const ContextMenu = ({ record, color, visible, songQueryParams }) => {
e.stopPropagation()
}
+ const [toggleStarred, { loading: updating }] = useUpdate(
+ resource,
+ record.id,
+ {
+ ...record,
+ starred: !record.starred,
+ },
+ {
+ undoable: false,
+ onFailure: (error) => {
+ console.log(error)
+ notify('ra.page.error', 'warning')
+ refresh()
+ },
+ }
+ )
+
+ const handleToggleStar = (e) => {
+ toggleStarred()
+ e.stopPropagation()
+ }
+
const open = Boolean(anchorEl)
return (
-
-
-
+ {showStar && (
+
+ {record.starred ? (
+
+ ) : (
+
+ )}
+
+ )}