incline 0.1.5

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 (303) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/Gemfile +17 -0
  4. data/Gemfile.lock +186 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.rdoc +208 -0
  7. data/Rakefile +37 -0
  8. data/app/assets/fonts/incline/.keep +0 -0
  9. data/app/assets/images/incline/.keep +0 -0
  10. data/app/assets/images/incline/barcode-B.svg +181 -0
  11. data/app/assets/javascripts/incline/activate_classed_items.js +11 -0
  12. data/app/assets/javascripts/incline/application.js +30 -0
  13. data/app/assets/javascripts/incline/bootstrap-datepicker.js +1800 -0
  14. data/app/assets/javascripts/incline/datatables.js +22193 -0
  15. data/app/assets/javascripts/incline/escapeHtml.js +10 -0
  16. data/app/assets/javascripts/incline/inline_actions.js +479 -0
  17. data/app/assets/javascripts/incline/jquery.doubleScroll.js +112 -0
  18. data/app/assets/javascripts/incline/jquery.number.js +764 -0
  19. data/app/assets/javascripts/incline/regexMask.js +27 -0
  20. data/app/assets/javascripts/incline/select2/i18n/en.js +3 -0
  21. data/app/assets/javascripts/incline/select2/select2.full.js +6436 -0
  22. data/app/assets/stylesheets/incline/application.css +18 -0
  23. data/app/assets/stylesheets/incline/bootstrap-theme.min.css +5 -0
  24. data/app/assets/stylesheets/incline/custom.scss +279 -0
  25. data/app/assets/stylesheets/incline/datatables.css +494 -0
  26. data/app/assets/stylesheets/incline/datepicker3.css +790 -0
  27. data/app/assets/stylesheets/incline/select2.css +484 -0
  28. data/app/controllers/incline/access_groups_controller.rb +127 -0
  29. data/app/controllers/incline/access_test_controller.rb +30 -0
  30. data/app/controllers/incline/account_activations_controller.rb +28 -0
  31. data/app/controllers/incline/application_controller.rb +11 -0
  32. data/app/controllers/incline/contact_controller.rb +34 -0
  33. data/app/controllers/incline/password_resets_controller.rb +113 -0
  34. data/app/controllers/incline/security_controller.rb +100 -0
  35. data/app/controllers/incline/sessions_controller.rb +50 -0
  36. data/app/controllers/incline/users_controller.rb +304 -0
  37. data/app/controllers/incline/welcome_controller.rb +19 -0
  38. data/app/helpers/incline/.keep +0 -0
  39. data/app/mailers/incline/application_mailer_base.rb +11 -0
  40. data/app/mailers/incline/contact_form.rb +19 -0
  41. data/app/mailers/incline/user_mailer.rb +45 -0
  42. data/app/models/incline/access_group.rb +121 -0
  43. data/app/models/incline/access_group_group_member.rb +12 -0
  44. data/app/models/incline/access_group_user_member.rb +10 -0
  45. data/app/models/incline/action_group.rb +12 -0
  46. data/app/models/incline/action_security.rb +222 -0
  47. data/app/models/incline/contact_message.rb +37 -0
  48. data/app/models/incline/disable_info.rb +20 -0
  49. data/app/models/incline/password_reset.rb +14 -0
  50. data/app/models/incline/password_reset_request.rb +14 -0
  51. data/app/models/incline/user.rb +437 -0
  52. data/app/models/incline/user_login_history.rb +30 -0
  53. data/app/views/incline/access_groups/_details.json.jbuilder +10 -0
  54. data/app/views/incline/access_groups/_form.html.erb +19 -0
  55. data/app/views/incline/access_groups/_list.html.erb +60 -0
  56. data/app/views/incline/access_groups/_messages.json.jbuilder +6 -0
  57. data/app/views/incline/access_groups/edit.html.erb +2 -0
  58. data/app/views/incline/access_groups/index.html.erb +6 -0
  59. data/app/views/incline/access_groups/index.json.jbuilder +16 -0
  60. data/app/views/incline/access_groups/new.html.erb +2 -0
  61. data/app/views/incline/access_groups/show.html.erb +9 -0
  62. data/app/views/incline/access_groups/show.json.jbuilder +11 -0
  63. data/app/views/incline/contact/new.html.erb +22 -0
  64. data/app/views/incline/contact_form/contact.html.erb +16 -0
  65. data/app/views/incline/contact_form/contact.text.erb +13 -0
  66. data/app/views/incline/password_resets/edit.html.erb +16 -0
  67. data/app/views/incline/password_resets/new.html.erb +12 -0
  68. data/app/views/incline/security/_details.json.jbuilder +7 -0
  69. data/app/views/incline/security/_form.html.erb +20 -0
  70. data/app/views/incline/security/_list.html.erb +89 -0
  71. data/app/views/incline/security/_messages.json.jbuilder +6 -0
  72. data/app/views/incline/security/edit.html.erb +2 -0
  73. data/app/views/incline/security/index.html.erb +6 -0
  74. data/app/views/incline/security/index.json.jbuilder +16 -0
  75. data/app/views/incline/security/show.html.erb +31 -0
  76. data/app/views/incline/security/show.json.jbuilder +11 -0
  77. data/app/views/incline/sessions/new.html.erb +26 -0
  78. data/app/views/incline/user_mailer/account_activation.html.erb +7 -0
  79. data/app/views/incline/user_mailer/account_activation.text.erb +6 -0
  80. data/app/views/incline/user_mailer/invalid_password_reset.html.erb +3 -0
  81. data/app/views/incline/user_mailer/invalid_password_reset.text.erb +5 -0
  82. data/app/views/incline/user_mailer/password_reset.html.erb +8 -0
  83. data/app/views/incline/user_mailer/password_reset.text.erb +7 -0
  84. data/app/views/incline/users/_details.json.jbuilder +32 -0
  85. data/app/views/incline/users/_form.html.erb +21 -0
  86. data/app/views/incline/users/_list.html.erb +102 -0
  87. data/app/views/incline/users/_messages.json.jbuilder +6 -0
  88. data/app/views/incline/users/disable_confirm.html.erb +19 -0
  89. data/app/views/incline/users/edit.html.erb +5 -0
  90. data/app/views/incline/users/index.html.erb +6 -0
  91. data/app/views/incline/users/index.json.jbuilder +16 -0
  92. data/app/views/incline/users/new.html.erb +5 -0
  93. data/app/views/incline/users/show.html.erb +12 -0
  94. data/app/views/incline/users/show.json.jbuilder +11 -0
  95. data/app/views/incline/welcome/home.html.erb +5 -0
  96. data/app/views/layouts/application.html.erb +1 -0
  97. data/app/views/layouts/incline/_account_menu.html.erb +18 -0
  98. data/app/views/layouts/incline/_app_menu_anon.html.erb +1 -0
  99. data/app/views/layouts/incline/_app_menu_authenticated.html.erb +1 -0
  100. data/app/views/layouts/incline/_footer.html.erb +13 -0
  101. data/app/views/layouts/incline/_header.html.erb +21 -0
  102. data/app/views/layouts/incline/_html_mailer.html.erb +5 -0
  103. data/app/views/layouts/incline/_incline_app.html.erb +25 -0
  104. data/app/views/layouts/incline/_messages.html.erb +3 -0
  105. data/app/views/layouts/incline/_shim.html.erb +3 -0
  106. data/app/views/layouts/incline/_text_mailer.text.erb +1 -0
  107. data/app/views/layouts/incline/application.html.erb +1 -0
  108. data/app/views/layouts/mailer.html.erb +2 -0
  109. data/app/views/layouts/mailer.text.erb +2 -0
  110. data/bin/rails +12 -0
  111. data/bin/test_scaffold.sh +10 -0
  112. data/config/routes.rb +61 -0
  113. data/db/migrate/20170511230126_create_incline_users.rb +26 -0
  114. data/db/migrate/20170515003052_create_incline_access_groups.rb +10 -0
  115. data/db/migrate/20170515003221_create_incline_user_login_histories.rb +12 -0
  116. data/db/migrate/20170515150908_create_incline_access_group_user_members.rb +11 -0
  117. data/db/migrate/20170515151058_create_incline_access_group_group_members.rb +11 -0
  118. data/db/migrate/20170517193432_add_comments_to_incline_user.rb +5 -0
  119. data/db/migrate/20170622132700_create_incline_action_securities.rb +16 -0
  120. data/db/migrate/20170622172712_create_incline_action_groups.rb +11 -0
  121. data/db/migrate/20170622195742_add_non_standard_to_action_security.rb +5 -0
  122. data/db/migrate/20170622230422_add_visible_to_action_security.rb +5 -0
  123. data/db/seeds.rb +81 -0
  124. data/exe/new_incline_app +42 -0
  125. data/lib/generators/incline/install_generator.rb +259 -0
  126. data/lib/generators/incline/templates/_app_menu_anon.html.erb +1 -0
  127. data/lib/generators/incline/templates/_app_menu_authenticated.html.erb +1 -0
  128. data/lib/generators/incline/templates/incline_application.css +17 -0
  129. data/lib/generators/incline/templates/incline_application.html.erb +1 -0
  130. data/lib/generators/incline/templates/incline_application.js +12 -0
  131. data/lib/generators/incline/templates/incline_database.yml +25 -0
  132. data/lib/generators/incline/templates/incline_email.yml +20 -0
  133. data/lib/generators/incline/templates/incline_mailer.html.erb +2 -0
  134. data/lib/generators/incline/templates/incline_mailer.text.erb +2 -0
  135. data/lib/generators/incline/templates/incline_users.yml +64 -0
  136. data/lib/generators/incline/templates/incline_version.rb +3 -0
  137. data/lib/incline/auth_engine_base.rb +52 -0
  138. data/lib/incline/data_tables_request.rb +336 -0
  139. data/lib/incline/date_time_formats.rb +6 -0
  140. data/lib/incline/engine.rb +212 -0
  141. data/lib/incline/errors.rb +15 -0
  142. data/lib/incline/extensions/action_controller_base.rb +526 -0
  143. data/lib/incline/extensions/action_mailer_base.rb +66 -0
  144. data/lib/incline/extensions/action_view_base.rb +489 -0
  145. data/lib/incline/extensions/active_record_base.rb +308 -0
  146. data/lib/incline/extensions/application.rb +137 -0
  147. data/lib/incline/extensions/application_configuration.rb +50 -0
  148. data/lib/incline/extensions/connection_adapter.rb +55 -0
  149. data/lib/incline/extensions/date_time_value.rb +123 -0
  150. data/lib/incline/extensions/date_value.rb +77 -0
  151. data/lib/incline/extensions/decimal_value.rb +55 -0
  152. data/lib/incline/extensions/erb_scaffold_generator.rb +31 -0
  153. data/lib/incline/extensions/float_value.rb +59 -0
  154. data/lib/incline/extensions/form_builder.rb +617 -0
  155. data/lib/incline/extensions/integer_value.rb +54 -0
  156. data/lib/incline/extensions/jbuilder_generator.rb +38 -0
  157. data/lib/incline/extensions/jbuilder_template.rb +39 -0
  158. data/lib/incline/extensions/main_app.rb +40 -0
  159. data/lib/incline/extensions/numeric.rb +63 -0
  160. data/lib/incline/extensions/object.rb +31 -0
  161. data/lib/incline/extensions/resource_route_generator.rb +53 -0
  162. data/lib/incline/extensions/session.rb +113 -0
  163. data/lib/incline/extensions/string.rb +50 -0
  164. data/lib/incline/extensions/test_case.rb +764 -0
  165. data/lib/incline/extensions/time_zone_converter.rb +40 -0
  166. data/lib/incline/global_status.rb +236 -0
  167. data/lib/incline/helpers/route_hash_formatter.rb +46 -0
  168. data/lib/incline/json_log_formatter.rb +96 -0
  169. data/lib/incline/json_logger.rb +17 -0
  170. data/lib/incline/log.rb +153 -0
  171. data/lib/incline/number_formats.rb +17 -0
  172. data/lib/incline/recaptcha.rb +346 -0
  173. data/lib/incline/user_manager.rb +212 -0
  174. data/lib/incline/validators/email_validator.rb +45 -0
  175. data/lib/incline/validators/ip_address_validator.rb +32 -0
  176. data/lib/incline/validators/recaptcha_validator.rb +37 -0
  177. data/lib/incline/validators/safe_name_validator.rb +31 -0
  178. data/lib/incline/version.rb +3 -0
  179. data/lib/incline/work_path.rb +75 -0
  180. data/lib/incline.rb +197 -0
  181. data/lib/tasks/incline_tasks.rake +4 -0
  182. data/lib/templates/erb/scaffold/_form.html.erb +43 -0
  183. data/lib/templates/erb/scaffold/_list.html.erb +81 -0
  184. data/lib/templates/erb/scaffold/edit.html.erb +1 -0
  185. data/lib/templates/erb/scaffold/index.html.erb +6 -0
  186. data/lib/templates/erb/scaffold/new.html.erb +1 -0
  187. data/lib/templates/erb/scaffold/show.html.erb +34 -0
  188. data/lib/templates/jbuilder/scaffold/_details.json.jbuilder +20 -0
  189. data/lib/templates/jbuilder/scaffold/index.json.jbuilder +16 -0
  190. data/lib/templates/jbuilder/scaffold/show.json.jbuilder +16 -0
  191. data/lib/templates/rails/scaffold_controller/controller.rb +128 -0
  192. data/test/controllers/incline/access_groups_controller_test.rb +65 -0
  193. data/test/controllers/incline/access_test_controller_test.rb +53 -0
  194. data/test/controllers/incline/contact_controller_test.rb +32 -0
  195. data/test/controllers/incline/security_controller_test.rb +39 -0
  196. data/test/controllers/incline/welcome_controller_test.rb +16 -0
  197. data/test/dummy/README.rdoc +28 -0
  198. data/test/dummy/Rakefile +6 -0
  199. data/test/dummy/app/assets/images/.keep +0 -0
  200. data/test/dummy/app/assets/javascripts/application.js +12 -0
  201. data/test/dummy/app/assets/stylesheets/application.css +17 -0
  202. data/test/dummy/app/controllers/application_controller.rb +5 -0
  203. data/test/dummy/app/controllers/concerns/.keep +0 -0
  204. data/test/dummy/app/helpers/application_helper.rb +2 -0
  205. data/test/dummy/app/mailers/.keep +0 -0
  206. data/test/dummy/app/models/.keep +0 -0
  207. data/test/dummy/app/models/concerns/.keep +0 -0
  208. data/test/dummy/app/views/layouts/application.html.erb +1 -0
  209. data/test/dummy/app/views/layouts/incline/_app_menu_anon.html.erb +1 -0
  210. data/test/dummy/app/views/layouts/incline/_app_menu_authenticated.html.erb +1 -0
  211. data/test/dummy/app/views/layouts/mailer.html.erb +2 -0
  212. data/test/dummy/app/views/layouts/mailer.text.erb +2 -0
  213. data/test/dummy/bin/bundle +3 -0
  214. data/test/dummy/bin/rails +4 -0
  215. data/test/dummy/bin/rake +4 -0
  216. data/test/dummy/bin/setup +29 -0
  217. data/test/dummy/config/application.rb +38 -0
  218. data/test/dummy/config/boot.rb +5 -0
  219. data/test/dummy/config/database.yml +34 -0
  220. data/test/dummy/config/email.yml +24 -0
  221. data/test/dummy/config/environment.rb +5 -0
  222. data/test/dummy/config/environments/development.rb +45 -0
  223. data/test/dummy/config/environments/production.rb +85 -0
  224. data/test/dummy/config/environments/test.rb +44 -0
  225. data/test/dummy/config/initializers/assets.rb +11 -0
  226. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  227. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  228. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  229. data/test/dummy/config/initializers/inflections.rb +16 -0
  230. data/test/dummy/config/initializers/mime_types.rb +4 -0
  231. data/test/dummy/config/initializers/session_store.rb +3 -0
  232. data/test/dummy/config/initializers/to_time_preserves_timezone.rb +10 -0
  233. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  234. data/test/dummy/config/locales/en.yml +23 -0
  235. data/test/dummy/config/routes.rb +6 -0
  236. data/test/dummy/config.ru +4 -0
  237. data/test/dummy/db/schema.rb +108 -0
  238. data/test/dummy/lib/assets/.keep +0 -0
  239. data/test/dummy/log/.keep +0 -0
  240. data/test/dummy/public/404.html +67 -0
  241. data/test/dummy/public/422.html +67 -0
  242. data/test/dummy/public/500.html +66 -0
  243. data/test/dummy/public/favicon.ico +0 -0
  244. data/test/extensions/action_controller_base_extensions_test.rb +21 -0
  245. data/test/extensions/action_mailer_base_extensions_test.rb +20 -0
  246. data/test/extensions/action_view_base_extensions_test.rb +267 -0
  247. data/test/extensions/active_record_extensions_test.rb +173 -0
  248. data/test/extensions/application_configuration_extensions_test.rb +46 -0
  249. data/test/extensions/application_extensions_test.rb +23 -0
  250. data/test/extensions/connection_adapter_extensions_test.rb +54 -0
  251. data/test/extensions/date_time_value_extensions_test.rb +104 -0
  252. data/test/extensions/date_value_extensions_test.rb +102 -0
  253. data/test/extensions/decimal_value_extensions_test.rb +85 -0
  254. data/test/extensions/erb_scaffold_generator_extensions_test.rb +17 -0
  255. data/test/extensions/float_value_extensions_test.rb +78 -0
  256. data/test/extensions/form_builder_extensions_test.rb +28 -0
  257. data/test/extensions/integer_value_extensions_test.rb +78 -0
  258. data/test/extensions/jbuilder_generator_extensions_test.rb +21 -0
  259. data/test/extensions/jbuilder_template_extensions_test.rb +47 -0
  260. data/test/extensions/main_app_extensions_test.rb +55 -0
  261. data/test/extensions/numeric_extensions_test.rb +76 -0
  262. data/test/extensions/object_extensions_test.rb +104 -0
  263. data/test/extensions/session_extensions_test.rb +69 -0
  264. data/test/extensions/string_extensions_test.rb +32 -0
  265. data/test/extensions/test_case_extensions_test.rb +538 -0
  266. data/test/extensions/time_zone_converter_extensions_test.rb +10 -0
  267. data/test/fixtures/incline/access_group_group_members.yml +1 -0
  268. data/test/fixtures/incline/access_group_user_members.yml +1 -0
  269. data/test/fixtures/incline/access_groups.yml +13 -0
  270. data/test/fixtures/incline/action_groups.yml +6 -0
  271. data/test/fixtures/incline/action_securities.yml +18 -0
  272. data/test/fixtures/incline/user_login_histories.yml +1 -0
  273. data/test/fixtures/incline/users.yml +64 -0
  274. data/test/incline_test.rb +63 -0
  275. data/test/integration/incline/users_edit_test.rb +180 -0
  276. data/test/integration/incline/users_login_test.rb +105 -0
  277. data/test/integration/incline/users_signup_test.rb +147 -0
  278. data/test/integration/navigation_test.rb +11 -0
  279. data/test/lib/data_tables_request_test.rb +245 -0
  280. data/test/lib/date_time_formats_test.rb +111 -0
  281. data/test/lib/global_status_test.rb +89 -0
  282. data/test/lib/json_log_formatter_test.rb +43 -0
  283. data/test/lib/log_test.rb +36 -0
  284. data/test/lib/recaptcha_test.rb +75 -0
  285. data/test/lib/user_manager_test.rb +47 -0
  286. data/test/lib/work_path_test.rb +18 -0
  287. data/test/models/incline/access_group_group_member_test.rb +30 -0
  288. data/test/models/incline/access_group_test.rb +60 -0
  289. data/test/models/incline/access_group_user_member_test.rb +29 -0
  290. data/test/models/incline/action_group_test.rb +27 -0
  291. data/test/models/incline/action_security_test.rb +176 -0
  292. data/test/models/incline/contact_message_test.rb +66 -0
  293. data/test/models/incline/disable_info_test.rb +29 -0
  294. data/test/models/incline/password_reset_request_test.rb +35 -0
  295. data/test/models/incline/password_reset_test.rb +51 -0
  296. data/test/models/incline/user_login_history_test.rb +31 -0
  297. data/test/models/incline/user_test.rb +91 -0
  298. data/test/test_helper.rb +42 -0
  299. data/test/validators/email_validator_test.rb +102 -0
  300. data/test/validators/ip_address_validator_test.rb +107 -0
  301. data/test/validators/recaptcha_validator_test.rb +57 -0
  302. data/test/validators/safe_name_validator_test.rb +101 -0
  303. metadata +584 -0
