diff --git a/Gemfile b/Gemfile index e57f43e..1d089d5 100644 --- a/Gemfile +++ b/Gemfile @@ -16,6 +16,7 @@ group :assets do gem "bourbon" gem "bootstrap-sass", "~> 2.0.4.0" gem "soundmanager-rails" + gem "font-awesome-rails" end group :development do @@ -25,8 +26,8 @@ group :development do gem "capistrano" end -# To use Jbuilder templates for JSON gem "jbuilder" +gem "haml" gem "robbie", path: "../robbie" gem "beatparser", path: "../beatparser" diff --git a/Gemfile.lock b/Gemfile.lock index 649eeb8..3bd7036 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -69,6 +69,9 @@ GEM eventmachine (0.12.10) execjs (1.4.0) multi_json (~> 1.0) + font-awesome-rails (0.4.0) + railties (~> 3.1) + haml (3.1.7) highline (1.6.13) hike (1.2.1) hogan_assets (1.3.2) @@ -175,6 +178,8 @@ DEPENDENCIES bourbon capistrano coffee-rails (~> 3.2.1) + font-awesome-rails + haml hogan_assets jbuilder jquery-rails diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js deleted file mode 100644 index 90c9df1..0000000 --- a/app/assets/javascripts/application.js +++ /dev/null @@ -1,15 +0,0 @@ -//= require jquery -//= require jquery_ujs -//= require jquery.autocomplete -//= require soundmanager -//= require vk_music -//= require mustache -//= require hogan -//= require underscore -//= require backbone -//= require backbone_rails_sync -//= require backbone_datalink -//= require backbone/beat_haven -//= require bootstrap-dropdown -//= require_tree . - diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee new file mode 100644 index 0000000..b2556a6 --- /dev/null +++ b/app/assets/javascripts/application.js.coffee @@ -0,0 +1,21 @@ +#= require jquery +#= require jquery_ujs +#= require jquery.autocomplete + +#= require soundmanager +#= require vk_music + +#= require hogan + +#= require underscore +#= require backbone +#= require backbone_rails_sync +#= require backbone_datalink +#= require backbone/beat_haven + +#= require bootstrap-dropdown +#= require bootstrap-tooltip +#= require bootstrap-popover + +#= require_tree . + diff --git a/app/assets/javascripts/backbone/autocomplete.js.coffee b/app/assets/javascripts/backbone/autocomplete.js.coffee index d8c437f..c01dc04 100644 --- a/app/assets/javascripts/backbone/autocomplete.js.coffee +++ b/app/assets/javascripts/backbone/autocomplete.js.coffee @@ -7,6 +7,6 @@ $ -> $(".player").animate(width: 518) window.desired = $(".navbar-search input").autocomplete - serviceUrl: "/api/search/complete" + serviceUrl: "/api/search/complete.json" onSelect: (selected) -> Backbone.history.navigate("/search/"+selected.replace(/\s/g, "+"), true) diff --git a/app/assets/javascripts/backbone/beat_haven.js.coffee b/app/assets/javascripts/backbone/beat_haven.js.coffee index 6b6e2bf..fa164ef 100644 --- a/app/assets/javascripts/backbone/beat_haven.js.coffee +++ b/app/assets/javascripts/backbone/beat_haven.js.coffee @@ -14,6 +14,7 @@ window.BeatHaven = User: null init: -> + new BeatHaven.Routers.Main() new BeatHaven.Routers.Artist() new BeatHaven.Routers.Album() new BeatHaven.Routers.Search() @@ -21,7 +22,7 @@ window.BeatHaven = @User = new BeatHaven.Models.User() @VK = new BeatHaven.Models.VK() - @VK.init() + # @VK.init() Backbone.history.start(pushState: true); $("a").live "click", (e) -> @@ -30,6 +31,8 @@ window.BeatHaven = Backbone.history.navigate($(this).attr("href"), true) false + # Backbone.history.navigate("/tour", true) + log: (data) -> console.log data diff --git a/app/assets/javascripts/backbone/models/vk.js.coffee b/app/assets/javascripts/backbone/models/vk.js.coffee index 364ea65..182393b 100644 --- a/app/assets/javascripts/backbone/models/vk.js.coffee +++ b/app/assets/javascripts/backbone/models/vk.js.coffee @@ -2,6 +2,7 @@ class BeatHaven.Models.VK extends Backbone.Model session_length: 3600 # seconds Music: null + BITMASK: 8 popup: -> alert(1) @@ -13,12 +14,13 @@ class BeatHaven.Models.VK extends Backbone.Model BH.VK.auth() # VK.Widgets.Like("vk-like", {type: "mini", height: 20, pageUrl: "http://beathaven.org/", text: "Like"}) - auth: -> + auth: (callback) -> BH.log "Requesting new Vkontakte session ..." window.VK.Auth.getLoginStatus (response) -> BH.VK.auth_info(response) + callback() if callback? false - , 8 + , window.BH.VK.BITMASK false auth_info: (response) -> @@ -38,6 +40,7 @@ class BeatHaven.Models.VK extends Backbone.Model else BH.log "Not authorized" + set_favorites: -> window.VK.Api.call "audio.get", uid: BH.User.vk_id(), (response) -> BH.User.set_favorites(response.response) diff --git a/app/assets/javascripts/backbone/routers/artist_router.js.coffee b/app/assets/javascripts/backbone/routers/artist_router.js.coffee index d7f2f8d..55a3d29 100644 --- a/app/assets/javascripts/backbone/routers/artist_router.js.coffee +++ b/app/assets/javascripts/backbone/routers/artist_router.js.coffee @@ -3,7 +3,7 @@ class BeatHaven.Routers.Artist extends Backbone.Router "artist/:name": "show" show: (name) -> - artist = new BeatHaven.Models.Artist(id: name) + artist = new BeatHaven.Models.Artist(id: name.replace(/\s|%2BF/g, "+")) artist.fetch() view = new BeatHaven.Views.ArtistShow(model: artist) $("#main").html(view.render().el) diff --git a/app/assets/javascripts/backbone/routers/main_router.js.coffee b/app/assets/javascripts/backbone/routers/main_router.js.coffee new file mode 100644 index 0000000..6f8323b --- /dev/null +++ b/app/assets/javascripts/backbone/routers/main_router.js.coffee @@ -0,0 +1,7 @@ +class BeatHaven.Routers.Main extends Backbone.Router + routes: + "tour": "tour" + + tour: -> + view = new BeatHaven.Views.MainTour() + $(".tour").html(view.render().el) diff --git a/app/assets/javascripts/backbone/templates/artist/show.hamstache_ b/app/assets/javascripts/backbone/templates/artist/show.hamstache_ new file mode 100644 index 0000000..2916b59 --- /dev/null +++ b/app/assets/javascripts/backbone/templates/artist/show.hamstache_ @@ -0,0 +1,36 @@ +.artist-page + %h1 {{ artist_title }} + .artist-info + .pic + %img{ src: "{{ artist_pic }}", alt: "{{ artist_title }}" } + .bio {{& artist_bio}} + + .albums + {{#artist_albums}} + .album + .pic + %img{ src: "{{ album_pic }}", alt: "{{ album_title }}" } + %br + .bh-underlay-blue + %a.btn.btn-bh-dark.album-add{ href: "" } + %i.icon-plus.icon-white + Add to playlist + .bh-underlay-green + %a.btn.btn-bh-dark.album-play{ href: "" } + %i.icon-play.icon-white + Play + + %h2.title {{ album_title }} ({{ album_year }}) + %ul.tracks + {{# album_tracks }} + %li{ "data-id" => "{{ track_id }}" } + %a.btn.btn-round.track-play{ href: "" } + %i.icon-play + %a.btn.btn-round.track-pause{ href: "" } + %i.icon-pause + .title + .inner + %a.track-link{ href: "{{track_url}}" } {{ track_title }} + %span.length {{ track_length }} + %a.btn.btn-round.track-add{ href: "" } + %i.icon-plus diff --git a/app/assets/javascripts/backbone/templates/artist/show.mustache b/app/assets/javascripts/backbone/templates/artist/show.mustache index 3030d1d..71f472f 100644 --- a/app/assets/javascripts/backbone/templates/artist/show.mustache +++ b/app/assets/javascripts/backbone/templates/artist/show.mustache @@ -12,7 +12,7 @@
{{album_title}}
- Add to playlist + Add to playlist
Play diff --git a/app/assets/javascripts/backbone/templates/main/tour.mustache b/app/assets/javascripts/backbone/templates/main/tour.mustache new file mode 100644 index 0000000..051b2b3 --- /dev/null +++ b/app/assets/javascripts/backbone/templates/main/tour.mustache @@ -0,0 +1,63 @@ + + + +
+
Это поиск
+
+

