barkest_core 1.5.3.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 (308) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/Gemfile +22 -0
  4. data/Gemfile.lock +254 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.md +364 -0
  7. data/Rakefile +37 -0
  8. data/app/assets/fonts/barkest_core/ArchivoNarrow-Bold.ttf +0 -0
  9. data/app/assets/fonts/barkest_core/ArchivoNarrow-BoldItalic.ttf +0 -0
  10. data/app/assets/fonts/barkest_core/ArchivoNarrow-Italic.ttf +0 -0
  11. data/app/assets/fonts/barkest_core/ArchivoNarrow-Regular.ttf +0 -0
  12. data/app/assets/images/barkest_core/.keep +0 -0
  13. data/app/assets/images/barkest_core/barcode-B.svg +181 -0
  14. data/app/assets/javascripts/barkest_core/.keep +0 -0
  15. data/app/assets/javascripts/barkest_core/application.js +22 -0
  16. data/app/assets/javascripts/barkest_core/bootstrap-datepicker.js +1800 -0
  17. data/app/assets/javascripts/barkest_core/field_init.js +7 -0
  18. data/app/assets/javascripts/barkest_core/jquery.doubleScroll.js +112 -0
  19. data/app/assets/javascripts/barkest_core/masked_edit.js +25 -0
  20. data/app/assets/javascripts/barkest_core/system_status.js.erb +201 -0
  21. data/app/assets/stylesheets/barkest_core/.keep +0 -0
  22. data/app/assets/stylesheets/barkest_core/application.css +17 -0
  23. data/app/assets/stylesheets/barkest_core/custom.css.scss +264 -0
  24. data/app/assets/stylesheets/barkest_core/datepicker3.css +790 -0
  25. data/app/controllers/.keep +0 -0
  26. data/app/controllers/access_groups_controller.rb +74 -0
  27. data/app/controllers/account_activations_controller.rb +29 -0
  28. data/app/controllers/application_controller.rb +5 -0
  29. data/app/controllers/barkest_core/application_controller_base.rb +113 -0
  30. data/app/controllers/barkest_core/engine_controller_base.rb +15 -0
  31. data/app/controllers/barkest_core/testsub_controller.rb +21 -0
  32. data/app/controllers/contact_controller.rb +32 -0
  33. data/app/controllers/log_view_controller.rb +31 -0
  34. data/app/controllers/password_resets_controller.rb +126 -0
  35. data/app/controllers/sessions_controller.rb +64 -0
  36. data/app/controllers/status_controller.rb +150 -0
  37. data/app/controllers/system_config_controller.rb +238 -0
  38. data/app/controllers/system_update_controller.rb +164 -0
  39. data/app/controllers/test_access_controller.rb +44 -0
  40. data/app/controllers/test_report_controller.rb +75 -0
  41. data/app/controllers/users_controller.rb +218 -0
  42. data/app/helpers/.keep +0 -0
  43. data/app/helpers/barkest_core/application_helper.rb +134 -0
  44. data/app/helpers/barkest_core/form_helper.rb +469 -0
  45. data/app/helpers/barkest_core/html_helper.rb +70 -0
  46. data/app/helpers/barkest_core/misc_helper.rb +68 -0
  47. data/app/helpers/barkest_core/pdf_helper.rb +180 -0
  48. data/app/helpers/barkest_core/recaptcha_helper.rb +115 -0
  49. data/app/helpers/barkest_core/sessions_helper.rb +94 -0
  50. data/app/helpers/barkest_core/status_helper.rb +118 -0
  51. data/app/helpers/barkest_core/users_helper.rb +32 -0
  52. data/app/mailers/.keep +0 -0
  53. data/app/mailers/application_mailer.rb +5 -0
  54. data/app/mailers/barkest_core/application_mailer_base.rb +30 -0
  55. data/app/mailers/barkest_core/contact_form.rb +20 -0
  56. data/app/mailers/barkest_core/user_mailer.rb +44 -0
  57. data/app/models/.keep +0 -0
  58. data/app/models/access_group.rb +121 -0
  59. data/app/models/access_group_group_member.rb +13 -0
  60. data/app/models/access_group_user_member.rb +11 -0
  61. data/app/models/barkest_core/auth_config.rb +95 -0
  62. data/app/models/barkest_core/authorize_failure.rb +7 -0
  63. data/app/models/barkest_core/contact_message.rb +37 -0
  64. data/app/models/barkest_core/database_config.rb +223 -0
  65. data/app/models/barkest_core/db_table.rb +21 -0
  66. data/app/models/barkest_core/email_config.rb +132 -0
  67. data/app/models/barkest_core/global_status.rb +267 -0
  68. data/app/models/barkest_core/log_entry.rb +101 -0
  69. data/app/models/barkest_core/log_view_options.rb +51 -0
  70. data/app/models/barkest_core/ms_sql_db_definition.rb +441 -0
  71. data/app/models/barkest_core/ms_sql_definition.rb +221 -0
  72. data/app/models/barkest_core/ms_sql_function.rb +423 -0
  73. data/app/models/barkest_core/not_logged_in.rb +7 -0
  74. data/app/models/barkest_core/pdf_table_builder.rb +407 -0
  75. data/app/models/barkest_core/self_update_config.rb +37 -0
  76. data/app/models/barkest_core/user_alert.rb +29 -0
  77. data/app/models/barkest_core/user_alert_generators.rb +58 -0
  78. data/app/models/barkest_core/user_manager.rb +404 -0
  79. data/app/models/barkest_core/work_path.rb +74 -0
  80. data/app/models/disable_user.rb +18 -0
  81. data/app/models/ldap_access_group.rb +15 -0
  82. data/app/models/system_config.rb +99 -0
  83. data/app/models/user.rb +405 -0
  84. data/app/models/user_login_history.rb +11 -0
  85. data/app/views/.keep +0 -0
  86. data/app/views/access_groups/_form.html.erb +19 -0
  87. data/app/views/access_groups/edit.html.erb +2 -0
  88. data/app/views/access_groups/index.html.erb +32 -0
  89. data/app/views/access_groups/new.html.erb +2 -0
  90. data/app/views/access_groups/show.html.erb +4 -0
  91. data/app/views/barkest_core/contact_form/contact.html.erb +16 -0
  92. data/app/views/barkest_core/contact_form/contact.text.erb +13 -0
  93. data/app/views/barkest_core/testsub/_links.html.erb +5 -0
  94. data/app/views/barkest_core/testsub/page1.html.erb +3 -0
  95. data/app/views/barkest_core/testsub/page2.html.erb +2 -0
  96. data/app/views/barkest_core/testsub/page3.html.erb +2 -0
  97. data/app/views/barkest_core/user_mailer/account_activation.html.erb +7 -0
  98. data/app/views/barkest_core/user_mailer/account_activation.text.erb +6 -0
  99. data/app/views/barkest_core/user_mailer/invalid_password_reset.html.erb +3 -0
  100. data/app/views/barkest_core/user_mailer/invalid_password_reset.text.erb +5 -0
  101. data/app/views/barkest_core/user_mailer/password_reset.html.erb +8 -0
  102. data/app/views/barkest_core/user_mailer/password_reset.text.erb +7 -0
  103. data/app/views/contact/index.html.erb +24 -0
  104. data/app/views/layouts/_footer_copyright.html.erb +1 -0
  105. data/app/views/layouts/_menu_admin.html.erb +5 -0
  106. data/app/views/layouts/_menu_anon.html.erb +0 -0
  107. data/app/views/layouts/_menu_auth.html.erb +3 -0
  108. data/app/views/layouts/_menu_footer.html.erb +1 -0
  109. data/app/views/layouts/_nav_logo.html.erb +1 -0
  110. data/app/views/layouts/application.html.erb +2 -0
  111. data/app/views/layouts/barkest_core/_application.html.erb +24 -0
  112. data/app/views/layouts/barkest_core/_footer.html.erb +18 -0
  113. data/app/views/layouts/barkest_core/_header.html.erb +38 -0
  114. data/app/views/layouts/barkest_core/_html_mailer.html.erb +11 -0
  115. data/app/views/layouts/barkest_core/_menu_account.html.erb +14 -0
  116. data/app/views/layouts/barkest_core/_menu_sample.html.erb +1 -0
  117. data/app/views/layouts/barkest_core/_messages.html.erb +4 -0
  118. data/app/views/layouts/barkest_core/_shim.html.erb +4 -0
  119. data/app/views/layouts/barkest_core/_subheader.html.erb +1 -0
  120. data/app/views/layouts/barkest_core/_text_mailer.text.erb +4 -0
  121. data/app/views/layouts/mailer.html.erb +1 -0
  122. data/app/views/layouts/mailer.text.erb +1 -0
  123. data/app/views/log_view/index.html.erb +100 -0
  124. data/app/views/password_resets/edit.html.erb +20 -0
  125. data/app/views/password_resets/new.html.erb +14 -0
  126. data/app/views/sessions/new.html.erb +27 -0
  127. data/app/views/shared/_error_messages.html.erb +29 -0
  128. data/app/views/shared/_generic_user_alert.html.erb +4 -0
  129. data/app/views/status/current.html.erb +34 -0
  130. data/app/views/status/test.html.erb +50 -0
  131. data/app/views/system_config/index.html.erb +25 -0
  132. data/app/views/system_config/show_auth.html.erb +28 -0
  133. data/app/views/system_config/show_database.html.erb +36 -0
  134. data/app/views/system_config/show_email.html.erb +21 -0
  135. data/app/views/system_config/show_self_update.html.erb +13 -0
  136. data/app/views/system_update/index.html.erb +31 -0
  137. data/app/views/system_update/new.html.erb +2 -0
  138. data/app/views/test_access/allow_anon.html.erb +2 -0
  139. data/app/views/test_access/require_admin.html.erb +2 -0
  140. data/app/views/test_access/require_group_x.html.erb +2 -0
  141. data/app/views/test_access/require_user.html.erb +2 -0
  142. data/app/views/test_report/index.csv.csvrb +23 -0
  143. data/app/views/test_report/index.html.erb +6 -0
  144. data/app/views/test_report/index.pdf.prawn +50 -0
  145. data/app/views/test_report/index.xlsx.axlsx +28 -0
  146. data/app/views/users/_user.html.erb +57 -0
  147. data/app/views/users/_user_details.html.erb +15 -0
  148. data/app/views/users/_user_details_for_list.html.erb +1 -0
  149. data/app/views/users/_user_form.html.erb +13 -0
  150. data/app/views/users/disable_confirm.html.erb +19 -0
  151. data/app/views/users/edit.html.erb +15 -0
  152. data/app/views/users/index.html.erb +9 -0
  153. data/app/views/users/new.html.erb +10 -0
  154. data/app/views/users/show.html.erb +46 -0
  155. data/bin/rails +12 -0
  156. data/config/routes.rb +3 -0
  157. data/db/migrate/20160617172539_create_access_groups.rb +10 -0
  158. data/db/migrate/20160617172725_create_users.rb +26 -0
  159. data/db/migrate/20160617172833_create_user_login_histories.rb +12 -0
  160. data/db/migrate/20160622151720_create_access_group_user_members.rb +9 -0
  161. data/db/migrate/20160622151925_create_access_group_group_members.rb +9 -0
  162. data/db/migrate/20160701005706_create_ldap_access_groups.rb +11 -0
  163. data/db/migrate/20161108155029_create_system_configs.rb +11 -0
  164. data/db/seeds/barkest_core_01_create_users.rb +42 -0
  165. data/db/seeds.rb +53 -0
  166. data/lib/barkest_core/concerns/association_with_defaults.rb +55 -0
  167. data/lib/barkest_core/concerns/boolean_parser.rb +88 -0
  168. data/lib/barkest_core/concerns/date_parser.rb +181 -0
  169. data/lib/barkest_core/concerns/email_tester.rb +55 -0
  170. data/lib/barkest_core/concerns/encrypted_fields.rb +156 -0
  171. data/lib/barkest_core/concerns/named_model.rb +73 -0
  172. data/lib/barkest_core/concerns/number_parser.rb +145 -0
  173. data/lib/barkest_core/concerns/utc_conversion.rb +60 -0
  174. data/lib/barkest_core/engine.rb +105 -0
  175. data/lib/barkest_core/extensions/active_record_extensions.rb +120 -0
  176. data/lib/barkest_core/extensions/application_configuration_extensions.rb +38 -0
  177. data/lib/barkest_core/extensions/application_extensions.rb +50 -0
  178. data/lib/barkest_core/extensions/axlsx_extenstions.rb +157 -0
  179. data/lib/barkest_core/extensions/fixture_set_extensions.rb +107 -0
  180. data/lib/barkest_core/extensions/generator_extensions.rb +271 -0
  181. data/lib/barkest_core/extensions/main_app_extensions.rb +35 -0
  182. data/lib/barkest_core/extensions/prawn_document_extensions.rb +367 -0
  183. data/lib/barkest_core/extensions/prawn_table_extensions.rb +131 -0
  184. data/lib/barkest_core/extensions/router_extensions.rb +106 -0
  185. data/lib/barkest_core/extensions/simple_formatter_extensions.rb +66 -0
  186. data/lib/barkest_core/extensions/test_case_extensions.rb +348 -0
  187. data/lib/barkest_core/extensions/time_extensions.rb +164 -0
  188. data/lib/barkest_core/handlers/csv_handler.rb +30 -0
  189. data/lib/barkest_core/version.rb +3 -0
  190. data/lib/barkest_core.rb +324 -0
  191. data/lib/generators/barkest/install_generator.rb +102 -0
  192. data/lib/generators/barkest_core/actions/01_patch_application_controller.rb +55 -0
  193. data/lib/generators/barkest_core/actions/02_patch_application_mailer.rb +56 -0
  194. data/lib/generators/barkest_core/actions/03_patch_assets.rb +62 -0
  195. data/lib/generators/barkest_core/actions/04_patch_layouts.rb +36 -0
  196. data/lib/generators/barkest_core/actions/05_patch_routes.rb +93 -0
  197. data/lib/generators/barkest_core/actions/06_patch_seeds.rb +60 -0
  198. data/lib/generators/barkest_core/actions/07_copy_migrations.rb +51 -0
  199. data/lib/generators/barkest_core/actions/08_configure_database.rb +52 -0
  200. data/lib/generators/barkest_core/actions/09_configure_secrets.rb +29 -0
  201. data/lib/generators/barkest_core/actions/99_patch_gitignore.rb +57 -0
  202. data/lib/generators/barkest_core/install_generator.rb +17 -0
  203. data/test/barkest_core_test.rb +83 -0
  204. data/test/controllers/access_groups_controller_test.rb +53 -0
  205. data/test/controllers/contact_controller_test.rb +10 -0
  206. data/test/controllers/sessions_controller_test.rb +10 -0
  207. data/test/controllers/users_controller_test.rb +10 -0
  208. data/test/dummy/.gitignore +10 -0
  209. data/test/dummy/README.rdoc +28 -0
  210. data/test/dummy/Rakefile +6 -0
  211. data/test/dummy/app/assets/images/.keep +0 -0
  212. data/test/dummy/app/assets/javascripts/application.js +14 -0
  213. data/test/dummy/app/assets/stylesheets/application.css +16 -0
  214. data/test/dummy/app/controllers/application_controller.rb +5 -0
  215. data/test/dummy/app/controllers/concerns/.keep +0 -0
  216. data/test/dummy/app/helpers/application_helper.rb +2 -0
  217. data/test/dummy/app/mailers/.keep +0 -0
  218. data/test/dummy/app/mailers/application_mailer.rb +3 -0
  219. data/test/dummy/app/models/.keep +0 -0
  220. data/test/dummy/app/models/concerns/.keep +0 -0
  221. data/test/dummy/app/views/layouts/application.html.erb +1 -0
  222. data/test/dummy/app/views/layouts/mailer.html.erb +1 -0
  223. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  224. data/test/dummy/app/views/system_config/show_fake.html.erb +3 -0
  225. data/test/dummy/bin/bundle +3 -0
  226. data/test/dummy/bin/rails +4 -0
  227. data/test/dummy/bin/rake +4 -0
  228. data/test/dummy/bin/setup +29 -0
  229. data/test/dummy/config/application.rb +27 -0
  230. data/test/dummy/config/boot.rb +5 -0
  231. data/test/dummy/config/environment.rb +5 -0
  232. data/test/dummy/config/environments/development.rb +47 -0
  233. data/test/dummy/config/environments/production.rb +79 -0
  234. data/test/dummy/config/environments/test.rb +44 -0
  235. data/test/dummy/config/initializers/assets.rb +11 -0
  236. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  237. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  238. data/test/dummy/config/initializers/db_updater_ext.rb +33 -0
  239. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  240. data/test/dummy/config/initializers/inflections.rb +16 -0
  241. data/test/dummy/config/initializers/mime_types.rb +4 -0
  242. data/test/dummy/config/initializers/session_store.rb +3 -0
  243. data/test/dummy/config/initializers/sys_config_ext.rb +12 -0
  244. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  245. data/test/dummy/config/locales/en.yml +23 -0
  246. data/test/dummy/config/routes.rb +60 -0
  247. data/test/dummy/config.ru +4 -0
  248. data/test/dummy/db/schema.rb +95 -0
  249. data/test/dummy/db/seeds/barkest_core_01_create_users.rb +42 -0
  250. data/test/dummy/db/seeds.rb +51 -0
  251. data/test/dummy/lib/assets/.keep +0 -0
  252. data/test/dummy/log/.keep +0 -0
  253. data/test/dummy/public/404.html +67 -0
  254. data/test/dummy/public/422.html +67 -0
  255. data/test/dummy/public/500.html +66 -0
  256. data/test/dummy/public/favicon.ico +0 -0
  257. data/test/dummy/sql/my_test_view.sql +3 -0
  258. data/test/fixtures/access_groups.yml +21 -0
  259. data/test/fixtures/users.yml +71 -0
  260. data/test/helpers/barkest_core/sessions_helper_test.rb +22 -0
  261. data/test/integration/access_group_mgmt_test.rb +33 -0
  262. data/test/integration/access_test.rb +24 -0
  263. data/test/integration/account_activations_access_test.rb +12 -0
  264. data/test/integration/contact_test.rb +98 -0
  265. data/test/integration/extra_partial_test.rb +41 -0
  266. data/test/integration/log_view_access_test.rb +12 -0
  267. data/test/integration/password_resets_test.rb +101 -0
  268. data/test/integration/reports_test.rb +53 -0
  269. data/test/integration/status_access_test.rb +27 -0
  270. data/test/integration/system_config_access_test.rb +24 -0
  271. data/test/integration/system_update_access_test.rb +19 -0
  272. data/test/integration/users_access_test.rb +34 -0
  273. data/test/integration/users_edit_test.rb +178 -0
  274. data/test/integration/users_index_test.rb +62 -0
  275. data/test/integration/users_login_test.rb +67 -0
  276. data/test/integration/users_signup_test.rb +54 -0
  277. data/test/mailers/.keep +0 -0
  278. data/test/mailers/barkest_core/contact_form_test.rb +28 -0
  279. data/test/mailers/barkest_core/user_mailer_test.rb +43 -0
  280. data/test/mailers/previews/barkest_core/contact_form_preview.rb +17 -0
  281. data/test/mailers/previews/barkest_core/user_mailer_preview.rb +26 -0
  282. data/test/models/access_group_group_member_test.rb +28 -0
  283. data/test/models/access_group_test.rb +114 -0
  284. data/test/models/access_group_user_member_test.rb +28 -0
  285. data/test/models/barkest_core/auth_config_test.rb +57 -0
  286. data/test/models/barkest_core/bool_parser_test.rb +28 -0
  287. data/test/models/barkest_core/contact_message_test.rb +61 -0
  288. data/test/models/barkest_core/database_config_test.rb +33 -0
  289. data/test/models/barkest_core/date_parser_test.rb +110 -0
  290. data/test/models/barkest_core/email_config_test.rb +57 -0
  291. data/test/models/barkest_core/global_status_test.rb +50 -0
  292. data/test/models/barkest_core/ms_sql_db_updater_test.rb +115 -0
  293. data/test/models/barkest_core/ms_sql_definition_test.rb +102 -0
  294. data/test/models/barkest_core/ms_sql_function_test.rb +131 -0
  295. data/test/models/barkest_core/number_parser_test.rb +29 -0
  296. data/test/models/barkest_core/self_update_config_test.rb +29 -0
  297. data/test/models/barkest_core/user_alert_test.rb +19 -0
  298. data/test/models/barkest_core/user_manager_test.rb +34 -0
  299. data/test/models/barkest_core/work_path_test.rb +26 -0
  300. data/test/models/disable_user_test.rb +27 -0
  301. data/test/models/generic_time_test.rb +66 -0
  302. data/test/models/ldap_access_group_test.rb +31 -0
  303. data/test/models/pdf_table_builder_test.rb +6 -0
  304. data/test/models/system_config_test.rb +78 -0
  305. data/test/models/user_login_history_test.rb +37 -0
  306. data/test/models/user_test.rb +130 -0
  307. data/test/test_helper.rb +63 -0
  308. metadata +798 -0
