Skip to content

Commit

Permalink
Paginate Playlist History view; Install importmap and stimulus to con…
Browse files Browse the repository at this point in the history
…trol the front end behavior; make the missing songs in the history link to archive.org
  • Loading branch information
hebron-george committed Nov 10, 2024
1 parent b5f261b commit aec54a5
Show file tree
Hide file tree
Showing 26 changed files with 265 additions and 61 deletions.
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ gem "dockerfile-rails", ">= 1.6", :group => :development

# Views
gem "slim-rails", "~> 3.6"
gem "kaminari" # Pagination for Playlist History page

# Error tracking
gem "honeybadger", "~> 5.15"
Expand All @@ -71,3 +72,5 @@ gem "honeybadger", "~> 5.15"
gem 'sidekiq'
gem 'sidekiq-cron'
gem "redis", "~> 5.2"
gem "importmap-rails"
gem "stimulus-rails"
21 changes: 21 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,25 @@ GEM
honeybadger (5.15.6)
i18n (1.14.6)
concurrent-ruby (~> 1.0)
importmap-rails (2.0.1)
actionpack (>= 6.0.0)
activesupport (>= 6.0.0)
railties (>= 6.0.0)
jbuilder (2.11.5)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
kaminari (1.2.2)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.2)
kaminari-activerecord (= 1.2.2)
kaminari-core (= 1.2.2)
kaminari-actionview (1.2.2)
actionview
kaminari-core (= 1.2.2)
kaminari-activerecord (1.2.2)
activerecord
kaminari-core (= 1.2.2)
kaminari-core (1.2.2)
listen (3.0.8)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
Expand Down Expand Up @@ -266,6 +282,8 @@ GEM
actionpack (>= 5.2)
activesupport (>= 5.2)
sprockets (>= 3.0.0)
stimulus-rails (1.3.4)
railties (>= 6.0.0)
temple (0.10.3)
thor (1.3.1)
tilt (2.1.0)
Expand Down Expand Up @@ -302,7 +320,9 @@ DEPENDENCIES
dotenv-rails
groupdate
honeybadger (~> 5.15)
importmap-rails
jbuilder (~> 2.10)
kaminari
listen (>= 3.0.5, < 3.2)
net-imap
net-pop
Expand All @@ -322,6 +342,7 @@ DEPENDENCIES
slim-rails (~> 3.6)
spring
spring-watcher-listen (~> 2.0.0)
stimulus-rails
turbolinks (~> 5)
tzinfo-data
uglifier (>= 1.3.0)
Expand Down
2 changes: 2 additions & 0 deletions app/assets/config/manifest.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//= link_tree ../images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css
//= link_tree ../../javascript .js
//= link_tree ../../../vendor/javascript .js
18 changes: 0 additions & 18 deletions app/assets/javascripts/application.js

This file was deleted.

15 changes: 14 additions & 1 deletion app/controllers/playlist_history_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ def index

def show
playlist_id = params[:playlist_id]
@history = TrackedPlaylist.get_history(playlist_id)
page = params[:page] || 1
@history = TrackedPlaylist.get_history(playlist_id, page)

respond_to do |format|
format.html # renders the full page for normal requests
end
end

def load_more_history
playlist_id = params[:playlist_id]
page = params[:page]
@history = TrackedPlaylist.get_history(playlist_id, page)

render partial: 'load_more_history'
end
end
1 change: 1 addition & 0 deletions app/javascript/application.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import "controllers"
9 changes: 9 additions & 0 deletions app/javascript/controllers/application.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Application } from "@hotwired/stimulus"

const application = Application.start()

// Configure Stimulus development experience
application.debug = false
window.Stimulus = application

export { application }
4 changes: 4 additions & 0 deletions app/javascript/controllers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Import and register all your controllers from the importmap via controllers/**/*_controller
import { application } from "./application"
import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
eagerLoadControllersFrom("controllers", application)
35 changes: 35 additions & 0 deletions app/javascript/controllers/load_more_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
static targets = ["button", "timeline", "loading"];

