INF 133 - User Interaction Software - Fall 2018


A3: Spotify Browser in Angular and Express

Due Wednesday, November 14th, 4:00am

In this assignment, you’ll demonstrate your ability to (1) create an authentication and authorization flow to enable gathering data from an API, and (2) develop a frontend interface which displays the data. You’ll use Angular and Express to create a webpage and backend server to browse the music on Spotify, a popular music streaming app. Your backend server will handle authentication via OAuth and communicate with the Spotify API. Your page will support searching for artists, albums, and tracks and navigating between the three resources.

This assignment may be completed in pairs (exactly two students enrolled in the class) or individually. You may choose your own partner or use Slack to help find one. Because the assignment features build on top of one another, it is recommended that you pair program rather than distribute the assignment features. There is no grade benefit or penalty to completing the assignment individually.

By the end the of day on Saturday, October 3rd, please navigate to the “People” tab on Canvas to sign up for an A3 group. Do correspond with your partner while signing up for groups. If you’re the first member to join a group, please sign up for the next group that’s empty. Keep a note of the Assignment Group Number that you’ve signed up for and add it to your readme file.

You will not be able to swap to another group after the 3rd. If something happens after you sign up and you decide you're best off working alone (team conflicts, incompatible schedules, etc.), you can disband your group and let the course staff know. However, you will not be able to team up with someone else, even if they do not have a partner. You will need to complete the assignment alone.

Starter code

A starter repository is on GitHub Classroom.

Repository structure

The repository contains somewhere around 80 files. You will not need to edit most of them in this assignment. The repository contains two folders: webserver and client. webserver includes the Express/Node.js backend for communicating with the Spotify API. client includes the Angular frontend for browsing music.

In the backend (webserver folder), the files you should edit are:

  • routes/index.js: a JavaScript file where calls to the server are routed and requests to the Spotify API are made.
  • You should also create two files: client_secret.json and tokens.json. Both contain secret information, so they should not be committed to the repository and is therefore listed in the .gitignore file.

In the frontend (client folder), the files which need editing are all under the app folder. Within that folder, the files/subfolders you should edit are:

  • The six components in the components folder: about, carousel, carousel-card, search, track-list, and thermometer. Each component folder contains four files (*.component.css, *.component.html, *.component.ts, and *.component.spec.ts). Of those, all edits will be made in the .component.html and .component.ts files.
  • Three of the four components in the pages folder : album-page, artist-page, and track-page. home-page will not be edited. Again, all edits will be made in the .component.html and .component.ts files.
  • The one service in the services folder: spotify-service. All edits will be made in the .service.ts file, none in the .service.spec.ts file.
  • One of the six classes in the data folder: track-features.ts. The four other classes do not need to be edited.

You will also edit the readme.txt file in the root folder.

This assignment can be completed without writing any additional files or functions. But you may add a file or function if you want (such as to complete one of the bonus features).

Setting up your Workspace

Some of the packages/libraries depend on newer versions of Node JS.

Check what version of Node JS you have installed with node --version. If you installed Node JS before this class, make sure you've updated to at least 10, such as with nvm or downloading the latest version from the node website. If you installed Node during A2, you should not need to update, but it's probably worth checking the version number anyways.

There are no global dependencies required to run the Express webserver.

For the client, you will need to install Angular thourhg npm. To do this, you will install the Angular Command Line Interface (CLI) globally with npm install -g @angular/cli. The Angular project is already set up in the client folder, but the CLI is necessary to run the project.

You will also need to install the dependencies for both the webserver and the client. These dependencies are defined in each project's respective package.json files. cd into each respective project's folder and install the dependencies with npm install.

When installing, if you run into issues which look like "permission denied, try changing the permissions of the node_modules directory. If you are still having trouble, ask on Slack or talk to the course staff. It's important to try to get the setup working sooner rather than later, even if you do not plan on working on the assignment until close to the deadline.

Running the webserver

A Spotify Developer account is required to set up the Express webserver. Create a Spotify account or log in at https://developer.spotify.com/dashboard/ and follow the instructions to create a client id. Name the app whatever you'd like. For the App description, enter:

