Skip to content

Commit

Permalink
Add tag filter to song page
Browse files Browse the repository at this point in the history
  • Loading branch information
jcraigk committed Oct 19, 2023
1 parent 2de8328 commit 45e8826
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 49 deletions.
16 changes: 12 additions & 4 deletions app/controllers/concerns/ambiguity/song_title.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,21 @@ def hydrate_song_page
@next_song = next_song
@view = 'songs/show'
@ambiguity_controller = 'songs'
@tracks = song.tracks
.includes(:songs, show: :venue, track_tags: :tag)
.order(@order_by)
.paginate(page: params[:page], per_page: params[:per_page].presence || 20)
@tracks = fetch_song_tracks
@tracks_likes = user_likes_for_tracks(@tracks)
end

def fetch_song_tracks
tracks = song.tracks.includes(:songs, show: :venue, track_tags: :tag).order(@order_by)
tracks = tagged_tracks(tracks)
tracks.paginate(page: params[:page], per_page: params[:per_page].presence || 20)
end

def tagged_tracks(tracks)
return tracks if params[:tag_slug].blank? || params[:tag_slug] == 'all'
tracks.tagged_with(params[:tag_slug])
end

def previous_song
Song.where('title < ?', @song.title)
.order(title: :desc)
Expand Down
48 changes: 28 additions & 20 deletions app/helpers/sort_helper.rb → app/helpers/filter_helper.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
module SortHelper
module FilterHelper
def filter_title(param_name, items)
item = items.find { |_k, v| params[param_name] == v }&.first&.html_safe
item.presence || items.first.first.html_safe
end

def filter(param_name, items) # rubocop:disable Metrics/AbcSize
skippables = %w[controller action name t slug] + [param_name.to_s]
items.map do |k, v|
link = params[param_name] == v ? "<strong>#{k}</strong>" : k
param_str = "?#{param_name}=#{CGI.escape(v)}"
params.each do |key, val|
next if key.in?(skippables)
param_str += "&#{key}=#{val}" if val.present?
end
tag.li(link_to(link.html_safe, param_str))
end.join.html_safe
end

def sort_songs_and_venues_links(item_hash)
item_hash.map do |k, v|
link = params[:sort] == v ? "<strong>#{k}</strong>" : k
Expand All @@ -24,25 +42,6 @@ def sort_tags_links(item_hash)
str.html_safe
end

def sort_filter_link_title(items)
items.each do |k, v|
return k.html_safe if params[:sort] == v || params[:sort].blank?
end
items.first.first.html_safe
end

def sort_filter(items)
items.map do |k, v|
link = params[:sort] == v ? "<strong>#{k}</strong>" : k
param_str = "?sort=#{CGI.escape(v)}"
params.each do |key, val|
next if key.in?(%w[controller action name t sort])
param_str += "&#{key}=#{val}" if val.present?
end
tag.li(link_to(link.html_safe, param_str))
end.join.html_safe
end

def sort_songs_title(items)
items.each_with_index do |(key, val), i|
return key.html_safe if (i.zero? && params[:sort].empty?) ||
Expand Down Expand Up @@ -100,4 +99,13 @@ def stored_playlist_sort_items
'<i class="glyphicon glyphicon-forward"></i> Duration' => 'duration'
}
end

