Skip to content

Commit 6625191

Browse files
committed
tables: revert back to action buttons and pass paths to table from callers
1 parent 604c19d commit 6625191

14 files changed

Lines changed: 99 additions & 236 deletions

File tree

app/assets/images/icons/ellipsis-v.svg

Lines changed: 0 additions & 2 deletions
This file was deleted.

app/components/shared/index_table_component.html.erb

Lines changed: 29 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -17,80 +17,54 @@
1717
</div>
1818
<% end %>
1919

20-
<!-- Construct columns sizes string from individual col_size parameters, include actions if present -->
21-
<% col_list = columns.map { |c| c.col_size || "minmax(0, 1fr)" }.to_a %>
22-
<% col_list << "50px" if has_actions? %>
23-
<% column_sizes = col_list.join(" ") %>
20+
<!-- Construct columns sizes string from individual col_size parameters -->
21+
<% column_sizes = columns.map { |c| c.col_size || "minmax(0, 1fr)" }.join(" ") %>
2422

2523
<!-- Each row (including header) is its own rounded box -->
2624
<div class="mb-2">
2725
<div class="card ui-enter-item bg-neutral rounded-lg" style="--ui-enter-delay: 80ms;">
28-
<div class="p-4 grid items-center gap-4" style="grid-template-columns: <%= column_sizes %>">
26+
<div class="p-4 grid items-stretch gap-4" style="grid-template-columns: <%= column_sizes %>">
2927
<% columns.each do |column| %>
30-
<div class="text-sm font-semibold text-neutral-content"><%= column.header %></div>
31-
<% end %>
32-
<% if has_actions? %>
33-
<div class="text-sm font-semibold text-neutral-content text-center"><%= t("shared.index_table_component.actions.label") %></div>
28+
<div class="text-sm font-semibold text-neutral-content flex items-center"><%= column.header %></div>
3429
<% end %>
3530
</div>
3631
</div>
3732
</div>
3833

39-
<div class="space-y-2" data-controller="table-actions-dropdown" data-action="click@window->table-actions-dropdown#handleDocumentClick">
34+
<div class="space-y-2">
4035
<% records.each_with_index do |record, index| %>
41-
<% record_actions = actions_for(record) %>
4236
<div
4337
data-index-table-component-target="row"
4438
class="card ui-enter-item bg-white rounded-lg group transition-shadow relative overflow-visible shadow-sm<%= " cursor-pointer hover:shadow-md" if clickable_rows %>"
45-
style="--ui-enter-delay: <%= 120 + ((index % 15) * 35) %>ms;"
46-
<% if clickable_rows %>
47-
data-action="click->table-actions-dropdown#navigateToRecord"
48-
data-record-path="<%= row_path_for(record) %>"
49-
<% end %>>
50-
<div class="p-3 grid items-center gap-4 rounded-lg<%= " group-hover:bg-secondary/30 transition-colors" if clickable_rows %>" style="grid-template-columns: <%= column_sizes %>">
51-
<% columns.each do |column| %>
52-
<div class="text-sm text-base-content"><%= render_cell_content(record, column) %></div>
53-
<% end %>
54-
<% if has_actions? %>
55-
<button type="button"
56-
class="flex items-center justify-center w-full hover:text-base-content transition-colors"
57-
data-action="click->table-actions-dropdown#openMenu">
58-
<%= render IconComponent.new(icon: "ellipsis-v", size: :sm, classes: "text-base-content/50 hover:text-base-content transition-colors") %>
59-
</button>
60-
<% end %>
61-
</div>
62-
63-
<% if has_actions? && record_actions.any? %>
64-
<div class="hidden ui-enter-item absolute top-full right-0 mt-1 z-50 bg-base-100 rounded-lg border border-base-300 shadow-lg min-w-48 py-1" data-table-actions-dropdown-target="menu">
65-
<% record_actions.each do |action| %>
66-
<% turbo_data = { turbo_method: action[:method] }.compact %>
67-
<% turbo_data[:turbo_confirm] = action[:confirm] if action[:confirm] %>
68-
<% if action[:turbo_stream] %>
69-
<% turbo_data[:turbo_stream] = true %>
70-
<% end %>
71-
<%= link_to(action[:path], data: turbo_data, class: "group/menu-item flex items-center gap-3 px-4 py-2 text-sm text-base-content hover:bg-primary/30 transition-colors") do %>
72-
<% if action[:icon] %>
73-
<%= render IconComponent.new(icon: action[:icon], size: :sm, classes: "text-base-content/50 group-hover/menu-item:text-primary transition-colors") %>
74-
<% end %>
75-
<span><%= action[:label] %></span>
39+
style="--ui-enter-delay: <%= 120 + ((index % 15) * 35) %>ms;">
40+
<div class="p-3 grid items-stretch gap-4 rounded-lg<%= " group-hover:bg-secondary/30 transition-colors" if clickable_rows %>" style="grid-template-columns: <%= column_sizes %>">
41+
<% columns.each do |column| %>
42+
<%= render_cell_wrapper(
43+
record,
44+
column,
45+
classes: class_names(
46+
"text-sm text-base-content min-w-0 w-full h-full flex items-center",
47+
row_clickable_for?(record, column) && "block"
48+
)
49+
) do %>
50+
<%= render_cell_content(record, column) %>
7651
<% end %>
7752
<% end %>
7853
</div>
79-
<% end %>
80-
</div>
81-
<% end %>
82-
<div data-index-table-component-target="emptyRow" class="card ui-enter-item bg-white rounded-lg shadow-sm <%= "hidden" unless empty? %>" style="--ui-enter-delay: 120ms;">
83-
<div class="flex justify-center p-3 items-center">
84-
<div class="text-sm text-base-content/40 font-bold"><%= t("shared.index_table_component.no_entries") %></div>
54+
</div>
55+
<% end %>
56+
<div data-index-table-component-target="emptyRow" class="card ui-enter-item bg-white rounded-lg shadow-sm <%= "hidden" unless empty? %>" style="--ui-enter-delay: 120ms;">
57+
<div class="flex justify-center p-3 items-center">
58+
<div class="text-sm text-base-content/40 font-bold"><%= t("shared.index_table_component.no_entries") %></div>
59+
</div>
8560
</div>
8661
</div>
87-
</div>
8862

