Add duplicate song warning. Fix #554
* duplicate_song_warning added * dialog_for_multiple_songs * skip button updated * duplicate_song_skip import removed * duplicate_song msg updated * handleSkip and checkDuplicateSong func modified * Update AddToPlaylistDialog.js * prettier applied * go.sum file added * duplicated songs bug fixed
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
export const ADD_TO_PLAYLIST_OPEN = 'ADD_TO_PLAYLIST_OPEN'
|
export const ADD_TO_PLAYLIST_OPEN = 'ADD_TO_PLAYLIST_OPEN'
|
||||||
export const ADD_TO_PLAYLIST_CLOSE = 'ADD_TO_PLAYLIST_CLOSE'
|
export const ADD_TO_PLAYLIST_CLOSE = 'ADD_TO_PLAYLIST_CLOSE'
|
||||||
|
export const DUPLICATE_SONG_WARNING_OPEN = 'DUPLICATE_SONG_WARNING_OPEN'
|
||||||
|
export const DUPLICATE_SONG_WARNING_CLOSE = 'DUPLICATE_SONG_WARNING_CLOSE'
|
||||||
export const openAddToPlaylist = ({ selectedIds, onSuccess }) => ({
|
export const openAddToPlaylist = ({ selectedIds, onSuccess }) => ({
|
||||||
type: ADD_TO_PLAYLIST_OPEN,
|
type: ADD_TO_PLAYLIST_OPEN,
|
||||||
selectedIds,
|
selectedIds,
|
||||||
@@ -10,3 +11,12 @@ export const openAddToPlaylist = ({ selectedIds, onSuccess }) => ({
|
|||||||
export const closeAddToPlaylist = () => ({
|
export const closeAddToPlaylist = () => ({
|
||||||
type: ADD_TO_PLAYLIST_CLOSE,
|
type: ADD_TO_PLAYLIST_CLOSE,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const openDuplicateSongWarning = (duplicateIds) => ({
|
||||||
|
type: DUPLICATE_SONG_WARNING_OPEN,
|
||||||
|
duplicateIds,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const closeDuplicateSongDialog = () => ({
|
||||||
|
type: DUPLICATE_SONG_WARNING_CLOSE,
|
||||||
|
})
|
||||||
|
|||||||
@@ -13,17 +13,29 @@ import {
|
|||||||
DialogContent,
|
DialogContent,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from '@material-ui/core'
|
} from '@material-ui/core'
|
||||||
import { closeAddToPlaylist } from '../actions'
|
import {
|
||||||
|
closeAddToPlaylist,
|
||||||
|
closeDuplicateSongDialog,
|
||||||
|
openDuplicateSongWarning,
|
||||||
|
} from '../actions'
|
||||||
import { SelectPlaylistInput } from './SelectPlaylistInput'
|
import { SelectPlaylistInput } from './SelectPlaylistInput'
|
||||||
|
import { httpClient } from '../dataProvider'
|
||||||
|
import { REST_URL } from '../consts'
|
||||||
|
import DuplicateSongDialog from './DuplicateSongDialog'
|
||||||
|
|
||||||
export const AddToPlaylistDialog = () => {
|
export const AddToPlaylistDialog = () => {
|
||||||
const { open, selectedIds, onSuccess } = useSelector(
|
const {
|
||||||
(state) => state.addToPlaylistDialog
|
open,
|
||||||
)
|
selectedIds,
|
||||||
|
onSuccess,
|
||||||
|
duplicateSong,
|
||||||
|
duplicateIds,
|
||||||
|
} = useSelector((state) => state.addToPlaylistDialog)
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
const translate = useTranslate()
|
const translate = useTranslate()
|
||||||
const notify = useNotify()
|
const notify = useNotify()
|
||||||
const [value, setValue] = useState({})
|
const [value, setValue] = useState({})
|
||||||
|
const [check, setCheck] = useState(false)
|
||||||
const dataProvider = useDataProvider()
|
const dataProvider = useDataProvider()
|
||||||
const [createAndAddToPlaylist] = useCreate(
|
const [createAndAddToPlaylist] = useCreate(
|
||||||
'playlist',
|
'playlist',
|
||||||
@@ -37,14 +49,15 @@ export const AddToPlaylistDialog = () => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const addToPlaylist = (playlistId) => {
|
const addToPlaylist = (playlistId, distinctIds) => {
|
||||||
|
const trackIds = Array.isArray(distinctIds) ? distinctIds : selectedIds
|
||||||
dataProvider
|
dataProvider
|
||||||
.create('playlistTrack', {
|
.create('playlistTrack', {
|
||||||
data: { ids: selectedIds },
|
data: { ids: trackIds },
|
||||||
filter: { playlist_id: playlistId },
|
filter: { playlist_id: playlistId },
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const len = selectedIds.length
|
const len = trackIds.length
|
||||||
notify('message.songsAddedToPlaylist', 'info', { smart_count: len })
|
notify('message.songsAddedToPlaylist', 'info', { smart_count: len })
|
||||||
onSuccess && onSuccess(value, len)
|
onSuccess && onSuccess(value, len)
|
||||||
})
|
})
|
||||||
@@ -53,26 +66,76 @@ export const AddToPlaylistDialog = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const checkDuplicateSong = (playlistId) => {
|
||||||
|
httpClient(`${REST_URL}/playlist/${playlistId}`)
|
||||||
|
.then((res) => {
|
||||||
|
const { tracks } = JSON.parse(res.body)
|
||||||
|
if (tracks) {
|
||||||
|
const dupSng = tracks.filter((song) =>
|
||||||
|
selectedIds.some((id) => id === song.id)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (dupSng.length) {
|
||||||
|
const dupIds = dupSng.map((song) => song.id)
|
||||||
|
return dispatch(openDuplicateSongWarning(dupIds))
|
||||||
|
}
|
||||||
|
return setCheck(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
setCheck(true)
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error)
|
||||||
|
notify('ra.page.error', 'warning')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const handleSubmit = (e) => {
|
const handleSubmit = (e) => {
|
||||||
if (value.id) {
|
if (value.id) {
|
||||||
addToPlaylist(value.id)
|
addToPlaylist(value.id)
|
||||||
} else {
|
} else {
|
||||||
createAndAddToPlaylist()
|
createAndAddToPlaylist()
|
||||||
}
|
}
|
||||||
|
setCheck(false)
|
||||||
dispatch(closeAddToPlaylist())
|
dispatch(closeAddToPlaylist())
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleClickClose = (e) => {
|
const handleClickClose = (e) => {
|
||||||
|
setCheck(false)
|
||||||
dispatch(closeAddToPlaylist())
|
dispatch(closeAddToPlaylist())
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleChange = (pls) => {
|
const handleChange = (pls) => {
|
||||||
|
if (pls.id) {
|
||||||
|
checkDuplicateSong(pls.id)
|
||||||
|
} else {
|
||||||
|
setCheck(true)
|
||||||
|
}
|
||||||
setValue(pls)
|
setValue(pls)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleDuplicateClose = () => {
|
||||||
|
dispatch(closeDuplicateSongDialog())
|
||||||
|
dispatch(closeAddToPlaylist())
|
||||||
|
}
|
||||||
|
const handleDuplicateSubmit = () => {
|
||||||
|
addToPlaylist(value.id)
|
||||||
|
dispatch(closeDuplicateSongDialog())
|
||||||
|
dispatch(closeAddToPlaylist())
|
||||||
|
}
|
||||||
|
const handleSkip = () => {
|
||||||
|
const distinctSongs = selectedIds.filter(
|
||||||
|
(id) => duplicateIds.indexOf(id) < 0
|
||||||
|
)
|
||||||
|
addToPlaylist(value.id, distinctSongs)
|
||||||
|
dispatch(closeDuplicateSongDialog())
|
||||||
|
dispatch(closeAddToPlaylist())
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<Dialog
|
<Dialog
|
||||||
open={open}
|
open={open}
|
||||||
onClose={handleClickClose}
|
onClose={handleClickClose}
|
||||||
@@ -91,10 +154,17 @@ export const AddToPlaylistDialog = () => {
|
|||||||
<Button onClick={handleClickClose} color="primary">
|
<Button onClick={handleClickClose} color="primary">
|
||||||
{translate('ra.action.cancel')}
|
{translate('ra.action.cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={handleSubmit} color="primary" disabled={!value.name}>
|
<Button onClick={handleSubmit} color="primary" disabled={!check}>
|
||||||
{translate('ra.action.add')}
|
{translate('ra.action.add')}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
<DuplicateSongDialog
|
||||||
|
open={duplicateSong}
|
||||||
|
handleClickClose={handleDuplicateClose}
|
||||||
|
handleSubmit={handleDuplicateSubmit}
|
||||||
|
handleSkip={handleSkip}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
DialogTitle,
|
||||||
|
} from '@material-ui/core'
|
||||||
|
|
||||||
|
import { useTranslate } from 'react-admin'
|
||||||
|
|
||||||
|
const DuplicateSongDialog = ({
|
||||||
|
open,
|
||||||
|
handleClickClose,
|
||||||
|
handleSubmit,
|
||||||
|
handleSkip,
|
||||||
|
}) => {
|
||||||
|
const translate = useTranslate()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
open={open}
|
||||||
|
onClose={handleClickClose}
|
||||||
|
onBackdropClick={handleClickClose}
|
||||||
|
aria-labelledby="form-dialog-duplicate-song"
|
||||||
|
>
|
||||||
|
<DialogTitle id="form-dialog-duplicate-song">
|
||||||
|
{translate('resources.playlist.message.duplicate_song')}
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
{translate('resources.playlist.message.song_exist')}
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={handleClickClose} color="primary">
|
||||||
|
{translate('ra.action.cancel')}
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleSkip} color="primary">
|
||||||
|
{translate('ra.action.skip')}
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleSubmit} color="primary">
|
||||||
|
{translate('ra.action.add')}
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DuplicateSongDialog
|
||||||
+6
-1
@@ -123,6 +123,10 @@
|
|||||||
"selectPlaylist": "Select a playlist:",
|
"selectPlaylist": "Select a playlist:",
|
||||||
"addNewPlaylist": "Create \"%{name}\"",
|
"addNewPlaylist": "Create \"%{name}\"",
|
||||||
"export": "Export"
|
"export": "Export"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"duplicate_song": "Add duplicated songs",
|
||||||
|
"song_exist": "There are duplicates being added to the playlist. Would you like to add the duplicates or skip them?"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -179,7 +183,8 @@
|
|||||||
"close": "Close",
|
"close": "Close",
|
||||||
"open_menu": "Open menu",
|
"open_menu": "Open menu",
|
||||||
"close_menu": "Close menu",
|
"close_menu": "Close menu",
|
||||||
"unselect": "Unselect"
|
"unselect": "Unselect",
|
||||||
|
"skip": "Skip"
|
||||||
},
|
},
|
||||||
"boolean": {
|
"boolean": {
|
||||||
"true": "Yes",
|
"true": "Yes",
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
import { ADD_TO_PLAYLIST_CLOSE, ADD_TO_PLAYLIST_OPEN } from '../actions'
|
import {
|
||||||
|
ADD_TO_PLAYLIST_CLOSE,
|
||||||
|
ADD_TO_PLAYLIST_OPEN,
|
||||||
|
DUPLICATE_SONG_WARNING_OPEN,
|
||||||
|
DUPLICATE_SONG_WARNING_CLOSE,
|
||||||
|
} from '../actions'
|
||||||
|
|
||||||
export const addToPlaylistDialogReducer = (
|
export const addToPlaylistDialogReducer = (
|
||||||
previousState = {
|
previousState = {
|
||||||
open: false,
|
open: false,
|
||||||
|
duplicateSong: false,
|
||||||
},
|
},
|
||||||
payload
|
payload
|
||||||
) => {
|
) => {
|
||||||
@@ -17,6 +23,14 @@ export const addToPlaylistDialogReducer = (
|
|||||||
}
|
}
|
||||||
case ADD_TO_PLAYLIST_CLOSE:
|
case ADD_TO_PLAYLIST_CLOSE:
|
||||||
return { ...previousState, open: false, onSuccess: undefined }
|
return { ...previousState, open: false, onSuccess: undefined }
|
||||||
|
case DUPLICATE_SONG_WARNING_OPEN:
|
||||||
|
return {
|
||||||
|
...previousState,
|
||||||
|
duplicateSong: true,
|
||||||
|
duplicateIds: payload.duplicateIds,
|
||||||
|
}
|
||||||
|
case DUPLICATE_SONG_WARNING_CLOSE:
|
||||||
|
return { ...previousState, duplicateSong: false }
|
||||||
default:
|
default:
|
||||||
return previousState
|
return previousState
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user