GithubHelp home page GithubHelp logo

nwelchr / bop Goto Github PK

View Code? Open in Web Editor NEW
9.0 0.0 1.0 61.91 MB

A single-page music-streaming app inspired by Spotify.

Home Page: http://bop-aa.herokuapp.com/

HTML 2.29% CSS 12.94% JavaScript 51.39% Ruby 32.84% CoffeeScript 0.54%

bop's Introduction

Bop

Live Version

Table of Contents

Bop is a simple single-page Spotify clone. It allows users to interact with playlists, stream music, explore new music, and follow other users and artists.

Project Design̨

Bop was built over a 2-week period in April 2018 as a part of App Academy's Software Engineering Bootcamp.

How It Works

Bop is built on a Rails 5 backend, connected to PostgresSQL for database management. Communication between frontend and backend was made through Fetch AJAX requests. Responses are served up by JBuilder and operated upon and displayed by React and Redux. The React Player API was used to have greater control over music.

Summary of Features

  • RESTful
    • Data resources are generally accessed via standard HTTP requests to an API endpoints. The few nonRESTful routes were done for the sake of grouping certain actions (follows and playlist saves) with their respective controllers to better organize routes.
  • Secure
    • User authentication is built from the ground up and maintained by in-app BCrypt password hashes as well as SecureRandom session key management.
  • Dynamic
    • Single-page application han̨dles all UI actions without redirecting to new links or re-rendering material. State įs managed and dynamically updated using Redux.

Specific Features

React Player

The meat of my application is in the implementation of React Player. Using refs to store a reference to the DOM object <ReactPlayer /> while managing local media state as well as global state (passing around variables such as currentSong and dispatchable actions such as playSong()), I was able to create a player that runs smoothly without pauses or unwanted behavior regardless of user interaction.

alt text

Followable

  • One feature I was excited about implementing was the many-to-many associations between users and other users, playlists, and artists through follows. I created model and controller Concerns that allowed me to apply the same code for all my follows features. Followable also allowed me to create powerful associations in my database:
module Followable
  extend ActiveSupport::Concern

  included do
    has_many :follows, as: :followable, dependent: :destroy
    has_many :followers, through: :follows, source: :user
  end

end

class Follow < ApplicationRecord

    belongs_to :followable, polymorphic: true 
    belongs_to :user

end

class User < ApplicationRecord
  include Followable
  
  has_many :followings, foreign_key: :user_id, class_name: 'Follow'
  has_many :followed_users, through: :followings, source: :followable, source_type: 'User'
  has_many :followed_playlists, through: :followings, source: :followable, source_type: 'Playlist'
  has_many :followed_artists, through: :followings, source: :followable, source_type: 'Artist'

end

I also add custom model-level validations to enhance user experience and prevent unwanted behavior:

class Follow < ApplicationRecord

    validate :user_cannot_follow_own_playlist
    validate :user_cannot_follow_self

    def user_cannot_follow_own_playlist
        if user_is_playlist_creator
            errors.add(:user, "cannot follow own playlist")
        end
    end

    def user_cannot_follow_self
        if user_is_self
            errors.add(:user, "can't follow themself")
        end
    end

    private

    def user_is_playlist_creator
        self.followable_type == 'Playlist' && Playlist.find(self.followable_id).creator_id == self.user_id
    end

    def user_is_self
        self.user_id == self.followable_id && self.followable_type == 'User'
    end
    
end

Doing so allowed me to create a multi-purpose set of front-end actions that handled type parsing for me:

