diff --git a/app.js b/app.js index 434b9c0..4cb22b7 100644 --- a/app.js +++ b/app.js @@ -91,9 +91,16 @@ app.get('/callback', function (req, res) { refresh_token = body.refresh_token; // we can also pass the token to the browser to make requests from there - res.send('') + res.redirect('/#' + + querystring.stringify({ + access_token: access_token, + refresh_token: refresh_token + })); } else { - res.send('') + res.redirect('/#' + + querystring.stringify({ + error: 'invalid_token' + })); } }); } diff --git a/public/index.html b/public/index.html index 1911af9..905efbe 100644 --- a/public/index.html +++ b/public/index.html @@ -9,30 +9,8 @@ - - -
+
diff --git a/public/script.js b/public/script.js index f1e66e2..5c03bea 100644 --- a/public/script.js +++ b/public/script.js @@ -1,9 +1,36 @@ 'use strict'; +/** + * Obtains parameters from the hash of the URL + * @return Object + */ +function getHashParams() { + var hashParams = {}; + var e, r = /([^&;=]+)=?([^&;]*)/g, + q = window.location.hash.substring(1); + while (e = r.exec(q)) { + hashParams[e[1]] = decodeURIComponent(e[2]); + } + return hashParams; +} + + var data = [ - {id: 1, name: "Mine"}, - {id: 2, name: "Other"}, - {id: 3, name: "A third"} + { + href: "https://api.spotify.com/v1/users/wizzler/playlists/53Y8wT46QIMz5H4WQ8O22c", + id: "53Y8wT46QIMz5H4WQ8O22c", + name: "Wizzlers Big Playlist", + owner: { + id: "wizzler" + } + }, { + href: "https://api.spotify.com/v1/users/wizzlersmate/playlists/1AVZz0mBuGbCEoNRQdYQju", + id: "1AVZz0mBuGbCEoNRQdYQju", + name: "Another Playlist", + owner: { + id: "wizzlersmate" + } + } ]; var dups = [ @@ -69,35 +96,49 @@ var Duplicate = React.createClass({ var DuplicatesBox = React.createClass({ render: function () { - var duplicates = this.props.data.map(function (duplicate) { + if (this.props.data && this.props.data.length > 0) { + var duplicates = this.props.data.map(function (duplicate) { + return ( + + ); + }); return ( - +
+ {duplicates} +
); - }); - return ( -
- {duplicates} -
- ); + } + else { + return ( +

No duplicate found

+ ); + } } }); -var Playlist = React.createClass({ - render: function () { - return ( - {this.props.name} - ); - } -}); - var PlaylistBox = React.createClass({ + getInitialState: function () { + return { + currentId: null + }; + }, + clickOnItem: function (id, uid) { + this.setState({currentId: id}); + this.props.handleClick(id, uid); + }, render: function () { - var playlists = this.props.data.map(function (playlist) { - return ( - - ); - }); + var currentId = this.state.currentId; + var playlists; + if (this.props.data) { + playlists = this.props.data.map(function (pl) { + var id = pl.id; + var classes = "list-group-item" + (currentId == id ? " active" : ""); + return ( + {pl.name} + ); + }, this); + } return (
{playlists} @@ -107,55 +148,207 @@ var PlaylistBox = React.createClass({ }); var DuplicateFinderBox = React.createClass({ + getInitialState: function () { + return { + currentId: null, + currentUId: null, + dups: null, + loading: false + }; + }, + handlePlaylistClick: function (id, uid) { + this.setState({ + currentId: id, + currentUId: uid, + loading: true + }); + var self = this; + + $.ajax({ + url: "/pl/" + uid + "/" + id, + data: { + 'access_token': self.props.auth.access_token + }, + success: function (data) { + var dups = data.data; + self.setState({ + dups: dups, + loading: false + }); + }, + error: function (xhr, response, err) { + console.error(response, err); + } + }); + }, render: function () { + var duplicates =

Loading...

; + if (!this.state.loading) { + duplicates = ; + } return (

Playlists

- +

Duplicates

- + {duplicates}
) } }); -ReactDOM.render( - , - document.getElementById('content') -); - var Authenticate = React.createClass({ + logout: function () { + this.props.refreshAuth(null, null); + }, + refreshToken: function (event) { + event.preventDefault(); + var self = this; + $.ajax({ + url: '/refresh_token', + data: { + 'refresh_token': self.props.auth.refresh_token + }, + success: function (data) { + self.props.refreshAuth(data.access_token, self.props.auth.refresh_token); + }, + error: function (xhr, status, err) { + console.error(status, err); + } + }); + }, render: function () { - var accessToken = ""; - if (accessToken == "") { - return ( + var auth; + if (this.props.auth.access_token == null) { + auth = ( ); } else { - return ( + auth = ( ); } + + return ( + + ); + } +}); + +var App = React.createClass({ + getInitialState: function () { + var params = getHashParams(); + var access_token = params.access_token || null; + var refresh_token = params.refresh_token || null; + + return { + access_token: access_token, + refresh_token: refresh_token, + playlists: null + }; + }, + getPlaylists: function () { + var self = this; + $.ajax({ + url: '/get_playlists', + data: { + 'access_token': this.state.access_token + }, + success: function (data) { + var pl = data.data; + self.setState({ + playlists: pl + }); + }, + error: function (xhr, response, err) { + console.error(response, err); + } + }); + }, + isLoggedIn: function () { + return !(this.state.access_token == null && this.state.refresh_token == null); + }, + refreshAuth: function (access, refresh) { + if (access == null && refresh == null) { + this.setState({ + access_token: access, + refresh_token: refresh, + playlists: null + }); + } + else { + this.setState({ + access_token: access, + refresh_token: refresh + }); + this.getPlaylists(); + } + }, + componentDidMount: function () { + if (this.state.access_token) { + this.getPlaylists(); + } + }, + render: function () { + var auth = { + access_token: this.state.access_token, + refresh_token: this.state.refresh_token + }; + var content =

Please log in with Spotify :)

+ if (this.isLoggedIn()) { + content = ( + + ); + } + + return ( +
+ +
+ {content} +
+
+ ); } }); ReactDOM.render( - , - document.getElementById('authentication') + , + document.getElementById('content') );