Skip to content

Commit

Permalink
WIP: Add resource table component
Browse files Browse the repository at this point in the history
Add first try of a resource table. It is pretty raw and does not create the right output, but it is only a proposal.
  • Loading branch information
kulturbande committed Mar 10, 2024
1 parent 63d5474 commit 056fb9e
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 0 deletions.
70 changes: 70 additions & 0 deletions app/components/alchemy/admin/resource_table.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# frozen_string_literal: true

module Alchemy
module Admin
class ResourceTable < ViewComponent::Base
include BaseHelper

attr_reader :columns, :collection, :nothing_found_label

erb_template <<~ERB
<% if collection.any? %>
<table class="list">
<thead>
<tr>
<% columns.each do |column| %>
<th><%= column.label || column.name %></th>
<% end %>
</tr>
</thead>
<tbody>
<% collection.each do |row| %>
<tr class="<%= cycle('even', 'odd') %>">
<% columns.each do |column| %>
<td class="<%= column.name %>">
<%= view_context.capture(row, &column.block) %>
</td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<div class="info">
<%= render_icon('info') %>
<%= nothing_found_label %>
</div>
<% end %>
ERB

def initialize(collection, nothing_found_label: Alchemy.t("Nothing found"))
@collection = collection
@nothing_found_label = nothing_found_label
@columns = []
end

def add_column(name, label: nil, sortable: true, &block)
@columns << Column.new(name, label: label, sortable: sortable, &block)
end

private

##
# the before_render - method is necessary to force ViewComponent to evaluate the add_column - calls
def before_render
content
end

class Column
attr_reader :block, :label, :name, :sortable

def initialize(name, sortable:, label: nil, &block)
@name = name
@label = label
@sortable = sortable
@block = block || lambda { |item| item[name] }
end
end
end
end
end
86 changes: 86 additions & 0 deletions spec/components/alchemy/admin/resource_table_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# frozen_string_literal: true

require "rails_helper"

RSpec.describe Alchemy::Admin::ResourceTable, type: :component do
let(:collection) { [] }
before do
render
end

subject(:render) do
render_inline(described_class.new(collection))
end

context "with data" do
let(:collection) {
[
{name: "Foo", description: "Awesome description"},
{name: "Bar", description: "Another description"}
]
}

it "doesn't renders an info message" do
expect(page).to_not have_content("Nothing found")
end

context "columns without block" do
subject(:render) do
render_inline(described_class.new(collection)) do |component|
component.add_column(:name)
component.add_column(:description)
end
end

it "renders a table header" do
expect(page).to have_selector("table th", text: "name")
expect(page).to have_selector("table th", text: "description")
end

it "renders a table cell" do
expect(page).to have_selector("table td.name", text: "Foo")
expect(page).to have_selector("table td.description", text: "Awesome description")
end
end

context "columns with custom label" do
subject(:render) do
render_inline(described_class.new(collection)) do |component|
component.add_column(:name, label: "Awesome Name")
end
end

it "renders a table header with custom label" do
expect(page).to have_selector("table th", text: "Awesome Name")
end
end

context "columns with a custom block" do
subject(:render) do
render_inline(described_class.new(collection)) do |component|
component.add_column(:description) { |item| item[:description].truncate(10) }
end
end

it "renders a table cell with a custom block" do
expect(page).to have_selector("table td", text: "Awesome...")
end
end
end

context "without any data" do
it "renders an info message" do
expect(page).to have_content("Nothing found")
end

context "with another nothing found - label" do
subject(:render) do
render_inline(described_class.new(collection, nothing_found_label: "No user found"))
end

it "renders an info message" do
expect(page).to have_content("No user found")
end
end
end
end

0 comments on commit 056fb9e

Please sign in to comment.