Skip to content

Commit

Permalink
Integrate Apple Music API to fetch and play songs
Browse files Browse the repository at this point in the history
  • Loading branch information
avvazana committed Dec 23, 2018
1 parent ba8809f commit 7bb40b1
Show file tree
Hide file tree
Showing 51 changed files with 2,353 additions and 121 deletions.
1,000 changes: 1,000 additions & 0 deletions 1-1000.txt

Large diffs are not rendered by default.

Binary file added app/assets/images/spoofifyIcon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/javascripts/.bundle.js 2.map.icloud
Binary file not shown.
1 change: 0 additions & 1 deletion app/assets/javascripts/bundle.js 2.map

This file was deleted.

1 change: 1 addition & 0 deletions app/assets/javascripts/bundle.js 3.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions app/assets/javascripts/bundle.js 4.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions app/assets/javascripts/bundle.js 5.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions app/assets/javascripts/bundle.js 6.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions app/assets/javascripts/bundle.js 7.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions app/assets/javascripts/bundle.js 8.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions app/assets/javascripts/bundle.js 9.map

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions app/models/artist.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ class Artist < ApplicationRecord
has_many :songs,
through: :song_artists,
source: :song

has_many :albums,
through: :songs,
source: :album
end
5 changes: 4 additions & 1 deletion app/views/api/artists/show.json.jbuilder
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
json.songs do
@albums.songs.each do |song|
@artist.songs.each do |song|
json.set! song.id do
json.extract! song, :id, :title
json.trackUrl url_for(song.track)
json.photoUrl url_for(song.album.photo)
json.album song.album.title
end
end
end

json.@artist do
json.extract! @artist, :id, :name, :song_ids
json.photoUrl url_for(@artist.photo);
json.album_ids @artist.albums.pluck(:id)
end
5 changes: 1 addition & 4 deletions app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet">

<link href="https://fonts.googleapis.com/css?family=Poppins|Raleway" rel="stylesheet">

<link rel="shortcut icon" type="image/png" href="<%= image_url('spoofifyIcon.png') %>"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>

<%= csrf_meta_tags %>
Expand Down
Binary file added app/views/layouts/spoofifyIcon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added favicon.ico
Binary file not shown.
2 changes: 1 addition & 1 deletion frontend/actions/album_actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const receiveAlbum = ({album, songs}) => {
};

