This application allows you to manage your music playlists on Spotify and simulates playing tracks queue. It is deployed on Github and is accessible on the following urls:
- http://nikola.pejoski.com/mysp/dist - production instance (minified and concatenated js)
- http://nikola.pejoski.com/mysp/src - development instance (uses the source files)
Following are instructions how to install the application locally.
clone this repository https://github.com/npejo/mysp.git
There are two configuration files for the application, one for development
and one for production
environment.
They are set in app-config.dev.js and app-config-prod.js respectively.
Each of the configurations can use different host
, port
, and Spotify client id
.
Set the client id
of the Spotify application that you are going to use and make sure that you have listed
valid Redirect URIs in the application profile.
Example:
For the default development
web server configuration, the redirect uri should be:
http://localhost:8888/auth-callback.html
For the default production
web server configuration, the redirect uri should be:
http://localhost:8484/auth-callback.html
You can run this application locally using grunt
or by deploying the code to running web server.
Make sure that you have installed grunt-cli
:
npm install -g grunt-cli
Install the development dependencies listed in package.json
npm install
To run the application in dev
mode run:
grunt server:dev
this will start web server listening on the port set in connect:dev
section in Gruntfile.js
and will open web browser pointing to the host
url set in app-config-dev.js
.
To change the host and port information these are the two places that should be updated.
In dev
mode the application is served from the src
folder, using the development source files.
To run the application in prod
mode run:
grunt server:prod
this will start web server listening to the port set in connect:prod
section in Gruntfile.js
and will open web browser pointing to the host
url set in app-config-prod.js
.
In prod
mode the application is served from the dist
folder, using minified and concatinated javascript files.
To re-build the code in dist
folder run:
grunt build
The testing environment is setup with mochajs
, chai
and sinonjs
.
In interest of time I just wrote only few unit tests for one file.
Run tests using:
grunt test
Copy the content of the src
folder somewhere on the web server and update the host
in
app-config.dev.js.
Copy the content of the dist
folder somewhere on the web server and update the host
in
app-config.js.
src
- contains the source filesdist
- generated folder withgrunt build
, contains copy of the source files with minified and concatenated javascripttests
- unit tests
index.html
- application entry point. Loads all dependencies and bootstraps the applicationauth-callback.html
- file specified as redirect uri for the oauth authentication with Spotify. The uri to this file should be specified in the list of redirect uris in the configuration of the Spotify App used for the authentication.
The application is organized using the following logical entities:
utils
- generic helper methods used through the whole applicationmodels
- handle the data and actions related to one segment of the application (User, Playlist, Queue...)views
- handle the rendering and DOM interactions of application sections
File by file description:
app-config-dev.js
- development configurationapp-config-prod.js
- production configurationapp-initialize.js
- setup namespace for the applicationapp-run.js
- create instances of all application level models, check authentication and bootstrap the applicationapp-views-config.js
- configure the views with all its subviews (create instances and pass dependencies)
Auth.js
- Manage authentication information in localStorage and handle login, logout actionsEvents.js
- Application level events subscribing and publishing. Allows interaction between views with custom eventsUser.js
- Handle data related to logged in user. Load his profile and playlists.Playlist.js
- Handle data for single playlist and manage the CRUD over the tracks in itQueue.js
- Handle the actions related to the current playing queue. Read/Write to localStorageSearch.js
- Manage search requests. Caches the loaded results for the last search query. The results list is refreshed when the query is changed.
ajax.js
- Helper methods that simplify creating XHR (ajax) requestsquerystring.js
- Helper methods for parsing simple querystring into object and object to querystringtime.js
- Helper method for parsing milliseconds timestamp in hh:mm:ss format
CoreView.js
- Parent view extended by all views (except TracksTableView) in the application. Implements the methods that are common for all viewsLoginView.js
- Render the login pageLoggerView.js
- Display info and error messages in the header section for all "important" eventsPlayerView.js
- Render and manage the actions of the player control. It is always visible in the header section.AppView.js
- Root view of the application. Binded to the app root element and renders the layout of the app sections: Header, Menu, Content.menu/MenuView.js
- Render the main menu by rendering the subviews:PlaylistMenuView.js
andSearchMenuView.js
. The search menu section is hidden with the user is on the search page.content/ContentView.js
- Depending on the#page=<page-value>
in url renders the appropriate viewscontent/common/TracksTableView.js
- Renders table for given list of tracks on input. It is reused on: Playlist, Search and Queue pages.content/search/SearchPageView.js
- Render the search page. It has two sections/subviews:SearchFormView.js
andSearchResultsView.js
content/playlist/PlaylistPageView.js
- Render the playlist page. It has two sections/subviews:PlaylistDetailsView.js
andPlaylistTracksView.js
content/queue/QueuePageView.js
- Render the content of the current playing queue. It has one subview:QueueTracksView.js
Potential improvements of the application
- In this version there is no pagination for the playlists.
- The management of view templates should be updated. Parsing them as inline strings is fast for development but reduces readability and scalability.
Thank you for challenging me to code this project using vanilla Javascript! It was fun week for me.