agilibox 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +11 -0
  3. data/README.md +28 -0
  4. data/Rakefile +37 -0
  5. data/app/assets/config/agilibox_manifest.js +2 -0
  6. data/app/assets/javascripts/agilibox/all.coffee +1 -0
  7. data/app/assets/javascripts/agilibox/filters_date.coffee +15 -0
  8. data/app/assets/javascripts/agilibox/form_anchor_referer.coffee +9 -0
  9. data/app/assets/javascripts/agilibox/form_reset.coffee +5 -0
  10. data/app/assets/javascripts/agilibox/modals.coffee +129 -0
  11. data/app/assets/stylesheets/agilibox/all.sass +5 -0
  12. data/app/assets/stylesheets/agilibox/filters.sass +43 -0
  13. data/app/assets/stylesheets/agilibox/flash.sass +6 -0
  14. data/app/assets/stylesheets/agilibox/modals.sass +45 -0
  15. data/app/assets/stylesheets/agilibox/pagination.sass +6 -0
  16. data/app/assets/stylesheets/agilibox/print.sass +74 -0
  17. data/app/controllers/agilibox/application_controller.rb +5 -0
  18. data/app/controllers/agilibox/small_data/filters_controller.rb +36 -0
  19. data/app/controllers/concerns/agilibox/back_url_concern.rb +18 -0
  20. data/app/filters/agilibox/small_data/filter.rb +68 -0
  21. data/app/filters/agilibox/small_data/filter_strategy.rb +5 -0
  22. data/app/filters/agilibox/small_data/filter_strategy_by_date.rb +6 -0
  23. data/app/filters/agilibox/small_data/filter_strategy_by_date_begin.rb +6 -0
  24. data/app/filters/agilibox/small_data/filter_strategy_by_date_end.rb +6 -0
  25. data/app/filters/agilibox/small_data/filter_strategy_by_key_value.rb +16 -0
  26. data/app/filters/agilibox/small_data/filter_strategy_by_tags.rb +11 -0
  27. data/app/filters/agilibox/small_data/filter_strategy_by_time_period.rb +37 -0
  28. data/app/helpers/agilibox/all_helpers.rb +13 -0
  29. data/app/helpers/agilibox/bootstrap_helper.rb +6 -0
  30. data/app/helpers/agilibox/button_helper.rb +160 -0
  31. data/app/helpers/agilibox/filters_helper.rb +68 -0
  32. data/app/helpers/agilibox/form_helper.rb +49 -0
  33. data/app/helpers/agilibox/link_helper.rb +52 -0
  34. data/app/helpers/agilibox/pagination_helper.rb +6 -0
  35. data/app/helpers/agilibox/routes_helper.rb +20 -0
  36. data/app/helpers/agilibox/sorting_helper.rb +50 -0
  37. data/app/helpers/agilibox/text_helper.rb +122 -0
  38. data/app/libs/agilibox/sortable_uuid_generator.rb +11 -0
  39. data/app/models/concerns/agilibox/active_record_uuid_concern.rb +15 -0
  40. data/app/models/concerns/agilibox/default_values_concern.rb +13 -0
  41. data/app/models/concerns/agilibox/model_i18n.rb +25 -0
  42. data/app/models/concerns/agilibox/model_to_s.rb +9 -0
  43. data/app/models/concerns/agilibox/polymorphic_id.rb +34 -0
  44. data/app/models/concerns/agilibox/search.rb +30 -0
  45. data/app/serializers/agilibox/serializers/base.rb +17 -0
  46. data/app/serializers/agilibox/serializers/xlsx.rb +36 -0
  47. data/app/serializers/agilibox/serializers.rb +2 -0
  48. data/app/views/agilibox/search/_form.html.slim +6 -0
  49. data/config/locales/common.en.yml +199 -0
  50. data/config/locales/common.fr.yml +210 -0
  51. data/config/routes.rb +5 -0
  52. data/lib/agilibox/active_record_comma_type_cast.rb +12 -0
  53. data/lib/agilibox/core_and_rails_ext.rb +2 -0
  54. data/lib/agilibox/engine.rb +9 -0
  55. data/lib/agilibox/form_back_url.rb +18 -0
  56. data/lib/agilibox/version.rb +3 -0
  57. data/lib/agilibox.rb +5 -0
  58. data/lib/tasks/agilibox_tasks.rake +4 -0
  59. metadata +115 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5f40e64e11fd724ef38a9e29fcdceb9679c6c060
