wice_grid_ms 3.6.0

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.
Files changed (92) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.inch.yml +3 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +181 -0
  6. data/.travis.yml +22 -0
  7. data/CHANGELOG.md +714 -0
  8. data/Gemfile +4 -0
  9. data/MIT-LICENSE +20 -0
  10. data/README.md +1518 -0
  11. data/Rakefile +59 -0
  12. data/SAVED_QUERIES_HOWTO.md +113 -0
  13. data/TODO.md +16 -0
  14. data/app/views/kaminari/wice_grid/_gap.html.erb +1 -0
  15. data/app/views/kaminari/wice_grid/_next_page.html.erb +1 -0
  16. data/app/views/kaminari/wice_grid/_page.html.erb +1 -0
  17. data/app/views/kaminari/wice_grid/_paginator.html.erb +19 -0
  18. data/app/views/kaminari/wice_grid/_prev_page.html.erb +1 -0
  19. data/config/locales/cz.yml +45 -0
  20. data/config/locales/de.yml +47 -0
  21. data/config/locales/en.yml +47 -0
  22. data/config/locales/es.yml +47 -0
  23. data/config/locales/fr.yml +45 -0
  24. data/config/locales/is.yml +46 -0
  25. data/config/locales/it.yml +38 -0
  26. data/config/locales/ja.yml +47 -0
  27. data/config/locales/nl.yml +45 -0
  28. data/config/locales/pt-BR.yml +36 -0
  29. data/config/locales/pt.yml +45 -0
  30. data/config/locales/ru.yml +45 -0
  31. data/config/locales/sk.yml +45 -0
  32. data/config/locales/uk.yml +45 -0
  33. data/config/locales/zh.yml +45 -0
  34. data/lib/generators/wice_grid/add_migration_for_serialized_queries_generator.rb +20 -0
  35. data/lib/generators/wice_grid/install_generator.rb +14 -0
  36. data/lib/generators/wice_grid/templates/create_wice_grid_serialized_queries.rb +14 -0
  37. data/lib/generators/wice_grid/templates/wice_grid_config.rb +192 -0
  38. data/lib/wice/active_record_column_wrapper.rb +123 -0
  39. data/lib/wice/columns.rb +276 -0
  40. data/lib/wice/columns/column_action.rb +52 -0
  41. data/lib/wice/columns/column_boolean.rb +40 -0
  42. data/lib/wice/columns/column_bootstrap_datepicker.rb +48 -0
  43. data/lib/wice/columns/column_custom_dropdown.rb +115 -0
  44. data/lib/wice/columns/column_float.rb +9 -0
  45. data/lib/wice/columns/column_html5_datepicker.rb +31 -0
  46. data/lib/wice/columns/column_integer.rb +78 -0
  47. data/lib/wice/columns/column_jquery_datepicker.rb +49 -0
  48. data/lib/wice/columns/column_processor_index.rb +23 -0
  49. data/lib/wice/columns/column_rails_date_helper.rb +41 -0
  50. data/lib/wice/columns/column_rails_datetime_helper.rb +40 -0
  51. data/lib/wice/columns/column_range.rb +72 -0
  52. data/lib/wice/columns/column_string.rb +92 -0
  53. data/lib/wice/columns/common_date_datetime_mixin.rb +20 -0
  54. data/lib/wice/columns/common_js_date_datetime_conditions_generator_mixin.rb +42 -0
  55. data/lib/wice/columns/common_js_date_datetime_mixin.rb +15 -0
  56. data/lib/wice/columns/common_rails_date_datetime_conditions_generator_mixin.rb +26 -0
  57. data/lib/wice/columns/common_standard_helper_date_datetime_mixin.rb +22 -0
  58. data/lib/wice/grid_output_buffer.rb +49 -0
  59. data/lib/wice/grid_renderer.rb +609 -0
  60. data/lib/wice/helpers/bs_calendar_helpers.rb +66 -0
  61. data/lib/wice/helpers/js_calendar_helpers.rb +83 -0
  62. data/lib/wice/helpers/wice_grid_misc_view_helpers.rb +75 -0
  63. data/lib/wice/helpers/wice_grid_serialized_queries_view_helpers.rb +95 -0
  64. data/lib/wice/helpers/wice_grid_view_helpers.rb +718 -0
  65. data/lib/wice/kaminari_monkey_patching.rb +14 -0
  66. data/lib/wice/table_column_matrix.rb +65 -0
  67. data/lib/wice/wice_grid_controller.rb +223 -0
  68. data/lib/wice/wice_grid_core_ext.rb +142 -0
  69. data/lib/wice/wice_grid_misc.rb +209 -0
  70. data/lib/wice/wice_grid_serialized_queries_controller.rb +87 -0
  71. data/lib/wice/wice_grid_serialized_query.rb +14 -0
  72. data/lib/wice/wice_grid_spreadsheet.rb +20 -0
  73. data/lib/wice_grid.rb +676 -0
  74. data/release_notes/RELEASE_NOTES_3.2.pre1.rdoc +81 -0
  75. data/release_notes/RELEASE_NOTES_3.2.pre2.rdoc +6 -0
  76. data/release_notes/RELEASE_NOTES_3.3.0.rdoc +21 -0
  77. data/spec/schema.rb +9 -0
  78. data/spec/spec_helper.rb +75 -0
  79. data/spec/support/active_record.rb +11 -0
  80. data/spec/support/wice_grid_test_config.rb +175 -0
  81. data/spec/wice/grid_output_buffer_spec.rb +41 -0
  82. data/spec/wice/table_column_matrix_spec.rb +38 -0
  83. data/spec/wice/wice_grid_misc_spec.rb +159 -0
  84. data/spec/wice/wice_grid_spreadsheet_spec.rb +14 -0
  85. data/test/readme.txt +1 -0
  86. data/vendor/assets/javascripts/wice_grid.js +3 -0
  87. data/vendor/assets/javascripts/wice_grid_init.js.coffee +339 -0
  88. data/vendor/assets/javascripts/wice_grid_processor.js.coffee +133 -0
  89. data/vendor/assets/javascripts/wice_grid_saved_queries_init.js.coffee +103 -0
  90. data/vendor/assets/stylesheets/wice_grid.scss +81 -0
  91. data/wice_grid.gemspec +36 -0
  92. metadata +335 -0
