diff --git a/ui/src/App.js b/ui/src/App.js index e992c087a..9a248980f 100644 --- a/ui/src/App.js +++ b/ui/src/App.js @@ -3,7 +3,7 @@ import React from 'react' import { Admin, Resource } from 'react-admin' import dataProvider from './dataProvider' import authProvider from './authProvider' -import { Login } from './layout' +import { Login, Layout } from './layout' import user from './user' import song from './song' import album from './album' @@ -12,10 +12,11 @@ const App = () => ( - - + + ) diff --git a/ui/src/album/AlbumList.js b/ui/src/album/AlbumList.js index 9ffd2527d..03557bde7 100644 --- a/ui/src/album/AlbumList.js +++ b/ui/src/album/AlbumList.js @@ -12,7 +12,7 @@ import { SimpleShowLayout, TextField } from 'react-admin' -import { BitrateField, DurationField, Title } from '../common' +import { DurationField, Title } from '../common' const AlbumFilter = (props) => ( diff --git a/ui/src/layout/Layout.js b/ui/src/layout/Layout.js new file mode 100644 index 000000000..1a11c11f2 --- /dev/null +++ b/ui/src/layout/Layout.js @@ -0,0 +1,5 @@ +import React from 'react' +import { Layout } from 'react-admin' +import Menu from './Menu' + +export default (props) => diff --git a/ui/src/layout/Menu.js b/ui/src/layout/Menu.js new file mode 100644 index 000000000..9e8229a51 --- /dev/null +++ b/ui/src/layout/Menu.js @@ -0,0 +1,73 @@ +// in src/Menu.js +import React, { useState, createElement } from 'react' +import { useSelector } from 'react-redux' +import { 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' +import ViewListIcon from '@material-ui/icons/ViewList' +import SubMenu from './SubMenu' +import inflection from 'inflection' + +const translatedResourceName = (resource, translate) => + translate(`resources.${resource.name}.name`, { + smart_count: 2, + _: + resource.options && resource.options.label + ? translate(resource.options.label, { + smart_count: 2, + _: resource.options.label + }) + : inflection.humanize(inflection.pluralize(resource.name)) + }) + +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 resources = useSelector(getResources) + + const [state, setState] = useState({ + menuLibrary: true + }) + + const handleToggle = (menu) => { + setState((state) => ({ ...state, [menu]: !state[menu] })) + } + + const renderMenuItemLink = (resource) => ( + + } + onClick={onMenuClick} + sidebarIsOpen={open} + dense={dense} + /> + ) + + const subItems = (subMenu) => (resource) => + resource.hasList && resource.options && resource.options.subMenu === subMenu + + return ( +
+ handleToggle('menuLibrary')} + isOpen={state.menuLibrary} + sidebarIsOpen={open} + name="Library" + icon={} + dense={dense} + > + {resources.filter(subItems('library')).map(renderMenuItemLink)} + + {resources.filter(subItems(undefined)).map(renderMenuItemLink)} + {isXsmall && logout} +
+ ) +} + +export default withRouter(Menu) diff --git a/ui/src/layout/SubMenu.js b/ui/src/layout/SubMenu.js new file mode 100644 index 000000000..1bd5a4afb --- /dev/null +++ b/ui/src/layout/SubMenu.js @@ -0,0 +1,74 @@ +import React, { Fragment } from 'react' +import ExpandMore from '@material-ui/icons/ExpandMore' +import List from '@material-ui/core/List' +import MenuItem from '@material-ui/core/MenuItem' +import ListItemIcon from '@material-ui/core/ListItemIcon' +import Typography from '@material-ui/core/Typography' +import Divider from '@material-ui/core/Divider' +import Collapse from '@material-ui/core/Collapse' +import Tooltip from '@material-ui/core/Tooltip' +import { makeStyles } from '@material-ui/core/styles' +import { useTranslate } from 'react-admin' + +const useStyles = makeStyles((theme) => ({ + icon: { minWidth: theme.spacing(5) }, + sidebarIsOpen: { + paddingLeft: 25, + transition: 'padding-left 195ms cubic-bezier(0.4, 0, 0.6, 1) 0ms' + }, + sidebarIsClosed: { + paddingLeft: 0, + transition: 'padding-left 195ms cubic-bezier(0.4, 0, 0.6, 1) 0ms' + } +})) + +const SubMenu = ({ + handleToggle, + sidebarIsOpen, + isOpen, + name, + icon, + children, + dense +}) => { + const translate = useTranslate() + const classes = useStyles() + + const header = ( + + + {isOpen ? : icon} + + + {translate(name)} + + + ) + + return ( + + {sidebarIsOpen || isOpen ? ( + header + ) : ( + + {header} + + )} + + + {children} + + + + + ) +} + +export default SubMenu diff --git a/ui/src/layout/index.js b/ui/src/layout/index.js index 5e18ae6cc..ebfb0760a 100644 --- a/ui/src/layout/index.js +++ b/ui/src/layout/index.js @@ -1,3 +1,4 @@ import Login from './Login' +import Layout from './Layout' -export { Login } +export { Layout, Login }