initialize() {
this.loading = false;
}

loadMore(event) {
event.preventDefault();

if (this.loading) return;

this.loading = true;
this.loadingTarget.style.display = "block"; // Show loading indicator

const url = this.buttonTarget.getAttribute("href");

if (url) {
fetch(url, { headers: { "X-Requested-With": "XMLHttpRequest" } })
.then(response => response.text())
.then(html => {
this.buttonTarget.remove(); // Remove the old "Load More" button from the page
this.timelineTarget.insertAdjacentHTML("beforeend", html); // Append new items
// this.updateButtonUrl();
})
.catch(error => console.error("Error loading more items:", error))
.finally(() => {
this.loading = false;
this.loadingTarget.style.display = "none"; // Hide loading indicator
});
}
}
}
58 changes: 42 additions & 16 deletions app/models/tracked_playlist.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,53 @@ class TrackedPlaylist < ApplicationRecord
validates :playlist_id, uniqueness: {message: "This playlist is already being tracked."}

has_many :playlist_snapshots, foreign_key: :playlist_id, primary_key: :playlist_id
has_many :playlist_deltas

def self.get_history(playlist_id)
def self.get_history(playlist_id, page)
playlist = find_by_playlist_id(playlist_id)
results = []
playlist.playlist_snapshots.order(:created_at).find_each(batch_size: 1).each_cons(2) do |p|
older, newer = p
diff = PlaylistDifferenceCalculator.calculate_diffs(newer.playlist_items, older.playlist_items)
if diff.any_changes?
result = {
start_date: older.created_at,
end_date: newer.created_at,
removed: diff.removed_songs.map(&:title),
added: diff.added_songs.map(&:title),
}
results << result
end
end
# results = []
# playlist.playlist_snapshots.find_each(batch_size: 1).each_cons(2) do |p|
# older, newer = p
# diff = PlaylistDifferenceCalculator.calculate_diffs(newer.playlist_items, older.playlist_items)
# if diff.any_changes?
# result = {
# start_date: older.created_at,
# end_date: newer.created_at,
# removed: diff.removed_songs.map(&:title),
# added: diff.added_songs.map(&:title),
# }
# results << result
# end
# end

# results = playlist.playlist_deltas.includes(:playlist_snapshot).map do |delta|
# snapshot = delta.playlist_snapshot
# {
# start_date: snapshot.created_at,
# end_date: snapshot.created_at,
# removed: delta.removed.map { |d| d["title"] },
# added: delta.added.map { |d| d["title"] },
# }
# end
deltas = playlist.playlist_deltas
.joins(:playlist_snapshot)
.select('playlist_delta.*, playlist_snapshots.created_at')
.order('playlist_snapshots.created_at DESC')
.page(page)
.per(50)

# # Preprocess added and removed data to make rendering faster
# deltas = deltas.map do |delta|
# {
# created_at: delta.playlist_snapshot.created_at,
# added: delta.added.map { |song| song["title"] },
# removed: delta.removed.map { |song| song["title"] }
# }
# end

{
name: playlist.name,
changes: results,
changes: deltas,
}
end

Expand Down
3 changes: 2 additions & 1 deletion app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
<%= csp_meta_tag %>

<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
<%#= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
<%= javascript_importmap_tags %>
</head>

<body>
Expand Down
35 changes: 35 additions & 0 deletions app/views/playlist_history/_delta_card.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<div class="card">
<div class="info">
<h3 class="title"><%= delta[:created_at].strftime("%b %d, %Y") %></h3>