This App is used to create a music browser as part of a course assignment for IN4MATX 133, User Interface Software, at the University of California, Irvine.
Indicate that you are building a Website and are not developing a commercial application.

Once you have created your application, create a file in the webserver folder (not the routes folder), client_secret.json, with your consumer key and secret. It should be of the form:

{
 "client_id": "Your Client Key",
 "client_secret": "Your Client Secret"
} 

At this time, also create a placeholder file in the same folder for tokens.json. This file will later be overwritten once an access and refresh token have been retrieved. Your tokens.json file should be exactly:

{
 "access_token": null,
 "refresh_token": null
} 

To run the Express webserver, cd into the webserver folder and run npm start. This will start the webserver at localhost:8888. Be sure the dependencies have been installed first via npm install.

When you make a change to code in the webserver, you will have to end the running program and re-run it. End it by typing Ctrl-C into the command line and then re-running it with npm start.

Running the client

To run the Angular client, cd into the client folder and run ng serve. This will start the client at localhost:4200. Adding the --openflag will open it up in the browser. Be sure the dependencies have been installed first via npm install.

Any code changes will be automatically reloaded on the client.

Working in pairs

If you are completing the assignment in pairs, you should work in one shared GitHub repository. The easiest way to do this is to have one of you create the repository and add the other as a collaborator.

The downside of working in pairs is that you open yourself up to potential issues merging one person's code into another. Make sure you always update the version of the code on your computer prior to beginning work. This guide offers some suggestions for how to resolve potential conflicts which might arise. But more generally, we suggest that you complete this assignment via pair programming, alternating roles as drivers and navigators.

Using another framework

A few students have asked the course staff whether they can use another framework, such as React, to complete this assignment in order to pick up a new skill. While this is an option, you are required to get approval from the course staff prior to pursuing this option.We expect to only allow grant approval for students who have used Angular, React, or another framework already. The next assignment will implement a mobile app in Ionic, a framework which adds mobile components on top of the Angular framework. Weak Angular fundamentals could therefore cause problems later in the course. The final assignment will present another opportunity to use another web framework and will have fewer downstream consequences.

Should you choose to use another framework, it is done with the understanding that the course staff will not support you in learning the framework or debugging your code. The course staff will not be more lenient in grading or give any extra credit for using something not covered in the course. You are required to complete the same assignment, which will likely mean adapting the provided starter code to the new framework. Should you choose this path, you are on your own. Godspeed!

Please include in your readme.txt any information we would need in order to run your code.

Requirements

There are five parts to this assignment. The first two parts are the most challenging and worth the bulk of the assignment grade. The later parts use many of the same components, so once those are implemented the later parts become a matter of gluing them together. You can also optionally add any of a number of bonus features.

Webserver Authentication and Authorization (OAuth)

In this part, you will implement an OAuth flow to authenticate and authorize your webserver to access data from the Spotify API. This process occurs entirely in the webserver folder, where you will need to edit routes/index.js.

As described in lecture, OAuth consists of four steps:

  1. To request authorization, you will edit the /login route to make a request. The functions include some starter code for what scopes to request.
  2. To get the access token, you will edit the /callbackroute to exchange the returned code for an access token and a refresh token. The writeTokenFile function should be used to update the tokens.json file with the tokens. Saving the tokens in a file will prevent having to re-authenticate every time the webserver is restarted. The function takes in a callback, which will be called after the file is written.
  3. To make API requests, update the makeAPIRequest function to make a request to the Spotify API. The variable spotify_base_uri can be used to reference the base component of the URI, and the spotify_endpoint argument designates the endpoint for the request. The res argument can be used to return the response as JSON. A list of endpoints which call that function have already been created. These endpoints will access the desired resources from the spotify API and do not need to be edited.
  4. To refresh the access token, you will pdate the refresh function to use the refresh token to get a new access token. Again, save the response to the tokens.json file with the writeTokenFile function. Once this function is written, edit your makeAPIRequest function to check whether an Unauthorized status code (401) was returned. If it was, refresh the token and make the request again.