89-
<div class="flex justify-center mt-4">
90-
<div class="join hidden" data-index-table-component-target="pagination">
91-
<button class="join-item btn btn-sm" data-action="index-table-component#previousPage" data-prev>&lt;</button>
92-
<span class="join-item btn btn-sm no-animation pointer-events-none" data-index-table-component-target="pageInfo"></span>
93-
<button class="join-item btn btn-sm" data-action="index-table-component#nextPage" data-next>&gt;</button>
63+
<div class="flex justify-center mt-4">
64+
<div class="join hidden" data-index-table-component-target="pagination">
65+
<button class="join-item btn btn-sm" data-action="index-table-component#previousPage" data-prev>&lt;</button>
66+
<span class="join-item btn btn-sm no-animation pointer-events-none" data-index-table-component-target="pageInfo"></span>
67+
<button class="join-item btn btn-sm" data-action="index-table-component#nextPage" data-next>&gt;</button>
68+
</div>
9469
</div>
9570
</div>
96-
</div>

app/components/shared/index_table_component.rb

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,53 @@
11
module Shared
22
class IndexTableComponent < ViewComponent::Base
3-
attr_reader :records, :columns, :searchable, :per_page, :actions, :clickable_rows, :turbo_stream_rows
3+
attr_reader :records, :columns, :searchable, :per_page, :clickable_rows, :turbo_stream_rows
44

55
Column = Struct.new(:attribute, :header, :cell_renderer, :col_size)
66

7-
def initialize(records:, searchable: true, per_page: 10, actions: nil, clickable_rows: true,
8-
turbo_stream_rows: false)
7+
def initialize(records:, searchable: true, per_page: 10, clickable_rows: true,
8+
turbo_stream_rows: false, record_path: nil)
99
super()
1010
@records = records
1111
@columns = []
1212
@searchable = searchable
1313
@per_page = per_page
14-
@actions = actions
1514
@clickable_rows = clickable_rows
1615
@turbo_stream_rows = turbo_stream_rows
17-
end
18-
19-
def row_path_for(record)
20-
options = @turbo_stream_rows ? { format: :turbo_stream } : {}
21-
polymorphic_path(record.to_polymorphic_path, **options)
16+
@record_path = record_path
2217
end
2318

2419
def column(attribute, header: nil, col_size: nil, &cell_renderer)
2520
label = header || default_header_for(attribute)
2621
@columns << Column.new(attribute, label, cell_renderer, col_size)
2722
end
2823

29-
def has_actions?
30-
@actions.present?
24+
private
25+
26+
def row_path_for(record)
27+
return nil unless @record_path
28+
29+
path = @record_path.call(record)
30+
31+
return path unless @turbo_stream_rows
32+
33+
path.include?("?") ? "#{path}&format=turbo_stream" : "#{path}?format=turbo_stream"
3134
end
3235

33-
def actions_for(record)
34-
return [] unless has_actions?
36+
def row_link_data
37+
{ turbo_stream: (@turbo_stream_rows ? true : nil) }.compact
38+
end
3539

