diff --git a/Gemfile b/Gemfile index b5b1520..4811e36 100644 --- a/Gemfile +++ b/Gemfile @@ -40,6 +40,8 @@ gem "aws-sdk-s3", require: false gem 'rspotify' gem "font-awesome-rails" gem 'ez_download', git: 'https://github.com/OscarAlvarez8830/EZDownload.git' +gem 'feedjira' + group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] diff --git a/app/assets/stylesheets/components/main_content.scss b/app/assets/stylesheets/components/main_content.scss index 011a213..72c1dbe 100644 --- a/app/assets/stylesheets/components/main_content.scss +++ b/app/assets/stylesheets/components/main_content.scss @@ -125,6 +125,7 @@ justify-content: center; margin-top: 20px; padding-left: 20%; + width: 800px; } .artist-item, .album-item, .playlist-item { diff --git a/app/assets/stylesheets/components/music_player.scss b/app/assets/stylesheets/components/music_player.scss index 6b7bf42..a447cb9 100644 --- a/app/assets/stylesheets/components/music_player.scss +++ b/app/assets/stylesheets/components/music_player.scss @@ -76,8 +76,8 @@ progress[value]::-webkit-progress-value { } .song-photo{ - width: 50px; - height: 50px; + width: 80px; + height: 80px; z-index: 3; } diff --git a/app/assets/stylesheets/components/show_box_content.scss b/app/assets/stylesheets/components/show_box_content.scss index e3c50bf..820bbb4 100644 --- a/app/assets/stylesheets/components/show_box_content.scss +++ b/app/assets/stylesheets/components/show_box_content.scss @@ -78,6 +78,7 @@ .tracks { margin-top: 50px; // margin-left: 100px; + width: 100% !important; } .song-index-item { @@ -85,7 +86,7 @@ display: flex; height: 60px; justify-content: space-between; - width: 900px; + width: 1200px; color: #f2f2f2; flex: 1; align-items: center; @@ -140,7 +141,7 @@ div[class*="song-index"] { height: 60px; padding: 5px 5px 5px 15px; transition: background-color .2s linear; - width: 1000px; + width: 100%; padding-right: 40px; } diff --git a/app/controllers/api/albums_controller.rb b/app/controllers/api/albums_controller.rb index dacca8d..d84cff8 100644 --- a/app/controllers/api/albums_controller.rb +++ b/app/controllers/api/albums_controller.rb @@ -1,7 +1,7 @@ class Api::AlbumsController < ApplicationController def index if search_query - @albums = Album.where('lower(title) LIKE ?', "%#{search_query.downcase}" ) + @albums = Album.where('lower(title) LIKE ?', "%#{search_query.downcase}%" ) else @albums = Album.all.includes(:songs) end @@ -13,6 +13,12 @@ def show render :show end + def get_albums + + @albums = Feedjira::Feed.fetch_and_parse(params[:feed_url]).entries + render 'api/albums/get_albums' + end + private def album_params diff --git a/app/controllers/api/playlists_controller.rb b/app/controllers/api/playlists_controller.rb index c5c0903..db16f99 100644 --- a/app/controllers/api/playlists_controller.rb +++ b/app/controllers/api/playlists_controller.rb @@ -2,7 +2,7 @@ class Api::PlaylistsController < ApplicationController def index if search_query - @playlists = Playlist.where('lower(title) LIKE ?', "%#{search_query.downcase}" ) + @playlists = Playlist.where('lower(title) LIKE ?', "%#{search_query.downcase}%" ) else @playlists = Playlist.all.includes(:songs, :author) end diff --git a/app/controllers/api/songs_controller.rb b/app/controllers/api/songs_controller.rb index 4272c64..99cfff3 100644 --- a/app/controllers/api/songs_controller.rb +++ b/app/controllers/api/songs_controller.rb @@ -1,9 +1,13 @@ class Api::SongsController < ApplicationController def index - # if song_ids - @saved_playlist = current_user.playlists.first - @songs = @saved_playlist.songs + + if search_query + @songs = Song.where('lower(title) LIKE ?', "%#{search_query.downcase}" ) + else + @saved_playlist = current_user.playlists.first + @songs = @saved_playlist.songs + end render :index end @@ -17,8 +21,8 @@ def song_params # params[:song_ids] # end # - # def search_term - # params[:search_term] - # end + def search_query + params[:search_query] + end end diff --git a/app/views/api/albums/get_albums.json.jbuilder b/app/views/api/albums/get_albums.json.jbuilder new file mode 100644 index 0000000..b33ab5c --- /dev/null +++ b/app/views/api/albums/get_albums.json.jbuilder @@ -0,0 +1,9 @@ + + +json.array! @albums do |album| + json.id album.id + json.title album.title + json.summary album.summary + json.audio album.enclosure_url + json.itunes_author album.itunes_author +end diff --git a/app/views/api/songs/index.json.jbuilder b/app/views/api/songs/index.json.jbuilder index 3aca1ac..5e58d49 100644 --- a/app/views/api/songs/index.json.jbuilder +++ b/app/views/api/songs/index.json.jbuilder @@ -1,7 +1,8 @@ -json.playlist do - json.extract! @playlist, :id, :title, :song_ids, :author_id - json.author @playlist.author.username -end + +# json.playlist do +# json.extract! @playlist, :id, :title, :song_ids, :author_id +# json.author @playlist.author.username +# end @songs.each do |song| json.set! song.id do diff --git a/config/routes.rb b/config/routes.rb index cd0acd9..266632f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,6 +3,7 @@ root to: "static_pages#root" namespace :api, defaults: { format: :json } do + get('albums/get_albums', { to: 'albums#get_albums' }) resources :users, only: [:show, :create] resource :session, only: [:create, :destroy] resources :songs, only: [:index, :show] diff --git a/frontend/actions/album_actions.js b/frontend/actions/album_actions.js index d92d397..b093377 100644 --- a/frontend/actions/album_actions.js +++ b/frontend/actions/album_actions.js @@ -19,6 +19,7 @@ const receiveAlbum = ({album, songs}) => { }; export const fetchAlbums = (props) => dispatch => { + return ( APIUtil.fetchAlbums(props).then( res => dispatch(receiveAlbums(res)) diff --git a/frontend/actions/playlist_actions.js b/frontend/actions/playlist_actions.js index 4dac5b5..54714b4 100644 --- a/frontend/actions/playlist_actions.js +++ b/frontend/actions/playlist_actions.js @@ -27,6 +27,7 @@ const removePlaylist = playlistId => { }; export const fetchPlaylists = (props) => dispatch => { + return ( APIUtil.fetchPlaylists(props).then( res => dispatch(receivePlaylists(res)) diff --git a/frontend/actions/search_actions.js b/frontend/actions/search_actions.js new file mode 100644 index 0000000..d30d051 --- /dev/null +++ b/frontend/actions/search_actions.js @@ -0,0 +1,41 @@ +import * as SearchApiUtil from '../util/search_api_util'; + +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) => { + return (dispatch) => { + return SearchApiUtil.fetchSingleAlbum(searchQuery) + .then(null, + (response) => { + dispatch(receiveSingleAlbum(JSON.parse(response.responseText).results[0])); + }); + }; +}; + +export const receiveAllAlbums = (albums) => { + + return { + type: RECEIVE_ALL_ALBUMS, + albums + }; +}; + +export const receiveSingleAlbum = (album) => { + return { + type: RECEIVE_ALBUM, + album + }; +}; diff --git a/frontend/actions/song_actions.js b/frontend/actions/song_actions.js index 8d9d8a7..f8fa373 100644 --- a/frontend/actions/song_actions.js +++ b/frontend/actions/song_actions.js @@ -16,9 +16,10 @@ const receiveSongs = ({songs, playlist}) => { }; }; -export const fetchSavedSongs = () => dispatch => { +export const fetchSavedSongs = (props) => dispatch => { + return ( - APIUtil.fetchSavedSongs().then( + APIUtil.fetchSavedSongs(props).then( res => dispatch(receiveSongs(res)) )); }; diff --git a/frontend/components/main/header/album_index_container.js b/frontend/components/main/header/album_index_container.js index 14717bb..e921398 100644 --- a/frontend/components/main/header/album_index_container.js +++ b/frontend/components/main/header/album_index_container.js @@ -2,13 +2,15 @@ import React from 'react'; import {connect} from 'react-redux'; import GridIndex from './grid_index'; import { fetchAlbums } from '../../../actions/album_actions'; +import { requestAllAlbums } from '../../../actions/search_actions'; import { selectRandomAlbums } from '../../../reducers/selectors'; const mapStateToProps = (state, ownProps) => { - + return { path: "album", navpath: ownProps.navpath, + // albums: Object.values(state.entities.remoteAlbums) || ownProps.albums || [], albums: ownProps.albums || selectRandomAlbums(state) || [], searchTerm: ownProps.searchTerm }; @@ -17,6 +19,9 @@ const mapStateToProps = (state, ownProps) => { const mapDispatchToProps = dispatch => { return { fetchAlbums: (props) => dispatch(fetchAlbums(props)), + requestAllAlbums: (searchQuery) => { + return dispatch(requestAllAlbums(searchQuery)); + }, }; }; diff --git a/frontend/components/main/header/grid_index.jsx b/frontend/components/main/header/grid_index.jsx index 08d99d3..0abc9f1 100644 --- a/frontend/components/main/header/grid_index.jsx +++ b/frontend/components/main/header/grid_index.jsx @@ -4,21 +4,19 @@ import GridIndexItem from './grid_index_item'; class GridIndex extends React.Component { constructor(props){ - super(props); this.fetchElements = props.fetchPlaylists || props.fetchArtists || props.fetchAlbums; this.fetchElements = this.fetchElements.bind(this); } componentDidMount(){ - this.fetchElements( {search_term: this.props.searchTerm} ); } componentWillReceiveProps(nextProps) { - + if (nextProps.searchTerm && this.props.searchTerm !== nextProps.searchTerm) { this.fetchElements({ search_term: nextProps.searchTerm diff --git a/frontend/components/main/header/grid_index_item.jsx b/frontend/components/main/header/grid_index_item.jsx index 26ff3ed..69404ab 100644 --- a/frontend/components/main/header/grid_index_item.jsx +++ b/frontend/components/main/header/grid_index_item.jsx @@ -22,7 +22,6 @@ import { Link } from 'react-router-dom'; } else { img = () } - debugger return (
  • diff --git a/frontend/components/main/header/search/search_results.jsx b/frontend/components/main/header/search/search_results.jsx index 90b00c5..f411e57 100644 --- a/frontend/components/main/header/search/search_results.jsx +++ b/frontend/components/main/header/search/search_results.jsx @@ -3,6 +3,7 @@ import React from 'react'; import AlbumIndexContainer from '../album_index_container'; import ArtistIndexContainer from '../artist_index_container'; import PlaylistIndexContainer from '../playlist_index_container'; +import SongsIndex from '../songs_index'; // import TrackIndex from '../util/tracks/track_container'; // import PlaylistIndex from '../util/playlists/playlist_container'; import { withRouter, Route, Link } from 'react-router-dom'; @@ -17,6 +18,7 @@ class SearchResults extends React.Component {

    Top Results

    +

    Albums

    Playlists

    @@ -33,3 +35,6 @@ const mapStateToProps = state => ({ }); export default withRouter(connect(mapStateToProps)(SearchResults)); +// +//

    Songs

    +// diff --git a/frontend/components/main/header/songs_index.jsx b/frontend/components/main/header/songs_index.jsx index 188db40..e09b877 100644 --- a/frontend/components/main/header/songs_index.jsx +++ b/frontend/components/main/header/songs_index.jsx @@ -6,14 +6,17 @@ import { logout, fetchCurrentUser } from '../../../actions/session_actions'; import { selectPlaylistSongs, selectAllSavedSongs, selectAllPlaylists } from '../../../reducers/selectors'; import SongsIndexItem from './songs_index_item'; -const mapStateToProps = (state) => { +const mapStateToProps = (state, ownProps) => { + const playlist = state.entities.playlists[323]; const songs = selectPlaylistSongs(state, playlist); const playlistId = 323; return { songs, playlist, - playlistId + playlistId, + searchTerm: ownProps.searchTerm, + navpath: ownProps.navpath }; }; @@ -22,22 +25,41 @@ const mapDispatchToProps = (dispatch) => { return { fetchPlaylist: (id) => dispatch(fetchPlaylist(id)), fetchCurrentUser: (user) => dispatch(fetchCurrentUser(user)), - fetchSavedSongs: () => dispatch(fetchSavedSongs()), + fetchSavedSongs: (props) => dispatch(fetchSavedSongs(props)), logout: () => dispatch(logout()) }; }; class SongsIndex extends React.Component { constructor(props){ + super(props); + this.fetchSavedSongs = props.fetchSavedSongs.bind(this); } componentDidMount() { - this.props.fetchPlaylist(this.props.playlistId); + + let search_query = this.props.searchTerm; + if (search_query) { + this.fetchSavedSongs( + {search_term: search_query} + ); + } else { + this.props.fetchPlaylist(this.props.playlistId); + } // this.props.fetchCurrentUser(window.currentUser); } + componentWillReceiveProps(nextProps) { + if (nextProps.searchTerm && this.props.searchTerm !== nextProps.searchTerm) { + this.fetchSavedSongs({ + search_term: nextProps.searchTerm + }); + } + } + render(){ + const {songs, playlist } = this.props; if (!playlist){return (
    );} if (!songs[songs.length-1]){return (
    );} diff --git a/frontend/reducers/entities/entities_reducer.js b/frontend/reducers/entities/entities_reducer.js index a741117..4b0c130 100644 --- a/frontend/reducers/entities/entities_reducer.js +++ b/frontend/reducers/entities/entities_reducer.js @@ -5,6 +5,7 @@ import songsReducer from './songs_reducer'; import artistsReducer from './artists_reducer'; import albumsReducer from './albums_reducer'; import usersReducer from './users_reducer'; +// import searchReducer from './search_reducer'; export default combineReducers({ playlists: playlistsReducer, @@ -12,3 +13,5 @@ export default combineReducers({ artists: artistsReducer, albums: albumsReducer }); + +// remoteAlbums: searchReducer diff --git a/frontend/reducers/entities/search_reducer.js b/frontend/reducers/entities/search_reducer.js new file mode 100644 index 0000000..f0a0066 --- /dev/null +++ b/frontend/reducers/entities/search_reducer.js @@ -0,0 +1,18 @@ +// import { RECEIVE_ALL_ALBUMS, RECEIVE_ALBUM } from '../../actions/search_actions'; +// import { merge } from 'lodash'; +// +// export default (state = {}, action) => { +// +// switch (action.type) { +// case RECEIVE_ALL_ALBUMS: +// const newState = merge({}, state); +// action.albums.map((album) => newState[album.collectionName] = album ); +// return newState; +// case RECEIVE_ALBUM: +// const otherNewState = merge({}, state); +// otherNewState[action.album.collectionName] = action.album; +// return otherNewState; +// default: +// return state; +// } +// }; diff --git a/frontend/util/album_api_util.jsx b/frontend/util/album_api_util.jsx index a74d3a1..232246f 100644 --- a/frontend/util/album_api_util.jsx +++ b/frontend/util/album_api_util.jsx @@ -1,4 +1,5 @@ export const fetchAlbums = (props) => { + return $.ajax({ method: 'GET', url: '/api/albums', diff --git a/frontend/util/search_api_util.jsx b/frontend/util/search_api_util.jsx new file mode 100644 index 0000000..44c57af --- /dev/null +++ b/frontend/util/search_api_util.jsx @@ -0,0 +1,39 @@ +export const fetchAllAlbums = (searchQuery) => { + + return $.ajax({ + method: 'GET', + url: parseSearchTerms(searchQuery) + }); +}; + +export const fetchSingleAlbum = (searchQuery) => { + return $.ajax({ + method: 'GET', + url: 'https://itunes.apple.com/search?', + data: { + country: 'US', + media: 'podcast', + limit: 10, + lang: 'en_us', + term: searchQuery + } + }); +}; + +const parseSearchTerms = (searchQuery) => { + + let query = ""; + const searchString = searchQuery.search_term.split(" ").join("+"); + const searchParams = { + country: 'US', + media: 'podcast', + limit: 10, + lang: 'en_us', + term: searchString + }; + for (let key in searchParams) + { + query = query + key + "=" + searchParams[key] + "&"; + } + return `https://itunes.apple.com/search?${query}`.slice(0, -1); +}; diff --git a/frontend/util/song_api_util.jsx b/frontend/util/song_api_util.jsx index 872b6f6..94e4291 100644 --- a/frontend/util/song_api_util.jsx +++ b/frontend/util/song_api_util.jsx @@ -1,6 +1,15 @@ -export const fetchSavedSongs = () => { +export const fetchSavedSongs = (props) => { + return $.ajax({ method: 'GET', - url: '/api/songs' + url: '/api/songs', + data: props }); }; + +// export const fetchSongs = () => { +// return $.ajax({ +// method: 'GET', +// url: '/api/songs' +// }); +// };