katalyst-tables 3.5.1 → 3.5.3
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/README.md +5 -262
- data/app/assets/stylesheets/katalyst/tables/_query.scss +7 -5
- data/app/components/katalyst/tables/pagy_nav_component.rb +15 -1
- data/app/components/katalyst/tables/query/modal_component.html.erb +6 -4
- data/app/controllers/concerns/katalyst/tables/backend.rb +14 -0
- data/app/helpers/katalyst/tables/frontend.rb +13 -0
- data/app/models/concerns/katalyst/tables/collection/pagination.rb +6 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67d99ce2d2301f9752494026a850f959582c8526629c9958e6cc9a330097012a
|
4
|
+
data.tar.gz: 3a17c798586675a6ac31d737e0b15700217c37ce39d93d9bea4db1a88489ddf0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 67282005deb832f18264557f4bb0334fabc53594325af5503e5a5839c8759f95f75fdabddef0c5d627ea38f281068540c78811f693f9319477d1aba74bb65882
|
7
|
+
data.tar.gz: b1158053505b7c836c96f7b1e0bb0e65578e45bc7d8f16c7fc1708059e69712e7809e3bd0a7bcfebd7091531ebbe1713140d0ed35b8ec70e1c0c490915dd1295
|
data/README.md
CHANGED
@@ -1,267 +1,10 @@
|
|
1
|
-
# Katalyst
|
1
|
+
# Katalyst Tables
|
2
2
|
|
3
|
-
|
3
|
+
A library for viewing and interacting with database tables in Ruby on Rails.
|
4
4
|
|
5
|
-
##
|
5
|
+
## Documentation
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
```ruby
|
10
|
-
gem "katalyst-tables"
|
11
|
-
```
|
12
|
-
|
13
|
-
And then execute:
|
14
|
-
|
15
|
-
$ bundle install
|
16
|
-
|
17
|
-
Add the Gem's javascript and CSS to your build pipeline. This assumes that
|
18
|
-
you're using `rails-dartsass` and `importmaps` to manage your assets.
|
19
|
-
|
20
|
-
```javascript
|
21
|
-
// app/javascript/controllers/application.js
|
22
|
-
import { application } from "controllers/application";
|
23
|
-
import tables from "@katalyst/tables";
|
24
|
-
application.load(tables);
|
25
|
-
```
|
26
|
-
|
27
|
-
```scss
|
28
|
-
// app/assets/stylesheets/application.scss
|
29
|
-
@use "@katalyst/tables";
|
30
|
-
```
|
31
|
-
|
32
|
-
## Usage
|
33
|
-
|
34
|
-
This gem provides entry points for backend and frontend concerns:
|
35
|
-
* `Katalyst::TableComponent` can be used render encapsulated tables,
|
36
|
-
* `Katalyst::SummaryTableComponent` can be used render a record using the table syntax,
|
37
|
-
* `Katalyst::Tables::Frontend` provides `table_with` for inline table generation,
|
38
|
-
* `Katalyst::Tables::Collection::Base` provides a default entry point for
|
39
|
-
building collections in your controller actions
|
40
|
-
* `Katalyst::Tables::Collection::Query` provides build-in query parsing and filtering
|
41
|
-
based on the attributes defined in your collection.
|
42
|
-
|
43
|
-
### Frontend
|
44
|
-
|
45
|
-
Add `include Katalyst::Tables::Frontend` to your `ApplicationHelper` or similar.
|
46
|
-
|
47
|
-
You can use the `table_with` helper to generate a table inline in your view without explicitly interacting with the
|
48
|
-
table component. This is the preferred approach when creating tables. However, if the table is complex or you need to
|
49
|
-
reuse it, you should consider moving the definition of the row into a partial.
|
50
|
-
|
51
|
-
```erb
|
52
|
-
<%= table_with collection: @people do |row, person| %>
|
53
|
-
<% row.text :name do |cell| %>
|
54
|
-
<%= link_to cell.value, [:edit, person] %>
|
55
|
-
<% end %>
|
56
|
-
<% row.text :email %>
|
57
|
-
<% end %>
|
58
|
-
```
|
59
|
-
|
60
|
-
By not providing a block to the `table_with` call, the gem will look for a partial called `_person.html+row.erb` to
|
61
|
-
render each row:
|
62
|
-
|
63
|
-
```erb
|
64
|
-
<%# locals: { row:, person: nil } %>
|
65
|
-
<% row.text :name do |cell| %>
|
66
|
-
<%= link_to cell.value, [:edit, person] %>
|
67
|
-
<% end %>
|
68
|
-
<% row.text :email %>
|
69
|
-
```
|
70
|
-
|
71
|
-
The table will call your block / partial once per row and accumulate the cells
|
72
|
-
you generate into rows, including a header row:
|
73
|
-
|
74
|
-
```html
|
75
|
-
|
76
|
-
<table>
|
77
|
-
<thead>
|
78
|
-
<tr>
|
79
|
-
<th>Name</th>
|
80
|
-
<th>Email</th>
|
81
|
-
</tr>
|
82
|
-
</thead>
|
83
|
-
<tbody>
|
84
|
-
<tr>
|
85
|
-
<td><a href="/people/1/edit">Alice</a></td>
|
86
|
-
<td>alice@acme.org</td>
|
87
|
-
</tr>
|
88
|
-
<tr>
|
89
|
-
<td><a href="/people/2/edit">Bob</a></td>
|
90
|
-
<td>bob@acme.org</td>
|
91
|
-
</tr>
|
92
|
-
</tbody>
|
93
|
-
</table>
|
94
|
-
```
|
95
|
-
|
96
|
-
You can customize the partial and/or the name of the resource in a similar style
|
97
|
-
to view partials:
|
98
|
-
|
99
|
-
```erb
|
100
|
-
<%= table_with(collection: @employees, as: :person, partial: "person") %>
|
101
|
-
```
|
102
|
-
|
103
|
-
### HTML Attributes
|
104
|
-
|
105
|
-
You can add custom attributes on table, row, and cell tags.
|
106
|
-
|
107
|
-
The table tag takes attributes passed to `table_with` helper, similar to `form_with`:
|
108
|
-
|
109
|
-
```erb
|
110
|
-
<%= table_with(collection: @people, id: "people-table")
|
111
|
-
```
|
112
|
-
|
113
|
-
Cells support the same approach:
|
114
|
-
|
115
|
-
```erb
|
116
|
-
<%= row.text :name, class: "name" %>
|
117
|
-
```
|
118
|
-
|
119
|
-
Rows do not get called directly, so instead you can assign to `html_attributes` on the row builder to customize row tag
|
120
|
-
generation.
|
121
|
-
|
122
|
-
```erb
|
123
|
-
<% row.update_html_attributes(id: person.id) if row.body? %>
|
124
|
-
```
|
125
|
-
|
126
|
-
Note: because the row builder gets called to generate the header row, you may need to guard calls that access the
|
127
|
-
`person` directly as shown in the previous example. You could also check whether `person` is present.
|
128
|
-
|
129
|
-
### Headers
|
130
|
-
|
131
|
-
Tables will automatically generate a header row for you by calling your row partial or provided block with no object.
|
132
|
-
During this call, `row.header?` is true, `row.body?` is false, and the object (`person`) is nil.
|
133
|
-
|
134
|
-
All cells generated in the table header iteration will automatically be header cells, but you can also make header cells
|
135
|
-
in your body rows by passing `heading: true` when you generate the cell.
|
136
|
-
|
137
|
-
```erb
|
138
|
-
<% row.number :id, heading: true %>
|
139
|
-
```
|
140
|
-
|
141
|
-
The table header cells default to showing the capitalized column name, but you can customize this in one of two ways:
|
142
|
-
|
143
|
-
* Set the value inline
|
144
|
-
```erb
|
145
|
-
<% row.number :id, label: "ID" %>
|
146
|
-
```
|
147
|
-
* Define a translation for the attribute
|
148
|
-
```yml
|
149
|
-
# en.yml
|
150
|
-
activerecord:
|
151
|
-
attributes:
|
152
|
-
person:
|
153
|
-
id: "ID"
|
154
|
-
```
|
155
|
-
|
156
|
-
Note: if the cell is given a block, it is not called during the header pass. This
|
157
|
-
is because the block is assumed to be for generating data for the body, not the
|
158
|
-
header. We suggest you set `label` instead.
|
159
|
-
|
160
|
-
#### Cell values
|
161
|
-
|
162
|
-
If you do not provide a value when you call the cell builder, the attribute you
|
163
|
-
provide will be retrieved from the current item and the result will be rendered in
|
164
|
-
the table cell. This is often all you need to do, but if you do want to customise
|
165
|
-
the value you can pass a block instead:
|
166
|
-
|
167
|
-
```erb
|
168
|
-
<% row.text :status do %>
|
169
|
-
<%= person.password.present? ? "Active" : "Invited" %>
|
170
|
-
<% end %>
|
171
|
-
```
|
172
|
-
|
173
|
-
In the context of the block you have access the cell component if you simply
|
174
|
-
want to extend the default behaviour:
|
175
|
-
|
176
|
-
```erb
|
177
|
-
<%# @type [Katalyst::Tables::CellComponent] cell %>
|
178
|
-
<% row.text :name do |cell| %>
|
179
|
-
<%= link_to cell, person %>
|
180
|
-
<% end %>
|
181
|
-
```
|
182
|
-
|
183
|
-
You can also update `html_attributes` on the cell builder, similar to the row
|
184
|
-
builder, see `katalyst-html-attributes` for details.
|
185
|
-
|
186
|
-
## Collections
|
187
|
-
|
188
|
-
The `Katalyst::Tables::Collection::Base` class provides a convenient way to
|
189
|
-
manage collections in your controller actions. It is designed to be used with
|
190
|
-
Pagy for pagination and provides built-in sorting when used with ActiveRecord
|
191
|
-
collections. Sorting and Pagination are off by default, you can either set them
|
192
|
-
on creation or create a custom `Collection` class that sets them on by default:
|
193
|
-
|
194
|
-
```ruby
|
195
|
-
# in #index
|
196
|
-
Katalyst::Tables::Collection::Base.new(sorting: "name asc", pagination: true)
|
197
|
-
# or as a nested class in your controller
|
198
|
-
class Collection < Katalyst::Tables::Collection::Base
|
199
|
-
config.sorting = "name asc" # requires models have a name attribute
|
200
|
-
config.pagination = true
|
201
|
-
end
|
202
|
-
```
|
203
|
-
|
204
|
-
Collections can be passed directly to `table_with` method and it will automatically
|
205
|
-
detect features such as sorting and generate the appropriate table header links.
|
206
|
-
|
207
|
-
```erb
|
208
|
-
<%= table_with(collection:) %>
|
209
|
-
```
|
210
|
-
|
211
|
-
### Query
|
212
|
-
|
213
|
-
Include `Katalyst::Tables::Collection::Query` into your collection to add automatic
|
214
|
-
query parsing and filtering based on the configured attributes. For example:
|
215
|
-
|
216
|
-
```ruby
|
217
|
-
class Collection < Katalyst::Tables::Collection::Base
|
218
|
-
include Katalyst::Tables::Collection::Query
|
219
|
-
|
220
|
-
attribute :first_name, :string
|
221
|
-
attribute :created_at, :date
|
222
|
-
end
|
223
|
-
```
|
224
|
-
|
225
|
-
With this definition and a text-input named `query`, your users can write tagged
|
226
|
-
query expressions such as `first_name:Aaron` or `created_at:>2024-01-01` and these
|
227
|
-
will be automatically parsed and applied to the collection attribute, and the collection
|
228
|
-
will automatically generate and apply ActiveRecord conditions to filter the given scope.
|
229
|
-
|
230
|
-
There's also a frontend utility, `table_query_with(collection:)` that will generate the form
|
231
|
-
and show a modal that helps users to interact with the query interface. More details available
|
232
|
-
in the [query](docs/query.md) documentation.
|
233
|
-
|
234
|
-
## Summary tables
|
235
|
-
You can use the `Katalyst::SummaryTableComponent` to render a single record utilizing all the functionality from the
|
236
|
-
`Katalyst::TableComponent`.
|
237
|
-
|
238
|
-
```erb
|
239
|
-
<%= summary_table_with model: @person do |row| %>
|
240
|
-
<% row.text :name %>
|
241
|
-
<% row.text :email %>
|
242
|
-
<% end %>
|
243
|
-
```
|
244
|
-
|
245
|
-
## Extensions
|
246
|
-
|
247
|
-
The following extensions are available and activated by default:
|
248
|
-
|
249
|
-
* [Filtering](docs/filtering.md) - adds automatic collection filtering based on attributes
|
250
|
-
* [Query](docs/query.md) - adds human-friendly text filtering that populates collection attributes
|
251
|
-
* [Identifiable](docs/identifiable.md) - adds default dom ids to the table and data rows.
|
252
|
-
* [Orderable](docs/orderable.md) - adds bulk-update for 'ordinal' columns via dragging rows in the table.
|
253
|
-
* [Pagination](docs/pagination.md) - handles paginating of data in the collection.
|
254
|
-
* [Selectable](docs/selectable.md) - adds bulk-action support for rows in the table.
|
255
|
-
* [Sortable](docs/sortable.md) - table column headers that can be sorted will be wrapped in links.
|
256
|
-
* [Customization](docs/customization.md) - customize the table and cell rendering.
|
257
|
-
|
258
|
-
You can disable extensions by altering the `Katalyst::Tables.config.component_extensions` before initialization.
|
259
|
-
|
260
|
-
## Development
|
261
|
-
|
262
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests.
|
263
|
-
|
264
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
7
|
+
See [katalyst.github.io/tables](https://katalyst.github.io/tables/) for documentation.
|
265
8
|
|
266
9
|
## Contributing
|
267
10
|
|
@@ -269,4 +12,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/kataly
|
|
269
12
|
|
270
13
|
## License
|
271
14
|
|
272
|
-
|
15
|
+
Katalyst Tables is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
@@ -54,7 +54,6 @@
|
|
54
54
|
box-shadow:
|
55
55
|
0 3px 6px rgba(0, 0, 0, 0.16),
|
56
56
|
0 3px 6px rgba(0, 0, 0, 0.23);
|
57
|
-
margin-top: 0.5rem;
|
58
57
|
background: white;
|
59
58
|
border-radius: 4px;
|
60
59
|
z-index: 1;
|
@@ -77,7 +76,7 @@
|
|
77
76
|
.content {
|
78
77
|
grid-area: content;
|
79
78
|
padding-inline: 1rem;
|
80
|
-
padding-block: 0.5rem
|
79
|
+
padding-block: 0.5rem;
|
81
80
|
}
|
82
81
|
|
83
82
|
ul {
|
@@ -96,10 +95,13 @@
|
|
96
95
|
}
|
97
96
|
}
|
98
97
|
|
99
|
-
|
98
|
+
footer {
|
100
99
|
grid-area: footer;
|
101
100
|
display: flex;
|
102
|
-
justify-content: flex-
|
103
|
-
padding-
|
101
|
+
justify-content: flex-start;
|
102
|
+
padding-inline: 1rem;
|
103
|
+
padding-block: 0.5rem;
|
104
|
+
border-top: 1px solid #d3d3d3;
|
105
|
+
font-size: small;
|
104
106
|
}
|
105
107
|
}
|
@@ -7,7 +7,11 @@ module Katalyst
|
|
7
7
|
# Expect to see NoMethodError failures if pagy is not available
|
8
8
|
"Pagy::Frontend".safe_constantize&.tap { |pagy| include(pagy) }
|
9
9
|
|
10
|
-
|
10
|
+
def self.pagy_legacy?
|
11
|
+
Pagy::VERSION.scan(/\d+/).first.to_i <= 8
|
12
|
+
end
|
13
|
+
|
14
|
+
delegate :pagy_legacy?, to: :class
|
11
15
|
|
12
16
|
def initialize(collection: nil, pagy: nil, **pagy_options)
|
13
17
|
super()
|
@@ -24,9 +28,19 @@ module Katalyst
|
|
24
28
|
pagy_nav(@pagy, **pagy_options).html_safe # rubocop:disable Rails/OutputSafety
|
25
29
|
end
|
26
30
|
|
31
|
+
def pagy_options
|
32
|
+
default_pagy_options.merge(@pagy_options)
|
33
|
+
end
|
34
|
+
|
27
35
|
def inspect
|
28
36
|
"#<#{self.class.name} pagy: #{@pagy.inspect}>"
|
29
37
|
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def default_pagy_options
|
42
|
+
pagy_legacy? ? {} : { anchor_string: 'data-turbo-action="replace"' }
|
43
|
+
end
|
30
44
|
end
|
31
45
|
end
|
32
46
|
end
|
@@ -16,9 +16,11 @@
|
|
16
16
|
</ul>
|
17
17
|
<% end %>
|
18
18
|
</div>
|
19
|
-
|
20
|
-
|
19
|
+
<footer>
|
20
|
+
<% if footer? %>
|
21
21
|
<%= footer %>
|
22
|
-
|
23
|
-
|
22
|
+
<% else %>
|
23
|
+
<a href="https://katalyst.github.io/tables/users/queries" target="_blank">Search syntax</a>
|
24
|
+
<% end %>
|
25
|
+
</footer>
|
24
26
|
<% end %>
|
@@ -8,6 +8,7 @@ module Katalyst
|
|
8
8
|
|
9
9
|
included do
|
10
10
|
class_attribute :_default_table_component, instance_accessor: false
|
11
|
+
class_attribute :_default_table_pagination_component, instance_accessor: false
|
11
12
|
class_attribute :_default_table_query_component, instance_accessor: false
|
12
13
|
class_attribute :_default_summary_table_component, instance_accessor: false
|
13
14
|
end
|
@@ -21,6 +22,14 @@ module Katalyst
|
|
21
22
|
self._default_table_component = component
|
22
23
|
end
|
23
24
|
|
25
|
+
# Set the table pagination component to be used as the default for all tables
|
26
|
+
# in the views rendered by this controller and its subclasses.
|
27
|
+
#
|
28
|
+
# @param component [Class] the table pagination component class to use
|
29
|
+
def default_table_pagination_component(component)
|
30
|
+
self._default_table_pagination_component = component
|
31
|
+
end
|
32
|
+
|
24
33
|
# Set the table query component to be used as the default for all tables
|
25
34
|
# in the views rendered by this controller and its subclasses.
|
26
35
|
#
|
@@ -44,6 +53,11 @@ module Katalyst
|
|
44
53
|
self.class._default_table_component
|
45
54
|
end
|
46
55
|
|
56
|
+
# Default table pagination component for this controller
|
57
|
+
def default_table_pagination_component
|
58
|
+
self.class._default_table_pagination_component
|
59
|
+
end
|
60
|
+
|
47
61
|
# Default table query component for this controller
|
48
62
|
def default_table_query_component
|
49
63
|
self.class._default_table_query_component
|
@@ -55,6 +55,14 @@ module Katalyst
|
|
55
55
|
render(Selectable::FormComponent.new(collection:, id:, primary_key:), &)
|
56
56
|
end
|
57
57
|
|
58
|
+
# Construct pagination navigation for the current page. Defaults to pagy_nav.
|
59
|
+
#
|
60
|
+
# @param collection [Katalyst::Tables::Collection::Core] the collection to render
|
61
|
+
def table_pagination_with(collection:, **)
|
62
|
+
component ||= default_table_pagination_component_class
|
63
|
+
render(component.new(collection:, **))
|
64
|
+
end
|
65
|
+
|
58
66
|
# Construct a new query interface for filtering the current page.
|
59
67
|
#
|
60
68
|
# @param collection [Katalyst::Tables::Collection::Core] the collection to render
|
@@ -85,6 +93,11 @@ module Katalyst
|
|
85
93
|
component.respond_to?(:constantize) ? component.constantize : component
|
86
94
|
end
|
87
95
|
|
96
|
+
def default_table_pagination_component_class
|
97
|
+
component = controller.try(:default_table_pagination_component) || PagyNavComponent
|
98
|
+
component.respond_to?(:constantize) ? component.constantize : component
|
99
|
+
end
|
100
|
+
|
88
101
|
def default_table_query_component_class
|
89
102
|
component = controller.try(:default_table_query_component) || QueryComponent
|
90
103
|
component.respond_to?(:constantize) ? component.constantize : component
|
@@ -37,12 +37,12 @@ module Katalyst
|
|
37
37
|
def paginate_options
|
38
38
|
opts = @paginate.is_a?(Hash) ? @paginate : {}
|
39
39
|
opts = opts.dup
|
40
|
-
opts[:anchor_string] ||= anchor_string
|
41
|
-
opts
|
42
|
-
end
|
43
40
|
|
44
|
-
|
45
|
-
|
41
|
+
if PagyNavComponent.pagy_legacy?
|
42
|
+
opts[:anchor_string] ||= "data-turbo-action=\"replace\""
|
43
|
+
end
|
44
|
+
|
45
|
+
opts
|
46
46
|
end
|
47
47
|
|
48
48
|
class Paginate # :nodoc:
|
@@ -57,7 +57,7 @@ module Katalyst
|
|
57
57
|
def call(collection)
|
58
58
|
@collection = @app.call(collection)
|
59
59
|
if collection.paginate?
|
60
|
-
@collection.pagination, @collection.items = pagy(@collection.items, collection.paginate_options
|
60
|
+
@collection.pagination, @collection.items = pagy(@collection.items, **collection.paginate_options)
|
61
61
|
end
|
62
62
|
@collection
|
63
63
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: katalyst-tables
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.5.
|
4
|
+
version: 3.5.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Katalyst Interactive
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07-
|
11
|
+
date: 2024-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: katalyst-html-attributes
|