check for spotify auth on run, updated helper text

This commit is contained in:
aj 2019-08-08 00:18:41 +01:00
parent f1dcf6fdd6
commit 61ac85d41f
4 changed files with 237 additions and 96 deletions

View File

@ -9,7 +9,39 @@ class Index extends Component{
}
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>
);
}
}

View File

@ -10,53 +10,83 @@ class NewPlaylist extends Component {
super(props);
this.state = {
name: '',
type: 'normal'
type: 'default',
description: ''
}
this.handleInputChange = this.handleInputChange.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){
this.setState({
[event.target.name]: event.target.value
});
this.setDescription(event.target.value);
}
handleSubmit(event){
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: 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})`);
var name = this.state.name;
this.setState({
name: ''
});
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(){
return (
<table className="app-table">
<table className="app-table max-width">
<thead>
<tr>
<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>
</tr>
</thead>
@ -64,7 +94,7 @@ class NewPlaylist extends Component {
<tr>
<td>
<select className="full-width" name="type" onChange={this.handleInputChange}>
<option value="default">normal</option>
<option value="default">default</option>
<option value="recents">recents</option>
</select>
</td>
@ -83,6 +113,11 @@ class NewPlaylist extends Component {
<input type="submit" className="button full-width" onClick={this.handleSubmit} value="create" />
</td>
</tr>
<tr>
<td colSpan="2" className="ui-text text-no-select center-text">
<br></br>{this.state.description}
</td>
</tr>
</tbody>
</table>
);

View File

@ -11,6 +11,7 @@ class PlaylistView extends Component{
name: this.props.match.params.name,
parts: [],
playlists: [],
filteredPlaylists: [],
playlist_references: [],
type: null,
@ -50,8 +51,13 @@ class PlaylistView extends Component{
return 0;
});
var filteredPlaylists = playlists.data.playlists.filter((entry) => entry.name != this.state.name);
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) => {
showMessage(`error getting playlist info (${error.response.status})`);
@ -67,6 +73,7 @@ class PlaylistView extends Component{
}
handleInputChange(event){
this.setState({
[event.target.name]: event.target.value
});
@ -123,59 +130,74 @@ class PlaylistView extends Component{
handleAddPart(event){
var check = this.state.parts.filter((e) => {
return e == event.target.value;
});
if(this.state.newPlaylistName.length != 0){
if(check.length == 0) {
var parts = this.state.parts.slice();
parts.push(this.state.newPlaylistName);
var check = this.state.parts.includes(this.state.newPlaylistName);
parts.sort(function(a, b){
if(a < b) { return -1; }
if(a > b) { return 1; }
return 0;
});
if(check == false) {
var parts = this.state.parts.slice();
parts.push(this.state.newPlaylistName);
this.setState({
parts: parts,
newPlaylistName: ''
});
axios.post('/api/playlist', {
name: this.state.name,
parts: parts
}).catch((error) => {
showMessage(`error adding part (${error.response.status})`);
});
parts.sort(function(a, b){
if(a < b) { return -1; }
if(a > b) { return 1; }
return 0;
});
this.setState({
parts: parts,
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){
var check = this.state.playlist_references.filter((e) => {
return e == event.target.value;
});
if(this.state.newPlaylistReference.length != 0){
if(check.length == 0) {
var playlist_references = this.state.playlist_references.slice();
playlist_references.push(this.state.newPlaylistReference);
var check = this.state.playlist_references.includes(this.state.newPlaylistReference);
playlist_references.sort(function(a, b){
if(a < b) { return -1; }
if(a > b) { return 1; }
return 0;
});
if(check == false) {
var playlist_references = this.state.playlist_references.slice();
playlist_references.push(this.state.newPlaylistReference);
this.setState({
playlist_references: playlist_references,
newPlaylistReference: ''
});
axios.post('/api/playlist', {
name: this.state.name,
playlist_references: playlist_references
}).catch((error) => {
showMessage(`error adding reference (${error.response.status})`);
});
playlist_references.sort(function(a, b){
if(a < b) { return -1; }
if(a > b) { return 1; }
return 0;
});
var filteredPlaylists = this.state.playlists.filter((entry) => entry.name != this.state.name);
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){
axios.get('/api/playlist/run', {params: {name: this.state.name}})
.then((reponse) => {
showMessage(`${this.state.name} ran`);
})
.catch((error) => {
axios.get('/api/user')
.then((response) => {
if(response.data.spotify_linked == true){
axios.get('/api/playlist/run', {params: {name: this.state.name}})
.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})`);
});
}
@ -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.parts.length > 0 && <ListBlock name="spotify" handler={this.handleRemoveRow} list={this.state.parts}/> }
<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>
<td>
<input type="text"
@ -246,7 +282,7 @@ class PlaylistView extends Component{
className="full-width"
value={this.state.newPlaylistName}
onChange={this.handleInputChange}
placeholder="spotify playlist"></input>
placeholder="spotify playlist name"></input>
</td>
<td>
<button className="button full-width" onClick={this.handleAddPart}>add</button>
@ -258,7 +294,9 @@ class PlaylistView extends Component{
className="full-width"
value={this.state.newPlaylistReference}
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>
</td>
<td>
@ -287,7 +325,7 @@ class PlaylistView extends Component{
</tr>
<tr>
<td className="center-text ui-text text-no-select">
recommendations sample size
number of recommendations
</td>
<td>
<input type="number"
@ -298,7 +336,7 @@ class PlaylistView extends Component{
</td>
</tr>
{ this.state.type == 'recents' &&
<tr>
<tr>
<td className="center-text ui-text text-no-select">
added since (days)
</td>
@ -311,6 +349,15 @@ class PlaylistView extends Component{
</td>
</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>
<td colSpan="2">
<button className="button full-width" onClick={this.handleRun}>run</button>

View File

@ -41,12 +41,21 @@ class PlaylistsView extends Component {
}
handleRunPlaylist(name, event){
axios.get('/api/playlist/run', {params: {name: name}})
axios.get('/api/user')
.then((response) => {
showMessage(`${name} ran`);
})
.catch((error) => {
showMessage(`error running ${name} (${error.response.status})`);
if(response.data.spotify_linked == true){
axios.get('/api/playlist/run', {params: {name: name}})
.then((response) => {
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){
axios.get('/api/playlist/run/user')
axios.get('/api/user')
.then((response) => {
showMessage("all playlists ran");
})
.catch((error) => {
showMessage(`error running all (${error.response.status})`);
if(response.data.spotify_linked == true){
axios.get('/api/playlist/run/user')
.then((response) => {
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){
return (
<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>
{ props.playlists.map((playlist) => <Row playlist={ playlist }
handleRunPlaylist={props.handleRunPlaylist}
handleDeletePlaylist={props.handleDeletePlaylist}
key={ playlist.name }/>) }
{ props.playlists.length > 0 &&
<tr>
<td colSpan="3"><button className="full-width button" onClick={props.handleRunAll}>run all</button></td>
</tr> }
</tr>
</tbody>
)}
</table>
);
}