diff --git a/.DS_Store b/.DS_Store index 6831926..aeafcdb 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/app/.DS_Store b/app/.DS_Store index 8734399..bede5b0 100644 Binary files a/app/.DS_Store and b/app/.DS_Store differ diff --git a/app/assets/.DS_Store b/app/assets/.DS_Store index ceaebf1..23eab17 100644 Binary files a/app/assets/.DS_Store and b/app/assets/.DS_Store differ diff --git a/app/assets/circular (1).otf b/app/assets/circular (1).otf new file mode 100644 index 0000000..9b61395 Binary files /dev/null and b/app/assets/circular (1).otf differ diff --git a/app/assets/images/face.jpg b/app/assets/images/face.jpg new file mode 100644 index 0000000..e28d260 Binary files /dev/null and b/app/assets/images/face.jpg differ diff --git a/app/assets/stylesheets/components/main_content.scss b/app/assets/stylesheets/components/main_content.scss index 3a37711..f60a109 100644 --- a/app/assets/stylesheets/components/main_content.scss +++ b/app/assets/stylesheets/components/main_content.scss @@ -1,7 +1,10 @@ .main-container { - height: 1000px; - background-color: red; /* For browsers that do not support gradients */ - background-image: linear-gradient(#8D200A, #6D1A08, #451005, #150501); + height: 100vh; + background: #34e89e; /* fallback for old browsers */ + background: -webkit-linear-gradient(to top, #0f3443, #34e89e); /* Chrome 10-25, Safari 5.1-6 */ + background: linear-gradient(to top, #0f3443, #34e89e); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */ + display: flex; + font-family: Circular,Helvetica,Arial,sans-serif; } .main-container .nav-bar { @@ -13,7 +16,6 @@ background-color: black; opacity: .8; box-sizing: border-box; - position: fixed; top: 0; } @@ -68,10 +70,50 @@ .nav-bar .logout{ color: white; - margin-top: 500px; align-self: end; + position: absolute; + bottom: 30px; + left: 70px; } .nav-bar .active-link{ color: green; + background-color: green; +} + +.grid ul { + display: flex; + align-items: flex-start; + flex-wrap: wrap; +} + +.playlist-item { + padding: 20px; + flex-basis: 15%; + box-sizing: border-box; +} + +.playlist-item-image { + min-width: 150px; + min-height: 150px; + max-height: 241px; + max-width: 241px; +} +.playlist-subtext { + padding-top: 10px; + display: flex; + flex-direction: column; + align-items: center; +} +.playlist-subtext p { + color:white; + padding-bottom: 5px; + font-size: 14px; + font-family: Circular,Helvetica,Arial,sans-serif; +} +.playlist-subtext span { + color: lightgray; + font-weight: 100; + font-size: 14px; + font-family: Circular,Helvetica,Arial,sans-serif; } diff --git a/app/assets/stylesheets/components/show_box_content.scss b/app/assets/stylesheets/components/show_box_content.scss new file mode 100644 index 0000000..1e185c7 --- /dev/null +++ b/app/assets/stylesheets/components/show_box_content.scss @@ -0,0 +1,37 @@ +.playlist-show-item { + display: flex; + flex-direction: column; + padding-left: 50px; + padding-top: 30px; +} + +.playlist-show-item-image { + min-width: 180px; + min-height: 180px; + max-height: 260px; + max-width: 260px; +} +.playlist-show-subtext { + padding-top: 10px; + display: flex; + flex-direction: column; + align-items: center; +} +.playlist-show-subtext p { + color: white; + padding-bottom: 5px; + font-size: 14px; + font-family: Circular,Helvetica,Arial,sans-serif; +} +.playlist-show-subtext span { + color: lightgray; + font-weight: 100; + font-size: 14px; + font-family: Circular,Helvetica,Arial,sans-serif; +} + +.loading { + width: 60px; + margin: auto; + margin-top: 160px; +} diff --git a/app/assets/stylesheets/components/splash.scss b/app/assets/stylesheets/components/splash.scss index eb8ead8..213d34a 100644 --- a/app/assets/stylesheets/components/splash.scss +++ b/app/assets/stylesheets/components/splash.scss @@ -1,7 +1,8 @@ .splash-page-contain{ width:100%; - height:1000px; + height:100vh; overflow:hidden; + min-width: 800px; } .splash-page{ @@ -29,6 +30,7 @@ right: 0; left: 0; z-index: 2; + min-width: 800px; } .splash-page .logo { diff --git a/app/controllers/api/playlists_controller.rb b/app/controllers/api/playlists_controller.rb index dcbed40..b0ee5b9 100644 --- a/app/controllers/api/playlists_controller.rb +++ b/app/controllers/api/playlists_controller.rb @@ -1,6 +1,11 @@ class Api::PlaylistsController < ApplicationController + def show + @playlist = Playlist.includes(:songs, :author).find(params[:id]) + render :show + end + def index - @playlists = Playlist.all + @playlists = Playlist.all.includes(:songs, :author) render :index end diff --git a/app/controllers/api/song_playlists_controller.rb b/app/controllers/api/song_playlists_controller.rb index 44c34d4..baa10da 100644 --- a/app/controllers/api/song_playlists_controller.rb +++ b/app/controllers/api/song_playlists_controller.rb @@ -1,4 +1,16 @@ class Api::SongPlaylistsController < ApplicationController + def create + @song_playlists = SongPlaylists.new(song_playlist_params) + @playlist_song.save + end + + def destroy + end + + private + def song_playlist_params + params.require(:song_playlist).permit(:song_id, :playlist_id) + end end # class Api::PlaylistSongsController < ApplicationController diff --git a/app/models/playlist.rb b/app/models/playlist.rb index 05c6886..1e83a90 100644 --- a/app/models/playlist.rb +++ b/app/models/playlist.rb @@ -20,6 +20,10 @@ class Playlist < ApplicationRecord foreign_key: :playlist_id, class_name: :Song_playlist + has_many :songs, + through: :song_playlists, + source: :song + has_one_attached :photo has_one_attached :track end diff --git a/app/models/song.rb b/app/models/song.rb index 090be79..4135084 100644 --- a/app/models/song.rb +++ b/app/models/song.rb @@ -27,4 +27,8 @@ class Song < ApplicationRecord has_many :arists, through: :song_artists, source: :artist + + has_many :playlists, + through: :song_playlists, + source: :playlist end diff --git a/app/views/api/playlists/index.json.jbuilder b/app/views/api/playlists/index.json.jbuilder index 79bd566..794eebb 100644 --- a/app/views/api/playlists/index.json.jbuilder +++ b/app/views/api/playlists/index.json.jbuilder @@ -1,5 +1,22 @@ -json.array! @playlists do |playlist| - json.extract! playlist, :id, :title - json.photoUrl url_for(playlist.photo) - json.trackUrl url_for(playlist.track) +@playlists.each do |playlist| + json.set! playlist.id do + json.extract! playlist, :id, :title, :author_id + json.author playlist.author.username + + json.song_ids playlist.songs.pluck(:id) + + if playlist.songs[0] + json.photoUrl url_for(playlist.songs[0].album.photo); + else + json.photoUrl image_path("face.jpg") + end + end end + +# json.photoUrl url_for(playlist.photo) +# json.trackUrl url_for(playlist.track) + + +# json.songs playlist.songs.each do |song| +# json.set! song.id +# end diff --git a/app/views/api/playlists/show.json.jbuilder b/app/views/api/playlists/show.json.jbuilder index e69de29..818b3ac 100644 --- a/app/views/api/playlists/show.json.jbuilder +++ b/app/views/api/playlists/show.json.jbuilder @@ -0,0 +1,18 @@ +json.songs do + @playlist.songs.each do |song| + json.set! song.id do + json.extract! song, :id, :title + json.trackUrl url_for(song.track) + end + end +end + +json.playlist do + json.extract! @playlist, :id, :title, :song_ids, :author_id + if @playlist.songs[0] + json.photoUrl url_for(@playlist.songs[0].album.photo); + else + json.photoUrl image_path("face.jpg") + end + json.author @playlist.author.username +end diff --git a/app/views/api/songs/index.json.jbuilder b/app/views/api/songs/index.json.jbuilder index 1d8ee4d..4796105 100644 --- a/app/views/api/songs/index.json.jbuilder +++ b/app/views/api/songs/index.json.jbuilder @@ -1,4 +1,11 @@ -json.array! @songs do |song| - json.extract! song, :id, :title, :album_id - json.trackUrl url_for(song.track) +@songs.each do |song| + json.set! song.id do + json.extract! song, :id, :title + json.trackUrl url_for(song.track) + end end + +# json.array! @songs do |song| +# json.extract! song, :id, :title, :album_id +# json.trackUrl url_for(song.track) +# end diff --git a/db/migrate/20181118235623_change_songs.rb b/db/migrate/20181118235623_change_songs.rb new file mode 100644 index 0000000..30e9ab9 --- /dev/null +++ b/db/migrate/20181118235623_change_songs.rb @@ -0,0 +1,5 @@ +class ChangeSongs < ActiveRecord::Migration[5.2] + def change + remove_index :songs, :album_id + end +end diff --git a/db/schema.rb b/db/schema.rb index fc4016a..9312314 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2018_11_18_002319) do +ActiveRecord::Schema.define(version: 2018_11_18_235623) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -84,7 +84,6 @@ t.string "title", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.index ["album_id"], name: "index_songs_on_album_id", unique: true t.index ["title"], name: "index_songs_on_title", unique: true end diff --git a/db/seeds.rb b/db/seeds.rb index ac0b257..be3343b 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -12,7 +12,99 @@ User.destroy_all Playlist.destroy_all -def create_album(params, filename) - album = Album.new(params) - file = EzDownload.open("") -end +l = Album.create!(title: "Chilis") +m = Album.create!(title: "Corbys") +n = Album.create!(title: "Samms") +o = Album.create!(title: "Vibes") +q = Album.create!(title: "Redemption") +r = Album.create!(title: "Epic") +s = Album.create!(title: "Yebbz") +t = Album.create!(title: "Gambining") +u = Album.create!(title: "Dragons") + +l.photo.attach(io: File.open("/Users/avichaivazana/Desktop/Photos/chilipeppers.jpg"), filename: "chilipeppers.jpg") +m.photo.attach(io: File.open("/Users/avichaivazana/Desktop/Photos/corby.jpg"), filename: "corby.jpg") +n.photo.attach(io: File.open("/Users/avichaivazana/Desktop/Photos/samm.jpg"), filename: "samm.jpg") +o.photo.attach(io: File.open("/Users/avichaivazana/Desktop/Photos/Wave.jpg"), filename: "Wave.jpg") +q.photo.attach(io: File.open("/Users/avichaivazana/Desktop/Photos/matisyahu.jpg"), filename: "matisyahu.jpg") +r.photo.attach(io: File.open("/Users/avichaivazana/Desktop/Photos/whirl.jpg"), filename: "whirl.jpg") +s.photo.attach(io: File.open("/Users/avichaivazana/Desktop/Photos/yebba.jpg"), filename: "yebba.jpg") +t.photo.attach(io: File.open("/Users/avichaivazana/Desktop/Photos/gambino.jpg"), filename: "gambino.jpg") +u.photo.attach(io: File.open("/Users/avichaivazana/Desktop/Photos/face.jpg"), filename: "face.jpg") + +c.track.attach(io: File.open("/Users/avichaivazana/Desktop/Songs/Monday.mp3"), filename: "Monday.mp3") + +a.track.attach(io: File.open("/Users/avichaivazana/Desktop/Songs/ Californication.mp3"), filename: "Californication.mp3") +b.track.attach(io: File.open("/Users/avichaivazana/Desktop/Songs/ Snow.mp3"), filename: "Snow.mp3") +d.track.attach(io: File.open("/Users/avichaivazana/Desktop/Songs/King Without a Crown.mp3"), filename: "King Without a Crown.mp3") +e.track.attach(io: File.open("/Users/avichaivazana/Desktop/Songs/Redbone.mp3"), filename: "Redbone.mp3") +f.track.attach(io: File.open("/Users/avichaivazana/Desktop/Songs/YEBBA.mp3"), filename: "YEBBA.mp3") +g.track.attach(io: File.open("/Users/avichaivazana/Desktop/Songs/Corporate_Innovative.mp3"), filename: "Corporate_Innovative.mp3") +h.track.attach(io: File.open("/Users/avichaivazana/Desktop/Songs/Corporate_Presentation.mp3"), filename: "Corporate_Presentation.mp3") +i.track.attach(io: File.open("/Users/avichaivazana/Desktop/Songs/Corporate_Success.mp3"), filename: "Corporate_Success.mp3") +j.track.attach(io: File.open("/Users/avichaivazana/Desktop/Songs/Smooth.mp3"), filename: "Smooth.mp3") +k.track.attach(io: File.open("/Users/avichaivazana/Desktop/Songs/the-battle.mp3"), filename: "the-battle.mp3") + +a = Song.second +b = Song.find_by(id: 14) +d = Song.find_by(id: 5) +e = Song.find_by(id: 6) +f = Song.find_by(id: 7) +g = Song.find_by(id: 8) +h = Song.find_by(id: 15) +i = Song.find_by(id: 16) +j = Song.find_by(id: 11) +k = Song.find_by(id: 12) + +a = Song.create!(album_id: 2, title: "Californication") +b = Song.create!(album_id: 2, title: "Snow") +c = Song.create!(album_id: 3, title: "Monday") +d = Song.create!(album_id: 4, title: "King Without a Crown") +e = Song.create!(album_id: 5, title: "Redbone") +f = Song.create!(album_id: 6, title: "Evergreen") +g = Song.create!(album_id: 7, title: "Corporate Innovation") +h = Song.create!(album_id: 7, title: "Corporate Presentation") +i = Song.create!(album_id: 7, title: "Corporate Success") +j = Song.create!(album_id: 8, title: "Smooth") +k = Song.create!(album_id: 9, title: "The Battle") + + + +Playlist.create!(author_id: 22, title: "Chill Vibes") +Playlist.create!(author_id: 22, title: "Summer Stuff") +Playlist.create!(author_id: 22, title: "Sleepy Time") +Playlist.create!(author_id: 22, title: "Study Music") +Playlist.create!(author_id: 22, title: "Party") +Playlist.create!(author_id: 22, title: "Random Mix") +Playlist.create!(author_id: 22, title: "Shower") +Playlist.create!(author_id: 22, title: "Walking") +Playlist.create!(author_id: 22, title: "Shower while walking") + + +Song_playlist.create!(4, 3) +Song_playlist.create!(4, 4) +Song_playlist.create!(4, 5) +Song_playlist.create!(5, 3) +Song_playlist.create!(5, 4) +Song_playlist.create!(5, 5) +Song_playlist.create!(5, 6) +Song_playlist.create!(6, 7) +Song_playlist.create!(6, 8) +Song_playlist.create!(6, 9) +Song_playlist.create!(6, 10) +Song_playlist.create!(7, 5) +Song_playlist.create!(7, 3) +Song_playlist.create!(7, 7) +Song_playlist.create!(7, 4) +Song_playlist.create!(8, 4) +Song_playlist.create!(8, 5) +Song_playlist.create!(11, 5) +Song_playlist.create!(11, 7) +Song_playlist.create!(11, 4) +Song_playlist.create!(11, 3) +Song_playlist.create!(12, 8) +Song_playlist.create!(12, 7) +Song_playlist.create!(15, 9) +Song_playlist.create!(16, 10) +Song_playlist.create!(14, 4) +Song_playlist.create!(2, 3) diff --git a/frontend/actions/playlist_actions.js b/frontend/actions/playlist_actions.js index 31fd612..6d869b0 100644 --- a/frontend/actions/playlist_actions.js +++ b/frontend/actions/playlist_actions.js @@ -1,4 +1,4 @@ -import * as APIUtil from '../util/playlist_api_util' +import * as APIUtil from '../util/playlist_api_util'; export const RECEIVE_ALL_PLAYLISTS = 'RECEIVE_ALL_PLAYLISTS'; export const RECEIVE_SINGLE_PLAYLIST = 'RECEIVE_SINGLE_PLAYLIST'; @@ -11,10 +11,11 @@ const receivePlaylists = (playlists) => { }; }; -const receivePlaylist = (playlist) => { +const receivePlaylist = ({playlist, songs}) => { return { type: RECEIVE_SINGLE_PLAYLIST, - playlist + playlist, + songs }; }; @@ -22,8 +23,8 @@ const removePlaylist = playlistId => { return { type: DELETE_PLAYLIST, playlistId - } -} + }; +}; export const fetchPlaylists = () => dispatch => { return ( @@ -34,8 +35,10 @@ export const fetchPlaylists = () => dispatch => { export const fetchPlaylist = (id) => dispatch => { return ( - APIUtil.fetchPlaylist(id).then( - res => dispatch(receivePlaylist(res)) + APIUtil.fetchPlaylist(id).then(res => { + + dispatch(receivePlaylist(res)); + } )); }; diff --git a/frontend/actions/song_actions.js b/frontend/actions/song_actions.js new file mode 100644 index 0000000..3032249 --- /dev/null +++ b/frontend/actions/song_actions.js @@ -0,0 +1,32 @@ +import * as APIUtil from '../util/song_api_util'; + +export const RECEIVE_ALL_SONGS = 'RECEIVE_ALL_SONGS'; +export const RECEIVE_SINGLE_SONG = 'RECEIVE_SINGLE_SONG'; + +const receiveSongs = (songs) => { + return { + type: RECEIVE_ALL_SONGS, + songs + }; +}; + +const receiveSong = (song) => { + return { + type: RECEIVE_SINGLE_SONG, + song + }; +}; + +export const fetchSongs = () => dispatch => { + return ( + APIUtil.fetchSongs().then( + res => dispatch(receiveSongs(res)) + )); +}; + +export const fetchSong = (id) => dispatch => { + return ( + APIUtil.fetchSong(id).then( + res => dispatch(receiveSong(res)) + )); +}; diff --git a/frontend/components/App.jsx b/frontend/components/App.jsx index 00f78ae..6d4c88c 100644 --- a/frontend/components/App.jsx +++ b/frontend/components/App.jsx @@ -7,28 +7,27 @@ import SplashContainer from './splash/splash_container'; import BrowseContainer from './main/browse_container'; import SearchContainer from './main/search_container'; import CollectionContainer from './main/collection_container'; +import PlaylistShowContainer from './main/playlist_show_container'; const App = () => { return (
- - - - - - - - - - - + + + + + + + + + +
-) +); }; export default App; - // // // diff --git a/frontend/components/main/browse_container.js b/frontend/components/main/browse_container.js index a57f23d..856feb3 100644 --- a/frontend/components/main/browse_container.js +++ b/frontend/components/main/browse_container.js @@ -3,13 +3,15 @@ import React from 'react'; import { Link } from 'react-router-dom'; import { logout } from '../../actions/session_actions'; import { fetchPlaylists } from '../../actions/playlist_actions'; -import { selectAllPlaylists } from '../../reducers/selectors'; -import MainContent from './main_content' +import { selectAllUnauthoredPlaylists } from '../../reducers/selectors'; +import MainContent from './main_content'; + +const mapStateToProps = (state, ownProps) => { -const mapStateToProps = state => { return { - playlists: selectAllPlaylists(state), - navpath: "browse" + playlists: selectAllUnauthoredPlaylists(state), + navpath: "browse", + path: ownProps.location.pathname }; }; diff --git a/frontend/components/main/collection_container.js b/frontend/components/main/collection_container.js index c25c1b7..13691e2 100644 --- a/frontend/components/main/collection_container.js +++ b/frontend/components/main/collection_container.js @@ -3,11 +3,11 @@ import React from 'react'; import { Link } from 'react-router-dom'; import { logout } from '../../actions/session_actions'; import { fetchPlaylists } from '../../actions/playlist_actions'; -import { selectAllPlaylists } from '../../reducers/selectors'; -import MainContent from './main_content' +import { selectAllAuthoredPlaylists } from '../../reducers/selectors'; +import MainContent from './main_content'; const mapStateToProps = state => ({ - playlists: selectAllPlaylists(state), + playlists: selectAllAuthoredPlaylists(state), navpath: "collection" }); diff --git a/frontend/components/main/header.jsx b/frontend/components/main/header.jsx new file mode 100644 index 0000000..c97192a --- /dev/null +++ b/frontend/components/main/header.jsx @@ -0,0 +1,57 @@ +// import React from 'react'; +// import { NavLink, withRouter } from 'react-router-dom'; +// import { connect } from 'react-redux'; +// import { openModal } from '../../actions/modal_actions'; +// +// const mapDispatchToProps = dispatch => ({ +// openModal: (modal) => dispatch(openModal(modal)) +// }); +// +// class Header extends React.Component { +// +// constructor(props) { +// super(props); +// } +// +// render() { +// +// return ( +//
    +//
    +// ALBUMS +// +// ARTISTS +// +// PLAYLISTS +// +// SONGS +// +//
    +// +// +//