Он твой лучший друг.

+

Начни вписывать в него название группы или альбома и он с первой же буквы постарается угадать что ты хочешь послушать.

+

+ Дальше! +
+
+
+
Музыка!
+
+

Чтобы начать слушать музыку достаточно нажать на кнопку слева от любимой песни

+

Послушаем?

+

+ Давай! +
+
+
+
Прогресс-бар
+
+

На нем всегда отображается название песни, которая играет в данный момент.

+

Еще с его помощью можно перематывать песню.

+

+ Понял +
+
+
+
Кнопочки
+
+

Предыдущая и следующая песня, плей/пауза, все как обычно.

+

Думаю, ты уже достаточно освоился. Наслаждайся музыкой!

+

+ Спасибо! +
+
diff --git a/app/assets/javascripts/backbone/views/artist/artist_show.js.coffee b/app/assets/javascripts/backbone/views/artist/artist_show.js.coffee index ae8f200..c200e94 100644 --- a/app/assets/javascripts/backbone/views/artist/artist_show.js.coffee +++ b/app/assets/javascripts/backbone/views/artist/artist_show.js.coffee @@ -1,5 +1,5 @@ class BeatHaven.Views.ArtistShow extends Backbone.View - template: HoganTemplates["backbone/templates/artist/show"] + template: HoganTemplates["artist/show"] initialize: -> @model.on("change", @render, this) diff --git a/app/assets/javascripts/backbone/views/main/main_tour.js.coffee b/app/assets/javascripts/backbone/views/main/main_tour.js.coffee new file mode 100644 index 0000000..ff5731f --- /dev/null +++ b/app/assets/javascripts/backbone/views/main/main_tour.js.coffee @@ -0,0 +1,7 @@ +class BeatHaven.Views.MainTour extends Backbone.View + template: HoganTemplates["backbone/templates/main/tour"] + + render: -> + $(".fullscreen").show() + $(@el).html(@template.render()) + this diff --git a/app/assets/javascripts/bindings/tour.js.coffee b/app/assets/javascripts/bindings/tour.js.coffee new file mode 100644 index 0000000..d56eaa9 --- /dev/null +++ b/app/assets/javascripts/bindings/tour.js.coffee @@ -0,0 +1,75 @@ +window.tour_auth = -> + VK.Auth.login (response) -> + BH.VK.auth_info(response) + if response.session? + $(".tour .step").hide() + $(".tour .step-2").show() + $(".tour .step-2 .your-name-here").text("#{response.session.user.first_name}") + $(".tour .step-2 .your-favorite-artist-here").text("Foo Fighters") + Backbone.history.navigate("/artist/Foo+Fighters", true) + else + $(".tour .step").hide() + $(".tour .step-1a").show() + , BH.VK.BITMASK + +$ -> + $(".tour .step-1 a").live "click", (e) -> + e.preventDefault() + tour_auth() + + $(".tour .step-1a a.again").live "click", (e) -> + e.preventDefault() + tour_auth() + + $(".tour .step-2 a").live "click", (e) -> + e.preventDefault() + $(".tour").hide() + $(".fullscreen").css(opacity: .3) + $(".navbar .search-query").popover( + placement: "bottom" + title: $(".tour .step-3 .title") + content: $(".tour .step-3 .content").html() + html: true + trigger: "manual" + ).popover("show") + + $("a.tour-step-3").live "click", (e) -> + e.preventDefault() + $(".navbar .search-query").popover("hide") + $(".artist-page .tracks li:first .track-play").popover( + placement: "top" + title: $(".tour .step-4 .title") + content: $(".tour .step-4 .content").html() + html: true + trigger: "manual" + ).popover("show") + + $("a.tour-step-4").live "click", (e) -> + e.preventDefault() + $(".artist-page .tracks li:first .track-play").popover("hide").trigger("click") + $(".player .progress-bar").popover( + placement: "bottom" + title: $(".tour .step-5 .title") + content: $(".tour .step-5 .content").html() + html: true + trigger: "manual" + ).popover("show") + + $("a.tour-step-5").live "click", (e) -> + e.preventDefault() + $(".player .progress-bar").popover("hide") + $(".player .controls").popover( + placement: "bottom" + title: $(".tour .step-6 .title") + content: $(".tour .step-6 .content").html() + html: true + trigger: "manual" + ).popover("show") + + $("a.tour-step-6").live "click", (e) -> + e.preventDefault() + $(".player .controls").popover("hide") + $(".popover").remove() + $(".fullscreen").hide() + + diff --git a/app/assets/stylesheets/album-track.css.scss b/app/assets/stylesheets/album-track.css.scss index a181397..715cf1d 100644 --- a/app/assets/stylesheets/album-track.css.scss +++ b/app/assets/stylesheets/album-track.css.scss @@ -59,7 +59,7 @@ border-radius: 50px; i { - margin: 3px 0 0 -1px; + margin: 6px 0 0 -2px; } } @@ -102,6 +102,7 @@ margin: 0; padding: 0; color: #808080; + text-shadow: none; .artist-page { color: #808080; @@ -132,6 +133,10 @@ top: 3px; right: 5px; display: none; + + i { + margin-left: -3px; + } } // li:hover diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss index 01f5029..d8bef5b 100644 --- a/app/assets/stylesheets/application.css.scss +++ b/app/assets/stylesheets/application.css.scss @@ -1,5 +1,7 @@ @import "bourbon"; -@import "bootstrap"; +@import "bootstrap_custom"; +@import "font-awesome"; + @import "noise"; @import "buttons"; @import "autocomplete"; @@ -7,6 +9,8 @@ @import "album-track"; @import "player"; @import "auth"; +@import "popup"; +@import "tour"; @import url(http://fonts.googleapis.com/css?family=Lobster+Two:400,400italic,700); @import url(http://fonts.googleapis.com/css?family=Source+Sans+Pro); diff --git a/app/assets/stylesheets/auth.css.scss b/app/assets/stylesheets/auth.css.scss index 545b58e..698550c 100644 --- a/app/assets/stylesheets/auth.css.scss +++ b/app/assets/stylesheets/auth.css.scss @@ -1,3 +1,14 @@ -.navbar .auth { - margin: 14px 10px 0 15px; +.navbar { + .preferences { + margin: 14px 10px 0 15px; + font-size: 27px; + color: #e0e0e0; + text-shadow: 0 0 2px rgba(255, 255, 255, .6); + text-decoration: none; + + &:hover { + color: #fafafa; + text-shadow: 0 0 4px rgba(255, 255, 255, .9); + } + } } diff --git a/app/assets/stylesheets/bootstrap_custom.css.scss b/app/assets/stylesheets/bootstrap_custom.css.scss new file mode 100644 index 0000000..e6964cb --- /dev/null +++ b/app/assets/stylesheets/bootstrap_custom.css.scss @@ -0,0 +1,51 @@ +@import "bootstrap/variables"; // Modify this for custom colors, font-sizes, etc +@import "bootstrap/mixins"; + +// CSS Reset +@import "bootstrap/reset"; + +// Grid system and page structure +@import "bootstrap/scaffolding"; +@import "bootstrap/grid"; +@import "bootstrap/layouts"; + +// Base CSS +@import "bootstrap/type"; +@import "bootstrap/code"; +@import "bootstrap/forms"; +// @import "bootstrap/tables"; + +// Components: common +// @import "bootstrap/sprites"; +// @import "bootstrap/dropdowns"; +// @import "bootstrap/wells"; +@import "bootstrap/component-animations"; +// @import "bootstrap/close"; + +// Components: Buttons & Alerts +@import "bootstrap/buttons"; +// @import "bootstrap/button-groups"; +@import "bootstrap/alerts"; // Note: alerts share common CSS with buttons and thus have styles in buttons.less + +// Components: Nav +@import "bootstrap/navs"; +@import "bootstrap/navbar"; +// @import "bootstrap/breadcrumbs"; +// @import "bootstrap/pagination"; +// @import "bootstrap/pager"; + +// Components: Popovers +@import "bootstrap/modals"; +@import "bootstrap/tooltip"; +@import "bootstrap/popovers"; + +// Components: Misc +// @import "bootstrap/thumbnails"; +// @import "bootstrap/labels-badges"; +// @import "bootstrap/progress-bars"; +// @import "bootstrap/accordion"; +// @import "bootstrap/carousel"; +@import "bootstrap/hero-unit"; + +// Utility classes +@import "bootstrap/utilities"; // Has to be last to override when necessary diff --git a/app/assets/stylesheets/buttons.css.scss b/app/assets/stylesheets/buttons.css.scss index 84c88dd..36d779d 100644 --- a/app/assets/stylesheets/buttons.css.scss +++ b/app/assets/stylesheets/buttons.css.scss @@ -16,6 +16,7 @@ background-position: 0 0 !important; color: #fafafa; text-shadow: 0 1px 1px rgba(0, 0, 0, .35); + &:hover { color: #ffffff; } diff --git a/app/assets/stylesheets/player.css.scss b/app/assets/stylesheets/player.css.scss index 279fff7..4d70c3c 100644 --- a/app/assets/stylesheets/player.css.scss +++ b/app/assets/stylesheets/player.css.scss @@ -6,7 +6,17 @@ margin: 3px 0 0 -103px; a { - margin: 5px 6px 0 -9px; + @include inline-block; + margin: 11px 10px 0 0; + font-size: 27px; + color: #e0e0e0; + text-shadow: 0 0 2px rgba(255, 255, 255, .6); + text-decoration: none; + + &:hover { + color: #fafafa; + text-shadow: 0 0 4px rgba(255, 255, 255, .9); + } } .pause { diff --git a/app/assets/stylesheets/popup.css.scss b/app/assets/stylesheets/popup.css.scss new file mode 100644 index 0000000..5da3184 --- /dev/null +++ b/app/assets/stylesheets/popup.css.scss @@ -0,0 +1,19 @@ +.fullscreen { + display: none; + position: absolute; + z-index: 9999; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, .7); +} +.popup { + position: absolute; + z-index: 99999; + top: 50%; + left: 50%; + width: 640px; + height: 360px; + margin: -240px 0 0 -380px; +} diff --git a/app/assets/stylesheets/tour.css.scss b/app/assets/stylesheets/tour.css.scss new file mode 100644 index 0000000..d39a313 --- /dev/null +++ b/app/assets/stylesheets/tour.css.scss @@ -0,0 +1,13 @@ +.tour .step { + display: none; +} +.tour .step-1 { + display: block; +} +.popover { + z-index: 99999; + + p { + margin: 8px 0; + } +} diff --git a/app/controllers/api/albums_controller.rb b/app/controllers/api/albums_controller.rb index f9d90fb..45f1a40 100644 --- a/app/controllers/api/albums_controller.rb +++ b/app/controllers/api/albums_controller.rb @@ -1,15 +1,13 @@ module Api - class AlbumsController < ::ApplicationController + class AlbumsController < BaseController def picture album = Album.find(params[:id]) redirect_to album.load_pic end def show - album = Album.find(params[:id]) - return render json: { fail: true } if album.nil? - - render json: album.dump_json + @album = Album.find(params[:id]) + return render json: { fail: true } if @album.nil? end end end diff --git a/app/controllers/api/artists_controller.rb b/app/controllers/api/artists_controller.rb index 463406c..30073ad 100644 --- a/app/controllers/api/artists_controller.rb +++ b/app/controllers/api/artists_controller.rb @@ -1,10 +1,8 @@ module Api - class ArtistsController < ::ApplicationController + class ArtistsController < BaseController def show - artist = Artist.with_name(params[:id].gsub("+", " ")) - return render json: { fail: true } if artist.nil? - - render json: artist.dump_json + @artist = Artist.with_name(params[:id].gsub("+", " ")) + return render json: { fail: true } if @artist.nil? end end end diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb new file mode 100644 index 0000000..97784c8 --- /dev/null +++ b/app/controllers/api/base_controller.rb @@ -0,0 +1,5 @@ +module Api + class BaseController < ::ApplicationController + respond_to :json + end +end diff --git a/app/controllers/api/search_controller.rb b/app/controllers/api/search_controller.rb index eb41277..89db91a 100644 --- a/app/controllers/api/search_controller.rb +++ b/app/controllers/api/search_controller.rb @@ -1,5 +1,5 @@ module Api - class SearchController < ApplicationController + class SearchController < BaseController def complete return render json: { suggestions: [] } if params[:query].to_s.length == 0 diff --git a/app/controllers/api/session_controller.rb b/app/controllers/api/session_controller.rb index 7179273..35f35ef 100644 --- a/app/controllers/api/session_controller.rb +++ b/app/controllers/api/session_controller.rb @@ -1,5 +1,5 @@ module Api - class SessionController < ApplicationController + class SessionController < BaseController def auth render json: { error: "Signature verification failed!" } unless request_valid? diff --git a/app/models/album.rb b/app/models/album.rb index 70254ee..21aeeda 100644 --- a/app/models/album.rb +++ b/app/models/album.rb @@ -6,10 +6,10 @@ class Album < ActiveRecord::Base self .where('"albums"."year" > ?', 0) .where(is_hidden: false) - .joins(:tracks) - .group('"albums"."id"') - .having('count("tracks"."id") > ?', 0) - .order('"albums"."year" ASC') + .includes(:tracks) + # .group('"albums"."id"') + # .having('count("tracks"."id") > ?', 0) + # .order('"albums"."year" ASC') } attr_accessible :artist_id, :pic, :rovi_id, :title, :year, :is_hidden @@ -24,7 +24,13 @@ class Album < ActiveRecord::Base end def load_pic - info = BeatParser::Sources::Lastfm.album_info((artist.nil? ? VA : artist.name), title) + info = begin + response = LastFM::Album.get_info(artist: (artist.nil? ? VA : artist.name), album: title) + { pic: response["album"]["image"][3]["#text"] } + rescue => e + { pic: nil } + end + unless info[:pic].nil? update_attributes(pic: info[:pic]) info[:pic] @@ -37,69 +43,35 @@ class Album < ActiveRecord::Base "/album/#{id}" end - def dump_json - Jbuilder.encode do |j| - j.album_title title - j.album_year year - j.album_pic pic_safe - j.album_tracks tracks.to_a do |j, track| - j.track_id track.id - j.track_title track.title - j.track_duration track.duration - j.track_artists track.artists do |j, artist| - j.artist_title artist.name - j.artist_url artist.url - end - j.track_disc track.disc_id - j.track_position track.position - j.track_length track.length - j.meta do |j| - j.id track.id - j.title track.title - j.duration track.duration - j.length track.length - j.artists track.artists.map(&:name) - j.album title - j.album_pic pic_safe - end - end - end - - - end - def import return unless rovi_id? - Album.import(Robbie::Album.find(rovi_id)) + robbie_album = Robbie::Album.find(rovi_id) + return if robbie_album.nil? + + update_attributes( + title: robbie_album.title, + year: robbie_album.year, + tracks: robbie_album.tracks.each { |robbie_track| + track = Track.find_or_create_by_rovi_id(robbie_track.id) + track.update_attributes( + disc_id: robbie_track.disc_id, + position: robbie_track.position, + title: robbie_track.title, + duration: robbie_track.duration, + artists: robbie_track.artists.map { |robbie_artist| + track_artist = Artist.find_or_create_by_rovi_id(robbie_artist.id) + track_artist.update_attributes( + name: robbie_artist.name + ) + track_artist + } + ) + track + } + ) + + self end - class << self - def import(rovi_album) - data = BeatParser::Aggregator.new.album(rovi_album.id) - album = Album.find_or_create_by_rovi_id(data[:id]) - album.update_attributes( - title: data[:title], - year: data[:year].to_i - ) - data[:tracks].each do |track_meta| - track = Track.find_or_create_by_rovi_id(track_meta[:id]) - track.update_attributes( - album_id: album.id, - disc_id: track_meta[:disc_id], - position: track_meta[:position], - title: track_meta[:title], - duration: track_meta[:duration] - ) - track_meta[:artists].each do |performer| - performer_artist = Artist.find_or_create_by_rovi_id(performer[:id]) - performer_artist.update_attributes( - name: performer[:name] - ) - Performer.find_or_create_by_artist_id_and_track_id(performer_artist.id, track.id) - end - end - album - end - end end diff --git a/app/models/artist.rb b/app/models/artist.rb index e9dda5d..c6fe0ed 100644 --- a/app/models/artist.rb +++ b/app/models/artist.rb @@ -6,6 +6,10 @@ class Artist < ActiveRecord::Base attr_accessible :bio, :is_group, :name, :pic, :rovi_id + scope :discography, lambda { + includes(:albums).includes(:tracks) + } + def loaded? pic? && bio? end @@ -14,47 +18,36 @@ class Artist < ActiveRecord::Base "/artist/#{name.gsub(/\s/, "+")}" end - def dump_json - Jbuilder.encode do |j| - j.artist_title name - j.artist_pic pic - j.artist_bio bio - j.artist_loaded loaded? - j.artist_url url - j.artist_albums albums.shown.to_a do |j, album| - j.album_title album.title - j.album_year album.year - j.album_pic album.pic_safe - j.album_tracks album.tracks.to_a do |j, track| - j.track_id track.id - j.track_title track.title - j.track_duration track.duration - j.track_disc track.disc_id - j.track_position track.position - j.meta do |j| - j.id track.id - j.title track.title - j.duration track.duration - j.length track.length - j.artists track.artists.map(&:name) - j.album album.title - j.album_pic album.pic_safe - end - end - end - end - end - def import return unless rovi_id? - Artist.import(Robbie::Artist.find(rovi_id)) + robbie_artist = Robbie::Artist.find(rovi_id) + return if robbie_artist.nil? + + update_attributes( + name: robbie_artist.name, + is_group: robbie_artist.is_group, + pic: nil, + bio: nil, + albums: robbie_artist.albums.map{ |robbie_album| + Album.find_or_create_by_rovi_id(robbie_album.id).import + }, + genres: robbie_artist.genres.map{ |robbie_genre| + genre = Genre.find_or_create_by_rovi_id(robbie_genre.id) + genre.update_attributes( + name: robbie_genre.name + ) + genre + } + ) + + self end class << self def with_name(name) # DB lookup - artist = find_by_name(name) + artist = where(name: name).discography.first return artist unless artist.nil? # Rovi correction @@ -62,51 +55,7 @@ class Artist < ActiveRecord::Base return artist if rovi_artist && artist = find_by_rovi_id(rovi_artist.id) # Parsing artist if ok - import(rovi_artist) if rovi_artist - end - - def import(rovi_artist) - data = BeatParser::Aggregator.new.artist(rovi_artist.id) - artist = Artist.find_or_create_by_rovi_id(data[:id]) - artist.update_attributes( - name: data[:name], - is_group: data[:is_group], - pic: data[:pic], - bio: data[:bio] - ) - data[:albums].each do |album_meta| - album = Album.find_or_create_by_rovi_id(album_meta[:id]) - album.update_attributes( - artist_id: artist.id, - title: album_meta[:title], - year: album_meta[:year].to_i - ) - album_meta[:tracks].each do |track_meta| - track = Track.find_or_create_by_rovi_id(track_meta[:id]) - track.update_attributes( - album_id: album.id, - disc_id: track_meta[:disc_id], - position: track_meta[:position], - title: track_meta[:title], - duration: track_meta[:duration] - ) - track_meta[:artists].each do |performer| - performer_artist = Artist.find_or_create_by_rovi_id(performer[:id]) - performer_artist.update_attributes( - name: performer[:name] - ) - Performer.find_or_create_by_artist_id_and_track_id(performer_artist.id, track.id) - end - end - end - data[:genres].each do |genre_meta| - genre = Genre.find_or_create_by_rovi_id(genre_meta[:id]) - genre.update_attributes( - name: genre_meta[:name] - ) - ArtistGenre.find_or_create_by_artist_id_and_genre_id(artist.id, genre.id) - end - artist + Artist.create(rovi_id: robbie_artist.id).import end end end diff --git a/app/models/track.rb b/app/models/track.rb index 17515e0..855603f 100644 --- a/app/models/track.rb +++ b/app/models/track.rb @@ -4,6 +4,9 @@ class Track < ActiveRecord::Base has_many :artists, through: :performers attr_accessible :album_id, :disc_id, :duration, :position, :rovi_id, :title + scope :with_artists, lambda{ + includes(:artists) + } def length return if duration.nil? diff --git a/app/views/api/albums/show.json.jbuilder b/app/views/api/albums/show.json.jbuilder new file mode 100644 index 0000000..b416774 --- /dev/null +++ b/app/views/api/albums/show.json.jbuilder @@ -0,0 +1,24 @@ +json.album_title @album.title +json.album_year @album.year +json.album_pic @album.pic_safe +json.album_tracks @album.tracks.to_a do |json, track| + json.track_id track.id + json.track_title track.title + json.track_duration track.duration + json.track_artists track.artists do |json, artist| + json.artist_title artist.name + json.artist_url artist.url + end + json.track_disc track.disc_id + json.track_position track.position + json.track_length track.length + json.meta do |json| + json.id track.id + json.title track.title + json.duration track.duration + json.length track.length + json.artists track.artists.map(&:name) + json.album title + json.album_pic pic_safe + end +end diff --git a/app/views/api/artists/show.json.jbuilder b/app/views/api/artists/show.json.jbuilder new file mode 100644 index 0000000..5de588c --- /dev/null +++ b/app/views/api/artists/show.json.jbuilder @@ -0,0 +1,26 @@ +json.artist_title @artist.name +json.artist_pic @artist.pic +json.artist_bio @artist.bio +json.artist_loaded @artist.loaded? +json.artist_url @artist.url +json.artist_albums @artist.albums.shown.to_a do |json, album| + json.album_title album.title + json.album_year album.year + json.album_pic album.pic_safe + json.album_tracks album.tracks.to_a do |json, track| + json.track_id track.id + json.track_title track.title + json.track_length track.length + json.track_disc track.disc_id + json.track_position track.position + json.meta do |json| + json.id track.id + json.title track.title + json.duration track.duration + json.length track.length + json.artists track.artists.map(&:name) + json.album album.title + json.album_pic album.pic_safe + end + end +end diff --git a/app/views/application/_player.html.erb b/app/views/application/_player.html.erb deleted file mode 100644 index 774eb8d..0000000 --- a/app/views/application/_player.html.erb +++ /dev/null @@ -1,13 +0,0 @@ -
-
- - - - -
-
-
-
Waiting...
-
-
-
diff --git a/app/views/application/_player.html.haml b/app/views/application/_player.html.haml new file mode 100644 index 0000000..871e36f --- /dev/null +++ b/app/views/application/_player.html.haml @@ -0,0 +1,10 @@ +.player.pull-right + .controls + %a.icon-backward.prev{ href: "" } + %a.icon-play.play{ href: "" } + %a.icon-pause.pause{ href: "" } + %a.icon-forward.next{ href: "" } + .progress-bar + .bar + .title Waiting... + .move-it diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb deleted file mode 100644 index bc51136..0000000 --- a/app/views/layouts/application.html.erb +++ /dev/null @@ -1,32 +0,0 @@ - - - - BeatHaven - <%= stylesheet_link_tag "application", media: "all" %> - <%= javascript_include_tag "application" %> - <%= javascript_include_tag "http://vkontakte.ru/js/api/openapi.js" %> - <%= csrf_meta_tags %> - - - - - -
You can't steal what's free
- - - diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml new file mode 100644 index 0000000..8d36d68 --- /dev/null +++ b/app/views/layouts/application.html.haml @@ -0,0 +1,26 @@ +!!! +%html + %head + %title BeatHaven + = stylesheet_link_tag "application", media: "all" + = javascript_include_tag "application" + = javascript_include_tag "http://vkontakte.ru/js/api/openapi.js" + = csrf_meta_tags + :javascript + window.VK_APP_ID = 2335068; + %body + + %div.navbar.navbar-fixed-top + .navbar-inner + .container + %a.brand{ href: "/" } BeatHaven + %form.navbar-search.pull-left + %input.search-query{ type: "search", placeholder: "Search" } + .pull-right + %a.icon-cog.preferences{ href: "/preferences" } + = render partial: "player" + + .container#main You can't steal what's free + .fullscreen + .tour + %div{ style: "font: 32px FontAwesome;"}  diff --git a/config/application.rb b/config/application.rb index 9d0875c..17c5ca4 100644 --- a/config/application.rb +++ b/config/application.rb @@ -10,7 +10,7 @@ require "sprockets/railtie" if defined?(Bundler) # If you precompile assets before deploying to production, use this line - Bundler.require(*Rails.groups(:assets => %w(development test))) + Bundler.require(*Rails.groups(:assets => %w[ development test ])) # If you want your assets lazily compiled in production, use this line # Bundler.require(:default, :assets, Rails.env) end diff --git a/config/environments/development.rb b/config/environments/development.rb index 21bb8f4..35f58ba 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -33,5 +33,6 @@ BeatHaven::Application.configure do config.assets.compress = false # Expands the lines which load the assets - config.assets.debug = true + config.assets.debug = false + config.assets.logger = nil end diff --git a/config/environments/production.rb b/config/environments/production.rb index 4a2efc9..e12406a 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -25,7 +25,7 @@ BeatHaven::Application.configure do # Specifies the header that your server uses for sending files # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache - # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx + config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. # config.force_ssl = true diff --git a/config/initializers/hogan_templates.rb b/config/initializers/hogan_templates.rb index 122204f..601a076 100644 --- a/config/initializers/hogan_templates.rb +++ b/config/initializers/hogan_templates.rb @@ -1,3 +1,3 @@ HoganAssets::Config.configure do |config| - config.path_prefix = "backbone/templates/" + config.path_prefix = "backbone/templates" end diff --git a/config/routes.rb b/config/routes.rb index 810b53e..4821e90 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,6 @@ BeatHaven::Application.routes.draw do namespace :api do - resources :artists, only: [:show], constraints: { id: /.+/ } + resources :artists, only: [:show], constraints: { id: /.+/ }, format: :json resources :albums, only: [:show, :picture] do member { get :picture } end