diff --git a/src/js/locale/en.yaml b/src/js/locale/en.yaml
index 66012d4b..e5ef04d4 100755
--- a/src/js/locale/en.yaml
+++ b/src/js/locale/en.yaml
@@ -175,6 +175,7 @@ sidebar:
context_menu:
add_to_playlist:
title: Add to playlist
+ new_playlist: Create playlist
no_playlists: No writable playlists
play_next: Play next
play_top_tracks: Play top tracks
@@ -511,6 +512,7 @@ modal:
edit_playlist:
title: Edit playlist
title_create: Create playlist
+ subtitle: 'And add %{count} track%{plural}'
name_required: Name is required
name: Name
description: Description
diff --git a/src/js/services/core/actions.js b/src/js/services/core/actions.js
index 09796904..82dc133f 100755
--- a/src/js/services/core/actions.js
+++ b/src/js/services/core/actions.js
@@ -403,16 +403,12 @@ export function savePlaylist(uri, name, description = '', is_public = false, is_
}
}
-export function createPlaylist(scheme, name, description = '', is_public = false, is_collaborative = false) {
- switch (scheme) {
+export function createPlaylist(playlist) {
+ switch (playlist.scheme) {
case 'spotify':
- if (description === '') {
- description = null;
- }
- return spotifyActions.createPlaylist(name, description, is_public, is_collaborative);
-
+ return spotifyActions.createPlaylist(playlist);
default:
- return mopidyActions.createPlaylist(name, scheme);
+ return mopidyActions.createPlaylist(playlist);
}
}
diff --git a/src/js/services/mopidy/actions.js b/src/js/services/mopidy/actions.js
index 5889b476..58ee6de7 100755
--- a/src/js/services/mopidy/actions.js
+++ b/src/js/services/mopidy/actions.js
@@ -422,11 +422,10 @@ export function getImages(uris) {
};
}
-export function createPlaylist(name, scheme) {
+export function createPlaylist(playlist) {
return {
type: 'MOPIDY_CREATE_PLAYLIST',
- name,
- scheme,
+ playlist,
};
}
diff --git a/src/js/services/mopidy/middleware.js b/src/js/services/mopidy/middleware.js
index 1dde1d6b..b21b657a 100755
--- a/src/js/services/mopidy/middleware.js
+++ b/src/js/services/mopidy/middleware.js
@@ -1346,7 +1346,11 @@ const MopidyMiddleware = (function () {
break;
case 'MOPIDY_CREATE_PLAYLIST':
- request(store, 'playlists.create', { name: action.name, uri_scheme: action.scheme })
+ const data = {
+ name: action.playlist.name,
+ uri_scheme: action.playlist.scheme,
+ };
+ request(store, 'playlists.create', data)
.then((response) => {
const playlist = formatPlaylist({
...response,
@@ -1358,6 +1362,12 @@ const MopidyMiddleware = (function () {
store.dispatch(uiActions.createNotification({
content: i18n('actions.created', { name: i18n('playlist.title') }),
}));
+ if (action.playlist.tracks_uris) {
+ store.dispatch(coreActions.addTracksToPlaylist(
+ playlist.uri,
+ action.playlist.tracks_uris,
+ ));
+ }
store.dispatch(coreActions.addToLibrary(
getProvider('playlists', 'm3u:')?.uri,
playlist,
diff --git a/src/js/services/spotify/actions.js b/src/js/services/spotify/actions.js
index 777f0cc5..25879099 100755
--- a/src/js/services/spotify/actions.js
+++ b/src/js/services/spotify/actions.js
@@ -22,7 +22,8 @@ import {
injectSortId,
} from '../../util/format';
import URILink from '../../components/URILink';
-import { getItem, providers, getProvider } from '../../util/selectors';
+import { i18n } from '../../locale';
+import { getItem, getProvider } from '../../util/selectors';
const coreActions = require('../core/actions');
const uiActions = require('../ui/actions');
@@ -1140,13 +1141,13 @@ export function getAlbum(uri, { full, forceRefetch } = {}) {
* ======================================================================================
* */
-export function createPlaylist(name, description, is_public, is_collaborative) {
+export function createPlaylist(playlist) {
return (dispatch, getState) => {
const data = {
- name,
- description,
- public: is_public,
- collaborative: is_collaborative,
+ name: playlist.name,
+ description: playlist.description || '',
+ public: playlist.public,
+ collaborative: playlist.collaborative,
};
const {
spotify: {
@@ -1176,7 +1177,12 @@ export function createPlaylist(name, description, is_public, is_collaborative) {
response,
));
- dispatch(uiActions.createNotification({ content: 'Created playlist' }));
+ dispatch(uiActions.createNotification({
+ content: i18n('actions.created', { name: i18n('playlist.title') }),
+ }));
+ if (playlist.tracks_uris) {
+ dispatch(coreActions.addTracksToPlaylist(response.uri, playlist.tracks_uris));
+ }
},
(error) => {
dispatch(coreActions.handleException(
diff --git a/src/js/views/modals/CreatePlaylist.js b/src/js/views/modals/CreatePlaylist.js
index 7c537b3b..bc1aa92d 100755
--- a/src/js/views/modals/CreatePlaylist.js
+++ b/src/js/views/modals/CreatePlaylist.js
@@ -1,49 +1,49 @@
-import React from 'react';
-import { connect } from 'react-redux';
-import { bindActionCreators } from 'redux';
+import React, { useState, useEffect } from 'react';
+import { useSelector, useDispatch } from 'react-redux';
+import { useParams } from 'react-router-dom';
import Modal from './Modal';
import * as coreActions from '../../services/core/actions';
import * as uiActions from '../../services/ui/actions';
import { i18n, I18n } from '../../locale';
+import { decodeUri } from '../../util/format';
+import TextField from '../../components/Fields/TextField';
import Button from '../../components/Button';
-class CreatePlaylist extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- name: '',
- description: '',
- scheme: 'm3u',
- is_public: true,
- is_collaborative: false,
- };
- }
+const CreatePlaylist = () => {
+ const { uris } = useParams();
+ const tracks_uris = uris ? decodeUri(uris).split(',') : undefined;
+ const dispatch = useDispatch();
+ const [playlist, setPlaylist] = useState({
+ scheme: 'm3u',
+ name: '',
+ description: '',
+ collaborative: false,
+ public: false,
+ });
+ const spotifyAvailable = useSelector((state) => state.spotify.access_token);
+ useEffect(
+ () => {
+ dispatch(uiActions.setWindowTitle(i18n('modal.edit_playlist.title_create')));
+ },
+ [],
+ );
- componentDidMount() {
- this.props.uiActions.setWindowTitle(i18n('modal.edit_playlist.title_create'));
- }
-
- createPlaylist(e) {
+ const onChange = (updates) => setPlaylist({ ...playlist, ...updates });
+ const onSubmit = (e) => {
e.preventDefault();
- if (!this.state.name || this.state.name == '') {
- this.setState({ error: i18n('modal.edit_playlist.name_required') });
+ if (!playlist.name || playlist.name === '') {
return false;
}
- this.props.coreActions.createPlaylist(
- this.state.scheme,
- this.state.name,
- this.state.description,
- this.state.is_public,
- this.state.is_collaborative,
+ dispatch(
+ coreActions.createPlaylist({ ...playlist, tracks_uris }),
);
window.history.back();
-
return false;
- }
+ };
- renderFields() {
- switch (this.state.scheme) {
+ const fields = () => {
+ switch (playlist.scheme) {
case 'spotify':
return (
@@ -52,10 +52,9 @@ class CreatePlaylist extends React.Component {
- this.setState({ name: e.target.value })}
- value={this.state.name}
+ onChange({ name: value })}
+ value={playlist.name}
/>
@@ -65,11 +64,9 @@ class CreatePlaylist extends React.Component {