// follow actions
export const follow = (type, id) => (dispatch) => (
    APIUtil.follow(type, id).then(response => dispatch(receiveFollow(response))
)

// session reducers on receive/removal of follow
case RECEIVE_FOLLOW:
  newState = merge({}, oldState);
  tableized = `${action.payload.followable_type.toLowerCase()}s`;
  newState.currentUser[`followed_${tableized}`].push(action.payload.followable_id);
  return newState;       

Search

  • Searches are fired automatically through a callback in a timeout function, waiting for users to finish typing to save on unnecessary queries the user doesn't want.

alt text

CSS Grid

  • Using CSS Grid granted me complete control over position and sizing of containers and made left-floating of music index items while center-justifying seamless.

alt text

Additional Features (to be implemented)

  • Tracklists: Users will be able to skip through songs using media player buttons. DONE
  • Shuffle: Users will be able to shuffle the current tracklist (album, playlist, etc.). DONE
  • Dynamic Image Creation: playlist covers will be generated as a collage of album covers. DONE
  • N + 1 Queries and unnecessary fetching will be eliminated. DONE
  • Queue: Users will be able to add songs to a 'next song' queue.
  • Dominant colors from album covers will be extracted to enhance user experience.
  • Users will be able to upload profile photos.
  • Search algorithms will fetch songs by relevance.
  • Settings page:
    • Language support (French, Spanish, etc.)
    • Color schemes (Dark, Light, and Funky themes)
    • Play button will optionally pulse to the beat of the song
  • See friends who are currently online
    • 'Currently listening to' pane

bop's People

Contributors

nwelchr avatar

Stargazers

Mark Puckett avatar Alizeh Iqbal avatar  avatar Jonathan avatar Cheng Tsai avatar Alexandra Savramis avatar Travis Tillotson avatar Atai Chynaliev avatar Yangchen Shen avatar

Forkers

tarsbase

bop's Issues

MVP List

  • Should have 7 MVPs.
    • 3 of those are User Auth, Heroku, and Production README.
    • The other 4 are from the MVP List
  • Contains a description sentence of the app
  • At least one CRUD feature, which states what CRUD operations are planned (creation, reading, updating, deletion)
  • Estimates how long it will take the code each MVP
  • Correctly formatted
    • MVPs are listed in an ordered list
    • Each MVP is broken down into bullet points

Sample State Shape

  • State shape is flat!
  • State's keys are camelCased
  • All keys within the values in the state are accessible in the schema (Ex: if you create a img_url key in the state, make sure your database also has a column that contains an img_url)
  • Correctly formatted
    • Sample state is rendered with 3 back ticks before and after. This will display the state as a code block instead of a giant line of text
    • Top level slices
      • entities
      • session
      • errors (here or in ui)
      • ui (if needed)
    • Should NOT have nested slices, aka comments inside of posts
      • Some info from other tables is ok, for instance:
        • the author username and imageurl for a post. basically any info that the user can't change
        • like count and a boolean on whether the user likes the post instead of a likes slice

MVP: Browse with Continuous Play

  • Backend: controller, views
  • Redux Loop: ajax, actions, reducer
  • Presentational Components
  • Styling
  • Smooth, bug-free navigation
  • Adequate and appropriate seeds

Problems I'm still working through:

  • Hitting play button upon entering app (i.e. without a currentSong) breaks the application

Not (yet) implemented:

  • Artists and Albums (backend/seeding done, just need to move to frontend)
  • Play first song from a playlist and pause/play by clicking on play button (songs array is messed up)
  • Next/previous songs (again, songs array messed up)
  • Volume bar icon only changes on toggling mute, not by seeking on the volume bar
  • Pause button persists after a song is finished if it's not set to loop

MVP: Song and Playlists

  • Backend: controller, views
  • Redux Loop: ajax, actions, reducer
  • Presentational Components
  • Styling
  • Smooth, bug-free navigation
  • Adequate and appropriate seeds

Problems I'm still working through:

  • Routing after successfully adding/removing song from playlist

Not implemented:

  • Modal to Add Playlist from the Add Song To Playlist modal and automatically save song
  • User's collection

MVP: Following Playlists/Users/Artists

  • Backend: controller, views
  • Redux Loop: ajax, actions, reducer
  • Presentational Components
  • Styling
  • Smooth, bug-free navigation
  • Adequate and appropriate seeds

Things you should check out:

  • User, artist, and playlist show pages have responsive follow and unfollow buttons.
  • Backend and frontend restrictions on 1.) a user following themselves and 2.) a user following their own playlist.
  • User show pages show the user's playlists, including 1.) playlists the user has created and 2.) playlists the user has followed.
  • User show pages also have tabs showing the users that follow them, as well as one for the users/artists that that user follows.
  • Artist show pages display their number of followers.

Mini Bonus Feature Explore:

  • Homepage shows all the playlists that don't belong to the user. Not that incredible but it kinda mimics the idea of an explore page.

Routes

  • Routes accurately reflect MVPs and Component Hierarchy
  • Covers the frontend functionality of the site through routes that match to the wireframes
  • Contains the following sections: HTML, API Endpoints(Backend), and Frontend Routes
  • Each route has a description
  • API Endpoint routes contains wildcard variables written in snake_case
  • Frontend routes contains wildcard variables written in camelCase
  • Routes does not contain superfluous routes
  • Have API routes that will allow the front end to get all info it needs and does not have unneeded routes:
    • probably doesn't need a GET likes api endpoint bc that info comes through the post show
  • Correctly formatted
    • Routes are displayed with inline coding text (backticks)

MVP: Search

  • Backend: controller, views
  • Redux Loop: ajax, actions, reducer
  • Presentational Components
  • Styling
  • Smooth, bug-free navigation
  • Adequate and appropriate seeds

Not (yet) implemented:

  • Artists and Albums show pages (working on it now)
  • Song index and show pages (working on it now)
  • Users (but that's part of my next MVP)

MVP: User Auth

  • Backend: DB, model, controller, views
  • Redux Loop: ajax, actions, reducer
  • Presentational Components
  • Styling
  • Smooth, bug-free navigation
  • Adequate and appropriate seeds

DB Schema

  • Contains correct datatypes
  • Contains appropriate constraints/details
    • primary key
    • not null
    • unique
    • indexed
    • foreign key
  • Contains bullet points after the table that state which foreign keys will reference to which table, or references to the associations which will be made
  • Correctly formatted
    • schema is written in a table format
    • the table's name are back_ticked
    • the table header column names are bolded
    • columns names are lowercased and snaked_cased and back_ticked

Wire Frames and Component Hierarchy

  • All routes listed in the routes wiki page is also listed in the component hierarchy
  • Each component, if necessary, has route, state, and other components it renders example
  • Necessary components are wrapped in a container
  • Correctly formatted
    • Bullet point hierarchy
    • Component names are displayed with inline coding text (backticks)
  • Wireframes included
  • Every component listed in the component hierarchy wiki page has at least one wireframe
  • Every MVPs listed on the MVP wiki page has at least one wireframe
  • Every route listed on the route wiki page has at least one wireframe
  • Contains Containers
  • Contains Lists
  • Contains ListItems
  • Correctly formatted
    • Wireframe images display on the page
    • Every wireframe has a header title

Wiki Home Page

  • Is the first page you see upon entering the wiki
  • Contains a welcome message
  • Contains a link/placeholder for a link to the live page
  • All links in the right sidebar should contain each wiki page and link to the correct page
  • Correctly formatted
    • each wiki page is listed in bullet points
    • all links route the correct page

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.