Material Redesign #1
@ -114,7 +114,7 @@ def auth():
|
|||||||
'client_id': client_id,
|
'client_id': client_id,
|
||||||
'response_type': 'code',
|
'response_type': 'code',
|
||||||
'scope': 'playlist-modify-public playlist-modify-private playlist-read-private user-read-playback-state user-modify-playback-state user-library-read',
|
'scope': 'playlist-modify-public playlist-modify-private playlist-read-private user-read-playback-state user-modify-playback-state user-library-read',
|
||||||
'redirect_uri': 'https://spotify.sarsoo.xyz/auth/spotify/token'
|
'redirect_uri': 'https://music.sarsoo.xyz/auth/spotify/token'
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ def token():
|
|||||||
data = {
|
data = {
|
||||||
'grant_type': 'authorization_code',
|
'grant_type': 'authorization_code',
|
||||||
'code': code,
|
'code': code,
|
||||||
'redirect_uri': 'https://spotify.sarsoo.xyz/auth/spotify/token'
|
'redirect_uri': 'https://music.sarsoo.xyz/auth/spotify/token'
|
||||||
}
|
}
|
||||||
|
|
||||||
req = requests.post('https://accounts.spotify.com/api/token', data=data, headers=headers)
|
req = requests.post('https://accounts.spotify.com/api/token', data=data, headers=headers)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
|
import { Card, CardContent, Typography, Grid } from '@material-ui/core';
|
||||||
|
|
||||||
class Index extends Component{
|
class Index extends Component{
|
||||||
|
|
||||||
constructor(props){
|
constructor(props){
|
||||||
@ -9,30 +11,26 @@ class Index extends Component{
|
|||||||
|
|
||||||
render(){
|
render(){
|
||||||
return (
|
return (
|
||||||
<table className="app-table">
|
<div style={{maxWidth: '500px', margin: 'auto', marginTop: '20px'}}>
|
||||||
<tbody>
|
<Card align="center">
|
||||||
<tr>
|
<CardContent>
|
||||||
<td className="center-text text-no-select ui-text" style={{fontSize: "20px"}}>
|
<Grid container>
|
||||||
Construct spotify playlists from selections of other playlists
|
<Grid item xs={12}>
|
||||||
</td>
|
<Typography variant="body1">Construct spotify playlists from selections of other playlists</Typography>
|
||||||
</tr>
|
</Grid>
|
||||||
<tr>
|
<Grid item xs={12}>
|
||||||
<td className="center-text text-no-select ui-text">
|
<Typography variant="body1">Group sub-genre playlists</Typography>
|
||||||
Group sub-genre playlists
|
</Grid>
|
||||||
</td>
|
<Grid item xs={12}>
|
||||||
</tr>
|
<Typography variant="body1">Optionally append auto-generated recommendations</Typography>
|
||||||
<tr>
|
</Grid>
|
||||||
<td className="center-text text-no-select ui-text">
|
<Grid item xs={12}>
|
||||||
Optionally append auto-generated recommendations
|
<Typography variant="body1">Playlists are run multiple times a day</Typography>
|
||||||
</td>
|
</Grid>
|
||||||
</tr>
|
</Grid>
|
||||||
<tr>
|
</CardContent>
|
||||||
<td className="center-text text-no-select ui-text">
|
</Card>
|
||||||
<br></br>Playlists are run multiple times a day
|
</div>
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,13 +83,14 @@ class NewPlaylist extends Component {
|
|||||||
|
|
||||||
render(){
|
render(){
|
||||||
return (
|
return (
|
||||||
|
<div style={{maxWidth: '500px', margin: 'auto', marginTop: '20px'}}>
|
||||||
<Card align="center">
|
<Card align="center">
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Grid container>
|
<Grid container spacing={5}>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Typography variant="h3">New</Typography>
|
<Typography variant="h3">New</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={4}>
|
<Grid item xs={12} sm={4}>
|
||||||
<FormControl variant="filled">
|
<FormControl variant="filled">
|
||||||
<InputLabel htmlFor="type-select">Type</InputLabel>
|
<InputLabel htmlFor="type-select">Type</InputLabel>
|
||||||
<Select
|
<Select
|
||||||
@ -100,19 +101,22 @@ class NewPlaylist extends Component {
|
|||||||
name: 'type',
|
name: 'type',
|
||||||
id: 'type-select',
|
id: 'type-select',
|
||||||
}}
|
}}
|
||||||
|
className="full-width"
|
||||||
>
|
>
|
||||||
<option value="default">Default</option>
|
<option value="default">Default</option>
|
||||||
<option value="recents">Recents</option>
|
<option value="recents">Recents</option>
|
||||||
|
<option value="fmchart">Last.fm Chart</option>
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={8}>
|
<Grid item xs={12} sm={8}>
|
||||||
<TextField
|
<TextField
|
||||||
label="Name"
|
label="Name"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={this.handleInputChange}
|
onChange={this.handleInputChange}
|
||||||
name="name"
|
name="name"
|
||||||
value={this.state.name} />
|
value={this.state.name}
|
||||||
|
className="full-width" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Typography variant="body2" color="textSecondary">{ this.state.description }</Typography>
|
<Typography variant="body2" color="textSecondary">{ this.state.description }</Typography>
|
||||||
@ -123,6 +127,7 @@ class NewPlaylist extends Component {
|
|||||||
<Button variant="contained" color="primary" className="full-width" onClick={this.handleSubmit}>Create</Button>
|
<Button variant="contained" color="primary" className="full-width" onClick={this.handleSubmit}>Create</Button>
|
||||||
</CardActions>
|
</CardActions>
|
||||||
</Card>
|
</Card>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ export class Edit extends Component{
|
|||||||
|
|
||||||
getPlaylistInfo(){
|
getPlaylistInfo(){
|
||||||
return axios.get(`/api/playlist?name=${ this.state.name }`);
|
return axios.get(`/api/playlist?name=${ this.state.name }`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlaylists(){
|
getPlaylists(){
|
||||||
return axios.get(`/api/playlists`);
|
return axios.get(`/api/playlists`);
|
||||||
@ -168,7 +168,7 @@ export class Edit extends Component{
|
|||||||
showMessage(`Error Updating Boundary Value (${error.response.status})`);
|
showMessage(`Error Updating Boundary Value (${error.response.status})`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRecommendationsSampleChange(sample){
|
handleRecommendationsSampleChange(sample){
|
||||||
if(sample == ''){
|
if(sample == ''){
|
||||||
sample = 0;
|
sample = 0;
|
||||||
@ -421,6 +421,7 @@ export class Edit extends Component{
|
|||||||
<Grid item xs={8} sm={8} md={3}>
|
<Grid item xs={8} sm={8} md={3}>
|
||||||
<TextField
|
<TextField
|
||||||
name="newPlaylistName"
|
name="newPlaylistName"
|
||||||
|
variant="outlined"
|
||||||
label="Spotify Playlist"
|
label="Spotify Playlist"
|
||||||
value={this.state.newPlaylistName}
|
value={this.state.newPlaylistName}
|
||||||
onChange={this.handleInputChange}
|
onChange={this.handleInputChange}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
const axios = require('axios');
|
const axios = require('axios');
|
||||||
|
|
||||||
|
import { Card, Grid, Button, TextField, CardContent, CardActions, Typography } from "@material-ui/core";
|
||||||
|
|
||||||
import showMessage from "../Toast.js"
|
import showMessage from "../Toast.js"
|
||||||
|
|
||||||
class ChangePassword extends Component {
|
class ChangePassword extends Component {
|
||||||
@ -63,49 +65,52 @@ class ChangePassword extends Component {
|
|||||||
|
|
||||||
render(){
|
render(){
|
||||||
return (
|
return (
|
||||||
<div>
|
<div style={{maxWidth: '500px', margin: 'auto', marginTop: '20px'}}>
|
||||||
<form onSubmit={this.handleSubmit}>
|
<Card align="center">
|
||||||
<table className="app-table max-width">
|
<form onSubmit={this.handleSubmit}>
|
||||||
<thead>
|
<CardContent>
|
||||||
<tr>
|
<Grid container spacing={2}>
|
||||||
<th colSpan="2"><h1 className="text-no-select">Change Password</h1></th>
|
<Grid item className="full-width">
|
||||||
</tr>
|
<Typography variant="h4" color="textPrimary">Change Password</Typography>
|
||||||
</thead>
|
</Grid>
|
||||||
<tbody>
|
<Grid item className="full-width">
|
||||||
<tr>
|
<TextField
|
||||||
<td className="ui-text center-text text-no-select">Current:</td>
|
label="Current Password"
|
||||||
<td><input
|
|
||||||
type="password"
|
type="password"
|
||||||
name="current"
|
variant="outlined"
|
||||||
value={this.state.current}
|
|
||||||
onChange={this.handleCurrentChange}
|
onChange={this.handleCurrentChange}
|
||||||
className="full-width" /></td>
|
name="current"
|
||||||
</tr>
|
value={this.state.current}
|
||||||
<tr>
|
className="full-width" />
|
||||||
<td className="ui-text center-text text-no-select">New:</td>
|
</Grid>
|
||||||
<td><input
|
<Grid item className="full-width">
|
||||||
|
<TextField
|
||||||
|
label="New Password"
|
||||||
|
variant="outlined"
|
||||||
type="password"
|
type="password"
|
||||||
name="new1"
|
|
||||||
value={this.state.new1}
|
|
||||||
onChange={this.handleNewChange}
|
onChange={this.handleNewChange}
|
||||||
className="full-width" /></td>
|
name="new1"
|
||||||
</tr>
|
value={this.state.new1}
|
||||||
<tr>
|
className="full-width" />
|
||||||
<td className="ui-text center-text text-no-select">New Again:</td>
|
</Grid>
|
||||||
<td><input
|
<Grid item className="full-width">
|
||||||
|
<TextField
|
||||||
|
label="New Password Again"
|
||||||
|
variant="outlined"
|
||||||
type="password"
|
type="password"
|
||||||
name="new2"
|
|
||||||
value={this.state.new2}
|
|
||||||
onChange={this.handleNew2Change}
|
onChange={this.handleNew2Change}
|
||||||
className="full-width" /></td>
|
name="new2"
|
||||||
</tr>
|
value={this.state.new2}
|
||||||
<tr>
|
className="full-width" />
|
||||||
<td colSpan="2"><input type="submit" style={{width: "100%"}} className="button" value="Change" /></td>
|
</Grid>
|
||||||
</tr>
|
{ this.state.error && <Grid item><Typography variant="textSeondary">{this.state.errorValue}</Typography></Grid>}
|
||||||
</tbody>
|
</Grid>
|
||||||
</table>
|
</CardContent>
|
||||||
</form>
|
<CardActions>
|
||||||
{ this.state.error && <p style={{color: "red"}} className="center-text">{this.state.errorValue}</p>}
|
<Button type="submit" variant="contained" className="full-width" onClick={this.runStats}>Change</Button>
|
||||||
|
</CardActions>
|
||||||
|
</form>
|
||||||
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
const axios = require('axios');
|
const axios = require('axios');
|
||||||
|
|
||||||
|
import { Card, Button, CardContent, CardActions, Typography, TextField, Grid } from "@material-ui/core";
|
||||||
|
|
||||||
import showMessage from "../Toast.js"
|
import showMessage from "../Toast.js"
|
||||||
|
|
||||||
class LastFM extends Component {
|
class LastFM extends Component {
|
||||||
@ -64,30 +66,32 @@ class LastFM extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
const table =
|
const table =
|
||||||
<form onSubmit={this.handleSubmit}>
|
<div style={{maxWidth: '400px', margin: 'auto', marginTop: '20px'}}>
|
||||||
<table className="app-table max-width">
|
<Card align="center">
|
||||||
<thead>
|
<form onSubmit={this.handleSubmit}>
|
||||||
<tr>
|
<CardContent>
|
||||||
<th colSpan="2"><h1 className="ui-text center-text text-no-select">Last.fm Username</h1></th>
|
<Grid container spacing={3}>
|
||||||
</tr>
|
<Grid item className="full-width">
|
||||||
</thead>
|
<Typography variant="h4" color="textPrimary">Last.fm Username</Typography>
|
||||||
<tbody>
|
</Grid>
|
||||||
<tr>
|
<Grid item className="full-width">
|
||||||
<td className="ui-text center-text text-no-select">Username:</td>
|
<TextField
|
||||||
<td><input
|
label="last.fm Username"
|
||||||
type="text"
|
variant="outlined"
|
||||||
name="current"
|
onChange={this.handleChange}
|
||||||
value={this.state.lastfm_username}
|
name="current"
|
||||||
onChange={this.handleChange}
|
value={this.state.lastfm_username}
|
||||||
className="full-width" /></td>
|
className="full-width" />
|
||||||
</tr>
|
</Grid>
|
||||||
<tr>
|
</Grid>
|
||||||
<td colSpan="2"><input type="submit" style={{width: "100%"}} className="button" value="save" /></td>
|
</CardContent>
|
||||||
</tr>
|
<CardActions>
|
||||||
</tbody>
|
<Button type="submit" variant="contained" className="full-width">Save</Button>
|
||||||
</table>
|
</CardActions>
|
||||||
</form>;
|
</form>
|
||||||
|
</Card>
|
||||||
|
</div>;
|
||||||
|
|
||||||
const loadingMessage = <p className="center-text text-no-select">Loading...</p>;
|
const loadingMessage = <p className="center-text text-no-select">Loading...</p>;
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { BrowserRouter as Route, Link } from "react-router-dom";
|
import { Route, Link, Switch } from "react-router-dom";
|
||||||
|
import { Paper, Tabs, Tab} from '@material-ui/core';
|
||||||
|
|
||||||
import ChangePassword from "./ChangePassword.js";
|
import ChangePassword from "./ChangePassword.js";
|
||||||
import SpotifyLink from "./SpotifyLink.js";
|
import SpotifyLink from "./SpotifyLink.js";
|
||||||
@ -7,19 +8,41 @@ import LastFM from "./LastFM.js";
|
|||||||
|
|
||||||
class Settings extends Component {
|
class Settings extends Component {
|
||||||
|
|
||||||
|
constructor(props){
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
tab: 0
|
||||||
|
}
|
||||||
|
this.handleChange = this.handleChange.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange(e, newValue){
|
||||||
|
this.setState({
|
||||||
|
tab: newValue
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ul className="navbar" style={{width: "100%"}}>
|
<Paper>
|
||||||
<li><Link to={`${this.props.match.url}/password`}>Password</Link></li>
|
<Tabs
|
||||||
<li><Link to={`${this.props.match.url}/spotify`}>Spotify</Link></li>
|
value={this.state.tab}
|
||||||
<li><Link to={`${this.props.match.url}/lastfm`}>Last.fm</Link></li>
|
onChange={this.handleChange}
|
||||||
</ul>
|
indicatorColor="primary"
|
||||||
|
centered
|
||||||
<Route path={`${this.props.match.url}/password`} component={ChangePassword} />
|
width="50%"
|
||||||
<Route path={`${this.props.match.url}/spotify`} component={SpotifyLink} />
|
>
|
||||||
<Route path={`${this.props.match.url}/lastfm`} component={LastFM} />
|
<Tab label="Password" component={Link} to={`${this.props.match.url}/password`} />
|
||||||
|
<Tab label="Spotify" component={Link} to={`${this.props.match.url}/spotify`} />
|
||||||
|
<Tab label="Last.fm" component={Link} to={`${this.props.match.url}/lastfm`} />
|
||||||
|
</Tabs>
|
||||||
|
</Paper>
|
||||||
|
<Switch>
|
||||||
|
<Route path={`${this.props.match.url}/password`} component={ChangePassword} />
|
||||||
|
<Route path={`${this.props.match.url}/spotify`} component={SpotifyLink} />
|
||||||
|
<Route path={`${this.props.match.url}/lastfm`} component={LastFM} />
|
||||||
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
const axios = require('axios');
|
const axios = require('axios');
|
||||||
|
|
||||||
|
import { Card, Button, CardContent, CardActions, Typography } from "@material-ui/core";
|
||||||
|
|
||||||
import showMessage from "../Toast.js"
|
import showMessage from "../Toast.js"
|
||||||
|
|
||||||
class SpotifyLink extends Component {
|
class SpotifyLink extends Component {
|
||||||
@ -29,25 +31,17 @@ class SpotifyLink extends Component {
|
|||||||
|
|
||||||
render(){
|
render(){
|
||||||
const table =
|
const table =
|
||||||
<table className="app-table max-width">
|
<div style={{maxWidth: '400px', margin: 'auto', marginTop: '20px'}}>
|
||||||
<thead>
|
<Card align="center">
|
||||||
<tr>
|
<CardContent>
|
||||||
<th><h1 className="ui-text center-text text-no-select">Spotify Link</h1></th>
|
<Typography variant="h4" color="textPrimary">Admin Functions</Typography>
|
||||||
</tr>
|
<Typography variant="body2" color="textSecondary">Status: { this.state.spotify_linked ? "Linked" : "Unlinked" }</Typography>
|
||||||
</thead>
|
</CardContent>
|
||||||
<tbody>
|
<CardActions>
|
||||||
<tr>
|
{ this.state.spotify_linked ? <DeAuthButton /> : <AuthButton /> }
|
||||||
<td className="ui-text center-text text-no-select">
|
</CardActions>
|
||||||
Status: { this.state.spotify_linked ? "Linked" : "Unlinked" }
|
</Card>
|
||||||
</td>
|
</div>;
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
{ this.state.spotify_linked ? <DeAuthButton /> : <AuthButton /> }
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>;
|
|
||||||
|
|
||||||
const loadingMessage = <p className="center-text text-no-select">Loading...</p>;
|
const loadingMessage = <p className="center-text text-no-select">Loading...</p>;
|
||||||
|
|
||||||
@ -56,11 +50,11 @@ class SpotifyLink extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function AuthButton(props) {
|
function AuthButton(props) {
|
||||||
return <a className="button full-width" href="/auth/spotify">Auth</a>;
|
return <Button component='a' variant="contained" className="full-width" href="/auth/spotify">Auth</Button>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DeAuthButton(props) {
|
function DeAuthButton(props) {
|
||||||
return <a className="button full-width" href="/auth/spotify/deauth">De-Auth</a>;
|
return <Button component='a' variant="contained" className="full-width" href="/auth/spotify/deauth">De-Auth</Button>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SpotifyLink;
|
export default SpotifyLink;
|
Loading…
Reference in New Issue
Block a user