@@ -0,0 +1,87 @@
1
+ # encoding: utf-8
2
+ module Wice
3
+ class <<self
4
+ # Used in routes.rb to define routes to the query processing controller.
5
+ # Parameters:
6
+ # * map - the context of the routes execution (instance of <tt>ActionDispatch::Routing::Mapper</tt>).
7
+ # Normally use +self+ for the first argument: <tt>Wice::define_routes(self, 'queries')</tt>
8
+ # * controller - name of the query processing controller, i.e. <tt>'queries'</tt> if the controller is +QueriesController+ .
9
+ # Read section "Saving Queries How-To" in README for more details.
10
+ def define_routes(map, controller)
11
+ controller = controller.to_s
12
+
13
+ map.post '/wice_grid_serialized_queries/:grid_name',
14
+ to: "#{controller}#create_saved_query",
15
+ as: 'create_serialized_query'
16
+
17
+ map.post '/wice_grid_serialized_queries/:grid_name/:id',
18
+ to: "#{controller}#delete_saved_query",
19
+ as: 'delete_serialized_query'
20
+ end
21
+ end
22
+
23
+ module SerializedQueriesControllerMixin #:nodoc:
24
+ def delete_saved_query #:nodoc:
25
+ init
26
+ if sq = @query_store_model.find_by_id_and_grid_name(params[:id], @grid_name)
27
+ if sq.destroy
28
+ if params[:current]
29
+ @current = @query_store_model.find_by_id_and_grid_name(params[:current], @grid_name)
30
+ end
31
+ @notification_messages = NlMessage['query_deleted_message']
32
+ else
33
+ @error_messages = sq.errors.full_raw_messages.join(' ')
34
+ end
35
+ end
36
+
37
+ render_asyns_result
38
+ end
39
+
40
+ def create_saved_query #:nodoc:
41
+ init
42
+ query_params = if params[@grid_name]
43
+ params[@grid_name]
44
+ else
45
+ {}
46
+ end
47
+ query_params.delete(:page)
48
+
49
+ @saved_query = @query_store_model.new
50
+
51
+ @saved_query.grid_name = @grid_name
52
+ @saved_query.name = params[:query_name]
53
+ @saved_query.query = query_params
54
+
55
+ @saved_query.attributes = extra unless extra.nil?
56
+
57
+ if @saved_query.save
58
+ @grid_title_id = "#{@grid_name}_title"
59
+ @notification_messages = NlMessage['query_saved_message']
60
+ else
61
+ @error_messages = @saved_query.errors.map { |_, msg| msg }.join(' ')
62
+ end
63
+
64
+ render_asyns_result
65
+ end
66
+
67
+ def extra #:nodoc:
68
+ params[:extra].permit! unless params[:extra].nil?
69
+ end
70
+
71
+ protected
72
+
73
+ def render_asyns_result #:nodoc:
74
+ render json: {
75
+ 'error_messages' => @error_messages,
76
+ 'notification_messages' => @notification_messages,
77
+ 'query_list' => render_to_string(inline: '<%=saved_queries_list(@grid_name, @saved_query, controller.extra, @confirm).html_safe%>')
78
+ }
79
+ end
80
+
81
+ def init #:nodoc:
82
+ @query_store_model = ::Wice.get_query_store_model
83
+ @confirm = params[:confirm] == '1' || params[:confirm] == 'true'
84
+ @grid_name = params[:grid_name]
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+ class WiceGridSerializedQuery < ActiveRecord::Base #:nodoc:
3
+ serialize :query
4
+
5
+ validates_uniqueness_of :name, scope: :grid_name, on: :create, message: 'A query with this name already exists'
6
+
7
+ validates_presence_of :name, message: 'Please submit the name of the custom query'
8
+
9
+ # returns a list of all serialized queries
10
+ def self.list(name, _controller)
11
+ conditions = { grid_name: name }
12
+ self.where(conditions).to_a
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ require 'csv'
3
+
4
+ module Wice
5
+ class Spreadsheet #:nodoc:
6
+
7
+ #:nodoc:
8
+ attr_reader :tempfile
9
+
10
+ def initialize(name, field_separator, encoding = nil) #:nodoc:
11
+ @tempfile = Tempfile.new(name)
12
+ @tempfile.set_encoding(encoding) unless encoding.blank?
13
+ @csv = CSV.new(@tempfile, col_sep: field_separator)
14
+ end
15
+
16
+ def << (row) #:nodoc:
17
+ @csv << row
18
+ end
19
+ end
20
+ end
data/lib/wice_grid.rb ADDED
@@ -0,0 +1,676 @@
1
+ # encoding: utf-8
2
+ require 'wice/wice_grid_misc.rb'
3
+ require 'wice/wice_grid_core_ext.rb'
4
+ require 'wice/grid_renderer.rb'
5
+ require 'wice/table_column_matrix.rb'
6
+ require 'wice/active_record_column_wrapper.rb'
7
+ require 'wice/helpers/wice_grid_view_helpers.rb'
8
+ require 'wice/helpers/wice_grid_misc_view_helpers.rb'
9
+ require 'wice/helpers/wice_grid_serialized_queries_view_helpers.rb'
10
+ require 'wice/helpers/wice_grid_view_helpers.rb'
11
+ require 'wice/helpers/bs_calendar_helpers.rb'
12
+ require 'wice/helpers/js_calendar_helpers.rb'
13
+ require 'wice/grid_output_buffer.rb'
14
+ require 'wice/wice_grid_controller.rb'
15
+ require 'wice/wice_grid_spreadsheet.rb'
16
+ require 'wice/wice_grid_serialized_queries_controller.rb'
17
+ require 'wice/columns/column_processor_index.rb'
18
+ require 'wice/columns.rb'
19
+ require 'wice/columns/common_date_datetime_mixin.rb'
20
+ require 'wice/columns/common_standard_helper_date_datetime_mixin.rb'
21
+ require 'wice/columns/common_js_date_datetime_mixin.rb'
22
+ require 'wice/columns/common_js_date_datetime_conditions_generator_mixin.rb'
23
+ require 'wice/columns/common_rails_date_datetime_conditions_generator_mixin.rb'
24
+ require 'kaminari.rb'
25
+
26
+
27
+ ActionController::Base.send(:helper_method, :wice_grid_custom_filter_params)
28
+
29
+ module Wice
30
+
31
+ def self.on_action_view_load #:nodoc:
32
+ ::ActionView::Base.class_eval { include Wice::GridViewHelper }
33
+ [ActionView::Helpers::AssetTagHelper,
34
+ ActionView::Helpers::TagHelper,
35
+ ActionView::Helpers::JavaScriptHelper,
36
+ ActionView::Helpers::FormTagHelper].each do |m|
37
+ JsCalendarHelpers.send(:include, m)
38
+ end
39
+
40
+ Columns.load_column_processors
41
+ require 'wice/wice_grid_serialized_query.rb'
42
+
43
+ # It is here only because of this: https://github.com/amatsuda/kaminari/pull/267
44
+ require 'wice/kaminari_monkey_patching.rb'
45
+
46
+ end
47
+
48
+ class WiceGridEngine < ::Rails::Engine #:nodoc:
49
+ initializer 'wice_grid_railtie.configure_rails_initialization' do |_app|
50
+ ActiveSupport.on_load :action_controller do
51
+ ActionController::Base.send(:include, Wice::Controller)
52
+ end
53
+
54
+ ActiveSupport.on_load :active_record do
55
+ ActiveRecord::ConnectionAdapters::Column.send(:include, ::Wice::WiceGridExtentionToActiveRecordColumn)
56
+ end
57
+
58
+ ActiveSupport.on_load :action_view do
59
+ ::Wice.on_action_view_load
60
+ end
61
+ end
62
+
63
+ initializer 'wice_grid_railtie.configure_rails_assets_precompilation' do |app|
64
+ app.config.assets.precompile << 'icons/grid/*'
65
+ end
66
+ end
67
+
68
+
69
+ # Main class responsible for keeping the state of the grid, building an ActiveRelation, and running queries
70
+ class WiceGrid
71
+ attr_reader :klass, :name, :resultset, :custom_order, :query_store_model #:nodoc:
72
+ attr_reader :ar_options, :status, :export_to_csv_enabled, :csv_file_name, :csv_field_separator, :csv_encoding, :saved_query #:nodoc:
73
+ attr_writer :renderer #:nodoc:
74
+ attr_accessor :output_buffer, :view_helper_finished, :csv_tempfile #:nodoc:
75
+
76
+ # core workflow methods START
77
+
78
+ def initialize(klass_or_relation, controller, opts = {}) #:nodoc:
79
+ @controller = controller
80
+
81
+ @relation = klass_or_relation
82
+ @klass = if @relation.is_a?(Class) && @relation.ancestors.index(ActiveRecord::Base)
83
+ klass_or_relation
84
+ else
85
+ klass_or_relation.klass
86
+ end
87
+
88
+ unless @klass.is_a?(Class) && @klass.ancestors.index(ActiveRecord::Base)
89
+ fail WiceGridArgumentError.new('ActiveRecord model class (second argument) must be a Class derived from ActiveRecord::Base')
90
+ end
91
+
92
+ # validate :with_resultset & :with_paginated_resultset
93
+ [:with_resultset, :with_paginated_resultset].each do |callback_symbol|
94
+ unless [NilClass, Symbol, Proc].index(opts[callback_symbol].class)
95
+ fail WiceGridArgumentError.new(":#{callback_symbol} must be either a Proc or Symbol object")
96
+ end
97
+ end
98
+
99
+ opts[:order_direction].downcase! if opts[:order_direction].is_a?(String)
100
+
101
+ # validate :order_direction
102
+ if opts[:order_direction] && ! (opts[:order_direction] == 'asc' || opts[:order_direction] == :asc || opts[:order_direction] == 'desc' ||
103
+ opts[:order_direction] == :desc)
104
+ fail WiceGridArgumentError.new(":order_direction must be either 'asc' or 'desc'.")
105
+ end
106
+
107
+ begin
108
+ # options that are understood
109
+ @options = {
110
+ conditions: nil,
111
+ csv_file_name: nil,
112
+ csv_field_separator: ConfigurationProvider.value_for(:CSV_FIELD_SEPARATOR),
113
+ csv_encoding: ConfigurationProvider.value_for(:CSV_ENCODING),
114
+ custom_order: {},
115
+ enable_export_to_csv: ConfigurationProvider.value_for(:ENABLE_EXPORT_TO_CSV),
116
+ group: nil,
117
+ include: nil,
118
+ joins: nil,
119
+ name: ConfigurationProvider.value_for(:GRID_NAME),
120
+ order: nil,
121
+ order_direction: ConfigurationProvider.value_for(:ORDER_DIRECTION),
122
+ page: 1,
123
+ page_method_name: ConfigurationProvider.value_for(:PAGE_METHOD_NAME),
124
+ per_page: ConfigurationProvider.value_for(:PER_PAGE),
125
+ saved_query: nil,
126
+ with_paginated_resultset: nil,
127
+ with_resultset: nil,
128
+ use_default_scope: ConfigurationProvider.value_for(:USE_DEFAULT_SCOPE)
129
+ }
130
+ rescue NameError
131
+ raise NameError.new('A constant is missing in wice_grid_config.rb: ' + $ERROR_INFO.message +
132
+ '. This can happen when you upgrade the WiceGrid to a newer version with a new configuration constant. ' \
133
+ 'Add the constant manually or re-run `bundle exec rails g wice_grid:install`.')
134
+ end
135
+ # validate parameters
136
+ opts.assert_valid_keys(@options.keys)
137
+
138
+ @options.merge!(opts)
139
+ @export_to_csv_enabled = @options[:enable_export_to_csv]
140
+ @csv_file_name = @options[:csv_file_name]
141
+ @csv_field_separator = @options[:csv_field_separator]
142
+ @csv_encoding = @options[:csv_encoding]
143
+
144
+ case @name = @options[:name]
145
+ when String
146
+ when Symbol
147
+ @name = @name.to_s
148
+ else
149
+ fail WiceGridArgumentError.new('name of the grid should be a string or a symbol')
150
+ end
151
+ fail WiceGridArgumentError.new('name of the grid can only contain alphanumeruc characters') unless @name =~ /^[a-zA-Z\d_]*$/
152
+
153
+ @table_column_matrix = TableColumnMatrix.new
154
+ @table_column_matrix.default_model_class = @klass
155
+
156
+ @ar_options = {}
157
+ @status = HashWithIndifferentAccess.new
158
+
159
+ if @options[:order]
160
+ @options[:order] = @options[:order].to_s
161
+ @options[:order_direction] = @options[:order_direction].to_s
162
+
163
+ @status[:order_direction] = @options[:order_direction]
164
+ @status[:order] = @options[:order]
165
+
166
+ end
167
+ @status[:per_page] = @options[:per_page]
168
+ @status[:page] = @options[:page]
169
+ @status[:conditions] = @options[:conditions]
170
+ @status[:f] = @options[:f]
171
+
172
+ process_loading_query
173
+ process_params
174
+
175
+ @ar_options_formed = false
176
+ end
177
+
178
+ # A block executed from within the plugin to process records of the current page.
179
+ # The argument to the callback is the array of the records. See the README for more details.
180
+ def with_paginated_resultset(&callback)
181
+ @options[:with_paginated_resultset] = callback
182
+ end
183
+
184
+ # A block executed from within the plugin to process all records browsable through
185
+ # all pages with the current filters. The argument to
186
+ # the callback is a lambda object which returns the list of records when called. See the README for the explanation.
187
+ def with_resultset(&callback)
188
+ @options[:with_resultset] = callback
189
+ end
190
+
191
+ def process_loading_query #:nodoc:
192
+ @saved_query = nil
193
+ if params[name] && params[name][:q]
194
+ @saved_query = load_query(params[name][:q])
195
+ params[name].delete(:q)
196
+ elsif @options[:saved_query]
197
+ if @options[:saved_query].is_a? ActiveRecord::Base
198
+ @saved_query = @options[:saved_query]
199
+ else
200
+ @saved_query = load_query(@options[:saved_query])
201
+ end
202
+ else
203
+ return
204
+ end
205
+
206
+ unless @saved_query.nil?
207
+ params[name] = HashWithIndifferentAccess.new if params[name].blank?
208
+ [:f, :order, :order_direction].each do |key|
209
+ if @saved_query.query[key].blank?
210
+ params[name].delete(key)
211
+ else
212
+ params[name][key] = @saved_query.query[key]
213
+ end
214
+ end
215
+ end
216
+ end
217
+
218
+ def process_params #:nodoc:
219
+ if this_grid_params
220
+ @status.merge!(this_grid_params)
221
+ @status.delete(:export) unless self.export_to_csv_enabled
222
+ end
223
+ end
224
+
225
+ # declare_column(String, ActiveRecord, CustomFilterSpec, nil | string, nil | Boolean)
226
+ def declare_column(
227
+ column_name: nil,
228
+ model: nil,
229
+ custom_filter_active: nil,
230
+ table_alias: nil,
231
+ filter_type: nil,
232
+ assocs: []) #:nodoc:
233
+
234
+
235
+ @options[:include] = Wice.build_includes(@options[:include], assocs)
236
+
237
+ if model # this is an included table
238
+ column = @table_column_matrix.get_column_by_model_class_and_column_name(model, column_name)
239
+ fail WiceGridArgumentError.new("Column '#{column_name}' is not found in table '#{model.table_name}'!") if column.nil?
240
+ main_table = false
241
+ table_name = model.table_name
242
+ else
243
+ column = @table_column_matrix.get_column_in_default_model_class_by_column_name(column_name)
244
+ if column.nil?
245
+ fail WiceGridArgumentError.new("Column '#{column_name}' is not found in table '#{@klass.table_name}'! " \
246
+ "If '#{column_name}' belongs to another table you should declare it in :include or :join when initialising " \
247
+ 'the grid, and specify :model in column declaration.')
248
+ end
249
+ main_table = true
250
+ table_name = @table_column_matrix.default_model_class.table_name
251
+ end
252
+
253
+ if column
254
+ conditions_generator = ActiveRecordColumnWrapper.new(column, @status[:f], main_table, table_alias, custom_filter_active, filter_type)
255
+ conditions, current_parameter_name = conditions_generator.wg_initialize_request_parameters
256
+
257
+ if @status[:f] && conditions.blank?
258
+ @status[:f].delete(current_parameter_name)
259
+ end
260
+
261
+ @table_column_matrix.add_condition(column, conditions)
262
+
263
+ # [ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::Column, String, Boolean]
264
+ [column, table_name, main_table]
265
+ end
266
+ end
267
+
268
+ def form_ar_options(opts = {}) #:nodoc:
269
+ return if @ar_options_formed
270
+ @ar_options_formed = true unless opts[:forget_generated_options]
271
+
272
+ # validate @status[:order_direction]
273
+ @status[:order_direction] = case @status[:order_direction]
274
+ when /desc/i
275
+ 'desc'
276
+ when /asc/i
277
+ 'asc'
278
+ else
279
+ ''
280
+ end
281
+
282
+ # conditions
283
+ # do not delete for a while
284
+ # https://github.com/leikind/wice_grid/issues/144
285
+ # if @table_column_matrix.generated_conditions.size == 0
286
+ # @status.delete(:f)
287
+ # end
288
+
289
+ initial_conditions_active_relation = @klass.where(@status[:conditions])
290
+
291
+ @ar_options[:conditions] =
292
+ @table_column_matrix.conditions.reduce(initial_conditions_active_relation) do |active_relation_accu, cond|
293
+ conditions_active_relation = @klass.where(cond)
294
+ active_relation_accu.merge(conditions_active_relation)
295
+ end
296
+
297
+ # conditions processed
298
+
299
+ if (!opts[:skip_ordering]) && ! @status[:order].blank?
300
+ @ar_options[:order] = add_custom_order_sql(complete_column_name(@status[:order]))
301
+
302
+ @ar_options[:order] += ' ' + @status[:order_direction]
303
+ end
304
+
305
+ @ar_options[:joins] = @options[:joins]
306
+ @ar_options[:include] = @options[:include]
307
+ @ar_options[:group] = @options[:group]
308
+
309
+ if self.output_html?
310
+ @ar_options[:per_page] = @status[:per_page]
311
+ @ar_options[:page] = @status[:page]
312
+
313
+ if (show_all_limit = Wice::ConfigurationProvider.value_for(:SHOW_ALL_ALLOWED_UP_TO, strict: false)) && all_record_mode?
314
+ if do_count > show_all_limit # force-reset SHOW-ALL to pagination
315
+ @status[:pp] = nil
316
+ end
317
+ end
318
+
319
+ end
320
+ end
321
+
322
+ def add_references(relation) #:nodoc:
323
+ if @ar_options[:include] && relation.respond_to?(:references)
324
+ # refs = [@ar_options[:include]] unless @ar_options[:include].is_a?(Array)
325
+ relation = relation.references(* @ar_options[:include])
326
+ end
327
+ relation
328
+ end
329
+
330
+ # TO DO: what to do with other @ar_options values?
331
+ def read #:nodoc:
332
+ form_ar_options
333
+ use_default_or_unscoped do
334
+ @resultset = if self.output_csv? || all_record_mode?
335
+ relation = @relation
336
+ .includes(@ar_options[:include])
337
+ .joins(@ar_options[:joins])
338
+ .order(@ar_options[:order])
339
+ .group(@ar_options[:group])
340
+ .merge(@ar_options[:conditions])
341
+ relation = add_references relation
342
+
343
+ relation
344
+ else
345
+ # p @ar_options
346
+ relation = @relation
347
+ .send(@options[:page_method_name], @ar_options[:page])
348
+ .per(@ar_options[:per_page])
349
+ .includes(@ar_options[:include])
350
+ .joins(@ar_options[:joins])
351
+ .order(@ar_options[:order])
352
+ .group(@ar_options[:group])
353
+ .merge(@ar_options[:conditions])
354
+
355
+ relation = add_references relation
356
+
357
+ relation
358
+ end
359
+ end
360
+ invoke_resultset_callbacks
361
+ end
362
+
363
+ # core workflow methods END
364
+
365
+ # Getters
366
+
367
+ def filter_params(view_column) #:nodoc:
368
+ column_name = view_column.attribute_name_fully_qualified_for_all_but_main_table_columns
369
+ if @status[:f] && @status[:f][column_name]
370
+ @status[:f][column_name]
371
+ else
372
+ {}
373
+ end
374
+ end
375
+
376
+ def resultset #:nodoc:
377
+ self.read unless @resultset # database querying is late!
378
+ @resultset
379
+ end
380
+
381
+ def each #:nodoc:
382
+ self.read unless @resultset # database querying is late!
383
+ @resultset.each do |r|
384
+ yield r
385
+ end
386
+ end
387
+
388
+ def ordered_by?(column) #:nodoc:
389
+ return nil if @status[:order].blank?
390
+ if column.main_table && ! @status[:order].index('.')
391
+ @status[:order] == column.attribute
392
+ else
393
+ @status[:order] == column.table_alias_or_table_name + '.' + column.attribute
394
+ end
395
+ end
396
+
397
+ def ordered_by #:nodoc:
398
+ @status[:order]
399
+ end
400
+
401
+ def order_direction #:nodoc:
402
+ @status[:order_direction]
403
+ end
404
+
405
+ def filtering_on? #:nodoc:
406
+ !@status[:f].blank?
407
+ end
408
+
409
+ def filtered_by #:nodoc:
410
+ @status[:f].nil? ? [] : @status[:f].keys
411
+ end
412
+
413
+ def filtered_by?(view_column) #:nodoc:
414
+ @status[:f].nil? ? false : @status[:f].key?(view_column.attribute_name_fully_qualified_for_all_but_main_table_columns)
415
+ end
416
+
417
+ def get_state_as_parameter_value_pairs(including_saved_query_request = false) #:nodoc:
418
+ res = []
419
+ unless status[:f].blank?
420
+ Wice::WgHash.parameter_names_and_values(status[:f], [name, 'f']).collect do |param_name, value|
421
+ if value.is_a?(Array)
422
+ param_name_ar = param_name + '[]'
423
+ value.each do |v|
424
+ res << [param_name_ar, v]
425
+ end
426
+ else
427
+ res << [param_name, value]
428
+ end
429
+ end
430
+ end
431
+
432
+ if including_saved_query_request && @saved_query
433
+ res << ["#{name}[q]", @saved_query.id]
434
+ end
435
+
436
+ [:order, :order_direction].select do|parameter|
437
+ status[parameter]
438
+ end.collect do |parameter|
439
+ res << ["#{name}[#{parameter}]", status[parameter]]
440
+ end
441
+
442
+ res
443
+ end
444
+
445
+ def count #:nodoc:
446
+ form_ar_options(skip_ordering: true, forget_generated_options: true)
447
+ do_count
448
+ end
449
+
450
+ def do_count #:nodoc:
451
+ @relation
452
+ .all
453
+ .merge(@ar_options[:conditions]).count(
454
+ joins: @ar_options[:joins],
455
+ include: @ar_options[:include],
456
+ group: @ar_options[:group]
457
+ )
458
+ end
459
+
460
+ alias_method :size, :count
461
+
462
+ def empty? #:nodoc:
463
+ self.count == 0
464
+ end
465
+
466
+ # with this variant we get even those values which do not appear in the resultset
467
+ def distinct_values_for_column(column) #:nodoc:
468
+ column.model.select("distinct #{column.name}").order("#{column.name} asc").collect do|ar|
469
+ ar[column.name]
470
+ end.reject(&:blank?).map { |i| [i, i] }
471
+ end
472
+
473
+ def distinct_values_for_column_in_resultset(messages) #:nodoc:
474
+ uniq_vals = Set.new
475
+
476
+ resultset_without_paging_without_user_filters.each do |ar|
477
+ v = ar.deep_send(*messages)
478
+ uniq_vals << v unless v.nil?
479
+ end
480
+ uniq_vals.to_a.map do|i|
481
+ if i.is_a?(Array) && i.size == 2
482
+ i
483
+ elsif i.is_a?(Hash) && i.size == 1
484
+ i.to_a.flatten
485
+ else
486
+ [i, i]
487
+ end
488
+ end.sort { |a, b| a[0] <=> b[0] }
489
+ end
490
+
491
+ def output_csv? #:nodoc:
492
+ @status[:export] == 'csv'
493
+ end
494
+
495
+ def output_html? #:nodoc:
496
+ @status[:export].blank?
497
+ end
498
+
499
+ def all_record_mode? #:nodoc:
500
+ @status[:pp]
501
+ end
502
+
503
+ def dump_status #:nodoc:
504
+ " params: #{params[name].inspect}\n" + " status: #{@status.inspect}\n" \
505
+ " ar_options #{@ar_options.inspect}\n"
506
+ end
507
+
508
+ # Returns the list of objects browsable through all pages with the current filters.
509
+ # Should only be called after the +grid+ helper.
510
+ def all_pages_records
511
+ fail WiceGridException.new('all_pages_records can only be called only after the grid view helper') unless self.view_helper_finished
512
+ resultset_without_paging_with_user_filters
513
+ end
514
+
515
+ # Returns the list of objects displayed on current page. Should only be called after the +grid+ helper.
516
+ def current_page_records
517
+ fail WiceGridException.new('current_page_records can only be called only after the grid view helper') unless self.view_helper_finished
518
+ @resultset
519
+ end
520
+
521
+ protected
522
+
523
+ def invoke_resultset_callback(callback, argument) #:nodoc:
524
+ case callback
525
+ when Proc
526
+ callback.call(argument)
527
+ when Symbol
528
+ @controller.send(callback, argument)
529
+ end
530
+ end
531
+
532
+ def invoke_resultset_callbacks #:nodoc:
533
+ invoke_resultset_callback(@options[:with_paginated_resultset], @resultset)
534
+ invoke_resultset_callback(@options[:with_resultset], self.active_relation_for_resultset_without_paging_with_user_filters)
535
+ end
536
+
537
+ def add_custom_order_sql(fully_qualified_column_name) #:nodoc:
538
+ custom_order = if @options[:custom_order].key?(fully_qualified_column_name)
539
+ @options[:custom_order][fully_qualified_column_name]
540
+ else
541
+ if view_column = @renderer[fully_qualified_column_name]
542
+ view_column.custom_order
543
+ end
544
+ end
545
+
546
+ if custom_order.blank?
547
+ sqlite = ActiveRecord::ConnectionAdapters.const_defined?(:SQLite3Adapter) && ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters::SQLite3Adapter)
548
+ postgres = ActiveRecord::ConnectionAdapters.const_defined?(:PostgreSQLAdapter) && ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
549
+ if sqlite || postgres
550
+ fully_qualified_column_name.strip.split('.').map { |chunk| ActiveRecord::Base.connection.quote_table_name(chunk) }.join('.')
551
+ else
552
+ ActiveRecord::Base.connection.quote_table_name(fully_qualified_column_name.strip)
553
+ end
554
+ else
555
+ if custom_order.is_a? String
556
+ custom_order.gsub(/\?/, fully_qualified_column_name)
557
+ elsif custom_order.is_a? Proc
558
+ custom_order.call(fully_qualified_column_name)
559
+ else
560
+ fail WiceGridArgumentError.new("invalid custom order #{custom_order.inspect}")
561
+ end
562
+ end
563
+ end
564
+
565
+ def complete_column_name(col_name) #:nodoc:
566
+ if col_name.index('.') # already has a table name
567
+ col_name
568
+ else # add the default table
569
+ "#{@klass.table_name}.#{col_name}"
570
+ end
571
+ end
572
+
573
+ def params #:nodoc:
574
+ @controller.params
575
+ end
576
+
577
+ def this_grid_params #:nodoc:
578
+ params[name]
579
+ end
580
+
581
+ def resultset_without_paging_without_user_filters #:nodoc:
582
+ form_ar_options
583
+
584
+ use_default_or_unscoped do
585
+ relation = @relation.joins(@ar_options[:joins])
586
+ .includes(@ar_options[:include])
587
+ .group(@ar_options[:group])
588
+ .where(@options[:conditions])
589
+
590
+ relation = add_references relation
591
+
592
+ relation
593
+ end
594
+ end
595
+
596
+ # not used right now
597
+ # def count_resultset_without_paging_without_user_filters #:nodoc:
598
+ # form_ar_options
599
+ # @klass.unscoped do
600
+ # @relation.count(
601
+ # joins: @ar_options[:joins],
602
+ # include: @ar_options[:include],
603
+ # group: @ar_options[:group],
604
+ # conditions: @options[:conditions]
605
+ # )
606
+ # end
607
+ # end
608
+
609
+ def resultset_without_paging_with_user_filters #:nodoc:
610
+ active_relation_for_resultset_without_paging_with_user_filters.to_a
611
+ end
612
+
613
+ def active_relation_for_resultset_without_paging_with_user_filters #:nodoc:
614
+ form_ar_options
615
+ relation = nil
616
+
617
+ use_default_or_unscoped do
618
+ relation = @relation
619
+ .joins(@ar_options[:joins])
620
+ .includes(@ar_options[:include])
621
+ .order(@ar_options[:order])
622
+ .merge(@ar_options[:conditions])
623
+
624
+ relation = add_references relation
625
+ end
626
+ relation
627
+ end
628
+
629
+ def load_query(query_id) #:nodoc:
630
+ @query_store_model ||= Wice.get_query_store_model
631
+ query = @query_store_model.find_by_id_and_grid_name(query_id, self.name)
632
+ Wice.log("Query with id #{query_id} for grid '#{self.name}' not found!!!") if query.nil?
633
+ query
634
+ end
635
+
636
+ def use_default_or_unscoped #:nodoc:
637
+ if @options[:use_default_scope]
638
+ yield
639
+ else
640
+ @klass.unscoped { yield }
641
+ end
642
+ end
643
+
644
+ end
645
+
646
+ # routines called from WiceGridExtentionToActiveRecordColumn (ActiveRecord::ConnectionAdapters::Column) or ConditionsGeneratorColumn classes
647
+ module GridTools #:nodoc:
648
+ class << self
649
+ def special_value(str) #:nodoc:
650
+ str =~ /^\s*(not\s+)?null\s*$/i
651
+ end
652
+
653
+ # create a Time instance out of parameters
654
+ def params_2_datetime(par) #:nodoc:
655
+ return nil if par.blank?
656
+ params = [par[:year], par[:month], par[:day], par[:hour], par[:minute]].collect { |v| v.blank? ? nil : v.to_i }
657
+ begin
658
+ Time.local(*params)
659
+ rescue ArgumentError, TypeError
660
+ nil
661
+ end
662
+ end
663
+
664
+ # create a Date instance out of parameters
665
+ def params_2_date(par) #:nodoc:
666
+ return nil if par.blank?
667
+ params = [par[:year], par[:month], par[:day]].collect { |v| v.blank? ? nil : v.to_i }
668
+ begin
669
+ Date.civil(*params)
670
+ rescue ArgumentError, TypeError
671
+ nil
672
+ end
673
+ end
674
+ end
675
+ end
676
+ end