pwice_grid 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (389) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +68 -0
  3. data/.circleci/run-build-locally.sh +7 -0
  4. data/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
  5. data/.gitignore +22 -0
  6. data/.inch.yml +3 -0
  7. data/.rspec +3 -0
  8. data/.rubocop.yml +186 -0
  9. data/Appraisals +11 -0
  10. data/CHANGELOG.md +758 -0
  11. data/Gemfile +3 -0
  12. data/Gemfile.lock +298 -0
  13. data/MIT-LICENSE +20 -0
  14. data/README.md +1561 -0
  15. data/Rakefile +49 -0
  16. data/SAVED_QUERIES_HOWTO.md +113 -0
  17. data/app/views/kaminari/wice_grid/_gap.html.erb +1 -0
  18. data/app/views/kaminari/wice_grid/_next_page.html.erb +1 -0
  19. data/app/views/kaminari/wice_grid/_page.html.erb +1 -0
  20. data/app/views/kaminari/wice_grid/_paginator.html.erb +19 -0
  21. data/app/views/kaminari/wice_grid/_prev_page.html.erb +1 -0
  22. data/config/locales/cz.yml +40 -0
  23. data/config/locales/de.yml +42 -0
  24. data/config/locales/en.yml +42 -0
  25. data/config/locales/es.yml +42 -0
  26. data/config/locales/fr.yml +40 -0
  27. data/config/locales/is.yml +41 -0
  28. data/config/locales/it.yml +33 -0
  29. data/config/locales/ja.yml +42 -0
  30. data/config/locales/nl.yml +40 -0
  31. data/config/locales/pt-BR.yml +31 -0
  32. data/config/locales/pt.yml +40 -0
  33. data/config/locales/ru.yml +40 -0
  34. data/config/locales/sk.yml +40 -0
  35. data/config/locales/uk.yml +40 -0
  36. data/config/locales/zh.yml +40 -0
  37. data/gemfiles/rails_5.0.gemfile +7 -0
  38. data/gemfiles/rails_5.0.gemfile.lock +299 -0
  39. data/gemfiles/rails_5.1.gemfile +7 -0
  40. data/gemfiles/rails_5.1.gemfile.lock +299 -0
  41. data/gemfiles/rails_5.2.gemfile +7 -0
  42. data/gemfiles/rails_5.2.gemfile.lock +307 -0
  43. data/lib/generators/wice_grid/add_migration_for_serialized_queries_generator.rb +19 -0
  44. data/lib/generators/wice_grid/install_generator.rb +13 -0
  45. data/lib/generators/wice_grid/templates/create_wice_grid_serialized_queries.rb +13 -0
  46. data/lib/generators/wice_grid/templates/wice_grid_config.rb +191 -0
  47. data/lib/wice/active_record_column_wrapper.rb +122 -0
  48. data/lib/wice/columns.rb +282 -0
  49. data/lib/wice/columns/column_action.rb +51 -0
  50. data/lib/wice/columns/column_boolean.rb +39 -0
  51. data/lib/wice/columns/column_bootstrap_datepicker.rb +47 -0
  52. data/lib/wice/columns/column_custom_dropdown.rb +114 -0
  53. data/lib/wice/columns/column_float.rb +8 -0
  54. data/lib/wice/columns/column_html5_datepicker.rb +30 -0
  55. data/lib/wice/columns/column_integer.rb +87 -0
  56. data/lib/wice/columns/column_jquery_datepicker.rb +48 -0
  57. data/lib/wice/columns/column_processor_index.rb +22 -0
  58. data/lib/wice/columns/column_rails_date_helper.rb +40 -0
  59. data/lib/wice/columns/column_rails_datetime_helper.rb +40 -0
  60. data/lib/wice/columns/column_range.rb +73 -0
  61. data/lib/wice/columns/column_string.rb +91 -0
  62. data/lib/wice/columns/common_date_datetime_mixin.rb +19 -0
  63. data/lib/wice/columns/common_js_date_datetime_conditions_generator_mixin.rb +38 -0
  64. data/lib/wice/columns/common_js_date_datetime_mixin.rb +14 -0
  65. data/lib/wice/columns/common_rails_date_datetime_conditions_generator_mixin.rb +25 -0
  66. data/lib/wice/columns/common_standard_helper_date_datetime_mixin.rb +21 -0
  67. data/lib/wice/grid_output_buffer.rb +48 -0
  68. data/lib/wice/grid_renderer.rb +624 -0
  69. data/lib/wice/helpers/bs_calendar_helpers.rb +73 -0
  70. data/lib/wice/helpers/js_calendar_helpers.rb +82 -0
  71. data/lib/wice/helpers/wice_grid_misc_view_helpers.rb +74 -0
  72. data/lib/wice/helpers/wice_grid_serialized_queries_view_helpers.rb +94 -0
  73. data/lib/wice/helpers/wice_grid_view_helpers.rb +719 -0
  74. data/lib/wice/kaminari_monkey_patching.rb +12 -0
  75. data/lib/wice/table_column_matrix.rb +64 -0
  76. data/lib/wice/wice_grid_controller.rb +174 -0
  77. data/lib/wice/wice_grid_core_ext.rb +145 -0
  78. data/lib/wice/wice_grid_misc.rb +208 -0
  79. data/lib/wice/wice_grid_serialized_queries_controller.rb +86 -0
  80. data/lib/wice/wice_grid_serialized_query.rb +13 -0
  81. data/lib/wice/wice_grid_spreadsheet.rb +19 -0
  82. data/lib/wice_grid.rb +702 -0
  83. data/spec/acceptance_helper.rb +59 -0
  84. data/spec/features/action_column_request_spec.rb +280 -0
  85. data/spec/features/adding_rows_request_spec.rb +21 -0
  86. data/spec/features/all_records_request_spec.rb +18 -0
  87. data/spec/features/auto_reloads2_request_spec.rb +366 -0
  88. data/spec/features/auto_reloads3_request_spec.rb +130 -0
  89. data/spec/features/auto_reloads_request_spec.rb +364 -0
  90. data/spec/features/basics1_request_spec.rb +11 -0
  91. data/spec/features/basics2_request_spec.rb +10 -0
  92. data/spec/features/basics3_request_spec.rb +29 -0
  93. data/spec/features/basics4_request_spec.rb +19 -0
  94. data/spec/features/basics5_request_spec.rb +13 -0
  95. data/spec/features/basics6_request_spec.rb +22 -0
  96. data/spec/features/blockless_column_definition_spec.rb +27 -0
  97. data/spec/features/buttons_request_spec.rb +172 -0
  98. data/spec/features/csv_and_detached_filters_spec.rb +10 -0
  99. data/spec/features/csv_export_request_spec.rb +13 -0
  100. data/spec/features/custom_filter_params_request_spec.rb +29 -0
  101. data/spec/features/custom_filters1_request_spec.rb +136 -0
  102. data/spec/features/custom_filters2_request_spec.rb +31 -0
  103. data/spec/features/custom_filters3_request_spec.rb +34 -0
  104. data/spec/features/custom_filters4_request_spec.rb +13 -0
  105. data/spec/features/custom_ordering_on_calculated_request_spec.rb +30 -0
  106. data/spec/features/custom_ordering_request_spec.rb +36 -0
  107. data/spec/features/custom_ordering_with_arel_request_spec.rb +36 -0
  108. data/spec/features/custom_ordering_with_proc_request_spec.rb +44 -0
  109. data/spec/features/custom_ordering_with_ruby_request_spec.rb +30 -0
  110. data/spec/features/dates_request_spec.rb +56 -0
  111. data/spec/features/detached_filters_spec.rb +10 -0
  112. data/spec/features/detached_filters_two_grids_spec.rb +135 -0
  113. data/spec/features/disable_all_filters_spec.rb +22 -0
  114. data/spec/features/hiding_checkboxes_in_action_column_request_spec.rb +294 -0
  115. data/spec/features/integration_with_application_view_request_spec.rb +43 -0
  116. data/spec/features/integration_with_forms_request_spec.rb +141 -0
  117. data/spec/features/joining_tables_spec.rb +40 -0
  118. data/spec/features/localization_request_spec.rb +24 -0
  119. data/spec/features/many_grids_on_page_request_spec.rb +104 -0
  120. data/spec/features/negation_request_spec.rb +25 -0
  121. data/spec/features/no_records_request_spec.rb +26 -0
  122. data/spec/features/numeric_filters_request_spec.rb +10 -0
  123. data/spec/features/resultset_processings2_request_spec.rb +27 -0
  124. data/spec/features/resultset_processings_request_spec.rb +30 -0
  125. data/spec/features/saved_queries_request_spec.rb +120 -0
  126. data/spec/features/shared.rb +1005 -0
  127. data/spec/features/shared_detached_filters.rb +175 -0
  128. data/spec/features/styling_spec.rb +15 -0
  129. data/spec/features/two_associations_spec.rb +48 -0
  130. data/spec/features/upper_pagination_panel_request_spec.rb +23 -0
  131. data/spec/features/when_filtered_spec.rb +209 -0
  132. data/spec/fixtures/.gitkeep +0 -0
  133. data/spec/fixtures/companies.yml +21 -0
  134. data/spec/fixtures/priorities.yml +31 -0
  135. data/spec/fixtures/project_roles.yml +25 -0
  136. data/spec/fixtures/projects.yml +22 -0
  137. data/spec/fixtures/statuses.yml +55 -0
  138. data/spec/fixtures/tasks.yml +751 -0
  139. data/spec/fixtures/tasks_users.yml +2089 -0
  140. data/spec/fixtures/users.yml +61 -0
  141. data/spec/fixtures/versions.yml +78 -0
  142. data/spec/models/company_spec.rb +6 -0
  143. data/spec/models/priority_spec.rb +6 -0
  144. data/spec/models/project_spec.rb +11 -0
  145. data/spec/models/status_spec.rb +6 -0
  146. data/spec/models/task_spec.rb +12 -0
  147. data/spec/models/user_project_participation_spec.rb +7 -0
  148. data/spec/models/user_spec.rb +12 -0
  149. data/spec/models/version_spec.rb +5 -0
  150. data/spec/rails_helper.rb +15 -0
  151. data/spec/schema.rb +8 -0
  152. data/spec/spec_helper.rb +75 -0
  153. data/spec/support/active_record.rb +10 -0
  154. data/spec/support/test_app/Rakefile +3 -0
  155. data/spec/support/test_app/app/assets/javascripts/application.js +20 -0
  156. data/spec/support/test_app/app/assets/javascripts/common.js.coffee +6 -0
  157. data/spec/support/test_app/app/assets/javascripts/jquery.ui.datepicker.locales.js +56 -0
  158. data/spec/support/test_app/app/assets/stylesheets/adding_rows.scss +3 -0
  159. data/spec/support/test_app/app/assets/stylesheets/application.scss +46 -0
  160. data/spec/support/test_app/app/assets/stylesheets/csv_and_detached_filters.scss +3 -0
  161. data/spec/support/test_app/app/assets/stylesheets/many_grids_on_page.scss +3 -0
  162. data/spec/support/test_app/app/controllers/action_column_controller.rb +15 -0
  163. data/spec/support/test_app/app/controllers/adding_rows_controller.rb +14 -0
  164. data/spec/support/test_app/app/controllers/all_records_controller.rb +14 -0
  165. data/spec/support/test_app/app/controllers/application_controller.rb +99 -0
  166. data/spec/support/test_app/app/controllers/auto_reloads2_controller.rb +14 -0
  167. data/spec/support/test_app/app/controllers/auto_reloads3_controller.rb +20 -0
  168. data/spec/support/test_app/app/controllers/auto_reloads_controller.rb +14 -0
  169. data/spec/support/test_app/app/controllers/basics1_controller.rb +6 -0
  170. data/spec/support/test_app/app/controllers/basics2_controller.rb +6 -0
  171. data/spec/support/test_app/app/controllers/basics3_controller.rb +6 -0
  172. data/spec/support/test_app/app/controllers/basics4_controller.rb +6 -0
  173. data/spec/support/test_app/app/controllers/basics5_controller.rb +6 -0
  174. data/spec/support/test_app/app/controllers/basics6_controller.rb +11 -0
  175. data/spec/support/test_app/app/controllers/blockless_column_definition_controller.rb +6 -0
  176. data/spec/support/test_app/app/controllers/buttons_controller.rb +6 -0
  177. data/spec/support/test_app/app/controllers/csv_and_detached_filters_controller.rb +13 -0
  178. data/spec/support/test_app/app/controllers/csv_export_controller.rb +28 -0
  179. data/spec/support/test_app/app/controllers/custom_filter_params_controller.rb +6 -0
  180. data/spec/support/test_app/app/controllers/custom_filters1_controller.rb +9 -0
  181. data/spec/support/test_app/app/controllers/custom_filters2_controller.rb +14 -0
  182. data/spec/support/test_app/app/controllers/custom_filters3_controller.rb +12 -0
  183. data/spec/support/test_app/app/controllers/custom_filters4_controller.rb +12 -0
  184. data/spec/support/test_app/app/controllers/custom_ordering_controller.rb +18 -0
  185. data/spec/support/test_app/app/controllers/custom_ordering_on_calculated_controller.rb +6 -0
  186. data/spec/support/test_app/app/controllers/custom_ordering_with_arel_controller.rb +18 -0
  187. data/spec/support/test_app/app/controllers/custom_ordering_with_proc_controller.rb +11 -0
  188. data/spec/support/test_app/app/controllers/custom_ordering_with_ruby_controller.rb +6 -0
  189. data/spec/support/test_app/app/controllers/dates_controller.rb +8 -0
  190. data/spec/support/test_app/app/controllers/detached_filters_controller.rb +6 -0
  191. data/spec/support/test_app/app/controllers/detached_filters_two_grids_controller.rb +7 -0
  192. data/spec/support/test_app/app/controllers/disable_all_filters_controller.rb +6 -0
  193. data/spec/support/test_app/app/controllers/hiding_checkboxes_in_action_column_controller.rb +13 -0
  194. data/spec/support/test_app/app/controllers/home_controller.rb +3 -0
  195. data/spec/support/test_app/app/controllers/integration_with_application_view_controller.rb +16 -0
  196. data/spec/support/test_app/app/controllers/integration_with_forms_controller.rb +11 -0
  197. data/spec/support/test_app/app/controllers/joining_tables_controller.rb +11 -0
  198. data/spec/support/test_app/app/controllers/localization_controller.rb +26 -0
  199. data/spec/support/test_app/app/controllers/many_grids_on_page_controller.rb +7 -0
  200. data/spec/support/test_app/app/controllers/negation_controller.rb +14 -0
  201. data/spec/support/test_app/app/controllers/no_records_controller.rb +8 -0
  202. data/spec/support/test_app/app/controllers/null_values_controller.rb +10 -0
  203. data/spec/support/test_app/app/controllers/numeric_filters_controller.rb +6 -0
  204. data/spec/support/test_app/app/controllers/queries_controller.rb +4 -0
  205. data/spec/support/test_app/app/controllers/resultset_processings2_controller.rb +29 -0
  206. data/spec/support/test_app/app/controllers/resultset_processings_controller.rb +30 -0
  207. data/spec/support/test_app/app/controllers/saved_queries_controller.rb +14 -0
  208. data/spec/support/test_app/app/controllers/styling_controller.rb +7 -0
  209. data/spec/support/test_app/app/controllers/tasks_controller.rb +14 -0
  210. data/spec/support/test_app/app/controllers/two_associations_controller.rb +6 -0
  211. data/spec/support/test_app/app/controllers/upper_pagination_panel_controller.rb +6 -0
  212. data/spec/support/test_app/app/controllers/when_filtered_controller.rb +6 -0
  213. data/spec/support/test_app/app/helpers/application_helper.rb +82 -0
  214. data/spec/support/test_app/app/mailers/.gitkeep +0 -0
  215. data/spec/support/test_app/app/models/.gitkeep +0 -0
  216. data/spec/support/test_app/app/models/company.rb +5 -0
  217. data/spec/support/test_app/app/models/populate.rb +84 -0
  218. data/spec/support/test_app/app/models/priority.rb +10 -0
  219. data/spec/support/test_app/app/models/project.rb +14 -0
  220. data/spec/support/test_app/app/models/project_role.rb +3 -0
  221. data/spec/support/test_app/app/models/status.rb +10 -0
  222. data/spec/support/test_app/app/models/task.rb +11 -0
  223. data/spec/support/test_app/app/models/to_dropdown_mixin.rb +16 -0
  224. data/spec/support/test_app/app/models/user.rb +8 -0
  225. data/spec/support/test_app/app/models/user_project_participation.rb +6 -0
  226. data/spec/support/test_app/app/models/version.rb +6 -0
  227. data/spec/support/test_app/app/views/action_column/_grid.html.erb +35 -0
  228. data/spec/support/test_app/app/views/action_column/index.html.haml +45 -0
  229. data/spec/support/test_app/app/views/adding_rows/_grid.html.erb +58 -0
  230. data/spec/support/test_app/app/views/adding_rows/index.html.haml +37 -0
  231. data/spec/support/test_app/app/views/all_records/_grid.html.erb +30 -0
  232. data/spec/support/test_app/app/views/all_records/index.html.haml +12 -0
  233. data/spec/support/test_app/app/views/auto_reloads/_grid.html.erb +32 -0
  234. data/spec/support/test_app/app/views/auto_reloads/index.html.haml +15 -0
  235. data/spec/support/test_app/app/views/auto_reloads2/_grid.html.erb +32 -0
  236. data/spec/support/test_app/app/views/auto_reloads2/index.html.haml +65 -0
  237. data/spec/support/test_app/app/views/auto_reloads3/_grid.html.erb +25 -0
  238. data/spec/support/test_app/app/views/auto_reloads3/index.html.haml +78 -0
  239. data/spec/support/test_app/app/views/basics1/_grid.html.erb +26 -0
  240. data/spec/support/test_app/app/views/basics1/index.html.haml +13 -0
  241. data/spec/support/test_app/app/views/basics2/_grid.html.erb +27 -0
  242. data/spec/support/test_app/app/views/basics2/index.html.haml +12 -0
  243. data/spec/support/test_app/app/views/basics3/_grid.html.erb +28 -0
  244. data/spec/support/test_app/app/views/basics3/index.html.haml +13 -0
  245. data/spec/support/test_app/app/views/basics4/_grid.html.erb +21 -0
  246. data/spec/support/test_app/app/views/basics4/index.html.haml +12 -0
  247. data/spec/support/test_app/app/views/basics5/_grid.html.erb +19 -0
  248. data/spec/support/test_app/app/views/basics5/index.html.haml +12 -0
  249. data/spec/support/test_app/app/views/basics6/_grid.html.erb +19 -0
  250. data/spec/support/test_app/app/views/basics6/index.html.haml +23 -0
  251. data/spec/support/test_app/app/views/blockless_column_definition/_grid.html.erb +19 -0
  252. data/spec/support/test_app/app/views/blockless_column_definition/index.html.haml +15 -0
  253. data/spec/support/test_app/app/views/buttons/_grid.html.erb +20 -0
  254. data/spec/support/test_app/app/views/buttons/index.html.haml +30 -0
  255. data/spec/support/test_app/app/views/csv_and_detached_filters/_grid.html.erb +23 -0
  256. data/spec/support/test_app/app/views/csv_and_detached_filters/index.html.haml +58 -0
  257. data/spec/support/test_app/app/views/csv_export/_projects_grid.html.erb +17 -0
  258. data/spec/support/test_app/app/views/csv_export/_tasks_grid.html.erb +43 -0
  259. data/spec/support/test_app/app/views/csv_export/index.html.haml +90 -0
  260. data/spec/support/test_app/app/views/custom_filter_params/_grid.html.erb +12 -0
  261. data/spec/support/test_app/app/views/custom_filter_params/index.html.haml +12 -0
  262. data/spec/support/test_app/app/views/custom_filters1/_g1.html.erb +8 -0
  263. data/spec/support/test_app/app/views/custom_filters1/_g2.html.erb +9 -0
  264. data/spec/support/test_app/app/views/custom_filters1/_g3.html.erb +9 -0
  265. data/spec/support/test_app/app/views/custom_filters1/_g4.html.erb +8 -0
  266. data/spec/support/test_app/app/views/custom_filters1/index.html.haml +30 -0
  267. data/spec/support/test_app/app/views/custom_filters2/_grid.html.erb +30 -0
  268. data/spec/support/test_app/app/views/custom_filters2/index.html.haml +41 -0
  269. data/spec/support/test_app/app/views/custom_filters3/_grid.html.erb +18 -0
  270. data/spec/support/test_app/app/views/custom_filters3/index.html.haml +16 -0
  271. data/spec/support/test_app/app/views/custom_filters4/_grid.html.erb +20 -0
  272. data/spec/support/test_app/app/views/custom_filters4/index.html.haml +12 -0
  273. data/spec/support/test_app/app/views/custom_ordering/_grid.html.erb +10 -0
  274. data/spec/support/test_app/app/views/custom_ordering/index.html.haml +24 -0
  275. data/spec/support/test_app/app/views/custom_ordering_on_calculated/_grid.html.erb +14 -0
  276. data/spec/support/test_app/app/views/custom_ordering_on_calculated/index.html.haml +23 -0
  277. data/spec/support/test_app/app/views/custom_ordering_with_arel/_grid.html.erb +10 -0
  278. data/spec/support/test_app/app/views/custom_ordering_with_arel/index.html.haml +24 -0
  279. data/spec/support/test_app/app/views/custom_ordering_with_proc/_grid.html.erb +10 -0
  280. data/spec/support/test_app/app/views/custom_ordering_with_proc/index.html.haml +21 -0
  281. data/spec/support/test_app/app/views/custom_ordering_with_ruby/_grid.html.erb +10 -0
  282. data/spec/support/test_app/app/views/custom_ordering_with_ruby/index.html.haml +23 -0
  283. data/spec/support/test_app/app/views/dates/_grid.html.erb +25 -0
  284. data/spec/support/test_app/app/views/dates/index.html.haml +52 -0
  285. data/spec/support/test_app/app/views/detached_filters/_grid.html.erb +23 -0
  286. data/spec/support/test_app/app/views/detached_filters/index.html.haml +79 -0
  287. data/spec/support/test_app/app/views/detached_filters_two_grids/_grid.html.erb +23 -0
  288. data/spec/support/test_app/app/views/detached_filters_two_grids/index.html.haml +85 -0
  289. data/spec/support/test_app/app/views/disable_all_filters/_grid.html.erb +21 -0
  290. data/spec/support/test_app/app/views/disable_all_filters/index.html.haml +14 -0
  291. data/spec/support/test_app/app/views/hiding_checkboxes_in_action_column/_grid.html.erb +34 -0
  292. data/spec/support/test_app/app/views/hiding_checkboxes_in_action_column/index.html.haml +32 -0
  293. data/spec/support/test_app/app/views/integration_with_application_view/_grid.html.erb +27 -0
  294. data/spec/support/test_app/app/views/integration_with_application_view/index.html.haml +33 -0
  295. data/spec/support/test_app/app/views/integration_with_forms/_grid.html.erb +23 -0
  296. data/spec/support/test_app/app/views/integration_with_forms/index.html.haml +18 -0
  297. data/spec/support/test_app/app/views/joining_tables/_grid.html.erb +23 -0
  298. data/spec/support/test_app/app/views/joining_tables/index.html.haml +26 -0
  299. data/spec/support/test_app/app/views/layouts/application.html.haml +61 -0
  300. data/spec/support/test_app/app/views/localization/_grid.html.erb +36 -0
  301. data/spec/support/test_app/app/views/localization/index.html.haml +20 -0
  302. data/spec/support/test_app/app/views/many_grids_on_page/_tasks_grid1.html.erb +12 -0
  303. data/spec/support/test_app/app/views/many_grids_on_page/_tasks_grid2.html.erb +12 -0
  304. data/spec/support/test_app/app/views/many_grids_on_page/index.html.haml +26 -0
  305. data/spec/support/test_app/app/views/negation/_grid.html.erb +30 -0
  306. data/spec/support/test_app/app/views/negation/index.html.haml +15 -0
  307. data/spec/support/test_app/app/views/no_records/_empty_grid.html.haml +1 -0
  308. data/spec/support/test_app/app/views/no_records/_grid1.html.erb +11 -0
  309. data/spec/support/test_app/app/views/no_records/_grid2.html.erb +9 -0
  310. data/spec/support/test_app/app/views/no_records/_grid3.html.erb +9 -0
  311. data/spec/support/test_app/app/views/no_records/index.html.haml +24 -0
  312. data/spec/support/test_app/app/views/null_values/_grid.html.erb +17 -0
  313. data/spec/support/test_app/app/views/null_values/index.html.haml +21 -0
  314. data/spec/support/test_app/app/views/numeric_filters/_grid.html.erb +19 -0
  315. data/spec/support/test_app/app/views/numeric_filters/index.html.haml +12 -0
  316. data/spec/support/test_app/app/views/resultset_processings/_grid.html.erb +27 -0
  317. data/spec/support/test_app/app/views/resultset_processings/index.html.haml +50 -0
  318. data/spec/support/test_app/app/views/resultset_processings2/_grid.html.erb +27 -0
  319. data/spec/support/test_app/app/views/resultset_processings2/index.html.haml +48 -0
  320. data/spec/support/test_app/app/views/saved_queries/_grid.html.erb +30 -0
  321. data/spec/support/test_app/app/views/saved_queries/index.html.haml +15 -0
  322. data/spec/support/test_app/app/views/styling/_grid1.html.erb +12 -0
  323. data/spec/support/test_app/app/views/styling/_grid2.html.erb +31 -0
  324. data/spec/support/test_app/app/views/styling/index.html.haml +65 -0
  325. data/spec/support/test_app/app/views/tasks/_grid.html.erb +19 -0
  326. data/spec/support/test_app/app/views/tasks/index.html.haml +1 -0
  327. data/spec/support/test_app/app/views/two_associations/_grid.html.erb +13 -0
  328. data/spec/support/test_app/app/views/two_associations/index.html.haml +13 -0
  329. data/spec/support/test_app/app/views/upper_pagination_panel/_grid.html.erb +27 -0
  330. data/spec/support/test_app/app/views/upper_pagination_panel/index.html.haml +14 -0
  331. data/spec/support/test_app/app/views/when_filtered/_grid.html.erb +19 -0
  332. data/spec/support/test_app/app/views/when_filtered/index.html.haml +15 -0
  333. data/spec/support/test_app/bin/rails +4 -0
  334. data/spec/support/test_app/bin/rake +4 -0
  335. data/spec/support/test_app/config.ru +5 -0
  336. data/spec/support/test_app/config/application.rb +70 -0
  337. data/spec/support/test_app/config/boot.rb +7 -0
  338. data/spec/support/test_app/config/database.travis.yml +27 -0
  339. data/spec/support/test_app/config/database.yml +16 -0
  340. data/spec/support/test_app/config/database.yml.mysql +19 -0
  341. data/spec/support/test_app/config/database.yml.postgresql +18 -0
  342. data/spec/support/test_app/config/environment.rb +6 -0
  343. data/spec/support/test_app/config/environments/development.rb +34 -0
  344. data/spec/support/test_app/config/environments/production.rb +66 -0
  345. data/spec/support/test_app/config/environments/test.rb +34 -0
  346. data/spec/support/test_app/config/initializers/backtrace_silencers.rb +8 -0
  347. data/spec/support/test_app/config/initializers/inflections.rb +16 -0
  348. data/spec/support/test_app/config/initializers/mime_types.rb +6 -0
  349. data/spec/support/test_app/config/initializers/secret_token.rb +12 -0
  350. data/spec/support/test_app/config/initializers/session_store.rb +9 -0
  351. data/spec/support/test_app/config/initializers/wice_grid_config.rb +163 -0
  352. data/spec/support/test_app/config/initializers/wrap_parameters.rb +15 -0
  353. data/spec/support/test_app/config/locales/en.yml +5 -0
  354. data/spec/support/test_app/config/locales/wice_grid.yml +550 -0
  355. data/spec/support/test_app/config/puma.rb +15 -0
  356. data/spec/support/test_app/config/routes.rb +125 -0
  357. data/spec/support/test_app/db/migrate/20120224193505_create_tasks.rb +27 -0
  358. data/spec/support/test_app/db/migrate/20120224193517_create_users.rb +12 -0
  359. data/spec/support/test_app/db/migrate/20120224193522_create_projects.rb +14 -0
  360. data/spec/support/test_app/db/migrate/20120224193529_create_priorities.rb +13 -0
  361. data/spec/support/test_app/db/migrate/20120224193537_create_statuses.rb +13 -0
  362. data/spec/support/test_app/db/migrate/20120224193543_create_versions.rb +15 -0
  363. data/spec/support/test_app/db/migrate/20120224193550_create_project_roles.rb +12 -0
  364. data/spec/support/test_app/db/migrate/20120224193610_create_companies.rb +12 -0
  365. data/spec/support/test_app/db/migrate/20120224195351_create_user_project_participations.rb +16 -0
  366. data/spec/support/test_app/db/migrate/20120224195521_add_tasks_users.rb +11 -0
  367. data/spec/support/test_app/db/migrate/20120610091944_create_wice_grid_serialized_queries.rb +14 -0
  368. data/spec/support/test_app/db/schema.rb +139 -0
  369. data/spec/support/test_app/db/seeds.rb +10 -0
  370. data/spec/support/test_app/lib/ar_fixtures.rb +100 -0
  371. data/spec/support/test_app/lib/assets/.gitkeep +0 -0
  372. data/spec/support/test_app/lib/tasks/.gitkeep +0 -0
  373. data/spec/support/test_app/lib/tasks/ar_fixtures.rake +45 -0
  374. data/spec/support/test_app/public/404.html +26 -0
  375. data/spec/support/test_app/public/422.html +26 -0
  376. data/spec/support/test_app/public/500.html +25 -0
  377. data/spec/support/test_app/public/favicon.ico +0 -0
  378. data/spec/support/test_app/public/robots.txt +5 -0
  379. data/spec/wice/grid_output_buffer_spec.rb +39 -0
  380. data/spec/wice/table_column_matrix_spec.rb +36 -0
  381. data/spec/wice/wice_grid_misc_spec.rb +157 -0
  382. data/spec/wice/wice_grid_spreadsheet_spec.rb +12 -0
  383. data/vendor/assets/javascripts/wice_grid.js +3 -0
  384. data/vendor/assets/javascripts/wice_grid_init.js.coffee +351 -0
  385. data/vendor/assets/javascripts/wice_grid_processor.js.coffee +133 -0
  386. data/vendor/assets/javascripts/wice_grid_saved_queries_init.js.coffee +104 -0
  387. data/vendor/assets/stylesheets/wice_grid.scss +81 -0
  388. data/wice_grid.gemspec +54 -0
  389. metadata +861 -0
