Extract component for admin officers table

This way we can remove duplication and simplify the code in the view.

Note we're not using the "within" method in the tests to access a row,
because it doesn't seem to work in components tests when passing the
`text:` option.
This commit is contained in:
Javi Martín
2020-07-06 19:53:24 +02:00
parent 08c2bfc255
commit 7cb0a4135b
5 changed files with 91 additions and 70 deletions

View File

@@ -0,0 +1,36 @@
<%= tag.table options do %>
<thead>
<tr>
<th><%= t("admin.poll_officers.officer.name") %></th>
<th><%= t("admin.poll_officers.officer.email") %></th>
<th class="small-3"><%= t("admin.actions.actions") %></th>
</tr>
</thead>
<tbody>
<% officers.each do |officer| %>
<tr>
<td>
<%= officer.name %>
</td>
<td>
<%= officer.email %>
</td>
<td>
<% if officer.persisted? %>
<%= render Admin::TableActionsComponent.new(officer,
actions: [:destroy],
destroy_text: t("admin.poll_officers.officer.delete")
) %>
<% else %>
<%= render Admin::TableActionsComponent.new(actions: []) do |actions| %>
<%= actions.link_to t("admin.poll_officers.officer.add"),
add_user_path(officer),
method: :post,
class: "button success expanded" %>
<% end %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
<% end %>

View File

@@ -0,0 +1,18 @@
class Admin::Poll::Officers::OfficersComponent < ApplicationComponent
attr_reader :officers, :options
def initialize(officers, **options)
@officers = officers
@options = options
end
private
def add_user_path(officer)
{
controller: "admin/poll/officers",
action: :create,
user_id: officer.user_id
}
end
end

View File

@@ -1,33 +1 @@
<table>
<thead>
<tr>
<th><%= t("admin.poll_officers.officer.name") %></th>
<th><%= t("admin.poll_officers.officer.email") %></th>
<th class="small-3"><%= t("admin.actions.actions") %></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<%= officer.name %>
</td>
<td>
<%= officer.email %>
</td>
<td>
<% if officer.persisted? %>
<%= render Admin::TableActionsComponent.new(officer,
actions: [:destroy],
destroy_text: t("admin.poll_officers.officer.delete")
) %>
<% else %>
<%= render Admin::TableActionsComponent.new(actions: []) do |actions| %>
<%= actions.link_to t("admin.poll_officers.officer.add"), { controller: "admin/poll/officers", action: :create, user_id: officer.user_id },
method: :post,
class: "button success expanded" %>
<% end %>
<% end %>
</td>
</tr>
</tbody>
</table>
<%= render Admin::Poll::Officers::OfficersComponent.new([officer]) %>

View File

@@ -11,43 +11,7 @@
</h3>
<% if @officers.any? %>
<table id="officers">
<thead>
<tr>
<th><%= t("admin.poll_officers.officer.name") %></th>
<th><%= t("admin.poll_officers.officer.email") %></th>
<th class="small-3"><%= t("admin.actions.actions") %></th>
</tr>
</thead>
<tbody>
<% @officers.each do |officer| %>
<tr>
<td>
<%= officer.name %>
</td>
<td>
<%= officer.email %>
</td>
<td>
<% if officer.persisted? %>
<%= render Admin::TableActionsComponent.new(officer,
actions: [:destroy],
destroy_text: t("admin.poll_officers.officer.delete")
) %>
<% else %>
<%= render Admin::TableActionsComponent.new(actions: []) do |actions| %>
<%= actions.link_to t("admin.poll_officers.officer.add"),
{ controller: "admin/poll/officers", action: :create,
user_id: officer.user_id },
method: :post,
class: "button success expanded" %>
<% end %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
<%= render Admin::Poll::Officers::OfficersComponent.new(@officers, id: "officers") %>
<%= paginate @officers %>
<% end %>

View File

@@ -0,0 +1,35 @@
require "rails_helper"
describe Admin::Poll::Officers::OfficersComponent, type: :component do
let(:existing_officer) { create(:poll_officer, name: "Old officer") }
let(:new_officer) { build(:poll_officer, name: "New officer") }
let(:officers) { [existing_officer, new_officer] }
let(:component) { Admin::Poll::Officers::OfficersComponent.new(officers) }
it "renders as many rows as officers" do
within "tbody" do
expect(page).to have_css "tr", count: 2
expect(page).to have_css "a", count: 2
end
end
it "renders link to destroy for existing officers" do
render_inline component
row = page.find("tr", text: "Old officer")
expect(row).to have_css "a[data-method='delete']", text: "Delete"
end
it "renders link to add for new officers" do
render_inline component
row = page.find("tr", text: "New officer")
expect(row).to have_css "a[data-method='post']", text: "Add"
end
it "accepts table options" do
render_inline Admin::Poll::Officers::OfficersComponent.new(officers, class: "my-officers-table")
expect(page).to have_css "table.my-officers-table"
end
end