datagrid 1.8.2 → 2.0.0
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/.yardopts +2 -0
- data/CHANGELOG.md +11 -1
- data/{Readme.markdown → README.md} +44 -29
- data/app/assets/stylesheets/datagrid.css +145 -0
- data/app/views/datagrid/_enum_checkboxes.html.erb +5 -3
- data/app/views/datagrid/_form.html.erb +4 -4
- data/app/views/datagrid/_head.html.erb +26 -3
- data/app/views/datagrid/_range_filter.html.erb +5 -3
- data/app/views/datagrid/_row.html.erb +12 -1
- data/app/views/datagrid/_table.html.erb +4 -4
- data/datagrid.gemspec +8 -7
- data/lib/datagrid/active_model.rb +9 -17
- data/lib/datagrid/base.rb +39 -0
- data/lib/datagrid/column_names_attribute.rb +9 -11
- data/lib/datagrid/columns/column.rb +155 -133
- data/lib/datagrid/columns.rb +325 -115
- data/lib/datagrid/configuration.rb +33 -4
- data/lib/datagrid/core.rb +89 -54
- data/lib/datagrid/deprecated_object.rb +20 -0
- data/lib/datagrid/drivers/abstract_driver.rb +12 -23
- data/lib/datagrid/drivers/active_record.rb +24 -26
- data/lib/datagrid/drivers/array.rb +22 -14
- data/lib/datagrid/drivers/mongo_mapper.rb +15 -14
- data/lib/datagrid/drivers/mongoid.rb +15 -17
- data/lib/datagrid/drivers/sequel.rb +14 -19
- data/lib/datagrid/drivers.rb +2 -1
- data/lib/datagrid/engine.rb +11 -3
- data/lib/datagrid/filters/base_filter.rb +166 -143
- data/lib/datagrid/filters/boolean_filter.rb +19 -5
- data/lib/datagrid/filters/date_filter.rb +33 -35
- data/lib/datagrid/filters/date_time_filter.rb +24 -16
- data/lib/datagrid/filters/default_filter.rb +9 -3
- data/lib/datagrid/filters/dynamic_filter.rb +151 -105
- data/lib/datagrid/filters/enum_filter.rb +43 -19
- data/lib/datagrid/filters/extended_boolean_filter.rb +39 -31
- data/lib/datagrid/filters/float_filter.rb +15 -5
- data/lib/datagrid/filters/integer_filter.rb +21 -10
- data/lib/datagrid/filters/ranged_filter.rb +66 -45
- data/lib/datagrid/filters/select_options.rb +58 -49
- data/lib/datagrid/filters/string_filter.rb +9 -4
- data/lib/datagrid/filters.rb +204 -79
- data/lib/datagrid/form_builder.rb +116 -128
- data/lib/datagrid/generators/scaffold.rb +184 -0
- data/lib/datagrid/generators/views.rb +20 -0
- data/lib/datagrid/helper.rb +436 -69
- data/lib/datagrid/ordering.rb +26 -29
- data/lib/datagrid/rspec.rb +6 -10
- data/lib/datagrid/utils.rb +37 -30
- data/lib/datagrid/version.rb +3 -1
- data/lib/datagrid.rb +8 -28
- data/templates/base.rb.erb +6 -4
- data/templates/grid.rb.erb +1 -1
- metadata +17 -17
- data/app/assets/stylesheets/datagrid.sass +0 -134
- data/lib/datagrid/filters/composite_filters.rb +0 -49
- data/lib/datagrid/renderer.rb +0 -157
- data/lib/datagrid/scaffold.rb +0 -129
- data/lib/tasks/datagrid_tasks.rake +0 -15
- data/templates/controller.rb.erb +0 -6
- data/templates/index.html.erb +0 -5
data/lib/datagrid/helper.rb
CHANGED
@@ -1,10 +1,248 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "action_view"
|
3
4
|
|
4
5
|
module Datagrid
|
6
|
+
# # Datagrid Frontend Guide
|
7
|
+
#
|
8
|
+
# ## Description
|
9
|
+
#
|
10
|
+
# The easiest way to start with Datagrid frontend is by using the generator:
|
11
|
+
#
|
12
|
+
# ``` sh
|
13
|
+
# rails generate datagrid:scaffold users
|
14
|
+
# ```
|
15
|
+
#
|
16
|
+
# This command builds the controller, view, route, and adds
|
17
|
+
# [built-in CSS](https://github.com/bogdan/datagrid/blob/master/app/assets/stylesheets/datagrid.sass).
|
18
|
+
#
|
19
|
+
# Datagrid includes helpers and a form builder for easy frontend generation.
|
20
|
+
# If you need a fully-featured custom GUI, create your templates manually
|
21
|
+
# with the help of the {Datagrid::Columns} API.
|
22
|
+
#
|
23
|
+
# ## Controller and Routing
|
24
|
+
#
|
25
|
+
# Grids usually implement the `index` action of a Rails REST resource. Here's an example:
|
26
|
+
#
|
27
|
+
# resources :models, only: [:index]
|
28
|
+
#
|
29
|
+
# Use the `GET` method in the form, and the controller becomes straightforward:
|
30
|
+
#
|
31
|
+
# class ModelsController < ApplicationController
|
32
|
+
# def index
|
33
|
+
# @grid = ModelsGrid.new(params[:my_report]) do |scope|
|
34
|
+
# scope.page(params[:page]) # See pagination section
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# To apply additional scoping conditions, such as visibility based on the current user:
|
40
|
+
#
|
41
|
+
# ModelsGrid.new(params[:my_report]) do |scope|
|
42
|
+
# scope.where(owner_id: current_user.id).page(params[:page])
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# To pass an object to a grid instance, define it as an accessible attribute:
|
46
|
+
#
|
47
|
+
# class ModelsGrid
|
48
|
+
# attr_accessor :current_user
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# Then pass it when initializing the grid:
|
52
|
+
#
|
53
|
+
# ModelsGrid.new(params[:models_grid].merge(current_user: current_user))
|
54
|
+
#
|
55
|
+
# ## Form Builder
|
56
|
+
#
|
57
|
+
# ### Basic Method
|
58
|
+
#
|
59
|
+
# Use the built-in partial:
|
60
|
+
#
|
61
|
+
# = datagrid_form_with model: @grid, url: report_path, other_form_for_option: value
|
62
|
+
#
|
63
|
+
# {#datagrid_form_with} supports the same options as Rails `form_with`.
|
64
|
+
#
|
65
|
+
# ### Advanced Method
|
66
|
+
#
|
67
|
+
# You can use Rails built-in tools to create a form.
|
68
|
+
# Additionally, Datagrid provides helpers to generate input/select elements for filters:
|
69
|
+
#
|
70
|
+
# ``` haml
|
71
|
+
# - form_with model: UserGrid.new, method: :get, url: users_path do |f|
|
72
|
+
# %div
|
73
|
+
# = f.datagrid_label :name
|
74
|
+
# = f.datagrid_filter :name # => <input name="grid[name]" type="text"/>
|
75
|
+
# %div
|
76
|
+
# = f.datagrid_label :category_id
|
77
|
+
# = f.datagrid_filter :category_id # => <select name="grid[category_id]">....</select>
|
78
|
+
# ```
|
79
|
+
#
|
80
|
+
# For more flexibility, use Rails default helpers:
|
81
|
+
#
|
82
|
+
# %div
|
83
|
+
# = f.label :name
|
84
|
+
# = f.text_field :name
|
85
|
+
#
|
86
|
+
# See the localization section of {Datagrid::Filters}.
|
87
|
+
#
|
88
|
+
# ## Datagrid Table
|
89
|
+
#
|
90
|
+
# Use the helper to display a report:
|
91
|
+
#
|
92
|
+
# %div== Total #{@grid.assets.total}
|
93
|
+
# = datagrid_table(@report)
|
94
|
+
# = will_paginate @report.assets
|
95
|
+
#
|
96
|
+
# Options:
|
97
|
+
#
|
98
|
+
# - `:html` - Attributes for the `<table>` tag.
|
99
|
+
# - `:order` - Set to `false` to disable ordering controls (default: `true`).
|
100
|
+
# - `:columns` - Specify an array of column names to display.
|
101
|
+
#
|
102
|
+
# ## Pagination
|
103
|
+
#
|
104
|
+
# Datagrid is abstracted from pagination but integrates seamlessly with tools like Kaminari, WillPaginate, or Pagy:
|
105
|
+
#
|
106
|
+
# # Kaminari
|
107
|
+
# @grid = MyGrid.new(params[:grid]) do |scope|
|
108
|
+
# scope.page(params[:page]).per(10)
|
109
|
+
# end
|
110
|
+
#
|
111
|
+
# # WillPaginate
|
112
|
+
# @grid = MyGrid.new(params[:grid]) do |scope|
|
113
|
+
# scope.page(params[:page]).per_page(10)
|
114
|
+
# end
|
115
|
+
#
|
116
|
+
# # Pagy
|
117
|
+
# @grid = MyGrid.new(params[:grid])
|
118
|
+
# @pagy, @records = pagy(@grid.assets)
|
119
|
+
#
|
120
|
+
# Render the paginated collection:
|
121
|
+
#
|
122
|
+
# # WillPaginate or Kaminari
|
123
|
+
# <%= datagrid_table(@grid, options) %>
|
124
|
+
# # Pagy
|
125
|
+
# <%= datagrid_table(@grid, @records, options) %>
|
126
|
+
#
|
127
|
+
# ## CSV Export
|
128
|
+
#
|
129
|
+
# Add CSV support to your controller:
|
130
|
+
#
|
131
|
+
# class UsersController < ApplicationController
|
132
|
+
# def index
|
133
|
+
# @grid = UsersGrid.new(params[:users_grid])
|
134
|
+
# respond_to do |f|
|
135
|
+
# f.html { @grid.scope { |scope| scope.page(params[:page]) } }
|
136
|
+
# f.csv do
|
137
|
+
# send_data @grid.to_csv, type: "text/csv", disposition: 'inline', filename: "grid-#{Time.now.to_s}.csv"
|
138
|
+
# end
|
139
|
+
# end
|
140
|
+
# end
|
141
|
+
# end
|
142
|
+
#
|
143
|
+
# Add a button in your interface:
|
144
|
+
#
|
145
|
+
# link_to "Get CSV", url_for(format: 'csv', users_grid: params[:users_grid])
|
146
|
+
#
|
147
|
+
# ## AJAX
|
148
|
+
#
|
149
|
+
# Datagrid supports asynchronous data loading. Add this to your controller:
|
150
|
+
#
|
151
|
+
# if request.xhr?
|
152
|
+
# render json: {table: view_context.datagrid_table(@grid)}
|
153
|
+
# end
|
154
|
+
#
|
155
|
+
# Modify the form for AJAX:
|
156
|
+
#
|
157
|
+
# = datagrid_form_with model: @grid, html: {class: 'js-datagrid-form'}
|
158
|
+
# .js-datagrid-table
|
159
|
+
# = datagrid_table @grid
|
160
|
+
# .js-pagination
|
161
|
+
# = paginate @grid.assets
|
162
|
+
# :javascript
|
163
|
+
# $('.js-datagrid-form').submit(function(event) {
|
164
|
+
# event.preventDefault();
|
165
|
+
# $.get($(this).attr("action"), $(this).serialize(), function (data) {
|
166
|
+
# $('.js-datagrid-table').html(data.table);
|
167
|
+
# });
|
168
|
+
# });
|
169
|
+
#
|
170
|
+
# ## Modifying Built-In Partials
|
171
|
+
#
|
172
|
+
# To customize Datagrid views:
|
173
|
+
#
|
174
|
+
# rake datagrid:copy_partials
|
175
|
+
#
|
176
|
+
# This creates files in `app/views/datagrid/`, which you can modify to suit your needs:
|
177
|
+
#
|
178
|
+
# app/views/datagrid/
|
179
|
+
# ├── _enum_checkboxes.html.erb # datagrid_filter for filter(name, :enum, checkboxes: true)
|
180
|
+
# ├── _form.html.erb # datagrid_form_with
|
181
|
+
# ├── _head.html.erb # datagrid_header
|
182
|
+
# ├── _range_filter.html.erb # datagrid_filter for filter(name, type, range: true)
|
183
|
+
# ├── _row.html.erb # datagrid_rows/datagrid_rows
|
184
|
+
# └── _table.html.erb # datagrid_table
|
185
|
+
#
|
186
|
+
# ## Custom Options
|
187
|
+
#
|
188
|
+
# You can add custom options to Datagrid columns and filters and implement their support on the frontend.
|
189
|
+
# For example, you might want to add a `description` option to a column that appears as a tooltip on mouseover.
|
190
|
+
#
|
191
|
+
# column(
|
192
|
+
# :aov, header: 'AOV',
|
193
|
+
# description: 'Average order value: sum of orders subtotal divided by their count'
|
194
|
+
# ) do |category|
|
195
|
+
# category.orders.sum(:subtotal) / category.orders.count
|
196
|
+
# end
|
197
|
+
#
|
198
|
+
# The `:description` option is not built into Datagrid, but you can implement it
|
199
|
+
# by adding the following to partial `app/views/datagrid/_header.html.erb`:
|
200
|
+
#
|
201
|
+
# <% if column.options[:description] %>
|
202
|
+
# <a data-toggle="tooltip" title="<%= column.options[:description] %>">
|
203
|
+
# <i class="icon-question-sign"></i>
|
204
|
+
# </a>
|
205
|
+
# <% end %>
|
206
|
+
#
|
207
|
+
# This modification allows the `:description` tooltip to work with your chosen UI and JavaScript library.
|
208
|
+
# The same technique can be applied to filters by calling `filter.options` in corresponding partials.
|
209
|
+
#
|
210
|
+
# ## Highlight Rows
|
211
|
+
#
|
212
|
+
# To add custom HTML classes to each row for styling, modify the `_row.html.erb` partial:
|
213
|
+
#
|
214
|
+
# ``` diff
|
215
|
+
# -<tr>
|
216
|
+
# +<tr class="<%= grid.respond_to?(:row_class) ? grid.row_class(asset) : "" %>">
|
217
|
+
# <% grid.html_columns(*options[:columns]).each do |column| %>
|
218
|
+
# <td class="<%= datagrid_column_classes(grid, column) %>">
|
219
|
+
# <%= datagrid_value(grid, column, asset) %>
|
220
|
+
# </td>
|
221
|
+
# <% end %>
|
222
|
+
# ```
|
223
|
+
#
|
224
|
+
# This allows you to define a custom `row_class` method in your grid class, like this:
|
225
|
+
#
|
226
|
+
# class IssuesGrid < ApplicationGrid
|
227
|
+
# scope { Issue }
|
228
|
+
#
|
229
|
+
# def row_class(issue)
|
230
|
+
# case issue.status
|
231
|
+
# when "fixed" then "green"
|
232
|
+
# when "rejected" then "red"
|
233
|
+
# else "blue"
|
234
|
+
# end
|
235
|
+
# end
|
236
|
+
# end
|
237
|
+
#
|
238
|
+
# ## Localization
|
239
|
+
#
|
240
|
+
# You can overwrite Datagrid’s custom localization keys at the application level.
|
241
|
+
# See the localization keys here:
|
242
|
+
#
|
243
|
+
# https://github.com/bogdan/datagrid/blob/master/lib/datagrid/locale/en.yml
|
5
244
|
module Helper
|
6
|
-
|
7
|
-
# @param grid [Datagrid] grid object
|
245
|
+
# @param grid [Datagrid::Base] grid object
|
8
246
|
# @param column [Datagrid::Columns::Column, String, Symbol] column name
|
9
247
|
# @param model [Object] an object from grid scope
|
10
248
|
# @return [Object] individual cell value from the given grid, column name and model
|
@@ -15,7 +253,9 @@ module Datagrid
|
|
15
253
|
# <% end %>
|
16
254
|
# </ul>
|
17
255
|
def datagrid_value(grid, column, model)
|
18
|
-
|
256
|
+
column = grid.column_by_name(column) if column.is_a?(String) || column.is_a?(Symbol)
|
257
|
+
|
258
|
+
grid.html_value(column, self, model)
|
19
259
|
end
|
20
260
|
|
21
261
|
# @!visibility private
|
@@ -26,133 +266,260 @@ module Datagrid
|
|
26
266
|
# Renders html table with columns defined in grid class.
|
27
267
|
# In the most common used you need to pass paginated collection
|
28
268
|
# to datagrid table because datagrid do not have pagination compatibilities:
|
29
|
-
#
|
30
|
-
#
|
31
|
-
# * <tt>:html</tt> - hash of attributes for <table> tag
|
32
|
-
# * <tt>:order</tt> - If false do not generate ordering controlls.
|
33
|
-
# Default: true.
|
34
|
-
# * <tt>:columns</tt> - Array of column names to display.
|
35
|
-
# Used in case when same grid class is used in different places
|
36
|
-
# and needs different columns. Default: all defined columns.
|
37
|
-
# * <tt>:partials</tt> - Path for partials lookup.
|
38
|
-
# Default: 'datagrid'.
|
39
|
-
# @param grid [Datagrid] grid object
|
269
|
+
# @param grid [Datagrid::Base] grid object
|
40
270
|
# @param assets [Array] objects from grid scope
|
271
|
+
# @param [Hash{Symbol => Object}] options HTML attributes to be passed to `<table>` tag
|
272
|
+
# @option options [Hash] html A hash of attributes for the `<table>` tag.
|
273
|
+
# @option options [Boolean] order Whether to generate ordering controls.
|
274
|
+
# If set to `false`, ordering controls are not generated. Default: `true`.
|
275
|
+
# @option options [Array<Symbol>] columns An array of column names to display.
|
276
|
+
# Use this when the same grid class is used in different contexts and requires different columns.
|
277
|
+
# Default: all defined columns.
|
278
|
+
# @option options [String] partials The path for partials lookup. Default: `'datagrid'`.
|
41
279
|
# @return [String] table tag HTML markup
|
42
280
|
# @example
|
43
281
|
# assets = grid.assets.page(params[:page])
|
44
282
|
# datagrid_table(grid, assets, options)
|
45
283
|
def datagrid_table(grid, assets = grid.assets, **options)
|
46
|
-
|
284
|
+
_render_partial(
|
285
|
+
"table", options[:partials],
|
286
|
+
{
|
287
|
+
grid: grid,
|
288
|
+
options: options,
|
289
|
+
assets: assets,
|
290
|
+
},
|
291
|
+
)
|
47
292
|
end
|
48
293
|
|
49
294
|
# Renders HTML table header for given grid instance using columns defined in it
|
50
295
|
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
# @param
|
296
|
+
# @option options [Boolean] order Whether to display ordering controls built into the header.
|
297
|
+
# Default: `true`.
|
298
|
+
# @option options [Array<Symbol,String>] columns An array of column names to display.
|
299
|
+
# Use this when the same grid class is used in different contexts and requires different columns.
|
300
|
+
# Default: all defined columns.
|
301
|
+
# @option options [String] partials The path for partials lookup.
|
302
|
+
# Default: `'datagrid'`.
|
303
|
+
# @param grid [Datagrid::Base] grid object
|
304
|
+
# @param [Object] opts (deprecated) pass keyword arguments instead
|
305
|
+
# @param [Hash] options
|
61
306
|
# @return [String] HTML table header tag markup
|
62
|
-
def datagrid_header(grid,
|
63
|
-
|
64
|
-
|
307
|
+
def datagrid_header(grid, opts = :__unspecified__, **options)
|
308
|
+
unless opts == :__unspecified__
|
309
|
+
Datagrid::Utils.warn_once("datagrid_header now requires ** operator when passing options.")
|
310
|
+
options.reverse_merge!(opts)
|
311
|
+
end
|
312
|
+
options[:order] = true unless options.key?(:order)
|
65
313
|
|
314
|
+
_render_partial("head", options[:partials],
|
315
|
+
{ grid: grid, options: options },)
|
316
|
+
end
|
66
317
|
|
67
318
|
# Renders HTML table rows using given grid definition using columns defined in it.
|
68
319
|
# Allows to provide a custom layout for each for in place with a block
|
69
320
|
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
# @example
|
79
|
-
# = datagrid_rows(grid)
|
80
|
-
#
|
81
|
-
# = datagrid_rows(grid) do |row| # Custom Layout
|
321
|
+
# @option options [Array<Symbol>] columns An array of column names to display.
|
322
|
+
# Use this when the same grid class is used in different contexts and requires different columns.
|
323
|
+
# Default: all defined columns.
|
324
|
+
# @option options [String] partials The path for partials lookup.
|
325
|
+
# Default: `'datagrid'`.
|
326
|
+
# @return [String]
|
327
|
+
# @example Generic table rows Layout
|
328
|
+
# = datagrid_rows(grid)
|
329
|
+
# @example Custom Layout
|
330
|
+
# = datagrid_rows(grid) do |row|
|
82
331
|
# %tr
|
83
332
|
# %td= row.project_name
|
84
333
|
# %td.project-status{class: row.status}= row.status
|
334
|
+
# @param [Datagrid::Base] grid datagrid object
|
335
|
+
# @param [Array<Object>] assets assets as per defined in grid scope
|
85
336
|
def datagrid_rows(grid, assets = grid.assets, **options, &block)
|
86
|
-
|
337
|
+
safe_join(
|
338
|
+
assets.map do |asset|
|
339
|
+
datagrid_row(grid, asset, **options, &block)
|
340
|
+
end.to_a,
|
341
|
+
)
|
87
342
|
end
|
88
343
|
|
89
|
-
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
#
|
344
|
+
# @return [String] renders ordering controls for the given column name
|
345
|
+
# @option options [String] partials The path for partials lookup.
|
346
|
+
# Default: `'datagrid'`.
|
347
|
+
# @param [Datagrid::Base] grid datagrid object
|
348
|
+
# @param [Datagrid::Columns::Column] column
|
349
|
+
# @deprecated Put necessary code inline inside datagrid/head partial.
|
350
|
+
# See built-in partial for example.
|
95
351
|
def datagrid_order_for(grid, column, options = {})
|
96
|
-
|
352
|
+
Datagrid::Utils.warn_once(<<~MSG)
|
353
|
+
datagrid_order_for is deprecated.
|
354
|
+
Put necessary code inline inside datagrid/head partial.
|
355
|
+
See built-in partial for example.
|
356
|
+
MSG
|
357
|
+
_render_partial("order_for", options[:partials],
|
358
|
+
{ grid: grid, column: column },)
|
97
359
|
end
|
98
360
|
|
99
|
-
# Renders HTML for
|
361
|
+
# Renders HTML for grid with all filters inputs and labels defined in it
|
362
|
+
# @option options [String] partials Path for form partial lookup.
|
363
|
+
# Default: `'datagrid'`, which uses `app/views/datagrid/` partials.
|
364
|
+
# Example: `'datagrid_admin'` uses `app/views/datagrid_admin` partials.
|
365
|
+
# @option options [Datagrid::Base] model a Datagrid object to be rendered.
|
366
|
+
# @option options [Hash] All options supported by Rails `form_with` helper.
|
367
|
+
# @param [Hash{Symbol => Object}] options
|
368
|
+
# @return [String] form HTML tag markup
|
369
|
+
def datagrid_form_with(**options)
|
370
|
+
raise ArgumentError, "datagrid_form_with block argument is invalid. Use form_with instead." if block_given?
|
371
|
+
|
372
|
+
grid = options[:model]
|
373
|
+
raise ArgumentError, "Grid has no available filters" if grid&.filters&.empty?
|
374
|
+
|
375
|
+
_render_partial("form", options[:partials], { grid: options[:model], options: options })
|
376
|
+
end
|
377
|
+
|
378
|
+
# Renders HTML for grid with all filters inputs and labels defined in it
|
100
379
|
#
|
101
380
|
# Supported options:
|
102
381
|
#
|
103
382
|
# * <tt>:partials</tt> - Path for form partial lookup.
|
104
383
|
# Default: 'datagrid'.
|
105
|
-
# * All options supported by Rails <tt>
|
106
|
-
# @
|
384
|
+
# * All options supported by Rails <tt>form_with</tt> helper
|
385
|
+
# @deprecated Use {#datagrid_form_with} instead.
|
386
|
+
# @param grid [Datagrid::Base] grid object
|
387
|
+
# @param [Hash] options
|
107
388
|
# @return [String] form HTML tag markup
|
108
389
|
def datagrid_form_for(grid, options = {})
|
109
|
-
|
390
|
+
Datagrid::Utils.warn_once("datagrid_form_for is deprecated if favor of datagrid_form_with.")
|
391
|
+
_render_partial(
|
392
|
+
"form", options[:partials],
|
393
|
+
grid: grid,
|
394
|
+
options: {
|
395
|
+
method: :get,
|
396
|
+
as: grid.param_name,
|
397
|
+
local: true,
|
398
|
+
**options,
|
399
|
+
},
|
400
|
+
)
|
110
401
|
end
|
111
402
|
|
112
403
|
# Provides access to datagrid columns data.
|
113
404
|
# Used in case you want to build html table completelly manually
|
114
|
-
# @param grid [Datagrid] grid object
|
405
|
+
# @param grid [Datagrid::Base] grid object
|
115
406
|
# @param asset [Object] object from grid scope
|
116
407
|
# @param block [Proc] block with Datagrid::Helper::HtmlRow as an argument returning a HTML markup as a String
|
408
|
+
# @param [Hash{Symbol => Object}] options
|
117
409
|
# @return [Datagrid::Helper::HtmlRow, String] captured HTML markup if block given otherwise row object
|
118
|
-
# @example
|
119
|
-
#
|
410
|
+
# @example Render default layout for row
|
411
|
+
# <%= datagrid_row(grid, user, columns: [:first_name, :last_name, :actions]) %>
|
412
|
+
# @example Rendering custom layout for `first_name` and `last_name` columns
|
120
413
|
# <%= datagrid_row(grid, user) do |row| %>
|
121
414
|
# <tr>
|
122
415
|
# <td><%= row.first_name %></td>
|
123
416
|
# <td><%= row.last_name %></td>
|
124
417
|
# </tr>
|
125
418
|
# <% end %>
|
126
|
-
# @example
|
419
|
+
# @example Rendering custom layout passing a block
|
127
420
|
# <% row = datagrid_row(grid, user) %>
|
128
421
|
# First Name: <%= row.first_name %>
|
129
422
|
# Last Name: <%= row.last_name %>
|
130
|
-
# @example
|
131
|
-
# <%= datagrid_row(grid, user, columns: [:first_name, :last_name, :actions]) %>
|
132
423
|
def datagrid_row(grid, asset, **options, &block)
|
133
|
-
|
424
|
+
Datagrid::Helper::HtmlRow.new(self, grid, asset, options).tap do |row|
|
425
|
+
return capture(row, &block) if block_given?
|
426
|
+
end
|
134
427
|
end
|
135
428
|
|
136
429
|
# Generates an ascending or descending order url for the given column
|
137
|
-
# @param grid [Datagrid] grid object
|
430
|
+
# @param grid [Datagrid::Base] grid object
|
138
431
|
# @param column [Datagrid::Columns::Column, String, Symbol] column name
|
139
|
-
# @param descending [Boolean]
|
432
|
+
# @param descending [Boolean] order direction, descending if true, otherwise ascending.
|
140
433
|
# @return [String] order layout HTML markup
|
141
434
|
def datagrid_order_path(grid, column, descending)
|
142
|
-
|
435
|
+
column = grid.column_by_name(column)
|
436
|
+
query = request&.query_parameters || {}
|
437
|
+
ActionDispatch::Http::URL.path_for(
|
438
|
+
path: request&.path || "/",
|
439
|
+
params: query.merge(grid.query_params(order: column.name, descending: descending)),
|
440
|
+
)
|
143
441
|
end
|
144
442
|
|
443
|
+
# @!visibility private
|
444
|
+
def datagrid_column_classes(grid, column)
|
445
|
+
Datagrid::Utils.warn_once(<<~MSG)
|
446
|
+
datagrid_column_classes is deprecated. Assign necessary classes manually.
|
447
|
+
Correspond to default datagrid/rows partial for example.)
|
448
|
+
MSG
|
449
|
+
column = grid.column_by_name(column)
|
450
|
+
order_class = if grid.ordered_by?(column)
|
451
|
+
["ordered", grid.descending ? "desc" : "asc"]
|
452
|
+
end
|
453
|
+
class_names(column.name, order_class, column.options[:class], column.tag_options[:class])
|
454
|
+
end
|
145
455
|
|
146
456
|
protected
|
147
457
|
|
148
|
-
def
|
149
|
-
|
458
|
+
def _render_partial(partial_name, partials_path, locals = {})
|
459
|
+
render({
|
460
|
+
partial: File.join(partials_path || "datagrid", partial_name),
|
461
|
+
locals: locals,
|
462
|
+
})
|
150
463
|
end
|
151
464
|
|
152
|
-
|
153
|
-
|
154
|
-
|
465
|
+
# Represents a datagrid row that provides access to column values for the given asset
|
466
|
+
# @example
|
467
|
+
# row = datagrid_row(grid, user)
|
468
|
+
# row.class # => Datagrid::Helper::HtmlRow
|
469
|
+
# row.first_name # => "<strong>Bogdan</strong>"
|
470
|
+
# row.grid # => Datagrid::Base object
|
471
|
+
# row.asset # => User object
|
472
|
+
# row.each do |value|
|
473
|
+
# puts value
|
474
|
+
# end
|
475
|
+
class HtmlRow
|
476
|
+
include Enumerable
|
477
|
+
|
478
|
+
attr_reader :grid, :asset, :options
|
479
|
+
|
480
|
+
# @!visibility private
|
481
|
+
def initialize(renderer, grid, asset, options)
|
482
|
+
@renderer = renderer
|
483
|
+
@grid = grid
|
484
|
+
@asset = asset
|
485
|
+
@options = options
|
486
|
+
end
|
487
|
+
|
488
|
+
# @return [Object] a column value for given column name
|
489
|
+
def get(column)
|
490
|
+
@renderer.datagrid_value(@grid, column, @asset)
|
491
|
+
end
|
492
|
+
|
493
|
+
# Iterates over all column values that are available in the row
|
494
|
+
# param block [Proc] column value iterator
|
495
|
+
def each(&block)
|
496
|
+
(@options[:columns] || @grid.html_columns).each do |column|
|
497
|
+
block.call(get(column))
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
# @return [String] HTML row format
|
502
|
+
def to_s
|
503
|
+
@renderer.send(:_render_partial, "row", options[:partials], {
|
504
|
+
grid: grid,
|
505
|
+
options: options,
|
506
|
+
asset: asset,
|
507
|
+
},)
|
508
|
+
end
|
509
|
+
|
510
|
+
protected
|
511
|
+
|
512
|
+
def method_missing(method, *args, &blk)
|
513
|
+
if (column = @grid.column_by_name(method))
|
514
|
+
get(column)
|
515
|
+
else
|
516
|
+
super
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
def respond_to_missing?(method, include_private = false)
|
521
|
+
!!@grid.column_by_name(method) || super
|
522
|
+
end
|
155
523
|
end
|
156
524
|
end
|
157
525
|
end
|
158
|
-
|