The first three parts are required to complete the rest of the assignment. If you are struggling to refresh the token, you can skip it and instead log back in whenever the access token expires.

It's easiest to debug this part of the assignment directly in the URL bar of the browser. To start the OAuth process, go to http://localhost:8888/login. Once set up, this page will redirect you to Spotify's authorization endpoint and kick off the OAuth flow. Since Express is running server-side JavaScript, any logged messages will be sent to your operating system console (e.g., Terminal on Mac or Command Prompt on Windows) rather than the browser console.

As you're debugging, you may encounter an error of the form "No default engine was specified and no extension was provided". This does not refer to an error in your oAuth code; all this means is that no webpage content was rendered. Keep looking in our oAuth code for other errors.

Once the oAuth flow is working, it can be started from the "login" button in the top-right of the Angular client. When the oAuth flow has completed, use res.redirect() in your express server to send the user back to the Angluar client (http://localhost:4200).

Spotify Browser Home Page

In this part, you will create a homepage to view some information about the logged in user's account. You will also create search requests to the Spotify API. As you get started with Angular, it may be helpful to review the code from the demo on October 29th or the lecture recording.

First, update the sendRequestToExpress function in the Spotify service to ask the Express webserver to make an API request to Spotify at the endpoint passed in. The endpoints should then return the appropriate data type for each API call.

Once API requests can be made via the Express server, edit the about component to call the endpoint created for the "about me" page when the load info button is clicked. To do so, you will need to inject the Spotify service you just edited. The Spotify API endpoint reference describes what this endpoint and other endpoints return. Update the variables in the component's .ts file and bind them to the appropriate places in the .html file. This will populate the left side of the home page with the logged in user's name, profile picture, and a link to open their profile on Spotify.com.

The right side of the page contains the search component. The search component contains an input and a select (dropdown) menu to declare what to search for. Bind the values in the component's model to the input and select controls. Bind the search button to a function which uses the Spotify service to have Express make the API request. You can also search online to learn how to trigger a search when a user presses "enter" in the input field or changes the dropdown menu. These two features are optional--you are only required to bind the search button. For simplicity, your code can assume that any search typed in is valid (e.g., returns at least one artist/track/album).

Map the response from Express into an array of the appropriate resource type--ArtistData, AlbumData, or TrackData. The constructor of each resource should automatically parse the dictionary values Spotify returns into an Object. For example, AlbumData loads the genres of the Album and creates an array with each of the artists on the album. Note that all three of these resource classes extend the ResourceData class, which parses some dictionary values common across all the resource types. You should not need to edit any of these four files; contact the course staff if a response parses differently than you would expect or causes an error.

Once the array of resources has been created, display the search results in either a carousel component (for artists or albums) or a track-list component (for tracks).

The carousel is implemented via a Bootstrap carousel. Edit the carousel component to create carousel-card components for each resource passed in. Additionally, edit the carousel-card component to link to the local URL for browsing the specific artist or album. Check the app router (app-routing.module.ts) to identify what the URL should be.

The track list is implemented in the track-list component. Edit the component to display each track in the response as a row in the component's table, displaying the track's index, name, duration, artist, and album. The component should support hiding the artist and/or album columns for the track when the hideArtist or hideAlbum variables are true.

Spotify Browser Artist Page

In this part, you will create a page to view some information about a searched-for or linked-to artist. You will update the artist-page component to do this. For simplicity, you can assume the id passed via the URL is always valid (e.g., always refers to an artist which exists in the Spotify API). The artist-page includes code for retrieving the artist's id from the URL.

Update the Artist Page to retrieve the basic information about the artist, their top tracks, their albums, and similar artists. The Express webserver has endpoints for each of these four requests. Update the component to display the information as described in the component's template. You will re-use the track-list and carousel components on this page.

Spotify Browser Album Page

In this part, you will create a page to view some information about a searched-for or lined-to album. You will update the album-page component to do this. For simplicity, you can assume the id passed via the URL is always valid (e.g., always refers to an album which exists in the Spotify API). The album-page includes code for retrieving the album's id from the URL.

Update the Album Page to retrieve the basic information about the album and it's tracks. The Express webserver has endpoints for each of these two requests. Update the component to display the information as described in the component's template. You will re-use the track-list component on this page.

Spotify Browser Track page

In this part, you will create a page to view some information about a searched-for or lined-to track. You will update the track-page component to do this. For simplicity, you can assume the id passed via the URL is always valid (e.g., always refers to a track which exists in the Spotify API). The track-page includes code for retrieving the track's id from the URL.

Update the Track Page to retrieve the basic information about the track and it's audio features. The Express webserver has endpoints for each of these two requests. Update the component to display the information as described in the component's template.

For this page, you will have to edit the thermometer component. The thermometer uses a Bootstrap progress bar to display the track's audio features. Note the component does not have any Input fields, so you will have to identify what fields you need and define them.

You should also edit the track-features class to use the chroma library to display the progress bar's color as a mix between two values depending on it's percent. The example mixes between red and green. You can choose whatever colors you like, so long as differences are visually distinct. HSL blending is recommended, as it more closely models how human vision blends colors.

Optional/Bonus Features

The five parts of the assignment create a tool for browsing the Spotify API. There are many ways of extending this browser, and we can offer a small amount of extra credit for implementing an extension or two. We’ve enumerated some potential extensions:

  • Moving the Express webserver to a publicly visible URL rather than running on localhost. One way of doing this would be to create a Heroku instance. Students can get a free Hobby-tier server on Heroku for two years. This guide may be helpful for deploying your heroku app.
  • The webserver for this assignment can only handle a single user because tokens are being saved in a JSON file with no user information. Use session middleware and an improved scheme for storing tokens to handle multiple users.
  • Adding a component which plays music for an Artist/Album/Track using Spotify's Web Playback SDK.

We are open to other suggestions for bonus features.

Submitting

Your code repository on GitHub Classroom is your submission. The service will take the latest snapshot of your repository as your submission. Any commits made after the deadline are considered late and are subject to the course's late policy.

Please update your readme.txt with how long the assignment took, who or what online resources you consulted with, any bonus features you added, and anything else we should know. If the assignment was completed in a pair, the readme should list names/emails/ids of both students. Only one submission needs to be made, however.

You may use up to two late days on this assignment. Please indicate whose late day(s) you are using in your readme. If you completed the assignment in a pair, the late day(s) can be from either of the pair's allowance, but must be divided as whole days. For example, one day from student A and one day from student B are allowed for a total of two late days. Two days from student A and zero from student B is also allowed. One day from student A and zero days from student B is also allowed (for a total of one late day). 12 hours from student A and 12 hours from student B is not allowed. One day from student A and two days from student B is also not allowed.

Because many people will complete this assignment in pairs, you are also required to complete a short evaluation on Canvas signifying how work was distributed. The survey is available at https://canvas.eee.uci.edu/courses/11457/quizzes/48512. Please fill out the survey even if you worked alone.

Grading

This assignment will be graded on a scale of 10 points, broken down as follows:

  • Webserver Authentication and Authorization (3 points)
  • Spotify Browser Home Page (3 points)
  • Spotify Browser Artist Page (2 points)
  • Spotify Browser Album Page (1 point)
  • Spotify Browser Track Page (1 point)

Each bonus feature completed will earn you 1 point of extra credit. However, you can only earn a maximum of 2 points this way (e.g., no points given for beyond two bonus features). The maximum grade for this assignment is therefore 12/10.

The course staff reserves the right to redistribute, penalize, or award bonus points to one or both students in situations where work was not distributed equitably among partnerships.

In prior courses, you've been asked to follow good principles for indentation, naming variables, commenting, etc. We expect you to do the same in this course, but aim to avoid being draconian in our enforcement of these principles. Egregiously poor formatting, completely uncommented code, etc. may incur a small penalty (e.g., -1 point), but we expect this to be rarely applied.