export const fetchAlbums = (props) => dispatch => {

return (
APIUtil.fetchAlbums(props).then(
res => dispatch(receiveAlbums(res))
Expand Down
1 change: 0 additions & 1 deletion frontend/actions/artist_actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export const fetchArtists = (props) => dispatch => {
};

export const fetchArtist = (id) => dispatch => {

return (
APIUtil.fetchArtist(id).then(res => {
dispatch(receiveArtist(res));
Expand Down
19 changes: 10 additions & 9 deletions frontend/actions/search_actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,39 @@ export const RECEIVE_ALL_ALBUMS = 'RECEIVE_ALL_ALBUMS';
export const RECEIVE_ALBUM = 'RECEIVE_ALBUM';

export const requestAllAlbums = (searchQuery) => {

return (dispatch) => {

return SearchApiUtil.fetchAllAlbums(searchQuery)
.then(null,
(response) => {
dispatch(receiveAllAlbums(JSON.parse(response.responseText).results));
});
});
};
};

export const requestSingleAlbum = (searchQuery) => {
export const requestSingleAlbum = (id) => {

return (dispatch) => {
return SearchApiUtil.fetchSingleAlbum(searchQuery)

return SearchApiUtil.fetchSingleAlbum(id)
.then(null,
(response) => {
dispatch(receiveSingleAlbum(JSON.parse(response.responseText).results[0]));
dispatch(receiveSingleAlbum(JSON.parse(response.responseText).results));
});
};
};

export const receiveAllAlbums = (albums) => {

return {
type: RECEIVE_ALL_ALBUMS,
albums
};
};

export const receiveSingleAlbum = (album) => {
export const receiveSingleAlbum = (res) => {

return {
type: RECEIVE_ALBUM,
album
album: res[0],
songs: res.slice(1)
};
};
14 changes: 6 additions & 8 deletions frontend/actions/session_actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as APIUtil from '../util/session_api_util'

export const RECEIVE_CURRENT_USER = 'RECEIVE_CURRENT_USER';
export const RECEIVE_SESSION_ERRORS = 'RECEIVE_SESSION_ERRORS';
export const CLEAR_SESSION_ERRORS = 'CLEAR_SESSION_ERRORS';

export const receiveCurrentUser = currentUser => {

Expand All @@ -16,14 +17,13 @@ export const receiveErrors = errors => ({
errors
});

// export const clearErrors = () => {
// return ({
//
// });
// };
export const clearErrors = () => {
return ({
type: CLEAR_SESSION_ERRORS
});
};

export const fetchCurrentUser = (user) => dispatch => {

return (
APIUtil.fetchCurrentUser(user).then(res => {
dispatch(receiveCurrentUser(res));
Expand All @@ -35,15 +35,13 @@ export const signup = user => dispatch => (
APIUtil.signup(user).then(user => (
dispatch(receiveCurrentUser(user))
), err => {

return (
dispatch(receiveErrors(err.responseJSON))
);
}
));

export const login = user => dispatch => {

return (
APIUtil.login(user).then(user => (
dispatch(receiveCurrentUser(user))
Expand Down
3 changes: 2 additions & 1 deletion frontend/actions/song_actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const receiveSongs = ({songs, playlist}) => {
};

export const fetchSavedSongs = (props) => dispatch => {

return (
APIUtil.fetchSavedSongs(props).then(
res => dispatch(receiveSongs(res))
Expand All @@ -39,6 +39,7 @@ export const removeSongFromState = () => {


export const receiveCurrentSong = (songId, elementId, elementType) => {

return {
type: RECEIVE_CURRENT_SONG,
songId: songId,
Expand Down
9 changes: 5 additions & 4 deletions frontend/components/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import SearchContainer from './main/navbar/search_container';
import CollectionContainer from './main/navbar/collection_container';
import PlaylistShowContainer from './main/header/playlist_show_container';
import AlbumShowContainer from './main/header/album_show_container';
import ArtistShowContainer from './main/header/artist_show_container';
import MusicPlayer from './main/playbar/music_player';
import NavBarContainer from './main/navbar/navbar_container';
import { logout } from '../actions/session_actions';
Expand All @@ -26,7 +27,7 @@ const App = () => {
<ProtectedRoute exact path="/browse/albums" component={BrowseContainer}/>
<ProtectedRoute exact path="/browse/artists" component={BrowseContainer}/>
<ProtectedRoute exact path="/browse/albums/:albumId" component={AlbumShowContainer}/>
<ProtectedRoute exact path="/browse/artists/:artistId" component={BrowseContainer}/>
<ProtectedRoute exact path="/browse/artists/:artistId" component={ArtistShowContainer}/>
<ProtectedRoute exact path="/search" component={SearchContainer}/>
<ProtectedRoute exact path="/search/playlists" component={SearchContainer}/>
<ProtectedRoute exact path="/collection" component={CollectionContainer}/>
Expand All @@ -36,13 +37,13 @@ const App = () => {
<ProtectedRoute exact path="/collection/songs" component={CollectionContainer}/>
<ProtectedRoute exact path="/collection/playlists/:playlistId" component={PlaylistShowContainer}/>
<ProtectedRoute exact path="/collection/albums/:albumId" component={AlbumShowContainer}/>
<ProtectedRoute exact path="/collection/artists/:artistId" component={BrowseContainer}/>
<ProtectedRoute exact path="/collection/artists/:artistId" component={ArtistShowContainer}/>
<Route exact path="/" component={SplashContainer}/>
<ProtectedRoute path="/" component={NavBarContainer}/>
<ProtectedRoute path="/" component={MusicPlayer}/>
</div>
);
};
);
};

export default App;

Expand Down
2 changes: 1 addition & 1 deletion frontend/components/main/header/album_index_container.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { requestAllAlbums } from '../../../actions/search_actions';
import { selectRandomAlbums } from '../../../reducers/selectors';

const mapStateToProps = (state, ownProps) => {
debugger

return {
path: "album",
navpath: ownProps.navpath,
Expand Down
11 changes: 7 additions & 4 deletions frontend/components/main/header/album_show_container.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import React from 'react';
import { fetchAlbum } from '../../../actions/album_actions';
import { connect } from 'react-redux';
import GridShow from './grid_show';
import { logout } from '../../../actions/session_actions';
import { selectAlbumSongs } from '../../../reducers/selectors';
import { fetchAlbum } from '../../../actions/album_actions';
import { logout } from '../../../actions/session_actions';
import { requestSingleAlbum } from '../../../actions/search_actions';


const mapStateToProps = (state, ownProps) => {
const album = state.entities.albums[ownProps.match.params.albumId] || { title: "", song_ids: [], photoUrl: "" };
const songs = selectAlbumSongs(state, album);
const album = state.entities.albums[ownProps.match.params.albumId] || Object.values(state.entities.remoteAlbums)[0] || { title: "", song_ids: [], photoUrl: "" };
const songs = Object.values(state.entities.remoteSongs) || selectAlbumSongs(state, album);

return {
album,
albumId: ownProps.match.params.albumId,
Expand All @@ -18,6 +20,7 @@ const mapStateToProps = (state, ownProps) => {

const mapDipatchToProps = (dispatch) => {
return {
requestSingleAlbum: (id) => dispatch(requestSingleAlbum(id)),
fetchAlbum: (id) => dispatch(fetchAlbum(id)),
logout: () => dispatch(logout())
};
Expand Down
30 changes: 30 additions & 0 deletions frontend/components/main/header/artist_show_container.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import { fetchArtist } from '../../../actions/artist_actions';
import { connect } from 'react-redux';
import GridShow from './grid_show';
import { logout } from '../../../actions/session_actions';
import { selectArtistSongs } from '../../../reducers/selectors';


const mapStateToProps = (state, ownProps) => {
// const artist = Object.values(state.entities.remoteArtists)[ownProps.match.params.artistId] || ownProps.artists || [],
const artist = state.entities.artists[ownProps.match.params.artistId] || { name: "", song_ids: [], photoUrl: "" };
const songs = selectArtistSongs(state, artist);
return {
artist,
artistId: ownProps.match.params.artistId,
songs
};
};

const mapDipatchToProps = (dispatch) => {
return {
fetchArtist: (id) => dispatch(fetchArtist(id)),
logout: () => dispatch(logout())
};
};

export default connect(
mapStateToProps,
mapDipatchToProps
)(GridShow);
9 changes: 4 additions & 5 deletions frontend/components/main/header/grid_index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@ class GridIndex extends React.Component {
}

componentDidMount(){
debugger

this.fetchElements(
{search_term: this.props.searchTerm}
);
}

componentWillReceiveProps(nextProps) {
debugger
if (nextProps.searchTerm && this.props.searchTerm !== nextProps.searchTerm) {
this.fetchElements({
search_term: nextProps.searchTerm
Expand All @@ -27,7 +26,7 @@ class GridIndex extends React.Component {
}

render(){
debugger

const {playlists, artists, albums, navpath, path} = this.props;
let property = "title";
let gridElements = [];
Expand All @@ -44,15 +43,15 @@ class GridIndex extends React.Component {
filteredElements = gridElements.filter(a => a.title.toLowerCase().includes(this.props.searchTerm.toLowerCase()));
} else if (this.props.searchTerm && gridElements && !albums) {
filteredElements = gridElements.filter(a => a.name.toLowerCase().includes(this.props.searchTerm.toLowerCase()));
}
}
else {
filteredElements = gridElements;
}

return (
<div className="grid">
<ul>
{filteredElements.map(element => <GridIndexItem key={element.id} element={element} navpath={navpath} path={path}/>)}
{filteredElements.map(element => <GridIndexItem key={element.id || element.collectionId} element={element} navpath={navpath} path={path}/>)}
</ul>
</div>
);
Expand Down
8 changes: 4 additions & 4 deletions frontend/components/main/header/grid_index_item.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { Link } from 'react-router-dom';
const GridIndexItem = ({ path, element, navpath}) => {
// path will be playlist, album, or artist
// navpath will be browse or collection

if (element.artworkUrl100) {
debugger

element.artworkUrl100 = element.artworkUrl100.replace('100x100', '600x600');
}
let img = '';
if (Array.isArray(element.photoUrl || element.artworkUrl100)) {
// element.photoUrl = element.photoUrl[0];
img = (
<div className="image-combiner">
<div className="combined-images">
Expand All @@ -27,8 +27,8 @@ import { Link } from 'react-router-dom';
img = (<img src={element.photoUrl || element.artworkUrl100}></img>)
}
return (
<li className={`${path}-item`} key={element.id}>
<Link to={`/${navpath}/${path}s/${element.id}`}>
<li className={`${path}-item`} key={element.id || element.collectionId}>
<Link to={`/${navpath}/${path}s/${element.id || element.collectionId}`}>
<div className={`${path}-item-image`}>
{img}
</div>
Expand Down
Loading

0 comments on commit 7bb40b1

Please sign in to comment.