added open in tag UI, added include_spotify_owned

This commit is contained in:
andy 2021-07-10 16:00:30 +01:00
parent 79c841d9d8
commit 365cafe004
4 changed files with 75 additions and 10 deletions

View File

@ -54,6 +54,8 @@ class Playlist(Model):
add_this_month = BooleanField(default=False)
day_boundary = NumberField(default=21)
include_spotify_owned = BooleanField(default=True)
chart_range = TextField(default='MONTH')
chart_limit = NumberField(default=50)

View File

@ -89,3 +89,11 @@ class User(Model):
return matches[0]
else:
return exact_match, matches
def get_playlists(self):
"""Get all playlists for a user
Returns:
List[Playlist]: List of users playlists
"""
return Playlist.collection.parent(self.key).fetch()

View File

@ -77,7 +77,10 @@ def run_user_playlist(user: User, playlist: Playlist, spotnet: SpotNetwork = Non
raise NameError(f'No Spotify network returned ({username} / {playlist_name})')
try:
user_playlists = [(i.name, i.uri) for i in spotnet.playlists()]
if not playlist.include_spotify_owned:
user_playlists = [(i.name, i.uri) for i in spotnet.playlists() if 'spotify' not in i.owner.display_name.lower()]
else:
user_playlists = [(i.name, i.uri) for i in spotnet.playlists()]
except SpotifyNetworkException as e:
logger.exception(f'error occured while retrieving playlists {username} / {playlist_name}')
raise e

View File

@ -1,8 +1,8 @@
import React, { Component } from "react";
const axios = require('axios');
import { Card, Button, CardActions, CardContent, FormControl, InputLabel, Select, Typography, Grid, TextField, MenuItem, FormControlLabel, Switch } from '@material-ui/core';
import { Delete } from '@material-ui/icons';
import { Card, Button, ButtonGroup, CardActions, CardContent, FormControl, InputLabel, Select, Typography, Grid, TextField, MenuItem, FormControlLabel, Switch } from '@material-ui/core';
import { Delete, ExitToApp } from '@material-ui/icons';
import { makeStyles } from '@material-ui/core/styles';
import showMessage from "../Toast.js";
@ -28,6 +28,7 @@ class TagView extends Component{
super(props);
this.state = {
tag_id: props.match.params.tag_id,
username: null,
tag: {
name: "",
tracks: [],
@ -44,6 +45,7 @@ class TagView extends Component{
}
this.handleInputChange = this.handleInputChange.bind(this);
this.handleRun = this.handleRun.bind(this);
this.handleView = this.handleView.bind(this);
this.handleRemoveObj = this.handleRemoveObj.bind(this);
this.handleCheckChange = this.handleCheckChange.bind(this);
@ -58,6 +60,7 @@ class TagView extends Component{
*/
componentDidMount(){
this.getTag();
this.getUserInfo();
// var intervalId = setInterval(() => {this.getTag(false)}, 5000);
// var timeoutId = setTimeout(() => {clearInterval(this.state.intervalId)}, 300000);
@ -72,6 +75,26 @@ class TagView extends Component{
// clearTimeout(this.state.timeoutId);
// }
/**
* Get user info from API
*/
getUserInfo(){
this.userInfoCancelToken = axios.CancelToken.source();
var self = this;
axios.get('/api/user', {
cancelToken: this.userInfoCancelToken.token
})
.then((response) => {
self.setState({
username: response.data.lastfm_username
})
})
.catch((error) => {
showMessage(`error getting user info (${error.response.status})`);
});
}
/**
* Get tag info from API
* @param {*} error_toast Whether to show toast on network error
@ -173,6 +196,30 @@ class TagView extends Component{
});
}
/**
* Open a tag element in Last.fm
* @param {*} music_obj Tag element to be viewed
* @param {*} addType Tag type, artist, album etc
* @param {*} event
*/
handleView(music_obj, addType, event){
let url = `https://last.fm/user/${this.state.username}/library/music/`;
switch(addType) {
case "artists":
url = url + encodeURI(music_obj.name);
break;
case "albums":
url = `${url}${encodeURI(music_obj.artist)}/${encodeURI(music_obj.name)}`;
break;
case "tracks":
url = `${url}${encodeURI(music_obj.artist)}/_/${encodeURI(music_obj.name)}`;
break;
}
window.open(url);
}
/**
* Handle remove watched part
* @param {*} music_obj Subject object to remove
@ -334,17 +381,17 @@ class TagView extends Component{
{/* ARTISTS TITLE */}
{ this.state.tag.artists.length > 0 && <Grid item xs={12} ><Typography color="textSecondary" variant="h4">Artists</Typography></Grid> }
{/* ARTIST CARDS */}
{ this.state.tag.artists.length > 0 && <ListBlock handler={this.handleRemoveObj} list={this.state.tag.artists} addType="artists" showTime={this.state.tag.time_objects}/> }
{ this.state.tag.artists.length > 0 && <ListBlock viewHandler={this.handleView} deleteHandler={this.handleRemoveObj} list={this.state.tag.artists} addType="artists" showTime={this.state.tag.time_objects}/> }
{/* ALBUMS TITLE */}
{ this.state.tag.albums.length > 0 && <Grid item xs={12} ><Typography color="textSecondary" variant="h4">Albums</Typography></Grid> }
{/* ALBUM CARDS */}
{ this.state.tag.albums.length > 0 && <ListBlock handler={this.handleRemoveObj} list={this.state.tag.albums} addType="albums" showTime={this.state.tag.time_objects}/> }
{ this.state.tag.albums.length > 0 && <ListBlock viewHandler={this.handleView} deleteHandler={this.handleRemoveObj} list={this.state.tag.albums} addType="albums" showTime={this.state.tag.time_objects}/> }
{/* TRACKS TITLE */}
{ this.state.tag.tracks.length > 0 && <Grid item xs={12} ><Typography color="textSecondary" variant="h4">Tracks</Typography></Grid> }
{/* TRACK CARDS */}
{ this.state.tag.tracks.length > 0 && <ListBlock handler={this.handleRemoveObj} list={this.state.tag.tracks} addType="tracks" showTime={this.state.tag.time_objects}/> }
{ this.state.tag.tracks.length > 0 && <ListBlock viewHandler={this.handleView} deleteHandler={this.handleRemoveObj} list={this.state.tag.tracks} addType="tracks" showTime={this.state.tag.time_objects}/> }
{/* NAME TEXTBOX */}
<Grid item xs={12} sm={this.state.addType != 'artists' ? 3 : 4} md={this.state.addType != 'artists' ? 3 : 4}>
@ -458,7 +505,7 @@ function ListBlock(props) {
alignItems="flex-start"
style={{padding: '24px'}}>
{props.list.map((music_obj) => <BlockGridItem music_obj={ music_obj } key={ music_obj.name }
handler={ props.handler } addType={ props.addType } showTime={ props.showTime }/>)}
deleteHandler={ props.deleteHandler } viewHandler={ props.viewHandler } addType={ props.addType } showTime={ props.showTime }/>)}
</Grid>
}
@ -504,9 +551,14 @@ function BlockGridItem (props) {
{/* DELETE BUTTON */}
<CardActions>
<Button className="full-width" color="secondary" variant="contained" aria-label="delete" onClick={(e) => props.handler(props.music_obj, props.addType, e)} startIcon={<Delete />}>
Delete
</Button>
<ButtonGroup className="full-width" orientation="vertical" color="secondary" variant="contained">
<Button className="full-width" aria-label="goto" onClick={(e) => props.viewHandler(props.music_obj, props.addType, e)} startIcon={<ExitToApp />}>
View
</Button>
<Button className="full-width" aria-label="delete" onClick={(e) => props.deleteHandler(props.music_obj, props.addType, e)} startIcon={<Delete />}>
Delete
</Button>
</ButtonGroup>
</CardActions>
</Card>
</Grid>