integrated spotify auth/deauth, adding parts to playlist
This commit is contained in:
parent
6617160c75
commit
e3615d0ccf
@ -2,6 +2,8 @@ from flask import Blueprint, session, request, jsonify
|
|||||||
from google.cloud import firestore
|
from google.cloud import firestore
|
||||||
from werkzeug.security import check_password_hash, generate_password_hash
|
from werkzeug.security import check_password_hash, generate_password_hash
|
||||||
|
|
||||||
|
import spotify.api.database as database
|
||||||
|
|
||||||
blueprint = Blueprint('api', __name__)
|
blueprint = Blueprint('api', __name__)
|
||||||
db = firestore.Client()
|
db = firestore.Client()
|
||||||
|
|
||||||
@ -11,15 +13,9 @@ def get_playlists():
|
|||||||
|
|
||||||
if 'username' in session:
|
if 'username' in session:
|
||||||
|
|
||||||
users = db.collection(u'spotify_users').where(u'username', u'==', session['username']).stream()
|
pulled_user = database.get_user_doc_ref(session['username'])
|
||||||
|
|
||||||
users = [i for i in users]
|
playlists = database.get_user_playlists_collection(pulled_user.id)
|
||||||
|
|
||||||
if len(users) == 1:
|
|
||||||
playlists = db.document(u'spotify_users/{}'.format(users[0].id)).collection(u'playlists')
|
|
||||||
else:
|
|
||||||
error = {'error': 'multiple usernames?'}
|
|
||||||
return jsonify(error), 500
|
|
||||||
|
|
||||||
response = {
|
response = {
|
||||||
'playlists': [i.to_dict() for i in playlists.stream()]
|
'playlists': [i.to_dict() for i in playlists.stream()]
|
||||||
@ -28,8 +24,7 @@ def get_playlists():
|
|||||||
return jsonify(response), 200
|
return jsonify(response), 200
|
||||||
|
|
||||||
else:
|
else:
|
||||||
error = {'error': 'not logged in'}
|
return jsonify({'error': 'not logged in'}), 401
|
||||||
return jsonify(error), 401
|
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route('/playlist', methods=['GET', 'POST', 'PUT'])
|
@blueprint.route('/playlist', methods=['GET', 'POST', 'PUT'])
|
||||||
@ -37,33 +32,25 @@ def get_playlist():
|
|||||||
|
|
||||||
if 'username' in session:
|
if 'username' in session:
|
||||||
|
|
||||||
users = db.collection(u'spotify_users').where(u'username', u'==', session['username']).stream()
|
user_ref = database.get_user_doc_ref(session['username'])
|
||||||
|
playlists = database.get_user_playlists_collection(user_ref.id)
|
||||||
users = [i for i in users]
|
|
||||||
|
|
||||||
if len(users) == 1:
|
|
||||||
playlists = db.document(u'spotify_users/{}'.format(users[0].id)).collection(u'playlists')
|
|
||||||
else:
|
|
||||||
error = {'error': 'multiple usernames?'}
|
|
||||||
return jsonify(error), 500
|
|
||||||
|
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
playlist_name = request.args.get('name', None)
|
playlist_name = request.args.get('name', None)
|
||||||
|
|
||||||
if playlist_name:
|
if playlist_name:
|
||||||
|
|
||||||
playlist = [i for i in playlists.where(u'name', u'==', playlist_name).stream()]
|
queried_playlist = [i for i in playlists.where(u'name', u'==', playlist_name).stream()]
|
||||||
|
|
||||||
if len(playlist) == 0:
|
if len(queried_playlist) == 0:
|
||||||
return jsonify({'error': 'no playlist found'}), 404
|
return jsonify({'error': 'no playlist found'}), 404
|
||||||
elif len(playlist) > 1:
|
elif len(queried_playlist) > 1:
|
||||||
return jsonify({'error': 'multiple playlists found'}), 500
|
return jsonify({'error': 'multiple playlists found'}), 500
|
||||||
|
|
||||||
return jsonify(playlist[0].to_dict()), 200
|
return jsonify(queried_playlist[0].to_dict()), 200
|
||||||
|
|
||||||
else:
|
else:
|
||||||
response = {"error": 'no name requested'}
|
return jsonify({"error": 'no name requested'}), 400
|
||||||
return jsonify(response), 400
|
|
||||||
|
|
||||||
elif request.method == 'POST' or request.method == 'PUT':
|
elif request.method == 'POST' or request.method == 'PUT':
|
||||||
|
|
||||||
@ -73,12 +60,54 @@ def get_playlist():
|
|||||||
return jsonify({'error': "no name provided"}), 400
|
return jsonify({'error': "no name provided"}), 400
|
||||||
|
|
||||||
playlist_name = request_json['name']
|
playlist_name = request_json['name']
|
||||||
|
playlist_parts = request_json.get('parts', None)
|
||||||
|
playlist_id = request_json.get('id', None)
|
||||||
|
|
||||||
return 404
|
queried_playlist = [i for i in playlists.where(u'name', u'==', playlist_name).stream()]
|
||||||
|
|
||||||
|
if request.method == 'PUT':
|
||||||
|
|
||||||
|
if len(queried_playlist) != 0:
|
||||||
|
return jsonify({'error': 'playlist already exists'}), 400
|
||||||
|
|
||||||
|
if playlist_parts is None or playlist_id is None:
|
||||||
|
return jsonify({'error': 'parts and id required'}), 400
|
||||||
|
|
||||||
|
playlists.add({
|
||||||
|
'name': playlist_name,
|
||||||
|
'parts': playlist_parts,
|
||||||
|
'playlist_id': playlist_id
|
||||||
|
})
|
||||||
|
|
||||||
|
return jsonify({"message": 'playlist added', "status": "success"}), 200
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
if len(queried_playlist) == 0:
|
||||||
|
return jsonify({'error': "playlist doesn't exist"}), 400
|
||||||
|
|
||||||
|
if len(queried_playlist) > 1:
|
||||||
|
return jsonify({'error': "multiple playlists exist"}), 500
|
||||||
|
|
||||||
|
if playlist_parts is None and playlist_id is None:
|
||||||
|
return jsonify({'error': "no chnages to make"}), 400
|
||||||
|
|
||||||
|
playlist_doc = playlists.document(queried_playlist[0].id)
|
||||||
|
|
||||||
|
dic = {}
|
||||||
|
|
||||||
|
if playlist_parts:
|
||||||
|
dic['parts'] = playlist_parts
|
||||||
|
|
||||||
|
if playlist_id:
|
||||||
|
dic['playlist_id'] = playlist_id
|
||||||
|
|
||||||
|
playlist_doc.update(dic)
|
||||||
|
|
||||||
|
return jsonify({"message": 'playlist updated', "status": "success"}), 200
|
||||||
|
|
||||||
else:
|
else:
|
||||||
error = {'error': 'not logged in'}
|
return jsonify({'error': 'not logged in'}), 401
|
||||||
return jsonify(error), 401
|
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route('/user', methods=['GET'])
|
@blueprint.route('/user', methods=['GET'])
|
||||||
@ -86,28 +115,19 @@ def user():
|
|||||||
|
|
||||||
if 'username' in session:
|
if 'username' in session:
|
||||||
|
|
||||||
users = db.collection(u'spotify_users').where(u'username', u'==', session['username']).stream()
|
pulled_user = database.get_user_doc_ref(session['username']).get().to_dict()
|
||||||
users = [i for i in users]
|
|
||||||
|
|
||||||
if len(users) == 1:
|
|
||||||
pulled_user = db.collection(u'spotify_users').document(u'{}'.format(users[0].id)).get()
|
|
||||||
else:
|
|
||||||
error = {'error': 'multiple usernames?'}
|
|
||||||
return jsonify(error), 500
|
|
||||||
|
|
||||||
doc = pulled_user.to_dict()
|
|
||||||
|
|
||||||
response = {
|
response = {
|
||||||
'username': doc['username'],
|
'username': pulled_user['username'],
|
||||||
'type': doc['type'],
|
'type': pulled_user['type'],
|
||||||
'validated': doc['validated']
|
'spotify_linked': pulled_user['spotify_linked'],
|
||||||
|
'validated': pulled_user['validated']
|
||||||
}
|
}
|
||||||
|
|
||||||
return jsonify(response), 200
|
return jsonify(response), 200
|
||||||
|
|
||||||
else:
|
else:
|
||||||
error = {'error': 'not logged in'}
|
return jsonify({'error': 'not logged in'}), 401
|
||||||
return jsonify(error), 401
|
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route('/user/password', methods=['POST'])
|
@blueprint.route('/user/password', methods=['POST'])
|
||||||
@ -120,21 +140,12 @@ def change_password():
|
|||||||
if 'new_password' in request_json and 'current_password' in request_json:
|
if 'new_password' in request_json and 'current_password' in request_json:
|
||||||
|
|
||||||
if len(request_json['new_password']) == 0:
|
if len(request_json['new_password']) == 0:
|
||||||
response = {"error": 'zero length password'}
|
return jsonify({"error": 'zero length password'}), 400
|
||||||
return jsonify(response), 400
|
|
||||||
|
|
||||||
if len(request_json['new_password']) > 30:
|
if len(request_json['new_password']) > 30:
|
||||||
response = {"error": 'password too long'}
|
return jsonify({"error": 'password too long'}), 400
|
||||||
return jsonify(response), 400
|
|
||||||
|
|
||||||
users = db.collection(u'spotify_users').where(u'username', u'==', session['username']).stream()
|
current_user = database.get_user_doc_ref(session['username'])
|
||||||
users = [i for i in users]
|
|
||||||
|
|
||||||
if len(users) == 1:
|
|
||||||
current_user = db.collection(u'spotify_users').document(u'{}'.format(users[0].id))
|
|
||||||
else:
|
|
||||||
error = {'error': 'multiple usernames?'}
|
|
||||||
return jsonify(error), 500
|
|
||||||
|
|
||||||
if check_password_hash(current_user.get().to_dict()['password'], request_json['current_password']):
|
if check_password_hash(current_user.get().to_dict()['password'], request_json['current_password']):
|
||||||
|
|
||||||
@ -144,18 +155,10 @@ def change_password():
|
|||||||
return jsonify(response), 200
|
return jsonify(response), 200
|
||||||
|
|
||||||
else:
|
else:
|
||||||
error = {'error': 'wrong password provided'}
|
return jsonify({'error': 'wrong password provided'}), 403
|
||||||
return jsonify(error), 403
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
error = {'error': 'malformed request, no old_password/new_password'}
|
return jsonify({'error': 'malformed request, no old_password/new_password'}), 400
|
||||||
return jsonify(error), 400
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
error = {'error': 'not logged in'}
|
return jsonify({'error': 'not logged in'}), 401
|
||||||
return jsonify(error), 401
|
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route('/playlist', methods=['GET', 'PUT', 'POST'])
|
|
||||||
def playlist():
|
|
||||||
return 401
|
|
||||||
|
32
spotify/api/database.py
Normal file
32
spotify/api/database.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from google.cloud import firestore
|
||||||
|
db = firestore.Client()
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_query_stream(user):
|
||||||
|
|
||||||
|
users = db.collection(u'spotify_users').where(u'username', u'==', user).stream()
|
||||||
|
users = [i for i in users]
|
||||||
|
|
||||||
|
return users
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_doc_ref(user):
|
||||||
|
|
||||||
|
users = get_user_query_stream(user)
|
||||||
|
|
||||||
|
if len(users) == 1:
|
||||||
|
|
||||||
|
return db.collection(u'spotify_users').document(u'{}'.format(users[0].id))
|
||||||
|
|
||||||
|
else:
|
||||||
|
print(len(users))
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_playlists_collection(user_id):
|
||||||
|
|
||||||
|
playlists = db.document(u'spotify_users/{}'.format(user_id)).collection(u'playlists')
|
||||||
|
|
||||||
|
return playlists
|
||||||
|
|
||||||
|
|
@ -2,6 +2,13 @@ from flask import Blueprint, session, flash, request, redirect, url_for
|
|||||||
from google.cloud import firestore
|
from google.cloud import firestore
|
||||||
from werkzeug.security import check_password_hash
|
from werkzeug.security import check_password_hash
|
||||||
|
|
||||||
|
import urllib
|
||||||
|
import datetime
|
||||||
|
from base64 import b64encode
|
||||||
|
import requests
|
||||||
|
|
||||||
|
import spotify.api.database as database
|
||||||
|
|
||||||
blueprint = Blueprint('authapi', __name__)
|
blueprint = Blueprint('authapi', __name__)
|
||||||
|
|
||||||
db = firestore.Client()
|
db = firestore.Client()
|
||||||
@ -17,9 +24,7 @@ def login():
|
|||||||
username = request.form['username'].lower()
|
username = request.form['username'].lower()
|
||||||
password = request.form['password']
|
password = request.form['password']
|
||||||
|
|
||||||
users = db.collection(u'spotify_users').where(u'username', u'==', username).stream()
|
users = database.get_user_query_stream(username)
|
||||||
|
|
||||||
users = [i for i in users]
|
|
||||||
|
|
||||||
if len(users) == 0:
|
if len(users) == 0:
|
||||||
flash('user not found')
|
flash('user not found')
|
||||||
@ -35,6 +40,10 @@ def login():
|
|||||||
return redirect(url_for('index'))
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
if check_password_hash(doc['password'], password):
|
if check_password_hash(doc['password'], password):
|
||||||
|
|
||||||
|
user_reference = db.collection(u'spotify_users').document(u'{}'.format(users[0].id))
|
||||||
|
user_reference.update({'last_login': datetime.datetime.utcnow()})
|
||||||
|
|
||||||
session['username'] = username
|
session['username'] = username
|
||||||
return redirect(url_for('app_route'))
|
return redirect(url_for('app_route'))
|
||||||
else:
|
else:
|
||||||
@ -50,3 +59,79 @@ def logout():
|
|||||||
session.pop('username', None)
|
session.pop('username', None)
|
||||||
flash('logged out')
|
flash('logged out')
|
||||||
return redirect(url_for('index'))
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route('/spotify')
|
||||||
|
def auth():
|
||||||
|
|
||||||
|
if 'username' in session:
|
||||||
|
|
||||||
|
client_id = db.document('key/spotify').get().to_dict()['clientid']
|
||||||
|
params = urllib.parse.urlencode(
|
||||||
|
{
|
||||||
|
'client_id': client_id,
|
||||||
|
'response_type': 'code',
|
||||||
|
'scope': 'playlist-modify-public playlist-modify-private playlist-read-private',
|
||||||
|
'redirect_uri': 'https://spotify.sarsoo.xyz/auth/spotify/token'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return redirect(urllib.parse.urlunparse(['https', 'accounts.spotify.com', 'authorize', '', params, '']))
|
||||||
|
|
||||||
|
return redirect('/')
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route('/spotify/token')
|
||||||
|
def token():
|
||||||
|
|
||||||
|
if 'username' in session:
|
||||||
|
|
||||||
|
code = request.args.get('code', None)
|
||||||
|
if code is None:
|
||||||
|
error = request.args.get('error', None)
|
||||||
|
print('error')
|
||||||
|
else:
|
||||||
|
app_credentials = db.document('key/spotify').get().to_dict()
|
||||||
|
|
||||||
|
idsecret = b64encode(bytes(app_credentials['clientid'] + ':' + app_credentials['clientsecret'], "utf-8")).decode("ascii")
|
||||||
|
headers = {'Authorization': 'Basic %s' % idsecret}
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'grant_type': 'authorization_code',
|
||||||
|
'code': code,
|
||||||
|
'redirect_uri': 'https://spotify.sarsoo.xyz/auth/spotify/token'
|
||||||
|
}
|
||||||
|
|
||||||
|
req = requests.post('https://accounts.spotify.com/api/token', data=data, headers=headers)
|
||||||
|
|
||||||
|
resp = req.json()
|
||||||
|
|
||||||
|
user_reference = database.get_user_doc_ref(session['username'])
|
||||||
|
|
||||||
|
user_reference.update({
|
||||||
|
'access_token': resp['access_token'],
|
||||||
|
'refresh_token': resp['refresh_token'],
|
||||||
|
'spotify_linked': True
|
||||||
|
})
|
||||||
|
|
||||||
|
return redirect('/app/settings/spotify')
|
||||||
|
|
||||||
|
return redirect('/')
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route('/spotify/deauth')
|
||||||
|
def deauth():
|
||||||
|
|
||||||
|
if 'username' in session:
|
||||||
|
|
||||||
|
user_reference = database.get_user_doc_ref(session['username'])
|
||||||
|
|
||||||
|
user_reference.update({
|
||||||
|
'access_token': None,
|
||||||
|
'refresh_token': None,
|
||||||
|
'spotify_linked': False
|
||||||
|
})
|
||||||
|
|
||||||
|
return redirect('/app/settings/spotify')
|
||||||
|
|
||||||
|
return redirect('/')
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
from flask import Flask, render_template, redirect, request, session, flash, url_for
|
from flask import Flask, render_template, redirect, request, session, flash, url_for
|
||||||
from google.cloud import firestore
|
from google.cloud import firestore
|
||||||
import requests
|
|
||||||
|
|
||||||
from base64 import b64encode
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import urllib
|
|
||||||
|
|
||||||
from spotify.auth import auth_blueprint
|
from spotify.auth import auth_blueprint
|
||||||
from spotify.api import api_blueprint
|
from spotify.api import api_blueprint
|
||||||
@ -24,51 +20,6 @@ def index():
|
|||||||
return render_template('index.html')
|
return render_template('index.html')
|
||||||
|
|
||||||
|
|
||||||
@app.route('/spotify/auth')
|
|
||||||
def auth():
|
|
||||||
|
|
||||||
client_id = db.document('key/spotify').get().to_dict()['clientid']
|
|
||||||
params = urllib.parse.urlencode(
|
|
||||||
{
|
|
||||||
'client_id': client_id,
|
|
||||||
'response_type': 'code',
|
|
||||||
'scope': 'playlist-modify-public playlist-modify-private playlist-read-private',
|
|
||||||
'redirect_uri': 'https://spotify.sarsoo.xyz/token'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return redirect(urllib.parse.urlunparse(['https', 'accounts.spotify.com', 'authorize', '', params, '']))
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/token')
|
|
||||||
def token():
|
|
||||||
|
|
||||||
code = request.args.get('code', None)
|
|
||||||
if code is None:
|
|
||||||
error = request.args.get('error', None)
|
|
||||||
print('error')
|
|
||||||
else:
|
|
||||||
app_credentials = db.document('key/spotify').get().to_dict()
|
|
||||||
|
|
||||||
idsecret = b64encode(bytes(app_credentials['clientid'] + ':' + app_credentials['clientsecret'], "utf-8")).decode("ascii")
|
|
||||||
headers = {'Authorization': 'Basic %s' % idsecret}
|
|
||||||
|
|
||||||
data = {
|
|
||||||
'grant_type': 'authorization_code',
|
|
||||||
'code': code,
|
|
||||||
'redirect_uri': 'https://spotify.sarsoo.xyz/token'
|
|
||||||
}
|
|
||||||
|
|
||||||
req = requests.post('https://accounts.spotify.com/api/token', data=data, headers=headers)
|
|
||||||
|
|
||||||
resp = req.json()
|
|
||||||
# print(str(req.status_code) + str(resp))
|
|
||||||
|
|
||||||
# if 200 <= req.status_code < 300:
|
|
||||||
|
|
||||||
return redirect('/app')
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/app', defaults={'path': ''})
|
@app.route('/app', defaults={'path': ''})
|
||||||
@app.route('/app/<path:path>')
|
@app.route('/app/<path:path>')
|
||||||
def app_route(path):
|
def app_route(path):
|
||||||
|
@ -22,7 +22,7 @@ class Index extends Component{
|
|||||||
}
|
}
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
return <p>index</p>;
|
return <h1 className="center-text">welcome to playlist manager!</h1>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,21 +1,97 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
|
|
||||||
const axios = require('axios');
|
const axios = require('axios');
|
||||||
|
|
||||||
class PlaylistView extends Component{
|
class PlaylistView extends Component{
|
||||||
|
|
||||||
constructor(props){
|
constructor(props){
|
||||||
super(props);
|
super(props);
|
||||||
console.log(this.props);
|
console.log(this.props.match.params.name);
|
||||||
this.state = {
|
this.state = {
|
||||||
name: this.props.match.name
|
name: this.props.match.params.name,
|
||||||
|
parts: [],
|
||||||
|
error: false,
|
||||||
|
error_text: null,
|
||||||
|
add_part_value: ''
|
||||||
}
|
}
|
||||||
|
this.handleAddPart = this.handleAddPart.bind(this);
|
||||||
|
this.handleAddPartChange = this.handleAddPartChange.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount(){
|
||||||
|
this.getPlaylistInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
getPlaylistInfo(){
|
||||||
|
axios.get(`/api/playlist?name=${ this.state.name }`)
|
||||||
|
.then((response) => {
|
||||||
|
this.setState(response.data);
|
||||||
|
}).catch((error) => {
|
||||||
|
this.setState({
|
||||||
|
error: true,
|
||||||
|
error_text: "error pulling playlist info"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleAddPartChange(event){
|
||||||
|
this.setState({
|
||||||
|
add_part_value: event.target.value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleAddPart(event){
|
||||||
|
var parts = this.state.parts;
|
||||||
|
parts.push(this.state.add_part_value);
|
||||||
|
this.setState({
|
||||||
|
parts: parts
|
||||||
|
});
|
||||||
|
axios.post('/api/playlist', {
|
||||||
|
name: this.state.name,
|
||||||
|
parts: parts
|
||||||
|
}).then((response) => {
|
||||||
|
console.log(reponse);
|
||||||
|
}).catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
return <p>{this.state.name}</p>;
|
|
||||||
|
const table = (
|
||||||
|
<table className="app-table max-width">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colSpan="2"><h1>{ this.state.name }</h1></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{ this.state.parts.map((part) => <Row part={ part } key={ part }/>) }
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="text" className="full-width" value={this.state.add_part_value} onChange={this.handleAddPartChange}></input>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button className="button full-width" onClick={this.handleAddPart}>add</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
);
|
||||||
|
|
||||||
|
const error = <p style={{textAlign: "center"}}>{ this.state.error_text }</p>;
|
||||||
|
|
||||||
|
return this.state.error ? error : table;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PlaylistView
|
function Row (props) {
|
||||||
|
return (
|
||||||
|
<tr>
|
||||||
|
<td className="ui-text center-text">{ props.part }</td>
|
||||||
|
<td className="ui-text center-text">remove</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PlaylistView;
|
@ -16,7 +16,8 @@ class PlaylistManager extends Component {
|
|||||||
constructor(props){
|
constructor(props){
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
type: null
|
type: null,
|
||||||
|
spotify_linked: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +38,8 @@ class PlaylistManager extends Component {
|
|||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
self.setState({
|
self.setState({
|
||||||
type: response.data.type
|
type: response.data.type,
|
||||||
|
spotify_linked: response.data.spotify_linked
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -61,7 +63,7 @@ class PlaylistManager extends Component {
|
|||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/app" exact component={Index} />
|
<Route path="/app" exact component={Index} />
|
||||||
<Route path="/app/playlists" exact component={Playlists} />
|
<Route path="/app/playlists" exact component={Playlists} />
|
||||||
<Route path="/app/settings" component={Settings} />
|
<Route path="/app/settings" render={(props) => <Settings {...props} spotify_linked={this.state.spotify_linked}/>} />
|
||||||
{ this.state.type == 'admin' && <Route path="/app/admin" component={Admin} /> }
|
{ this.state.type == 'admin' && <Route path="/app/admin" component={Admin} /> }
|
||||||
<Route path='/app/playlist/:name' component={PlaylistView} />
|
<Route path='/app/playlist/:name' component={PlaylistView} />
|
||||||
<Route component={NotFound} />
|
<Route component={NotFound} />
|
||||||
|
@ -80,9 +80,13 @@ class ChangePassword extends Component {
|
|||||||
render(){
|
render(){
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1>change password</h1>
|
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
<table className="app-table max-width">
|
<table className="app-table max-width">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colSpan="2"><h1>change password</h1></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td className="ui-text center-text">current:</td>
|
<td className="ui-text center-text">current:</td>
|
||||||
@ -117,7 +121,7 @@ class ChangePassword extends Component {
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
{ this.state.error && <p style={{color: "red"}}>{this.state.errorValue}</p>}
|
{ this.state.error && <p style={{color: "red"}} className="center-text">{this.state.errorValue}</p>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { BrowserRouter as Router, Route, Link, Switch, Redirect} from "react-router-dom";
|
import { BrowserRouter as Router, Route, Link, Switch, Redirect} from "react-router-dom";
|
||||||
|
|
||||||
import ChangePassword from "./ChangePassword.js"
|
import ChangePassword from "./ChangePassword.js";
|
||||||
|
import SpotifyLink from "./SpotifyLink.js";
|
||||||
|
|
||||||
class Settings extends Component {
|
class Settings extends Component {
|
||||||
|
|
||||||
@ -10,9 +11,11 @@ class Settings extends Component {
|
|||||||
<div>
|
<div>
|
||||||
<ul className="navbar" style={{width: "100%"}}>
|
<ul className="navbar" style={{width: "100%"}}>
|
||||||
<li><Link to={`${this.props.match.url}/password`}>password</Link></li>
|
<li><Link to={`${this.props.match.url}/password`}>password</Link></li>
|
||||||
|
<li><Link to={`${this.props.match.url}/spotify`}>spotify</Link></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<Route path={`${this.props.match.url}/password`} component={ChangePassword} />
|
<Route path={`${this.props.match.url}/password`} component={ChangePassword} />
|
||||||
|
<Route path={`${this.props.match.url}/spotify`} render={(props) => <SpotifyLink {...props} spotify_linked={this.props.spotify_linked}/>} />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
50
src/js/Settings/SpotifyLink.js
Normal file
50
src/js/Settings/SpotifyLink.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import React, { Component } from "react";
|
||||||
|
const axios = require('axios');
|
||||||
|
|
||||||
|
class SpotifyLink extends Component {
|
||||||
|
|
||||||
|
constructor(props){
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
spotify_linked: props.spotify_linked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getUserInfo(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
render(){
|
||||||
|
return (
|
||||||
|
<table className="app-table max-width">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th><h1 className="ui-text center-text">spotify link status</h1></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td className="ui-text center-text">
|
||||||
|
status: { this.state.spotify_linked ? "linked" : "unlinked" }
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{ this.state.spotify_linked ? <DeAuthButton /> : <AuthButton /> }
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function AuthButton(props) {
|
||||||
|
return <a className="button full-width" href="/auth/spotify">auth</a>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function DeAuthButton(props) {
|
||||||
|
return <a className="button full-width" href="/auth/spotify/deauth">de-auth</a>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SpotifyLink;
|
Loading…
Reference in New Issue
Block a user