4
+ data.tar.gz: f6a811edd6333dae0b8e9823516ff3e118bafca4
5
+ SHA512:
6
+ metadata.gz: a43f05bc2d8d9dfc8158651e2588b889c808feff3539dae6bf54ccea3c2dc02d41fe85493b34fe16144ba39ea3298f4d43739f46902adf9e80ca9f10d4605db4
7
+ data.tar.gz: c31306c47052b96c236dfaf0b26cacd8dcd7da703e694654014177393476ba42a28bde890e3583c8a99fc429696d85a47702f7579118c3ecc92101b024599a12
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # Changelog
2
+
3
+ ## Next version
4
+
5
+ Nothing.
6
+
7
+ ## 1.0.0
8
+
9
+ - First version imported from agilidee/dorsale
10
+ - `sortable_column_order` now returns symbols
11
+ - modal fixes + allow upload
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # Agilibox
2
+ Short description and motivation.
3
+
4
+ ## Usage
5
+ How to use my plugin.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'agilibox'
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install agilibox
22
+ ```
23
+
24
+ ## Contributing
25
+ Contribution directions go here.
26
+
27
+ ## License
28
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Agilibox'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+ load 'rails/tasks/statistics.rake'
22
+
23
+
24
+
25
+ require 'bundler/gem_tasks'
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'lib'
31
+ t.libs << 'test'
32
+ t.pattern = 'test/**/*_test.rb'
33
+ t.verbose = false
34
+ end
35
+
36
+
37
+ task default: :test
@@ -0,0 +1,2 @@
1
+ //= link_directory ../javascripts/agilibox .js
2
+ //= link_directory ../stylesheets/agilibox .css
@@ -0,0 +1 @@
1
+ #= require_tree .
@@ -0,0 +1,15 @@
1
+ $(document).on "turbolinks:load", ->
2
+ $("select").map ->
3
+ select = $(this)
4
+ form = select.parents("form")
5
+
6
+ return if select.find("[value=custom_date]").length == 0
7
+
8
+ select.change ->
9
+ if select.val() == "custom_date"
10
+ form.find(".form-group[class*=date_begin], .form-group[class*=date_end]").show()
11
+ else
12
+ form.find("input[id*=date_begin], input[id*=date_end]").val("")
13
+ form.find(".form-group[class*=date_begin], .form-group[class*=date_end]").hide()
14
+
15
+ select.change()
@@ -0,0 +1,9 @@
1
+ $(document).on "submit", "form", ->
2
+ return if this.method.toUpperCase() == "GET"
3
+ return if $(this).find("[name=form_url]").length > 0
4
+
5
+ input = document.createElement("input")
6
+ input.type = "hidden"
7
+ input.name = "form_url"
8
+ input.value = location.href
9
+ $(this).append(input)
@@ -0,0 +1,5 @@
1
+ $(document).on "click", "button.reset", ->
2
+ form = $(this).parents("form")
3
+ form.find("input, textarea, select").map ->
4
+ return if String(this.type).match(/submit|hidden|button/)
5
+ $(this).val String($(this).data("default-value") || "")
@@ -0,0 +1,129 @@
1
+ window.modal =
2
+ i18n:
3
+ loading: "Loading..."
4
+ error: "Error."
5
+
6
+ template: """
7
+ <div id='modal' class='closable'>
8
+ <div id='modal-overlay'></div>
9
+
10
+ <button id='modal-close'>×</button>
11
+
12
+ <div id='modal-body'>
13
+ {{content}}
14
+ </div>
15
+ </div>
16
+ """
17
+
18
+ _generateModalHTML: (content) ->
19
+ $(modal.template.replace("{{content}}", content))
20
+
21
+ open: (content) ->
22
+ if modal.is_opened()
23
+ modal._update(content)
24
+ else
25
+ modal._create(content)
26
+ $(document).trigger("modal:open")
27
+
28
+ _create: (content) ->
29
+ $("body").addClass("modal-open")
30
+ $("body").append(modal._generateModalHTML(content))
31
+
32
+ _update: (content) ->
33
+ $("#modal-body").html(content)
34
+
35
+ close: ->
36
+ $("body").removeClass("modal-open")
37
+ $("#modal").remove()
38
+ $(document).trigger("modal:close")
39
+ return false
40
+
41
+ is_opened: ->
42
+ return $("#modal").length > 0
43
+
44
+ is_closed: ->
45
+ return $("#modal").length == 0
46
+
47
+ is_closable: ->
48
+ return $("#modal").hasClass("closable")
49
+
50
+ autoclose: ->
51
+ modal.close() if modal.is_closable()
52
+ return false
53
+
54
+ set_closable: ->
55
+ $("#modal").addClass("closable")
56
+
57
+ set_unclosable: ->
58
+ $("#modal").removeClass("closable")
59
+
60
+ _set_closable_for_element: (element) ->
61
+ return modal.set_closable() if $(element).is("[data-modal-closable=1]")
62
+ return modal.set_unclosable() if $(element).is("[data-modal-closable=0]")
63
+
64
+ openUrl: (url, type = "GET", data = {}) ->
65
+ modal.open(modal.i18n.loading)
66
+
67
+ $.ajax
68
+ url: url
69
+ type: type
70
+ data: data
71
+ dataType: "html"
72
+ processData: false
73
+ contentType: false
74
+
75
+ success: (data, textStatus, xhr) ->
76
+ contentType = xhr.getResponseHeader("Content-Type")
77
+
78
+ if contentType.match(/html/)
79
+ modal.open(data)
80
+ $(document).trigger("modal:load")
81
+ else if contentType.match(/javascript/)
82
+ eval(data)
83
+ else
84
+ console.log("Invalid Content-Type " + contentType)
85
+
86
+ error: ->
87
+ modal.open(modal.i18n.error)
88
+ modal.set_closable()
89
+
90
+ _callbacks:
91
+ links: ->
92
+ modal.openUrl(this.href)
93
+ modal._set_closable_for_element(this)
94
+ return false
95
+
96
+ forms: ->
97
+ modal.openUrl(this.action, this.method, new FormData(this))
98
+ modal._set_closable_for_element(this)
99
+ return false
100
+
101
+ escape: (event) ->
102
+ modal.autoclose() if event.keyCode == 27
103
+ return true
104
+
105
+ setup: ->
106
+ $(document)
107
+ .off("keyup", modal._callbacks.escape)
108
+ .on("keyup", modal._callbacks.escape)
109
+
110
+ $("#modal-overlay, #modal-close")
111
+ .off("click", modal.autoclose)
112
+ .on("click", modal.autoclose)
113
+
114
+ $("a[href][data-modal=1], #modal-body a[href]")
115
+ .not("[data-modal=0]")
116
+ .not("[data-method]")
117
+ .not("[data-remote]")
118
+ .off("click", modal._callbacks.links)
119
+ .on("click", modal._callbacks.links)
120
+
121
+ $("form[data-modal=1], #modal-body form")
122
+ .not("[data-modal=0]")
123
+ .not("[data-remote]")
124
+ .off("submit", modal._callbacks.forms)
125
+ .on("submit", modal._callbacks.forms)
126
+
127
+
128
+ $(document).on "turbolinks:load modal:open", ->
129
+ modal.setup()
@@ -0,0 +1,5 @@
1
+ @import agilibox/filters
2
+ @import agilibox/flash
3
+ @import agilibox/modals
4
+ @import agilibox/pagination
5
+ @import agilibox/print
@@ -0,0 +1,43 @@
1
+ .filters
2
+ @extend .well
3
+ padding: 8px
4
+ box-shadow: none
5
+ display: flex
6
+
7
+ select,
8
+ button,
9
+ input,
10
+ .form-control,
11
+ .select2-container,
12
+ .btn + .btn,
13
+ margin: 0 5px 0 0
14
+ max-width: 15em
15
+
16
+ .form-group
17
+ display: inline-block
18
+ width: auto
19
+ padding: 0
20
+ margin: 0
21
+
22
+ .form-control,
23
+ @extend .input-sm
24
+ display: inline-block
25
+ width: auto
26
+
27
+ .btn
28
+ @extend .btn-sm
29
+
30
+ input[id*=date]
31
+ width: 8em
32
+
33
+ .select2-container
34
+ display: inline-block !important
35
+ width: 30em !important
36
+ height: 30px !important
37
+
38
+ .select2-selection
39
+ height: 28px !important
40
+ min-height: 0 !important
41
+
42
+ .select2-selection__choice
43
+ margin-top: 3px !important
@@ -0,0 +1,6 @@
1
+ // Convert Rails flash to bootstrap flash
2
+ .alert-notice
3
+ @extend .alert-success
4
+
5
+ .alert-alert
6
+ @extend .alert-danger
@@ -0,0 +1,45 @@
1
+ body.modal-open
2
+ height: 100%
3
+ overflow: hidden
4
+
5
+ #modal
6
+ display: block !important // override bootstrap
7
+ z-index: 9999
8
+
9
+ #modal, #modal-overlay
10
+ position: fixed
11
+ top: 0
12
+ right: 0
13
+ bottom: 0
14
+ left: 0
15
+ overflow: auto
16
+
17
+ #modal-overlay
18
+ background: rgba(0, 0, 0, 0.75)
19
+
20
+ #modal-body
21
+ position: relative
22
+ margin: 10vh auto
23
+ padding: 2rem
24
+ width: auto
25
+ min-width: 50%
26
+ max-width: 980px
27
+ background: white
28
+ z-index: 9999
29
+
30
+ &.fixed-height
31
+ max-height: 80vh
32
+ overflow: auto
33
+
34
+ #modal-close
35
+ color: white
36
+ position: absolute
37
+ font-size: 4rem
38
+ line-height: 0.5rem
39
+ top: 0.25rem
40
+ right: 0.25rem
41
+ border: none
42
+ background: none
43
+
44
+ #modal:not(.closable) #modal-close
45
+ display: none
@@ -0,0 +1,6 @@
1
+ .pagination
2
+ display: block
3
+ text-align: center
4
+
5
+ li
6
+ display: inline-block
@@ -0,0 +1,74 @@
1
+ @media print
2
+ html,
3
+ body,
4
+ #body,
5
+ #main,
6
+ #context,
7
+ #context-main,
8
+ .row,
9
+ div[class^=col],
10
+ thead *,
11
+ tfoot *,
12
+ th,
13
+ margin: 0 !important
14
+ padding: 0 !important
15
+ font-size: 11px !important
16
+ float: none !important
17
+ width: auto !important
18
+ height: auto !important
19
+
20
+ .panel-title,
21
+ .context-header,
22
+ thead *,
23
+ tfoot *,
24
+ th,
25
+ font-size: 12px !important
26
+ line-height: 12px !important
27
+
28
+ h1
29
+ font-size: 2em
30
+
31
+ .filters,
32
+ form.search,
33
+ .input-group-addon,
34
+ .btn,
35
+ .actions,
36
+ .actions + hr,
37
+ .navbar,
38
+ .nav,
39
+ .nav-tabs,
40
+ a[href]:after,
41
+ #flash,
42
+ display: none !important
43
+
44
+ .panel,
45
+ .table,
46
+ .list-group,
47
+ .well,
48
+ hr,
49
+ p,
50
+ margin: 1em 0 !important
51
+
52
+ .panel table,
53
+ .well p,
54
+ td p,
55
+ margin: 0 !important
56
+
57
+ .well,
58
+ padding: 0.5em !important
59
+
60
+ .panel-heading,
61
+ .panel-title,
62
+ .panel-body,
63
+ .panel-footer,
64
+ .context-header,
65
+ .context-body,
66
+ .context-footer,
67
+ .list-group-item,
68
+ thead tr > *,
69
+ tfoot tr > *,
70
+ padding: 0.5em !important
71
+ margin: 0 !important
72
+
73
+ .panel-heading .panel-title,
74
+ padding: 0 !important
@@ -0,0 +1,5 @@
1
+ module Agilibox
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+ end
5
+ end
@@ -0,0 +1,36 @@
1
+ class Agilibox::SmallData::FiltersController < ::Agilibox::ApplicationController
2
+ def create
3
+ skip_authorization if respond_to?(:skip_authorization)
4
+ skip_policy_scope if respond_to?(:skip_policy_scope)
5
+
6
+ filters = ::Agilibox::SmallData::Filter.new(cookies)
7
+ new_filters = params.fetch(:filters, {}).permit!.to_h
8
+ filters.merge new_filters
9
+
10
+ # Rewrite cookie with 1 year expiry
11
+ cookies[:filters] = {
12
+ :value => cookies[:filters],
13
+ :expires => 1.year.from_now,
14
+ :path => "/",
15
+ }
16
+
17
+ redirect_to back_url
18
+ end
19
+
20
+ private
21
+
22
+ def back_url
23
+ url = [
24
+ params[:form_url],
25
+ request.referer,
26
+ (main_app.root_path rescue "/"),
27
+ ].select(&:present?).first
28
+
29
+ # Delete page param
30
+ base, query_string = url.split("?")
31
+ query_string = query_string.to_s.split("&").delete_if { |p| p.include?("page=") }.join("&")
32
+ query_string = "?#{query_string}" if query_string.present?
33
+ base + query_string
34
+ end
35
+
36
+ end
@@ -0,0 +1,18 @@
1
+ module Agilibox::BackUrlConcern
2
+ extend ActiveSupport::Concern
3
+
4
+ private
5
+
6
+ def default_back_url; end
7
+
8
+ def back_url
9
+ [
10
+ params[:back_url],
11
+ request.referer,
12
+ default_back_url,
13
+ main_app.root_path,
14
+ "/",
15
+ ].select(&:present?).first
16
+ end
17
+
18
+ end
@@ -0,0 +1,68 @@
1
+ class Agilibox::SmallData::Filter
2
+ STRATEGIES = {}
3
+
4
+ attr_reader :jar
5
+
6
+ def initialize(jar)
7
+ @jar = jar
8
+ end
9
+
10
+ def strategies
11
+ self.class::STRATEGIES
12
+ end
13
+
14
+ def apply(query)
15
+ strategies.each do |key, strategy|
16
+ value = get(key)
17
+
18
+ next if value.blank?
19
+
20
+ query = strategy.apply(query, value)
21
+ end
22
+
23
+ return query
24
+ end
25
+
26
+ def method_missing(method, *args)
27
+ if method.to_s.end_with?("=")
28
+ key = method.to_s[0..-2]
29
+ value = args.first
30
+ action = :write
31
+ else
32
+ key = method.to_s
33
+ action = :read
34
+ end
35
+
36
+ if strategies.key?(key) && action == :read
37
+ get(key)
38
+ elsif strategies.key?(key) && action == :write
39
+ set(key, value)
40
+ else
41
+ super
42
+ end
43
+ end
44
+
45
+ def read
46
+ JSON.parse jar["filters"].to_s
47
+ rescue JSON::ParserError
48
+ {}
49
+ end
50
+
51
+ def write(filters)
52
+ jar["filters"] = filters.to_json
53
+ end
54
+
55
+ def merge(new_filters)
56
+ write read.merge(new_filters)
57
+ end
58
+
59
+ private
60
+
61
+ def get(key)
62
+ read[key.to_s]
63
+ end
64
+
65
+ def set(key, value)
66
+ merge(key.to_s => value)
67
+ end
68
+ end
@@ -0,0 +1,5 @@
1
+ class Agilibox::SmallData::FilterStrategy
2
+ def apply(query, value)
3
+ raise NotImplementedError
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class Agilibox::SmallData::FilterStrategyByDate < ::Agilibox::SmallData::FilterStrategyByKeyValue
2
+ def apply(query, value)
3
+ value = Date.parse(value)
4
+ super(query, value)
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ class Agilibox::SmallData::FilterStrategyByDateBegin < ::Agilibox::SmallData::FilterStrategyByKeyValue
2
+ def apply(query, value)
3
+ value = Time.parse(value).beginning_of_day
4
+ query.where("#{key} >= ?", value)
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ class Agilibox::SmallData::FilterStrategyByDateEnd < ::Agilibox::SmallData::FilterStrategyByKeyValue
2
+ def apply(query, value)
3
+ value = Time.parse(value).end_of_day
4
+ query.where("#{key} <= ?", value)
5
+ end
6
+ end
@@ -0,0 +1,16 @@
1
+ class Agilibox::SmallData::FilterStrategyByKeyValue < ::Agilibox::SmallData::FilterStrategy
2
+ attr_reader :key
3
+
4
+ def initialize(key = nil)
5
+ @key = key
6
+ end
7
+
8
+ def apply(query, value)
9
+ value = true if value == "true"
10
+ value = false if value == "false"
11
+ value = nil if value == "nil"
12
+ value = nil if value == "null"
13
+
14
+ query.where("#{key} = ?", value)
15
+ end
16
+ end
@@ -0,0 +1,11 @@
1
+ class Agilibox::SmallData::FilterStrategyByTags < ::Agilibox::SmallData::FilterStrategy
2
+ def apply(query, value)
3
+ value = [*value].flatten.select{ |v| v.present? }
4
+
5
+ if value.any?
6
+ query.tagged_with(value)
7
+ else
8
+ query
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,37 @@
1
+ class Agilibox::SmallData::FilterStrategyByTimePeriod < ::Agilibox::SmallData::FilterStrategyByKeyValue
2
+ def apply(query, value)
3
+ if value == "today"
4
+ a = Time.zone.now.beginning_of_day
5
+ b = Time.zone.now.end_of_day
6
+ elsif value == "yesterday"
7
+ a = (Time.zone.now - 1.day).beginning_of_day
8
+ b = (Time.zone.now - 1.day).end_of_day
9
+ elsif value == "this_week"
10
+ a = Time.zone.now.beginning_of_week
11
+ b = Time.zone.now.end_of_week
12
+ elsif value == "this_month"
13
+ a = Time.zone.now.beginning_of_month
14
+ b = Time.zone.now.end_of_month
15
+ elsif value == "this_year"
16
+ a = Time.zone.now.beginning_of_year
17
+ b = Time.zone.now.end_of_year
18
+ elsif value == "last_week"
19
+ a = (Time.zone.now - 1.week).beginning_of_week
20
+ b = (Time.zone.now - 1.week).end_of_week
21
+ elsif value == "last_month"
22
+ a = (Time.zone.now - 1.month).beginning_of_month
23
+ b = (Time.zone.now - 1.month).end_of_month
24
+ elsif value == "last_year"
25
+ a = (Time.zone.now - 1.year).beginning_of_year
26
+ b = (Time.zone.now - 1.year).end_of_year
27
+ else
28
+ return query
29
+ end
30
+
31
+ criteria = "#{query.model.table_name}.#{key}"
32
+
33
+ query
34
+ .where("#{criteria} >= ?", a.to_date)
35
+ .where("#{criteria} <= ?", b.to_date)
36
+ end
37
+ end
@@ -0,0 +1,13 @@
1
+ module Agilibox::AllHelpers
2
+ include Agilibox::BootstrapHelper
3
+ include Agilibox::ButtonHelper
4
+ include Agilibox::FiltersHelper
5
+ include Agilibox::FormHelper
6
+ include Agilibox::LinkHelper
7
+ include Agilibox::PaginationHelper
8
+ include Agilibox::RoutesHelper
9
+ include Agilibox::SortingHelper
10
+ include Agilibox::TextHelper
11
+
12
+ extend self
13
+ end