data/app/helpers/.keep ADDED
File without changes
@@ -0,0 +1,134 @@
1
+ # this shouldn't be necessary, but engines seem to have a few weak spots.
2
+ require 'will_paginate/view_helpers/action_view'
3
+ # removes a circular loading warning during testing
4
+ # while still allowing the styling during development/production
5
+ unless Rails.env.test?
6
+ require 'bootstrap-will_paginate'
7
+ end
8
+
9
+ module BarkestCore
10
+ ##
11
+ # This module contains some generic helper functions for use in all views and all controllers.
12
+ module ApplicationHelper
13
+
14
+ ##
15
+ # Generates a title string for a page using a standard format.
16
+ #
17
+ # In this case, the standard format is either 'application name' or 'application name - page specific title'.
18
+ #
19
+ # * +title+ Specifies the page specific title.
20
+ #
21
+ def page_title(title = nil)
22
+ return Rails.application.app_name if title.blank?
23
+ "#{Rails.application.app_name} - #{title}"
24
+ end
25
+
26
+ ##
27
+ # Renders an error summary for the specified model.
28
+ #
29
+ # Any model that includes an +errors+ method that returns an +full_messages+ collection can be passed to this method.
30
+ #
31
+ # If more than 6 errors exist, then the first 3 will be shown with a link to display all of the error messages.
32
+ #
33
+ def error_summary(model)
34
+ render partial: 'shared/error_messages', locals: { model: model }
35
+ end
36
+
37
+ ##
38
+ # Renders an alert message.
39
+ #
40
+ # * +type+ The type of message [info, success, warn, error, danger, etc]
41
+ # * +message+ The message to display.
42
+ #
43
+ # To provide messages including HTML, you need to prefix the type with 'safe_'.
44
+ #
45
+ # render_alert(safe_info, '<strong>This</strong> is a message containing <code>HTML</code> content.')
46
+ #
47
+ # The message can be a string, hash, or array. When an array is specified, then each array element is enumerated and
48
+ # joined together. The real power comes in when you specify a hash. A hash will print the key as a label and then
49
+ # enumerate the value (string, hash, or array) in an unordered list. Hash values are processed recursively, allowing
50
+ # you to create alerts with lists within lists.
51
+ #
52
+ # render_alert(info, { 'Section 1' => [ 'Line 1', 'Line 2', 'Line 3' ] })
53
+ #
54
+ # <label>Section 1</label>
55
+ # <ul>
56
+ # <li>Line 1</li>
57
+ # <li>Line 2</li>
58
+ # <li>Line 3</li>
59
+ # </ul>
60
+ #
61
+ # render_alert(info, { 'Block A' => { 'Block A:1' => [ 'Line 1', 'Line 2' ] }})
62
+ #
63
+ # <label>Block A</label>
64
+ # <ul>
65
+ # <li>
66
+ # <label>Block A:1</label>
67
+ # <ul>
68
+ # <li>Line 1</li>
69
+ # <li>Line 2</li>
70
+ # </ul>
71
+ # </li>
72
+ # </ul>
73
+ #
74
+ def render_alert(type, message)
75
+ if type.to_s.index('safe_')
76
+ type = type.to_s[5..-1]
77
+ message = message.to_s.html_safe
78
+ end
79
+
80
+ type = type.to_sym
81
+
82
+ type = :info if type == :notice
83
+ type = :danger if type == :alert
84
+
85
+ return nil unless [:info, :success, :danger, :warning].include?(type)
86
+
87
+ "<div class=\"alert alert-#{type} alert-dismissible\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>#{render_alert_message(message)}</div>".html_safe
88
+ end
89
+
90
+ ##
91
+ # <%= render_for_namespace 'layout_partial_name' %>
92
+ #
93
+ # Only renders if the current controller is namespaced.
94
+ # If the specified partial doesn't exist, no error is raised.
95
+ def render_for_namespace view
96
+ nmspc = params[:controller].include?('/') ? params[:controller].rpartition('/')[0] : nil
97
+ # recurse down the namespace tree to see if we get any hits.
98
+ until nmspc.blank?
99
+ template = "layouts/#{nmspc}/_#{view}"
100
+ partial = "layouts/#{nmspc}/#{view}"
101
+ if lookup_context.template_exists?(template)
102
+ return render(partial)
103
+ end
104
+ nmspc = nmspc.include?('/') ? nmspc.rpartition('/')[0] : nil
105
+ end
106
+ end
107
+
108
+ private
109
+
110
+ def render_alert_message(message, bottom = true)
111
+ ret = ''
112
+ if message.is_a?(Array)
113
+ message = message.map { |v| render_alert_message(v, bottom) }
114
+ ret += message.join
115
+ elsif message.is_a?(Hash)
116
+ message.each do |k,v|
117
+ ret += '<li>' unless bottom
118
+ ret += "<label>#{h k.to_s}</label>"
119
+ ret += "<ul>#{render_alert_message(v, false)}</ul>"
120
+ ret += '</li>' unless bottom
121
+ end
122
+ else
123
+ if bottom
124
+ ret += h(message)
125
+ else
126
+ ret += "<li>#{h message}</li>".html_safe
127
+ end
128
+ end
129
+ ret.html_safe
130
+ end
131
+
132
+
133
+ end
134
+ end
@@ -0,0 +1,469 @@
1
+ module BarkestCore
2
+ ##
3
+ # This module contains a number of utility functions to make generating forms even easier.
4
+ module FormHelper
5
+
6
+ ##
7
+ # Creates a date picker selection field using a bootstrap input group.
8
+ #
9
+ # Valid options:
10
+ # * +input_group_size+
11
+ # Valid optional sizes are 'small' or 'large'.
12
+ # * +readonly+
13
+ # Set to true to make the input field read only.
14
+ # * +pre_calendar+
15
+ # Set to true to put a calendar icon before the input field.
16
+ # * +post_calendar+
17
+ # Set to true to put a calendar icon after the input field. This is the default setting.
18
+ # * +pre_label+
19
+ # Set to a text value to put a label before the input field. Replaces +pre_calendar+ if specified.
20
+ # * +post_label+
21
+ # Set to a text value to put a label after the input field. Replaces +post_calendar+ if specified.
22
+ def date_picker_field(f, method, options = {})
23
+ options = {
24
+ class: 'form-control',
25
+ read_only: false,
26
+ pre_calendar: false,
27
+ pre_label: nil,
28
+ post_calendar: true,
29
+ post_label: false,
30
+ attrib_val: { },
31
+ style: { },
32
+ input_group_size: ''
33
+ }.merge(options)
34
+
35
+ style = ''
36
+ options[:style].each { |k,v| style += "#{k}: #{v};" }
37
+
38
+ attrib = options[:attrib_val]
39
+ attrib[:class] = options[:class]
40
+ attrib[:style] = style
41
+ attrib[:readonly] = 'readonly' if options[:read_only]
42
+
43
+ if options[:input_group_size] == 'sm' || options[:input_group_size] == 'small' || options[:input_group_size] == 'input-group-sm'
44
+ options[:input_group_size] = 'input-group-sm'
45
+ elsif options[:input_group_size] == 'lg' || options[:input_group_size] == 'large' || options[:input_group_size] == 'input-group-lg'
46
+ options[:input_group_size] = 'input-group-lg'
47
+ else
48
+ options[:input_group_size] = ''
49
+ end
50
+
51
+
52
+ attrib[:value] = f.object.send(method).to_s(:date4) if f.object.send(method)
53
+ fld = f.text_field(method, attrib)
54
+
55
+ # must have at least one attachment, default to post-calendar.
56
+ options[:post_calendar] = true unless options[:pre_calendar] || options[:pre_label] || options[:post_label]
57
+
58
+ # labels override calendars.
59
+ options[:pre_calendar] = false if options[:pre_label]
60
+ options[:post_calendar] = false if options[:post_label]
61
+
62
+ # construct the prefix
63
+ if options[:pre_calendar]
64
+ pre = '<span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>'
65
+ elsif options[:pre_label]
66
+ pre = "<span class=\"input-group-addon\">#{h options[:pre_label]}</span>"
67
+ else
68
+ pre = ''
69
+ end
70
+
71
+ # construct the postfix
72
+ if options[:post_calendar]
73
+ post = '<span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>'
74
+ elsif options[:post_label]
75
+ post = "<span class=\"input-group-addon\">#{h options[:post_label]}</span>"
76
+ else
77
+ post = ''
78
+ end
79
+
80
+ # and then the return value.
81
+ "<div class=\"input-group date #{options[:input_group_size]}\">#{pre}#{fld}#{post}</div>".html_safe
82
+ end
83
+
84
+ ##
85
+ # Creates an input group containing multiple input fields.
86
+ #
87
+ # Valid options:
88
+ # * +input_group_size+
89
+ # Valid optional sizes are 'small' or 'large'.
90
+ # * +readonly+
91
+ # Set to true to make the input field read only.
92
+ # * +width+
93
+ # Set to any value to set the width of the overall field in percent. Default is 100%.
94
+ # * +width_1+ ... +width_N+
95
+ # Set the width of the child field to a specific percent. Defaults to equal amount for all children.
96
+ # * +placeholder_1+ ... +placeholder_N+
97
+ # Set the placeholder of the child field. Defaults to the method name.
98
+ def multi_input_field(f, methods, options = {})
99
+ raise ArgumentError.new('methods must respond to :count') unless methods.respond_to?(:count)
100
+
101
+ options = {
102
+ class: 'form-control',
103
+ read_only: false,
104
+ attrib_val: { },
105
+ style: { },
106
+ input_group_size: ''
107
+ }.merge(options)
108
+
109
+ style = ''
110
+ options[:style].each do |k,v|
111
+ if k.to_s == 'width'
112
+ options[:input_group_width] = "width: #{v};"
113
+ else
114
+ style += "#{k}: #{v};"
115
+ end
116
+ end
117
+
118
+ options[:input_group_width] ||= 'width: 100%;'
119
+
120
+ attrib = options[:attrib_val]
121
+ attrib[:class] = options[:class]
122
+ attrib[:readonly] = 'readonly' if options[:read_only]
123
+
124
+ if options[:input_group_size] == 'sm' || options[:input_group_size] == 'small' || options[:input_group_size] == 'input-group-sm'
125
+ options[:input_group_size] = 'input-group-sm'
126
+ elsif options[:input_group_size] == 'lg' || options[:input_group_size] == 'large' || options[:input_group_size] == 'input-group-lg'
127
+ options[:input_group_size] = 'input-group-lg'
128
+ else
129
+ options[:input_group_size] = ''
130
+ end
131
+
132
+ fld = []
133
+
134
+ remaining_width = 100.0
135
+ width = (100.0 / methods.count).round(2)
136
+
137
+ builder = Proc.new do |method,label,index|
138
+ num = index + 1
139
+ # if user specified width, use it.
140
+ width = options[:"width_#{num}"].to_s.to_f
141
+
142
+ # otherwise compute the width.
143
+ if width <= 0
144
+ width = (remaining_width / (methods.count - index)).round(2)
145
+ width = remaining_width if width > remaining_width || index == methods.count - 1
146
+ end
147
+
148
+ remaining_width -= width
149
+ attrib[:style] = style + "width: #{width}%;"
150
+ attrib[:value] = f.object.send(method)
151
+
152
+ ph = options[:"placeholder_#{num}"] || (label.blank? ? method.to_s.humanize : label)
153
+ attrib[:placeholder] = ph
154
+
155
+ options.each do |opt_key, opt_val|
156
+ attr_key,_,fld_num = opt_key.to_s.rpartition('_')
157
+ if fld_num.to_i == num
158
+ unless %w(value width placeholder).include?(attr_key)
159
+ if %w(class style).include?(attr_key)
160
+ attrib[:class] += ' ' + opt_val.to_s
161
+ else
162
+ attrib[attr_key.to_sym] = opt_val.to_s
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ fld << f.text_field(method, attrib)
169
+ end
170
+
171
+ if methods.is_a?(Array)
172
+ methods.each_with_index do |method, index|
173
+ builder.call method, method.to_s.humanize, index
174
+ end
175
+ elsif methods.is_a?(Hash)
176
+ methods.each_with_index do |(method,label), index|
177
+ builder.call method, label.to_s, index
178
+ end
179
+ else
180
+ raise ArgumentError.new('methods must either be an array or a hash')
181
+ end
182
+
183
+ "<div class=\"input-group #{options[:input_group_size]}\" style=\"#{options[:input_group_width]}\">#{fld.join}</div>".html_safe
184
+ end
185
+
186
+ ##
187
+ # Creates a currency input field.
188
+ #
189
+ # Specify the +currency_symbol+ if you want it to be something other than '$'.
190
+ # Additional options are passed on to the text field.
191
+ def currency_field(f, method, options = {})
192
+ # get the symbol for the field.
193
+ sym = '$'
194
+ if options[:currency_symbol]
195
+ sym = options[:currency_symbol]
196
+ options.except! :currency_symbol
197
+ end
198
+
199
+ # get the value
200
+ if (val = f.object.send(method))
201
+ options[:value] = number_with_precision val, precision: 2, delimiter: ','
202
+ end
203
+
204
+ # build the field
205
+ fld = f.text_field(method, options)
206
+
207
+ # return the value.
208
+ "<div class=\"input-symbol\"><span>#{h sym}</span>#{fld}</div>".html_safe
209
+ end
210
+
211
+ ##
212
+ # Creates a label followed by small text.
213
+ #
214
+ # Set the :small_text option to include small text.
215
+ def label_with_small(f, method, text=nil, options = {}, &block)
216
+ if text.is_a?(Hash)
217
+ options = text
218
+ text = nil
219
+ end
220
+ small_text = options.delete(:small_text)
221
+ text = text || options.delete(:text) || method.to_s.humanize.capitalize
222
+ lbl = f.label(method, text, options, &block) #do
223
+ # contents = text
224
+ # contents += "<small>#{h small_text}</small>" if small_text
225
+ # contents += yield if block_given?
226
+ # contents.html_safe
227
+ #end
228
+ lbl += "&nbsp;<small>(#{h small_text})</small>".html_safe if small_text
229
+ lbl.html_safe
230
+ end
231
+
232
+ ##
233
+ # Creates a form group including a label and a text field.
234
+ #
235
+ # To specify a label, set the +label_text+ option, otherwise the method name will be used.
236
+ # Prefix field options with +field_+ and label options with +label_+.
237
+ # Any additional options are passed to the form group.
238
+ def text_form_group(f, method, options = {})
239
+ gopt, lopt, fopt = split_form_group_options(options)
240
+ lbl = f.label_with_small method, lopt.delete(:text), lopt
241
+ fld = gopt[:wrap].call(f.text_field(method, fopt))
242
+ form_group lbl, fld, gopt
243
+ end
244
+
245
+ ##
246
+ # Creates a form group including a label and a text area.
247
+ #
248
+ # To specify a label, set the +label_text+ option, otherwise the method name will be used.
249
+ # Prefix field options with +field_+ and label options with +label_+.
250
+ # Any additional options are passed to the form group.
251
+ def textarea_form_group(f, method, options = {})
252
+ gopt, lopt, fopt = split_form_group_options(options)
253
+ lbl = f.label_with_small method, lopt.delete(:text), lopt
254
+ fld = gopt[:wrap].call(f.text_area(method, fopt))
255
+ form_group lbl, fld, gopt
256
+ end
257
+
258
+ ##
259
+ # Creates a form group including a label and a currency field.
260
+ #
261
+ # To specify a label, set the +label_text+ option, otherwise the method name will be used.
262
+ # Prefix field options with +field_+ and label options with +label_+.
263
+ # Any additional options are passed to the form group.
264
+ def currency_form_group(f, method, options = {})
265
+ gopt, lopt, fopt = split_form_group_options(options)
266
+ lbl = f.label_with_small method, lopt.delete(:text), lopt
267
+ fld = gopt[:wrap].call(currency_field(f, method, fopt))
268
+ form_group lbl, fld, gopt
269
+ end
270
+
271
+ ##
272
+ # Creates a form group including a label and a static field.
273
+ # The static field is simple a readonly input field with no name.
274
+ #
275
+ # To specify a label, set the +label_text+ option, otherwise the method name will be used.
276
+ # Prefix field options with +field_+ and label options with +label_+.
277
+ # Any additional options are passed to the form group.
278
+ def static_form_group(f, method, options = {})
279
+ gopt, lopt, fopt = split_form_group_options(options)
280
+ lbl = f.label_with_small method, lopt.delete(:text), lopt
281
+ fld = gopt[:wrap].call("<input type=\"text\" class=\"form-control disabled\" readonly=\"readonly\" value=\"#{h(fopt[:value] || f.object.send(method))}\">")
282
+ form_group lbl, fld, gopt
283
+ end
284
+
285
+ ##
286
+ # Creates a form group including a label and a date picker field.
287
+ #
288
+ # To specify a label, set the +label_text+ option, otherwise the method name will be used.
289
+ # Prefix field options with +field_+ and label options with +label_+.
290
+ # Any additional options are passed to the form group.
291
+ def date_picker_form_group(f, method, options = {})
292
+ gopt, lopt, fopt = split_form_group_options(options)
293
+ lbl = f.label_with_small method, lopt.delete(:text), lopt
294
+ fld = gopt[:wrap].call(date_picker_field(f, method, fopt))
295
+ form_group lbl, fld, gopt
296
+ end
297
+
298
+ ##
299
+ # Creates a form group including a label and a multiple input field.
300
+ #
301
+ # To specify a label, set the +label_text+ option, otherwise the method name will be used.
302
+ # Prefix field options with +field_+ and label options with +label_+.
303
+ # Any additional options are passed to the form group.
304
+ def multi_input_form_group(f, methods, options = {})
305
+ gopt, lopt, fopt = split_form_group_options(options)
306
+ lopt[:text] ||= gopt[:label]
307
+ if lopt[:text].blank?
308
+ lopt[:text] = methods.map {|k,_| k.to_s.humanize }.join(', ')
309
+ end
310
+ lbl = f.label_with_small methods.map{|k,_| k}.first, lopt[:text], lopt
311
+ fld = gopt[:wrap].call(multi_input_field(f, methods, fopt))
312
+ form_group lbl, fld, gopt
313
+ end
314
+
315
+ ##
316
+ # Creates a form group including a label and a checkbox.
317
+ #
318
+ # To specify a label, set the +label_text+ option, otherwise the method name will be used.
319
+ # Prefix field options with +field_+ and label options with +label_+.
320
+ # Any additional options are passed to the form group.
321
+ def checkbox_form_group(f, method, options = {})
322
+ gopt, lopt, fopt = split_form_group_options({ class: 'checkbox', field_class: ''}.merge(options))
323
+
324
+ if gopt[:h_align]
325
+ gopt[:class] = gopt[:class].blank? ?
326
+ "col-sm-#{12-gopt[:h_align]} col-sm-offset-#{gopt[:h_align]}" :
327
+ "#{gopt[:class]} col-sm-#{12-gopt[:h_align]} col-sm-offset-#{gopt[:h_align]}"
328
+ end
329
+
330
+ lbl = f.label method do
331
+ f.check_box(method, fopt) +
332
+ h(lopt[:text] || method.to_s.humanize) +
333
+ if lopt[:small_text]
334
+ "<small>#{h lopt[:small_text]}</small>"
335
+ else
336
+ ''
337
+ end.html_safe
338
+ end
339
+
340
+ "<div class=\"#{gopt[:h_align] ? 'row' : 'form-group'}\"><div class=\"#{gopt[:class]}\">#{lbl}</div></div>".html_safe
341
+ end
342
+
343
+ ##
344
+ # Creates a form group including a label and a collection select field.
345
+ #
346
+ # To specify a label, set the +label_text+ option, otherwise the method name will be used.
347
+ # Prefix field options with +field_+ and label options with +label_+.
348
+ # Any additional options are passed to the form group.
349
+ def select_form_group(f, method, collection, value_method = nil, text_method = nil, options = {})
350
+ gopt, lopt, fopt = split_form_group_options({ field_include_blank: true }.merge(options))
351
+ lbl = f.label_with_small method, lopt.delete(:text), lopt
352
+ value_method ||= :to_s
353
+ text_method ||= :to_s
354
+ opt = {}
355
+ [:include_blank, :prompt, :include_hidden].each do |attr|
356
+ if fopt[attr] != nil
357
+ opt[attr] = fopt[attr]
358
+ fopt.except! attr
359
+ end
360
+ end
361
+ fld = gopt[:wrap].call(f.collection_select(method, collection, value_method, text_method, opt, fopt))
362
+ form_group lbl, fld, gopt
363
+ end
364
+
365
+ private
366
+
367
+ def form_group(lbl, fld, opt)
368
+ ret = '<div'
369
+ ret += " class=\"#{h opt[:class]}" unless opt[:class].blank?
370
+ ret += '"'
371
+ ret += " style=\"#{h opt[:style]}\"" unless opt[:style].blank?
372
+ ret += ">#{lbl}#{fld}</div>"
373
+ ret.html_safe
374
+ end
375
+
376
+ def split_form_group_options(options)
377
+ options = {class: 'form-group', field_class: 'form-control'}.merge(options || {})
378
+ group = {}
379
+ label = {}
380
+ field = {}
381
+
382
+ options.keys.each do |k|
383
+ sk = k.to_s
384
+ if sk.index('label_') == 0
385
+ label[sk[6..-1].to_sym] = options[k]
386
+ elsif sk.index('field_') == 0
387
+ field[sk[6..-1].to_sym] = options[k]
388
+ else
389
+ group[k.to_sym] = options[k]
390
+ end
391
+ end
392
+
393
+ group[:wrap] = Proc.new do |fld|
394
+ fld
395
+ end
396
+ if group[:h_align]
397
+ if group[:h_align].is_a?(TrueClass)
398
+ l = 3
399
+ else
400
+ l = group[:h_align].to_i
401
+ end
402
+ l = 1 if l < 1
403
+ l = 6 if l > 6
404
+ f = 12 - l
405
+ group[:h_align] = l
406
+ label[:class] = label[:class].blank? ? "col-sm-#{l} control-label" : "#{label[:class]} col-sm-#{l} control-label"
407
+ group[:wrap] = Proc.new do |fld|
408
+ "<div class=\"col-sm-#{f}\">#{fld}</div>"
409
+ end
410
+ end
411
+
412
+ [group, label, field]
413
+ end
414
+
415
+ end
416
+ end
417
+
418
+ # :enddoc:
419
+
420
+ ActionView::Helpers::FormBuilder.class_eval do
421
+
422
+ def label_with_small(method, text = nil, options = {}, &block)
423
+ @template.send(:label_with_small, self, method, text, options, &block)
424
+ end
425
+
426
+ def date_picker_field(method, options = {})
427
+ @template.send(:date_picker_field, self, method, options)
428
+ end
429
+
430
+ def multi_input_field(methods, options = {})
431
+ @template.send(:multi_input_field, self, methods, options)
432
+ end
433
+
434
+ def currency_field(method, options = {})
435
+ @template.send(:currency_field, self, method, options)
436
+ end
437
+
438
+ def text_form_group(method, options = {})
439
+ @template.send(:text_form_group, self, method, options)
440
+ end
441
+
442
+ def textarea_form_group(method, options = {})
443
+ @template.send(:textarea_form_group, self, method, options)
444
+ end
445
+
446
+ def currency_form_group(method, options = {})
447
+ @template.send(:currency_form_group, self, method, options)
448
+ end
449
+
450
+ def static_form_group(method, options = {})
451
+ @template.send(:static_form_group, self, method, options)
452
+ end
453
+
454
+ def date_picker_form_group(method, options = {})
455
+ @template.send(:date_picker_form_group, self, method, options)
456
+ end
457
+
458
+ def multi_input_form_group(method, options = {})
459
+ @template.send(:multi_input_form_group, self, method, options)
460
+ end
461
+
462
+ def select_form_group(method, collection, value_method = nil, text_method = nil, options = {})
463
+ @template.send(:select_form_group, self, method, collection, value_method, text_method, options)
464
+ end
465
+
466
+ def checkbox_form_group(method, options = {})
467
+ @template.send(:checkbox_form_group, self, method, options)
468
+ end
469
+ end