36-
@actions.call(record)
40+
def render_cell_wrapper(record, column, classes:, &)
41+
if row_clickable_for?(record, column)
42+
link_to(row_path_for(record), data: row_link_data, class: classes, &)
43+
else
44+
content_tag(:div, class: classes, &)
45+
end
3746
end
3847

39-
private
48+
def row_clickable_for?(record, column)
49+
clickable_rows && row_path_for(record).present? && column.attribute != :actions
50+
end
4051

4152
def render_cell_content(record, column)
4253
if column.cell_renderer

app/javascript/controllers/table_actions_dropdown_controller.js

Lines changed: 0 additions & 108 deletions
This file was deleted.

app/models/application_record.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
11
class ApplicationRecord < ActiveRecord::Base
22
primary_abstract_class
3-
4-
def to_polymorphic_path
5-
self
6-
end
73
end

app/models/journal.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,4 @@ class Journal < ApplicationRecord
88
has_rich_text :markdown_content
99

1010
validates :title, presence: true
11-
12-
def to_polymorphic_path
13-
[subproject.project, subproject, self]
14-
end
1511
end

app/models/log_entry.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
class LogEntry < ApplicationRecord
22
belongs_to :subproject
33
belongs_to :user
4-
5-
def to_polymorphic_path
6-
[subproject.project, subproject, self]
7-
end
84
end

app/models/subproject.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,4 @@ class Subproject < ApplicationRecord
66

77
has_many :log_entries, dependent: :destroy
88
has_many :journals, dependent: :destroy
9-
10-
def to_polymorphic_path
11-
[project, self]
12-
end
139
end

app/views/projects/show.html.erb

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,7 @@
2626
<h1 class="text-2xl font-bold"><%= t(".subprojects") %></h1>
2727
<%= render Shared::IndexTableComponent.new(
2828
records: @project.subprojects,
29-
actions: lambda { |subproject|
30-
[
31-
{ icon: "edit", label: t("shared.index_table_component.actions.edit"), path: edit_project_subproject_path(@project, subproject), turbo_stream: true },
32-
{ icon: "delete", label: t("shared.index_table_component.actions.delete"), path: project_subproject_path(@project, subproject), method: :delete, confirm: t("subprojects.destroy.confirm") }
33-
]
34-
}
29+
record_path: ->(subproject) { project_subproject_path(@project, subproject) }
3530
) do |table| %>
3631
<% table.column :name do |subproject| %>
3732
<%= subproject.name %>
@@ -45,6 +40,12 @@
4540
<% table.column :created_at do |subproject| %>
4641
<%= l(subproject.created_at) %>
4742
<% end %>
43+
<% table.column :actions, header: t("shared.index_table_component.actions.label"), col_size: "90px" do |subproject| %>
44+
<div class="flex flex-row gap-2 items-center justify-center">
45+
<%= render ActionButtonComponent.new(to: edit_project_subproject_path(@project, subproject), icon: "edit", turbo_stream: true, colour: :info) %>
46+
<%= render ActionButtonComponent.new(to: project_subproject_path(@project, subproject), method: :delete, icon: "delete", colour: :error, confirm: t("subprojects.destroy.confirm")) %>
47+
</div>
48+
<% end %>
4849
<% end %>
4950
<% end %>
5051
</div>

app/views/regions/index.html.erb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,6 @@
88
<%= render ContentCardComponent.new do %>
99
<%= render Shared::IndexTableComponent.new(
1010
records: @regions,
11-
actions: lambda { |region|
12-
[
13-
{ icon: "edit", label: t("shared.index_table_component.actions.edit"), path: edit_region_path(region), turbo_stream: true },
14-
{ icon: "delete", label: t("shared.index_table_component.actions.delete"), path: region_path(region), method: :delete, confirm: t("regions.destroy.confirm") }
15-
]
16-
},
1711
clickable_rows: false
1812
) do |table| %>
1913
<% table.column :name %>
@@ -23,6 +17,12 @@
2317
<% table.column :longitude do |region| %>
2418
<%= "#{region.longitude.abs.round(4)}° #{region.longitude >= 0 ? 'E' : 'W'}" %>
2519
<% end %>
20+
<% table.column :actions, header: t("shared.index_table_component.actions.label"), col_size: "90px" do |region| %>
21+
<div class="flex flex-row gap-2 items-center justify-center">
22+
<%= render ActionButtonComponent.new(to: edit_region_path(region), icon: "edit", turbo_stream: true, colour: :info) %>
23+
<%= render ActionButtonComponent.new(to: region_path(region), method: :delete, icon: "delete", colour: :error, confirm: t("regions.destroy.confirm")) %>
24+
</div>
25+
<% end %>
2626
<% end %>
2727
<% end %>
2828
</div>

0 commit comments

Comments
 (0)