power_grid 0.2.0 → 0.2.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/components/power_grid/table_component.html.erb +123 -106
- data/lib/power_grid/base.rb +3 -0
- data/lib/power_grid/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7029d0bebbab40ecdabfa5d050f403a57611bb43ffb9f9f0c79169d2c4aa7aad
|
|
4
|
+
data.tar.gz: 5e2e7b62f5e4167b8bb7813fe047ba611446662cc20772e8a607ad73d57adca9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 67a99440174654e935086b375d7513e9347ce57cf5557fadc965c19351b426b7bc444b74217aea28ad174576b3f9fc8f212b0c0b1fe8fb23c5aa6f8f390eb248
|
|
7
|
+
data.tar.gz: f4058ab216eefc43c1a35d10a2c14b2415a4273972866b4bee4409f6e2f53ceeebb8be852471d40dcdb509bf8af4bb6b4d7f2384dc83ee23f1015188a59088b0
|
|
@@ -1,103 +1,100 @@
|
|
|
1
|
-
<div class="power-grid-container w-full bg-white dark:bg-slate-900 rounded-
|
|
1
|
+
<div class="power-grid-container w-full bg-white dark:bg-slate-900 rounded-xl shadow-sm border border-slate-200 dark:border-slate-800" data-controller="power-grid-table">
|
|
2
2
|
|
|
3
|
-
<!--
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<!-- Per Page -->
|
|
17
|
-
<div class="flex items-center">
|
|
18
|
-
<span class="mr-2 text-slate-700 dark:text-slate-300">Show</span>
|
|
19
|
-
<%= select_tag :per_page, options_for_select([10, 25, 50, 100], @grid.per_page),
|
|
20
|
-
class: "block w-20 rounded-md border-slate-300 py-1.5 text-base focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm dark:bg-slate-800 dark:border-slate-600 dark:text-white",
|
|
21
|
-
data: { action: "change->power-grid-table#search" }
|
|
22
|
-
%>
|
|
3
|
+
<!-- Clean Toolbar -->
|
|
4
|
+
<% unless @grid.try(:hide_controls) %>
|
|
5
|
+
<div class="flex flex-col md:flex-row md:items-center justify-between gap-4 p-4 border-b border-slate-200 dark:border-slate-800">
|
|
6
|
+
|
|
7
|
+
<!-- Search -->
|
|
8
|
+
<div class="w-full md:w-72">
|
|
9
|
+
<% if @grid.searchable? %>
|
|
10
|
+
<div class="relative">
|
|
11
|
+
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
|
12
|
+
<svg class="h-5 w-5 text-slate-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
13
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
|
14
|
+
</svg>
|
|
23
15
|
</div>
|
|
16
|
+
<%= text_field_tag :q, params[:q], placeholder: "Search...",
|
|
17
|
+
class: "block w-full pl-12 pr-3 py-2 border border-slate-300 dark:border-slate-700 rounded-lg leading-5 bg-white dark:bg-slate-800 text-slate-900 dark:text-white placeholder-slate-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm",
|
|
18
|
+
data: { action: "input->power-grid-table#search" },
|
|
19
|
+
form: "power_grid_form_#{request.path.parameterize}"
|
|
20
|
+
%>
|
|
21
|
+
</div>
|
|
22
|
+
<% end %>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<!-- Filters & Actions -->
|
|
26
|
+
<div class="flex items-center gap-3">
|
|
27
|
+
<%= form_with url: request.path, method: :get, data: { turbo_frame: "power_grid_table", turbo_action: "advance", power_grid_table_target: "form" }, class: "flex items-center gap-3", id: "power_grid_form_#{request.path.parameterize}" do |f| %>
|
|
28
|
+
<% params.except(:per_page, :page, :q, *(@grid.class.defined_filters.keys)).each do |key, value| %>
|
|
29
|
+
<%= hidden_field_tag key, value %>
|
|
30
|
+
<% end %>
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
<div class="
|
|
28
|
-
|
|
32
|
+
<!-- Filters -->
|
|
33
|
+
<% @grid.class.defined_filters.each do |name, options| %>
|
|
34
|
+
<div class="relative">
|
|
35
|
+
<% if options[:collection] %>
|
|
29
36
|
<%= select_tag name, options_for_select(options[:collection], params[name]),
|
|
30
|
-
include_blank:
|
|
31
|
-
class: "block w-
|
|
32
|
-
|
|
37
|
+
include_blank: "All #{name.to_s.humanize.pluralize}",
|
|
38
|
+
class: "block w-full pl-3 pr-10 py-2 text-base border-slate-300 dark:border-slate-700 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-lg bg-white dark:bg-slate-800",
|
|
39
|
+
onchange: "this.form.requestSubmit()"
|
|
33
40
|
%>
|
|
34
|
-
|
|
35
|
-
<%= text_field_tag name, params[name],
|
|
36
|
-
placeholder:
|
|
37
|
-
|
|
38
|
-
data: { action: "change->power-grid-table#search" } # Debounce handled by controller if implemented for change, otherwise change triggers immediately
|
|
41
|
+
<% else %>
|
|
42
|
+
<%= text_field_tag name, params[name], placeholder: name.to_s.humanize,
|
|
43
|
+
class: "block w-full pl-3 pr-3 py-2 border border-slate-300 dark:border-slate-700 rounded-lg leading-5 bg-white dark:bg-slate-800 text-slate-900 dark:text-white placeholder-slate-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm",
|
|
44
|
+
data: { action: "input->power-grid-table#search" }
|
|
39
45
|
%>
|
|
40
|
-
|
|
41
|
-
</div>
|
|
42
|
-
<% end %>
|
|
43
|
-
|
|
44
|
-
<% end %>
|
|
45
|
-
</div>
|
|
46
|
-
|
|
47
|
-
<!-- Right: Search -->
|
|
48
|
-
<% if @grid.searchable? %>
|
|
49
|
-
<div class="w-full sm:w-auto">
|
|
50
|
-
<label for="search" class="sr-only">Search</label>
|
|
51
|
-
<div class="relative rounded-md shadow-sm">
|
|
52
|
-
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
|
53
|
-
<svg class="h-5 w-5 text-slate-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
54
|
-
<path fill-rule="evenodd" d="M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z" clip-rule="evenodd" />
|
|
55
|
-
</svg>
|
|
46
|
+
<% end %>
|
|
56
47
|
</div>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
48
|
+
<% end %>
|
|
49
|
+
|
|
50
|
+
<!-- Per Page -->
|
|
51
|
+
<div>
|
|
52
|
+
<%= select_tag :per_page, options_for_select([10, 25, 50, 100], @grid.per_page),
|
|
53
|
+
class: "block w-full pl-3 pr-10 py-2 text-base border-slate-300 dark:border-slate-700 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-lg bg-white dark:bg-slate-800",
|
|
54
|
+
onchange: "this.form.requestSubmit()"
|
|
55
|
+
%>
|
|
63
56
|
</div>
|
|
57
|
+
|
|
64
58
|
<% end %>
|
|
65
|
-
|
|
66
59
|
</div>
|
|
67
60
|
</div>
|
|
61
|
+
<% end %>
|
|
68
62
|
|
|
69
|
-
<%= turbo_frame_tag "power_grid_table" do %>
|
|
63
|
+
<%= turbo_frame_tag "power_grid_table", class: "w-full block" do %>
|
|
70
64
|
<div class="overflow-x-auto">
|
|
71
65
|
<table class="min-w-full divide-y divide-slate-200 dark:divide-slate-700">
|
|
72
|
-
<thead class="bg-slate-50 dark:bg-slate-800
|
|
66
|
+
<thead class="bg-slate-50 dark:bg-slate-800">
|
|
73
67
|
<tr>
|
|
74
|
-
<% columns.
|
|
75
|
-
<th scope="col" class="px-6 py-3 text-left text-xs font-
|
|
68
|
+
<% columns.each_with_index do |(key, options), idx| %>
|
|
69
|
+
<th scope="col" class="px-6 py-3 text-left text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-wider">
|
|
70
|
+
<% label = options[:header] || key.to_s.humanize %>
|
|
76
71
|
<% if options[:sortable] %>
|
|
77
|
-
<%= link_to request.params.merge(order: key, dir: (params[:order] == key.to_s && params[:dir] == "asc" ? "desc" : "asc")), class: "group inline-flex items-center", data: { turbo_action: "advance" } do %>
|
|
78
|
-
|
|
79
|
-
<span class="
|
|
72
|
+
<%= link_to request.params.merge(order: key, dir: (params[:order] == key.to_s && params[:dir] == "asc" ? "desc" : "asc")), class: "group inline-flex items-center space-x-1 hover:text-slate-700 dark:hover:text-slate-200", data: { turbo_action: "advance" } do %>
|
|
73
|
+
<span><%= label %></span>
|
|
74
|
+
<span class="flex-none rounded text-slate-400 group-hover:text-slate-600 dark:group-hover:text-slate-300">
|
|
80
75
|
<% if params[:order] == key.to_s %>
|
|
81
|
-
|
|
76
|
+
<% if params[:dir] == "asc" %>
|
|
77
|
+
<svg class="h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M14.77 12.79a.75.75 0 01-1.06-.02L10 8.832 6.29 12.77a.75.75 0 11-1.08-1.04l4.25-4.5a.75.75 0 011.08 0l4.25 4.5a.75.75 0 01-.02 1.06z" clip-rule="evenodd" /></svg>
|
|
78
|
+
<% else %>
|
|
79
|
+
<svg class="h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd" /></svg>
|
|
80
|
+
<% end %>
|
|
82
81
|
<% else %>
|
|
83
|
-
<svg class="h-4 w-4 opacity-
|
|
84
|
-
<path fill-rule="evenodd" d="M10 3a.75.75 0 01.55.24l3.25 3.5a.75.75 0 11-1.1 1.02L10 4.852 7.3 7.76a.75.75 0 01-1.1-1.02l3.25-3.5A.75.75 0 0110 3zm-3.76 9.2a.75.75 0 011.06.04l2.7 2.908 2.7-2.908a.75.75 0 111.1 1.02l-3.25 3.5a.75.75 0 01-1.1 0l-3.25-3.5a.75.75 0 01.04-1.06z" clip-rule="evenodd" />
|
|
85
|
-
</svg>
|
|
82
|
+
<svg class="h-4 w-4 opacity-50 group-hover:opacity-100" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd" /></svg>
|
|
86
83
|
<% end %>
|
|
87
84
|
</span>
|
|
88
85
|
<% end %>
|
|
89
86
|
<% else %>
|
|
90
|
-
<%=
|
|
87
|
+
<%= label %>
|
|
91
88
|
<% end %>
|
|
92
89
|
</th>
|
|
93
90
|
<% end %>
|
|
94
91
|
</tr>
|
|
95
92
|
</thead>
|
|
96
|
-
<tbody class="
|
|
93
|
+
<tbody class="divide-y divide-slate-200 dark:divide-slate-700 bg-white dark:bg-slate-900">
|
|
97
94
|
<% records.each_with_index do |record, index| %>
|
|
98
|
-
<tr class="
|
|
95
|
+
<tr class="hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
|
|
99
96
|
<% columns.each do |key, options| %>
|
|
100
|
-
<td class="px-6 py-
|
|
97
|
+
<td class="px-6 py-5 whitespace-nowrap text-sm text-slate-700 dark:text-slate-300 font-medium <%= options[:class] %>">
|
|
101
98
|
<% if options[:block] %>
|
|
102
99
|
<%= options[:block].call(record) %>
|
|
103
100
|
<% else %>
|
|
@@ -109,8 +106,16 @@
|
|
|
109
106
|
<% end %>
|
|
110
107
|
<% if records.empty? %>
|
|
111
108
|
<tr>
|
|
112
|
-
<td colspan="<%= columns.size %>" class="px-6 py-
|
|
113
|
-
|
|
109
|
+
<td colspan="<%= columns.size %>" class="px-6 py-12 text-center text-sm text-slate-500 dark:text-slate-400">
|
|
110
|
+
<div class="flex flex-col items-center justify-center space-y-3">
|
|
111
|
+
<div style="height: 48px; width: 48px;" class="mx-auto text-slate-300">
|
|
112
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" width="48" height="48" style="min-width: 48px; min-height: 48px;">
|
|
113
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
|
114
|
+
</svg>
|
|
115
|
+
</div>
|
|
116
|
+
<p class="text-base font-medium text-slate-900 dark:text-white">No records found</p>
|
|
117
|
+
<p class="text-slate-400">Try adjusting your search or filters</p>
|
|
118
|
+
</div>
|
|
114
119
|
</td>
|
|
115
120
|
</tr>
|
|
116
121
|
<% end %>
|
|
@@ -118,40 +123,52 @@
|
|
|
118
123
|
</table>
|
|
119
124
|
</div>
|
|
120
125
|
|
|
121
|
-
<!-- Pagination Footer -->
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
126
|
+
<!-- Clean Pagination Footer -->
|
|
127
|
+
<% if @grid.total_pages > 1 %>
|
|
128
|
+
<div class="flex items-center justify-between px-6 py-4 border-t border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-900 rounded-b-xl">
|
|
129
|
+
<!-- Mobile Pagination help text -->
|
|
130
|
+
<div class="text-sm text-slate-700 dark:text-slate-400 hidden sm:block">
|
|
131
|
+
Showing <span class="font-medium"><%= @grid.current_page %></span> of <span class="font-medium"><%= @grid.total_pages %></span> pages
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
<!-- Centered Pagination Controls -->
|
|
135
|
+
<div class="flex-1 flex justify-end sm:justify-end">
|
|
136
|
+
<nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
|
|
137
|
+
<!-- Prev -->
|
|
138
|
+
<%= link_to (@grid.current_page > 1 ? request.params.merge(page: @grid.current_page - 1) : "#"),
|
|
139
|
+
class: "relative inline-flex items-center px-2 py-2 rounded-l-md border border-slate-300 dark:border-slate-700 bg-white dark:bg-slate-800 text-sm font-medium #{@grid.current_page > 1 ? 'text-slate-500 hover:bg-slate-50 dark:text-slate-400 dark:hover:bg-slate-700' : 'text-slate-300 cursor-not-allowed'}",
|
|
140
|
+
disabled: @grid.current_page <= 1,
|
|
141
|
+
data: { turbo_action: "advance" } do %>
|
|
142
|
+
<span class="sr-only">Previous</span>
|
|
143
|
+
<svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
144
|
+
<path fill-rule="evenodd" d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z" clip-rule="evenodd" />
|
|
145
|
+
</svg>
|
|
146
|
+
<% end %>
|
|
147
|
+
|
|
148
|
+
<% @grid.pagination_window.each do |page| %>
|
|
149
|
+
<% if page == :gap %>
|
|
150
|
+
<span class="relative inline-flex items-center px-4 py-2 border border-slate-300 dark:border-slate-700 bg-white dark:bg-slate-800 text-sm font-medium text-slate-700 dark:text-slate-300">...</span>
|
|
151
|
+
<% elsif page == @grid.current_page %>
|
|
152
|
+
<span class="z-10 bg-indigo-50 dark:bg-indigo-900 border-indigo-500 text-indigo-600 dark:text-indigo-200 relative inline-flex items-center px-4 py-2 border text-sm font-medium"><%= page %></span>
|
|
153
|
+
<% else %>
|
|
154
|
+
<%= link_to page, request.params.merge(page: page), class: "bg-white dark:bg-slate-800 border-slate-300 dark:border-slate-700 text-slate-500 hover:bg-slate-50 dark:text-slate-400 dark:hover:bg-slate-700 relative inline-flex items-center px-4 py-2 border text-sm font-medium", data: { turbo_action: "advance" } %>
|
|
155
|
+
<% end %>
|
|
156
|
+
<% end %>
|
|
147
157
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
158
|
+
<!-- Next -->
|
|
159
|
+
<%= link_to (@grid.current_page < @grid.total_pages ? request.params.merge(page: @grid.current_page + 1) : "#"),
|
|
160
|
+
class: "relative inline-flex items-center px-2 py-2 rounded-r-md border border-slate-300 dark:border-slate-700 bg-white dark:bg-slate-800 text-sm font-medium #{@grid.current_page < @grid.total_pages ? 'text-slate-500 hover:bg-slate-50 dark:text-slate-400 dark:hover:bg-slate-700' : 'text-slate-300 cursor-not-allowed'}",
|
|
161
|
+
disabled: @grid.current_page >= @grid.total_pages,
|
|
162
|
+
data: { turbo_action: "advance" } do %>
|
|
163
|
+
<span class="sr-only">Next</span>
|
|
164
|
+
<svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
165
|
+
<path fill-rule="evenodd" d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" clip-rule="evenodd" />
|
|
166
|
+
</svg>
|
|
167
|
+
<% end %>
|
|
151
168
|
</nav>
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
</div>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
<% end %>
|
|
156
172
|
<% end %>
|
|
157
173
|
</div>
|
|
174
|
+
<%# Optimized script for input debounce if needed elsewhere, but handled by stimulus in this project context %>
|
data/lib/power_grid/base.rb
CHANGED
|
@@ -29,10 +29,13 @@ module PowerGrid
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
attr_reader :params, :initial_scope
|
|
32
|
+
attr_accessor :hide_controls
|
|
32
33
|
|
|
33
34
|
def initialize(params = {}, initial_scope: nil, **options)
|
|
35
|
+
params = params.to_unsafe_h if params.respond_to?(:to_unsafe_h)
|
|
34
36
|
@params = params.merge(options)
|
|
35
37
|
@initial_scope = initial_scope
|
|
38
|
+
@hide_controls = false # Initialize to false by default
|
|
36
39
|
end
|
|
37
40
|
|
|
38
41
|
def records
|
data/lib/power_grid/version.rb
CHANGED