diff --git a/Gemfile b/Gemfile
index 523f562b..5e1820ee 100644
--- a/Gemfile
+++ b/Gemfile
@@ -36,6 +36,7 @@ gem 'stripe', '~> 10.5'
gem 'tailwindcss-rails'
gem 'turbo-rails'
gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby]
+gem 'view_component'
gem 'zaru', '~> 1.0'
group :development, :test do
diff --git a/Gemfile.lock b/Gemfile.lock
index 4d1962ad..eb15c129 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -201,6 +201,7 @@ GEM
matrix (0.4.2)
meta-tags (2.19.0)
actionpack (>= 3.2.0, < 7.2)
+ method_source (1.1.0)
mini_magick (4.12.0)
mini_mime (1.1.5)
minitest (5.22.2)
@@ -373,6 +374,10 @@ GEM
concurrent-ruby (~> 1.0)
unicode-display_width (2.5.0)
uri (0.13.0)
+ view_component (3.13.0)
+ activesupport (>= 5.2.0, < 8.0)
+ concurrent-ruby (~> 1.0)
+ method_source (~> 1.0)
webmock (3.23.1)
addressable (>= 2.8.0)
crack (>= 0.3.2)
@@ -437,6 +442,7 @@ DEPENDENCIES
tailwindcss-rails
turbo-rails
tzinfo-data
+ view_component
webmock
zaru (~> 1.0)
diff --git a/app/components/card_component.rb b/app/components/card_component.rb
new file mode 100644
index 00000000..aaaf1152
--- /dev/null
+++ b/app/components/card_component.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class CardComponent < ViewComponent::Base
+ def initialize(title:, subtitle:, image:)
+ @title = title
+ @subtitle = subtitle
+ @image = image
+
+ super
+ end
+end
diff --git a/app/components/card_component/card_component.html.erb b/app/components/card_component/card_component.html.erb
new file mode 100644
index 00000000..a2eb0ae6
--- /dev/null
+++ b/app/components/card_component/card_component.html.erb
@@ -0,0 +1,7 @@
+
<% @albums.in_release_order.each do |album| %>
<%= link_to(artist_album_path(album.artist, album)) do %>
-
-
- <% if album.cover.representable? %>
- <%= image_tag cdn_url(album.cover.representation(resize_to_limit: [1000, 1000])), class: 'object-cover' %>
- <% end %>
-
- <% if album.published? %>
-
<%= album.title %>
- <% else %>
-
<%= album.title %> (<%= album.publication_status %>)
- <% end %>
-
+ <%= render(CardComponent.new(
+ title: album.title,
+ subtitle: ( album.publication_status if !album.published? ),
+ image: ( cdn_url(album.cover.representation(resize_to_limit: [1000, 1000])) if album.cover.representable? )
+ )) %>
<% end %>
<% end %>
diff --git a/app/views/collections/show.html.erb b/app/views/collections/show.html.erb
index b2bdddd8..289927f6 100644
--- a/app/views/collections/show.html.erb
+++ b/app/views/collections/show.html.erb
@@ -7,15 +7,11 @@
<% Current.user.collection.each do |purchase| %>
<%= link_to(artist_album_path(purchase.album.artist, purchase.album)) do %>
-
-
- <% if purchase.album.cover.representable? %>
- <%= image_tag cdn_url(purchase.album.cover.representation(resize_to_limit: [1000, 1000])), class: 'object-cover' %>
- <% end %>
-
-
<%= purchase.album.title %>
-
<%= purchase.album.artist.name %>
-
+ <%= render(CardComponent.new(
+ title: purchase.album.title,
+ subtitle: purchase.album.artist.name,
+ image: ( cdn_url(purchase.album.cover.representation(resize_to_limit: [1000, 1000])) if purchase.album.cover.representable? )
+ )) %>
<% end %>
<% end %>
diff --git a/app/views/interests/new.html.erb b/app/views/interests/new.html.erb
index 51dd9581..cee0948c 100644
--- a/app/views/interests/new.html.erb
+++ b/app/views/interests/new.html.erb
@@ -14,17 +14,13 @@
Recently purchased
<% Album.best_selling.limit(8).each do |album| %>
- <%= link_to(artist_album_path(album.artist, album)) do %>
-
-
- <% if album.cover.representable? %>
- <%= image_tag cdn_url(album.cover.representation(resize_to_limit: [1000, 1000])), class: 'object-cover' %>
- <% end %>
-
-
<%= album.title %>
-
<%= album.artist.name %>
-
- <% end %>
+ <%= link_to(artist_album_path(album.artist, album)) do %>
+ <%= render(CardComponent.new(
+ title: album.title,
+ subtitle: album.artist.name,
+ image: ( cdn_url(album.cover.representation(resize_to_limit: [1000, 1000])) if album.cover.representable? )
+ )) %>
+ <% end %>
<% end %>
diff --git a/config/tailwind.config.js b/config/tailwind.config.js
index a7873ffc..2a828c28 100644
--- a/config/tailwind.config.js
+++ b/config/tailwind.config.js
@@ -6,6 +6,8 @@ module.exports = {
'./app/helpers/**/*.rb',
'./app/javascript/**/*.js',
'./app/views/**/*.{erb,haml,html,slim}',
+ './app/components/**/*.{erb,haml,html,slim}',
+ './test/components/previews/**/*.{erb,haml,html,slim}',
'./app/form_builders/*.rb',
'./lib/renderers/*.rb'
],
diff --git a/test/components/card_component_test.rb b/test/components/card_component_test.rb
new file mode 100644
index 00000000..3c6fb4ef
--- /dev/null
+++ b/test/components/card_component_test.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'test_helper'
+
+class CardComponentTest < ViewComponent::TestCase
+ def setup
+ render_inline(
+ CardComponent.new(
+ title: 'Title',
+ subtitle: 'Subtitle',
+ image: 'http://example.com'
+ )
+ )
+ end
+
+ def test_component_renders_title
+ assert_text('Title')
+ end
+
+ def test_component_renders_subtitle
+ assert_text('Subtitle')
+ end
+
+ def test_component_renders_image
+ assert_selector("img[src='http://example.com']")
+ end
+end
diff --git a/test/components/previews/card_component_preview.rb b/test/components/previews/card_component_preview.rb
new file mode 100644
index 00000000..fb9d3d80
--- /dev/null
+++ b/test/components/previews/card_component_preview.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class CardComponentPreview < ViewComponent::Preview
+ def default; end
+end
diff --git a/test/components/previews/card_component_preview/default.html.erb b/test/components/previews/card_component_preview/default.html.erb
new file mode 100644
index 00000000..e1ecfe76
--- /dev/null
+++ b/test/components/previews/card_component_preview/default.html.erb
@@ -0,0 +1,10 @@
+
+ <%= render(
+ CardComponent.new(
+ title: 'Fables of the Reconstuction',
+ subtitle: 'R.E.M.',
+ image: 'https://upload.wikimedia.org/wikipedia/en/d/dc/R.E.M._-_Fables_of_the_Reconstruction.jpg'
+ )
+ )
+ %>
+
diff --git a/test/controllers/artists_controller_test.rb b/test/controllers/artists_controller_test.rb
index a9dd0178..1e1d0fd4 100644
--- a/test/controllers/artists_controller_test.rb
+++ b/test/controllers/artists_controller_test.rb
@@ -57,7 +57,7 @@ class ArtistsControllerTestSignedIn < ActionDispatch::IntegrationTest
get artist_url(@artist)
- assert_select 'p', 'Album Title (unpublished)'
+ assert_select 'p', 'unpublished'
end
test '#show should include pending albums' do
@@ -65,7 +65,7 @@ class ArtistsControllerTestSignedIn < ActionDispatch::IntegrationTest
get artist_url(@artist)
- assert_select 'p', 'Album Title (pending)'
+ assert_select 'p', 'pending'
end
test '#new' do
@@ -130,7 +130,7 @@ class ArtistsControllerTestSignedInArtist < ActionDispatch::IntegrationTest
get artist_url(@artist)
- assert_select 'p', 'Album Title (unpublished)'
+ assert_select 'p', 'unpublished'
end
test '#show should include pending albums' do
@@ -138,7 +138,7 @@ class ArtistsControllerTestSignedInArtist < ActionDispatch::IntegrationTest
get artist_url(@artist)
- assert_select 'p', 'Album Title (pending)'
+ assert_select 'p', 'pending'
end
end
@@ -202,7 +202,7 @@ class ArtistsControllerTestSignedOut < ActionDispatch::IntegrationTest
get artist_url(@artist)
- assert_select 'p', { text: 'Album Title (unpublished)', count: 0 }
+ assert_select 'p', { text: 'unpublished', count: 0 }
end
test '#show should not include pending albums' do
@@ -210,7 +210,7 @@ class ArtistsControllerTestSignedOut < ActionDispatch::IntegrationTest
get artist_url(@artist)
- assert_select 'p', { text: 'Album Title (pending)', count: 0 }
+ assert_select 'p', { text: 'pending', count: 0 }
end
test '#show includes auto-discovery link for atom feed' do
diff --git a/test/system/creating_an_album_test.rb b/test/system/creating_an_album_test.rb
index d1bd89ea..ae3aef48 100644
--- a/test/system/creating_an_album_test.rb
+++ b/test/system/creating_an_album_test.rb
@@ -24,8 +24,9 @@ class CreatingAnAlbumTest < ApplicationSystemTestCase
click_on 'Save'
- assert_text "A Hard Day's Night (unpublished)"
- click_on "A Hard Day's Night (unpublished)"
+ assert_text "A Hard Day's Night"
+ assert_text 'unpublished'
+ click_on "A Hard Day's Night"
assert_text '1. And I Love Her'
end
diff --git a/test/system/publishing_an_album_test.rb b/test/system/publishing_an_album_test.rb
index 2d97e0a3..83c46651 100644
--- a/test/system/publishing_an_album_test.rb
+++ b/test/system/publishing_an_album_test.rb
@@ -13,7 +13,7 @@ class PublishingAnAlbumTest < ApplicationSystemTestCase
test 'publishing an album' do
# Artist requests publication
visit artist_url(@album.artist)
- click_on "#{@album.title} (unpublished)"
+ click_on @album.title.to_s
click_on 'Publish'
assert_text "Thank you! We'll email you when your album is published."
sign_out