From 23bd5e11311d2807b8ce16c9103685a7644fdb50 Mon Sep 17 00:00:00 2001 From: Deluan Date: Sun, 24 May 2020 00:03:42 -0400 Subject: [PATCH] First version of dialog --- ui/src/App.js | 2 + ui/src/common/AddToPlaylistMenu.js | 68 +++++++++------- ui/src/dialogs/NewPlaylist.js | 120 +++++++++++++++++++++++++++++ ui/src/dialogs/dialogState.js | 36 +++++++++ ui/src/i18n/en.json | 3 +- 5 files changed, 201 insertions(+), 28 deletions(-) create mode 100644 ui/src/dialogs/NewPlaylist.js create mode 100644 ui/src/dialogs/dialogState.js diff --git a/ui/src/App.js b/ui/src/App.js index 3677da3b024..4b4de694dac 100644 --- a/ui/src/App.js +++ b/ui/src/App.js @@ -17,6 +17,7 @@ import { albumViewReducer } from './album/albumState' import config from './config' import customRoutes from './routes' import themeReducer from './personal/themeReducer' +import { newPlaylistDialogReducer } from './dialogs/dialogState' import createAdminStore from './store/createAdminStore' import { i18nProvider } from './i18n' @@ -32,6 +33,7 @@ const App = () => ( queue: playQueueReducer, albumView: albumViewReducer, theme: themeReducer, + newPlaylistDialog: newPlaylistDialogReducer, }, })} > diff --git a/ui/src/common/AddToPlaylistMenu.js b/ui/src/common/AddToPlaylistMenu.js index 404e2a1344b..4d993448b8b 100644 --- a/ui/src/common/AddToPlaylistMenu.js +++ b/ui/src/common/AddToPlaylistMenu.js @@ -1,12 +1,16 @@ import React from 'react' +import { useDispatch } from 'react-redux' +import PropTypes from 'prop-types' import { useDataProvider, useGetList, useNotify, useTranslate, } from 'react-admin' -import { MenuItem } from '@material-ui/core' -import PropTypes from 'prop-types' +import { MenuItem, Divider } from '@material-ui/core' +import NewPlaylistIcon from '@material-ui/icons/Add' +import { openNewPlaylist } from '../dialogs/dialogState' +import NewPlaylistDialog from '../dialogs/NewPlaylist' export const addTracksToPlaylist = (dataProvider, selectedIds, playlistId) => dataProvider @@ -29,6 +33,7 @@ export const addAlbumToPlaylist = (dataProvider, albumId, playlistId) => const AddToPlaylistMenu = React.forwardRef( ({ selectedIds, albumId, onClose, onItemAdded }, ref) => { const notify = useNotify() + const dispatch = useDispatch() const translate = useTranslate() const dataProvider = useDataProvider() const { ids, data, loaded } = useGetList( @@ -42,48 +47,55 @@ const AddToPlaylistMenu = React.forwardRef( return Loading... } - // TODO: This is temporary, while we don't have the "New Playlist" option in the menu - if (ids.length === 0) { - return ( - { - e.stopPropagation() - onClose && onClose(e) - }} - > - {translate('message.noPlaylistsAvailable')} - - ) + const addToPlaylist = (playlistId) => { + const add = albumId + ? addAlbumToPlaylist(dataProvider, albumId, playlistId) + : addTracksToPlaylist(dataProvider, selectedIds, playlistId) + + add + .then((len) => { + notify('message.songsAddedToPlaylist', 'info', { smart_count: len }) + onItemAdded(playlistId) + }) + .catch(() => { + notify('ra.page.error', 'warning') + }) } const handleItemClick = (e) => { e.preventDefault() const playlistId = e.target.getAttribute('value') if (playlistId !== '') { - const add = albumId - ? addAlbumToPlaylist(dataProvider, albumId, playlistId) - : addTracksToPlaylist(dataProvider, selectedIds, playlistId) - - add - .then((len) => { - notify('message.songsAddedToPlaylist', 'info', { smart_count: len }) - onItemAdded && onItemAdded(playlistId, selectedIds) - }) - .catch(() => { - notify('ra.page.error', 'warning') - }) + addToPlaylist(playlistId) } e.stopPropagation() - onClose && onClose(e) + onClose(e) + } + + const handleOpenDialog = (e) => { + e.preventDefault() + dispatch(openNewPlaylist(albumId, selectedIds)) + e.stopPropagation() + onClose(e) } return ( <> + {ids.map((id) => ( {data[id].name} ))} + + {}  + {translate('resources.playlist.actions.newPlaylist')} + + ) } @@ -98,6 +110,8 @@ AddToPlaylistMenu.propTypes = { AddToPlaylistMenu.defaultProps = { selectedIds: [], + onClose: () => {}, + onItemAdded: () => {}, } export default AddToPlaylistMenu diff --git a/ui/src/dialogs/NewPlaylist.js b/ui/src/dialogs/NewPlaylist.js new file mode 100644 index 00000000000..891c4bd0806 --- /dev/null +++ b/ui/src/dialogs/NewPlaylist.js @@ -0,0 +1,120 @@ +import React from 'react' +import { useDispatch, useSelector } from 'react-redux' +import { + useCreate, + useDataProvider, + useTranslate, + useNotify, +} from 'react-admin' +import { + Button, + TextField, + Dialog, + DialogActions, + DialogContent, + DialogTitle, +} from '@material-ui/core' +import PropTypes from 'prop-types' +import { closeNewPlaylist } from './dialogState' +import { + addAlbumToPlaylist, + addTracksToPlaylist, +} from '../common/AddToPlaylistMenu' + +const NewPlaylistDialog = ({ onCancel, onSubmit }) => { + const { open, albumId, selectedIds } = useSelector( + (state) => state.newPlaylistDialog + ) + const dispatch = useDispatch() + const translate = useTranslate() + const notify = useNotify() + const [value, setValue] = React.useState('') + const dataProvider = useDataProvider() + const [create] = useCreate( + 'playlist', + { name: value }, + { + onSuccess: ({ data }) => { + addToPlaylist(data.id) + }, + onFailure: (error) => notify(`Error: ${error.message}`, 'warning'), + } + ) + + const addToPlaylist = (playlistId) => { + const add = albumId + ? addAlbumToPlaylist(dataProvider, albumId, playlistId) + : addTracksToPlaylist(dataProvider, selectedIds, playlistId) + + add + .then((len) => { + notify('message.songsAddedToPlaylist', 'info', { smart_count: len }) + onSubmit(value) + }) + .catch(() => { + notify('ra.page.error', 'warning') + }) + } + + const handleSubmit = (e) => { + create() + dispatch(closeNewPlaylist()) + e.stopPropagation() + } + + const handleChange = (e) => { + setValue(e.target.value) + } + + const handleClickClose = (e) => { + onCancel(e) + dispatch(closeNewPlaylist()) + e.stopPropagation() + } + + return ( +
+ + + {translate('resources.playlist.actions.newPlaylist')} + + + + + + + + + +
+ ) +} + +NewPlaylistDialog.propTypes = { + onCancel: PropTypes.func, + onSubmit: PropTypes.func, +} + +NewPlaylistDialog.defaultProps = { + onCancel: () => {}, + onSubmit: () => {}, +} + +export default NewPlaylistDialog diff --git a/ui/src/dialogs/dialogState.js b/ui/src/dialogs/dialogState.js new file mode 100644 index 00000000000..4d77a930b1e --- /dev/null +++ b/ui/src/dialogs/dialogState.js @@ -0,0 +1,36 @@ +const NEW_PLAYLIST_OPEN = 'NEW_PLAYLIST_OPEN' +const NEW_PLAYLIST_CLOSE = 'NEW_PLAYLIST_CLOSE' + +const openNewPlaylist = (albumId, selectedIds) => ({ + type: NEW_PLAYLIST_OPEN, + albumId, + selectedIds, +}) + +const closeNewPlaylist = () => ({ + type: NEW_PLAYLIST_CLOSE, +}) + +const newPlaylistDialogReducer = ( + previousState = { + open: false, + }, + payload +) => { + const { type } = payload + switch (type) { + case NEW_PLAYLIST_OPEN: + return { + ...previousState, + open: true, + albumId: payload.albumId, + selectedIds: payload.selectedIds, + } + case NEW_PLAYLIST_CLOSE: + return { ...previousState, open: false } + default: + return previousState + } +} + +export { openNewPlaylist, closeNewPlaylist, newPlaylistDialogReducer } diff --git a/ui/src/i18n/en.json b/ui/src/i18n/en.json index fc1bee3288e..274390ca5e7 100644 --- a/ui/src/i18n/en.json +++ b/ui/src/i18n/en.json @@ -69,7 +69,8 @@ "createdAt": "Created at" }, "actions": { - "selectPlaylist": "Add songs to playlist:" + "selectPlaylist": "Add songs to playlist:", + "newPlaylist": "New playlist" } }, "user": {