From d5da23ae42331cb314c60698fbae67eb84a4bdf7 Mon Sep 17 00:00:00 2001
From: Deluan <deluan@navidrome.org>
Date: Wed, 29 Jul 2020 14:12:51 -0400
Subject: [PATCH] Redirect from plain `/album` path to a default album list

---
 ui/src/album/AlbumList.js  | 16 ++++++++++++++--
 ui/src/album/albumLists.js | 25 +++++++++++++++++++++++++
 ui/src/layout/Menu.js      | 37 ++++++++-----------------------------
 3 files changed, 47 insertions(+), 31 deletions(-)
 create mode 100644 ui/src/album/albumLists.js

diff --git a/ui/src/album/AlbumList.js b/ui/src/album/AlbumList.js
index d8d9b7ea3..959e50781 100644
--- a/ui/src/album/AlbumList.js
+++ b/ui/src/album/AlbumList.js
@@ -1,6 +1,6 @@
 import React from 'react'
 import { useSelector } from 'react-redux'
-import { useLocation } from 'react-router-dom'
+import { Redirect, useLocation } from 'react-router-dom'
 import {
   AutocompleteInput,
   Filter,
@@ -19,6 +19,7 @@ import AlbumListView from './AlbumListView'
 import AlbumGridView from './AlbumGridView'
 import { ALBUM_MODE_LIST } from './albumState'
 import AddToPlaylistDialog from '../dialogs/AddToPlaylistDialog'
+import albumLists from './albumLists'
 
 const AlbumFilter = (props) => {
   const translate = useTranslate()
@@ -53,6 +54,18 @@ const AlbumList = (props) => {
   })
   const isArtistView = !!(query.filter && query.filter.artist_id)
 
+  // If it does not have filter/sort params (usually coming from Menu),
+  // reload with correct filter/sort params
+  if (!location.search) {
+    let type =
+      location.pathname.replace(/^\/album/, '').replace(/^\//, '') || 'all'
+
+    const listParams = albumLists[type]
+    if (listParams) {
+      return <Redirect to={`/album/${type}?${listParams.params}`} />
+    }
+  }
+
   return (
     <>
       <List
@@ -61,7 +74,6 @@ const AlbumList = (props) => {
         bulkActionButtons={false}
         actions={<AlbumListActions />}
         filters={<AlbumFilter />}
-        sort={{ field: 'name', order: 'ASC' }}
         perPage={perPage}
         pagination={<Pagination rowsPerPageOptions={perPageOptions} />}
       >
diff --git a/ui/src/album/albumLists.js b/ui/src/album/albumLists.js
new file mode 100644
index 000000000..49ec4674d
--- /dev/null
+++ b/ui/src/album/albumLists.js
@@ -0,0 +1,25 @@
+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'
+
+export default {
+  all: {
+    icon: AlbumIcon,
+    params: 'sort=name&order=ASC',
+  },
+  random: { icon: ShuffleIcon, params: 'sort=random' },
+  recentlyAdded: {
+    icon: LibraryAddIcon,
+    params: 'sort=created_at&order=DESC',
+  },
+  recentlyPlayed: {
+    icon: VideoLibraryIcon,
+    params: 'sort=play_date&order=DESC&filter={"recently_played":true}',
+  },
+  mostPlayed: {
+    icon: RepeatIcon,
+    params: 'sort=play_count&order=DESC&filter={"recently_played":true}',
+  },
+}
diff --git a/ui/src/layout/Menu.js b/ui/src/layout/Menu.js
index ff2fa5f8f..deff95bfd 100644
--- a/ui/src/layout/Menu.js
+++ b/ui/src/layout/Menu.js
@@ -10,10 +10,7 @@ import AlbumIcon from '@material-ui/icons/Album'
 import SubMenu from './SubMenu'
 import inflection from 'inflection'
 import PersonalMenu from './PersonalMenu'
-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 albumLists from '../album/albumLists'
 
 const translatedResourceName = (resource, translate) =>
   translate(`resources.${resource.name}.name`, {
@@ -27,26 +24,6 @@ const translatedResourceName = (resource, translate) =>
         : inflection.humanize(inflection.pluralize(resource.name)),
   })
 
-const albumLists = [
-  { type: '', icon: AlbumIcon, params: 'sort=name&order=ASC' },
-  { type: 'random', icon: ShuffleIcon, params: 'sort=random' },
-  {
-    type: 'recentlyAdded',
-    icon: LibraryAddIcon,
-    params: 'sort=created_at&order=DESC',
-  },
-  {
-    type: 'recentlyPlayed',
-    icon: VideoLibraryIcon,
-    params: 'sort=play_date&order=DESC&filter={"recently_played":true}',
-  },
-  {
-    type: 'mostPlayed',
-    icon: RepeatIcon,
-    params: 'sort=play_count&order=DESC&filter={"recently_played":true}',
-  },
-]
-
 const Menu = ({ onMenuClick, dense, logout }) => {
   const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs'))
   const open = useSelector((state) => state.admin.ui.sidebarOpen)
@@ -78,13 +55,13 @@ const Menu = ({ onMenuClick, dense, logout }) => {
     />
   )
 
-  const renderAlbumMenuItemLink = ({ type, params, icon }) => {
+  const renderAlbumMenuItemLink = (type, al) => {
     const resource = resources.find((r) => r.name === 'album')
     if (!resource) {
       return null
     }
 
-    const albumListAddress = `/album/${type}?${params}`
+    const albumListAddress = `/album/${type}`
 
     const name = translate(`resources.album.lists.${type || 'default'}`, {
       _: translatedResourceName(resource, translate),
@@ -92,10 +69,10 @@ const Menu = ({ onMenuClick, dense, logout }) => {
 
     return (
       <MenuItemLink
-        key={`album/${type}`}
+        key={albumListAddress}
         to={albumListAddress}
         primaryText={name}
-        leftIcon={(icon && createElement(icon)) || <ViewListIcon />}
+        leftIcon={(al.icon && createElement(al.icon)) || <ViewListIcon />}
         onClick={onMenuClick}
         sidebarIsOpen={open}
         dense={dense}
@@ -117,7 +94,9 @@ const Menu = ({ onMenuClick, dense, logout }) => {
         icon={<AlbumIcon />}
         dense={dense}
       >
-        {albumLists.map((al) => renderAlbumMenuItemLink(al))}
+        {Object.keys(albumLists).map((type) =>
+          renderAlbumMenuItemLink(type, albumLists[type])
+        )}
       </SubMenu>
       <SubMenu
         handleToggle={() => handleToggle('menuLibrary')}