diff --git a/ui/src/album/albumLists.js b/ui/src/album/albumLists.js
index e38bcb612..c18c38ffc 100644
--- a/ui/src/album/albumLists.js
+++ b/ui/src/album/albumLists.js
@@ -1,40 +1,80 @@
+import React from 'react'
import ShuffleIcon from '@material-ui/icons/Shuffle'
import LibraryAddIcon from '@material-ui/icons/LibraryAdd'
import VideoLibraryIcon from '@material-ui/icons/VideoLibrary'
import RepeatIcon from '@material-ui/icons/Repeat'
import AlbumIcon from '@material-ui/icons/Album'
import FavoriteIcon from '@material-ui/icons/Favorite'
+import FavoriteBorderIcon from '@material-ui/icons/FavoriteBorder'
import StarIcon from '@material-ui/icons/Star'
+import StarBorderIcon from '@material-ui/icons/StarBorder'
+import AlbumOutlinedIcon from '@material-ui/icons/AlbumOutlined'
+import LibraryAddOutlinedIcon from '@material-ui/icons/LibraryAddOutlined'
+import VideoLibraryOutlinedIcon from '@material-ui/icons/VideoLibraryOutlined'
import config from '../config'
+import DynamicMenuIcon from '../layout/DynamicMenuIcon'
export default {
all: {
- icon: AlbumIcon,
+ icon: (
+
+ ),
params: 'sort=name&order=ASC',
},
- random: { icon: ShuffleIcon, params: 'sort=random&order=ASC' },
+ random: {
+ icon: ,
+ params: 'sort=random&order=ASC',
+ },
...(config.enableFavourites && {
starred: {
- icon: FavoriteIcon,
+ icon: (
+
+ ),
params: 'sort=starred_at&order=DESC&filter={"starred":true}',
},
}),
...(config.enableStarRating && {
topRated: {
- icon: StarIcon,
+ icon: (
+
+ ),
params: 'sort=rating&order=DESC&filter={"has_rating":true}',
},
}),
recentlyAdded: {
- icon: LibraryAddIcon,
+ icon: (
+
+ ),
params: 'sort=recently_added&order=DESC',
},
recentlyPlayed: {
- icon: VideoLibraryIcon,
+ icon: (
+
+ ),
params: 'sort=play_date&order=DESC&filter={"recently_played":true}',
},
mostPlayed: {
- icon: RepeatIcon,
+ icon: ,
params: 'sort=play_count&order=DESC&filter={"recently_played":true}',
},
}
diff --git a/ui/src/album/index.js b/ui/src/album/index.js
index dc1a684a4..1cdb9d05a 100644
--- a/ui/src/album/index.js
+++ b/ui/src/album/index.js
@@ -1,9 +1,7 @@
-import AlbumIcon from '@material-ui/icons/Album'
import AlbumList from './AlbumList'
import AlbumShow from './AlbumShow'
export default {
list: AlbumList,
show: AlbumShow,
- icon: AlbumIcon,
}
diff --git a/ui/src/artist/index.js b/ui/src/artist/index.js
index 1cd69b12c..206bfb6cd 100644
--- a/ui/src/artist/index.js
+++ b/ui/src/artist/index.js
@@ -1,7 +1,16 @@
-import MicIcon from '@material-ui/icons/Mic'
+import React from 'react'
import ArtistList from './ArtistList'
+import DynamicMenuIcon from '../layout/DynamicMenuIcon'
+import MicNoneOutlinedIcon from '@material-ui/icons/MicNoneOutlined'
+import MicIcon from '@material-ui/icons/Mic'
export default {
list: ArtistList,
- icon: MicIcon,
+ icon: (
+
+ ),
}
diff --git a/ui/src/layout/DynamicMenuIcon.js b/ui/src/layout/DynamicMenuIcon.js
new file mode 100644
index 000000000..e86bff6ca
--- /dev/null
+++ b/ui/src/layout/DynamicMenuIcon.js
@@ -0,0 +1,23 @@
+import PropTypes from 'prop-types'
+import { useLocation } from 'react-router-dom'
+import { createElement } from 'react'
+
+const DynamicMenuIcon = ({ icon, activeIcon, path }) => {
+ const location = useLocation()
+
+ if (!activeIcon) {
+ return createElement(icon, { 'data-testid': 'icon' })
+ }
+
+ return location.pathname.startsWith('/' + path)
+ ? createElement(activeIcon, { 'data-testid': 'activeIcon' })
+ : createElement(icon, { 'data-testid': 'icon' })
+}
+
+DynamicMenuIcon.propTypes = {
+ path: PropTypes.string.isRequired,
+ icon: PropTypes.object.isRequired,
+ activeIcon: PropTypes.object,
+}
+
+export default DynamicMenuIcon
diff --git a/ui/src/layout/DynamicMenuIcon.test.js b/ui/src/layout/DynamicMenuIcon.test.js
new file mode 100644
index 000000000..a48ed9aff
--- /dev/null
+++ b/ui/src/layout/DynamicMenuIcon.test.js
@@ -0,0 +1,56 @@
+import * as React from 'react'
+import { cleanup, render } from '@testing-library/react'
+import { createMemoryHistory } from 'history'
+import { Router } from 'react-router-dom'
+import StarIcon from '@material-ui/icons/Star'
+import StarBorderIcon from '@material-ui/icons/StarBorder'
+import DynamicMenuIcon from './DynamicMenuIcon'
+
+describe('', () => {
+ it('renders icon if no activeIcon is specified', () => {
+ const history = createMemoryHistory()
+ const route = '/test'
+ history.push(route)
+
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('icon')).not.toBeNull()
+ })
+
+ it('renders icon if path does not match the URL', () => {
+ const history = createMemoryHistory()
+ const route = '/path'
+ history.push(route)
+
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('icon')).not.toBeNull()
+ })
+
+ it('renders activeIcon if path matches the URL', () => {
+ const history = createMemoryHistory()
+ const route = '/path'
+ history.push(route)
+
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('activeIcon')).not.toBeNull()
+ })
+})
diff --git a/ui/src/layout/Menu.js b/ui/src/layout/Menu.js
index 9aae9c05d..820d6a5ae 100644
--- a/ui/src/layout/Menu.js
+++ b/ui/src/layout/Menu.js
@@ -1,6 +1,6 @@
-import React, { useState, createElement } from 'react'
+import React, { useState } from 'react'
import { useSelector } from 'react-redux'
-import { useMediaQuery } from '@material-ui/core'
+import { makeStyles, useMediaQuery } from '@material-ui/core'
import { useTranslate, MenuItemLink, getResources } from 'react-admin'
import { withRouter } from 'react-router-dom'
import LibraryMusicIcon from '@material-ui/icons/LibraryMusic'
@@ -11,6 +11,13 @@ import inflection from 'inflection'
import albumLists from '../album/albumLists'
import { HelpDialog } from '../dialogs'
+const useStyles = makeStyles((theme) => ({
+ active: {
+ color: theme.palette.text.primary,
+ fontWeight: 'bold',
+ },
+}))
+
const translatedResourceName = (resource, translate) =>
translate(`resources.${resource.name}.name`, {
smart_count: 2,
@@ -27,6 +34,7 @@ const Menu = ({ onMenuClick, dense, logout }) => {
const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs'))
const open = useSelector((state) => state.admin.ui.sidebarOpen)
const translate = useTranslate()
+ const classes = useStyles()
const resources = useSelector(getResources)
// TODO State is not persisted in mobile when you close the sidebar menu. Move to redux?
@@ -44,10 +52,9 @@ const Menu = ({ onMenuClick, dense, logout }) => {
- }
+ leftIcon={resource.icon || }
onClick={onMenuClick}
sidebarIsOpen={open}
dense={dense}
@@ -70,8 +77,9 @@ const Menu = ({ onMenuClick, dense, logout }) => {
}
+ leftIcon={al.icon || }
onClick={onMenuClick}
sidebarIsOpen={open}
dense={dense}
diff --git a/ui/src/playlist/index.js b/ui/src/playlist/index.js
index 19530f8e8..3a7111ddb 100644
--- a/ui/src/playlist/index.js
+++ b/ui/src/playlist/index.js
@@ -1,13 +1,22 @@
-import PlaylistIcon from '../icons/Playlist'
+import React from 'react'
+import QueueMusicOutlinedIcon from '@material-ui/icons/QueueMusicOutlined'
+import QueueMusicIcon from '@material-ui/icons/QueueMusic'
+import DynamicMenuIcon from '../layout/DynamicMenuIcon'
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,
+ icon: (
+
+ ),
}
diff --git a/ui/src/song/index.js b/ui/src/song/index.js
index 949bd6184..bbd3b2086 100644
--- a/ui/src/song/index.js
+++ b/ui/src/song/index.js
@@ -1,7 +1,16 @@
-import MusicNoteIcon from '@material-ui/icons/MusicNote'
+import React from 'react'
import SongList from './SongList'
+import MusicNoteOutlinedIcon from '@material-ui/icons/MusicNoteOutlined'
+import MusicNoteIcon from '@material-ui/icons/MusicNote'
+import DynamicMenuIcon from '../layout/DynamicMenuIcon'
export default {
list: SongList,
- icon: MusicNoteIcon,
+ icon: (
+
+ ),
}