barkest_core 1.5.3.0

Sign up to get free protection for your applications and to get access to all the features.
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