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
@@ -0,0 +1,35 @@
1
+
2
+ module BarkestCore
3
+ ##
4
+ # Gives the ability to hunt for a 'main_app' helper if a URL helper is missing.
5
+ module MainAppUrlHelper
6
+
7
+ # :nodoc:
8
+ def self.included(base)
9
+ base.class_eval do
10
+
11
+ # :nodoc:
12
+ alias :barkest_core_original_method_missing :method_missing
13
+
14
+ # :nodoc:
15
+ def method_missing(method, *args, &block)
16
+
17
+ if respond_to?(:main_app)
18
+ main_app = send(:main_app)
19
+ if main_app && main_app.respond_to?(method)
20
+ return main_app.send(method, *args, &block)
21
+ end
22
+ end
23
+
24
+ barkest_core_original_method_missing(method, *args, &block)
25
+ end
26
+
27
+ end
28
+ end
29
+
30
+ end
31
+ end
32
+
33
+ ActionController::Base.include BarkestCore::MainAppUrlHelper
34
+ ActionMailer::Base.include BarkestCore::MainAppUrlHelper
35
+ ActionView::Base.include BarkestCore::MainAppUrlHelper
@@ -0,0 +1,367 @@
1
+ require 'prawn'
2
+ require 'prawn/table'
3
+ require 'prawn-rails'
4
+
5
+ ##
6
+ # Additions and improvements made to the Prawn::Document class.
7
+ class Prawn::Document
8
+ ##
9
+ # An object linked to the PDF document.
10
+ #
11
+ attr_accessor :object
12
+
13
+ ##
14
+ # Grabs a value from the object, similar to how form helpers do.
15
+ #
16
+ def object_field_value(method)
17
+ meth = "#{method}_before_type_cast"
18
+ if object && object.respond_to?(meth)
19
+ object.send(meth)
20
+ elsif object && object.respond_to?(method)
21
+ object.send(method)
22
+ else
23
+ method.to_s.humanize
24
+ end
25
+ end
26
+
27
+ ##
28
+ # Gets the footer values for the current page.
29
+ #
30
+ # Returns an array.
31
+ #
32
+ def footer_values
33
+ @footer_values ||= []
34
+ @footer_values[@page_number] ||= []
35
+ end
36
+
37
+ ##
38
+ # Sets the footer values for the current page.
39
+ #
40
+ # The +values+ should be provided as an array with up to three values.
41
+ # The first value is the left text, the second is the center text, and the third is the right text.
42
+ #
43
+ # [ 'Left', 'Center', 'Right' ]
44
+ #
45
+ # Any value that is nil will get replaced with the default value for the position based on how the PDF
46
+ # document was configured. This is of course, only true if you are using the PdfHelper::pdf_doc helper function.
47
+ # If you are working with the document yourself, this is a place to cache the footer values for later usage.
48
+ #
49
+ def footer_values=(values)
50
+ @footer_values ||= []
51
+ values = [values] * 3 unless values.is_a?(Array)
52
+ @footer_values[@page_number] = values
53
+ end
54
+
55
+ ##
56
+ # Uses the grid system to create a bounding box and then executes the provided code block.
57
+ #
58
+ # The bounding box can be defined in percentage as opposed to absolutes.
59
+ #
60
+ # Valid options:
61
+ #
62
+ # rectangle::
63
+ # Allows you to specify the dimensions of the box with a single value. You can provide an array or a hash
64
+ # to this option.
65
+ # [ column, row, width, height ]
66
+ # { :column => ?, :row => ?, :width => ?, :height => ? }
67
+ # { :left => ?, :top => ?, :width => ?, :height => ? }
68
+ #
69
+ # column::
70
+ # Sets the starting column for the bounding box.
71
+ # This will be overridden if +rectangle+ is also set.
72
+ # This can be either an absolute grid location (5) or a percentage (5%).
73
+ #
74
+ # row::
75
+ # Sets the starting row for the bounding box.
76
+ # This will be overridden if +rectangle+ is also set.
77
+ # This can be either an absolute grid location (5) or a percentage (5%).
78
+ #
79
+ # width::
80
+ # Sets the width for the bounding box.
81
+ # This will be overridden if +rectangle+ is also set.
82
+ # This can be either an absolute grid location (5) or a percentage (5%).
83
+ #
84
+ # height::
85
+ # Sets the height for the bounding box.
86
+ # This will be overridden if +rectangle+ is also set.
87
+ # This can be either an absolute grid location (5) or a percentage (5%).
88
+ #
89
+ # fill_width::
90
+ # If set, the width will spring out to fill the grid from the starting column.
91
+ # This overrides both +rectangle+ and +width+.
92
+ #
93
+ # fill_height::
94
+ # If set, the height will spring out to fill the grid from the starting row.
95
+ # This overrides both +rectangle+ and +height+.
96
+ #
97
+ def layout(options = {}, &block)
98
+ options ||= {}
99
+
100
+ col_max = grid.columns
101
+ row_max = grid.rows
102
+
103
+ if options[:rectangle]
104
+ r = options[:rectangle]
105
+ if r.is_a?(Array)
106
+ options[:column] ||= r[0]
107
+ options[:row] ||= r[1]
108
+ options[:width] ||= r[2]
109
+ options[:height] ||= r[3]
110
+ elsif r.is_a?(Hash)
111
+ options[:column] ||= r[:column] || r[:left]
112
+ options[:row] ||= r[:row] || r[:top]
113
+ options[:width] ||= r[:width]
114
+ options[:height] ||= r[:height]
115
+ end
116
+ end
117
+
118
+ col = options[:column] || 1
119
+ row = options[:row] || 1
120
+ width = options[:width] || 1
121
+ height = options[:height] || 1
122
+
123
+ ptov = Proc.new do |pval,max,plus|
124
+ if pval.is_a?(String)
125
+ if pval[-1] == '%'
126
+ pval = (pval.to_f * 0.01 * max).to_i + plus
127
+ pval = max if pval > max
128
+ pval = 1 if pval < 1
129
+ else
130
+ pval = pval.to_i
131
+ end
132
+ end
133
+ pval
134
+ end
135
+
136
+ col = ptov.call(col, col_max, 1)
137
+ width = ptov.call(width, col_max, 0)
138
+ row = ptov.call(row, row_max, 1)
139
+ height = ptov.call(height, row_max, 0)
140
+
141
+ width = col_max - col + 1 if options[:fill_width]
142
+ height = row_max - row + 1 if options[:fill_height]
143
+
144
+ raise StandardError.new("column must be between 1 and #{col_max}") unless col >= 1 && col <= col_max
145
+ raise StandardError.new("row must be between 1 and #{row_max}") unless row >= 1 && row <= row_max
146
+ raise StandardError.new('width is invalid') unless width >= 1 && col + width - 1 <= col_max
147
+ raise StandardError.new('height is invalid') unless height >= 1 && row + height - 1 <= row_max
148
+
149
+ col -= 1
150
+ row -= 1
151
+
152
+ grid([row, col], [row + height - 1, col + width - 1]).bounding_box(&block)
153
+ end
154
+
155
+ ##
156
+ # Creates a header row for a page.
157
+ #
158
+ # The text is 20pt and bold.
159
+ # The +height+ would be the height you want your header row to be in percent. 4 is a good starting point for portrait.
160
+ #
161
+ #
162
+ def header(height, *columns)
163
+ columns = columns.to_a.map{ |v| preprocess_table_data(v) }
164
+ layout column: 1, row: 1, fill_width: true, height: height do
165
+ table [
166
+ # row 1
167
+ columns
168
+ ],
169
+ width_ratio: 1.0,
170
+ cell_style: {
171
+ borders: [ :bottom ],
172
+ border_width: 1.5,
173
+ padding: [ 0, 0, 0, 0 ],
174
+ font_style: :bold,
175
+ size: 20
176
+ }
177
+ end
178
+ end
179
+
180
+ ##
181
+ # Creates a bounded box inside of the current bounds with side and top padding, then it executes the provided
182
+ # code block.
183
+ #
184
+ # This can be useful to provide padding to the left and above text inside of a layout box.
185
+ #
186
+ def padded(padding = 2, &block)
187
+ r = bounds
188
+ padding ||= 2
189
+ bounding_box([padding, r.top - padding], width: r.width - (2 * padding), &block)
190
+ end
191
+
192
+ ##
193
+ # Creates a small box that can be used as a checkbox.
194
+ #
195
+ # The +x+ and +y+ parameters are absolute positions for the checkbox.
196
+ #
197
+ # Valid options:
198
+ #
199
+ # checked::
200
+ # If set, the box will be marked with an X.
201
+ #
202
+ # stroke_width::
203
+ # The line width to draw the checkbox with. Defaults to 0.5.
204
+ #
205
+ # size::
206
+ # The size of the checkbox. Defaults to 8.0.
207
+ #
208
+ # rounded::
209
+ # Set to true to have rounded corners. Defaults to false.
210
+ #
211
+ # color::
212
+ # The color to draw the checkbox in. Defaults to '000000' (black).
213
+ #
214
+ # label::
215
+ # An optional label to follow the checkbox.
216
+ #
217
+ def checkbox(x, y, options = { })
218
+ options = { stroke_width: 0.5, size: 8, rounded: false, color: '000000' }.merge(options || {})
219
+ stored_line_width = line_width
220
+ stored_color = stroke_color
221
+ self.line_width = options[:stroke_width]
222
+ self.stroke_color = options[:color]
223
+ if options[:rounded]
224
+ stroke_rounded_rectangle [x, y], options[:size], options[:size], options[:size] * 0.2
225
+ else
226
+ stroke_rectangle [x, y], options[:size], options[:size]
227
+ end
228
+ if options[:checked]
229
+ self.stroke_color = '000000'
230
+ self.line_width = options[:size] * 0.125
231
+ offset = options[:size] * 0.1
232
+ stroke_line [x + offset, y - offset], [x + options[:size] - offset, y - options[:size] + offset]
233
+ stroke_line [x + offset, y - options[:size] + offset], [x + options[:size] - offset, y - offset]
234
+ end
235
+ self.line_width = stored_line_width
236
+ self.stroke_color = stored_color
237
+ unless options[:label].blank?
238
+ text_box options[:label], at: [x + options[:size] + 2.pt, y]
239
+ end
240
+ end
241
+
242
+ ##
243
+ # Strokes the bottom of the current bounds.
244
+ #
245
+ # The +stroke_width+ is the thickness of the line to draw.
246
+ #
247
+ def stroke_bottom(stroke_width = 0.5)
248
+ stored_line_width = line_width
249
+ self.line_width = stroke_width
250
+ horizontal_line 0, bounds.width, at: 0
251
+ self.line_width = stored_line_width
252
+ end
253
+
254
+ ##
255
+ # Gets a filesystem path to a font file.
256
+ #
257
+ def asset_font_path(font_name)
258
+ File.expand_path("../../assets/fonts/#{font_name}", __FILE__)
259
+ end
260
+
261
+ ##
262
+ # Gets a filesystem path to an image file.
263
+ #
264
+ def asset_image_path(image_name)
265
+ File.expand_path("../../assets/images/#{image_name}", __FILE__)
266
+ end
267
+
268
+ ##
269
+ # Draws text with a line under it.
270
+ #
271
+ # Valid options:
272
+ #
273
+ # at::
274
+ # The position to draw the text. Defaults to [0, 0].
275
+ #
276
+ # width::
277
+ # The width of the text to draw. Defaults to the actual width of the text.
278
+ # You can set this to either limit the width of the underline field, or
279
+ # ensure that the underline field is large enough to fill a void (ie - on a form).
280
+ #
281
+ # height::
282
+ # The height of the text to draw. Defaults to the actual height of the text within the width specified.
283
+ # This can be set to prevent line wrapping if you also specified a width.
284
+ #
285
+ def underline(text, options = {})
286
+ options = { at: [0, 0] }.merge(options || {})
287
+ text ||= ''
288
+ text = Prawn::Text::NBSP if text.empty?
289
+ text_width = options[:width] || width_of(text)
290
+ text_height = options[:height] || height_of(text, width: text_width)
291
+ text_box text, at: options[:at], width: text_width, height: text_height
292
+ stored_line_width = line_width
293
+ stored_stroke_color = stroke_color
294
+ self.line_width = 0.5
295
+ self.stroke_color = '000000'
296
+ y = options[:at][1] - text_height + 2.pt
297
+ x = options[:at][0]
298
+ stroke_line [x, y], [ x + text_width, y ]
299
+ self.line_width = stored_line_width
300
+ self.stroke_color = stored_stroke_color
301
+ end
302
+
303
+ ##
304
+ # Generates a text field for a form.
305
+ #
306
+ # Your Name:______________
307
+ #
308
+ # The label is required, but the value is optional.
309
+ #
310
+ # Valid options:
311
+ #
312
+ # at::
313
+ # The position to draw the field. Defaults to [0,0].
314
+ #
315
+ # width::
316
+ # The width of the field. Defaults to 2 in. This is the total width
317
+ # including both the label and the value.
318
+ #
319
+ def text_field(label, value = nil, options = {})
320
+ options = { at: [0, 0], width: 2.0.in }.merge(options || {})
321
+
322
+ value ||= ''
323
+ label_height = height_of(label)
324
+ label_width = width_of(label) + 2.pt
325
+ value_width = options[:width] - label_width
326
+ actual_value_width = width_of(value) + 2.pt
327
+ if value_width < actual_value_width * 0.5
328
+ raise StandardError.new('The width of the text field is not large enough to accomodate the label.')
329
+ end
330
+ y = options[:at][1]
331
+ x = options[:at][0] + label_width
332
+
333
+ text_box label, at: options[:at], height: label_height, width: label_width
334
+ text_box value, at: [ x + 2.pt, y ], height: label_height, width: value_width - 4.pt, overflow: :shrink_to_fit
335
+ stored_line_width = line_width
336
+ stored_line_color = stroke_color
337
+ self.line_width = 0.5
338
+ self.stroke_color = '000000'
339
+ stroke_line [x, y - label_height], [x + value_width, y - label_height]
340
+ self.line_width = stored_line_width
341
+ self.stroke_color = stored_line_color
342
+ end
343
+
344
+ ##
345
+ # Reverses a y coordinate to be from the top of the bounding box instead of from the bottom.
346
+ #
347
+ def from_top(y)
348
+ bounds.top - bounds.bottom - y
349
+ end
350
+
351
+ ##
352
+ # Changes to the specified font style.
353
+ #
354
+ # If a block is provided, the block is executed and then the font style is reverted.
355
+ #
356
+ def font_style(style)
357
+ f = font
358
+ if block_given?
359
+ font(f.name, size: font_size, style: style) do
360
+ yield
361
+ end
362
+ else
363
+ font(f.name, size: font_size, style: style)
364
+ end
365
+ end
366
+
367
+ end
@@ -0,0 +1,131 @@
1
+ require 'prawn'
2
+ require 'prawn/table'
3
+
4
+ ##
5
+ # Improvements made to the Prawn::Table::Interface module.
6
+ module Prawn::Table::Interface
7
+ private
8
+
9
+ # process and remove custom table options.
10
+ def preprocess_table_options(options)
11
+
12
+ # get the maximum width.
13
+ max_width = bounds.right - bounds.left
14
+
15
+ # allow column and table widths to be specified as ratios.
16
+ { column_ratios: :column_widths, width_ratio: :width }.each do |k,v|
17
+ if options[k]
18
+ # extract the option.
19
+ ratio = options[k]
20
+ options.except!(k)
21
+
22
+ if ratio.is_a?(Array)
23
+ options[v] = ratio.map { |r| (r > 1 ? r/100.0 : r).to_f * max_width }
24
+ elsif ratio.respond_to?(:to_f)
25
+ options[v] = (ratio > 1 ? ratio/100.0 : ratio).to_f * max_width
26
+ end
27
+ end
28
+ end
29
+
30
+ options
31
+ end
32
+
33
+ # process the table data and verify all values are strings.
34
+ def preprocess_table_data(data)
35
+ # recurse into arrays.
36
+ if data.is_a?(Array)
37
+ data = data.map { |item| preprocess_table_data(item) }
38
+
39
+ # verify the hash :content value is a string.
40
+ elsif data.is_a?(Hash)
41
+ data[:content] = preprocess_table_data(data[:content])
42
+
43
+ # symbols should resolve to methods on the attached object.
44
+ # we filter it through the preprocess function again just to make sure it's good.
45
+ elsif data.is_a?(Symbol)
46
+ data = preprocess_table_data(object_field_value(data))
47
+
48
+ # Nil, True, False, Date, Time, and Numeric values should be converted to strings.
49
+ elsif data.nil? || data.is_a?(Numeric) || data.is_a?(Date) || data.is_a?(Time) || data.is_a?(TrueClass) || data.is_a?(FalseClass)
50
+ data = data.to_s
51
+ end
52
+
53
+ data
54
+ end
55
+
56
+ public
57
+
58
+ alias :barkest_core_original_table :table
59
+
60
+ ##
61
+ # An overridden version of the table method allowing for more powerful options and dynamic data.
62
+ #
63
+ # The +data+ gains the ability to receive values from a linked object. Much like form helpers, if you
64
+ # specify :name for a cell value, and there is a linked object, the linked object will be searched for a :name
65
+ # attribute. If that exists, then the value of the attribute is used, otherwise the symbol is converted to a
66
+ # string and that value is used.
67
+ #
68
+ # The +options+ hash gains :column_ratios and :width_ratio keys that automatically set the :column_widths and
69
+ # :width keys based on the current bounding box.
70
+ #
71
+ # { :column_rations => [ 5, 25, 10, 10 ], :width_ratio => 50 }
72
+ #
73
+ # A potential weakness would be that the :column_ratios are a percentage of the maximum width, not the table
74
+ # width. In the example above, the table is 50% of the maximum width and the column widths add up to 50%.
75
+ #
76
+ # After the table is constructed, it is rendered to the PDF.
77
+ #
78
+ def table(data, options = {}, &block)
79
+ options = preprocess_table_options(options)
80
+ data = preprocess_table_data(data)
81
+
82
+ t = Prawn::Table.new(data, self, options, &block)
83
+ t.draw
84
+ t
85
+ end
86
+
87
+ alias :barkest_core_original_make_table :make_table
88
+
89
+ ##
90
+ # This is the same as #table except the table is not rendered after construction.
91
+ #
92
+ def make_table(data, options = {}, &block)
93
+ options = preprocess_table_options(options)
94
+ data = preprocess_table_data(data)
95
+
96
+ Prawn::Table.new(data, self, options, &block)
97
+ end
98
+
99
+ ##
100
+ # Uses a TableBuilder to construct a table and then renders the results to the PDF.
101
+ #
102
+ def table_builder(options = {}, &block)
103
+ t = BarkestCore::PdfTableBuilder.new(self, options, &block).to_table
104
+ t.draw
105
+ t
106
+ end
107
+
108
+ ##
109
+ # Generates an array containing a label cell and a value cell.
110
+ #
111
+ # The label cell has a bold font, the value cell does not.
112
+ # Both cells inherit the shared_attribs.
113
+ #
114
+ def table_pair(label, value, shared_attribs = {})
115
+ bold_label = ({ bold_label: true }.merge(shared_attribs))[:bold_label]
116
+ shared_attribs.except!(:bold_label)
117
+
118
+ label = preprocess_table_data(label)
119
+ value = preprocess_table_data(value)
120
+
121
+ label = shared_attribs.merge(label.is_a?(Hash) ? label : { content: label })
122
+ value = shared_attribs.merge(value.is_a?(Hash) ? value : { content: value })
123
+
124
+ if bold_label
125
+ label = label.merge({ font_style: :bold })
126
+ end
127
+
128
+ [ label, value ]
129
+ end
130
+
131
+ end