+// ) +// } +// +// } +// +// export default withRouter(connect(null, mapDispatchToProps)(Header)); diff --git a/frontend/components/main/main_content.jsx b/frontend/components/main/main_content.jsx index 8793f4f..bf47793 100644 --- a/frontend/components/main/main_content.jsx +++ b/frontend/components/main/main_content.jsx @@ -3,14 +3,15 @@ import PlaylistIndexItem from './playlist_index_item'; // import PlaylistIndex from './playlist_index_item'; import { NavLink, Redirect } from 'react-router-dom'; import NavBar from './navbar'; +import Header from './header'; class MainContent extends React.Component { constructor(props) { super(props); - this.state = { - playlists: [] - }; + // this.state = { + // headerpath: props.headerpath + // }; this.fetchPlaylists = props.fetchPlaylists.bind(this); this.logout = props.logout.bind(this); } @@ -20,15 +21,29 @@ class MainContent extends React.Component { } render() { - const {playlists} = this.props; + const {playlists, navpath, show} = this.props; + + const index = ( +
+
    + {playlists.map(playlist => )} +
+
+ ); + + + let redirect = ""; + if (this.props.path === '/browse' || this.props.path === '/browse/'){ + redirect = ; + } return (
- -
    Image Goes Here: - {playlists.map(playlist => )} -
- + + + {show ? show : index} + + {redirect}
); } @@ -36,4 +51,16 @@ class MainContent extends React.Component { export default MainContent; +//
+//
    +// {songs.map(song => )} +//
+//
+//
+//
    +// {artists.map(song => )} +//
+//
+ +// // diff --git a/frontend/components/main/playlist_index_item.jsx b/frontend/components/main/playlist_index_item.jsx index 9e3ad16..0a4a208 100644 --- a/frontend/components/main/playlist_index_item.jsx +++ b/frontend/components/main/playlist_index_item.jsx @@ -1,12 +1,17 @@ import React from 'react'; - const PlaylistIndexItem = ({ playlist }) => ( -
  • - +import { Link } from 'react-router-dom'; + + const PlaylistIndexItem = ({ playlist, navpath}) => ( +
  • + +
    + +
    +
    +

    {playlist.title}

    + {playlist.author} +
    +
  • ); export default PlaylistIndexItem; - - -// diff --git a/frontend/components/main/playlist_show_container.js b/frontend/components/main/playlist_show_container.js new file mode 100644 index 0000000..89463c9 --- /dev/null +++ b/frontend/components/main/playlist_show_container.js @@ -0,0 +1,30 @@ +import React from 'react'; +import { fetchPlaylist } from '../../actions/playlist_actions'; +import { connect } from 'react-redux'; +import ShowBoxContent from './show_box_content'; +import { logout } from '../../actions/session_actions'; +import { selectPlaylistSongs } from '../../reducers/selectors'; + + +const mapStateToProps = (state, ownProps) => { + const playlist = state.entities.playlists[ownProps.match.params.playlistId] || { title: "", song_ids: [], photoUrl: "" }; + + const songs = selectPlaylistSongs(state, playlist); + return { + playlist, + playlistId: ownProps.match.params.playlistId, + songs + }; +}; + +const mapDipatchToProps = (dispatch) => { + return { + fetchPlaylist: (id) => dispatch(fetchPlaylist(id)), + logout: () => dispatch(logout()) + }; +}; + +export default connect( + mapStateToProps, + mapDipatchToProps +)(ShowBoxContent); diff --git a/frontend/components/main/show_box_content.jsx b/frontend/components/main/show_box_content.jsx new file mode 100644 index 0000000..1c496fb --- /dev/null +++ b/frontend/components/main/show_box_content.jsx @@ -0,0 +1,67 @@ +import React from 'react'; +import NavBar from './navbar'; +import { PulseLoader } from 'react-spinners'; + + +class ShowBoxContent extends React.Component { + constructor(props) { + super(props); + this.state = { loading: true }; + } + + componentDidMount(){ + this.props.fetchPlaylist(this.props.playlistId) + .then( () => setTimeout(() => this.setState({loading: false}), 100)); + } + + render () { + const {playlist, logout, songs} = this.props; + + let tracks = ''; + if(songs[0]){ + tracks = songs.map( (song) => { + return ( + + ); + }); + } + + if (this.state.loading) { + return ( +
    + +
    + ); + } + + return ( +
    + + +
    +
    + +
    +
    +

    {playlist.title}

    + {playlist.author} +
    +
    +
    + {tracks} +
    + +
    + ); + } +} +export default ShowBoxContent; diff --git a/frontend/reducers/entities/entities_reducer.js b/frontend/reducers/entities/entities_reducer.js index 87774f8..fa7cfc1 100644 --- a/frontend/reducers/entities/entities_reducer.js +++ b/frontend/reducers/entities/entities_reducer.js @@ -1,7 +1,9 @@ import { combineReducers } from 'redux'; import playlistsReducer from './playlists_reducer'; +import songsReducer from './songs_reducer'; export default combineReducers({ - playlists: playlistsReducer + playlists: playlistsReducer, + songs: songsReducer }); diff --git a/frontend/reducers/entities/playlists_reducer.js b/frontend/reducers/entities/playlists_reducer.js index d393fe5..e72653e 100644 --- a/frontend/reducers/entities/playlists_reducer.js +++ b/frontend/reducers/entities/playlists_reducer.js @@ -4,11 +4,12 @@ import merge from 'lodash/merge'; const playlistsReducer = (state = {}, action) => { Object.freeze(state); let newState; + let playlist; switch(action.type){ case RECEIVE_ALL_PLAYLISTS: - return action.playlists; + return merge({}, state, action.playlists ); case RECEIVE_SINGLE_PLAYLIST: - return merge({}, state, {[action.playlist.id]: action.playlist}); + return merge({}, state, {[action.playlist.id]: action.playlist} ); case DELETE_PLAYLIST: newState = merge({}, state); delete newState[action.playlistId]; diff --git a/frontend/reducers/entities/songs_reducer.js b/frontend/reducers/entities/songs_reducer.js new file mode 100644 index 0000000..4cc7992 --- /dev/null +++ b/frontend/reducers/entities/songs_reducer.js @@ -0,0 +1,20 @@ +import { RECEIVE_ALL_SONGS } from '../../actions/song_actions'; +import { RECEIVE_SINGLE_PLAYLIST } from '../../actions/playlist_actions'; +import merge from 'lodash/merge'; + +const songsReducer = (state = {}, action) => { + + Object.freeze(state); + let songs; + switch(action.type){ + case RECEIVE_ALL_SONGS: + return merge({}, state, action.songs ); + case RECEIVE_SINGLE_PLAYLIST: + songs = action.songs; + return merge({}, state, songs); + default: + return state; + } +}; + +export default songsReducer; diff --git a/frontend/reducers/selectors.js b/frontend/reducers/selectors.js index cbf0544..2ff9efe 100644 --- a/frontend/reducers/selectors.js +++ b/frontend/reducers/selectors.js @@ -1,3 +1,34 @@ import values from 'lodash/values'; export const selectAllPlaylists = state => Object.values(state.entities.playlists); + +export const selectAllAuthoredPlaylists = state => { + let authoredPlaylists = []; + let playlists = state.entities.playlists; + Object.values(playlists).forEach((playlist) => { + debugger + if (playlist.author_id === state.session.currentUser.id){ + authoredPlaylists.push(playlist); + } + }); + return authoredPlaylists; +}; + +export const selectAllUnauthoredPlaylists = state => { + let unauthoredPlaylists = []; + let playlists = state.entities.playlists; + Object.values(playlists).forEach((playlist) => { + debugger + if (playlist.author_id != state.session.currentUser.id){ + unauthoredPlaylists.push(playlist); + } + }); + return unauthoredPlaylists; +}; + +export const selectPlaylistSongs = (state, playlist) => { + + return playlist ? playlist.song_ids.map(id => state.entities.songs[id]) : []; +}; + +export const selectAllSongs = state => Object.values(state.entities.songs); diff --git a/frontend/util/playlist_api_util.jsx b/frontend/util/playlist_api_util.jsx index 781b893..d91bbf6 100644 --- a/frontend/util/playlist_api_util.jsx +++ b/frontend/util/playlist_api_util.jsx @@ -2,22 +2,22 @@ export const fetchPlaylists = () => { return $.ajax({ method: 'GET', url: '/api/playlists' - }) + }); }; export const fetchPlaylist = (id) => { return $.ajax({ method: 'GET', url: `/api/playlists/${id}` - }) + }); }; export const createPlaylist = (playlist) => { return $.ajax({ method: 'POST', url: `/api/playlists`, - data: { playlist } - }) + data: { playlist } + }); }; export const updatePlaylist = (playlist) => { @@ -25,12 +25,12 @@ export const updatePlaylist = (playlist) => { method: 'PATCH', url: `/api/playlists/${playlist.id}`, data: { playlist } - }) + }); }; export const deletePlaylist = (id) => { return $.ajax({ method: 'DELETE', url: `/api/playlists/${id}` - }) + }); }; diff --git a/frontend/util/song_api_util.jsx b/frontend/util/song_api_util.jsx new file mode 100644 index 0000000..3f134dc --- /dev/null +++ b/frontend/util/song_api_util.jsx @@ -0,0 +1,13 @@ +export const fetchSongs = () => { + return $.ajax({ + method: 'GET', + url: '/api/songs' + }); +}; + +export const fetchSong = (id) => { + return $.ajax({ + method: 'GET', + url: `/api/songs/${id}` + }); +}; diff --git a/package-lock.json b/package-lock.json index 11fc52a..5fb63e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -721,6 +721,70 @@ "to-fast-properties": "2.0.0" } }, + "@emotion/babel-utils": { + "version": "0.6.10", + "resolved": "https://registry.npmjs.org/@emotion/babel-utils/-/babel-utils-0.6.10.tgz", + "integrity": "sha512-/fnkM/LTEp3jKe++T0KyTszVGWNKPNOUJfjNKLO17BzQ6QPxgbg3whayom1Qr2oLFH3V92tDymU+dT5q676uow==", + "requires": { + "@emotion/hash": "0.6.6", + "@emotion/memoize": "0.6.6", + "@emotion/serialize": "0.9.1", + "convert-source-map": "1.6.0", + "find-root": "1.1.0", + "source-map": "0.7.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" + } + } + }, + "@emotion/hash": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.6.6.tgz", + "integrity": "sha512-ojhgxzUHZ7am3D2jHkMzPpsBAiB005GF5YU4ea+8DNPybMk01JJUM9V9YRlF/GE95tcOm8DxQvWA2jq19bGalQ==" + }, + "@emotion/is-prop-valid": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.6.8.tgz", + "integrity": "sha512-IMSL7ekYhmFlILXcouA6ket3vV7u9BqStlXzbKOF9HBtpUPMMlHU+bBxrLOa2NvleVwNIxeq/zL8LafLbeUXcA==", + "requires": { + "@emotion/memoize": "0.6.6" + } + }, + "@emotion/memoize": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.6.6.tgz", + "integrity": "sha512-h4t4jFjtm1YV7UirAFuSuFGyLa+NNxjdkq6DpFLANNQY5rHueFZHVY+8Cu1HYVP6DrheB0kv4m5xPjo7eKT7yQ==" + }, + "@emotion/serialize": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.9.1.tgz", + "integrity": "sha512-zTuAFtyPvCctHBEL8KZ5lJuwBanGSutFEncqLn/m9T1a6a93smBStK+bZzcNPgj4QS8Rkw9VTwJGhRIUVO8zsQ==", + "requires": { + "@emotion/hash": "0.6.6", + "@emotion/memoize": "0.6.6", + "@emotion/unitless": "0.6.7", + "@emotion/utils": "0.8.2" + } + }, + "@emotion/stylis": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.7.1.tgz", + "integrity": "sha512-/SLmSIkN13M//53TtNxgxo57mcJk/UJIDFRKwOiLIBEyBHEcipgR6hNMQ/59Sl4VjCJ0Z/3zeAZyvnSLPG/1HQ==" + }, + "@emotion/unitless": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.6.7.tgz", + "integrity": "sha512-Arj1hncvEVqQ2p7Ega08uHLr1JuRYBuO5cIvcA+WWEQ5+VmkOE3ZXzl04NbQxeQpWX78G7u6MqxKuNX3wvYZxg==" + }, + "@emotion/utils": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.8.2.tgz", + "integrity": "sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw==" + }, "@webassemblyjs/ast": { "version": "1.7.11", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz", @@ -885,6 +949,11 @@ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz", "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==" }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "acorn": { "version": "5.7.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", @@ -941,6 +1010,14 @@ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "1.0.3" + } + }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", @@ -961,6 +1038,11 @@ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", @@ -1020,6 +1102,55 @@ "util.promisify": "1.0.0" } }, + "babel-plugin-emotion": { + "version": "9.2.11", + "resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-9.2.11.tgz", + "integrity": "sha512-dgCImifnOPPSeXod2znAmgc64NhaaOjGEHROR/M+lmStb3841yK1sgaDYAYMnlvWNz8GnpwIPN0VmNpbWYZ+VQ==", + "requires": { + "@babel/helper-module-imports": "7.0.0", + "@emotion/babel-utils": "0.6.10", + "@emotion/hash": "0.6.6", + "@emotion/memoize": "0.6.6", + "@emotion/stylis": "0.7.1", + "babel-plugin-macros": "2.4.2", + "babel-plugin-syntax-jsx": "6.18.0", + "convert-source-map": "1.6.0", + "find-root": "1.1.0", + "mkdirp": "0.5.1", + "source-map": "0.5.7", + "touch": "2.0.2" + } + }, + "babel-plugin-macros": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.4.2.tgz", + "integrity": "sha512-NBVpEWN4OQ/bHnu1fyDaAaTPAjnhXCEPqr1RwqxrU7b6tZ2hypp+zX4hlNfmVGfClD5c3Sl6Hfj5TJNF5VG5aA==", + "requires": { + "cosmiconfig": "5.0.7", + "resolve": "1.8.1" + } + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "2.5.7", + "regenerator-runtime": "0.11.1" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + } + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -1284,6 +1415,27 @@ "unset-value": "1.0.0" } }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "requires": { + "callsites": "2.0.0" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "requires": { + "caller-callsite": "2.0.0" + } + }, + "callsites": { + "version": "2.0.0", + "resolved": "http://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=" + }, "camelcase": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", @@ -1304,6 +1456,11 @@ "supports-color": "5.5.0" } }, + "change-emitter": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz", + "integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU=" + }, "chokidar": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", @@ -1474,11 +1631,27 @@ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cosmiconfig": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.7.tgz", + "integrity": "sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==", + "requires": { + "import-fresh": "2.0.0", + "is-directory": "0.3.1", + "js-yaml": "3.12.0", + "parse-json": "4.0.0" + } + }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", @@ -1488,6 +1661,28 @@ "elliptic": "6.4.1" } }, + "create-emotion": { + "version": "9.2.12", + "resolved": "https://registry.npmjs.org/create-emotion/-/create-emotion-9.2.12.tgz", + "integrity": "sha512-P57uOF9NL2y98Xrbl2OuiDQUZ30GVmASsv5fbsjF4Hlraip2kyAvMm+2PoYUvFFw03Fhgtxk3RqZSm2/qHL9hA==", + "requires": { + "@emotion/hash": "0.6.6", + "@emotion/memoize": "0.6.6", + "@emotion/stylis": "0.7.1", + "@emotion/unitless": "0.6.7", + "csstype": "2.5.7", + "stylis": "3.5.4", + "stylis-rule-sheet": "0.0.10" + } + }, + "create-emotion-styled": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/create-emotion-styled/-/create-emotion-styled-9.2.8.tgz", + "integrity": "sha512-2LrNM5MREWzI5hZK+LyiBHglwE18WE3AEbBQgpHQ1+zmyLSm/dJsUZBeFAwuIMb+TjNZP0KsMZlV776ufOtFdg==", + "requires": { + "@emotion/is-prop-valid": "0.6.8" + } + }, "create-hash": { "version": "1.2.0", "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", @@ -1543,6 +1738,11 @@ "randomfill": "1.0.4" } }, + "csstype": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.5.7.tgz", + "integrity": "sha512-Nt5VDyOTIIV4/nRFswoCKps1R5CD1hkiyjBE9/thNaNZILLEviVw9yWQw15+O+CpNjQKB/uvdcxFFOrSflY3Yw==" + }, "cyclist": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", @@ -1683,6 +1883,23 @@ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" }, + "emotion": { + "version": "9.2.12", + "resolved": "https://registry.npmjs.org/emotion/-/emotion-9.2.12.tgz", + "integrity": "sha512-hcx7jppaI8VoXxIWEhxpDW7I+B4kq9RNzQLmsrF6LY8BGKqe2N+gFAQr0EfuFucFlPs2A9HM4+xNj4NeqEWIOQ==", + "requires": { + "babel-plugin-emotion": "9.2.11", + "create-emotion": "9.2.12" + } + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "0.4.24" + } + }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -1709,6 +1926,14 @@ "prr": "1.0.1" } }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "0.2.1" + } + }, "es-abstract": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", @@ -1745,6 +1970,11 @@ "estraverse": "4.2.0" } }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", @@ -1924,6 +2154,27 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, + "fbjs": { + "version": "0.8.17", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", + "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", + "requires": { + "core-js": "1.2.7", + "isomorphic-fetch": "2.2.1", + "loose-envify": "1.4.0", + "object-assign": "4.1.1", + "promise": "7.3.1", + "setimmediate": "1.0.5", + "ua-parser-js": "0.7.19" + }, + "dependencies": { + "core-js": { + "version": "1.2.7", + "resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + } + } + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -1955,6 +2206,11 @@ "pkg-dir": "2.0.0" } }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -2715,6 +2971,14 @@ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": "2.1.2" + } + }, "ieee754": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", @@ -2725,6 +2989,15 @@ "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "requires": { + "caller-path": "2.0.0", + "resolve-from": "3.0.0" + } + }, "import-local": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", @@ -2842,6 +3115,11 @@ } } }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", @@ -2900,6 +3178,11 @@ } } }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=" + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -2990,6 +3273,15 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "1.7.3", + "whatwg-fetch": "3.0.0" + } + }, "js-levenshtein": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.4.tgz", @@ -3000,6 +3292,15 @@ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.1" + } + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -3295,6 +3596,15 @@ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "0.1.12", + "is-stream": "1.1.0" + } + }, "node-libs-browser": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", @@ -3340,6 +3650,14 @@ "semver": "5.6.0" } }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "requires": { + "abbrev": "1.1.1" + } + }, "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", @@ -3510,6 +3828,15 @@ "pbkdf2": "3.0.17" } }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "1.3.2", + "json-parse-better-errors": "1.0.2" + } + }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -3598,6 +3925,14 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "2.0.6" + } + }, "promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", @@ -3708,6 +4043,15 @@ "scheduler": "0.11.2" } }, + "react-emotion": { + "version": "9.2.12", + "resolved": "https://registry.npmjs.org/react-emotion/-/react-emotion-9.2.12.tgz", + "integrity": "sha512-qt7XbxnEKX5sZ73rERJ92JMbEOoyOwG3BuCRFRkXrsJhEe+rFBRTljRw7yOLHZUCQC4GBObZhjXIduQ8S0ZpYw==", + "requires": { + "babel-plugin-emotion": "9.2.11", + "create-emotion-styled": "9.2.8" + } + }, "react-is": { "version": "16.6.3", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.6.3.tgz", @@ -3766,6 +4110,17 @@ "warning": "4.0.2" } }, + "react-spinners": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/react-spinners/-/react-spinners-0.4.7.tgz", + "integrity": "sha512-+XPY9HkcNshu8+zZ5VomK+dWSkGTycEWH41OJnqItm7ooopLCXngJIh80OTBYZReLQ9gFwLjVsjfZz2sV+14Tg==", + "requires": { + "emotion": "9.2.12", + "prop-types": "15.6.2", + "react-emotion": "9.2.12", + "recompose": "0.27.1" + } + }, "readable-stream": { "version": "2.3.6", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", @@ -3797,6 +4152,26 @@ "readable-stream": "2.3.6" } }, + "recompose": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.27.1.tgz", + "integrity": "sha512-p7xsyi/rfNjHfdP7vPU02uSFa+Q1eHhjKrvO+3+kRP4Ortj+MxEmpmd+UQtBGM2D2iNAjzNI5rCyBKp9Ob5McA==", + "requires": { + "babel-runtime": "6.26.0", + "change-emitter": "0.1.6", + "fbjs": "0.8.17", + "hoist-non-react-statics": "2.5.5", + "react-lifecycles-compat": "3.0.4", + "symbol-observable": "1.2.0" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz", + "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==" + } + } + }, "redux": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.1.tgz", @@ -3986,6 +4361,11 @@ "ret": "0.1.15" } }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "scheduler": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.11.2.tgz", @@ -4217,6 +4597,11 @@ "extend-shallow": "3.0.2" } }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, "ssri": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", @@ -4309,6 +4694,16 @@ "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, + "stylis": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz", + "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==" + }, + "stylis-rule-sheet": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz", + "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==" + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -4392,6 +4787,14 @@ "repeat-string": "1.6.1" } }, + "touch": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/touch/-/touch-2.0.2.tgz", + "integrity": "sha512-qjNtvsFXTRq7IuMLweVgFxmEuQ6gLbRs2jQxL80TtZ31dEKWYIxRXquij6w6VimyDek5hD3PytljHmEtAs2u0A==", + "requires": { + "nopt": "1.0.10" + } + }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", @@ -4412,6 +4815,11 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, + "ua-parser-js": { + "version": "0.7.19", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.19.tgz", + "integrity": "sha512-T3PVJ6uz8i0HzPxOF9SWzWAlfN/DavlpQqepn22xgve/5QecC+XMCAtmUNnY7C9StehaV6exjUCI801lOI7QlQ==" + }, "uglify-es": { "version": "3.3.9", "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", @@ -4724,6 +5132,11 @@ } } }, + "whatwg-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/package.json b/package.json index 3864961..215abe3 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "react-dom": "^16.6.3", "react-redux": "^5.1.1", "react-router-dom": "^4.3.1", + "react-spinners": "^0.4.7", "redux": "^4.0.1", "redux-logger": "^3.0.6", "redux-thunk": "^2.3.0",