admino 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +82 -52
- data/lib/admino/query/filter_group.rb +4 -4
- data/lib/admino/query/filter_group_presenter.rb +7 -3
- data/lib/admino/table/head_row.rb +24 -12
- data/lib/admino/table/presenter.rb +27 -11
- data/lib/admino/table/resource_row.rb +70 -56
- data/lib/admino/table/row.rb +4 -13
- data/lib/admino/version.rb +1 -1
- data/spec/admino/query/filter_group_presenter_spec.rb +9 -3
- data/spec/admino/query/filter_group_spec.rb +4 -4
- data/spec/admino/query/sorting_presenter_spec.rb +11 -7
- data/spec/admino/table/row_spec.rb +8 -8
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb6f069c49996e9bf994e63b48c08fc778387606
|
4
|
+
data.tar.gz: 5a189da715fb212272cb14396cc1351ef3b6765b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76abf92afbb96a5d7afcda73150b01aa7f12c6173dbfe1f3ff038f35827727baac685c41b7d6afdd5e7a9f63222671ff335d842840bf2bb7beb40387e49f60a2
|
7
|
+
data.tar.gz: 47cfae8cb1f1703424e58d7cbe0ba62353e7d9494fd6fbc1403101ce1dd3bc234443dff57b79979eba5fffe54c0f657bcd26a096db3492ffa9f5c12cc39b2211
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -47,7 +47,7 @@ class TasksQuery < Admino::Query::Base
|
|
47
47
|
end
|
48
48
|
```
|
49
49
|
|
50
|
-
Each query object gets initialized with a hash of params, and features a `#scope` method that returns the filtered/sorted result set. As you may have guessed, query objects can be great companions to index
|
50
|
+
Each query object gets initialized with a hash of params, and features a `#scope` method that returns the filtered/sorted result set. As you may have guessed, query objects can be great companions to index actions:
|
51
51
|
|
52
52
|
```ruby
|
53
53
|
class TasksController < ApplicationController
|
@@ -86,8 +86,7 @@ class TasksQuery < Admino::Query::Base
|
|
86
86
|
search_field :title_matches
|
87
87
|
end
|
88
88
|
```
|
89
|
-
The `#scope` method will check the presence of the `params[:query][:title_matches]` key. If it finds it, it will augment the query with a
|
90
|
-
named scope called `:title_matches`, expected to be found within the `Task` model, that needs to accept an argument.
|
89
|
+
The `#scope` method will check the presence of the `params[:query][:title_matches]` key. If it finds it, it will augment the query with a named scope called `:title_matches`, expected to be found within the `Task` model. The scope needs to accept an argument.
|
91
90
|
|
92
91
|
```ruby
|
93
92
|
class Task < ActiveRecord::Base
|
@@ -112,7 +111,7 @@ class TasksQuery < Admino::Query::Base
|
|
112
111
|
end
|
113
112
|
```
|
114
113
|
|
115
|
-
Just like a search field, with a declared filter group the `#scope` method will check the presence of a `params[:query][:status]` key. If it finds it (and its value corresponds to one of the declared scopes) it will augment the query the scope itself:
|
114
|
+
Just like a search field, with a declared filter group the `#scope` method will check the presence of a `params[:query][:status]` key. If it finds it (and its value corresponds to one of the declared scopes) it will augment the query with the scope itself:
|
116
115
|
|
117
116
|
```ruby
|
118
117
|
class Task < ActiveRecord::Base
|
@@ -250,32 +249,21 @@ The great thing is that:
|
|
250
249
|
|
251
250
|
The presenter also offers a `#simple_form` method to make it work with [Simple Form](https://github.com/plataformatec/simple_form) out of the box.
|
252
251
|
|
253
|
-
###
|
252
|
+
### Output customization
|
254
253
|
|
255
|
-
|
254
|
+
The `#scope_link` methods are very flexible, allowing you to change almost every aspect of the generated links:
|
256
255
|
|
257
|
-
```
|
258
|
-
|
259
|
-
query:
|
260
|
-
attributes:
|
261
|
-
tasks_query:
|
262
|
-
title_matches: 'Title contains'
|
263
|
-
filter_groups:
|
264
|
-
tasks_query:
|
265
|
-
status:
|
266
|
-
name: 'Filter by status'
|
267
|
-
scopes:
|
268
|
-
completed: 'Completed'
|
269
|
-
pending: 'Pending'
|
270
|
-
sorting_scopes:
|
271
|
-
task_query:
|
272
|
-
by_due_date: 'By due date'
|
273
|
-
by_title: 'By title'
|
274
|
-
```
|
256
|
+
```erb
|
257
|
+
<% status_filter = query.filter_group_by_name(:status) %>
|
275
258
|
|
276
|
-
|
259
|
+
<%= status_filter.scope_link :completed,
|
260
|
+
'Custom title',
|
261
|
+
active_class: 'active',
|
262
|
+
class: 'custom-class'
|
263
|
+
%>
|
264
|
+
```
|
277
265
|
|
278
|
-
|
266
|
+
Please refer to the tests for the details.
|
279
267
|
|
280
268
|
### Overwriting the starting scope
|
281
269
|
|
@@ -290,16 +278,26 @@ end
|
|
290
278
|
|
291
279
|
### Coertions
|
292
280
|
|
293
|
-
|
281
|
+
Suppose the presence of a model scope that requires a non-textual argument (ie. a date):
|
282
|
+
|
283
|
+
```ruby
|
284
|
+
class Task < ActiveRecord::Base
|
285
|
+
scope :due_date_from, ->(date) { where('due_date >= ?', date) }
|
286
|
+
end
|
287
|
+
```
|
288
|
+
|
289
|
+
Admino can perform some automatic coertions to the textual parameter it gets, and pass the coerced value to the scope:
|
294
290
|
|
295
291
|
```ruby
|
296
292
|
class TasksQuery < Admino::Query::Base
|
297
|
-
|
298
|
-
field :due_date_from, coerce: :to_date
|
299
|
-
field :due_date_to, coerce: :to_date
|
293
|
+
search_field :due_date_from, coerce: :to_date
|
300
294
|
end
|
295
|
+
|
296
|
+
query = TaskQuery.new(query: { due_date_from: '2014-03-01' })
|
297
|
+
query.search_field_by_name(:due_date_from).value # => #<Date Sat, 01 Mar 2014>
|
301
298
|
```
|
302
|
-
|
299
|
+
|
300
|
+
If a specific coercion cannot be performed with the provided input, the scope won't be chained. The following coertions are available:
|
303
301
|
|
304
302
|
* `:to_boolean`
|
305
303
|
* `:to_constant`
|
@@ -311,13 +309,11 @@ The following coertions are available:
|
|
311
309
|
* `:to_symbol`
|
312
310
|
* `:to_time`
|
313
311
|
|
314
|
-
If a specific coercion cannot be performed with the provided input, the scope won't be chained.
|
315
|
-
|
316
312
|
Please see the [`Coercible::Coercer::String`](https://github.com/solnic/coercible/blob/master/lib/coercible/coercer/string.rb) class for details.
|
317
313
|
|
318
314
|
### Default sorting
|
319
315
|
|
320
|
-
If you need to setup a default sorting, you can pass some optional arguments to
|
316
|
+
If you need to setup a default sorting, you can pass some optional arguments to the `sorting` declaration:
|
321
317
|
|
322
318
|
```ruby
|
323
319
|
class TasksQuery < Admino::Query::Base
|
@@ -328,6 +324,29 @@ class TasksQuery < Admino::Query::Base
|
|
328
324
|
end
|
329
325
|
```
|
330
326
|
|
327
|
+
### I18n
|
328
|
+
|
329
|
+
To localize the search form labels, as well as the group filter names and scope links, please refer to the following YAML file:
|
330
|
+
|
331
|
+
```yaml
|
332
|
+
en:
|
333
|
+
query:
|
334
|
+
attributes:
|
335
|
+
tasks_query:
|
336
|
+
title_matches: 'Title contains'
|
337
|
+
filter_groups:
|
338
|
+
tasks_query:
|
339
|
+
status:
|
340
|
+
name: 'Filter by status'
|
341
|
+
scopes:
|
342
|
+
completed: 'Completed'
|
343
|
+
pending: 'Pending'
|
344
|
+
sorting_scopes:
|
345
|
+
task_query:
|
346
|
+
by_due_date: 'By due date'
|
347
|
+
by_title: 'By title'
|
348
|
+
```
|
349
|
+
|
331
350
|
## Admino::Table::Presenter
|
332
351
|
|
333
352
|
Admino offers a [Showcase collection presenter](https://github.com/stefanoverna/showcase) that makes it really easy to generate HTML tables from a set of records:
|
@@ -348,14 +367,14 @@ Admino offers a [Showcase collection presenter](https://github.com/stefanoverna/
|
|
348
367
|
<tr>
|
349
368
|
<th role='title'>Title</th>
|
350
369
|
<th role='completed'>Completed</th>
|
351
|
-
<th role='
|
370
|
+
<th role='due-date'>Due date</th>
|
352
371
|
</tr>
|
353
372
|
<thead>
|
354
373
|
<tbody>
|
355
374
|
<tr id='task_1' class='is-even'>
|
356
375
|
<td role='title'>Call mum ASAP</td>
|
357
376
|
<td role='completed'>✓</td>
|
358
|
-
<td role='
|
377
|
+
<td role='due-date'>2013-02-04</td>
|
359
378
|
</tr>
|
360
379
|
<tr id='task_2' class='is-odd'>
|
361
380
|
<!-- ... -->
|
@@ -366,7 +385,7 @@ Admino offers a [Showcase collection presenter](https://github.com/stefanoverna/
|
|
366
385
|
|
367
386
|
### Record actions
|
368
387
|
|
369
|
-
Often
|
388
|
+
Often tables need to offer some kind of action associated with the records. The presenter implements the following DSL to support that:
|
370
389
|
|
371
390
|
```erb
|
372
391
|
<%= Admino::Table::Presenter.new(@tasks, Task, self).to_html do |row, record| %>
|
@@ -402,7 +421,15 @@ Often table rows needs to offer some kind of action associated with the record.
|
|
402
421
|
|
403
422
|
### Sortable columns
|
404
423
|
|
405
|
-
|
424
|
+
If you want to make the table headers sortable, then please create an Admino query object class to define the available sorting scopes.
|
425
|
+
|
426
|
+
```ruby
|
427
|
+
class TaskQuery < Admino::Query::Base
|
428
|
+
sorting :by_title, :by_due_date
|
429
|
+
end
|
430
|
+
```
|
431
|
+
|
432
|
+
You can then pass the query object as a parameter to the table presenter initializer, and associate table columns to specific sorting scopes of the query object using the `sorting` directive:
|
406
433
|
|
407
434
|
```erb
|
408
435
|
<% query = present(@query) %>
|
@@ -420,10 +447,10 @@ This generates links that allow the visitor to sort the result set in ascending
|
|
420
447
|
<thead>
|
421
448
|
<tr>
|
422
449
|
<th role='title'>
|
423
|
-
<a href=
|
450
|
+
<a href='/admin/tasks?sorting=by_title&sort_order=desc' class='is-asc'>Title</a>
|
424
451
|
</th>
|
425
|
-
<th role='
|
426
|
-
<a href=
|
452
|
+
<th role='due-date'>
|
453
|
+
<a href='/admin/tasks?sorting=by_due_date&sort_order=asc'>Due date</a>
|
427
454
|
</th>
|
428
455
|
</tr>
|
429
456
|
<thead>
|
@@ -433,7 +460,7 @@ This generates links that allow the visitor to sort the result set in ascending
|
|
433
460
|
|
434
461
|
### Customizing the output
|
435
462
|
|
436
|
-
The `#column` and `#action` methods are very flexible, allowing
|
463
|
+
The `#column` and `#action` methods are very flexible, allowing you to change almost every aspect of the generated table cells:
|
437
464
|
|
438
465
|
```erb
|
439
466
|
<%= Admino::Table::Presenter.new(@tasks, Task, self).to_html(class: 'table-class') do |row, record| %>
|
@@ -447,7 +474,7 @@ The `#column` and `#action` methods are very flexible, allowing youto change alm
|
|
447
474
|
<% end %>
|
448
475
|
```
|
449
476
|
|
450
|
-
If you need more power, you can also
|
477
|
+
If you need more power, you can also subclass `Admino::Table::Presenter`. For each HTML element, there's a set of methods you can override to customize it's appeareance.
|
451
478
|
Table cells are generated through two collaborator classes: `Admino::Table::HeadRow` and `Admino::Table::ResourceRow`. You can easily replace them with a subclass if you want. To grasp the idea here's an example:
|
452
479
|
|
453
480
|
```ruby
|
@@ -500,17 +527,11 @@ end
|
|
500
527
|
|
501
528
|
Please refer to the tests for all the details.
|
502
529
|
|
503
|
-
### Inherited resources
|
530
|
+
### Inherited resources (and similar)
|
504
531
|
|
505
|
-
If
|
532
|
+
If your controller actions are generated through [Inherited Resources](https://github.com/josevalim/inherited_resources), then you can always get the URL pointing to the show action with the `resource_path` helper method. Similar helpers [are available for the other REST actions too](https://github.com/josevalim/inherited_resources#url-helpers) (new, edit, destroy).
|
506
533
|
|
507
|
-
|
508
|
-
<%= CustomTablePresenter.new(@tasks, Task, self).to_html do |row, record| %>
|
509
|
-
<%# ... %>
|
510
|
-
<%= row.actions :show, :edit, :destroy %>
|
511
|
-
<% end %>
|
512
|
-
```
|
513
|
-
For instance, using [Inherited Resources](https://github.com/josevalim/inherited_resources) to generate controller actions, you can use its [helper methods](https://github.com/josevalim/inherited_resources#url-helpers) to build a custom subclass of `Admino::Table::Presenter`:
|
534
|
+
More in general, if you are able to programmatically generate/obtain the URLs of your row actions, you can subclass `Admino::Table::Presenter` and declare them:
|
514
535
|
|
515
536
|
```ruby
|
516
537
|
class CustomTablePresenter < Admino::Table::Presenter
|
@@ -540,6 +561,15 @@ class CustomTablePresenter < Admino::Table::Presenter
|
|
540
561
|
end
|
541
562
|
```
|
542
563
|
|
564
|
+
This will enable you to generate row actions even faster, simply declaring them as arguments to the `#actions` DSL method:
|
565
|
+
|
566
|
+
```erb
|
567
|
+
<%= CustomTablePresenter.new(@tasks, Task, self).to_html do |row, record| %>
|
568
|
+
<%# ... %>
|
569
|
+
<%= row.actions :show, :edit, :destroy %>
|
570
|
+
<% end %>
|
571
|
+
```
|
572
|
+
|
543
573
|
### I18n
|
544
574
|
|
545
575
|
Column titles are generated using the model [`#human_attribute_name`](http://apidock.com/rails/ActiveRecord/Base/human_attribute_name/class) method, so if you already translated the model attribute names, you're good to go. To translate actions, please refer to the following YAML file:
|
@@ -23,8 +23,8 @@ module Admino
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def active_scope
|
26
|
-
if
|
27
|
-
|
26
|
+
if value && scopes.include?(value.to_sym)
|
27
|
+
value.to_sym
|
28
28
|
else
|
29
29
|
nil
|
30
30
|
end
|
@@ -34,8 +34,8 @@ module Admino
|
|
34
34
|
active_scope == scope
|
35
35
|
end
|
36
36
|
|
37
|
-
def
|
38
|
-
params.fetch(param_name, nil)
|
37
|
+
def value
|
38
|
+
params.fetch(:query, {}).fetch(param_name, nil)
|
39
39
|
end
|
40
40
|
|
41
41
|
def param_name
|
@@ -28,12 +28,16 @@ module Admino
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def scope_params(scope)
|
31
|
-
params = ActiveSupport::HashWithIndifferentAccess.new(
|
31
|
+
params = ActiveSupport::HashWithIndifferentAccess.new(
|
32
|
+
h.request.query_parameters
|
33
|
+
)
|
34
|
+
|
35
|
+
params[:query] ||= {}
|
32
36
|
|
33
37
|
if is_scope_active?(scope)
|
34
|
-
params.delete(param_name)
|
38
|
+
params[:query].delete(param_name)
|
35
39
|
else
|
36
|
-
params.merge!(param_name => scope.to_s)
|
40
|
+
params[:query].merge!(param_name => scope.to_s)
|
37
41
|
end
|
38
42
|
|
39
43
|
params
|
@@ -30,23 +30,18 @@ module Admino
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def column(*args, &block)
|
33
|
-
|
33
|
+
attribute_name, label, html_options = parse_column_args(args)
|
34
34
|
|
35
|
-
|
36
|
-
label = params[:label]
|
37
|
-
options = params[:html_options]
|
35
|
+
label ||= column_label(attribute_name)
|
38
36
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
default_options = column_html_options(attribute_name)
|
44
|
-
html_options = Showcase::Helpers::HtmlOptions.new(default_options)
|
45
|
-
html_options.merge_attrs!(options)
|
46
|
-
html_options = html_options.to_h
|
37
|
+
html_options = complete_column_html_options(
|
38
|
+
attribute_name,
|
39
|
+
html_options
|
40
|
+
)
|
47
41
|
|
48
42
|
sorting_scope = html_options.delete(:sorting)
|
49
43
|
sorting_html_options = html_options.delete(:sorting_html_options) { {} }
|
44
|
+
|
50
45
|
if sorting_scope
|
51
46
|
raise ArgumentError, 'query object is required' unless query
|
52
47
|
label = query.sorting.scope_link(sorting_scope, label, sorting_html_options)
|
@@ -61,6 +56,23 @@ module Admino
|
|
61
56
|
|
62
57
|
private
|
63
58
|
|
59
|
+
def column_label(attribute_name)
|
60
|
+
if attribute_name
|
61
|
+
resource_klass.human_attribute_name(attribute_name.to_s)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def complete_column_html_options(attribute_name, final_html_options)
|
66
|
+
if attribute_name.nil?
|
67
|
+
return final_html_options
|
68
|
+
end
|
69
|
+
|
70
|
+
default_options = column_html_options(attribute_name)
|
71
|
+
html_options = Showcase::Helpers::HtmlOptions.new(default_options)
|
72
|
+
html_options.merge_attrs!(final_html_options)
|
73
|
+
html_options = html_options.to_h
|
74
|
+
end
|
75
|
+
|
64
76
|
def column_html_options(attribute_name)
|
65
77
|
{ role: attribute_name.to_s.gsub(/_/, '-') }
|
66
78
|
end
|
@@ -43,26 +43,42 @@ module Admino
|
|
43
43
|
table_tag(options) do
|
44
44
|
thead_tag do
|
45
45
|
thead_tr_tag do
|
46
|
-
|
47
|
-
h.capture(row, nil, &block) if block_given?
|
48
|
-
row.to_html
|
46
|
+
th_tags(&block)
|
49
47
|
end
|
50
48
|
end <<
|
51
49
|
tbody_tag do
|
52
|
-
|
53
|
-
html_options = base_tbody_tr_html_options(resource, index)
|
54
|
-
tbody_tr_tag(resource, index, html_options) do
|
55
|
-
row = resource_row(resource, view_context)
|
56
|
-
h.capture(row, resource, &block) if block_given?
|
57
|
-
row.to_html
|
58
|
-
end
|
59
|
-
end.join.html_safe
|
50
|
+
tbody_tr_tags(&block)
|
60
51
|
end
|
61
52
|
end
|
62
53
|
end
|
63
54
|
|
64
55
|
private
|
65
56
|
|
57
|
+
def tbody_tr_tags(&block)
|
58
|
+
collection.each_with_index.map do |resource, index|
|
59
|
+
html_options = base_tbody_tr_html_options(resource, index)
|
60
|
+
tbody_tr_tag(resource, index, html_options) do
|
61
|
+
td_tags(resource, &block)
|
62
|
+
end
|
63
|
+
end.join.html_safe
|
64
|
+
end
|
65
|
+
|
66
|
+
def th_tags(&block)
|
67
|
+
row = head_row(collection_klass, query, view_context)
|
68
|
+
if block_given?
|
69
|
+
h.capture(row, nil, &block)
|
70
|
+
end
|
71
|
+
row.to_html
|
72
|
+
end
|
73
|
+
|
74
|
+
def td_tags(resource, &block)
|
75
|
+
row = resource_row(resource, view_context)
|
76
|
+
if block_given?
|
77
|
+
h.capture(row, resource, &block)
|
78
|
+
end
|
79
|
+
row.to_html
|
80
|
+
end
|
81
|
+
|
66
82
|
def collection
|
67
83
|
object
|
68
84
|
end
|
@@ -15,11 +15,12 @@ module Admino
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def column(*args, &block)
|
18
|
-
|
18
|
+
attribute_name, label, html_options = parse_column_args(args)
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
html_options = complete_column_html_options(
|
21
|
+
attribute_name,
|
22
|
+
html_options
|
23
|
+
)
|
23
24
|
|
24
25
|
if block_given?
|
25
26
|
content = h.capture(resource, &block)
|
@@ -29,11 +30,7 @@ module Admino
|
|
29
30
|
raise ArgumentError, 'attribute name or block required'
|
30
31
|
end
|
31
32
|
|
32
|
-
|
33
|
-
html_options = Showcase::Helpers::HtmlOptions.new(default_options)
|
34
|
-
html_options.merge_attrs!(options)
|
35
|
-
|
36
|
-
@columns << h.content_tag(:td, content, html_options.to_h)
|
33
|
+
@columns << h.content_tag(:td, content, html_options)
|
37
34
|
end
|
38
35
|
|
39
36
|
def actions(*actions, &block)
|
@@ -47,76 +44,93 @@ module Admino
|
|
47
44
|
end
|
48
45
|
|
49
46
|
def action(*args, &block)
|
50
|
-
params = parse_action_args(args)
|
51
|
-
|
52
|
-
action_name = params[:action_name]
|
53
|
-
label = params[:label]
|
54
|
-
url = params[:url]
|
55
|
-
options = params[:html_options]
|
56
|
-
|
57
47
|
if block_given?
|
58
48
|
@actions << h.capture(resource, &block)
|
59
|
-
|
60
|
-
|
49
|
+
else
|
50
|
+
action_name, url, label, html_options = parse_action_args(args)
|
61
51
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
52
|
+
label ||= action_label(action_name)
|
53
|
+
url ||= action_url(action_name)
|
54
|
+
html_options = complete_action_html_options(
|
55
|
+
action_name,
|
56
|
+
html_options
|
57
|
+
)
|
58
|
+
|
59
|
+
@actions << h.link_to(label, url, html_options)
|
60
|
+
end
|
61
|
+
end
|
66
62
|
|
67
|
-
|
63
|
+
def to_html
|
64
|
+
buffer = @columns
|
68
65
|
|
69
|
-
|
70
|
-
|
71
|
-
|
66
|
+
if @actions.any?
|
67
|
+
html_options = column_html_options(:actions)
|
68
|
+
buffer << h.content_tag(:td, html_options) do
|
69
|
+
@actions.join(" ").html_safe
|
72
70
|
end
|
73
|
-
|
74
|
-
url = send(action_url_method)
|
75
71
|
end
|
76
72
|
|
77
|
-
|
78
|
-
|
79
|
-
end
|
80
|
-
|
81
|
-
html_options = Showcase::Helpers::HtmlOptions.new(base_options)
|
73
|
+
buffer.html_safe
|
74
|
+
end
|
82
75
|
|
83
|
-
|
76
|
+
private
|
84
77
|
|
85
|
-
|
86
|
-
|
87
|
-
|
78
|
+
def action_url(action_name)
|
79
|
+
if action_name.nil?
|
80
|
+
raise ArgumentError,
|
81
|
+
'no URL provided, action name required'
|
88
82
|
end
|
89
83
|
|
90
|
-
|
84
|
+
action_url_method = "#{action_name}_action_url"
|
91
85
|
|
92
|
-
if
|
93
|
-
|
94
|
-
|
95
|
-
scope: 'table.actions',
|
96
|
-
default: [
|
97
|
-
:"#{action_name}",
|
98
|
-
action_name.to_s.titleize
|
99
|
-
]
|
100
|
-
)
|
86
|
+
if !respond_to?(action_url_method, true)
|
87
|
+
raise ArgumentError,
|
88
|
+
"no URL provided, ##{action_url_method} method required"
|
101
89
|
end
|
102
90
|
|
103
|
-
|
91
|
+
url = send(action_url_method)
|
104
92
|
end
|
105
93
|
|
106
|
-
def
|
107
|
-
|
94
|
+
def complete_action_html_options(action_name, final_html_options)
|
95
|
+
if action_name
|
96
|
+
default_options = column_html_options(action_name)
|
97
|
+
html_options = Showcase::Helpers::HtmlOptions.new(default_options)
|
108
98
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
@actions.join(" ").html_safe
|
99
|
+
action_html_options_method = "#{action_name}_action_html_options"
|
100
|
+
if respond_to?(action_html_options_method, true)
|
101
|
+
html_options.merge_attrs!(send(action_html_options_method))
|
113
102
|
end
|
103
|
+
|
104
|
+
html_options.merge_attrs!(final_html_options)
|
105
|
+
html_options.to_h
|
106
|
+
else
|
107
|
+
final_html_options
|
114
108
|
end
|
109
|
+
end
|
115
110
|
|
116
|
-
|
111
|
+
def complete_column_html_options(attribute_name, final_html_options)
|
112
|
+
if attribute_name
|
113
|
+
default_options = column_html_options(attribute_name)
|
114
|
+
html_options = Showcase::Helpers::HtmlOptions.new(default_options)
|
115
|
+
html_options.merge_attrs!(final_html_options)
|
116
|
+
html_options.to_h
|
117
|
+
else
|
118
|
+
final_html_options
|
119
|
+
end
|
117
120
|
end
|
118
121
|
|
119
|
-
|
122
|
+
def action_label(action_name)
|
123
|
+
return nil unless action_name
|
124
|
+
|
125
|
+
I18n.t(
|
126
|
+
:"#{resource.class.model_name.i18n_key}.#{action_name}",
|
127
|
+
scope: 'table.actions',
|
128
|
+
default: [
|
129
|
+
:"#{action_name}",
|
130
|
+
action_name.to_s.titleize
|
131
|
+
]
|
132
|
+
)
|
133
|
+
end
|
120
134
|
|
121
135
|
def action_html_options(action_name)
|
122
136
|
{ role: action_name.to_s.gsub(/_/, '-') }
|
data/lib/admino/table/row.rb
CHANGED
@@ -10,7 +10,7 @@ module Admino
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def parse_column_args(args)
|
13
|
-
|
13
|
+
html_options = args.extract_options!
|
14
14
|
|
15
15
|
attribute_name = if args.first.is_a?(Symbol)
|
16
16
|
args.shift
|
@@ -24,15 +24,11 @@ module Admino
|
|
24
24
|
nil
|
25
25
|
end
|
26
26
|
|
27
|
-
|
28
|
-
attribute_name: attribute_name,
|
29
|
-
label: label,
|
30
|
-
html_options: options
|
31
|
-
}
|
27
|
+
[attribute_name, label, html_options]
|
32
28
|
end
|
33
29
|
|
34
30
|
def parse_action_args(args)
|
35
|
-
|
31
|
+
html_options = args.extract_options!
|
36
32
|
|
37
33
|
action_name = if args.first.is_a?(Symbol)
|
38
34
|
args.shift
|
@@ -48,12 +44,7 @@ module Admino
|
|
48
44
|
|
49
45
|
label = args.shift
|
50
46
|
|
51
|
-
|
52
|
-
action_name: action_name,
|
53
|
-
url: url,
|
54
|
-
label: label,
|
55
|
-
html_options: options
|
56
|
-
}
|
47
|
+
[action_name, url, label, html_options]
|
57
48
|
end
|
58
49
|
|
59
50
|
def to_html
|
data/lib/admino/version.rb
CHANGED
@@ -16,7 +16,7 @@ module Admino
|
|
16
16
|
let(:request_object) do
|
17
17
|
double(
|
18
18
|
'ActionDispatch::Request',
|
19
|
-
query_parameters: { 'filter_group' => 'bar' },
|
19
|
+
query_parameters: { 'query' => { 'field' => 'value', 'filter_group' => 'bar' } },
|
20
20
|
path: '/'
|
21
21
|
)
|
22
22
|
end
|
@@ -86,6 +86,8 @@ module Admino
|
|
86
86
|
end
|
87
87
|
|
88
88
|
describe '#scope_params' do
|
89
|
+
let(:scope_active) { false }
|
90
|
+
|
89
91
|
before do
|
90
92
|
filter_group.stub(:is_scope_active?).with(:foo).and_return(scope_active)
|
91
93
|
end
|
@@ -94,7 +96,7 @@ module Admino
|
|
94
96
|
let(:scope_active) { true }
|
95
97
|
|
96
98
|
it 'deletes the filter_group param' do
|
97
|
-
expect(presenter.scope_params(:foo)).not_to have_key 'filter_group'
|
99
|
+
expect(presenter.scope_params(:foo)[:query]).not_to have_key 'filter_group'
|
98
100
|
end
|
99
101
|
end
|
100
102
|
|
@@ -102,9 +104,13 @@ module Admino
|
|
102
104
|
let(:scope_active) { false }
|
103
105
|
|
104
106
|
it 'is set as filter group value' do
|
105
|
-
expect(presenter.scope_params(:foo)[:filter_group]).to eq 'foo'
|
107
|
+
expect(presenter.scope_params(:foo)[:query][:filter_group]).to eq 'foo'
|
106
108
|
end
|
107
109
|
end
|
110
|
+
|
111
|
+
it 'preserves the other params' do
|
112
|
+
expect(presenter.scope_params(:foo)[:query][:field]).to eq 'value'
|
113
|
+
end
|
108
114
|
end
|
109
115
|
|
110
116
|
describe '#name' do
|
@@ -17,7 +17,7 @@ module Admino
|
|
17
17
|
end
|
18
18
|
|
19
19
|
context 'with an invalid value' do
|
20
|
-
let(:params) { { 'foo' => 'qux' } }
|
20
|
+
let(:params) { { 'query' => { 'foo' => 'qux' } } }
|
21
21
|
|
22
22
|
it 'returns nil' do
|
23
23
|
expect(filter_group.active_scope).to be_nil
|
@@ -25,7 +25,7 @@ module Admino
|
|
25
25
|
end
|
26
26
|
|
27
27
|
context 'with a valid value' do
|
28
|
-
let(:params) { { 'foo' => 'bar' } }
|
28
|
+
let(:params) { { 'query' => { 'foo' => 'bar' } } }
|
29
29
|
|
30
30
|
it 'returns the scope name' do
|
31
31
|
expect(filter_group.active_scope).to eq :bar
|
@@ -38,7 +38,7 @@ module Admino
|
|
38
38
|
let(:scope) { ScopeMock.new('original') }
|
39
39
|
|
40
40
|
context 'if the search_field has a value' do
|
41
|
-
let(:params) { { 'foo' => 'bar' } }
|
41
|
+
let(:params) { { 'query' => { 'foo' => 'bar' } } }
|
42
42
|
|
43
43
|
it 'returns the original scope chained with the filter_group scope' do
|
44
44
|
expect(result.chain).to eq [:bar, []]
|
@@ -53,7 +53,7 @@ module Admino
|
|
53
53
|
end
|
54
54
|
|
55
55
|
describe '#is_scope_active?' do
|
56
|
-
let(:params) { { 'foo' => 'bar' } }
|
56
|
+
let(:params) { { 'query' => { 'foo' => 'bar' } } }
|
57
57
|
|
58
58
|
it 'returns true if the provided scope is the one currently active' do
|
59
59
|
expect(filter_group.is_scope_active?(:bar)).to be_true
|
@@ -15,7 +15,7 @@ module Admino
|
|
15
15
|
let(:request_object) do
|
16
16
|
double(
|
17
17
|
'ActionDispatch::Request',
|
18
|
-
query_parameters: { 'sorting' => 'by_date' },
|
18
|
+
query_parameters: { 'sorting' => 'by_date', 'other' => 'value' },
|
19
19
|
path: '/'
|
20
20
|
)
|
21
21
|
end
|
@@ -103,8 +103,12 @@ module Admino
|
|
103
103
|
sorting.stub(:is_scope_active?).with(:by_title).and_return(false)
|
104
104
|
end
|
105
105
|
|
106
|
+
it 'preserves other params' do
|
107
|
+
expect(subject[:other]).to eq 'value'
|
108
|
+
end
|
109
|
+
|
106
110
|
it 'sets the sorting param as the scope' do
|
107
|
-
subject[:sorting]
|
111
|
+
expect(subject[:sorting]).to eq 'by_title'
|
108
112
|
end
|
109
113
|
|
110
114
|
context 'scope is active' do
|
@@ -118,7 +122,7 @@ module Admino
|
|
118
122
|
end
|
119
123
|
|
120
124
|
it 'sets the sorting order to descending' do
|
121
|
-
subject[:sort_order]
|
125
|
+
expect(subject[:sort_order]).to eq 'desc'
|
122
126
|
end
|
123
127
|
end
|
124
128
|
|
@@ -128,7 +132,7 @@ module Admino
|
|
128
132
|
end
|
129
133
|
|
130
134
|
it 'sets the sorting order to ascending' do
|
131
|
-
subject[:sort_order]
|
135
|
+
expect(subject[:sort_order]).to eq 'asc'
|
132
136
|
end
|
133
137
|
end
|
134
138
|
end
|
@@ -142,7 +146,7 @@ module Admino
|
|
142
146
|
end
|
143
147
|
|
144
148
|
it 'sets the sorting order to ascending' do
|
145
|
-
subject[:sort_order]
|
149
|
+
expect(subject[:sort_order]).to eq 'asc'
|
146
150
|
end
|
147
151
|
end
|
148
152
|
|
@@ -152,7 +156,7 @@ module Admino
|
|
152
156
|
end
|
153
157
|
|
154
158
|
it 'sets the sorting order to descending' do
|
155
|
-
subject[:sort_order]
|
159
|
+
expect(subject[:sort_order]).to eq 'desc'
|
156
160
|
end
|
157
161
|
end
|
158
162
|
end
|
@@ -163,7 +167,7 @@ module Admino
|
|
163
167
|
end
|
164
168
|
|
165
169
|
it 'sets the sorting order to ascending' do
|
166
|
-
subject[:sort_order]
|
170
|
+
expect(subject[:sort_order]).to eq 'asc'
|
167
171
|
end
|
168
172
|
end
|
169
173
|
end
|
@@ -21,22 +21,22 @@ module Admino
|
|
21
21
|
|
22
22
|
context 'with a symbol param' do
|
23
23
|
let(:arguments) { [:title] }
|
24
|
-
it { should eq
|
24
|
+
it { should eq [:title, nil, {}] }
|
25
25
|
end
|
26
26
|
|
27
27
|
context 'with a string param' do
|
28
28
|
let(:arguments) { ['Title'] }
|
29
|
-
it { should eq
|
29
|
+
it { should eq [nil, 'Title', {}] }
|
30
30
|
end
|
31
31
|
|
32
32
|
context 'with a string and a symbol param' do
|
33
33
|
let(:arguments) { [:title, 'Title'] }
|
34
|
-
it { should eq
|
34
|
+
it { should eq [:title, 'Title', {}] }
|
35
35
|
end
|
36
36
|
|
37
37
|
context 'with options' do
|
38
38
|
let(:arguments) { [{ foo: 'bar' }] }
|
39
|
-
it { should eq
|
39
|
+
it { should eq [nil, nil, { foo: 'bar' }] }
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -47,22 +47,22 @@ module Admino
|
|
47
47
|
|
48
48
|
context 'with a symbol param' do
|
49
49
|
let(:arguments) { [:show] }
|
50
|
-
it { should eq
|
50
|
+
it { should eq [:show, nil, nil, {}] }
|
51
51
|
end
|
52
52
|
|
53
53
|
context 'with a one string param' do
|
54
54
|
let(:arguments) { ['/'] }
|
55
|
-
it { should eq
|
55
|
+
it { should eq [nil, '/', nil, {}] }
|
56
56
|
end
|
57
57
|
|
58
58
|
context 'with a two string params' do
|
59
59
|
let(:arguments) { ['/', 'Details'] }
|
60
|
-
it { should eq
|
60
|
+
it { should eq [nil, '/', 'Details', {}] }
|
61
61
|
end
|
62
62
|
|
63
63
|
context 'with options' do
|
64
64
|
let(:arguments) { [{ foo: 'bar' }] }
|
65
|
-
it { should eq
|
65
|
+
it { should eq [nil, nil, nil, { foo: 'bar' }] }
|
66
66
|
end
|
67
67
|
end
|
68
68
|
end
|