katalyst-tables 3.5.1 → 3.5.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3814f29f662d5198c08b423d4f7ac76a07e327588f601fcc163adaa239f7b842
4
- data.tar.gz: 24c1a6a392a570cd2338b1d3501a8d6a10c3f96f0d445aafb64b0fa541764e06
3
+ metadata.gz: 5402c4de7c04e40f7586c7ab01498e17a085b16c630a556eecbd5ddf7557fc08
4
+ data.tar.gz: 52de56d41efe1dc78a47e43891db23bcca41feccb285f450e4fb45e5810d51f0
5
5
  SHA512:
6
- metadata.gz: ec8aeebe3f1470b3cc1f0d15802cabf82365d91646b70ea9dabbbb1ad7fca2cde1d983014bbb84bdfd6af0ad3a0fd85305ae33e00de38ed789b105ce5f6b7aae
7
- data.tar.gz: 7b630dde2814a741df30c2dac1c5e21ed23a6137a588413044172ba8b658287462fb7a860d961d8f489ad4be1fe4207b4aab203419bfc2c7ed65cfc6a1437965
6
+ metadata.gz: 107ebb571430631da2083805322b3734d0a1ef5ca9f4bbf43433e0e32658ea3fec5ad8bb94e8cf768978e2b1d9224f755f81d0e32b69e59737425f23c5f9c68f
7
+ data.tar.gz: c43331d1a1fc21587f0cd5a874a5adbf34813b94eae3007586418b3c440876ec00a8e810aa19eb2d15eb52b55f4c37280dee8992f8e86e95ae826094bfc5ad74
data/README.md CHANGED
@@ -1,267 +1,10 @@
1
- # Katalyst::Tables
1
+ # Katalyst Tables
2
2
 
3
- Tools for building HTML tables from ActiveRecord collections.
3
+ A library for viewing and interacting with database tables in Ruby on Rails.
4
4
 
5
- ## Installation
5
+ ## Documentation
6
6
 
7
- Add this line to your application's Gemfile:
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
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
15
+ Katalyst Tables is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -96,10 +96,12 @@
96
96
  }
97
97
  }
98
98
 
99
- .footer {
99
+ footer {
100
100
  grid-area: footer;
101
101
  display: flex;
102
- justify-content: flex-end;
103
- padding-block: 1rem;
102
+ justify-content: flex-start;
103
+ padding-inline: 1rem;
104
+ padding-block: 0.5rem;
105
+ border-top: 1px solid #d3d3d3;
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
- attr_reader :pagy_options
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
@@ -22,6 +22,12 @@ module Katalyst
22
22
  collection.suggestions.each do |suggestion|
23
23
  with_suggestion(suggestion:)
24
24
  end
25
+
26
+ unless footer?
27
+ with_footer do
28
+ link_to("Search syntax", "https://katalyst.github.io/tables/users/queries")
29
+ end
30
+ end
25
31
  end
26
32
 
27
33
  private
@@ -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
- def anchor_string
45
- "data-turbo-action=\"replace\""
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.dup)
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.1
4
+ version: 3.5.2
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-18 00:00:00.000000000 Z
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