zadok 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/app/controllers/zadok_controller.rb +40 -0
- data/app/views/zadok/filters/_autocomplete.html.slim +8 -0
- data/app/views/zadok/filters/_edit.html.slim +4 -0
- data/app/views/zadok/filters/_form_fields.html.slim +17 -0
- data/app/views/zadok/filters/_hidden.html.slim +1 -0
- data/app/views/zadok/filters/_multiselect.slim +2 -0
- data/app/views/zadok/filters/_numeric_range_field.html.slim +13 -0
- data/app/views/zadok/filters/_options.html.slim +5 -0
- data/app/views/zadok/filters/_range.html.slim +9 -0
- data/app/views/zadok/filters/_select.html.slim +3 -0
- data/app/views/zadok/filters/_textfield.html.slim +2 -0
- data/app/views/zadok/filters/_typeable_multiselect.html.slim +25 -0
- data/app/views/zadok/index.html.slim +1 -1
- data/lib/zadok/filter_collection.rb +44 -0
- data/lib/zadok/filters/ransack/autocomplete_filter.rb +49 -0
- data/lib/zadok/filters/ransack/base.rb +68 -0
- data/lib/zadok/filters/ransack/hidden_filter.rb +17 -0
- data/lib/zadok/filters/ransack/multiselect_filter.rb +24 -0
- data/lib/zadok/filters/ransack/numeric_range_filter.rb +73 -0
- data/lib/zadok/filters/ransack/options_filter.rb +17 -0
- data/lib/zadok/filters/ransack/range_filter.rb +31 -0
- data/lib/zadok/filters/ransack/select_filter.rb +21 -0
- data/lib/zadok/filters/ransack/textfield_filter.rb +17 -0
- data/lib/zadok/filters/ransack/typeable_multiselect_filter.rb +19 -0
- data/lib/zadok/version.rb +1 -1
- metadata +23 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f672da6d9e4bf75eca14ab1b8659bfe92f362c38dfe22ced3fdf9a31c5c204cd
|
4
|
+
data.tar.gz: bf67606b9b15e5dcdf00fa1dd23e00e8b261a239b2f8fa51370f005206de86c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a02b809e8ff1094dc12fc06dc7a2d1eacd3578affb18bddea6da73036c2a3771f6bcfee64ab24ee2547173e0363eacf3345ac99e60fc4f2e9ae732343cdcb86
|
7
|
+
data.tar.gz: 6a1a91ce657643eb57f948bd0efaff1e11b8dcb54282df3f508f5181638fe24c720fb13aff49b0125367834b21cb0fda9a945e0a50c4f55d0722d63ea577af5e
|
data/Gemfile.lock
CHANGED
@@ -59,6 +59,46 @@ class ZadokController < ApplicationController
|
|
59
59
|
|
60
60
|
protected
|
61
61
|
|
62
|
+
def filter_collection
|
63
|
+
Zadok::FilterCollection.new(search_params, filters_namespace)
|
64
|
+
end
|
65
|
+
|
66
|
+
def filters_namespace
|
67
|
+
"filters/#{search_model}".classify.pluralize.constantize
|
68
|
+
end
|
69
|
+
|
70
|
+
def filtered_resources
|
71
|
+
current_search.result
|
72
|
+
end
|
73
|
+
|
74
|
+
def search_params
|
75
|
+
permitted_params.fetch(:q) { {} }
|
76
|
+
end
|
77
|
+
|
78
|
+
def search_model
|
79
|
+
raise "search_model method not implemented"
|
80
|
+
end
|
81
|
+
|
82
|
+
def current_search
|
83
|
+
search_model.ransack(search_params)
|
84
|
+
end
|
85
|
+
|
86
|
+
def search_results
|
87
|
+
current_search.result
|
88
|
+
end
|
89
|
+
|
90
|
+
def page
|
91
|
+
permitted_params.fetch(:page) { nil }
|
92
|
+
end
|
93
|
+
|
94
|
+
def per_page
|
95
|
+
permitted_params.fetch(:per_page) { 30 }
|
96
|
+
end
|
97
|
+
|
98
|
+
def current_sort
|
99
|
+
search_params.fetch(:s) { nil }
|
100
|
+
end
|
101
|
+
|
62
102
|
def permitted_params
|
63
103
|
params.permit(:page, :per_page, q: %i[s search_model])
|
64
104
|
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
.autocomplete.ui-front
|
2
|
+
= f.hidden_field filter.param, value: filter.describe(search_params)
|
3
|
+
= text_field_tag(filter.field_id, filter.field_value(search_params), { role: "autocomplete",
|
4
|
+
class: "form-control",
|
5
|
+
id: filter.field_id,
|
6
|
+
data: { source: filter.source,
|
7
|
+
parent: "#filter-form",
|
8
|
+
target_id: filter.target_field_id }})
|
@@ -0,0 +1,17 @@
|
|
1
|
+
= form.hidden_field :s, value: current_sort
|
2
|
+
= form.hidden_field :search_model, value: search_model
|
3
|
+
|
4
|
+
.row
|
5
|
+
- filter_collection.filters.each do |filter|
|
6
|
+
.col-lg-3.col-md-3.col-sm-4.col-xs-12[class=filter.type]
|
7
|
+
= form.label filter.param, filter.i18n_name
|
8
|
+
= render "zadok/filters/#{filter.type}", f: form, filter: filter
|
9
|
+
|
10
|
+
.row
|
11
|
+
.col-lg-3.col-md-3.col-sm-4.col-xs-12
|
12
|
+
|
|
13
|
+
= form.submit t("application.buttons.apply"), class: "btn btn-block btn-default"
|
14
|
+
.col-lg-6.col-md-6.col-sm-4.visible-sm-block.visible-md-block.visible-lg-block.hidden
|
15
|
+
.results.col-lg-3.col-md-3.col-sm-4.col-xs-12.text-right
|
16
|
+
= "#{t("filter.amount")}: "
|
17
|
+
.total-results.label.label-default
|
@@ -0,0 +1 @@
|
|
1
|
+
= f.hidden_field filter.param, value: filter.describe(search_params)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
.textfield.numeric_range_field
|
2
|
+
= text_field_tag filter.name, filter.value(params),
|
3
|
+
placeholder: I18n.t("filter_labels.numeric_range.placeholder"),
|
4
|
+
pattern: ' *- *\d+|\d+( *- *(\d+)?)?',
|
5
|
+
"data-role" => "numeric_range",
|
6
|
+
"data-left" => filter.params[0],
|
7
|
+
"data-right" => filter.params[1],
|
8
|
+
"data-content" => filter.popover_content,
|
9
|
+
"data-trigger" => "focus",
|
10
|
+
"data-html" => "true",
|
11
|
+
class: "form-control"
|
12
|
+
= f.hidden_field filter.params[0]
|
13
|
+
= f.hidden_field filter.params[1]
|
@@ -0,0 +1,9 @@
|
|
1
|
+
.range
|
2
|
+
= f.text_field filter.param, value: filter.describe(search_params),
|
3
|
+
data: { provide: :slider,
|
4
|
+
"slider-step": 5,
|
5
|
+
"slider-value": filter.describe(search_params),
|
6
|
+
"slider-ticks": filter.ticks,
|
7
|
+
"slider-ticks_labels": filter.ticks_labels,
|
8
|
+
"slider-ticks_positions": filter.ticks_positions,
|
9
|
+
"slider-tooltip": "hide" }
|
@@ -0,0 +1,25 @@
|
|
1
|
+
.textfield.input-group
|
2
|
+
= f.hidden_field filter.param, id: "#{filter.param}_id",
|
3
|
+
name: "",
|
4
|
+
value: ""
|
5
|
+
= f.text_field filter.param, class: "autocomplete form-control",
|
6
|
+
id: "#{filter.param}_name",
|
7
|
+
name: "",
|
8
|
+
value: "",
|
9
|
+
autocomplete:"off",
|
10
|
+
data: { id: "#{filter.data_id}",
|
11
|
+
path: filter.data_path,
|
12
|
+
type: filter.data_type }
|
13
|
+
.input-group-addon.add-entry id="#{filter.param}_button"
|
14
|
+
.fa.fa-plus
|
15
|
+
|
16
|
+
ul.active-filters id="#{filter.param}_list"
|
17
|
+
- if params[filter.param]
|
18
|
+
- params[filter.param].each do |value|
|
19
|
+
li
|
20
|
+
= filter.options[value]
|
21
|
+
= f.hidden_field filter.param, id: "#{filter.param}_#{value}",
|
22
|
+
value: value,
|
23
|
+
name: "q[#{filter.param}][]"
|
24
|
+
a.remove-entry[href="#"]
|
25
|
+
.fa.fa-times.pull-right
|
@@ -6,7 +6,7 @@
|
|
6
6
|
- if can?(:create, resource_name.classify.constantize)
|
7
7
|
= link_to t("#{resource_name.pluralize}.new"), resource_url_for(:new), class: "btn btn-primary text-white float-right"
|
8
8
|
|
9
|
-
= render "filters/edit"
|
9
|
+
= render "zadok/filters/edit"
|
10
10
|
|
11
11
|
table.table.table-light.table-bordered.table-striped.table-hover.table-sm
|
12
12
|
thead
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/inflector"
|
4
|
+
|
5
|
+
Dir[Rails.root + "app/filters/**/*.rb"].each do |file|
|
6
|
+
require_dependency file
|
7
|
+
end
|
8
|
+
|
9
|
+
module Zadok
|
10
|
+
class FilterCollection
|
11
|
+
attr_reader :filters, :params
|
12
|
+
|
13
|
+
def initialize(params, filters_namespace = Zadok::Filters)
|
14
|
+
@params = params
|
15
|
+
@filters = []
|
16
|
+
filters_namespace.constants.each do |constant|
|
17
|
+
unless constant.match?(/Ransack/)
|
18
|
+
@filters << "#{filters_namespace}::#{constant}".constantize.new
|
19
|
+
end
|
20
|
+
end
|
21
|
+
@filters.sort! { |a, b| a.index <=> b.index }
|
22
|
+
end
|
23
|
+
|
24
|
+
def current_filters
|
25
|
+
@filters.select do |filter|
|
26
|
+
filter.active_in? params
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def current_filter_params(params)
|
31
|
+
current_filters.flat_map(&:params).uniq.map do |param|
|
32
|
+
[param, params[param]]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def active_filters?
|
37
|
+
current_filters.count.positive?
|
38
|
+
end
|
39
|
+
|
40
|
+
def variable_results?
|
41
|
+
current_filters.any?(&:variable_results?)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Zadok
|
4
|
+
module Filters
|
5
|
+
module Ransack
|
6
|
+
class AutocompleteFilter < Base
|
7
|
+
def describe(current_params)
|
8
|
+
current_params[param]
|
9
|
+
end
|
10
|
+
|
11
|
+
def model
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
def attr
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
def autocomplete_attribute
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
|
23
|
+
def source
|
24
|
+
model.to_s.downcase.pluralize
|
25
|
+
end
|
26
|
+
|
27
|
+
def options
|
28
|
+
Hash[model.uniq.pluck(attr, autocomplete_attribute)]
|
29
|
+
end
|
30
|
+
|
31
|
+
def type
|
32
|
+
:autocomplete
|
33
|
+
end
|
34
|
+
|
35
|
+
def field_id
|
36
|
+
"#{source.singularize}_#{autocomplete_attribute}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def target_field_id
|
40
|
+
"q_#{param}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def field_value(params)
|
44
|
+
model.find_by(attr => describe(params))&.send(autocomplete_attribute)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Zadok
|
4
|
+
module Filters
|
5
|
+
module Ransack
|
6
|
+
class Base
|
7
|
+
def initialize(opts = {})
|
8
|
+
@params = opts[:params]
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :params
|
12
|
+
|
13
|
+
# most filters just use a single param
|
14
|
+
def param
|
15
|
+
params[0]
|
16
|
+
end
|
17
|
+
|
18
|
+
def active_in?(current_params)
|
19
|
+
params.any? { |param| current_params.include? param }
|
20
|
+
end
|
21
|
+
|
22
|
+
def index
|
23
|
+
99
|
24
|
+
end
|
25
|
+
|
26
|
+
def i18n_name
|
27
|
+
I18n.t("filter.#{self.class.name.split('::').last.underscore}")
|
28
|
+
end
|
29
|
+
|
30
|
+
def title
|
31
|
+
i18n_name
|
32
|
+
end
|
33
|
+
|
34
|
+
def describe(_current_params)
|
35
|
+
raise NotImplementedError
|
36
|
+
end
|
37
|
+
|
38
|
+
# form control type
|
39
|
+
def type
|
40
|
+
raise NotImplementedError
|
41
|
+
end
|
42
|
+
|
43
|
+
def text(_current_params)
|
44
|
+
param
|
45
|
+
end
|
46
|
+
|
47
|
+
# options hash for filters with options
|
48
|
+
def options
|
49
|
+
I18n.t("filter_labels.#{param}").with_indifferent_access
|
50
|
+
end
|
51
|
+
|
52
|
+
# Each filter may opt to change the column(s) of the filtered admission
|
53
|
+
# list table - add or remove some.
|
54
|
+
def modify_columns(columns)
|
55
|
+
columns
|
56
|
+
end
|
57
|
+
|
58
|
+
def remove_from_params(current_params)
|
59
|
+
current_params.except(*params)
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_to_params(current_params, value)
|
63
|
+
current_params.merge(param => value)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Zadok
|
4
|
+
module Filters
|
5
|
+
module Ransack
|
6
|
+
class MultiselectFilter < Base
|
7
|
+
def describe(current_params)
|
8
|
+
return [] if current_params[param].blank?
|
9
|
+
options.map do |key, value|
|
10
|
+
value if current_params[param].include?(key)
|
11
|
+
end.compact.join(", ")
|
12
|
+
end
|
13
|
+
|
14
|
+
def type
|
15
|
+
:multiselect
|
16
|
+
end
|
17
|
+
|
18
|
+
def active_in?(current_params)
|
19
|
+
super && (current_params[param] & options.keys).present?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "abbrev"
|
4
|
+
|
5
|
+
module Zadok
|
6
|
+
module Filters
|
7
|
+
module Ransack
|
8
|
+
class NumericRangeFilter < Base
|
9
|
+
def describe(current_params = {})
|
10
|
+
left, right = range_ends current_params
|
11
|
+
key = key_from_range_ends left, right
|
12
|
+
if key
|
13
|
+
I18n.t("filter_labels.numeric_range.#{key}", left: left, right: right)
|
14
|
+
else
|
15
|
+
left
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def range_ends(current_params = {})
|
20
|
+
params.map do |param|
|
21
|
+
x = current_params[param]
|
22
|
+
x == "" ? nil : x
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def key_from_range_ends(left, right)
|
27
|
+
if left && right
|
28
|
+
"closed" if left != right
|
29
|
+
elsif right
|
30
|
+
"left_open"
|
31
|
+
elsif left
|
32
|
+
"right_open"
|
33
|
+
else
|
34
|
+
raise "Both range ends missing; filter shouldn't be active"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def type
|
39
|
+
:numeric_range_field
|
40
|
+
end
|
41
|
+
|
42
|
+
def active_in?(current_params = {})
|
43
|
+
range_ends(current_params).any?
|
44
|
+
end
|
45
|
+
|
46
|
+
def name
|
47
|
+
prefix = common_prefix params.map(&:to_s)
|
48
|
+
prefix = params.join("_") + "_" if prefix.empty?
|
49
|
+
prefix + "range"
|
50
|
+
end
|
51
|
+
|
52
|
+
def common_prefix(strings)
|
53
|
+
strings.abbrev.keys.sort_by(&:length).first[0..-2]
|
54
|
+
end
|
55
|
+
|
56
|
+
def value(current_params)
|
57
|
+
left, right = range_ends current_params
|
58
|
+
if left == right
|
59
|
+
left
|
60
|
+
elsif left || right
|
61
|
+
"#{left} - #{right}"
|
62
|
+
else
|
63
|
+
""
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def popover_content
|
68
|
+
I18n.t("filter_labels.numeric_range.popover_text")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Zadok
|
4
|
+
module Filters
|
5
|
+
module Ransack
|
6
|
+
class RangeFilter < Base
|
7
|
+
def describe(current_params)
|
8
|
+
current_params[param]
|
9
|
+
end
|
10
|
+
|
11
|
+
def type
|
12
|
+
:range
|
13
|
+
end
|
14
|
+
|
15
|
+
def ticks
|
16
|
+
options.map { |k, _v| k.to_s.to_i }
|
17
|
+
end
|
18
|
+
|
19
|
+
def ticks_labels
|
20
|
+
options.map { |_k, v| v }
|
21
|
+
end
|
22
|
+
|
23
|
+
def ticks_positions
|
24
|
+
ticks.map.with_index do |_tick, index|
|
25
|
+
(100 / (ticks.count.to_f - 1)) * index
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Zadok
|
4
|
+
module Filters
|
5
|
+
module Ransack
|
6
|
+
class SelectFilter < Base
|
7
|
+
def describe(current_params)
|
8
|
+
current_params[param]
|
9
|
+
end
|
10
|
+
|
11
|
+
def type
|
12
|
+
:select
|
13
|
+
end
|
14
|
+
|
15
|
+
def html_options
|
16
|
+
{ class: "form-control" }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Zadok
|
4
|
+
module Filters
|
5
|
+
module Ransack
|
6
|
+
class TypeableMultiselect < Base
|
7
|
+
def describe(current_params)
|
8
|
+
options.map do |key, value|
|
9
|
+
value if current_params[param].include?(key)
|
10
|
+
end.compact.join("|")
|
11
|
+
end
|
12
|
+
|
13
|
+
def type
|
14
|
+
:typeable_multiselect
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/zadok/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zadok
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leon Hooijer
|
@@ -197,6 +197,17 @@ files:
|
|
197
197
|
- app/controllers/zadok_controller.rb
|
198
198
|
- app/helpers/zadok_helper.rb
|
199
199
|
- app/views/zadok/edit.html.slim
|
200
|
+
- app/views/zadok/filters/_autocomplete.html.slim
|
201
|
+
- app/views/zadok/filters/_edit.html.slim
|
202
|
+
- app/views/zadok/filters/_form_fields.html.slim
|
203
|
+
- app/views/zadok/filters/_hidden.html.slim
|
204
|
+
- app/views/zadok/filters/_multiselect.slim
|
205
|
+
- app/views/zadok/filters/_numeric_range_field.html.slim
|
206
|
+
- app/views/zadok/filters/_options.html.slim
|
207
|
+
- app/views/zadok/filters/_range.html.slim
|
208
|
+
- app/views/zadok/filters/_select.html.slim
|
209
|
+
- app/views/zadok/filters/_textfield.html.slim
|
210
|
+
- app/views/zadok/filters/_typeable_multiselect.html.slim
|
200
211
|
- app/views/zadok/form/fields/_email_field.html.slim
|
201
212
|
- app/views/zadok/form/fields/_select.html.slim
|
202
213
|
- app/views/zadok/form/fields/_text_field.html.slim
|
@@ -204,6 +215,17 @@ files:
|
|
204
215
|
- app/views/zadok/new.html.slim
|
205
216
|
- lib/zadok.rb
|
206
217
|
- lib/zadok/engine.rb
|
218
|
+
- lib/zadok/filter_collection.rb
|
219
|
+
- lib/zadok/filters/ransack/autocomplete_filter.rb
|
220
|
+
- lib/zadok/filters/ransack/base.rb
|
221
|
+
- lib/zadok/filters/ransack/hidden_filter.rb
|
222
|
+
- lib/zadok/filters/ransack/multiselect_filter.rb
|
223
|
+
- lib/zadok/filters/ransack/numeric_range_filter.rb
|
224
|
+
- lib/zadok/filters/ransack/options_filter.rb
|
225
|
+
- lib/zadok/filters/ransack/range_filter.rb
|
226
|
+
- lib/zadok/filters/ransack/select_filter.rb
|
227
|
+
- lib/zadok/filters/ransack/textfield_filter.rb
|
228
|
+
- lib/zadok/filters/ransack/typeable_multiselect_filter.rb
|
207
229
|
- lib/zadok/link_renderer.rb
|
208
230
|
- lib/zadok/version.rb
|
209
231
|
- zadok.gemspec
|