administrate_ransack 0.1.6 → 0.1.14

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a078f88d2e79c5adbdc16067e6e89f596070d78bac034679683f4df009e726e1
4
- data.tar.gz: 404b723fb74cc7bd4bc2906ed1519afbca0e3f826cddc1ca7a8f6dfa31c19533
3
+ metadata.gz: 03cd63f65e6f42ec034fa6452a68effb67323fbe935036a643c4f17f6013adfa
4
+ data.tar.gz: d7bb0e58c6a9a0cd8791a8d4faf130361a9bfc823e6c006ac581213ad874fc3b
5
5
  SHA512:
6
- metadata.gz: 1f61aa1ad07e32e11817999360dd28b99b0172d4c9b42eeff3241412681c0f78c31396cbe2f1c64b7a32692b8cb400269ed30a0e2e793e23492dfc0a7973bba4
7
- data.tar.gz: dcbdcfccf39362122f7c4c745210e56d1023015050c48249c997df3fc0adb1de54ed612cb69bb0c7015ca973c19d3630cd27e290022c32e2316bfe6308518bee
6
+ metadata.gz: 31d0540c3ed2218c72fe49e1f8ce25c9cfcd2b8e45e716fde2343a75ef72af886120b555f27821e6412a33c76bd51cd6238d29f37e037f5a4b2be63114ce581f
7
+ data.tar.gz: 288e6c8a0ec50670583e4a5fc5b9e65bf4238a01538e57308bdfa20d3ab5d626262aca02d90508a924ffa41a775ff4b8c1e1a20630dd5d2973e8c18e6cf8ba47
data/README.md CHANGED
@@ -2,8 +2,8 @@
2
2
  A plugin for [Administrate](https://github.com/thoughtbot/administrate) to use [Ransack](https://github.com/activerecord-hackery/ransack) for filtering resources.
3
3
 
4
4
  Features:
5
- - add Ransack method via module prepend in controller;
6
- - offer a filters bar based on the resource's attributes;
5
+ - add Ransack search results using module prepend inside an Administrate controller;
6
+ - offer a filters side bar based on the resource's attributes;
7
7
  - customize searchable attributes.
8
8
 
9
9
  ## Installation
@@ -14,13 +14,17 @@ prepend AdministrateRansack::Searchable
14
14
  ```
15
15
  - Add to your resource index view:
16
16
  ```erb
17
- <%= render('administrate_ransack/filters', attribute_types: page.attribute_types) %>
17
+ <%= render('administrate_ransack/filters') %>
18
18
  ```
19
+ - See the Usage section for extra options
19
20
 
20
21
  ## Usage
21
- For associations (has many/belongs to) the label used can be customized adding an `admin_label` method to the target model which returns a string while the collection can by filtered with `admin_scope`.
22
+ - The filters partial accepts some optional parameters:
23
+ + `attribute_labels`: hash used to override the field labels, ex. `{ title: "The title" }`
24
+ + `attribute_types`: hash used to specify the filter fields, ex. `{ title: Administrate::Field::String }`
25
+ + `search_path`: the path to use for searching (form URL)
26
+ - For associations (has many/belongs to) the label used can be customized adding an `admin_label` method to the target model which returns a string while the collection can by filtered with `admin_scope`. Example:
22
27
 
23
- Example:
24
28
  ```rb
25
29
  class Post < ApplicationRecord
26
30
  scope :admin_scope, -> { where(published: true) }
@@ -32,17 +36,25 @@ end
32
36
  ```
33
37
 
34
38
  ## Notes
35
- - Administrate Search input works independently from Ransack searches, I suggest to disable it eventually
36
- - Ordering by clicking on the headers of the table preserving the Ransack searches requires a change to the headers links, replacing the th links of *_collection* partial with:
37
- ```rb
38
- sort_link(@ransack_results, attr_name) do
39
- # ...
39
+ - Administrate Search logic works independently from Ransack searches, I suggest to disable it eventually (ex. overriding `show_search_bar?` in the controller)
40
+ - Date/time filters use Rails `datetime_field` method which produces a `datetime-local` input field, at the moment this type of element is not broadly supported, a workaround is to include [flatpickr](https://github.com/flatpickr/flatpickr) datetime library.
41
+ + This gem checks if `flatpickr` function is available in the global scope and applies it to the `datetime-local` filter inputs;
42
+ + you can include the library using your application assets or via CDN, ex. adding to **app/views/layouts/admin/application.html.erb**:
43
+ ```html
44
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr@4.5.7/dist/flatpickr.min.css">
45
+ <script src="https://cdn.jsdelivr.net/npm/flatpickr@4.5.7/dist/flatpickr.min.js"></script>
46
+
47
+ <script>
48
+ // optionally change the flatpikr options:
49
+ window.flatpickr_filters_options = { dateFormat: "Y-m-d" };
50
+ </script>
40
51
  ```
41
52
 
42
53
  ## Customizations
43
- - Allow only some fields for the filters in the index view:
54
+ - Sample with different options provided:
44
55
  ```erb
45
56
  <%
57
+ # In alternative prepare an hash in the dashboard like RANSACK_TYPES = {}
46
58
  attribute_types = {
47
59
  title: Administrate::Field::String,
48
60
  author: Administrate::Field::BelongsTo,
@@ -56,9 +68,14 @@ attribute_labels = {
56
68
  <%= render(
57
69
  'administrate_ransack/filters',
58
70
  attribute_types: attribute_types,
59
- attribute_labels: attribute_labels
71
+ attribute_labels: attribute_labels,
72
+ search_path: admin_root_path
60
73
  ) %>
61
74
  ```
75
+ - An alternative is to prepare some hashes constants in the dashboard (ex. `RANSACK_TYPES`) and then:
76
+ ```erb
77
+ <%= render('administrate_ransack/filters', attribute_types: @dashboard.class::RANSACK_TYPES) %>
78
+ ```
62
79
  - Optional basic style to setup the filters as a sidebar:
63
80
  ```css
64
81
  .main-content__body {
@@ -86,6 +103,25 @@ attribute_labels = {
86
103
  Screenshot:
87
104
  ![screenshot](screenshot.png)
88
105
 
106
+ ## Extra notes
107
+ - If you need to define custom search logics you can skip prepending the module (`AdministrateRansack::Searchable`) and create your own search query in a controller, ex:
108
+ ```ruby
109
+ def scoped_resource
110
+ @ransack_results = super.ransack(params[:q])
111
+ @ransack_results.result(distinct: true)
112
+ end
113
+ ```
114
+ - Sometimes it's easier to create a new ransack field than overriding the search logic, example to search in a `jsonb` field adding to a Post model:
115
+ ```ruby
116
+ ransacker :keywords do
117
+ Arel.sql("posts.metadata ->> 'keywords'")
118
+ end
119
+ ```
120
+ - With this component you can easily link another resource applying some filters, example to add in a tag show page the link to the related posts:
121
+ ```erb
122
+ <%= link_to("Tag's posts", admin_posts_path('q[tags_id_in][]': page.resource.id), class: "button") %>
123
+ ```
124
+
89
125
  ## Do you like it? Star it!
90
126
  If you use this component just star it. A developer is more motivated to improve a project when there is some interest.
91
127
 
@@ -1,5 +1,30 @@
1
- <% attribute_labels ||= {} %>
2
- <%= search_form_for [:admin, @ransack_results], html: { 'data-administrate-ransack-filters': '1' } do |f| %>
1
+ <% content_for :javascript do %>
2
+ <script>
3
+ document.addEventListener('DOMContentLoaded', (_event) => {
4
+ if(typeof window.flatpickr === 'function') {
5
+ var options = window.flatpickr_filters_options;
6
+ if(typeof options !== 'object') options = { enableTime: true };
7
+ window.flatpickr('.filter [type="datetime-local"]', options);
8
+ }
9
+ });
10
+ </script>
11
+ <% end %>
12
+
13
+ <%
14
+ attribute_labels ||= {}
15
+ attribute_types ||= @dashboard.attribute_types.select { |key, _value| @dashboard.collection_attributes.include?(key) }
16
+ form_options = { html: { 'data-administrate-ransack-filters': '1' } }
17
+ if local_assigns.has_key?(:search_path)
18
+ form_path = @ransack_results
19
+ form_options[:url] = search_path
20
+ clear_filters_path = search_path
21
+ else
22
+ form_path = [:admin, @ransack_results]
23
+ clear_filters_path = url_for(url_for([:admin, @ransack_results.klass]))
24
+ end
25
+ %>
26
+
27
+ <%= search_form_for form_path, form_options do |f| %>
3
28
  <div class="filters">
4
29
  <% attribute_types.each do |field, type| %>
5
30
  <% next if field == :id %>
@@ -12,32 +37,32 @@
12
37
  <% if association %>
13
38
  <% label = association.klass.method_defined?(:admin_label) ? :admin_label : :to_s %>
14
39
  <% collection = association.klass.send(association.klass.respond_to?(:admin_scope) ? :admin_scope : :all) %>
15
- <%= f.label (attribute_labels.include?(field) ? attribute_labels[field] : field) %>
40
+ <%= f.label(attribute_labels.include?(field) ? attribute_labels[field] : field) %>
16
41
  <%= f.collection_select "#{field}_id_eq", collection, :id, label, include_blank: true %>
17
42
  <% end %>
18
43
  <% when 'Administrate::Field::Boolean' %>
19
- <%= f.label (attribute_labels.include?(field) ? attribute_labels[field] : field) %>
44
+ <%= f.label(attribute_labels.include?(field) ? attribute_labels[field] : field) %>
20
45
  <%= f.select "#{field}_eq", [[t('administrate_ransack.filters.no'), false], [t('administrate_ransack.filters.yes'), true]], include_blank: true %>
21
46
  <% when 'Administrate::Field::Date' %>
22
- <%= f.label (attribute_labels.include?(field) ? attribute_labels[field] : field) %>
47
+ <%= f.label(attribute_labels.include?(field) ? attribute_labels[field] : field) %>
23
48
  <%= f.date_field "#{field}_gteq" %>
24
49
  <%= f.date_field "#{field}_lteq" %>
25
50
  <% when 'Administrate::Field::DateTime' %>
26
- <%= f.label (attribute_labels.include?(field) ? attribute_labels[field] : field) %>
51
+ <%= f.label(attribute_labels.include?(field) ? attribute_labels[field] : field) %>
27
52
  <%= f.datetime_field "#{field}_gteq" %>
28
53
  <%= f.datetime_field "#{field}_lteq" %>
29
54
  <% when 'Administrate::Field::Email', 'Administrate::Field::String', 'Administrate::Field::Text' %>
30
- <%= f.label (attribute_labels.include?(field) ? attribute_labels[field] : field) %>
55
+ <%= f.label(attribute_labels.include?(field) ? attribute_labels[field] : field) %>
31
56
  <%= f.search_field "#{field}_cont" %>
32
57
  <% when 'Administrate::Field::Number' %>
33
- <%= f.label (attribute_labels.include?(field) ? attribute_labels[field] : field) %>
58
+ <%= f.label(attribute_labels.include?(field) ? attribute_labels[field] : field) %>
34
59
  <%= f.number_field "#{field}_eq" %>
35
60
  <% when 'Administrate::Field::HasMany' %>
36
61
  <% association = @ransack_results.klass.reflections[field.to_s] %>
37
62
  <% if association %>
38
63
  <% label = association.klass.method_defined?(:admin_label) ? :admin_label : :to_s %>
39
64
  <% collection = association.klass.send(association.klass.respond_to?(:admin_scope) ? :admin_scope : :all) %>
40
- <%= f.label (attribute_labels.include?(field) ? attribute_labels[field] : field) %>
65
+ <%= f.label(attribute_labels.include?(field) ? attribute_labels[field] : field) %>
41
66
  <%= f.collection_check_boxes "#{field}_id_in", collection, :id, label do |b| %>
42
67
  <%= b.label do %>
43
68
  <%= b.check_box %>
@@ -46,18 +71,19 @@
46
71
  <% end %>
47
72
  <% end %>
48
73
  <% when 'Administrate::Field::Select' %>
49
- <%= f.label (attribute_labels.include?(field) ? attribute_labels[field] : field) %>
74
+ <%= f.label(attribute_labels.include?(field) ? attribute_labels[field] : field) %>
50
75
  <%= f.select "#{field}_eq", type.options[:collection], include_blank: true %>
76
+ <% else %>
77
+ <!-- unsupported Field::HasOne -->
78
+ <!-- unsupported Field::Polymorphic -->
79
+ <!-- unsupported Field::Password -->
51
80
  <% end %>
52
- <%# unsupported Field::HasOne %>
53
- <%# unsupported Field::Polymorphic %>
54
- <%# unsupported Field::Password %>
55
81
  </div>
56
82
  <% end %>
57
83
  </div>
58
84
 
59
85
  <div class="filters-buttons">
60
- <%= f.submit %>
61
- <%= link_to t('administrate_ransack.filters.clear_filters'), url_for([:admin, @ransack_results.klass]), class: 'btn-clear-filters' %>
86
+ <%= f.submit t('administrate_ransack.filters.search'), name: nil %>
87
+ <%= link_to t('administrate_ransack.filters.clear_filters'), clear_filters_path, class: 'btn-clear-filters' %>
62
88
  </div>
63
89
  <% end %>
@@ -3,4 +3,5 @@ en:
3
3
  filters:
4
4
  'clear_filters': Clear filters
5
5
  'no': 'No'
6
+ 'search': Search
6
7
  'yes': 'Yes'
@@ -8,5 +8,20 @@ module AdministrateRansack
8
8
  @ransack_results = super.ransack(params[:q])
9
9
  @ransack_results.result(distinct: true)
10
10
  end
11
+
12
+ # ref => https://github.com/thoughtbot/administrate/blob/v0.15.0/app/helpers/administrate/application_helper.rb#L54-L60
13
+ def sanitized_order_params(page, current_field_name)
14
+ collection_names = page.item_includes + [current_field_name]
15
+ association_params = collection_names.map do |assoc_name|
16
+ { assoc_name => %i[order direction page per_page] }
17
+ end
18
+ params.permit(:search, :id, :page, :per_page, association_params, q: {})
19
+ end
20
+
21
+ class << self
22
+ def prepended(base)
23
+ base.helper_method :sanitized_order_params
24
+ end
25
+ end
11
26
  end
12
27
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AdministrateRansack
4
- VERSION = '0.1.6'
4
+ VERSION = '0.1.14'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: administrate_ransack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mattia Roccoberton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-24 00:00:00.000000000 Z
11
+ date: 2021-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: administrate
@@ -227,7 +227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
227
227
  - !ruby/object:Gem::Version
228
228
  version: '0'
229
229
  requirements: []
230
- rubygems_version: 3.1.4
230
+ rubygems_version: 3.0.3
231
231
  signing_key:
232
232
  specification_version: 4
233
233
  summary: Administrate Ransack plugin