<% if delta[:added].present? %>
<div>
<h5>Added</h5>
<ul>
<% delta[:added].each do |song| %>
<% if ["private video", "deleted video"].include?(song["title"].downcase) %>
<li><a href="https://web.archive.org/web/*/<%= song["url"] %>" target="_blank" rel="noopener noreferrer">Song Removed - Click to look up an archive for the link.</a></li>
<% else %>
<li><a href="<%= song["url"] %>" target="_blank" rel="noopener noreferrer"><%= song["title"] %></a></li>
<% end %>
<% end %>
</ul>
</div>
<% end %>

<% if delta[:removed].present? %>
<div>
<h5>Removed</h5>
<ul>
<% delta[:removed].each do |song| %>
<% if ["private video", "deleted video"].include?(song["title"].downcase) %>
<li><a href="https://web.archive.org/web/*/<%= song["url"] %>" target="_blank" rel="noopener noreferrer">Song Removed - Click to look up an archive for the link.</a></li>
<% else %>
<li><a href="https://web.archive.org/web/*/<%= song["url"] %>" target="_blank" rel="noopener noreferrer"><%= song["title"] %></a></li>
<% end %>
<% end %>
</ul>
</div>
<% end %>
</div>
</div>
3 changes: 3 additions & 0 deletions app/views/playlist_history/_load_more_history.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<%= render partial: 'delta_card', collection: @history[:changes], as: :delta %>

<%= render partial: 'load_more_history_button', locals: {history: @history, params: params} %>
8 changes: 8 additions & 0 deletions app/views/playlist_history/_load_more_history_button.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<%=
link_to('Load More',
load_more_history_path(playlist_id: params[:playlist_id], page: history[:changes].next_page),
remote: true,
id: 'load-more',
class: 'btn btn-primary',
data: { action: "click->load-more#loadMore", load_more_target: "button" }) if history[:changes].next_page
%>
2 changes: 1 addition & 1 deletion app/views/playlist_history/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@

<ul>
<% @playlists.each do |playlist| %>
<li><%=link_to playlist[:name], "history/#{playlist[:playlist_id]}" %></li>
<li><%=link_to playlist[:name], "#{playlist[:playlist_id]}" %></li>
<% end %>
</ul>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
h1 History for #{@history[:name]}
- start_time = Time.now
- puts "Started building view at: #{start_time}"
/
/ .timeline
/ .outer
/ - @history[:changes].each do |change|
/ .card
/ .info
/ h3.title #{change[:start_date].strftime("%b %d, %Y")} - #{change[:end_date].strftime("%b %d, %Y")}
/
/ - if change[:added].present?
/ div
/ h5 Added
/ ul
/ - change[:added].each do |song|
/ li = song
/
/ - if change[:removed].present?
/ div
/ h5 Removed
/ ul
/ - change[:removed].each do |song|
/ li = song
.timeline
.outer
- @history[:changes].each do |delta|
.card
.info
h3.title #{delta.playlist_snapshot.created_at.strftime("%b %d, %Y")}

- if delta.added.present?
div
h5 Added
ul
- delta.added.each do |song|
li = song["title"]

- if delta.removed.present?
div
h5 Removed
ul
- delta.removed.each do |song|
li = song["title"]

- finish_time = Time.now
- puts "Finished building view at: #{finish_time}"
- puts "Built view in: #{finish_time - start_time}s"
10 changes: 10 additions & 0 deletions app/views/playlist_history/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<h1>History for <%= @history[:name] %></h1>
<div class="timeline" data-controller="load-more" data-load-more-target="timeline">
<div class="outer">
<%= render partial: "delta_card", collection: @history[:changes], as: :delta %>
</div>

<div id="loading" data-load-more-target="loading" style="display: none;">Loading more items...</div>

<%= render partial: 'load_more_history_button', locals: {history: @history, params: params} %>
</div>
22 changes: 0 additions & 22 deletions app/views/playlist_history/show.html.slim

This file was deleted.

4 changes: 4 additions & 0 deletions bin/importmap
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env ruby

require_relative "../config/application"
require "importmap/commands"
Loading

0 comments on commit aec54a5

Please sign in to comment.