@@ -0,0 +1,617 @@
1
+ require 'cgi/util'
2
+ require 'action_view'
3
+
4
+ module Incline::Extensions
5
+ ##
6
+ # Adds additional helper methods to form builders.
7
+ module FormBuilder
8
+
9
+ ##
10
+ # Creates a date picker selection field using a bootstrap input group.
11
+ #
12
+ # *Valid options:*
13
+ #
14
+ # input_group_size::
15
+ # Valid optional sizes are 'small' or 'large'.
16
+ # readonly::
17
+ # Set to true to make the input field read only.
18
+ # pre_calendar::
19
+ # Set to true to put a calendar icon before the input field.
20
+ # post_calendar::
21
+ # Set to true to put a calendar icon after the input field. This is the default setting if no other pre/post
22
+ # is selected.
23
+ # pre_label::
24
+ # Set to a text value to put a label before the input field. Replaces +pre_calendar+ if specified.
25
+ # post_label::
26
+ # Set to a text value to put a label after the input field. Replaces +post_calendar+ if specified.
27
+ #
28
+ # f.date_picker :end_date, :pre_label => 'End'
29
+ #
30
+ def date_picker(method, options = {})
31
+ options = {
32
+ class: 'form-control',
33
+ read_only: false,
34
+ pre_calendar: false,
35
+ pre_label: nil,
36
+ post_calendar: false,
37
+ post_label: false,
38
+ attrib_val: { },
39
+ style: { },
40
+ input_group_size: ''
41
+ }.merge(options)
42
+
43
+ style = ''
44
+ options[:style].each { |k,v| style += "#{k}: #{v};" }
45
+
46
+ attrib = options[:attrib_val]
47
+ attrib[:class] = options[:class]
48
+ attrib[:style] = style
49
+ attrib[:readonly] = 'readonly' if options[:read_only]
50
+
51
+ if %w(sm small input-group-sm).include?(options[:input_group_size])
52
+ options[:input_group_size] = 'input-group-sm'
53
+ elsif %w(lg large input-group-lg).include?(options[:input_group_size])
54
+ options[:input_group_size] = 'input-group-lg'
55
+ else
56
+ options[:input_group_size] = ''
57
+ end
58
+
59
+ attrib[:value] = object.send(method).strftime('%m/%d/%Y') if object.send(method)
60
+ fld = text_field(method, attrib)
61
+
62
+ # must have at least one attachment, default to post-calendar.
63
+ options[:post_calendar] = true unless options[:pre_calendar] || options[:pre_label] || options[:post_label]
64
+
65
+ # labels override calendars.
66
+ options[:pre_calendar] = false if options[:pre_label]
67
+ options[:post_calendar] = false if options[:post_label]
68
+
69
+ # construct the prefix
70
+ if options[:pre_calendar]
71
+ pre = '<span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>'
72
+ elsif options[:pre_label]
73
+ pre = "<span class=\"input-group-addon\">#{CGI::escape_html options[:pre_label]}</span>"
74
+ else
75
+ pre = ''
76
+ end
77
+
78
+ # construct the postfix
79
+ if options[:post_calendar]
80
+ post = '<span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>'
81
+ elsif options[:post_label]
82
+ post = "<span class=\"input-group-addon\">#{CGI::escape_html options[:post_label]}</span>"
83
+ else
84
+ post = ''
85
+ end
86
+
87
+ # and then the return value.
88
+ "<div class=\"input-group date #{options[:input_group_size]}\">#{pre}#{fld}#{post}</div>".html_safe
89
+ end
90
+
91
+ ##
92
+ # Creates a multiple input field control for the provided form.
93
+ #
94
+ # The +methods+ parameter can be either an array of method names, or a hash with method names as the
95
+ # keys and labels as the values.
96
+ #
97
+ # For instance:
98
+ # [ :alpha, :bravo, :charlie ]
99
+ # { :alpha => 'The first item', :bravo => 'The second item', :charlie => 'The third item' }
100
+ #
101
+ # *Valid options:*
102
+ #
103
+ # class::
104
+ # The CSS class to apply. Defaults to 'form-control'.
105
+ #
106
+ # read_only::
107
+ # Should the control be read-only? Defaults to false.
108
+ #
109
+ # style::
110
+ # A hash containing CSS styling attributes to apply to the input fields.
111
+ # Width is generated automatically or specified individually using the "field_n" option.
112
+ #
113
+ # input_group_size::
114
+ # You can specific *small* or *large* to change the control's overall size.
115
+ #
116
+ # attrib::
117
+ # Any additional attributes you want to apply to the input fields.
118
+ #
119
+ # field_n::
120
+ # Sets specific attributes for field "n". These values will override the "attrib" and "style" options.
121
+ #
122
+ # f.multi_input [ :city, :state, :zip ],
123
+ # :field_1 => { :maxlength => 30, :style => { :width => '65%' } },
124
+ # :field_2 => { :maxlength => 2 },
125
+ # :field_3 => { :maxlength => 10, :style => { :width => '25%' } }
126
+ #
127
+ def multi_input(methods, options = {})
128
+ raise ArgumentError.new('methods must be either a Hash or an Array') unless methods.is_a?(::Hash) || methods.is_a?(::Array)
129
+ options = options.dup
130
+
131
+ # add some defaults.
132
+ options = {
133
+ class: 'form-control',
134
+ read_only: false,
135
+ attrib: { },
136
+ style: { },
137
+ input_group_size: ''
138
+ }.merge(options)
139
+
140
+ # build the style attribute.
141
+ options[:attrib][:style] ||= ''
142
+ options[:style].each do |k,v|
143
+ if k.to_s == 'width'
144
+ options[:input_group_width] = "width: #{v};"
145
+ else
146
+ options[:attrib][:style] += "#{k}: #{v};"
147
+ end
148
+ end
149
+
150
+ # Standardize the "methods" list to be an array of arrays.
151
+ if methods.is_a?(::Hash)
152
+ methods = methods.to_a
153
+ elsif methods.is_a?(::Array)
154
+ methods = methods.map{|v| v.is_a?(::Array) ? v : [ v, v.to_s.humanize ] }
155
+ end
156
+
157
+ # Extract field attributes.
158
+ fields = { }
159
+ index = 1
160
+ methods.each do |(meth,label)|
161
+ fields[meth] = options[:attrib].merge(options.delete(:"field_#{index}") || {})
162
+ fields[meth][:readonly] = 'readonly' if options[:read_only]
163
+ fields[meth][:class] ||= options[:class]
164
+ if fields[meth][:style].is_a?(::Hash)
165
+ fields[meth][:style] = fields[meth][:style].to_a.map{|v| v.map(&:to_s).join(':') + ';'}.join(' ')
166
+ end
167
+ fields[meth][:placeholder] ||= label
168
+ end
169
+
170
+ if %w(sm small input-group-sm).include?(options[:input_group_size])
171
+ options[:input_group_size] = 'input-group-sm'
172
+ elsif %w(lg large input-group-lg).include?(options[:input_group_size])
173
+ options[:input_group_size] = 'input-group-lg'
174
+ else
175
+ options[:input_group_size] = ''
176
+ end
177
+
178
+ # We want each field to have a width specified.
179
+ remaining_width = 100.0
180
+ remaining_fields = fields.count
181
+ width_match_1 = /^width:([^;]);/
182
+ width_match_2 = /;\s*width:([^;]);/
183
+
184
+ # pass 1, compute remaining width.
185
+ fields.each do |meth, attr|
186
+ width = width_match_1.match(attr[:style]) || width_match_2.match(attr[:style])
187
+ if width
188
+ if width[-1] == '%'
189
+ width = width[0...-1].strip.to_f
190
+ if width > remaining_width
191
+ Incline::Log::warn "Field width adds up to more than 100% in multi_input affecting field \"#{meth}\"."
192
+ width = remaining_width
193
+ attr[:style] = attr[:style].gsub(width_match_1, '').gsub(width_match_2, '') + "width: #{width}%;"
194
+ end
195
+ remaining_width -= width
196
+ remaining_width = 0 if remaining_width < 0
197
+ remaining_fields -= 1
198
+ else
199
+ # we do not support pixel, em, etc, so dump the unsupported width.
200
+ Incline::Log::warn "Unsupported width style in multi_input affecting field \"#{meth}\": #{width}"
201
+ attr[:style] = attr[:style].gsub(width_match_1, '').gsub(width_match_2, '')
202
+ end
203
+ end
204
+ end
205
+
206
+ # pass 2, fill in missing widths.
207
+ fields.each do |meth, attr|
208
+ width = width_match_1.match(attr[:style]) || width_match_2.match(attr[:style])
209
+ unless width
210
+ width =
211
+ if remaining_fields > 1
212
+ (remaining_width / remaining_fields).to_i
213
+ else
214
+ remaining_width
215
+ end
216
+
217
+ Incline::Log::warn "Computed field width of 0% in multi_input affecting field \"#{meth}\"." if width == 0
218
+
219
+ attr[:style] += "width: #{width}%;"
220
+ remaining_width -= width
221
+ remaining_fields -= 1
222
+ remaining_width = 0 if remaining_width < 0
223
+ end
224
+ end
225
+
226
+ fld = []
227
+ fields.each do |meth, attr|
228
+ attr[:value] = object.send(meth)
229
+ fld << text_field(meth, attr)
230
+ end
231
+
232
+ "<div class=\"input-group #{options[:input_group_size]}\" style=\"#{options[:input_group_width]}\">#{fld.join}</div>".html_safe
233
+ end
234
+
235
+ ##
236
+ # Creates a currency entry field.
237
+ #
238
+ # *Valid options:*
239
+ #
240
+ # currency_symbol::
241
+ # A string used to prefix the input field. Defaults to '$'.
242
+ #
243
+ # All other options will be passed through to the {FormHelper#text_field}[http://apidock.com/rails/ActionView/Helpers/FormHelper/text_field] method.
244
+ #
245
+ # The value will be formatted with comma delimiters and two decimal places.
246
+ #
247
+ # f.currency :pay_rate
248
+ #
249
+ def currency_field(method, options = {})
250
+ # get the symbol for the field.
251
+ sym = options.delete(:currency_symbol) || '$'
252
+
253
+ # get the value
254
+ if (val = object.send(method))
255
+ options[:value] = number_with_precision val, precision: 2, delimiter: ','
256
+ end
257
+
258
+ # build the field
259
+ fld = text_field(method, options)
260
+
261
+ # return the value.
262
+ "<div class=\"input-symbol\"><span>#{CGI::escape_html sym}</span>#{fld}</div>".html_safe
263
+ end
264
+
265
+ ##
266
+ # Creates a label followed by an optional small text description.
267
+ # For instance, <label>Hello</label> <small>(World)</small>
268
+ #
269
+ # Valid options:
270
+ #
271
+ # text::
272
+ # The text for the label. If not set, the method name is humanized and that value will be used.
273
+ #
274
+ # small_text::
275
+ # The small text to follow the label. If not set, then no small text will be included.
276
+ # This is useful for flagging fields as optional.
277
+ #
278
+ # For additional options, see {FormHelper#label}[http://apidock.com/rails/ActionView/Helpers/FormHelper/label].
279
+ def label_w_small(method, options = {})
280
+ text = options.delete(:text) || method.to_s.humanize
281
+ small_text = options.delete(:small_text)
282
+ label(method, text, options) +
283
+ (small_text ? " <small>(#{CGI::escape_html small_text})</small>" : '').html_safe
284
+ end
285
+
286
+ ##
287
+ # Creates a standard form group with a label and text field.
288
+ #
289
+ # The +options+ is a hash containing label, field, and group options.
290
+ # Prefix label options with +label_+ and field options with +field_+.
291
+ # All other options will apply to the group itself.
292
+ #
293
+ # Group options:
294
+ #
295
+ # class::
296
+ # The CSS class for the form group. Defaults to 'form-group'.
297
+ #
298
+ # style::
299
+ # Any styles to apply to the form group.
300
+ #
301
+ # For label options, see #label_w_small.
302
+ # For field options, see {FormHelper#text_field}[http://apidock.com/rails/ActionView/Helpers/FormHelper/text_field].
303
+ #
304
+ def text_form_group(method, options = {})
305
+ gopt, lopt, fopt = split_form_group_options(options)
306
+ lbl = label_w_small(method, lopt)
307
+ fld = gopt[:wrap].call(text_field(method, fopt))
308
+ form_group lbl, fld, gopt
309
+ end
310
+
311
+ ##
312
+ # Creates a standard form group with a label and password field.
313
+ #
314
+ # The +options+ is a hash containing label, field, and group options.
315
+ # Prefix label options with +label_+ and field options with +field_+.
316
+ # All other options will apply to the group itself.
317
+ #
318
+ # Group options:
319
+ #
320
+ # class::
321
+ # The CSS class for the form group. Defaults to 'form-group'.
322
+ #
323
+ # style::
324
+ # Any styles to apply to the form group.
325
+ #
326
+ # For label options, see #label_w_small.
327
+ # For field options, see {FormHelper#password_field}[http://apidock.com/rails/ActionView/Helpers/FormHelper/password_field].
328
+ #
329
+ def password_form_group(method, options = {})
330
+ gopt, lopt, fopt = split_form_group_options(options)
331
+ lbl = label_w_small(method, lopt)
332
+ fld = gopt[:wrap].call(password_field(method, fopt))
333
+ form_group lbl, fld, gopt
334
+ end
335
+
336
+
337
+ ##
338
+ # Creates a form group including a label and a text area.
339
+ #
340
+ # The +options+ is a hash containing label, field, and group options.
341
+ # Prefix label options with +label_+ and field options with +field_+.
342
+ # All other options will apply to the group itself.
343
+ #
344
+ # Group options:
345
+ #
346
+ # class::
347
+ # The CSS class for the form group. Defaults to 'form-group'.
348
+ #
349
+ # style::
350
+ # Any styles to apply to the form group.
351
+ #
352
+ # For label options, see #label_w_small.
353
+ # For field options, see {FormHelper#text_area}[http://apidock.com/rails/ActionView/Helpers/FormHelper/text_area].
354
+ def textarea_form_group(method, options = {})
355
+ gopt, lopt, fopt = split_form_group_options(options)
356
+ lbl = label_w_small method, lopt
357
+ fld = gopt[:wrap].call(text_area(method, fopt))
358
+ form_group lbl, fld, gopt
359
+ end
360
+
361
+ ##
362
+ # Creates a standard form group with a label and currency field.
363
+ #
364
+ # The +options+ is a hash containing label, field, and group options.
365
+ # Prefix label options with +label_+ and field options with +field_+.
366
+ # All other options will apply to the group itself.
367
+ #
368
+ # Group options:
369
+ #
370
+ # class::
371
+ # The CSS class for the form group. Defaults to 'form-group'.
372
+ #
373
+ # style::
374
+ # Any styles to apply to the form group.
375
+ #
376
+ # For label options, see #label_w_small.
377
+ # For field options, see #currency_field.
378
+ #
379
+ def currency_form_group(method, options = {})
380
+ gopt, lopt, fopt = split_form_group_options(options)
381
+ lbl = label_w_small(method, lopt)
382
+ fld = gopt[:wrap].call(currency_field(method, fopt))
383
+ form_group lbl, fld, gopt
384
+ end
385
+
386
+ ##
387
+ # Creates a standard form group with a label and a static text field.
388
+ #
389
+ # The +options+ is a hash containing label, field, and group options.
390
+ # Prefix label options with +label_+ and field options with +field_+.
391
+ # All other options will apply to the group itself.
392
+ #
393
+ # Group options:
394
+ #
395
+ # class::
396
+ # The CSS class for the form group. Defaults to 'form-group'.
397
+ #
398
+ # style::
399
+ # Any styles to apply to the form group.
400
+ #
401
+ # For label options, see #label_w_small.
402
+ #
403
+ # Field options:
404
+ #
405
+ # value::
406
+ # Allows you to specify a value for the static field, otherwise the value from +method+ will be used.
407
+ #
408
+ def static_form_group(method, options = {})
409
+ gopt, lopt, fopt = split_form_group_options(options)
410
+ lbl = label_w_small(method, lopt)
411
+ fld = gopt[:wrap].call("<input type=\"text\" class=\"form-control disabled\" readonly=\"readonly\" value=\"#{CGI::escape_html(fopt[:value] || object.send(method))}\">")
412
+ form_group lbl, fld, gopt
413
+ end
414
+
415
+ ##
416
+ # Creates a standard form group with a datepicker field.
417
+ #
418
+ # The +options+ is a hash containing label, field, and group options.
419
+ # Prefix label options with +label_+ and field options with +field_+.
420
+ # All other options will apply to the group itself.
421
+ #
422
+ # Group options:
423
+ #
424
+ # class::
425
+ # The CSS class for the form group. Defaults to 'form-group'.
426
+ #
427
+ # style::
428
+ # Any styles to apply to the form group.
429
+ #
430
+ # For label options, see #label_w_small.
431
+ # For field options, see #date_picker.
432
+ #
433
+ def datepicker_form_group(method, options = {})
434
+ gopt, lopt, fopt = split_form_group_options(options)
435
+ lbl = label_w_small(method, lopt)
436
+ fld = gopt[:wrap].call(date_picker(method, fopt))
437
+ form_group lbl, fld, gopt
438
+ end
439
+
440
+ ##
441
+ # Creates a standard form group with a multiple input control.
442
+ #
443
+ # The +options+ is a hash containing label, field, and group options.
444
+ # Prefix label options with +label_+ and field options with +field_+.
445
+ # All other options will apply to the group itself.
446
+ #
447
+ # Group options:
448
+ #
449
+ # class::
450
+ # The CSS class for the form group. Defaults to 'form-group'.
451
+ #
452
+ # style::
453
+ # Any styles to apply to the form group.
454
+ #
455
+ # For label options, see #label_w_small.
456
+ # For field options, see #multi_input_field.
457
+ #
458
+ def multi_input_form_group(methods, options = {})
459
+ gopt, lopt, fopt = split_form_group_options(options)
460
+ lopt[:text] ||= gopt[:label]
461
+ if lopt[:text].blank?
462
+ lopt[:text] = methods.map {|k,_| k.to_s.humanize }.join(', ')
463
+ end
464
+ lbl = label_w_small(methods.map{|k,_| k}.first, lopt)
465
+ fld = gopt[:wrap].call(multi_input(methods, fopt))
466
+ form_group lbl, fld, gopt
467
+ end
468
+
469
+ ##
470
+ # Creates a standard form group with a checkbox field.
471
+ #
472
+ # The +options+ is a hash containing label, field, and group options.
473
+ # Prefix label options with +label_+ and field options with +field_+.
474
+ # All other options will apply to the group itself.
475
+ #
476
+ # Group options:
477
+ #
478
+ # class::
479
+ # The CSS class for the form group.
480
+ #
481
+ # h_align::
482
+ # Create a checkbox aligned to a certain column (1-12) if set.
483
+ # If not set, then a regular form group is generated.
484
+ #
485
+ # For label options, see #label_w_small.
486
+ # For field options, see {FormHelper#check_box}[http://apidock.com/rails/ActionView/Helpers/FormHelper/check_box].
487
+ #
488
+ def check_box_form_group(method, options = {})
489
+ gopt, lopt, fopt = split_form_group_options({ class: 'checkbox', field_class: ''}.merge(options))
490
+
491
+ if gopt[:h_align]
492
+ gopt[:class] = gopt[:class].blank? ?
493
+ "col-sm-#{12-gopt[:h_align]} col-sm-offset-#{gopt[:h_align]}" :
494
+ "#{gopt[:class]} col-sm-#{12-gopt[:h_align]} col-sm-offset-#{gopt[:h_align]}"
495
+ end
496
+
497
+ lbl = label method do
498
+ check_box(method, fopt) +
499
+ CGI::escape_html(lopt[:text] || method.to_s.humanize) +
500
+ (lopt[:small_text] ? " <small>(#{CGI::escape_html lopt[:small_text]})</small>" : '').html_safe
501
+ end
502
+
503
+ "<div class=\"#{gopt[:h_align] ? 'row' : 'form-group'}\"><div class=\"#{gopt[:class]}\">#{lbl}</div></div>".html_safe
504
+ end
505
+
506
+ ##
507
+ # Creates a standard form group with a collection select field.
508
+ #
509
+ # The +collection+ should be an enumerable object (responds to 'each').
510
+ #
511
+ # The +value_method+ would be the method to call on the objects in the collection to get the value.
512
+ # This default to 'to_s' and is appropriate for any array of strings.
513
+ #
514
+ # The +text_method+ would be the method to call on the objects in the collection to get the display text.
515
+ # This defaults to 'to_s' as well, and should be appropriate for most objects.
516
+ #
517
+ # The +options+ is a hash containing label, field, and group options.
518
+ # Prefix label options with +label_+ and field options with +field_+.
519
+ # All other options will apply to the group itself.
520
+ #
521
+ # Group options:
522
+ #
523
+ # class::
524
+ # The CSS class for the form group. Defaults to 'form-group'.
525
+ #
526
+ # style::
527
+ # Any styles to apply to the form group.
528
+ #
529
+ # For label options, see #label_w_small.
530
+ # For field options, see {FormOptionsHelper#collection_select}[http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/collection_select].
531
+ #
532
+ def select_form_group(method, collection, value_method = :to_s, text_method = :to_s, options = {})
533
+ gopt, lopt, fopt = split_form_group_options({ field_include_blank: true }.merge(options))
534
+ lbl = label_w_small(method, lopt)
535
+ opt = {}
536
+ [:include_blank, :prompt, :include_hidden].each do |attr|
537
+ if fopt[attr] != nil
538
+ opt[attr] = fopt[attr]
539
+ fopt.except! attr
540
+ end
541
+ end
542
+ fld = gopt[:wrap].call(collection_select(method, collection, value_method, text_method, opt, fopt))
543
+ form_group lbl, fld, gopt
544
+ end
545
+
546
+ ##
547
+ # Adds a recaptcha challenge to the form configured to set the specified attribute to the recaptcha response.
548
+ #
549
+ # Valid options:
550
+ # theme::
551
+ # Can be :dark or :light, defaults to :light.
552
+ # type::
553
+ # Can be :image or :audio, defaults to :image.
554
+ # size::
555
+ # Can be :compact or :normal, defaults to :normal.
556
+ # tab_index::
557
+ # Can be any valid integer if you want a specific tab order, defaults to 0.
558
+ #
559
+ def recaptcha(method, options = {})
560
+ Incline::Recaptcha::Tag.new(@object_name, method, @template, options).render
561
+ end
562
+
563
+
564
+ private
565
+
566
+ def form_group(lbl, fld, opt)
567
+ ret = '<div'
568
+ ret += " class=\"#{CGI::escape_html opt[:class]}" unless opt[:class].blank?
569
+ ret += '"'
570
+ ret += " style=\"#{CGI::escape_html opt[:style]}\"" unless opt[:style].blank?
571
+ ret += ">#{lbl}#{fld}</div>"
572
+ ret.html_safe
573
+ end
574
+
575
+ def split_form_group_options(options)
576
+ options = {class: 'form-group', field_class: 'form-control'}.merge(options || {})
577
+ group = {}
578
+ label = {}
579
+ field = {}
580
+
581
+ options.keys.each do |k|
582
+ sk = k.to_s
583
+ if sk.index('label_') == 0
584
+ label[sk[6..-1].to_sym] = options[k]
585
+ elsif sk.index('field_') == 0
586
+ field[sk[6..-1].to_sym] = options[k]
587
+ else
588
+ group[k.to_sym] = options[k]
589
+ end
590
+ end
591
+
592
+ group[:wrap] = Proc.new do |fld|
593
+ fld
594
+ end
595
+ if group[:h_align]
596
+ if group[:h_align].is_a?(::TrueClass)
597
+ l = 3
598
+ else
599
+ l = group[:h_align].to_i
600
+ end
601
+ l = 1 if l < 1
602
+ l = 6 if l > 6
603
+ f = 12 - l
604
+ group[:h_align] = l
605
+ label[:class] = label[:class].blank? ? "col-sm-#{l} control-label" : "#{label[:class]} col-sm-#{l} control-label"
606
+ group[:wrap] = Proc.new do |fld|
607
+ "<div class=\"col-sm-#{f}\">#{fld}</div>"
608
+ end
609
+ end
610
+
611
+ [group, label, field]
612
+ end
613
+
614
+ end
615
+ end
616
+
617
+ ActionView::Helpers::FormBuilder.include Incline::Extensions::FormBuilder
@@ -0,0 +1,54 @@
1
+ require 'incline/number_formats'
2
+ require 'active_record'
3
+
4
+ module Incline::Extensions
5
+ ##
6
+ # Patches the ActiveRecord Integer type to be able to accept more numbers.
7
+ #
8
+ # Specifically this will allow comma delimited numbers to be provided to active record models.
9
+ module IntegerValue
10
+
11
+ ##
12
+ # Patches the ActiveRecord Integer type.
13
+ def self.included(base) #:nodoc:
14
+ base.class_eval do
15
+
16
+ private
17
+
18
+ undef cast_value
19
+
20
+ def cast_value(value)
21
+ begin
22
+ case value
23
+ when true then 1
24
+ when false then 0
25
+ when ::String
26
+ # 1,234.56789
27
+ if value =~ Incline::NumberFormats::WITH_DELIMITERS
28
+ value = value.gsub(',', '')
29
+ end
30
+ if value =~ Incline::NumberFormats::WITHOUT_DELIMITERS
31
+ value.to_i
32
+ else
33
+ nil
34
+ end
35
+ else
36
+ if value.respond_to?(:to_i)
37
+ value.to_i
38
+ else
39
+ nil
40
+ end
41
+ end
42
+ rescue
43
+ Incline::Log::warn "Failed to parse #{value.inspect}: #{$!.message}"
44
+ nil
45
+ end
46
+ end
47
+
48
+ end
49
+ end
50
+
51
+ end
52
+ end
53
+
54
+ ActiveRecord::Type::Integer.include Incline::Extensions::IntegerValue
@@ -0,0 +1,38 @@
1
+ require 'rails/generators'
2
+ require 'generators/rails/jbuilder_generator'
3
+
4
+ module Incline::Extensions
5
+ ##
6
+ # Adds _details view to jbuilder.
7
+ module JbuilderGenerator
8
+
9
+ ##
10
+ # Overrides the copy_view_files method to include the _details view.
11
+ def self.included(base)
12
+ base.class_eval do
13
+
14
+ source_root File.expand_path('../../../templates/jbuilder/scaffold', __FILE__)
15
+
16
+ undef copy_view_files
17
+
18
+ def copy_view_files
19
+ available_views.each do |view|
20
+ filename = filename_with_extensions(view)
21
+ template filename, File.join('app/views', controller_file_path, filename)
22
+ end
23
+ end
24
+
25
+ protected
26
+
27
+ def available_views
28
+ %w(index show _details)
29
+ end
30
+
31
+ end
32
+ end
33
+
34
+ end
35
+ end
36
+
37
+ Rails::Generators::JbuilderGenerator.include Incline::Extensions::JbuilderGenerator
38
+