administrate_filterable 0.0.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 +7 -0
- data/.github/workflows/main.yml +20 -0
- data/.gitignore +20 -0
- data/.rspec +3 -0
- data/CHANGELOG +5 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +238 -0
- data/LICENSE +21 -0
- data/README.md +120 -0
- data/Rakefile +6 -0
- data/administrate_filterable.gemspec +40 -0
- data/app/assets/javascripts/administrate_filterable/application.js +107 -0
- data/app/assets/stylesheets/administrate_filterable/application.css +92 -0
- data/app/views/admin/application/_index_filter.html.erb +32 -0
- data/app/views/admin/application/_index_header.html.erb +19 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/administrate_filterable/filterer.rb +39 -0
- data/lib/administrate_filterable/filterer_service.rb +30 -0
- data/lib/administrate_filterable/version.rb +3 -0
- data/lib/administrate_filterable.rb +11 -0
- metadata +176 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 655e44dca6e45d18592d84ccc20dbc79f47da6f79e5c7995c32cc2553f8d1a29
|
4
|
+
data.tar.gz: 05d8c8e708c9d6a08a1a917938f5c26b67e49872374b08206e4167de82b17721
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d4c07a5076e76713970cdacad3fa7b90a56cefe00a4aa4fa385f20389642c39e284ea72a9528d6f9111b422f45ad197517269d5c4c6ceb6f574c811914ea9a6b
|
7
|
+
data.tar.gz: 6f2a3adc9344bb6014f9a61b1048f012a87d60418d363df6e9f40a9caa2df2d67fa95f574d6d4af641ecc271fcd762942b18a37075ef8b9c59fccca29e94afe5
|
@@ -0,0 +1,20 @@
|
|
1
|
+
---
|
2
|
+
name: CI
|
3
|
+
on: [push,pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
test:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
|
9
|
+
steps:
|
10
|
+
- run: ls /opt/hostedtoolcache/Ruby
|
11
|
+
- uses: actions/checkout@v2
|
12
|
+
- name: Set up Ruby
|
13
|
+
uses: ruby/setup-ruby@master
|
14
|
+
with:
|
15
|
+
ruby-version: 3.2.2
|
16
|
+
|
17
|
+
- name: Install dependencies
|
18
|
+
run: bundle install
|
19
|
+
- name: Run tests
|
20
|
+
run: bundle exec rspec
|
data/.gitignore
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
/.bundle/
|
2
|
+
/.yardoc
|
3
|
+
/_yardoc/
|
4
|
+
/coverage/
|
5
|
+
/doc/
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/tmp/
|
9
|
+
|
10
|
+
# rspec failure tracking
|
11
|
+
.rspec_status
|
12
|
+
|
13
|
+
|
14
|
+
# Ignore the default SQLite database.
|
15
|
+
spec/dummy/db/*.sqlite3
|
16
|
+
spec/dummy/db/*.sqlite3-journal
|
17
|
+
|
18
|
+
# Ignore all logfiles and tempfiles.
|
19
|
+
spec/dummy/log/*
|
20
|
+
spec/dummy/tmp/*
|
data/.rspec
ADDED
data/CHANGELOG
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,238 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
administrate_filterable (0.0.2)
|
5
|
+
actionview (>= 5.2.2.1)
|
6
|
+
administrate (>= 0.17.0)
|
7
|
+
rails (>= 4.2)
|
8
|
+
railties (>= 5.2.2.1)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
actioncable (7.0.4.3)
|
14
|
+
actionpack (= 7.0.4.3)
|
15
|
+
activesupport (= 7.0.4.3)
|
16
|
+
nio4r (~> 2.0)
|
17
|
+
websocket-driver (>= 0.6.1)
|
18
|
+
actionmailbox (7.0.4.3)
|
19
|
+
actionpack (= 7.0.4.3)
|
20
|
+
activejob (= 7.0.4.3)
|
21
|
+
activerecord (= 7.0.4.3)
|
22
|
+
activestorage (= 7.0.4.3)
|
23
|
+
activesupport (= 7.0.4.3)
|
24
|
+
mail (>= 2.7.1)
|
25
|
+
net-imap
|
26
|
+
net-pop
|
27
|
+
net-smtp
|
28
|
+
actionmailer (7.0.4.3)
|
29
|
+
actionpack (= 7.0.4.3)
|
30
|
+
actionview (= 7.0.4.3)
|
31
|
+
activejob (= 7.0.4.3)
|
32
|
+
activesupport (= 7.0.4.3)
|
33
|
+
mail (~> 2.5, >= 2.5.4)
|
34
|
+
net-imap
|
35
|
+
net-pop
|
36
|
+
net-smtp
|
37
|
+
rails-dom-testing (~> 2.0)
|
38
|
+
actionpack (7.0.4.3)
|
39
|
+
actionview (= 7.0.4.3)
|
40
|
+
activesupport (= 7.0.4.3)
|
41
|
+
rack (~> 2.0, >= 2.2.0)
|
42
|
+
rack-test (>= 0.6.3)
|
43
|
+
rails-dom-testing (~> 2.0)
|
44
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
45
|
+
actiontext (7.0.4.3)
|
46
|
+
actionpack (= 7.0.4.3)
|
47
|
+
activerecord (= 7.0.4.3)
|
48
|
+
activestorage (= 7.0.4.3)
|
49
|
+
activesupport (= 7.0.4.3)
|
50
|
+
globalid (>= 0.6.0)
|
51
|
+
nokogiri (>= 1.8.5)
|
52
|
+
actionview (7.0.4.3)
|
53
|
+
activesupport (= 7.0.4.3)
|
54
|
+
builder (~> 3.1)
|
55
|
+
erubi (~> 1.4)
|
56
|
+
rails-dom-testing (~> 2.0)
|
57
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
58
|
+
activejob (7.0.4.3)
|
59
|
+
activesupport (= 7.0.4.3)
|
60
|
+
globalid (>= 0.3.6)
|
61
|
+
activemodel (7.0.4.3)
|
62
|
+
activesupport (= 7.0.4.3)
|
63
|
+
activerecord (7.0.4.3)
|
64
|
+
activemodel (= 7.0.4.3)
|
65
|
+
activesupport (= 7.0.4.3)
|
66
|
+
activestorage (7.0.4.3)
|
67
|
+
actionpack (= 7.0.4.3)
|
68
|
+
activejob (= 7.0.4.3)
|
69
|
+
activerecord (= 7.0.4.3)
|
70
|
+
activesupport (= 7.0.4.3)
|
71
|
+
marcel (~> 1.0)
|
72
|
+
mini_mime (>= 1.1.0)
|
73
|
+
activesupport (7.0.4.3)
|
74
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
75
|
+
i18n (>= 1.6, < 2)
|
76
|
+
minitest (>= 5.1)
|
77
|
+
tzinfo (~> 2.0)
|
78
|
+
administrate (0.17.0)
|
79
|
+
actionpack (>= 5.0)
|
80
|
+
actionview (>= 5.0)
|
81
|
+
activerecord (>= 5.0)
|
82
|
+
datetime_picker_rails (~> 0.0.7)
|
83
|
+
jquery-rails (>= 4.0)
|
84
|
+
kaminari (>= 1.0)
|
85
|
+
momentjs-rails (~> 2.8)
|
86
|
+
sassc-rails (~> 2.1)
|
87
|
+
selectize-rails (~> 0.6)
|
88
|
+
builder (3.2.4)
|
89
|
+
byebug (11.1.3)
|
90
|
+
concurrent-ruby (1.1.10)
|
91
|
+
crass (1.0.6)
|
92
|
+
date (3.3.4)
|
93
|
+
datetime_picker_rails (0.0.7)
|
94
|
+
momentjs-rails (>= 2.8.1)
|
95
|
+
diff-lcs (1.5.0)
|
96
|
+
erubi (1.10.0)
|
97
|
+
ffi (1.15.5)
|
98
|
+
globalid (1.2.1)
|
99
|
+
activesupport (>= 6.1)
|
100
|
+
i18n (1.10.0)
|
101
|
+
concurrent-ruby (~> 1.0)
|
102
|
+
jquery-rails (4.4.0)
|
103
|
+
rails-dom-testing (>= 1, < 3)
|
104
|
+
railties (>= 4.2.0)
|
105
|
+
thor (>= 0.14, < 2.0)
|
106
|
+
kaminari (1.2.2)
|
107
|
+
activesupport (>= 4.1.0)
|
108
|
+
kaminari-actionview (= 1.2.2)
|
109
|
+
kaminari-activerecord (= 1.2.2)
|
110
|
+
kaminari-core (= 1.2.2)
|
111
|
+
kaminari-actionview (1.2.2)
|
112
|
+
actionview
|
113
|
+
kaminari-core (= 1.2.2)
|
114
|
+
kaminari-activerecord (1.2.2)
|
115
|
+
activerecord
|
116
|
+
kaminari-core (= 1.2.2)
|
117
|
+
kaminari-core (1.2.2)
|
118
|
+
loofah (2.18.0)
|
119
|
+
crass (~> 1.0.2)
|
120
|
+
nokogiri (>= 1.5.9)
|
121
|
+
mail (2.8.1)
|
122
|
+
mini_mime (>= 0.1.1)
|
123
|
+
net-imap
|
124
|
+
net-pop
|
125
|
+
net-smtp
|
126
|
+
marcel (1.0.2)
|
127
|
+
method_source (1.0.0)
|
128
|
+
mini_mime (1.1.5)
|
129
|
+
mini_portile2 (2.8.0)
|
130
|
+
minitest (5.15.0)
|
131
|
+
momentjs-rails (2.29.1.1)
|
132
|
+
railties (>= 3.1)
|
133
|
+
net-imap (0.4.4)
|
134
|
+
date
|
135
|
+
net-protocol
|
136
|
+
net-pop (0.1.2)
|
137
|
+
net-protocol
|
138
|
+
net-protocol (0.2.2)
|
139
|
+
timeout
|
140
|
+
net-smtp (0.4.0)
|
141
|
+
net-protocol
|
142
|
+
nio4r (2.5.9)
|
143
|
+
nokogiri (1.13.6)
|
144
|
+
mini_portile2 (~> 2.8.0)
|
145
|
+
racc (~> 1.4)
|
146
|
+
racc (1.6.0)
|
147
|
+
rack (2.2.3)
|
148
|
+
rack-test (1.1.0)
|
149
|
+
rack (>= 1.0, < 3)
|
150
|
+
rails (7.0.4.3)
|
151
|
+
actioncable (= 7.0.4.3)
|
152
|
+
actionmailbox (= 7.0.4.3)
|
153
|
+
actionmailer (= 7.0.4.3)
|
154
|
+
actionpack (= 7.0.4.3)
|
155
|
+
actiontext (= 7.0.4.3)
|
156
|
+
actionview (= 7.0.4.3)
|
157
|
+
activejob (= 7.0.4.3)
|
158
|
+
activemodel (= 7.0.4.3)
|
159
|
+
activerecord (= 7.0.4.3)
|
160
|
+
activestorage (= 7.0.4.3)
|
161
|
+
activesupport (= 7.0.4.3)
|
162
|
+
bundler (>= 1.15.0)
|
163
|
+
railties (= 7.0.4.3)
|
164
|
+
rails-dom-testing (2.0.3)
|
165
|
+
activesupport (>= 4.2.0)
|
166
|
+
nokogiri (>= 1.6)
|
167
|
+
rails-html-sanitizer (1.4.2)
|
168
|
+
loofah (~> 2.3)
|
169
|
+
railties (7.0.4.3)
|
170
|
+
actionpack (= 7.0.4.3)
|
171
|
+
activesupport (= 7.0.4.3)
|
172
|
+
method_source
|
173
|
+
rake (>= 12.2)
|
174
|
+
thor (~> 1.0)
|
175
|
+
zeitwerk (~> 2.5)
|
176
|
+
rake (13.0.6)
|
177
|
+
rb-readline (0.5.5)
|
178
|
+
rspec-core (3.9.3)
|
179
|
+
rspec-support (~> 3.9.3)
|
180
|
+
rspec-expectations (3.9.4)
|
181
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
182
|
+
rspec-support (~> 3.9.0)
|
183
|
+
rspec-mocks (3.9.1)
|
184
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
185
|
+
rspec-support (~> 3.9.0)
|
186
|
+
rspec-rails (3.9.1)
|
187
|
+
actionpack (>= 3.0)
|
188
|
+
activesupport (>= 3.0)
|
189
|
+
railties (>= 3.0)
|
190
|
+
rspec-core (~> 3.9.0)
|
191
|
+
rspec-expectations (~> 3.9.0)
|
192
|
+
rspec-mocks (~> 3.9.0)
|
193
|
+
rspec-support (~> 3.9.0)
|
194
|
+
rspec-support (3.9.4)
|
195
|
+
sassc (2.4.0)
|
196
|
+
ffi (~> 1.9)
|
197
|
+
sassc-rails (2.1.2)
|
198
|
+
railties (>= 4.0.0)
|
199
|
+
sassc (>= 2.0)
|
200
|
+
sprockets (> 3.0)
|
201
|
+
sprockets-rails
|
202
|
+
tilt
|
203
|
+
selectize-rails (0.12.6)
|
204
|
+
sprockets (4.0.3)
|
205
|
+
concurrent-ruby (~> 1.0)
|
206
|
+
rack (> 1, < 3)
|
207
|
+
sprockets-rails (3.4.2)
|
208
|
+
actionpack (>= 5.2)
|
209
|
+
activesupport (>= 5.2)
|
210
|
+
sprockets (>= 3.0.0)
|
211
|
+
sqlite3 (1.4.2)
|
212
|
+
thor (1.2.1)
|
213
|
+
tilt (2.0.10)
|
214
|
+
timeout (0.4.1)
|
215
|
+
tzinfo (2.0.6)
|
216
|
+
concurrent-ruby (~> 1.0)
|
217
|
+
websocket-driver (0.7.6)
|
218
|
+
websocket-extensions (>= 0.1.0)
|
219
|
+
websocket-extensions (0.1.5)
|
220
|
+
zeitwerk (2.6.12)
|
221
|
+
|
222
|
+
PLATFORMS
|
223
|
+
ruby
|
224
|
+
|
225
|
+
DEPENDENCIES
|
226
|
+
administrate (~> 0.17.0)
|
227
|
+
administrate_filterable!
|
228
|
+
byebug
|
229
|
+
rails (~> 7.0.0)
|
230
|
+
rb-readline
|
231
|
+
rspec-rails (~> 3.8)
|
232
|
+
sqlite3
|
233
|
+
|
234
|
+
RUBY VERSION
|
235
|
+
ruby 3.2.2p53
|
236
|
+
|
237
|
+
BUNDLED WITH
|
238
|
+
2.4.22
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2023 Irvan Fauziansyah
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
# Administrate Custom Filter
|
2
|
+
|
3
|
+

|
4
|
+

|
5
|
+
|
6
|
+
An [Administrate](https://github.com/thoughtbot/administrate/) plugin to add custom filter in your index page. Highly inspired by [ActiveAdmin](https://github.com/activeadmin/activeadmin)'s filter.
|
7
|
+
|
8
|
+
## Why you need this?
|
9
|
+
|
10
|
+
Let's agree that the Administrate's team has done a great job with the default search or filter functionality. It's simple and easy to use. It supports multiple search fields, cross relation search, and it's easy to customize (like enable/disable the search, defining custom search fields, etc).
|
11
|
+
|
12
|
+
But there are some drawbacks that I found:
|
13
|
+
1. Since it uses single search box, the search process behind it is quite heavy. It will search all the attributes of the model, and it will be slower if you have a lot of data.
|
14
|
+
2. Again, because it search all the attributes, it will be hard to search for a specific attribute. For example, if you have `registration_status` and `employment_status`, and you want to search for "active" registration status only, you will get all the "active" records, including the employment status.
|
15
|
+
3. It's not user friendly when it comes to defined search list (e.g. dropdown list). The user will have to type the value manually, and it's not good for the user experience.
|
16
|
+
|
17
|
+
Please share your thoughts if you have any other reasons.
|
18
|
+
|
19
|
+
## Requirements
|
20
|
+
|
21
|
+
- Ruby on Rails version >= 5.0
|
22
|
+
- Administrate version >= 0.2.2
|
23
|
+
|
24
|
+
## Installation
|
25
|
+
|
26
|
+
Add `administrate_filterable` to your Gemfile:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
gem 'administrate_filterable'
|
30
|
+
```
|
31
|
+
|
32
|
+
And then execute:
|
33
|
+
```
|
34
|
+
$ bundle install
|
35
|
+
```
|
36
|
+
|
37
|
+
Or, simply just run:
|
38
|
+
```
|
39
|
+
$ bundle add administrate_filterable
|
40
|
+
```
|
41
|
+
|
42
|
+
## Usage
|
43
|
+
|
44
|
+
For each resource you want to add custom filter, add the following line to the their respective Administrate controller.
|
45
|
+
```ruby
|
46
|
+
include AdministrateFilterable::Filterer
|
47
|
+
```
|
48
|
+
|
49
|
+
Example:
|
50
|
+
```ruby
|
51
|
+
class UsersController < Administrate::ApplicationController
|
52
|
+
include AdministrateFilterable::Filterer
|
53
|
+
|
54
|
+
# ...
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
By default all the attributes from COLLECTION_ATTRIBUTES will be rendered as the filter fields. You can override this by adding FILTER_ATTRIBUTES to your Administrate's dashboard file.
|
59
|
+
|
60
|
+
Example (`app/dashboards/user_dashboard.rb`):
|
61
|
+
```ruby
|
62
|
+
class UserDashboard < Administrate::BaseDashboard
|
63
|
+
# ..
|
64
|
+
FILTER_ATTRIBUTES = [
|
65
|
+
:first_name,
|
66
|
+
:last_name,
|
67
|
+
:email,
|
68
|
+
:created_at
|
69
|
+
].freeze
|
70
|
+
# ..
|
71
|
+
end
|
72
|
+
```
|
73
|
+
|
74
|
+
By default this gem will add a filter button to the partial `views/admin/application/_index_header.html.erb`. But if you have your own Administrate index views or override that partial in your application you can add the button manually by adding the following line:
|
75
|
+
```erb
|
76
|
+
<%= render('index_filter', page: page) %>
|
77
|
+
```
|
78
|
+
|
79
|
+
Example (`app/views/admin/users/_index_header.html.erb`):
|
80
|
+
```erb
|
81
|
+
... other code here ...
|
82
|
+
<header class="main-content__header">
|
83
|
+
... other code here ...
|
84
|
+
|
85
|
+
<%= render('index_filter', page: page) %>
|
86
|
+
</header>
|
87
|
+
```
|
88
|
+
|
89
|
+
If you use assets pipeline, you need to include this gem's assets to your `app/assets/config/manifest.js` file:
|
90
|
+
```javascript
|
91
|
+
// ... other code here ...
|
92
|
+
|
93
|
+
//= link administrate_filterable/application.css
|
94
|
+
//= link administrate_filterable/application.js
|
95
|
+
```
|
96
|
+
|
97
|
+
## To Do
|
98
|
+
There are still a lot of things to do to make this gem better. Here are some of them (sorted highest priority first):
|
99
|
+
- [ ] Add support for relational filter (e.g. filter by `belongs_to` association, etc)
|
100
|
+
- [ ] Add support to customize the dropdown list (e.g. add `prompt` option, add `include_blank` option, etc)
|
101
|
+
- [ ] Exclude checkbox, radio, or select value from the filter params if no action is performed on them
|
102
|
+
- [ ] Figure out a better way to implement the filter functionality (currently I override the `scoped_resource` method)
|
103
|
+
- [ ] Figure out a better way to pass the filter attributes to the form (currently I use instance variable in the overridden `scoped_resource` method)
|
104
|
+
- [ ] Add capability to customize the filter behavior (e.g. search by exact match, search by partial match, etc just like in the ActiveAdmin filter)
|
105
|
+
- [ ] Improve the toggle button user experience (e.g. add open/close animation, add dynamic open/close title, etc)
|
106
|
+
|
107
|
+
## Contributing
|
108
|
+
|
109
|
+
1. Contribution are welcome (codes, suggestions, and bugs)
|
110
|
+
2. Please test your code: `bundle exec rspec`
|
111
|
+
3. Please document your code
|
112
|
+
|
113
|
+
## License
|
114
|
+
|
115
|
+
[MIT License](https://github.com/IrvanFza/administrate_filterable/blob/master/LICENSE)
|
116
|
+
|
117
|
+
## Credits
|
118
|
+
Huge thanks for the following resources that help me a lot in creating this gem:
|
119
|
+
- [administrate_filterable](https://github.com/SourceLabsLLC/administrate_exportable): Basically I just copy the code from this gem and modify it to suit my needs, highly recommended if you need to export your data from Administrate.
|
120
|
+
- [Off-Canvas Menu](https://web.archive.org/web/20210304195120/https://codepen.io/11bits/pen/jryEGW): I found this CodePen from Google Images when I was looking for a way to create an off-canvas menu. I modified it a little bit to suit my needs. But it seems the codepen is no longer available, so I put the archived version here. If any of you know the original author, please let me know so I can give the proper credit.
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "administrate_filterable/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "administrate_filterable"
|
8
|
+
spec.version = AdministrateFilterable::VERSION
|
9
|
+
spec.authors = ["Irvan Fauziansyah"]
|
10
|
+
spec.email = ["ervhan@gmail.com"]
|
11
|
+
spec.homepage = 'https://github.com/IrvanFza/administrate_filterable'
|
12
|
+
spec.summary = "Administrate Custom Filter"
|
13
|
+
spec.description = "Simple plugin to add custom filter functionality to your Administrate index page."
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
# if spec.respond_to?(:metadata)
|
19
|
+
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
20
|
+
# else
|
21
|
+
# raise "RubyGems 2.0 or newer is required to protect against " \
|
22
|
+
# "public gem pushes."
|
23
|
+
# end
|
24
|
+
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
26
|
+
f.match(%r{^(test|spec|features)/})
|
27
|
+
end
|
28
|
+
spec.bindir = "exe"
|
29
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
30
|
+
spec.require_paths = ["lib"]
|
31
|
+
|
32
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
33
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
34
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
35
|
+
spec.add_development_dependency "byebug", "~> 10.0"
|
36
|
+
spec.add_dependency 'administrate','>= 0.17.0'
|
37
|
+
spec.add_dependency 'rails', '>= 4.2'
|
38
|
+
spec.add_dependency 'actionview', '>= 5.2.2.1'
|
39
|
+
spec.add_dependency 'railties', '>= 5.2.2.1'
|
40
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
const navTrigger = document.getElementsByClassName('administrate-filterable__toggle-button')[0];
|
2
|
+
const body = document.getElementsByTagName('body')[0];
|
3
|
+
|
4
|
+
navTrigger.addEventListener('click', toggleNavigation);
|
5
|
+
|
6
|
+
function toggleNavigation(event) {
|
7
|
+
event.preventDefault();
|
8
|
+
body.classList.toggle('administrate-filterable__open');
|
9
|
+
}
|
10
|
+
|
11
|
+
const applyFilterButton = document.getElementsByClassName('administrate-filterable__apply-filter')[0];
|
12
|
+
const form = document.getElementsByClassName('administrate-filterable__form')[0];
|
13
|
+
|
14
|
+
applyFilterButton.addEventListener('click', function(event) {
|
15
|
+
// Prevent form submission
|
16
|
+
event.preventDefault();
|
17
|
+
|
18
|
+
// Instantiate a new FormData object
|
19
|
+
let formData = new FormData(form);
|
20
|
+
|
21
|
+
// Create URLSearchParams from FormData
|
22
|
+
let formDataParams = new URLSearchParams([...formData.entries()]);
|
23
|
+
|
24
|
+
// get existing query params
|
25
|
+
let existingParams = new URLSearchParams(window.location.search);
|
26
|
+
|
27
|
+
// Get keys of existingParams
|
28
|
+
let keys = [...existingParams.keys()];
|
29
|
+
|
30
|
+
// delete keys from existingParams which don't exist in formDataParams
|
31
|
+
keys.forEach((key) => {
|
32
|
+
if (!formDataParams.has(key)) {
|
33
|
+
existingParams.delete(key);
|
34
|
+
}
|
35
|
+
});
|
36
|
+
|
37
|
+
// append or replace new formDataParams
|
38
|
+
formDataParams.forEach((value, key) => {
|
39
|
+
if (value.trim() !== '') {
|
40
|
+
existingParams.set(key, value);
|
41
|
+
} else {
|
42
|
+
existingParams.delete(key);
|
43
|
+
}
|
44
|
+
});
|
45
|
+
|
46
|
+
// Create query params string from existingParams
|
47
|
+
let queryParamsString = '?' + existingParams.toString();
|
48
|
+
|
49
|
+
// Get the URL without query params
|
50
|
+
const currentUrl = window.location.href.split('?')[0];
|
51
|
+
|
52
|
+
// Construct new URL with updated parameters
|
53
|
+
const newUrl = currentUrl + queryParamsString;
|
54
|
+
|
55
|
+
// Redirect to current url with new query params
|
56
|
+
window.location.href = newUrl;
|
57
|
+
});
|
58
|
+
|
59
|
+
window.onload = function() {
|
60
|
+
// Get form fields
|
61
|
+
const form = document.getElementsByClassName('administrate-filterable__form')[0];
|
62
|
+
let formData = new FormData(form);
|
63
|
+
|
64
|
+
// Extract query params from URL
|
65
|
+
const queryParams = new URLSearchParams(window.location.search);
|
66
|
+
|
67
|
+
// Loop through the query parameters and set form field values
|
68
|
+
for (let pair of queryParams.entries()) {
|
69
|
+
const formFields = document.getElementsByName(pair[0]);
|
70
|
+
const fieldValue = decodeURIComponent(pair[1]);
|
71
|
+
for(let field of formFields) {
|
72
|
+
if(field.type === "checkbox" || field.type === "radio") {
|
73
|
+
field.checked = field.value === fieldValue;
|
74
|
+
} else if(field.tagName === 'SELECT') {
|
75
|
+
// Check for Selectize
|
76
|
+
if (field.className.indexOf('selectized') != -1) {
|
77
|
+
// Field uses Selectize
|
78
|
+
field.selectize.setValue(fieldValue, true);
|
79
|
+
} else {
|
80
|
+
// Regular SELECT Field
|
81
|
+
for(let option of field.options) {
|
82
|
+
if(option.value === fieldValue) {
|
83
|
+
option.selected = true;
|
84
|
+
break;
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
} else {
|
89
|
+
field.value = fieldValue;
|
90
|
+
}
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
const clearFilterButton = document.getElementsByClassName('administrate-filterable__clear-filter')[0];
|
96
|
+
// Clear all query params on clear filter click
|
97
|
+
clearFilterButton.addEventListener('click', function(event) {
|
98
|
+
// Prevent form submission
|
99
|
+
event.preventDefault();
|
100
|
+
window.location = removeQueryParams(window.location.href);
|
101
|
+
});
|
102
|
+
|
103
|
+
function removeQueryParams(url) {
|
104
|
+
let parsedUrl = new URL(url);
|
105
|
+
|
106
|
+
return parsedUrl.origin + parsedUrl.pathname;
|
107
|
+
}
|
@@ -0,0 +1,92 @@
|
|
1
|
+
.administrate-filterable__toggle-button {
|
2
|
+
position: fixed;
|
3
|
+
z-index: 4;
|
4
|
+
top: 38px;
|
5
|
+
right: 10px;
|
6
|
+
}
|
7
|
+
|
8
|
+
.administrate-filterable__overlay {
|
9
|
+
position: fixed;
|
10
|
+
z-index: 2;
|
11
|
+
top: 0;
|
12
|
+
left: 0;
|
13
|
+
width: 100%;
|
14
|
+
height: 100%;
|
15
|
+
background: #1C1D21;
|
16
|
+
opacity: 0;
|
17
|
+
visibility: hidden;
|
18
|
+
transition: opacity .5s, visibility .5s;
|
19
|
+
}
|
20
|
+
|
21
|
+
.administrate-filterable__open .administrate-filterable__overlay {
|
22
|
+
opacity: .6;
|
23
|
+
visibility: visible;
|
24
|
+
}
|
25
|
+
|
26
|
+
.administrate-filterable__container {
|
27
|
+
position: fixed;
|
28
|
+
z-index: 3;
|
29
|
+
top: 0;
|
30
|
+
right: 0;
|
31
|
+
height: 100%;
|
32
|
+
width: 90%;
|
33
|
+
max-width: 460px;
|
34
|
+
padding: 2em 3.5em;
|
35
|
+
background: #F3F3F3;
|
36
|
+
overflow: auto;
|
37
|
+
transform: translateZ(0);
|
38
|
+
transform: translateX(100%);
|
39
|
+
transition: transform .5s cubic-bezier(.07,.23,.34,1);
|
40
|
+
}
|
41
|
+
|
42
|
+
.administrate-filterable__open .administrate-filterable__container {
|
43
|
+
transform: translateX(0);
|
44
|
+
}
|
45
|
+
|
46
|
+
.administrate-filterable__container h2 {
|
47
|
+
font-size: 15px;
|
48
|
+
font-weight: bold;
|
49
|
+
text-transform: uppercase;
|
50
|
+
color: #AAAAAA;
|
51
|
+
margin: 1.5em 0;
|
52
|
+
}
|
53
|
+
|
54
|
+
@keyframes slide-in {
|
55
|
+
0% {
|
56
|
+
opacity: 0;
|
57
|
+
transform: translateX(80px);
|
58
|
+
}
|
59
|
+
|
60
|
+
100% {
|
61
|
+
opacity: 1;
|
62
|
+
transform: translateX(0);
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
.administrate-filterable__form .field-unit {
|
67
|
+
display: block;
|
68
|
+
}
|
69
|
+
|
70
|
+
.administrate-filterable__form .field-unit__label {
|
71
|
+
width: 100%;
|
72
|
+
margin-left: 0;
|
73
|
+
text-align: left;
|
74
|
+
margin-bottom: 5px;
|
75
|
+
}
|
76
|
+
|
77
|
+
.administrate-filterable__form .field-unit__field {
|
78
|
+
margin-left: 0;
|
79
|
+
}
|
80
|
+
|
81
|
+
.administrate-filterable__form .form-actions {
|
82
|
+
margin-left: 0;
|
83
|
+
text-align: center;
|
84
|
+
}
|
85
|
+
|
86
|
+
.administrate-filterable__form .administrate-filterable__clear-filter {
|
87
|
+
background: #888888;
|
88
|
+
}
|
89
|
+
|
90
|
+
.administrate-filterable__form .administrate-filterable__clear-filter:hover {
|
91
|
+
background: #666666;
|
92
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<% if @administrate_filterable_attributes.present? %>
|
2
|
+
<% resource_title = display_resource_name(page.resource_name) %>
|
3
|
+
|
4
|
+
<% # TODO: Improve the toggle button user experience (e.g. add open/close animation, add dynamic open/close title, etc) %>
|
5
|
+
<a href="#administrate-filterable" class="administrate-filterable__toggle-button" title="Filter <%= resource_title %>">
|
6
|
+
<svg style="width: 44px; height: 44px;" width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
7
|
+
<path d="M21 6H19M21 12H16M21 18H16M7 20V13.5612C7 13.3532 7 13.2492 6.97958 13.1497C6.96147 13.0615 6.93151 12.9761 6.89052 12.8958C6.84431 12.8054 6.77934 12.7242 6.64939 12.5617L3.35061 8.43826C3.22066 8.27583 3.15569 8.19461 3.10948 8.10417C3.06849 8.02393 3.03853 7.93852 3.02042 7.85026C3 7.75078 3 7.64677 3 7.43875V5.6C3 5.03995 3 4.75992 3.10899 4.54601C3.20487 4.35785 3.35785 4.20487 3.54601 4.10899C3.75992 4 4.03995 4 4.6 4H13.4C13.9601 4 14.2401 4 14.454 4.10899C14.6422 4.20487 14.7951 4.35785 14.891 4.54601C15 4.75992 15 5.03995 15 5.6V7.43875C15 7.64677 15 7.75078 14.9796 7.85026C14.9615 7.93852 14.9315 8.02393 14.8905 8.10417C14.8443 8.19461 14.7793 8.27583 14.6494 8.43826L11.3506 12.5617C11.2207 12.7242 11.1557 12.8054 11.1095 12.8958C11.0685 12.9761 11.0385 13.0615 11.0204 13.1497C11 13.2492 11 13.3532 11 13.5612V17L7 20Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
8
|
+
</svg>
|
9
|
+
</a>
|
10
|
+
|
11
|
+
<div class="administrate-filterable__container" id="administrate-filterable">
|
12
|
+
<header>
|
13
|
+
<h2>Filter <%= resource_title %></h2>
|
14
|
+
</header>
|
15
|
+
|
16
|
+
<%= form_with(model: [:admin, @administrate_filterable_resource], method: :get, html: { class: "form administrate-filterable__form" }) do |f| %>
|
17
|
+
<% @administrate_filterable_attributes.each do |attribute| -%>
|
18
|
+
<% # TODO: Add capability to customize the filter behavior (e.g. search by exact match, search by partial match, etc just like in the ActiveAdmin filter) %>
|
19
|
+
<div class="field-unit field-unit--<%= attribute.html_class %> administrate-filterable__field">
|
20
|
+
<%= render_field attribute, f: f %>
|
21
|
+
</div>
|
22
|
+
<% end -%>
|
23
|
+
|
24
|
+
<div class="form-actions">
|
25
|
+
<%= f.button 'Clear Filter', class: 'administrate-filterable__clear-filter' %>
|
26
|
+
<%= f.submit 'Apply Filter', class: 'administrate-filterable__apply-filter' %>
|
27
|
+
</div>
|
28
|
+
<% end %>
|
29
|
+
</div>
|
30
|
+
|
31
|
+
<div class="administrate-filterable__overlay"></div>
|
32
|
+
<% end %>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<% content_for(:title) do %>
|
2
|
+
<%= display_resource_name(page.resource_name) %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<header class="main-content__header">
|
6
|
+
<h1 class="main-content__page-title" id="page-title">
|
7
|
+
<%= content_for(:title) %>
|
8
|
+
</h1>
|
9
|
+
|
10
|
+
<% if show_search_bar %>
|
11
|
+
<%= render(
|
12
|
+
"search",
|
13
|
+
search_term: search_term,
|
14
|
+
resource_name: display_resource_name(page.resource_name)
|
15
|
+
) %>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
<%= render('index_filter', page: page) %>
|
19
|
+
</header>
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "administrate_filterable"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module AdministrateFilterable
|
2
|
+
module Filterer
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
filterable
|
7
|
+
end
|
8
|
+
|
9
|
+
class_methods do
|
10
|
+
def filterable
|
11
|
+
# TODO: Figure out a better way to implement the filter functionality
|
12
|
+
# This is a hack to implement the filter functionality by overriding the scoped_resource method
|
13
|
+
# It would be better to implement this as a separate controller action, but I don't have time to explore that right now
|
14
|
+
define_method(:scoped_resource) do
|
15
|
+
# TODO: Figure out a better way to pass the filter data to the form
|
16
|
+
# This is a hack to get the filter resource and attributes to show up in the form, but it's not ideal
|
17
|
+
# So I tried to make the variable name as unique as possible to avoid collisions
|
18
|
+
@administrate_filterable_resource = resource_name.to_s.titleize.constantize.new
|
19
|
+
@administrate_filterable_attributes = FiltererService.filter_attributes(dashboard, @administrate_filterable_resource)
|
20
|
+
|
21
|
+
data = resource_class.all
|
22
|
+
|
23
|
+
filter_params = params[resource_name]
|
24
|
+
return data if filter_params.blank?
|
25
|
+
|
26
|
+
filter_params.each do |key, value|
|
27
|
+
next unless data.column_names.include?(key.to_s) && value.present?
|
28
|
+
|
29
|
+
# TODO: Add support for relational filter (e.g. filter by `belongs_to` association, etc)
|
30
|
+
sanitized_query = ActiveRecord::Base.send(:sanitize_sql_array, ["#{key} LIKE ?", "%#{value}%"])
|
31
|
+
data = data.where(sanitized_query)
|
32
|
+
end
|
33
|
+
|
34
|
+
data
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module AdministrateFilterable
|
4
|
+
class FiltererService
|
5
|
+
def self.filter_attributes(dashboard, resource)
|
6
|
+
new(dashboard, resource).filter_attributes
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(dashboard, resource)
|
10
|
+
@dashboard = dashboard
|
11
|
+
@resource = resource
|
12
|
+
end
|
13
|
+
|
14
|
+
def filter_attributes
|
15
|
+
form = Administrate::Page::Form.new(@dashboard, @resource)
|
16
|
+
|
17
|
+
attributes.map do |attribute|
|
18
|
+
form.send :attribute_field, @dashboard, @resource, attribute, :form
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def attributes
|
25
|
+
return @dashboard.class::FILTER_ATTRIBUTES if @dashboard.class.const_defined?("FILTER_ATTRIBUTES")
|
26
|
+
|
27
|
+
@dashboard.class::COLLECTION_ATTRIBUTES
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require "administrate_filterable/version"
|
2
|
+
require "administrate_filterable/filterer_service"
|
3
|
+
require "administrate_filterable/filterer"
|
4
|
+
require "administrate/engine"
|
5
|
+
|
6
|
+
module AdministrateFilterable
|
7
|
+
class Engine < ::Rails::Engine
|
8
|
+
Administrate::Engine.add_javascript "administrate_filterable/application"
|
9
|
+
Administrate::Engine.add_stylesheet "administrate_filterable/application"
|
10
|
+
end
|
11
|
+
end
|
metadata
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: administrate_filterable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Irvan Fauziansyah
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-11-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: byebug
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: administrate
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.17.0
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.17.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rails
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '4.2'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '4.2'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: actionview
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 5.2.2.1
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 5.2.2.1
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: railties
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 5.2.2.1
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 5.2.2.1
|
125
|
+
description: Simple plugin to add custom filter functionality to your Administrate
|
126
|
+
index page.
|
127
|
+
email:
|
128
|
+
- ervhan@gmail.com
|
129
|
+
executables: []
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- ".github/workflows/main.yml"
|
134
|
+
- ".gitignore"
|
135
|
+
- ".rspec"
|
136
|
+
- CHANGELOG
|
137
|
+
- Gemfile
|
138
|
+
- Gemfile.lock
|
139
|
+
- LICENSE
|
140
|
+
- README.md
|
141
|
+
- Rakefile
|
142
|
+
- administrate_filterable.gemspec
|
143
|
+
- app/assets/javascripts/administrate_filterable/application.js
|
144
|
+
- app/assets/stylesheets/administrate_filterable/application.css
|
145
|
+
- app/views/admin/application/_index_filter.html.erb
|
146
|
+
- app/views/admin/application/_index_header.html.erb
|
147
|
+
- bin/console
|
148
|
+
- bin/setup
|
149
|
+
- lib/administrate_filterable.rb
|
150
|
+
- lib/administrate_filterable/filterer.rb
|
151
|
+
- lib/administrate_filterable/filterer_service.rb
|
152
|
+
- lib/administrate_filterable/version.rb
|
153
|
+
homepage: https://github.com/IrvanFza/administrate_filterable
|
154
|
+
licenses:
|
155
|
+
- MIT
|
156
|
+
metadata: {}
|
157
|
+
post_install_message:
|
158
|
+
rdoc_options: []
|
159
|
+
require_paths:
|
160
|
+
- lib
|
161
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">="
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
167
|
+
requirements:
|
168
|
+
- - ">="
|
169
|
+
- !ruby/object:Gem::Version
|
170
|
+
version: '0'
|
171
|
+
requirements: []
|
172
|
+
rubygems_version: 3.4.22
|
173
|
+
signing_key:
|
174
|
+
specification_version: 4
|
175
|
+
summary: Administrate Custom Filter
|
176
|
+
test_files: []
|