build(ui): migrate from CRA/Jest to Vite/Vitest (#3311)

* feat: create vite project

* feat: it's alive!

* feat: `make dev` working!

* feat: replace custom serviceWorker with vite plugin

* test: replace Jest with Vitest

* fix: run prettier

* fix: skip eslint for now.

* chore: remove ui.old folder

* refactor: replace lodash.pick with simple destructuring

* fix: eslint errors (wip)

* fix: eslint errors (wip)

* fix: display-name eslint errors (wip)

* fix: no-console eslint errors (wip)

* fix: react-refresh/only-export-components eslint errors (wip)

* fix: react-refresh/only-export-components eslint errors (wip)

* fix: react-refresh/only-export-components eslint errors (wip)

* fix: react-refresh/only-export-components eslint errors (wip)

* fix: build

* fix: pwa manifest

* refactor: pwa manifest

* refactor: simplify PORT configuration

* refactor: rename simple JS files

* test: cover playlistUtils

* fix: react-image-lightbox

* feat(ui): add sourcemaps to help debug issues
This commit is contained in:
Deluan Quintão
2024-09-28 11:54:36 -04:00
committed by GitHub
parent dd48a23f92
commit fcdd30ba8f
212 changed files with 6231 additions and 31060 deletions
+144
View File
@@ -0,0 +1,144 @@
import React, { useState } from 'react'
import { useSelector } from 'react-redux'
import { Divider, makeStyles } from '@material-ui/core'
import clsx from 'clsx'
import { useTranslate, MenuItemLink, getResources } from 'react-admin'
import ViewListIcon from '@material-ui/icons/ViewList'
import AlbumIcon from '@material-ui/icons/Album'
import SubMenu from './SubMenu'
import inflection from 'inflection'
import albumLists from '../album/albumLists'
import PlaylistsSubMenu from './PlaylistsSubMenu'
import config from '../config'
const useStyles = makeStyles((theme) => ({
root: {
marginTop: theme.spacing(1),
marginBottom: theme.spacing(1),
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
paddingBottom: (props) => (props.addPadding ? '80px' : '20px'),
},
open: {
width: 240,
},
closed: {
width: 55,
},
active: {
color: theme.palette.text.primary,
fontWeight: 'bold',
},
}))
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 = ({ dense = false }) => {
const open = useSelector((state) => state.admin.ui.sidebarOpen)
const translate = useTranslate()
const queue = useSelector((state) => state.player?.queue)
const classes = useStyles({ addPadding: queue.length > 0 })
const resources = useSelector(getResources)
// TODO State is not persisted in mobile when you close the sidebar menu. Move to redux?
const [state, setState] = useState({
menuAlbumList: true,
menuPlaylists: true,
menuSharedPlaylists: true,
})
const handleToggle = (menu) => {
setState((state) => ({ ...state, [menu]: !state[menu] }))
}
const renderResourceMenuItemLink = (resource) => (
<MenuItemLink
key={resource.name}
to={`/${resource.name}`}
activeClassName={classes.active}
primaryText={translatedResourceName(resource, translate)}
leftIcon={resource.icon || <ViewListIcon />}
sidebarIsOpen={open}
dense={dense}
/>
)
const renderAlbumMenuItemLink = (type, al) => {
const resource = resources.find((r) => r.name === 'album')
if (!resource) {
return null
}
const albumListAddress = `/album/${type}`
const name = translate(`resources.album.lists.${type || 'default'}`, {
_: translatedResourceName(resource, translate),
})
return (
<MenuItemLink
key={albumListAddress}
to={albumListAddress}
activeClassName={classes.active}
primaryText={name}
leftIcon={al.icon || <ViewListIcon />}
sidebarIsOpen={open}
dense={dense}
exact
/>
)
}
const subItems = (subMenu) => (resource) =>
resource.hasList && resource.options && resource.options.subMenu === subMenu
return (
<div
className={clsx(classes.root, {
[classes.open]: open,
[classes.closed]: !open,
})}
>
<SubMenu
handleToggle={() => handleToggle('menuAlbumList')}
isOpen={state.menuAlbumList}
sidebarIsOpen={open}
name="menu.albumList"
icon={<AlbumIcon />}
dense={dense}
>
{Object.keys(albumLists).map((type) =>
renderAlbumMenuItemLink(type, albumLists[type]),
)}
</SubMenu>
{resources.filter(subItems(undefined)).map(renderResourceMenuItemLink)}
{config.devSidebarPlaylists && open ? (
<>
<Divider />
<PlaylistsSubMenu
state={state}
setState={setState}
sidebarIsOpen={open}
dense={dense}
/>
</>
) : (
resources.filter(subItems('playlist')).map(renderResourceMenuItemLink)
)}
</div>
)
}
export default Menu