@@ -0,0 +1,40 @@
1
+ module Wice
2
+ module Columns #:nodoc:
3
+ class ViewColumnRailsDateHelper < ViewColumn #:nodoc:
4
+
5
+ include ActionView::Helpers::DateHelper
6
+ include Wice::Columns::CommonDateDatetimeMixin
7
+ include Wice::Columns::CommonStandardDateDatetimeMixin
8
+
9
+ def chunk_names #:nodoc:
10
+ %w(year month day)
11
+ end
12
+
13
+ def do_render(params) #:nodoc:
14
+ '<div class="date-filter">' +
15
+ select_date(params[:fr], include_blank: true, prefix: @name1, id: @dom_id) + '<br/>' +
16
+ select_date(params[:to], include_blank: true, prefix: @name2, id: @dom_id2) +
17
+ '</div>'
18
+ end
19
+
20
+ # name_and_id_from_options in Rails Date helper does not substitute '.' with '_'
21
+ # like all other simpler form helpers do. Thus, overriding it here.
22
+ def name_and_id_from_options(options, type) #:nodoc:
23
+ options[:name] = (options[:prefix] || DEFAULT_PREFIX) + (options[:discard_type] ? '' : "[#{type}]")
24
+ options[:id] = options[:name].gsub(/([\[\(])|(\]\[)/, '_').gsub(/[\]\)]/, '').gsub(/\./, '_').gsub(/_+/, '_')
25
+ end
26
+
27
+
28
+ def has_auto_reloading_calendar? #:nodoc:
29
+ false
30
+ end
31
+
32
+ end
33
+
34
+ class ConditionsGeneratorColumnRailsDateHelper < ConditionsGeneratorColumn #:nodoc:
35
+
36
+ include Wice::Columns::CommonRailsDateDatetimeConditionsGeneratorMixin
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ module Wice
2
+ module Columns #:nodoc:
3
+ class ViewColumnRailsDatetimeHelper < ViewColumn #:nodoc:
4
+
5
+ include ActionView::Helpers::DateHelper
6
+ include Wice::Columns::CommonDateDatetimeMixin
7
+ include Wice::Columns::CommonStandardDateDatetimeMixin
8
+
9
+ def chunk_names #:nodoc:
10
+ %w(year month day hour minute)
11
+ end
12
+
13
+ def do_render(params) #:nodoc:
14
+ datetime_options = filter_control_options ? filter_control_options.slice(:start_year, :end_year, :max_year_allowed) : {}
15
+ '<div class="date-filter">' +
16
+ select_datetime(params[:fr], datetime_options.merge(include_blank: true, prefix: @name1)) + '<br/>' +
17
+ select_datetime(params[:to], datetime_options.merge(include_blank: true, prefix: @name2)) +
18
+ '</div>'
19
+ end
20
+
21
+ # name_and_id_from_options in Rails Date helper does not substitute '.' with '_'
22
+ # like all other simpler form helpers do. Thus, overriding it here.
23
+ def name_and_id_from_options(options, type) #:nodoc:
24
+ options[:name] = (options[:prefix] || DEFAULT_PREFIX) + (options[:discard_type] ? '' : "[#{type}]")
25
+ options[:id] = options[:name].gsub(/([\[\(])|(\]\[)/, '_').gsub(/[\]\)]/, '').gsub(/\./, '_').gsub(/_+/, '_')
26
+ end
27
+
28
+ def has_auto_reloading_calendar? #:nodoc:
29
+ false
30
+ end
31
+
32
+ end
33
+
34
+ class ConditionsGeneratorColumnRailsDatetimeHelper < ConditionsGeneratorColumn #:nodoc:
35
+
36
+ include Wice::Columns::CommonRailsDateDatetimeConditionsGeneratorMixin
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,73 @@
1
+ module Wice
2
+ module Columns #:nodoc:
3
+ class ViewColumnRange < ViewColumn #:nodoc:
4
+ def render_filter_internal(params) #:nodoc:
5
+ @contains_a_text_input = true
6
+
7
+ @query, _, parameter_name, @dom_id = form_parameter_name_id_and_query(fr: '')
8
+ @query2, _, parameter_name2, @dom_id2 = form_parameter_name_id_and_query(to: '')
9
+
10
+ opts1 = { size: 2, id: @dom_id, class: 'form-control input-sm range-start' }
11
+ opts2 = { size: 2, id: @dom_id2, class: 'form-control input-sm range-end' }
12
+
13
+ if auto_reload
14
+ opts1[:class] += ' auto-reload'
15
+ opts2[:class] += ' auto-reload'
16
+ end
17
+
18
+ content_tag(
19
+ :div,
20
+ text_field_tag(parameter_name, params[:fr], opts1) + text_field_tag(parameter_name2, params[:to], opts2),
21
+ class: 'form-inline')
22
+ end
23
+
24
+ def yield_declaration_of_column_filter #:nodoc:
25
+ {
26
+ templates: [@query, @query2],
27
+ ids: [@dom_id, @dom_id2]
28
+ }
29
+ end
30
+
31
+ def has_auto_reloading_input? #:nodoc:
32
+ auto_reload
33
+ end
34
+ end
35
+
36
+ class ConditionsGeneratorColumnRange < ConditionsGeneratorColumn #:nodoc:
37
+ def generate_conditions(table_alias, opts) #:nodoc:
38
+ unless opts.is_a? Hash
39
+ Wice.log 'invalid parameters for the grid integer filter - must be a hash'
40
+ return false
41
+ end
42
+ conditions = [[]]
43
+ if opts[:fr]
44
+ fr_num = ConditionsGeneratorColumnInteger.get_value(opts[:fr])
45
+ if fr_num
46
+ conditions[0] << " #{@column_wrapper.alias_or_table_name(table_alias)}.#{@column_wrapper.name} >= ? "
47
+ conditions << fr_num
48
+ else
49
+ opts.delete(:fr)
50
+ end
51
+ end
52
+
53
+ if opts[:to]
54
+ to_num = ConditionsGeneratorColumnInteger.get_value(opts[:to])
55
+ if to_num
56
+ conditions[0] << " #{@column_wrapper.alias_or_table_name(table_alias)}.#{@column_wrapper.name} <= ? "
57
+ conditions << to_num
58
+ else
59
+ opts.delete(:to)
60
+ end
61
+ end
62
+
63
+ if conditions.size == 1
64
+ return false
65
+ end
66
+
67
+ conditions[0] = conditions[0].join(' and ')
68
+
69
+ conditions
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,91 @@
1
+ module Wice
2
+ module Columns #:nodoc:
3
+ class ViewColumnString < ViewColumn #:nodoc:
4
+
5
+ # whether the filter contains a negation checkbox
6
+ attr_accessor :negation
7
+
8
+ # whether the filter contains a negation checkbox and autoreloading is necessary
9
+ attr_accessor :auto_reloading_input_with_negation_checkbox
10
+
11
+ def render_filter_internal(params) #:nodoc:
12
+ @contains_a_text_input = true
13
+ css_class = 'form-control input-sm ' + (auto_reload ? 'auto-reload' : '')
14
+
15
+ if negation
16
+ self.auto_reloading_input_with_negation_checkbox = true if auto_reload
17
+
18
+ @query, _, parameter_name, @dom_id = form_parameter_name_id_and_query(v: '')
19
+ @query2, _, parameter_name2, @dom_id2 = form_parameter_name_id_and_query(n: '')
20
+
21
+ '<div class="text-filter-container">' +
22
+ text_field_tag(parameter_name, params[:v], size: 8, id: @dom_id, class: css_class) +
23
+ if defined?(Wice::Defaults::NEGATION_CHECKBOX_LABEL) && !Wice::ConfigurationProvider.value_for(:NEGATION_CHECKBOX_LABEL).blank?
24
+ Wice::ConfigurationProvider.value_for(:NEGATION_CHECKBOX_LABEL)
25
+ else
26
+ ''
27
+ end +
28
+ check_box_tag(parameter_name2, '1', (params[:n] == '1'),
29
+ id: @dom_id2,
30
+ title: NlMessage['negation_checkbox_title'],
31
+ class: "negation-checkbox #{css_class}") +
32
+ '</div>'
33
+ else
34
+ @query, _, parameter_name, @dom_id = form_parameter_name_id_and_query('')
35
+ text_field_tag(parameter_name, (params.blank? ? '' : params), size: 8, id: @dom_id, class: css_class)
36
+ end
37
+ end
38
+
39
+ def yield_declaration_of_column_filter #:nodoc:
40
+ if negation
41
+ {
42
+ templates: [@query, @query2],
43
+ ids: [@dom_id, @dom_id2]
44
+ }
45
+ else
46
+ {
47
+ templates: [@query],
48
+ ids: [@dom_id]
49
+ }
50
+ end
51
+ end
52
+
53
+ def has_auto_reloading_input? #:nodoc:
54
+ auto_reload
55
+ end
56
+
57
+ def auto_reloading_input_with_negation_checkbox? #:nodoc:
58
+ self.auto_reloading_input_with_negation_checkbox
59
+ end
60
+ end
61
+
62
+ class ConditionsGeneratorColumnString < ConditionsGeneratorColumn #:nodoc:
63
+ def generate_conditions(table_alias, opts) #:nodoc:
64
+ if opts.is_a? String
65
+ string_fragment = opts
66
+ negation = ''
67
+ elsif (opts.is_a? Hash) && opts.key?(:v)
68
+ string_fragment = opts[:v]
69
+ negation = opts[:n] == '1' ? 'NOT' : ''
70
+ else
71
+ Wice.log "invalid parameters for the grid string filter - must be a string: #{opts.inspect} or a Hash with keys :v and :n"
72
+ return false
73
+ end
74
+ if string_fragment.empty?
75
+ return false
76
+ end
77
+
78
+ string_matching_operator = ::Wice.get_string_matching_operators(@column_wrapper.model)
79
+
80
+ comparator = if string_matching_operator == 'CI_LIKE'
81
+ " #{negation} UPPER(#{@column_wrapper.alias_or_table_name(table_alias)}.#{@column_wrapper.name}) LIKE UPPER(?)"
82
+ else
83
+ " #{negation} #{@column_wrapper.alias_or_table_name(table_alias)}.#{@column_wrapper.name} #{string_matching_operator} ?"
84
+ end
85
+
86
+ [ comparator, '%' + string_fragment + '%' ]
87
+
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,19 @@
1
+ module Wice
2
+ module Columns #:nodoc:
3
+ module CommonDateDatetimeMixin #:nodoc:
4
+
5
+ def render_filter_internal(params) #:nodoc:
6
+ prepare
7
+ do_render(params)
8
+ end
9
+
10
+ def yield_declaration_of_column_filter #:nodoc:
11
+ {
12
+ templates: @queris_ids.collect { |tuple| tuple[0] },
13
+ ids: @queris_ids.collect { |tuple| tuple[1] }
14
+ }
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,38 @@
1
+ module Wice
2
+ module Columns #:nodoc:
3
+ module CommonJsDateDatetimeConditionsGeneratorMixin #:nodoc:
4
+
5
+ def generate_conditions(table_alias, opts) #:nodoc:
6
+
7
+ datetime = @column_type == :datetime || @column_type == :timestamp
8
+
9
+ conditions = [[]]
10
+ if opts[:fr]
11
+ conditions[0] << " #{@column_wrapper.alias_or_table_name(table_alias)}.#{@column_wrapper.name} >= ? "
12
+ date = opts[:fr].to_date
13
+ if datetime
14
+ date = date.to_datetime
15
+ end
16
+ conditions << date
17
+ end
18
+
19
+ if opts[:to]
20
+ op = '<='
21
+ date = opts[:to].to_date
22
+ if datetime
23
+ date = (date + 1).to_datetime
24
+ op = '<'
25
+ end
26
+ conditions[0] << " #{@column_wrapper.alias_or_table_name(table_alias)}.#{@column_wrapper.name} #{op} ? "
27
+ conditions << date
28
+ end
29
+
30
+ return false if conditions.size == 1
31
+
32
+ conditions[0] = conditions[0].join(' and ')
33
+ conditions
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,14 @@
1
+ module Wice
2
+ module Columns #:nodoc:
3
+ module CommonJsDateDatetimeMixin #:nodoc:
4
+
5
+ def prepare #:nodoc:
6
+ query, _, @name1, @dom_id = form_parameter_name_id_and_query(fr: '')
7
+ query2, _, @name2, @dom_id2 = form_parameter_name_id_and_query(to: '')
8
+
9
+ @queris_ids = [[query, @dom_id], [query2, @dom_id2]]
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,25 @@
1
+ module Wice
2
+ module Columns #:nodoc:
3
+ module CommonRailsDateDatetimeConditionsGeneratorMixin #:nodoc:
4
+
5
+ def generate_conditions(table_alias, opts) #:nodoc:
6
+ conditions = [[]]
7
+ if opts[:fr]
8
+ conditions[0] << " #{@column_wrapper.alias_or_table_name(table_alias)}.#{@column_wrapper.name} >= ? "
9
+ conditions << opts[:fr].to_date
10
+ end
11
+
12
+ if opts[:to]
13
+ conditions[0] << " #{@column_wrapper.alias_or_table_name(table_alias)}.#{@column_wrapper.name} <= ? "
14
+ conditions << (opts[:to].to_date + 1)
15
+ end
16
+
17
+ return false if conditions.size == 1
18
+
19
+ conditions[0] = conditions[0].join(' and ')
20
+ conditions
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ module Wice
2
+ module Columns #:nodoc:
3
+ module CommonStandardDateDatetimeMixin #:nodoc:
4
+
5
+ def prepare #:nodoc:
6
+ x = lambda do|sym|
7
+ chunk_names.map do|datetime_chunk_name|
8
+ triple = form_parameter_name_id_and_query(sym => { datetime_chunk_name => '' })
9
+ [triple[0], triple[3]]
10
+ end
11
+ end
12
+
13
+ @queris_ids = x.call(:fr) + x.call(:to)
14
+
15
+ _, _, @name1, _ = form_parameter_name_id_and_query(fr: '')
16
+ _, _, @name2, _ = form_parameter_name_id_and_query(to: '')
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,48 @@
1
+ module Wice
2
+ class GridOutputBuffer < String #:nodoc:
3
+
4
+ # defines behavior for rendering nonexistent filters.
5
+ # If return_empty_strings_for_nonexistent_filters is true, a call to render a non existent filter will raise an exception
6
+ # If return_empty_strings_for_nonexistent_filters is false (CSV mode), no exception will be raised.
7
+ attr_accessor :return_empty_strings_for_nonexistent_filters
8
+
9
+ # initializes a grid output buffer
10
+ def initialize(*attrs)
11
+ super(*attrs)
12
+ @filters = HashWithIndifferentAccess.new
13
+ end
14
+
15
+ # returns HTML code the grid
16
+ def to_s
17
+ super.html_safe
18
+ end
19
+
20
+ # stores HTML code for a detached filter
21
+ def add_filter(detach_with_id, filter_code)
22
+ raise WiceGridException.new("Detached ID #{detach_with_id} is already used!") if @filters.key? detach_with_id
23
+ @filters[detach_with_id] = filter_code
24
+ end
25
+
26
+ # returns HTML code for a detached filter
27
+ def filter_for(detach_with_id)
28
+ unless @filters.key? detach_with_id
29
+ if @return_empty_strings_for_nonexistent_filters
30
+ return ''
31
+ else
32
+ raise WiceGridException.new("No filter with Detached ID '#{detach_with_id}'!")
33
+ end
34
+ end
35
+
36
+ unless @filters[detach_with_id]
37
+ raise WiceGridException.new("Filter with Detached ID '#{detach_with_id}' has already been requested once! There cannot be two instances of the same filter on one page")
38
+ end
39
+
40
+ res = @filters[detach_with_id]
41
+ @filters[detach_with_id] = false
42
+ res
43
+ end
44
+
45
+ # returns HTML code for a detached filter
46
+ alias_method :[], :filter_for
47
+ end
48
+ end
@@ -0,0 +1,624 @@
1
+ module Wice
2
+
3
+ # Instance of `GridRenderer` is injected into the top level block of the `grid` helper.
4
+ # `g.column`, `g.action_column` are all examples of methods of `GridRenderer`
5
+ class GridRenderer
6
+ include ActionView::Helpers::TagHelper
7
+ include ActionView::Helpers::CaptureHelper
8
+ include ActionView::Helpers::TextHelper
9
+ include ActionView::Helpers::AssetTagHelper
10
+ include ActionView::Helpers::JavaScriptHelper
11
+
12
+ # a Proc object for the after_row block
13
+ attr_reader :after_row_handler
14
+
15
+ # a Proc object for the before_row block
16
+ attr_reader :before_row_handler
17
+
18
+ # a Proc object for the replace_row block
19
+ attr_reader :replace_row_handler
20
+
21
+ # Configuration or a Proc object for the blank_slate block
22
+ attr_reader :blank_slate_handler
23
+
24
+ # a Proc object which returns contents of the last row
25
+ attr_reader :last_row_handler
26
+
27
+ # reference to the WiceGrid instance
28
+ attr_reader :grid
29
+
30
+ # Contents of <caption></caption>
31
+ attr_reader :kaption
32
+
33
+ # HTTP parameter for the order field
34
+ ORDER_PARAMETER_NAME = 'order'
35
+
36
+ # HTTP parameter for the order direction (asc/desc)
37
+ ORDER_DIRECTION_PARAMETER_NAME = 'order_direction'
38
+
39
+ def initialize(grid, view) #:nodoc:
40
+ @grid = grid
41
+ @grid.renderer = self
42
+ @columns = []
43
+ @columns_table = {}
44
+ @action_column_present = false
45
+ @view = view
46
+ end
47
+
48
+ def config #:nodoc:
49
+ @view.config
50
+ end
51
+
52
+ def controller #:nodoc:
53
+ @view.controller
54
+ end
55
+
56
+ def add_column(vc) #:nodoc:
57
+ @columns_table[vc.fully_qualified_attribute_name] = vc if vc.attribute
58
+ @columns << vc
59
+ end
60
+
61
+ def [](k) #:nodoc:
62
+ @columns_table[k]
63
+ end
64
+
65
+ def number_of_columns(filter = nil) #:nodoc:
66
+ filter_columns(filter).size
67
+ end
68
+
69
+ def each_column_label(filter = nil) #:nodoc:
70
+ filter_columns(filter).each { |col| yield col.name }
71
+ end
72
+
73
+ def column_labels(filter = nil) #:nodoc:
74
+ filter_columns(filter).collect(&:name)
75
+ end
76
+
77
+ def each_column(filter = nil) #:nodoc:
78
+ filter_columns(filter).each { |col| yield col }
79
+ end
80
+
81
+ def each_column_aware_of_one_last_one(filter = nil) #:nodoc:
82
+ cols = filter_columns(filter)
83
+ cols[0..-2].each { |col| yield col, false }
84
+ yield cols.last, true
85
+ end
86
+
87
+ def last_column_for_html #:nodoc:
88
+ filter_columns(:in_html).last
89
+ end
90
+
91
+ def select_for(filter) #:nodoc:
92
+ filter_columns(filter).select { |col| yield col }
93
+ end
94
+
95
+ def find_one_for(filter) #:nodoc:
96
+ filter_columns(filter).find { |col| yield col }
97
+ end
98
+
99
+ def each_column_with_attribute #:nodoc:
100
+ @columns.select(&:attribute).each { |col| yield col }
101
+ end
102
+
103
+ alias_method :each, :each_column
104
+ include Enumerable
105
+
106
+ def csv_export_icon #:nodoc:
107
+ content_tag(
108
+ :div,
109
+ content_tag(:i, '', class: 'fa fa-file-csv'),
110
+ title: NlMessage['csv_export_tooltip'],
111
+ class: 'clickable export-to-csv-button'
112
+ )
113
+ end
114
+
115
+ def pagination_panel(number_of_columns, hide_csv_button) #:nodoc:
116
+ panel = yield
117
+
118
+ render_csv_button = @grid.export_to_csv_enabled && !hide_csv_button
119
+
120
+ if panel.nil?
121
+ if render_csv_button
122
+ "<tr><td colspan=\"#{number_of_columns}\"></td><td>#{csv_export_icon}</td></tr>"
123
+ else
124
+ ''
125
+ end
126
+ else
127
+ if render_csv_button
128
+ "<tr><td colspan=\"#{number_of_columns}\">#{panel}</td><td>#{csv_export_icon}</td></tr>"
129
+ else
130
+ "<tr><td colspan=\"#{number_of_columns + 1}\">#{panel}</td></tr>"
131
+ end
132
+ end
133
+ end
134
+
135
+ # Takes one argument and adds the <caption></caption> tag to the table with the
136
+ # argument value as the contents of <caption>.
137
+ def caption(kaption)
138
+ @kaption = kaption
139
+ end
140
+
141
+ # Adds a column with checkboxes for each record. Useful for actions with multiple records, for example, deleting
142
+ # selected records. Please note that +action_column+ only creates the checkboxes and the 'Select All' and
143
+ # 'Deselect All' buttons, and the form itelf as well as processing the parameters should be taken care of
144
+ # by the application code.
145
+ #
146
+ # * <tt>:param_name</tt> - The name of the HTTP parameter.
147
+ # The complete HTTP parameter is <tt>"#{grid_name}[#{param_name}][]"</tt>.
148
+ # The default param_name is 'selected'.
149
+ # * <tt>:html</tt> - a hash of HTML attributes to be included into the <tt>td</tt> tag.
150
+ # * <tt>:select_all_buttons</tt> - show/hide buttons 'Select All' and 'Deselect All' in the column header.
151
+ # The default is +true+.
152
+ # * <tt>:object_property</tt> - a method used to obtain the value for the HTTP parameter. The default is +id+.
153
+ # * <tt>:html_check_box</tt> - can be used to switch from a real check box to two images. The default is +true+.
154
+ #
155
+ # You can hide a certain action checkbox if you add the usual block to +g.action_column+, just like with the
156
+ # +g.column+ definition. If the block returns +nil+ or +false+ no checkbox will be rendered.
157
+
158
+ def action_column(opts = {}, &block)
159
+ if @action_column_present
160
+ raise Wice::WiceGridException.new('There can be only one action column in a WiceGrid')
161
+ end
162
+
163
+ options = {
164
+ param_name: :selected,
165
+ html: {},
166
+ select_all_buttons: true,
167
+ object_property: :id,
168
+ html_check_box: true
169
+ }
170
+
171
+ opts.assert_valid_keys(options.keys)
172
+ options.merge!(opts)
173
+ @action_column_present = true
174
+ column_processor_klass = Columns.get_view_column_processor(:action)
175
+
176
+ @columns << column_processor_klass.new(
177
+ @grid,
178
+ options[:html],
179
+ options[:param_name],
180
+ options[:select_all_buttons],
181
+ options[:object_property],
182
+ options[:html_check_box],
183
+ @view,
184
+ block
185
+ )
186
+ end
187
+
188
+ # Defines everything related to a column in a grid - column name, filtering, rendering cells, etc.
189
+ #
190
+ # +column+ is only used inside the block of the +grid+ method. See documentation for the +grid+ method for more details.
191
+ #
192
+ # The only parameter is a hash of options. None of them is optional. If no options are supplied, the result will be a
193
+ # column with no name, no filtering and no sorting.
194
+ #
195
+ # * <tt>:name</tt> - Name of the column.
196
+ # * <tt>:html</tt> - a hash of HTML attributes to be included into the <tt>td</tt> tag.
197
+ # * <tt>:class</tt> - a shortcut for <tt>html: {class: 'css_class'}</tt>
198
+ # * <tt>:attribute</tt> - name of a database column (which normally correspond to a model attribute with the
199
+ # same name). By default the field is assumed to belong to the default table (see documentation for the
200
+ # +initialize_grid+ method). Parameter <tt>:assoc</tt> (association) allows to specify another joined table. Presence of
201
+ # this parameter
202
+ # * adds sorting capabilities by this field
203
+ # * automatically creates a filter based on the type of the field unless parameter <tt>:filter</tt> is set to false.
204
+ # The following filters exist for the following types:
205
+ # * <tt>string</tt> - a text field
206
+ # * <tt>integer</tt> and <tt>float</tt> - two text fields to specify the range. Both limits or only one
207
+ # can be specified
208
+ # * <tt>boolean</tt> - a dropdown list with 'yes', 'no', or '-'. These labels can be changed in
209
+ # <tt>lib/wice_grid_config.rb</tt>.
210
+ # * <tt>date</tt> - two sets of standard date dropdown lists so specify the time range.
211
+ # * <tt>datetime</tt> - two sets of standard datetime dropdown lists so specify the time range. This filter
212
+ # is far from being user-friendly due to the number of dropdown lists.
213
+ # * <tt>:filter</tt> - Disables filters when set to false.
214
+ # This is needed if sorting is required while filters are not.
215
+ # * <tt>:filter_type</tt> - Using a column filter different from the default filter chosen automatically based on the
216
+ # data type or the <tt>:custom_filter</tt> argument. See <tt>lib/columns/column_processor_index.rb</tt> for the
217
+ # list of available filters.
218
+ # * <tt>:filter_control_options</tt> - Additional options to pass to the filter class to change the filter control
219
+ # behaviour. Supported options are dependent on the filter used.
220
+ # This is needed if sorting is required while filters are not.
221
+ # * <tt>:ordering</tt> - Enable/disable ordering links in the column titles. The default is +true+
222
+ # (i.e. if <tt>:attribute</tt> is defined, ordering is enabled)
223
+ # * <tt>:assoc</tt> - Name of the model association. <tt>:attribute</tt> belongs to the table joined via this association.
224
+ # * <tt>:table_alias</tt> - In case there are two joined assocations both referring to the same table, ActiveRecord
225
+ # constructs a query where the second join provides an alias for the joined table. Setting <tt>:table_alias</tt>
226
+ # to this alias will enable WiceGrid to order and filter by columns belonging to different associatiations but
227
+ # originating from the same table without confusion. See README for an example.
228
+ # * <tt>:custom_filter</tt> - Allows to construct a custom dropdown filter. Depending on the value of
229
+ # <tt>:custom_filter</tt> different modes are available:
230
+ # * array of strings and/or numbers - this is a direct definition of possible values of the dropdown.
231
+ # Every item will be used both as the value of the select option and as its label.
232
+ # * Array of two-element arrays - Every first item of the two-element array is used for the label of the select option
233
+ # while the second element is the value of the select option
234
+ # * Hash - The keys of the hash become the labels of the generated dropdown list,
235
+ # while the values will be values of options of the dropdown list:
236
+ # * <tt>:auto</tt> - a powerful option which populates the dropdown list with all unique values of the field specified by
237
+ # <tt>:attribute</tt> and <tt>:model</tt>.
238
+ # <tt>:attribute</tt> throughout all pages. In other words, this runs an SQL query without +offset+ and +limit+
239
+ # clauses and with <tt>distinct(table.field)</tt> instead of <tt>distinct(*)</tt>
240
+ # * any other symbol name (method name) - The dropdown list is populated by all unique value returned by the
241
+ # method with this name sent to <em>all</em> ActiveRecord objects throughout all pages. The main difference
242
+ # from <tt>:auto</tt> is that this method does not have to be a field in the result set, it is just some
243
+ # value computed in the method after the database call and ActiveRecord instantiation.
244
+ #
245
+ # But here lies the major drawback - this mode requires additional query without +offset+ and +limit+
246
+ # clauses to instantiate _all_ ActiveRecord objects, and performance-wise it brings all the advantages
247
+ # of pagination to nothing. Thus, memory- and performance-wise this can be really bad for some queries
248
+ # and tables and should be used with care.
249
+ #
250
+ # If the method returns a atomic value like a string or an integer, it is used for both the value and the
251
+ # label of the select option element. However, if the retuned value is a two element array, the first element
252
+ # is used for the option label and the second - for the value.
253
+ # Read more in README, section 'Custom dropdown filters'
254
+ # * An array of symbols (method names) - similar to the mode with a single symbol name. The first method name
255
+ # is sent to the ActiveRecord object if it responds to this method, the second method name is sent to the
256
+ # returned value unless it is +nil+, and so on. In other words, a single symbol mode is a
257
+ # case of an array of symbols where the array contains just one element. Thus the warning about the single method name
258
+ # mode applies here as well.
259
+ #
260
+ # If the last method returns a atomic value like a string or an integer, it is used for both the value and the
261
+ # label of the select option element.
262
+ # However, if the retuned value is a two element array, the first element is used for the option label and the
263
+ # second - for the value.
264
+ # Read more in README, section 'Custom dropdown filters'
265
+ # * <tt>:sort_by</tt> - allows arbitrary sorting of the results. This option takes a Proc which returns a value to
266
+ # sort by. When this option is used and sorting on this column is activated, the entire resultset is loaded and
267
+ # the Proc is passed to Enumerable#sort_by. This can also be used with calculated columns, but an arbitrary
268
+ # <tt>:attribute</tt> option must be included to provide a request parameter key. Because this option will load
269
+ # the entire resultset, it should only be used with small resultsets. The <tt>:custom_order</tt> option on grid
270
+ # initialization should be preferred if possible, as it will perform the sorting in SQL.
271
+ # * <tt>:boolean_filter_true_label</tt> - overrides the label for <tt>true</tt> in the boolean filter (<tt>wice_grid.boolean_filter_true_label</tt> in <tt>wice_grid.yml</tt>).
272
+ # * <tt>:boolean_filter_false_label</tt> - overrides the label for <tt>false</tt> in the boolean filter (<tt>wice_grid.boolean_filter_false_label</tt> in <tt>wice_grid.yml</tt>).
273
+ # * <tt>:allow_multiple_selection</tt> - enables or disables switching between single and multiple selection modes for
274
+ # custom dropdown boxes. +true+ by default (see +ALLOW_MULTIPLE_SELECTION+ in the configuration file).
275
+ # * <tt>:filter_all_label</tt> - overrides the default value for <tt>BOOLEAN_FILTER_FALSE_LABEL</tt> ('<tt>--</tt>')
276
+ # in the config. Has effect in a column with a boolean filter _or_ a custom filter.
277
+ # * <tt>:detach_with_id</tt> - allows to detach the filter and render it after or before the grid with the
278
+ # +grid_filter+ helper. The value is an arbitrary unique identifier
279
+ # of the filter. Read section 'Detached Filters' in README for details.
280
+ # Has effect in a column with a boolean filter _or_ a custom filter.
281
+ # * <tt>:in_csv</tt> - When CSV export is enabled, all columns are included into the export. Setting <tt>:in_csv</tt>
282
+ # to false will prohibit the column from inclusion into the export.
283
+ # * <tt>:in_html</tt> - When CSV export is enabled and it is needed to use a column for CSV export only and ignore it
284
+ # in HTML, set this parameter to false.
285
+ # * <tt>:negation</tt> - turn on/off the negation checkbox in string filters
286
+ # * <tt>:auto_reload</tt> - a boolean value specifying if a change in a filter triggers reloading of the grid. Works with all
287
+ # filter types including the JS calendar, the only exception is the standard Rails date/datetime filters.
288
+ # The default is false. (see +AUTO_RELOAD+ in the configuration file).
289
+ #
290
+ # The block parameter is an ActiveRecord instance. This block is called for every ActiveRecord shown, and the return
291
+ # value of the block is a string which becomes the contents of one table cell, or an array of two elements where
292
+ # the first element is the cell contents and the second is a hash of HTML attributes to be added for the <tt><td></tt>
293
+ # tag of the current cell.
294
+ #
295
+ # In case of an array output, please note that if you need to define HTML attributes for all <tt><td></tt>'s in a
296
+ # column, use +html+. Also note that if the method returns a hash with a <tt>:class</tt> or <tt>'class'</tt>
297
+ # element, it will not overwrite the class defined in +html+, or classes added by the grid itself
298
+ # (+active-filter+ and +sorted+), instead they will be all concatenated:
299
+ # <tt><td class="sorted user_class_for_columns user_class_for_this_specific_cell"></tt>
300
+ #
301
+ # It is up to the developer to make sure that what in rendered in column cells
302
+ # corresponds to sorting and filtering specified by parameters <tt>:attribute</tt> and <tt>:model</tt>.
303
+
304
+ def column(opts = {}, &block)
305
+ options = {
306
+ allow_multiple_selection: ConfigurationProvider.value_for(:ALLOW_MULTIPLE_SELECTION),
307
+ assoc: nil,
308
+ attribute: nil,
309
+ auto_reload: ConfigurationProvider.value_for(:AUTO_RELOAD),
310
+ boolean_filter_false_label: NlMessage['boolean_filter_false_label'],
311
+ boolean_filter_true_label: NlMessage['boolean_filter_true_label'],
312
+ class: nil,
313
+ custom_filter: nil,
314
+ detach_with_id: nil,
315
+ filter: true,
316
+ filter_all_label: ConfigurationProvider.value_for(:CUSTOM_FILTER_ALL_LABEL),
317
+ filter_control_options: {},
318
+ filter_type: nil,
319
+ html: {},
320
+ in_csv: true,
321
+ in_html: true,
322
+ model: nil, # will throw an exception with instructions
323
+ name: '',
324
+ negation: ConfigurationProvider.value_for(:NEGATION_IN_STRING_FILTERS),
325
+ ordering: true,
326
+ table_alias: nil,
327
+ sort_by: nil,
328
+ }
329
+
330
+ opts.assert_valid_keys(options.keys)
331
+ options.merge!(opts)
332
+
333
+ assocs = nil
334
+
335
+ if options[:model]
336
+ raise WiceGridArgumentError.new('Instead of specifying a model of a joined table please use assoc: :name_of_association')
337
+ end
338
+
339
+ unless options[:assoc].nil?
340
+
341
+ unless options[:assoc].is_a?(Symbol) ||
342
+ (options[:assoc].is_a?(Array) && ! options[:assoc].empty? && options[:assoc].all?{ |assoc| assoc.is_a?(Symbol)})
343
+
344
+ raise WiceGridArgumentError.new('Option :assoc can only be a symbol or an array of symbols')
345
+ end
346
+
347
+ assocs = options[:assoc].is_a?(Symbol) ? [options[:assoc]] : options[:assoc]
348
+
349
+ options[:model] = get_model_from_associations(@grid.klass, assocs)
350
+ end
351
+
352
+ if options[:attribute].nil? && options[:model]
353
+ raise WiceGridArgumentError.new('Option :assoc is only used together with :attribute')
354
+ end
355
+
356
+ if options[:attribute] && options[:attribute].index('.')
357
+ raise WiceGridArgumentError.new("Invalid attribute name #{options[:attribute]}. An attribute name must not contain a table name!")
358
+ end
359
+
360
+
361
+ if options[:class]
362
+ options[:html] ||= {}
363
+ Wice::WgHash.add_or_append_class_value!(options[:html], options[:class])
364
+ options.delete(:class)
365
+ end
366
+
367
+ if block.nil?
368
+ if !options[:attribute].blank?
369
+ if assocs.nil?
370
+ block = ->(obj) { obj.send(options[:attribute]) }
371
+ else
372
+ messages = assocs + [ options[:attribute] ]
373
+ block = ->(obj) { obj.deep_send(*messages) }
374
+ end
375
+ else
376
+ raise WiceGridArgumentError.new(
377
+ 'Missing column block without attribute defined. You can only omit the block if attribute is present.')
378
+ end
379
+ end
380
+
381
+ klass = Columns::ViewColumn
382
+ if options[:attribute] &&
383
+ col_type_and_table_name = @grid.declare_column(
384
+ column_name: options[:attribute],
385
+ model: options[:model],
386
+ custom_filter_active: options[:custom_filter],
387
+ table_alias: options[:table_alias],
388
+ filter_type: options[:filter_type],
389
+ assocs: assocs,
390
+ sort_by: options[:sort_by],
391
+ )
392
+
393
+ # [ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::Column, String, Boolean]
394
+ db_column, table_name, main_table = col_type_and_table_name
395
+ col_type = db_column.type
396
+
397
+ if options[:custom_filter]
398
+
399
+ custom_filter = if options[:custom_filter] == :auto
400
+ -> { @grid.distinct_values_for_column(db_column) } # Thank God Ruby has higher order functions!!!
401
+
402
+ elsif options[:custom_filter].class == Symbol
403
+ -> { @grid.distinct_values_for_column_in_resultset([options[:custom_filter]]) }
404
+
405
+ elsif options[:custom_filter].class == Hash
406
+ options[:custom_filter].keys
407
+
408
+ options[:custom_filter].to_a
409
+
410
+ elsif options[:custom_filter].class == Array
411
+ if options[:custom_filter].empty?
412
+ []
413
+ elsif Wice::WgEnumerable.all_items_are_of_class(options[:custom_filter], Symbol)
414
+ -> { @grid.distinct_values_for_column_in_resultset(options[:custom_filter]) }
415
+
416
+ elsif Wice::WgEnumerable.all_items_are_of_class(options[:custom_filter], String) || WgEnumerable.all_items_are_of_class(options[:custom_filter], Numeric)
417
+ options[:custom_filter].map { |i| [i, i] }
418
+
419
+ elsif Wice::WgEnumerable.all_items_are_of_class(options[:custom_filter], Array)
420
+ options[:custom_filter]
421
+ else
422
+ raise WiceGridArgumentError.new(
423
+ ':custom_filter can equal :auto, an array of string and/or numbers (direct values for the dropdown), ' \
424
+ 'a homogeneous array of symbols (a sequence of methods to send to AR objects in the result set to ' \
425
+ 'retrieve unique values for the dropdown), a Symbol (a shortcut for a one member array of symbols), ' \
426
+ 'a hash where keys are labels and values are values for the dropdown option, or an array of two-item arrays, ' \
427
+ 'each of which contains the label (first element) and the value (second element) for a dropdown option'
428
+ )
429
+ end
430
+ end
431
+
432
+ klass = Columns.get_view_column_processor(:custom)
433
+ elsif options[:filter_type]
434
+ klass = Columns.get_view_column_processor(options[:filter_type])
435
+ else
436
+
437
+ col_type = case col_type
438
+ when :date
439
+ Wice::Defaults::DEFAULT_FILTER_FOR_DATE
440
+ when :datetime
441
+ Wice::Defaults::DEFAULT_FILTER_FOR_DATETIME
442
+ when :timestamp
443
+ Wice::Defaults::DEFAULT_FILTER_FOR_DATETIME
444
+ else
445
+ col_type
446
+ end
447
+
448
+ klass = Columns.get_view_column_processor(col_type)
449
+ end # custom_filter
450
+
451
+ end # attribute
452
+
453
+ vc = klass.new(block, options, @grid, table_name, main_table, custom_filter, @view)
454
+
455
+ vc.negation = options[:negation] if vc.respond_to? :negation=
456
+
457
+ vc.filter_all_label = options[:filter_all_label] if vc.is_a?(Columns.get_view_column_processor(:custom))
458
+ if vc.is_a?(Columns.get_view_column_processor(:boolean))
459
+ vc.boolean_filter_true_label = options[:boolean_filter_true_label]
460
+ vc.boolean_filter_false_label = options[:boolean_filter_false_label]
461
+ end
462
+ add_column(vc)
463
+ end
464
+
465
+ def get_model_from_associations(model, assocs) # :nodoc:
466
+ if assocs.empty?
467
+ model
468
+ else
469
+ head = assocs[0]
470
+ tail = assocs[1..-1]
471
+
472
+ if reflection = model.reflect_on_association(head)
473
+ next_model = reflection.klass
474
+ get_model_from_associations(next_model, tail)
475
+ else
476
+ raise WiceGridArgumentError.new("Association #{head} not found in #{model}")
477
+ end
478
+ end
479
+ end
480
+
481
+ # Optional method inside the +grid+ block, to which every ActiveRecord instance is injected, just like +column+.
482
+ # Unlike +column+, it returns a hash which will be used as HTML attributes for the row with the given ActiveRecord instance.
483
+ #
484
+ # Note that if the method returns a hash with a <tt>:class</tt> or <tt>'class'</tt> element, it will not overwrite
485
+ # classes +even+ and +odd+, instead they will be concatenated: <tt><tr class="even highlighted_row_class_name"></tt>
486
+ def row_attributes(&block)
487
+ @row_attributes_handler = block
488
+ end
489
+
490
+ # Can be used to add HTML code (another row, for example) right after each grid row.
491
+ # Nothing is added if the block return +false+ or +nil+.
492
+ def after_row(&block)
493
+ @after_row_handler = block
494
+ end
495
+
496
+ # Can be used to add HTML code (another row, for example) right before each grid row.
497
+ # Nothing is added if the block return +false+ or +nil+.
498
+ def before_row(&block)
499
+ @before_row_handler = block
500
+ end
501
+
502
+ # Can be used to replace the HTML code (for example to make a multi-column spanning row) of a row.
503
+ # Nothing is replaced if the block return +false+ or +nil+.
504
+ def replace_row(&block)
505
+ @replace_row_handler = block
506
+ end
507
+
508
+ # Can be used to add HTML code (calculation results, for example) after all rows.
509
+ # Nothing is added if the block return +false+ or +nil+.
510
+ def last_row(&block)
511
+ @last_row_handler = block
512
+ end
513
+
514
+ # The output of the block submitted to +blank_slate+ is rendered instead of the whole grid if no filters are active
515
+ # and there are no records to render.
516
+ # In addition to the block style two other variants are accepted:
517
+ # * <tt>g.blank_slate "some text to be rendered"</tt>
518
+ # * <tt>g.blank_slate partial: "partial_name"</tt>
519
+ def blank_slate(opts = nil, &block)
520
+ if (opts.is_a?(Hash) && opts.key?(:partial) && block.nil?) || (opts.is_a?(String) && block.nil?)
521
+ @blank_slate_handler = opts
522
+ elsif opts.nil? && block
523
+ @blank_slate_handler = block
524
+ else
525
+ raise WiceGridArgumentError.new("blank_slate accepts only a string, a block, or template: 'path_to_template' ")
526
+ end
527
+ end
528
+
529
+ def get_row_attributes(ar_object) #:nodoc:
530
+ if @row_attributes_handler
531
+ row_attributes = @row_attributes_handler.call(ar_object)
532
+ row_attributes = {} if row_attributes.blank?
533
+ unless row_attributes.is_a?(Hash)
534
+ raise WiceGridArgumentError.new("row_attributes block must return a hash containing HTML attributes. The returned value is #{row_attributes.inspect}")
535
+ end
536
+ row_attributes
537
+ else
538
+ {}
539
+ end
540
+ end
541
+
542
+ def no_filter_needed? #:nodoc:
543
+ !@columns.inject(false) { |a, b| a || b.filter_shown? }
544
+ end
545
+
546
+ def no_filter_needed_in_main_table? #:nodoc:
547
+ !@columns.inject(false) { |a, b| a || b.filter_shown_in_main_table? }
548
+ end
549
+
550
+ def base_link_for_filter(controller, extra_parameters = {}) #:nodoc:
551
+ new_params = Wice::WgHash.deep_clone controller.params.to_unsafe_h
552
+ new_params.merge!(extra_parameters)
553
+
554
+ if new_params[@grid.name]
555
+ new_params[@grid.name].delete(:page) # we reset paging here
556
+ new_params[@grid.name].delete(:f) # no filter for the base url
557
+ new_params[@grid.name].delete(:foc) # nullify the focus
558
+ new_params[@grid.name].delete(:q) # and no request for the saved query
559
+ end
560
+
561
+ new_params[:only_path] = false
562
+ base_link_with_pp_info = omit_empty_query controller.url_for(new_params)
563
+
564
+ if new_params[@grid.name]
565
+ new_params[@grid.name].delete(:pp) # and reset back to pagination if show all mode is on
566
+ end
567
+ [base_link_with_pp_info, omit_empty_query(controller.url_for(new_params))]
568
+ end
569
+
570
+ def link_for_export(controller, format, extra_parameters = {}) #:nodoc:
571
+ new_params = Wice::WgHash.deep_clone controller.params.to_unsafe_h
572
+ new_params.merge!(extra_parameters)
573
+
574
+ new_params[@grid.name] = {} unless new_params[@grid.name]
575
+ new_params[@grid.name][:export] = format
576
+
577
+ new_params[:only_path] = false
578
+ controller.url_for(new_params)
579
+ end
580
+
581
+ def column_link(column, direction, params, extra_parameters = {}) #:nodoc:
582
+ column_attribute_name = if column.attribute.index('.') || column.main_table || column.table_alias_or_table_name.nil?
583
+ column.attribute
584
+ else
585
+ column.table_alias_or_table_name + '.' + column.attribute
586
+ end
587
+
588
+ query_params = { @grid.name => {
589
+ ORDER_PARAMETER_NAME => column_attribute_name,
590
+ ORDER_DIRECTION_PARAMETER_NAME => direction
591
+ } }
592
+
593
+ cleaned_params = Wice::WgHash.deep_clone params.to_unsafe_h
594
+ cleaned_params.merge!(extra_parameters)
595
+
596
+ cleaned_params.delete(:controller)
597
+ cleaned_params.delete(:action)
598
+
599
+ query_params = Wice::WgHash.rec_merge(cleaned_params, query_params)
600
+
601
+ if Rails.version.to_i >= 5
602
+ '?' + query_params.to_h.to_query
603
+ else
604
+ '?' + query_params.to_query
605
+ end
606
+ end
607
+
608
+ protected
609
+
610
+ def filter_columns(method_name = nil) #:nodoc:
611
+ method_name ? @columns.select(&method_name) : @columns
612
+ end
613
+
614
+ def omit_empty_query(url) #:nodoc:
615
+ # /foo? --> /foo
616
+ # /foo?grid= --> /foo
617
+ # /foo?grid=&page=1 --> /foo?page=1
618
+ # /foo?grid=some_value --> /foo?grid=some_value
619
+
620
+ empty_hash_rx = Regexp.new "([&?])#{Regexp.escape @grid.name}=([&?]|$)" # c.f., issue #140
621
+ url.gsub(empty_hash_rx, '\1').gsub(/\?+$/, '')
622
+ end
623
+ end
624
+ end