zadok 0.1.5 → 0.1.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 802adfb741625bb0a92b833800900763c43650fc69575976ccc5e291b31e27b7
4
- data.tar.gz: c55686ea9b6959c99da063821f32fe7fa0af582c081829f3a450c79859b698be
3
+ metadata.gz: f672da6d9e4bf75eca14ab1b8659bfe92f362c38dfe22ced3fdf9a31c5c204cd
4
+ data.tar.gz: bf67606b9b15e5dcdf00fa1dd23e00e8b261a239b2f8fa51370f005206de86c5
5
5
  SHA512:
6
- metadata.gz: 613351795412bee396b05ad9b53c93fe3635b812b00baa5a78c1b0c30f601fb98e17f87ca42e6a555cf17c59d04c70ca3512799cfa3282a6a747b1e885cbf857
7
- data.tar.gz: 02bbf8b19aedf75f2fda96bea3e3f648d290d514ac84c939ac738d223bd630557539163c4ef6b72a52557316cbfadff8f53c3e37b9a4cf8dabd2c334f9cfc3bd
6
+ metadata.gz: 8a02b809e8ff1094dc12fc06dc7a2d1eacd3578affb18bddea6da73036c2a3771f6bcfee64ab24ee2547173e0363eacf3345ac99e60fc4f2e9ae732343cdcb86
7
+ data.tar.gz: 6a1a91ce657643eb57f948bd0efaff1e11b8dcb54282df3f508f5181638fe24c720fb13aff49b0125367834b21cb0fda9a945e0a50c4f55d0722d63ea577af5e
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- zadok (0.1.4)
4
+ zadok (0.1.5)
5
5
  bootstrap (~> 4.0.0.beta2.1)
6
6
  cancancan (~> 2.0)
7
7
  font-awesome-rails (~> 4.7)
@@ -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,4 @@
1
+ - if filter_collection.active_filters?
2
+ #filter-form
3
+ = search_form_for current_search, url: filters_path, method: :put do |form|
4
+ = render "zadok/filters/form_fields", form: form
@@ -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
+ | &nbsp;
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,2 @@
1
+ = f.select filter.param, options_for_select(filter.options, filter.describe(search_params)),
2
+ { include_blank: true }, { multiple: true, class: "form-control" }
@@ -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,5 @@
1
+ - filter.options.each do |value, label|
2
+ .radio
3
+ label
4
+ = f.radio_button filter.param, value
5
+ = label
@@ -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,3 @@
1
+ = f.select filter.param,
2
+ options_for_select(filter.options, filter.describe(search_params)),
3
+ { include_blank: true }, filter.html_options
@@ -0,0 +1,2 @@
1
+ .textfield
2
+ = f.text_field filter.param, class: "form-control"
@@ -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,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Zadok
4
+ module Filters
5
+ module Ransack
6
+ class HiddenFilter < Base
7
+ def describe(current_params)
8
+ current_params[param]
9
+ end
10
+
11
+ def type
12
+ :hidden
13
+ end
14
+ end
15
+ end
16
+ end
17
+ 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,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Zadok
4
+ module Filters
5
+ module Ransack
6
+ class OptionsFilter < Base
7
+ def current_params
8
+ options[current_params[param]]
9
+ end
10
+
11
+ def type
12
+ :options
13
+ end
14
+ end
15
+ end
16
+ end
17
+ 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,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Zadok
4
+ module Filters
5
+ module Ransack
6
+ class TextfieldFilter < Base
7
+ def describe(current_params)
8
+ current_params[param]
9
+ end
10
+
11
+ def type
12
+ :textfield
13
+ end
14
+ end
15
+ end
16
+ end
17
+ 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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Zadok
4
- VERSION = "0.1.5"
4
+ VERSION = "0.1.6"
5
5
  end
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.5
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