check for spotify auth on run, updated helper text
This commit is contained in:
parent
f1dcf6fdd6
commit
61ac85d41f
@ -9,7 +9,39 @@ class Index extends Component{
|
|||||||
}
|
}
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
return <h1 className="center-text text-no-select">welcome to playlist manager!</h1>;
|
return (
|
||||||
|
<table className="app-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<h1 className="center-text text-no-select">playlist manager</h1>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td className="center-text text-no-select ui-text" style={{fontSize: "20px"}}>
|
||||||
|
construct playlists from selections of other playlists
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="center-text text-no-select ui-text">
|
||||||
|
group sub-genre playlists
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="center-text text-no-select ui-text">
|
||||||
|
optionally append recommendations generated by spotify
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="center-text text-no-select ui-text">
|
||||||
|
<br></br>playlists are run multiple times a day
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,53 +10,83 @@ class NewPlaylist extends Component {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
name: '',
|
name: '',
|
||||||
type: 'normal'
|
type: 'default',
|
||||||
|
description: ''
|
||||||
}
|
}
|
||||||
this.handleInputChange = this.handleInputChange.bind(this);
|
this.handleInputChange = this.handleInputChange.bind(this);
|
||||||
this.handleSubmit = this.handleSubmit.bind(this);
|
this.handleSubmit = this.handleSubmit.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount(){
|
||||||
|
this.setDescription('default');
|
||||||
|
}
|
||||||
|
|
||||||
|
setDescription(value){
|
||||||
|
switch(value){
|
||||||
|
case 'default':
|
||||||
|
this.setState({
|
||||||
|
description: 'merge playlists as-is with deduplication by spotify id'
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
case 'recents':
|
||||||
|
this.setState({
|
||||||
|
description: "select songs from playlists which have been added since a variable number of days"
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleInputChange(event){
|
handleInputChange(event){
|
||||||
this.setState({
|
this.setState({
|
||||||
[event.target.name]: event.target.value
|
[event.target.name]: event.target.value
|
||||||
});
|
});
|
||||||
|
this.setDescription(event.target.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSubmit(event){
|
handleSubmit(event){
|
||||||
axios.get('/api/playlists')
|
var name = this.state.name;
|
||||||
.then((response) => {
|
this.setState({
|
||||||
|
name: ''
|
||||||
var names = response.data.playlists.map(entry => entry.name)
|
|
||||||
|
|
||||||
var sameName = names.includes(this.state.name);
|
|
||||||
if(sameName == false){
|
|
||||||
axios.put('/api/playlist', {
|
|
||||||
name: this.state.name,
|
|
||||||
parts: [],
|
|
||||||
playlist_references: [],
|
|
||||||
shuffle: false,
|
|
||||||
type: this.state.type,
|
|
||||||
}).then((response) => {
|
|
||||||
showMessage(`${this.state.name} created`);
|
|
||||||
}).catch((error) => {
|
|
||||||
showMessage(`error creating playlist (${error.response.status})`);
|
|
||||||
});
|
|
||||||
}else{
|
|
||||||
showMessage('named playlist already exists');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
showMessage(`error getting playlists (${error.response.status})`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(name.length != 0){
|
||||||
|
axios.get('/api/playlists')
|
||||||
|
.then((response) => {
|
||||||
|
|
||||||
|
var names = response.data.playlists.map(entry => entry.name)
|
||||||
|
|
||||||
|
var sameName = names.includes(this.state.name);
|
||||||
|
if(sameName == false){
|
||||||
|
axios.put('/api/playlist', {
|
||||||
|
name: name,
|
||||||
|
parts: [],
|
||||||
|
playlist_references: [],
|
||||||
|
shuffle: false,
|
||||||
|
type: this.state.type,
|
||||||
|
}).then((response) => {
|
||||||
|
showMessage(`${this.state.name} created`);
|
||||||
|
}).catch((error) => {
|
||||||
|
showMessage(`error creating playlist (${error.response.status})`);
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
showMessage('named playlist already exists');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
showMessage(`error getting playlists (${error.response.status})`);
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
showMessage('enter name');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
return (
|
return (
|
||||||
<table className="app-table">
|
<table className="app-table max-width">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th colSpan="2">
|
<th colSpan="2">
|
||||||
<h1 className="ui-text center-text">new playlist</h1>
|
<h1 className="ui-text center-text text-no-select">new playlist</h1>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -64,7 +94,7 @@ class NewPlaylist extends Component {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<select className="full-width" name="type" onChange={this.handleInputChange}>
|
<select className="full-width" name="type" onChange={this.handleInputChange}>
|
||||||
<option value="default">normal</option>
|
<option value="default">default</option>
|
||||||
<option value="recents">recents</option>
|
<option value="recents">recents</option>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
@ -83,6 +113,11 @@ class NewPlaylist extends Component {
|
|||||||
<input type="submit" className="button full-width" onClick={this.handleSubmit} value="create" />
|
<input type="submit" className="button full-width" onClick={this.handleSubmit} value="create" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colSpan="2" className="ui-text text-no-select center-text">
|
||||||
|
<br></br>{this.state.description}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
);
|
);
|
||||||
|
@ -11,6 +11,7 @@ class PlaylistView extends Component{
|
|||||||
name: this.props.match.params.name,
|
name: this.props.match.params.name,
|
||||||
parts: [],
|
parts: [],
|
||||||
playlists: [],
|
playlists: [],
|
||||||
|
filteredPlaylists: [],
|
||||||
playlist_references: [],
|
playlist_references: [],
|
||||||
type: null,
|
type: null,
|
||||||
|
|
||||||
@ -50,8 +51,13 @@ class PlaylistView extends Component{
|
|||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var filteredPlaylists = playlists.data.playlists.filter((entry) => entry.name != this.state.name);
|
||||||
|
|
||||||
this.setState(info.data);
|
this.setState(info.data);
|
||||||
this.setState({playlists: playlists.data.playlists});
|
this.setState({
|
||||||
|
playlists: playlists.data.playlists,
|
||||||
|
newPlaylistReference: filteredPlaylists.length > 0 ? filteredPlaylists[0].name : ''
|
||||||
|
});
|
||||||
}))
|
}))
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
showMessage(`error getting playlist info (${error.response.status})`);
|
showMessage(`error getting playlist info (${error.response.status})`);
|
||||||
@ -67,6 +73,7 @@ class PlaylistView extends Component{
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleInputChange(event){
|
handleInputChange(event){
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
[event.target.name]: event.target.value
|
[event.target.name]: event.target.value
|
||||||
});
|
});
|
||||||
@ -123,59 +130,74 @@ class PlaylistView extends Component{
|
|||||||
|
|
||||||
handleAddPart(event){
|
handleAddPart(event){
|
||||||
|
|
||||||
var check = this.state.parts.filter((e) => {
|
if(this.state.newPlaylistName.length != 0){
|
||||||
return e == event.target.value;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(check.length == 0) {
|
var check = this.state.parts.includes(this.state.newPlaylistName);
|
||||||
var parts = this.state.parts.slice();
|
|
||||||
parts.push(this.state.newPlaylistName);
|
|
||||||
|
|
||||||
parts.sort(function(a, b){
|
if(check == false) {
|
||||||
if(a < b) { return -1; }
|
var parts = this.state.parts.slice();
|
||||||
if(a > b) { return 1; }
|
parts.push(this.state.newPlaylistName);
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.setState({
|
parts.sort(function(a, b){
|
||||||
parts: parts,
|
if(a < b) { return -1; }
|
||||||
newPlaylistName: ''
|
if(a > b) { return 1; }
|
||||||
});
|
return 0;
|
||||||
axios.post('/api/playlist', {
|
});
|
||||||
name: this.state.name,
|
|
||||||
parts: parts
|
this.setState({
|
||||||
}).catch((error) => {
|
parts: parts,
|
||||||
showMessage(`error adding part (${error.response.status})`);
|
newPlaylistName: ''
|
||||||
});
|
});
|
||||||
|
axios.post('/api/playlist', {
|
||||||
|
name: this.state.name,
|
||||||
|
parts: parts
|
||||||
|
}).catch((error) => {
|
||||||
|
showMessage(`error adding part (${error.response.status})`);
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
showMessage('playlist already added');
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
showMessage('enter playlist name');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAddReference(event){
|
handleAddReference(event){
|
||||||
|
|
||||||
var check = this.state.playlist_references.filter((e) => {
|
if(this.state.newPlaylistReference.length != 0){
|
||||||
return e == event.target.value;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(check.length == 0) {
|
var check = this.state.playlist_references.includes(this.state.newPlaylistReference);
|
||||||
var playlist_references = this.state.playlist_references.slice();
|
|
||||||
playlist_references.push(this.state.newPlaylistReference);
|
|
||||||
|
|
||||||
playlist_references.sort(function(a, b){
|
if(check == false) {
|
||||||
if(a < b) { return -1; }
|
var playlist_references = this.state.playlist_references.slice();
|
||||||
if(a > b) { return 1; }
|
playlist_references.push(this.state.newPlaylistReference);
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.setState({
|
playlist_references.sort(function(a, b){
|
||||||
playlist_references: playlist_references,
|
if(a < b) { return -1; }
|
||||||
newPlaylistReference: ''
|
if(a > b) { return 1; }
|
||||||
});
|
return 0;
|
||||||
axios.post('/api/playlist', {
|
});
|
||||||
name: this.state.name,
|
|
||||||
playlist_references: playlist_references
|
var filteredPlaylists = this.state.playlists.filter((entry) => entry.name != this.state.name);
|
||||||
}).catch((error) => {
|
|
||||||
showMessage(`error adding reference (${error.response.status})`);
|
this.setState({
|
||||||
});
|
playlist_references: playlist_references,
|
||||||
|
newPlaylistReference: filteredPlaylists.length > 0 ? filteredPlaylists[0].name : ''
|
||||||
|
});
|
||||||
|
axios.post('/api/playlist', {
|
||||||
|
name: this.state.name,
|
||||||
|
playlist_references: playlist_references
|
||||||
|
}).catch((error) => {
|
||||||
|
showMessage(`error adding reference (${error.response.status})`);
|
||||||
|
});
|
||||||
|
|
||||||
|
}else{
|
||||||
|
showMessage('playlist already added');
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
showMessage('no other playlists to add');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,11 +240,20 @@ class PlaylistView extends Component{
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleRun(event){
|
handleRun(event){
|
||||||
axios.get('/api/playlist/run', {params: {name: this.state.name}})
|
axios.get('/api/user')
|
||||||
.then((reponse) => {
|
.then((response) => {
|
||||||
showMessage(`${this.state.name} ran`);
|
if(response.data.spotify_linked == true){
|
||||||
})
|
axios.get('/api/playlist/run', {params: {name: this.state.name}})
|
||||||
.catch((error) => {
|
.then((reponse) => {
|
||||||
|
showMessage(`${this.state.name} ran`);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
showMessage(`error running ${this.state.name} (${error.response.status})`);
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
showMessage(`link spotify before running`);
|
||||||
|
}
|
||||||
|
}).catch((error) => {
|
||||||
showMessage(`error running ${this.state.name} (${error.response.status})`);
|
showMessage(`error running ${this.state.name} (${error.response.status})`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -239,6 +270,11 @@ class PlaylistView extends Component{
|
|||||||
{ this.state.playlist_references.length > 0 && <ListBlock name="managed" handler={this.handleRemoveRefRow} list={this.state.playlist_references}/> }
|
{ this.state.playlist_references.length > 0 && <ListBlock name="managed" handler={this.handleRemoveRefRow} list={this.state.playlist_references}/> }
|
||||||
{ this.state.parts.length > 0 && <ListBlock name="spotify" handler={this.handleRemoveRow} list={this.state.parts}/> }
|
{ this.state.parts.length > 0 && <ListBlock name="spotify" handler={this.handleRemoveRow} list={this.state.parts}/> }
|
||||||
<tbody>
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td colSpan="2" className="center-text ui-text text-no-select" style={{fontStyle: "italic"}}>
|
||||||
|
<br></br>spotify playlist can be the name of either your own created playlist or one you follow, names are case sensitive
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<input type="text"
|
<input type="text"
|
||||||
@ -246,7 +282,7 @@ class PlaylistView extends Component{
|
|||||||
className="full-width"
|
className="full-width"
|
||||||
value={this.state.newPlaylistName}
|
value={this.state.newPlaylistName}
|
||||||
onChange={this.handleInputChange}
|
onChange={this.handleInputChange}
|
||||||
placeholder="spotify playlist"></input>
|
placeholder="spotify playlist name"></input>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button className="button full-width" onClick={this.handleAddPart}>add</button>
|
<button className="button full-width" onClick={this.handleAddPart}>add</button>
|
||||||
@ -258,7 +294,9 @@ class PlaylistView extends Component{
|
|||||||
className="full-width"
|
className="full-width"
|
||||||
value={this.state.newPlaylistReference}
|
value={this.state.newPlaylistReference}
|
||||||
onChange={this.handleInputChange}>
|
onChange={this.handleInputChange}>
|
||||||
{ this.state.playlists.map((entry) => <ReferenceEntry name={entry.name} key={entry.name} />) }
|
{ this.state.playlists
|
||||||
|
.filter((entry) => entry.name != this.state.name)
|
||||||
|
.map((entry) => <ReferenceEntry name={entry.name} key={entry.name} />) }
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@ -287,7 +325,7 @@ class PlaylistView extends Component{
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td className="center-text ui-text text-no-select">
|
<td className="center-text ui-text text-no-select">
|
||||||
recommendations sample size
|
number of recommendations
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="number"
|
<input type="number"
|
||||||
@ -298,7 +336,7 @@ class PlaylistView extends Component{
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{ this.state.type == 'recents' &&
|
{ this.state.type == 'recents' &&
|
||||||
<tr>
|
<tr>
|
||||||
<td className="center-text ui-text text-no-select">
|
<td className="center-text ui-text text-no-select">
|
||||||
added since (days)
|
added since (days)
|
||||||
</td>
|
</td>
|
||||||
@ -311,6 +349,15 @@ class PlaylistView extends Component{
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
}
|
}
|
||||||
|
{ this.state.type == 'recents' &&
|
||||||
|
<tr>
|
||||||
|
<td colSpan="2" className="center-text ui-text text-no-select" style={{fontStyle: "italic"}}>
|
||||||
|
<br></br>'recents' playlists search for and include this months and last months playlists when named in the format
|
||||||
|
<br></br>[month] [year]
|
||||||
|
<br></br>e.g july 19 (lowercase)
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan="2">
|
<td colSpan="2">
|
||||||
<button className="button full-width" onClick={this.handleRun}>run</button>
|
<button className="button full-width" onClick={this.handleRun}>run</button>
|
||||||
|
@ -41,12 +41,21 @@ class PlaylistsView extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleRunPlaylist(name, event){
|
handleRunPlaylist(name, event){
|
||||||
axios.get('/api/playlist/run', {params: {name: name}})
|
axios.get('/api/user')
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
showMessage(`${name} ran`);
|
if(response.data.spotify_linked == true){
|
||||||
})
|
axios.get('/api/playlist/run', {params: {name: name}})
|
||||||
.catch((error) => {
|
.then((response) => {
|
||||||
showMessage(`error running ${name} (${error.response.status})`);
|
showMessage(`${name} ran`);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
showMessage(`error running ${name} (${error.response.status})`);
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
showMessage(`link spotify before running`);
|
||||||
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
showMessage(`error running ${this.state.name} (${error.response.status})`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,12 +70,21 @@ class PlaylistsView extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleRunAll(event){
|
handleRunAll(event){
|
||||||
axios.get('/api/playlist/run/user')
|
axios.get('/api/user')
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
showMessage("all playlists ran");
|
if(response.data.spotify_linked == true){
|
||||||
})
|
axios.get('/api/playlist/run/user')
|
||||||
.catch((error) => {
|
.then((response) => {
|
||||||
showMessage(`error running all (${error.response.status})`);
|
showMessage("all playlists ran");
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
showMessage(`error running all (${error.response.status})`);
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
showMessage(`link spotify before running`);
|
||||||
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
showMessage(`error running ${this.state.name} (${error.response.status})`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,16 +106,25 @@ class PlaylistsView extends Component {
|
|||||||
function Table(props){
|
function Table(props){
|
||||||
return (
|
return (
|
||||||
<table className="app-table max-width">
|
<table className="app-table max-width">
|
||||||
|
{ props.playlists.length == 0 ? (
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td className="ui-text text-no-select center-text">
|
||||||
|
no playlists
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
) : (
|
||||||
<tbody>
|
<tbody>
|
||||||
{ props.playlists.map((playlist) => <Row playlist={ playlist }
|
{ props.playlists.map((playlist) => <Row playlist={ playlist }
|
||||||
handleRunPlaylist={props.handleRunPlaylist}
|
handleRunPlaylist={props.handleRunPlaylist}
|
||||||
handleDeletePlaylist={props.handleDeletePlaylist}
|
handleDeletePlaylist={props.handleDeletePlaylist}
|
||||||
key={ playlist.name }/>) }
|
key={ playlist.name }/>) }
|
||||||
{ props.playlists.length > 0 &&
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan="3"><button className="full-width button" onClick={props.handleRunAll}>run all</button></td>
|
<td colSpan="3"><button className="full-width button" onClick={props.handleRunAll}>run all</button></td>
|
||||||
</tr> }
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
)}
|
||||||
</table>
|
</table>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user