Code Monkey home page Code Monkey logo

prodigy's Introduction

Prodigy

LIVE SITE

Prodigy is a single-page web app clone of Genius.com. Prodigy allows users to add tracks, annotate lyrics, and comment and vote on annotations. Prodigy is built with Ruby on Rails on the backend and React.js / Redux on the front end.

Features & Implementation

User Authorization

Users can sign up and login on Prodigy. A custom authorization is built in Rails utilizing the BCrypt Gem.

sign_up

Tracks

Creating Tracks

Users can create tracks by clicking Create Track in the nav bar. Tracks require lyrics, an artist, desciption, and title. Optionally, a user can add album art by uploading an image. To keep pressure off of the server, AWS S3 is utilized to store the images.

new_track

Viewing Tracks

Clicking on or searching for a track displays the track page, showcasing the lyrics, album art and other information uploaded by the user.

track_show

Generating Lyrics

To generate the annotated lyrics, I wrote an algorithm that iterates through an array of annotations that stores start and end indices. The algorithm creates spans from the lyrics, splicing appropriately to obtain a collection of stylized spans.

generateLyricsAnnotations() {
  let lyricsDiv = [];
  let startIdx = 0;
  this.props.track.annotations.forEach((annotation, idx) => {
    lyricsDiv.push(<span key={idx} className="non-annotated-lyric">
      { this.props.track.lyrics.slice(startIdx, annotation.start_idx) }
    </span>);
    lyricsDiv.push(
      <span key={idx + 1000} className="annotated-lyric" onClick={ this.handleAnnotationClick.bind(null, annotation) }>
        {this.props.track.lyrics.slice(annotation.start_idx, annotation.end_idx) }
      </span>);
    startIdx = annotation.end_idx;
  });

  lyricsDiv.push(<span key={2000} className="non-annotated-lyric">
    { this.props.track.lyrics.slice(startIdx, this.props.track.lyrics.length) }
  </span>);

  return lyricsDiv;
}

Making Annotations

Users can create annotations by choosing a track and highlighting text. The user must be signed in to do so, so don't forget! After highlighting, make an annotation and contribute to Prodigy's vast database of lyrical knowledge!

new_annotation

new_annotation_2

Annotation Creation Algorithm

Using document.getSelection(), this algorithm extracts the lyrics that the user has highlighted. First, it checks whether or not the selection is valid by checking if the anchorNode (click-down node) is equal to the focusNode (click-up node) and also validates that the highlighted node is not already an annotated-lyric. Since each annotation is its own span, the algorithm then adds the innerHTML length of each previousSibling to generate an accurate index within the lyrics.

handleSelection(e){
  const selection = document.getSelection().toString();
  if (selection.length > 0 && this.props.currentUser){
    //Ensures that you cannot annotate over existing annotations
    if (
      document.getSelection().anchorNode !==
      document.getSelection().focusNode ||
      document.getSelection().anchorNode.parentElement.className === 'annotated-lyric'){
      return;
    }
    //Cancels your annotation if you click again
    if (this.state.annotating){
      this.setState({annotating: false, annotationIndices:[], body:"", selectedAnnotation:null, location: null, startLoc: null, endLoc: null});
      return;
    }ร‚
    let startIdx = document.getSelection().anchorOffset;
    let endIdx = document.getSelection().focusOffset;
    let span = document.getSelection().anchorNode.parentElement;

    //Allows users to highlight backwards
    if (startIdx > endIdx) {
      const temp = startIdx;
      startIdx = endIdx;
      endIdx = temp;
    }
    //Accounts for the lengths of the previous elements, ensuring accurate index within entire lyrics
    while (span.previousSibling) {
      startIdx += span.previousSibling.innerText.length;
      endIdx += span.previousSibling.innerText.length;
      span = span.previousSibling;
    }
    this.setState({annotating:true, annotationIndices:[startIdx, endIdx], endLoc: e.pageY});
  } else {
    this.setState({annotating:false, annotationIndices:[], selectedAnnotation:null, startLoc: null, endLoc: null});
  }
}

Viewing Annotations

After you create your annotation, you can view it by clicking on the newly highlighted lyrics. Your masterpiece will display on the side, where other users can comment and upvote!

show_annotation

Search

Users can search for songs utilizing the search bar on the top right of the header.

search

I wrote a simple query that filters tracks based on user input:

def filter
  @results = Track.where("title ~* ?", params[:query])
  render :index
end
handleSearch(e) {
  e.preventDefault();
  this.setState({query:e.currentTarget.value});
  const query = e.currentTarget.value ;
  if (query.length > 0){
    this.props.requestSearch(query);
  }
}

prodigy's People

Contributors

jnico810 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

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.