def song_track_tag_items(song)
tag_data = song.tracks.joins(:tags).distinct.order('tags.name').pluck('tags.name', 'tags.slug')
items = { "<i class='glyphicon glyphicon-tags'></i>&nbsp; All Tags" => 'all' }
tag_data.each do |name, slug|
items["<i class='glyphicon glyphicon-tag'></i> #{name}"] = slug
end
items
end
end
15 changes: 14 additions & 1 deletion app/javascript/packs/application.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ html {
.current {
color: $nav_highlight !important;
font-weight: bold !important;
margin-right: 3px;
}
a:hover, a:focus {
text-decoration: underline !important;
Expand Down Expand Up @@ -1086,7 +1087,6 @@ html {
width: 100%;
border-bottom: 1px solid $hr_gray;
margin-top: 10px;
margin-bottom: 5px;
}
.next_item_link {
float: right;
Expand Down Expand Up @@ -1145,6 +1145,19 @@ html {
font-size: 18px;
}
}
.filter_label {
float: left;
width: 30px;
position: relative;
top: 7px;
font-size: 1.2em;
}
.filter_dropdown {
float: left;
}
.hr {
margin-bottom: 15px;
}
.app_callout {
* {
float: left;
Expand Down
8 changes: 8 additions & 0 deletions app/views/shared/_song_track_tag_filter.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.filter_label Tag
.filter_dropdown
.btn-group
button.btn.btn-default.dropdown-toggle type='button' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'
=> filter_title(:tag_slug, item_hash)
span.caret
ul.dropdown-menu = filter(:tag_slug, item_hash)
= clear_both
9 changes: 5 additions & 4 deletions app/views/shared/_sort_filter.html.slim
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
h3
|> Sort by
.filter_label Sort
.filter_dropdown
.btn-group
button.btn.btn-default.dropdown-toggle type='button' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'
=> sort_filter_link_title(item_hash)
=> filter_title(:sort, item_hash)
span.caret
ul.dropdown-menu = sort_filter(item_hash)
ul.dropdown-menu = filter(:sort, item_hash)
= clear_both
5 changes: 3 additions & 2 deletions app/views/shared/_sort_songs_and_venues_filter.html.slim
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
h3
|> Sort by
.filter_label Sort
.filter_dropdown
.btn-group
button.btn.btn-default.dropdown-toggle type='button' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'
=> sort_songs_title(item_hash)
span.caret
ul.dropdown-menu = sort_songs_and_venues_links(item_hash)
= clear_both
12 changes: 6 additions & 6 deletions app/views/songs/show.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@
- if @song.instrumental?
h3 (Instrumental)

h3 Total tracks: #{@song.tracks.size}
h3 Total tracks: #{@tracks.size}

.hr

= render partial: 'shared/sort_filter', locals: { item_hash: track_sort_items }
= render partial: 'shared/song_track_tag_filter', locals: { item_hash: song_track_tag_items(@song) }

.hr
br

- if @song.lyrics.present?
= link_to "#{tag.i(class: 'glyphicon glyphicon-book')} &nbsp;Lyrics".html_safe, '#', class: 'song_lyrics btn btn-default', data: { title: @song.title, lyrics: lyrics_for(@song) }
Expand All @@ -35,10 +39,6 @@

.hr

= render partial: 'shared/sort_filter', locals: { item_hash: track_sort_items }

.hr

= link_to('<< Previous Song'.html_safe, "/#{@previous_song.slug}")
= clear_both
= link_to('Next Song >>'.html_safe, "/#{@next_song.slug}", class: 'next_item_link')
Expand Down
4 changes: 2 additions & 2 deletions spec/features/songs_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@

# Default sort by Title
within('#title_box') do
expect_content('Sort by', 'Title')
expect_content('Sort', 'Title')
end
expect_content_in_order([song1, song2, song3].map(&:title))

# Sort by Track Count
within('#title_box') do
first('.btn-group').click
click_link('Track Count')
expect_content('Sort by', 'Track Count')
expect_content('Sort', 'Track Count')
end
expect_content_in_order([song2, song1, song3].map(&:title))
end
Expand Down
4 changes: 2 additions & 2 deletions spec/features/venues_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@

# Default sort by Name
within('#title_box') do
expect_content('Sort by', 'Name')
expect_content('Sort', 'Name')
end
expect_content_in_order([venue1, venue2, venue3].map(&:name))

# Sort by Track Count
within('#title_box') do
first('.btn-group').click
click_link('Show Count')
expect_content('Sort by', 'Show Count')
expect_content('Sort', 'Show Count')
end
expect_content_in_order([venue3, venue1, venue2].map(&:name))
end
Expand Down
16 changes: 8 additions & 8 deletions spec/support/feature_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,31 @@ def expect_track_sorting_controls(tracks) # rubocop:disable Metrics/AbcSize

# Default sort by Reverse date
within('#title_box') do
expect_content('Sort by', 'Reverse Date')
expect_content('Sort', 'Reverse Date')
end
expect_content_in_order(titles_by_date.reverse)

# Sort by Date
within('#title_box') do
first('.dropdown-toggle').click
click_link('Date')
expect_content('Sort by', 'Date')
expect_content('Sort', 'Date')
end
expect_content_in_order(titles_by_date)

# Sort by Likes
within('#title_box') do
first('.dropdown-toggle').click
click_link('Likes')
expect_content('Sort by', 'Likes')
expect_content('Sort', 'Likes')
end
expect_content_in_order(titles_by_likes)

# Sort by Duration
within('#title_box') do
first('.dropdown-toggle').click
click_link('Duration')
expect_content('Sort by', 'Duration')
expect_content('Sort', 'Duration')
end
expect_content_in_order(titles_by_duration)
end
Expand All @@ -64,31 +64,31 @@ def expect_show_sorting_controls(shows) # rubocop:disable Metrics/AbcSize

# Default sort by Reverse date
within('#title_box') do
expect_content('Sort by', 'Reverse Date')
expect_content('Sort', 'Reverse Date')
end
expect_content_in_order(dates_by_date.reverse)

# Sort by Date
within('#title_box') do
first('.dropdown-toggle').click
click_link('Date')
expect_content('Sort by', 'Date')
expect_content('Sort', 'Date')
end
expect_content_in_order(dates_by_date)

# Sort by Likes
within('#title_box') do
first('.dropdown-toggle').click
click_link('Likes')
expect_content('Sort by', 'Likes')
expect_content('Sort', 'Likes')
end
expect_content_in_order(dates_by_likes)

# Sort by Duration
within('#title_box') do
first('.dropdown-toggle').click
click_link('Duration')
expect_content('Sort by', 'Duration')
expect_content('Sort', 'Duration')
end
expect_content_in_order(dates_by_duration)
end
Expand Down

0 comments on commit 45e8826

Please sign in to comment.