brisk-bills 0.6.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 (524) hide show
  1. data/CHANGELOG +8 -0
  2. data/COPYING +674 -0
  3. data/COPYING.LESSER +165 -0
  4. data/INSTALL +5 -0
  5. data/README +22 -0
  6. data/Rakefile +11 -0
  7. data/TODO.txt +112 -0
  8. data/app/controllers/admin/activities_controller.rb +151 -0
  9. data/app/controllers/admin/activities_controller/adjustment.rb +16 -0
  10. data/app/controllers/admin/activities_controller/labor.rb +119 -0
  11. data/app/controllers/admin/activities_controller/labor/slimtimer.rb +28 -0
  12. data/app/controllers/admin/activities_controller/material.rb +20 -0
  13. data/app/controllers/admin/activities_controller/proposal.rb +15 -0
  14. data/app/controllers/admin/activities_with_prices_controller.rb +68 -0
  15. data/app/controllers/admin/adjustments_controller.rb +22 -0
  16. data/app/controllers/admin/client_accounting_controller.rb +49 -0
  17. data/app/controllers/admin/client_financial_transactions_controller.rb +24 -0
  18. data/app/controllers/admin/client_representatives_controller.rb +31 -0
  19. data/app/controllers/admin/clients_controller.rb +31 -0
  20. data/app/controllers/admin/employee_client_labor_rate_controller.rb +30 -0
  21. data/app/controllers/admin/employees_controller.rb +32 -0
  22. data/app/controllers/admin/employees_controller/slimtimer.rb +29 -0
  23. data/app/controllers/admin/invoices_controller.rb +165 -0
  24. data/app/controllers/admin/labors_controller.rb +103 -0
  25. data/app/controllers/admin/labors_controller/slimtimer.rb +31 -0
  26. data/app/controllers/admin/materials_controller.rb +24 -0
  27. data/app/controllers/admin/payments_controller.rb +75 -0
  28. data/app/controllers/admin/proposals_controller.rb +22 -0
  29. data/app/controllers/admin/settings_controller.rb +23 -0
  30. data/app/controllers/application_controller.rb +22 -0
  31. data/app/controllers/authentication_controller.rb +131 -0
  32. data/app/helpers/activity_type_model_helper.rb +194 -0
  33. data/app/helpers/admin/activities_helper.rb +110 -0
  34. data/app/helpers/admin/activities_helper/labor_helper.rb +28 -0
  35. data/app/helpers/admin/activities_helper/proposal_helper.rb +11 -0
  36. data/app/helpers/admin/activities_helper/slimtimer_helper.rb +13 -0
  37. data/app/helpers/admin/activities_with_prices_helper.rb +17 -0
  38. data/app/helpers/admin/activity_tax_controller_helper.rb +48 -0
  39. data/app/helpers/admin/activity_tax_field_helper.rb +33 -0
  40. data/app/helpers/admin/activity_type_controller_helper.rb +83 -0
  41. data/app/helpers/admin/activity_type_field_helper.rb +45 -0
  42. data/app/helpers/admin/adjustments_helper.rb +5 -0
  43. data/app/helpers/admin/client_accounting_helper.rb +13 -0
  44. data/app/helpers/admin/client_financial_transactions_helper.rb +9 -0
  45. data/app/helpers/admin/client_representatives_helper.rb +26 -0
  46. data/app/helpers/admin/clients_helper.rb +6 -0
  47. data/app/helpers/admin/employee_client_labor_rate_helper.rb +77 -0
  48. data/app/helpers/admin/employees_helper.rb +9 -0
  49. data/app/helpers/admin/employees_helper/slimtimer_helper.rb +2 -0
  50. data/app/helpers/admin/has_credential_column_helper.rb +60 -0
  51. data/app/helpers/admin/invoices_helper.rb +59 -0
  52. data/app/helpers/admin/is_active_column_helper.rb +46 -0
  53. data/app/helpers/admin/labors_helper.rb +20 -0
  54. data/app/helpers/admin/labors_helper/slimtimer_helper.rb +13 -0
  55. data/app/helpers/admin/materials_helper.rb +5 -0
  56. data/app/helpers/admin/payments_helper.rb +41 -0
  57. data/app/helpers/admin/proposals_helper.rb +3 -0
  58. data/app/helpers/admin/settings_helper.rb +8 -0
  59. data/app/helpers/admin_layout_helper.rb +91 -0
  60. data/app/helpers/application_helper.rb +27 -0
  61. data/app/helpers/authentication_helper.rb +61 -0
  62. data/app/helpers/extensible_object_helper.rb +28 -0
  63. data/app/helpers/has_credential_model_helper.rb +39 -0
  64. data/app/helpers/invoice_pdf_helper.rb +71 -0
  65. data/app/helpers/is_active_model_helper.rb +40 -0
  66. data/app/helpers/money_model_helper.rb +21 -0
  67. data/app/model_views/client_accounting.rb +5 -0
  68. data/app/model_views/client_financial_transaction.rb +15 -0
  69. data/app/model_views/invoices_with_total.rb +36 -0
  70. data/app/models/activity.rb +104 -0
  71. data/app/models/activity/adjustment.rb +34 -0
  72. data/app/models/activity/labor.rb +91 -0
  73. data/app/models/activity/labor/slimtimer.rb +28 -0
  74. data/app/models/activity/material.rb +16 -0
  75. data/app/models/activity/proposal.rb +17 -0
  76. data/app/models/activity_type.rb +2 -0
  77. data/app/models/client.rb +93 -0
  78. data/app/models/client_eventlog.rb +5 -0
  79. data/app/models/client_representative.rb +22 -0
  80. data/app/models/credential.rb +195 -0
  81. data/app/models/employee.rb +49 -0
  82. data/app/models/employee/labor.rb +13 -0
  83. data/app/models/employee/slimtimer.rb +43 -0
  84. data/app/models/employee_client_labor_rate.rb +20 -0
  85. data/app/models/invoice.rb +280 -0
  86. data/app/models/invoice_payment.rb +8 -0
  87. data/app/models/notifier.rb +85 -0
  88. data/app/models/payment.rb +108 -0
  89. data/app/models/payment_method.rb +7 -0
  90. data/app/models/setting.rb +39 -0
  91. data/app/models/slimtimer_task.rb +6 -0
  92. data/app/models/slimtimer_time_entry.rb +69 -0
  93. data/app/views/admin/activities/_adjustment_column.rhtml +23 -0
  94. data/app/views/admin/activities/_form.rhtml +20 -0
  95. data/app/views/admin/activities/_form_attribute.rhtml +12 -0
  96. data/app/views/admin/activities/_labor_column.rhtml +17 -0
  97. data/app/views/admin/activities/_material_column.rhtml +10 -0
  98. data/app/views/admin/activities/_proposal_column.rhtml +11 -0
  99. data/app/views/admin/activities_with_prices/move_to_invoice.rhtml +44 -0
  100. data/app/views/admin/activities_with_prices/move_to_invoice.rjs +9 -0
  101. data/app/views/admin/invoices/download.rpdf +224 -0
  102. data/app/views/authentication/email.rjs +9 -0
  103. data/app/views/authentication/login.rhtml +75 -0
  104. data/app/views/authentication/login.rjs +14 -0
  105. data/app/views/authentication/reset_password_via_token.rhtml +16 -0
  106. data/app/views/authentication/reset_password_via_token.rjs +6 -0
  107. data/app/views/authentication/sign_in_error.rjs +2 -0
  108. data/app/views/layouts/_navigation_tree.rhtml +15 -0
  109. data/app/views/layouts/admin.rhtml +26 -0
  110. data/app/views/layouts/public.rhtml +18 -0
  111. data/app/views/notifier/_email_footer.html.rhtml +12 -0
  112. data/app/views/notifier/_email_footer.plain.rhtml +3 -0
  113. data/app/views/notifier/_email_header.html.rhtml +53 -0
  114. data/app/views/notifier/invoice_available.html.rhtml +5 -0
  115. data/app/views/notifier/invoice_available.plain.rhtml +4 -0
  116. data/app/views/notifier/reset_password_requested.html.rhtml +15 -0
  117. data/app/views/notifier/reset_password_requested.plain.rhtml +9 -0
  118. data/bin/brisk-bills +51 -0
  119. data/config/boot.rb +164 -0
  120. data/config/environment.rb +39 -0
  121. data/config/environments/development.rb +17 -0
  122. data/config/environments/production.rb +18 -0
  123. data/config/environments/test.rb +19 -0
  124. data/config/locale/en.rb +26 -0
  125. data/config/routes.rb +20 -0
  126. data/config/secrets.yml +2 -0
  127. data/db/migrate/001_create_employees.rb +14 -0
  128. data/db/migrate/002_create_employee_slimtimers.rb +14 -0
  129. data/db/migrate/003_create_slimtimer_tasks.rb +21 -0
  130. data/db/migrate/004_create_slimtimer_time_entries.rb +25 -0
  131. data/db/migrate/005_create_clients.rb +12 -0
  132. data/db/migrate/006_create_client_representatives.rb +16 -0
  133. data/db/migrate/007_create_client_eventlogs.rb +13 -0
  134. data/db/migrate/008_create_activities.rb +17 -0
  135. data/db/migrate/009_create_activity_labors.rb +16 -0
  136. data/db/migrate/010_create_employee_client_labor_rates.rb +19 -0
  137. data/db/migrate/011_create_activity_adjustments.rb +16 -0
  138. data/db/migrate/012_create_activity_materials.rb +16 -0
  139. data/db/migrate/013_create_activity_proposals.rb +18 -0
  140. data/db/migrate/014_create_invoices.rb +16 -0
  141. data/db/migrate/015_create_payments.rb +18 -0
  142. data/db/migrate/016_create_payment_methods.rb +18 -0
  143. data/db/migrate/017_create_invoice_payments.rb +14 -0
  144. data/db/migrate/018_create_activity_types.rb +37 -0
  145. data/db/migrate/019_create_settings.rb +45 -0
  146. data/db/migrate/020_is_active_employees_clients.rb +11 -0
  147. data/db/migrate/021_create_views_and_indexes.rb +78 -0
  148. data/db/migrate/022_create_client_financial_transactions.rb +32 -0
  149. data/db/migrate/023_create_credentials_migrate_representatives.rb +133 -0
  150. data/db/migrate/024_updates_for_sales_tax.rb +91 -0
  151. data/db/migrate/025_alter_credentials_for_reset.rb +11 -0
  152. data/db/migrate/026_create_st_settings.rb +17 -0
  153. data/db/migrate/027_create_sessions.rb +16 -0
  154. data/db/migrate/028_money_to_cents.rb +136 -0
  155. data/db/schema.rb +301 -0
  156. data/lib/brisk-bills.rb +17 -0
  157. data/lib/brisk-bills/initializer.rb +100 -0
  158. data/lib/dti-navigation-menu/lib/dti-navigation-menu.rb +27 -0
  159. data/lib/generators/generator_base_extension.rb +16 -0
  160. data/lib/generators/instance/instance_generator.rb +117 -0
  161. data/lib/generators/instance/templates/databases/mysql.yml +47 -0
  162. data/lib/generators/instance/templates/instance_boot.rb +166 -0
  163. data/lib/generators/instance/templates/instance_environment.rb +65 -0
  164. data/lib/generators/instance/templates/instance_generate +18 -0
  165. data/lib/generators/instance/templates/instance_rakefile +3 -0
  166. data/lib/generators/instance/templates/instance_routes.rb +1 -0
  167. data/lib/tasks/create_last_months_invoices.rake +37 -0
  168. data/lib/tasks/credential_tasks.rake +47 -0
  169. data/lib/tasks/first_time_setup.rake +96 -0
  170. data/lib/tasks/instance.rake +27 -0
  171. data/lib/tasks/invoice_as_csv.rake +32 -0
  172. data/lib/tasks/package.rake +120 -0
  173. data/lib/tasks/slimtimer_import.rake +198 -0
  174. data/lib/utilities.rb +18 -0
  175. data/log/.keep +0 -0
  176. data/public/.htaccess +40 -0
  177. data/public/404.html +30 -0
  178. data/public/500.html +30 -0
  179. data/public/blank.html +33 -0
  180. data/public/blank_iframe.html +2 -0
  181. data/public/dispatch.cgi +10 -0
  182. data/public/dispatch.fcgi +24 -0
  183. data/public/dispatch.rb +10 -0
  184. data/public/favicon.ico +0 -0
  185. data/public/images/active_scaffold/DO_NOT_EDIT +2 -0
  186. data/public/images/active_scaffold/default/add.gif +0 -0
  187. data/public/images/active_scaffold/default/arrow_down.gif +0 -0
  188. data/public/images/active_scaffold/default/arrow_up.gif +0 -0
  189. data/public/images/active_scaffold/default/close.gif +0 -0
  190. data/public/images/active_scaffold/default/cross.png +0 -0
  191. data/public/images/active_scaffold/default/indicator-small.gif +0 -0
  192. data/public/images/active_scaffold/default/indicator.gif +0 -0
  193. data/public/images/active_scaffold/default/magnifier.png +0 -0
  194. data/public/images/background.gif +0 -0
  195. data/public/images/brisk-bills-logo.gif +0 -0
  196. data/public/images/calendar_date_select/calendar.gif +0 -0
  197. data/public/images/dti-logo.gif +0 -0
  198. data/public/images/dti-logo.jpg +0 -0
  199. data/public/images/favicon.ico +0 -0
  200. data/public/images/invoice-background.jpg +0 -0
  201. data/public/images/login-form-spinner.gif +0 -0
  202. data/public/images/nav-arrow.gif +0 -0
  203. data/public/images/notice-error.gif +0 -0
  204. data/public/images/notice-info.gif +0 -0
  205. data/public/images/rails.png +0 -0
  206. data/public/javascripts/active_scaffold/DO_NOT_EDIT +2 -0
  207. data/public/javascripts/active_scaffold/default/active_scaffold.js +430 -0
  208. data/public/javascripts/active_scaffold/default/dhtml_history.js +867 -0
  209. data/public/javascripts/active_scaffold/default/form_enhancements.js +114 -0
  210. data/public/javascripts/active_scaffold/default/rico_corner.js +370 -0
  211. data/public/javascripts/application.js +2 -0
  212. data/public/javascripts/briskbills-quick-helpers.js +9 -0
  213. data/public/javascripts/builder.js +136 -0
  214. data/public/javascripts/controls.js +963 -0
  215. data/public/javascripts/dragdrop.js +973 -0
  216. data/public/javascripts/effects.js +1128 -0
  217. data/public/javascripts/modalbox.js +573 -0
  218. data/public/javascripts/prototype.js +4320 -0
  219. data/public/javascripts/scriptaculous.js +58 -0
  220. data/public/javascripts/shadedborder.js +249 -0
  221. data/public/javascripts/slider.js +275 -0
  222. data/public/javascripts/sound.js +55 -0
  223. data/public/javascripts/unittest.js +568 -0
  224. data/public/robots.txt +1 -0
  225. data/public/stylesheets/active_scaffold/DO_NOT_EDIT +2 -0
  226. data/public/stylesheets/active_scaffold/default/stylesheet-ie.css +35 -0
  227. data/public/stylesheets/active_scaffold/default/stylesheet.css +809 -0
  228. data/public/stylesheets/admin/global.css +152 -0
  229. data/public/stylesheets/admin/pages.css +137 -0
  230. data/public/stylesheets/admin/screen.css +3 -0
  231. data/public/stylesheets/admin/structure.css +88 -0
  232. data/public/stylesheets/modalbox.css +95 -0
  233. data/public/stylesheets/public/global.css +36 -0
  234. data/public/stylesheets/public/pages.css +105 -0
  235. data/public/stylesheets/public/screen.css +3 -0
  236. data/public/stylesheets/public/structure.css +0 -0
  237. data/public/stylesheets/spinner.gif +0 -0
  238. data/script/about +3 -0
  239. data/script/breakpointer +3 -0
  240. data/script/console +3 -0
  241. data/script/dbconsole +3 -0
  242. data/script/destroy +3 -0
  243. data/script/generate +3 -0
  244. data/script/performance/benchmarker +3 -0
  245. data/script/performance/profiler +3 -0
  246. data/script/performance/request +3 -0
  247. data/script/plugin +3 -0
  248. data/script/process/inspector +3 -0
  249. data/script/process/reaper +3 -0
  250. data/script/process/spawner +3 -0
  251. data/script/runner +3 -0
  252. data/script/server +3 -0
  253. data/test/fixtures/activities.yml +28 -0
  254. data/test/fixtures/activity_adjustments.yml +7 -0
  255. data/test/fixtures/activity_labors.yml +25 -0
  256. data/test/fixtures/activity_materials.yml +7 -0
  257. data/test/fixtures/activity_proposals.yml +7 -0
  258. data/test/fixtures/activity_types.yml +23 -0
  259. data/test/fixtures/client_eventlogs.yml +5 -0
  260. data/test/fixtures/client_financial_transactions.yml +7 -0
  261. data/test/fixtures/client_representatives.yml +56 -0
  262. data/test/fixtures/clients.yml +172 -0
  263. data/test/fixtures/credentials.yml +34 -0
  264. data/test/fixtures/employee_client_labor_rates.yml +365 -0
  265. data/test/fixtures/employee_slimtimers.yml +19 -0
  266. data/test/fixtures/employees.yml +22 -0
  267. data/test/fixtures/invoice_payments.yml +7 -0
  268. data/test/fixtures/invoices.yml +7 -0
  269. data/test/fixtures/payment_methods.yml +7 -0
  270. data/test/fixtures/payments.yml +7 -0
  271. data/test/fixtures/settings.yml +7 -0
  272. data/test/fixtures/slimtimer_tasks.yml +5 -0
  273. data/test/fixtures/slimtimer_time_entries.yml +5 -0
  274. data/test/functional/admin/activities_controller_test.rb +8 -0
  275. data/test/functional/admin/adjustments_controller_test.rb +8 -0
  276. data/test/functional/admin/client_accounting_controller_test.rb +8 -0
  277. data/test/functional/admin/client_financial_transactions_controller_test.rb +8 -0
  278. data/test/functional/admin/client_representatives_controller_test.rb +8 -0
  279. data/test/functional/admin/clients_controller_test.rb +8 -0
  280. data/test/functional/admin/employee_client_labor_rate_controller_test.rb +8 -0
  281. data/test/functional/admin/employees/slimtimer_controller_test.rb +8 -0
  282. data/test/functional/admin/employees_controller_test.rb +8 -0
  283. data/test/functional/admin/invoices_controller_test.rb +8 -0
  284. data/test/functional/admin/labors_controller_test.rb +8 -0
  285. data/test/functional/admin/materials_controller_test.rb +8 -0
  286. data/test/functional/admin/payments_controller_test.rb +8 -0
  287. data/test/functional/admin/proposals_controller_test.rb +8 -0
  288. data/test/functional/admin/settings_controller_test.rb +8 -0
  289. data/test/functional/authentication_controller_test.rb +8 -0
  290. data/test/test_helper.rb +30 -0
  291. data/test/test_unit_factory_helper.rb +154 -0
  292. data/test/unit/activity/adjustment_test.rb +8 -0
  293. data/test/unit/activity/labor_test.rb +279 -0
  294. data/test/unit/activity/material_test.rb +8 -0
  295. data/test/unit/activity/proposal_test.rb +8 -0
  296. data/test/unit/activity_test.rb +83 -0
  297. data/test/unit/activity_type_test.rb +8 -0
  298. data/test/unit/client_eventlog_test.rb +10 -0
  299. data/test/unit/client_financial_transaction_test.rb +8 -0
  300. data/test/unit/client_representative_test.rb +10 -0
  301. data/test/unit/client_test.rb +24 -0
  302. data/test/unit/credential_test.rb +217 -0
  303. data/test/unit/employee/slimtimer_test.rb +10 -0
  304. data/test/unit/employee_client_labor_rate_test.rb +8 -0
  305. data/test/unit/employee_test.rb +25 -0
  306. data/test/unit/invoice_payment_test.rb +8 -0
  307. data/test/unit/invoice_test.rb +459 -0
  308. data/test/unit/notifier_test.rb +9 -0
  309. data/test/unit/payment_method_test.rb +8 -0
  310. data/test/unit/payment_test.rb +155 -0
  311. data/test/unit/setting_test.rb +8 -0
  312. data/test/unit/slimtimer_task_test.rb +10 -0
  313. data/test/unit/slimtimer_time_entry_test.rb +132 -0
  314. data/vendor/plugins/InlineAttachment-0.3.0-modified/README +79 -0
  315. data/vendor/plugins/InlineAttachment-0.3.0-modified/init.rb +2 -0
  316. data/vendor/plugins/InlineAttachment-0.3.0-modified/lib/inline_attachment.rb +136 -0
  317. data/vendor/plugins/InlineAttachment-0.3.0-modified/lib/tmail_content_id.rb +40 -0
  318. data/vendor/plugins/active_scaffold/CHANGELOG +152 -0
  319. data/vendor/plugins/active_scaffold/MIT-LICENSE +20 -0
  320. data/vendor/plugins/active_scaffold/README +28 -0
  321. data/vendor/plugins/active_scaffold/Rakefile +24 -0
  322. data/vendor/plugins/active_scaffold/environment.rb +17 -0
  323. data/vendor/plugins/active_scaffold/frontends/default/images/add.gif +0 -0
  324. data/vendor/plugins/active_scaffold/frontends/default/images/arrow_down.gif +0 -0
  325. data/vendor/plugins/active_scaffold/frontends/default/images/arrow_up.gif +0 -0
  326. data/vendor/plugins/active_scaffold/frontends/default/images/close.gif +0 -0
  327. data/vendor/plugins/active_scaffold/frontends/default/images/cross.png +0 -0
  328. data/vendor/plugins/active_scaffold/frontends/default/images/indicator-small.gif +0 -0
  329. data/vendor/plugins/active_scaffold/frontends/default/images/indicator.gif +0 -0
  330. data/vendor/plugins/active_scaffold/frontends/default/images/magnifier.png +0 -0
  331. data/vendor/plugins/active_scaffold/frontends/default/javascripts/active_scaffold.js +430 -0
  332. data/vendor/plugins/active_scaffold/frontends/default/javascripts/dhtml_history.js +867 -0
  333. data/vendor/plugins/active_scaffold/frontends/default/javascripts/form_enhancements.js +114 -0
  334. data/vendor/plugins/active_scaffold/frontends/default/javascripts/rico_corner.js +370 -0
  335. data/vendor/plugins/active_scaffold/frontends/default/stylesheets/stylesheet-ie.css +35 -0
  336. data/vendor/plugins/active_scaffold/frontends/default/stylesheets/stylesheet.css +809 -0
  337. data/vendor/plugins/active_scaffold/frontends/default/views/_add_existing_form.html.erb +40 -0
  338. data/vendor/plugins/active_scaffold/frontends/default/views/_create_form.html.erb +49 -0
  339. data/vendor/plugins/active_scaffold/frontends/default/views/_create_form_on_list.html.erb +38 -0
  340. data/vendor/plugins/active_scaffold/frontends/default/views/_field_search.html.erb +45 -0
  341. data/vendor/plugins/active_scaffold/frontends/default/views/_form.html.erb +18 -0
  342. data/vendor/plugins/active_scaffold/frontends/default/views/_form_association.html.erb +20 -0
  343. data/vendor/plugins/active_scaffold/frontends/default/views/_form_association_footer.html.erb +42 -0
  344. data/vendor/plugins/active_scaffold/frontends/default/views/_form_association_header.html.erb +10 -0
  345. data/vendor/plugins/active_scaffold/frontends/default/views/_form_association_record.html.erb +27 -0
  346. data/vendor/plugins/active_scaffold/frontends/default/views/_form_attribute.html.erb +12 -0
  347. data/vendor/plugins/active_scaffold/frontends/default/views/_form_hidden_attribute.html.erb +1 -0
  348. data/vendor/plugins/active_scaffold/frontends/default/views/_form_messages.html.erb +5 -0
  349. data/vendor/plugins/active_scaffold/frontends/default/views/_horizontal_subform.html.erb +21 -0
  350. data/vendor/plugins/active_scaffold/frontends/default/views/_list.html.erb +37 -0
  351. data/vendor/plugins/active_scaffold/frontends/default/views/_list_actions.html.erb +13 -0
  352. data/vendor/plugins/active_scaffold/frontends/default/views/_list_calculations.html.erb +22 -0
  353. data/vendor/plugins/active_scaffold/frontends/default/views/_list_column_headings.html.erb +32 -0
  354. data/vendor/plugins/active_scaffold/frontends/default/views/_list_header.html.erb +14 -0
  355. data/vendor/plugins/active_scaffold/frontends/default/views/_list_inline_adapter.html.erb +9 -0
  356. data/vendor/plugins/active_scaffold/frontends/default/views/_list_pagination_links.html.erb +30 -0
  357. data/vendor/plugins/active_scaffold/frontends/default/views/_list_record.html.erb +35 -0
  358. data/vendor/plugins/active_scaffold/frontends/default/views/_live_search.html.erb +25 -0
  359. data/vendor/plugins/active_scaffold/frontends/default/views/_messages.html.erb +10 -0
  360. data/vendor/plugins/active_scaffold/frontends/default/views/_nested.html.erb +44 -0
  361. data/vendor/plugins/active_scaffold/frontends/default/views/_search.html.erb +21 -0
  362. data/vendor/plugins/active_scaffold/frontends/default/views/_show.html.erb +8 -0
  363. data/vendor/plugins/active_scaffold/frontends/default/views/_show_columns.html.erb +11 -0
  364. data/vendor/plugins/active_scaffold/frontends/default/views/_update_actions.html.erb +9 -0
  365. data/vendor/plugins/active_scaffold/frontends/default/views/_update_form.html.erb +53 -0
  366. data/vendor/plugins/active_scaffold/frontends/default/views/add_existing.js.rjs +16 -0
  367. data/vendor/plugins/active_scaffold/frontends/default/views/add_existing_form.html.erb +5 -0
  368. data/vendor/plugins/active_scaffold/frontends/default/views/create.html.erb +5 -0
  369. data/vendor/plugins/active_scaffold/frontends/default/views/delete.html.erb +13 -0
  370. data/vendor/plugins/active_scaffold/frontends/default/views/destroy.js.rjs +10 -0
  371. data/vendor/plugins/active_scaffold/frontends/default/views/edit_associated.js.rjs +15 -0
  372. data/vendor/plugins/active_scaffold/frontends/default/views/field_search.html.erb +5 -0
  373. data/vendor/plugins/active_scaffold/frontends/default/views/form_messages.js.rjs +1 -0
  374. data/vendor/plugins/active_scaffold/frontends/default/views/form_messages_on_create.js.rjs +2 -0
  375. data/vendor/plugins/active_scaffold/frontends/default/views/form_messages_on_update.js.rjs +2 -0
  376. data/vendor/plugins/active_scaffold/frontends/default/views/list.html.erb +44 -0
  377. data/vendor/plugins/active_scaffold/frontends/default/views/on_create.js.rjs +25 -0
  378. data/vendor/plugins/active_scaffold/frontends/default/views/on_update.js.rjs +11 -0
  379. data/vendor/plugins/active_scaffold/frontends/default/views/search.html.erb +5 -0
  380. data/vendor/plugins/active_scaffold/frontends/default/views/show.html.erb +5 -0
  381. data/vendor/plugins/active_scaffold/frontends/default/views/update.html.erb +8 -0
  382. data/vendor/plugins/active_scaffold/frontends/default/views/update_column.js.rjs +12 -0
  383. data/vendor/plugins/active_scaffold/init.rb +18 -0
  384. data/vendor/plugins/active_scaffold/install.rb +40 -0
  385. data/vendor/plugins/active_scaffold/install_assets.rb +36 -0
  386. data/vendor/plugins/active_scaffold/lib/active_record_permissions.rb +123 -0
  387. data/vendor/plugins/active_scaffold/lib/active_scaffold.rb +144 -0
  388. data/vendor/plugins/active_scaffold/lib/active_scaffold/actions/core.rb +102 -0
  389. data/vendor/plugins/active_scaffold/lib/active_scaffold/actions/create.rb +120 -0
  390. data/vendor/plugins/active_scaffold/lib/active_scaffold/actions/delete.rb +46 -0
  391. data/vendor/plugins/active_scaffold/lib/active_scaffold/actions/field_search.rb +46 -0
  392. data/vendor/plugins/active_scaffold/lib/active_scaffold/actions/list.rb +77 -0
  393. data/vendor/plugins/active_scaffold/lib/active_scaffold/actions/live_search.rb +46 -0
  394. data/vendor/plugins/active_scaffold/lib/active_scaffold/actions/nested.rb +215 -0
  395. data/vendor/plugins/active_scaffold/lib/active_scaffold/actions/search.rb +40 -0
  396. data/vendor/plugins/active_scaffold/lib/active_scaffold/actions/show.rb +34 -0
  397. data/vendor/plugins/active_scaffold/lib/active_scaffold/actions/subform.rb +17 -0
  398. data/vendor/plugins/active_scaffold/lib/active_scaffold/actions/update.rb +114 -0
  399. data/vendor/plugins/active_scaffold/lib/active_scaffold/attribute_params.rb +185 -0
  400. data/vendor/plugins/active_scaffold/lib/active_scaffold/config/base.rb +37 -0
  401. data/vendor/plugins/active_scaffold/lib/active_scaffold/config/core.rb +189 -0
  402. data/vendor/plugins/active_scaffold/lib/active_scaffold/config/create.rb +43 -0
  403. data/vendor/plugins/active_scaffold/lib/active_scaffold/config/delete.rb +25 -0
  404. data/vendor/plugins/active_scaffold/lib/active_scaffold/config/field_search.rb +53 -0
  405. data/vendor/plugins/active_scaffold/lib/active_scaffold/config/form.rb +49 -0
  406. data/vendor/plugins/active_scaffold/lib/active_scaffold/config/list.rb +134 -0
  407. data/vendor/plugins/active_scaffold/lib/active_scaffold/config/live_search.rb +52 -0
  408. data/vendor/plugins/active_scaffold/lib/active_scaffold/config/nested.rb +31 -0
  409. data/vendor/plugins/active_scaffold/lib/active_scaffold/config/search.rb +52 -0
  410. data/vendor/plugins/active_scaffold/lib/active_scaffold/config/show.rb +39 -0
  411. data/vendor/plugins/active_scaffold/lib/active_scaffold/config/subform.rb +33 -0
  412. data/vendor/plugins/active_scaffold/lib/active_scaffold/config/update.rb +32 -0
  413. data/vendor/plugins/active_scaffold/lib/active_scaffold/configurable.rb +29 -0
  414. data/vendor/plugins/active_scaffold/lib/active_scaffold/constraints.rb +178 -0
  415. data/vendor/plugins/active_scaffold/lib/active_scaffold/data_structures/action_columns.rb +97 -0
  416. data/vendor/plugins/active_scaffold/lib/active_scaffold/data_structures/action_link.rb +136 -0
  417. data/vendor/plugins/active_scaffold/lib/active_scaffold/data_structures/action_links.rb +47 -0
  418. data/vendor/plugins/active_scaffold/lib/active_scaffold/data_structures/actions.rb +45 -0
  419. data/vendor/plugins/active_scaffold/lib/active_scaffold/data_structures/column.rb +297 -0
  420. data/vendor/plugins/active_scaffold/lib/active_scaffold/data_structures/columns.rb +75 -0
  421. data/vendor/plugins/active_scaffold/lib/active_scaffold/data_structures/error_message.rb +24 -0
  422. data/vendor/plugins/active_scaffold/lib/active_scaffold/data_structures/set.rb +62 -0
  423. data/vendor/plugins/active_scaffold/lib/active_scaffold/data_structures/sorting.rb +89 -0
  424. data/vendor/plugins/active_scaffold/lib/active_scaffold/finder.rb +234 -0
  425. data/vendor/plugins/active_scaffold/lib/active_scaffold/helpers/association_helpers.rb +40 -0
  426. data/vendor/plugins/active_scaffold/lib/active_scaffold/helpers/controller_helpers.rb +25 -0
  427. data/vendor/plugins/active_scaffold/lib/active_scaffold/helpers/country_helpers.rb +348 -0
  428. data/vendor/plugins/active_scaffold/lib/active_scaffold/helpers/form_column_helpers.rb +267 -0
  429. data/vendor/plugins/active_scaffold/lib/active_scaffold/helpers/id_helpers.rb +125 -0
  430. data/vendor/plugins/active_scaffold/lib/active_scaffold/helpers/list_column_helpers.rb +178 -0
  431. data/vendor/plugins/active_scaffold/lib/active_scaffold/helpers/pagination_helpers.rb +37 -0
  432. data/vendor/plugins/active_scaffold/lib/active_scaffold/helpers/search_column_helpers.rb +172 -0
  433. data/vendor/plugins/active_scaffold/lib/active_scaffold/helpers/show_column_helpers.rb +46 -0
  434. data/vendor/plugins/active_scaffold/lib/active_scaffold/helpers/view_helpers.rb +196 -0
  435. data/vendor/plugins/active_scaffold/lib/active_scaffold/locale/en.rb +66 -0
  436. data/vendor/plugins/active_scaffold/lib/active_scaffold/locale/es.yml +64 -0
  437. data/vendor/plugins/active_scaffold/lib/active_scaffold/locale/hu.yml +62 -0
  438. data/vendor/plugins/active_scaffold/lib/bridges/bridge.rb +52 -0
  439. data/vendor/plugins/active_scaffold/lib/bridges/calendar_date_select/bridge.rb +11 -0
  440. data/vendor/plugins/active_scaffold/lib/bridges/calendar_date_select/lib/as_cds_bridge.rb +53 -0
  441. data/vendor/plugins/active_scaffold/lib/bridges/file_column/bridge.rb +12 -0
  442. data/vendor/plugins/active_scaffold/lib/bridges/file_column/lib/as_file_column_bridge.rb +49 -0
  443. data/vendor/plugins/active_scaffold/lib/bridges/file_column/lib/file_column_helpers.rb +51 -0
  444. data/vendor/plugins/active_scaffold/lib/bridges/file_column/lib/form_ui.rb +32 -0
  445. data/vendor/plugins/active_scaffold/lib/bridges/file_column/lib/list_ui.rb +26 -0
  446. data/vendor/plugins/active_scaffold/lib/bridges/file_column/test/functional/file_column_keep_test.rb +43 -0
  447. data/vendor/plugins/active_scaffold/lib/bridges/file_column/test/mock_model.rb +9 -0
  448. data/vendor/plugins/active_scaffold/lib/bridges/file_column/test/test_helper.rb +15 -0
  449. data/vendor/plugins/active_scaffold/lib/dhtml_confirm.rb +54 -0
  450. data/vendor/plugins/active_scaffold/lib/extensions/action_controller_rendering.rb +20 -0
  451. data/vendor/plugins/active_scaffold/lib/extensions/action_view_rendering.rb +87 -0
  452. data/vendor/plugins/active_scaffold/lib/extensions/array.rb +7 -0
  453. data/vendor/plugins/active_scaffold/lib/extensions/component_response_with_namespacing.rb +17 -0
  454. data/vendor/plugins/active_scaffold/lib/extensions/generic_view_paths.rb +33 -0
  455. data/vendor/plugins/active_scaffold/lib/extensions/localize.rb +10 -0
  456. data/vendor/plugins/active_scaffold/lib/extensions/name_option_for_datetime.rb +12 -0
  457. data/vendor/plugins/active_scaffold/lib/extensions/nil_id_in_url_params.rb +7 -0
  458. data/vendor/plugins/active_scaffold/lib/extensions/resources.rb +26 -0
  459. data/vendor/plugins/active_scaffold/lib/extensions/reverse_associations.rb +56 -0
  460. data/vendor/plugins/active_scaffold/lib/extensions/to_label.rb +8 -0
  461. data/vendor/plugins/active_scaffold/lib/extensions/unsaved_associated.rb +61 -0
  462. data/vendor/plugins/active_scaffold/lib/extensions/unsaved_record.rb +20 -0
  463. data/vendor/plugins/active_scaffold/lib/extensions/usa_state.rb +46 -0
  464. data/vendor/plugins/active_scaffold/lib/paginator.rb +136 -0
  465. data/vendor/plugins/active_scaffold/lib/responds_to_parent.rb +68 -0
  466. data/vendor/plugins/active_scaffold/public/blank.html +33 -0
  467. data/vendor/plugins/active_scaffold/test/bridges/bridge_test.rb +47 -0
  468. data/vendor/plugins/active_scaffold/test/config/create_test.rb +55 -0
  469. data/vendor/plugins/active_scaffold/test/config/list_test.rb +74 -0
  470. data/vendor/plugins/active_scaffold/test/config/update_test.rb +17 -0
  471. data/vendor/plugins/active_scaffold/test/const_mocker.rb +36 -0
  472. data/vendor/plugins/active_scaffold/test/data_structures/action_columns_test.rb +119 -0
  473. data/vendor/plugins/active_scaffold/test/data_structures/action_link_test.rb +78 -0
  474. data/vendor/plugins/active_scaffold/test/data_structures/action_links_test.rb +78 -0
  475. data/vendor/plugins/active_scaffold/test/data_structures/actions_test.rb +25 -0
  476. data/vendor/plugins/active_scaffold/test/data_structures/association_column_test.rb +41 -0
  477. data/vendor/plugins/active_scaffold/test/data_structures/column_test.rb +161 -0
  478. data/vendor/plugins/active_scaffold/test/data_structures/columns_test.rb +69 -0
  479. data/vendor/plugins/active_scaffold/test/data_structures/error_message_test.rb +28 -0
  480. data/vendor/plugins/active_scaffold/test/data_structures/set_test.rb +86 -0
  481. data/vendor/plugins/active_scaffold/test/data_structures/sorting_test.rb +96 -0
  482. data/vendor/plugins/active_scaffold/test/data_structures/standard_column_test.rb +34 -0
  483. data/vendor/plugins/active_scaffold/test/data_structures/virtual_column_test.rb +34 -0
  484. data/vendor/plugins/active_scaffold/test/extensions/active_record_test.rb +45 -0
  485. data/vendor/plugins/active_scaffold/test/extensions/array.rb +12 -0
  486. data/vendor/plugins/active_scaffold/test/misc/active_record_permissions.rb +154 -0
  487. data/vendor/plugins/active_scaffold/test/misc/configurable_test.rb +96 -0
  488. data/vendor/plugins/active_scaffold/test/misc/constraints_test.rb +175 -0
  489. data/vendor/plugins/active_scaffold/test/misc/finder_test.rb +70 -0
  490. data/vendor/plugins/active_scaffold/test/misc/lang_test.rb +12 -0
  491. data/vendor/plugins/active_scaffold/test/model_stub.rb +39 -0
  492. data/vendor/plugins/active_scaffold/test/run_all.rb +8 -0
  493. data/vendor/plugins/active_scaffold/test/test_helper.rb +13 -0
  494. data/vendor/plugins/active_scaffold/uninstall.rb +12 -0
  495. data/vendor/plugins/active_scaffold_as_gem/init.rb +21 -0
  496. data/vendor/plugins/active_scaffold_form_observation/init.rb +4 -0
  497. data/vendor/plugins/active_scaffold_form_observation/lib/active_scaffold_form_observation.rb +99 -0
  498. data/vendor/plugins/active_scaffold_full_refresh/init.rb +7 -0
  499. data/vendor/plugins/active_scaffold_full_refresh/lib/active_scaffold_full_refresh.rb +46 -0
  500. data/vendor/plugins/active_scaffold_move_column_under/init.rb +17 -0
  501. data/vendor/plugins/acts_as_money/README +24 -0
  502. data/vendor/plugins/acts_as_money/Rakefile +22 -0
  503. data/vendor/plugins/acts_as_money/init.rb +3 -0
  504. data/vendor/plugins/acts_as_money/install.rb +1 -0
  505. data/vendor/plugins/acts_as_money/lib/acts_as_money.rb +27 -0
  506. data/vendor/plugins/acts_as_money/tasks/money_tasks.rake +4 -0
  507. data/vendor/plugins/acts_as_money/test/money_test.rb +8 -0
  508. data/vendor/plugins/association_hacks/init.rb +1 -0
  509. data/vendor/plugins/association_hacks/lib/association_hacks.rb +27 -0
  510. data/vendor/plugins/railspdf/CHANGELOG +5 -0
  511. data/vendor/plugins/railspdf/README +88 -0
  512. data/vendor/plugins/railspdf/Rakefile +22 -0
  513. data/vendor/plugins/railspdf/TODO +1 -0
  514. data/vendor/plugins/railspdf/init.rb +3 -0
  515. data/vendor/plugins/railspdf/lib/railspdf.rb +65 -0
  516. data/vendor/plugins/railspdf/test/railspdf_test.rb +14 -0
  517. data/vendor/plugins/railspdf/test/test_helper.rb +9 -0
  518. data/vendor/plugins/render_component/README +37 -0
  519. data/vendor/plugins/render_component/Rakefile +22 -0
  520. data/vendor/plugins/render_component/init.rb +2 -0
  521. data/vendor/plugins/render_component/lib/components.rb +142 -0
  522. data/vendor/plugins/render_component/test/abstract_unit.rb +8 -0
  523. data/vendor/plugins/render_component/test/components_test.rb +140 -0
  524. metadata +657 -0
@@ -0,0 +1,40 @@
1
+ module ActiveScaffold::Actions
2
+ module Search
3
+ def self.included(base)
4
+ base.before_filter :search_authorized?, :only => :show_search
5
+ base.before_filter :do_search
6
+ end
7
+
8
+ def show_search
9
+ respond_to do |type|
10
+ type.html { render(:action => "search") }
11
+ type.js { render(:partial => "search") }
12
+ end
13
+ end
14
+
15
+ protected
16
+
17
+ def do_search
18
+ @query = params[:search].to_s.strip rescue ''
19
+
20
+ unless @query.empty?
21
+ columns = active_scaffold_config.search.columns
22
+ like_pattern = active_scaffold_config.search.full_text_search? ? '%?%' : '?%'
23
+ search_conditions = self.class.create_conditions_for_columns(@query.split(' '), columns, like_pattern)
24
+ self.active_scaffold_conditions = merge_conditions(self.active_scaffold_conditions, search_conditions)
25
+ @filtered = !search_conditions.blank?
26
+
27
+ includes_for_search_columns = columns.collect{ |column| column.includes}.flatten.uniq.compact
28
+ self.active_scaffold_joins.concat includes_for_search_columns
29
+
30
+ active_scaffold_config.list.user.page = nil
31
+ end
32
+ end
33
+
34
+ # The default security delegates to ActiveRecordPermissions.
35
+ # You may override the method to customize.
36
+ def search_authorized?
37
+ authorized_for?(:action => :read)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,34 @@
1
+ module ActiveScaffold::Actions
2
+ module Show
3
+ def self.included(base)
4
+ base.before_filter :show_authorized?, :only => :show
5
+ end
6
+
7
+ def show
8
+ do_show
9
+
10
+ successful?
11
+ respond_to do |type|
12
+ type.html { render :action => 'show' }
13
+ type.js { render :partial => 'show' }
14
+ type.xml { render :xml => response_object.to_xml, :content_type => Mime::XML, :status => response_status }
15
+ type.json { render :text => response_object.to_json, :content_type => Mime::JSON, :status => response_status }
16
+ type.yaml { render :text => response_object.to_yaml, :content_type => Mime::YAML, :status => response_status }
17
+ end
18
+ end
19
+
20
+ protected
21
+
22
+ # A simple method to retrieve and prepare a record for showing.
23
+ # May be overridden to customize show routine
24
+ def do_show
25
+ @record = find_if_allowed(params[:id], :read)
26
+ end
27
+
28
+ # The default security delegates to ActiveRecordPermissions.
29
+ # You may override the method to customize.
30
+ def show_authorized?
31
+ authorized_for?(:action => :read)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,17 @@
1
+ module ActiveScaffold::Actions
2
+ module Subform
3
+ def edit_associated
4
+ @parent_record = params[:id].nil? ? active_scaffold_config.model.new : find_if_allowed(params[:id], :update)
5
+ @column = active_scaffold_config.columns[params[:association]]
6
+
7
+ # NOTE: we don't check whether the user is allowed to update this record, because if not, we'll still let them associate the record. we'll just refuse to do more than associate, is all.
8
+ @record = @column.association.klass.find(params[:associated_id]) if params[:associated_id]
9
+ @record ||= @column.association.klass.new
10
+
11
+ @scope = "[#{@column.name}]"
12
+ @scope += (@record.new_record?) ? "[#{(Time.now.to_f*1000).to_i.to_s}]" : "[#{@record.id}]" if @column.plural_association?
13
+
14
+ render :action => 'edit_associated'
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,114 @@
1
+ module ActiveScaffold::Actions
2
+ module Update
3
+ def self.included(base)
4
+ base.before_filter :update_authorized?, :only => [:edit, :update]
5
+ base.verify :method => [:post, :put],
6
+ :only => :update,
7
+ :redirect_to => { :action => :index }
8
+ end
9
+
10
+ def edit
11
+ do_edit
12
+
13
+ respond_to do |type|
14
+ type.html do
15
+ if successful?
16
+ render(:action => 'update')
17
+ else
18
+ return_to_main
19
+ end
20
+ end
21
+ type.js do
22
+ render(:partial => 'update_form')
23
+ end
24
+ end
25
+ end
26
+
27
+ def update
28
+ do_update
29
+
30
+ respond_to do |type|
31
+ type.html do
32
+ if params[:iframe]=='true' # was this an iframe post ?
33
+ responds_to_parent do
34
+ if successful?
35
+ render :action => 'on_update'
36
+ else
37
+ render :action => 'form_messages_on_update'
38
+ end
39
+ end
40
+ else # just a regular post
41
+ if successful?
42
+ flash[:info] = as_(:updated_model, :model => @record.to_label)
43
+ return_to_main
44
+ else
45
+ render(:action => 'update')
46
+ end
47
+ end
48
+ end
49
+ type.js do
50
+ render :action => 'on_update'
51
+ end
52
+ type.xml { render :xml => response_object.to_xml, :content_type => Mime::XML, :status => response_status }
53
+ type.json { render :text => response_object.to_json, :content_type => Mime::JSON, :status => response_status }
54
+ type.yaml { render :text => response_object.to_yaml, :content_type => Mime::YAML, :status => response_status }
55
+ end
56
+ end
57
+
58
+ # for inline (inlist) editing
59
+ def update_column
60
+ do_update_column
61
+ render :action => 'update_column'
62
+ end
63
+
64
+ protected
65
+
66
+ # A simple method to find and prepare a record for editing
67
+ # May be overridden to customize the record (set default values, etc.)
68
+ def do_edit
69
+ @record = find_if_allowed(params[:id], :update)
70
+ end
71
+
72
+ # A complex method to update a record. The complexity comes from the support for subforms, and saving associated records.
73
+ # If you want to customize this algorithm, consider using the +before_update_save+ callback
74
+ def do_update
75
+ @record = find_if_allowed(params[:id], :update)
76
+ begin
77
+ active_scaffold_config.model.transaction do
78
+ @record = update_record_from_params(@record, active_scaffold_config.update.columns, params[:record])
79
+ before_update_save(@record)
80
+ self.successful = [@record.valid?, @record.associated_valid?].all? {|v| v == true} # this syntax avoids a short-circuit
81
+ if successful?
82
+ @record.save! and @record.save_associated!
83
+ after_update_save(@record)
84
+ end
85
+ end
86
+ rescue ActiveRecord::RecordInvalid
87
+ rescue ActiveRecord::StaleObjectError
88
+ @record.errors.add_to_base as_(:version_inconsistency)
89
+ self.successful=false
90
+ end
91
+ end
92
+
93
+ def do_update_column
94
+ @record = find_if_allowed(params[:id], :update)
95
+ if @record.authorized_for?(:action => :update, :column => params[:column])
96
+ params[:value] ||= @record.column_for_attribute(params[:column]).default unless @record.column_for_attribute(params[:column]).null
97
+ @record.send("#{params[:column]}=", params[:value])
98
+ @record.save
99
+ end
100
+ end
101
+
102
+ # override this method if you want to inject data in the record (or its associated objects) before the save
103
+ def before_update_save(record); end
104
+
105
+ # override this method if you want to do something after the save
106
+ def after_update_save(record); end
107
+
108
+ # The default security delegates to ActiveRecordPermissions.
109
+ # You may override the method to customize.
110
+ def update_authorized?
111
+ authorized_for?(:action => :update)
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,185 @@
1
+ module ActiveScaffold
2
+ # Provides support for param hashes assumed to be model attributes.
3
+ # Support is primarily needed for creating/editing associated records using a nested hash structure.
4
+ #
5
+ # Paradigm Params Hash (should write unit tests on this):
6
+ # params[:record] = {
7
+ # # a simple record attribute
8
+ # 'name' => 'John',
9
+ # # a plural association hash
10
+ # 'roles' => {
11
+ # # associate with an existing role
12
+ # '5' => {'id' => 5}
13
+ # # associate with an existing role and edit it
14
+ # '6' => {'id' => 6, 'name' => 'designer'}
15
+ # # create and associate a new role
16
+ # '124521' => {'name' => 'marketer'}
17
+ # }
18
+ # # a singular association hash
19
+ # 'location' => {'id' => 12, 'city' => 'New York'}
20
+ # }
21
+ #
22
+ # Simpler association structures are also supported, like:
23
+ # params[:record] = {
24
+ # # a simple record attribute
25
+ # 'name' => 'John',
26
+ # # a plural association ... all ids refer to existing records
27
+ # 'roles' => ['5', '6'],
28
+ # # a singular association ... all ids refer to existing records
29
+ # 'location' => '12'
30
+ # }
31
+ module AttributeParams
32
+ # Takes attributes (as from params[:record]) and applies them to the parent_record. Also looks for
33
+ # association attributes and attempts to instantiate them as associated objects.
34
+ #
35
+ # This is a secure way to apply params to a record, because it's based on a loop over the columns
36
+ # set. The columns set will not yield unauthorized columns, and it will not yield unregistered columns.
37
+ def update_record_from_params(parent_record, columns, attributes)
38
+ action = parent_record.new_record? ? :create : :update
39
+ return parent_record unless parent_record.authorized_for?(:action => action)
40
+
41
+ multi_parameter_attributes = {}
42
+ attributes.each do |k, v|
43
+ next unless k.include? '('
44
+ column_name = k.split('(').first.to_sym
45
+ multi_parameter_attributes[column_name] ||= []
46
+ multi_parameter_attributes[column_name] << [k, v]
47
+ end
48
+
49
+ columns.each :for => parent_record, :action => action, :flatten => true do |column|
50
+ if multi_parameter_attributes.has_key? column.name
51
+ parent_record.send(:assign_multiparameter_attributes, multi_parameter_attributes[column.name])
52
+ elsif attributes.has_key? column.name
53
+ value = attributes[column.name]
54
+
55
+ # convert the value, possibly by instantiating associated objects
56
+ value = if value.is_a?(Hash)
57
+ # this is just for backwards compatibility. we should clean this up in 2.0.
58
+ if column.form_ui == :select
59
+ ids = if column.singular_association?
60
+ value[:id]
61
+ else
62
+ value.values.collect {|hash| hash[:id]}
63
+ end
64
+ (ids and not ids.empty?) ? column.association.klass.find(ids) : nil
65
+
66
+ elsif column.singular_association?
67
+ hash = value
68
+ record = find_or_create_for_params(hash, column, parent_record.send("#{column.name}"))
69
+ if record
70
+ record_columns = active_scaffold_config_for(column.association.klass).subform.columns
71
+ update_record_from_params(record, record_columns, hash)
72
+ record.unsaved = true
73
+ end
74
+ record
75
+
76
+ elsif column.plural_association?
77
+ collection = value.collect do |key_value_pair|
78
+ hash = key_value_pair[1]
79
+ record = find_or_create_for_params(hash, column, parent_record.send("#{column.name}"))
80
+ if record
81
+ record_columns = active_scaffold_config_for(column.association.klass).subform.columns
82
+ update_record_from_params(record, record_columns, hash)
83
+ record.unsaved = true
84
+ end
85
+ record
86
+ end
87
+ collection.compact
88
+ end
89
+ else
90
+ if column.singular_association?
91
+ # it's a single id
92
+ column.association.klass.find(value) if value and not value.empty?
93
+ elsif column.plural_association?
94
+ # it's an array of ids
95
+ column.association.klass.find(value) if value and not value.empty?
96
+ else
97
+ # convert empty strings into nil. this works better with 'null => true' columns (and validations),
98
+ # and 'null => false' columns should just convert back to an empty string.
99
+ # ... but we can at least check the ConnectionAdapter::Column object to see if nulls are allowed
100
+ value = nil if value.is_a? String and value.empty? and !column.column.nil? and column.column.null
101
+ value
102
+ end
103
+ end
104
+
105
+ # we avoid assigning a value that already exists because otherwise has_one associations will break (AR bug in has_one_association.rb#replace)
106
+ parent_record.send("#{column.name}=", value) unless column.through_association? or parent_record.send(column.name) == value
107
+
108
+ # Set any passthrough parameters that may be associated with this column (ie, file column "keep" and "temp" attributes)
109
+ unless column.params.empty?
110
+ column.params.each{|p| parent_record.send("#{p}=", attributes[p])}
111
+ end
112
+
113
+ # plural associations may not actually appear in the params if all of the options have been unselected or cleared away.
114
+ # NOTE: the "form_ui" check isn't really necessary, except that without it we have problems
115
+ # with subforms. the UI cuts out deep associations, which means they're not present in the
116
+ # params even though they're in the columns list. the result is that associations were being
117
+ # emptied out way too often. BUT ... this means there's still a lingering bug in the default association
118
+ # form code: you can't delete the last association in the list.
119
+ elsif column.form_ui and column.plural_association? and not column.through_association?
120
+ parent_record.send("#{column.name}=", [])
121
+ end
122
+ end
123
+
124
+ if parent_record.new_record?
125
+ parent_record.class.reflect_on_all_associations.each do |a|
126
+ next unless [:has_one, :has_many].include?(a.macro) and not a.options[:through]
127
+ next unless association_proxy = parent_record.send(a.name)
128
+
129
+ raise ActiveScaffold::ReverseAssociationRequired, "In order to support :has_one and :has_many where the parent record is new and the child record(s) validate the presence of the parent, ActiveScaffold requires the reverse association (the belongs_to)." unless a.reverse
130
+
131
+ association_proxy = [association_proxy] if a.macro == :has_one
132
+ association_proxy.each { |record| record.send("#{a.reverse}=", parent_record) }
133
+ end
134
+ end
135
+
136
+ parent_record
137
+ end
138
+
139
+ # Attempts to create or find an instance of klass (which must be an ActiveRecord object) from the
140
+ # request parameters given. If params[:id] exists it will attempt to find an existing object
141
+ # otherwise it will build a new one.
142
+ def find_or_create_for_params(params, parent_column, current)
143
+ klass = parent_column.association.klass
144
+ return nil if parent_column.show_blank_record and attributes_hash_is_empty?(params, klass)
145
+
146
+ if params.has_key? :id
147
+ # modifying the current object of a singular association
148
+ if current and current.is_a? ActiveRecord::Base and current.id.to_s == params[:id]
149
+ return current
150
+ # modifying one of the current objects in a plural association
151
+ elsif current and current.respond_to?(:any?) and current.any? {|o| o.id.to_s == params[:id]}
152
+ return current.detect {|o| o.id.to_s == params[:id]}
153
+ # attaching an existing but not-current object
154
+ else
155
+ return klass.find(params[:id])
156
+ end
157
+ else
158
+ return klass.new if klass.authorized_for?(:action => :create)
159
+ end
160
+ end
161
+
162
+ # Determines whether the given attributes hash is "empty".
163
+ # This isn't a literal emptiness - it's an attempt to discern whether the user intended it to be empty or not.
164
+ def attributes_hash_is_empty?(hash, klass)
165
+ hash.all? do |key,value|
166
+ # convert any possible multi-parameter attributes like 'created_at(5i)' to simply 'created_at'
167
+ column_name = key.to_s.split('(').first
168
+ column = klass.columns_hash[column_name]
169
+
170
+ # booleans and datetimes will always have a value. so we ignore them when checking whether the hash is empty.
171
+ # this could be a bad idea. but the current situation (excess record entry) seems worse.
172
+ next true if column and [:boolean, :datetime, :date, :time].include?(column.type)
173
+
174
+ # defaults are pre-filled on the form. we can't use them to determine if the user intends a new row.
175
+ next true if column and value == column.default.to_s
176
+
177
+ if value.is_a?(Hash)
178
+ attributes_hash_is_empty?(value, klass)
179
+ else
180
+ value.respond_to?(:empty?) ? value.empty? : false
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,37 @@
1
+ module ActiveScaffold::Config
2
+ class Base
3
+ include ActiveScaffold::Configurable
4
+ extend ActiveScaffold::Configurable
5
+
6
+ def self.inherited(subclass)
7
+ class << subclass
8
+ # the crud type of the action. possible values are :create, :read, :update, :destroy, and nil.
9
+ # this is not a setting for the developer. it's self-description for the actions.
10
+ def crud_type; @crud_type; end
11
+
12
+ protected
13
+
14
+ def crud_type=(val)
15
+ raise ArgumentError, "unknown CRUD type #{val}" unless [:create, :read, :update, :destroy].include?(val.to_sym)
16
+ @crud_type = val.to_sym
17
+ end
18
+ end
19
+ end
20
+ # delegate
21
+ def crud_type; self.class.crud_type end
22
+
23
+ # the user property gets set to the instantiation of the local UserSettings class during the automatic instantiation of this class.
24
+ attr_accessor :user
25
+
26
+ class UserSettings
27
+ def initialize(conf, storage, params)
28
+ # the session hash relevant to this action
29
+ @session = storage
30
+ # all the request params
31
+ @params = params
32
+ # the configuration object for this action
33
+ @conf = conf
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,189 @@
1
+ module ActiveScaffold::Config
2
+ class Core < Base
3
+ # global level configuration
4
+ # --------------------------
5
+
6
+ # provides read/write access to the global Actions DataStructure
7
+ cattr_reader :actions
8
+ def self.actions=(val)
9
+ @@actions = ActiveScaffold::DataStructures::Actions.new(*val)
10
+ end
11
+ self.actions = [:create, :list, :search, :update, :delete, :show, :nested, :subform]
12
+
13
+ # configures where the ActiveScaffold plugin itself is located. there is no instance version of this.
14
+ cattr_accessor :plugin_directory
15
+ @@plugin_directory = File.expand_path(__FILE__).match(/vendor\/plugins\/([^\/]*)/)[1]
16
+
17
+ # lets you specify a global ActiveScaffold frontend.
18
+ cattr_accessor :frontend
19
+ @@frontend = :default
20
+
21
+ # lets you specify a global ActiveScaffold theme for your frontend.
22
+ cattr_accessor :theme
23
+ @@theme = :default
24
+
25
+ # lets you disable the DHTML history
26
+ def self.dhtml_history=(val)
27
+ @@dhtml_history = val
28
+ end
29
+ def self.dhtml_history?
30
+ @@dhtml_history ? true : false
31
+ end
32
+ @@dhtml_history = true
33
+
34
+ # action links are used by actions to tie together. you can use them, too! this is a collection of ActiveScaffold::DataStructures::ActionLink objects.
35
+ cattr_reader :action_links
36
+ @@action_links = ActiveScaffold::DataStructures::ActionLinks.new
37
+
38
+ # access to the permissions configuration.
39
+ # configuration options include:
40
+ # * current_user_method - what method on the controller returns the current user. default: :current_user
41
+ # * default_permission - what the default permission is. default: true
42
+ def self.security
43
+ ActiveRecordPermissions
44
+ end
45
+
46
+ # columns that should be ignored for every model. these should be metadata columns like change dates, versions, etc.
47
+ # values in this array may be symbols or strings.
48
+ def self.ignore_columns
49
+ @@ignore_columns
50
+ end
51
+ def self.ignore_columns=(val)
52
+ @@ignore_columns = ActiveScaffold::DataStructures::Set.new(*val)
53
+ end
54
+ @@ignore_columns = ActiveScaffold::DataStructures::Set.new
55
+
56
+ # instance-level configuration
57
+ # ----------------------------
58
+
59
+ # provides read/write access to the local Actions DataStructure
60
+ attr_reader :actions
61
+ def actions=(args)
62
+ @actions = ActiveScaffold::DataStructures::Actions.new(*args)
63
+ end
64
+
65
+ # provides read/write access to the local Columns DataStructure
66
+ attr_reader :columns
67
+ def columns=(val)
68
+ @columns._inheritable = val.collect {|c| c.to_sym}
69
+ # Add virtual columns
70
+ @columns << val.collect {|c| c.to_sym unless @columns[c.to_sym]}.compact
71
+ end
72
+
73
+ # lets you override the global ActiveScaffold frontend for a specific controller
74
+ attr_accessor :frontend
75
+
76
+ # lets you override the global ActiveScaffold theme for a specific controller
77
+ attr_accessor :theme
78
+
79
+ # action links are used by actions to tie together. they appear as links for each record, or general links for the ActiveScaffold.
80
+ attr_reader :action_links
81
+
82
+ # a generally-applicable name for this ActiveScaffold ... will be used for generating page/section headers
83
+ attr_writer :label
84
+ def label(options={})
85
+ options[:count] ||= model.count
86
+ as_(@label, options) || model.human_name(options)
87
+ end
88
+
89
+ ##
90
+ ## internal usage only below this point
91
+ ## ------------------------------------
92
+
93
+ def initialize(model_id)
94
+ # model_id is the only absolutely required configuration value. it is also not publicly accessible.
95
+ @model_id = model_id.to_s.pluralize.singularize
96
+
97
+ # inherit the actions list directly from the global level
98
+ @actions = self.class.actions.clone
99
+
100
+ # create a new default columns datastructure, since it doesn't make sense before now
101
+ attribute_names = self.model.columns.collect{ |c| c.name.to_sym }.sort_by { |c| c.to_s }
102
+ association_column_names = self.model.reflect_on_all_associations.collect{ |a| a.name.to_sym }.sort_by { |c| c.to_s }
103
+ @columns = ActiveScaffold::DataStructures::Columns.new(self.model, attribute_names + association_column_names)
104
+
105
+ # and then, let's remove some columns from the inheritable set.
106
+ @columns.exclude(*self.class.ignore_columns)
107
+ @columns.exclude(*@columns.find_all { |c| c.column and (c.column.primary or c.column.name =~ /(_id|_count)$/) }.collect {|c| c.name})
108
+ @columns.exclude(*self.model.reflect_on_all_associations.collect{|a| :"#{a.name}_type" if a.options[:polymorphic]}.compact)
109
+
110
+ # inherit the global frontend
111
+ @frontend = self.class.frontend
112
+ @theme = self.class.theme
113
+
114
+ # inherit from the global set of action links
115
+ @action_links = self.class.action_links.clone
116
+ end
117
+
118
+ # To be called after your finished configuration
119
+ def _load_action_columns
120
+ ActiveScaffold::DataStructures::ActionColumns.class_eval {include ActiveScaffold::DataStructures::ActionColumns::AfterConfiguration}
121
+
122
+ # then, register the column objects
123
+ self.actions.each do |action_name|
124
+ action = self.send(action_name)
125
+ next unless action.respond_to? :columns
126
+ action.columns.set_columns(self.columns)
127
+ end
128
+ end
129
+
130
+ # configuration routing.
131
+ # we want to route calls named like an activated action to that action's global or local Config class.
132
+ # ---------------------------
133
+ def method_missing(name, *args)
134
+ @action_configs ||= {}
135
+ titled_name = name.to_s.camelcase
136
+ underscored_name = name.to_s.underscore.to_sym
137
+ klass = "ActiveScaffold::Config::#{titled_name}".constantize rescue nil
138
+ if klass
139
+ if @actions.include? underscored_name
140
+ return @action_configs[underscored_name] ||= klass.new(self)
141
+ else
142
+ raise "#{titled_name} is not enabled. Please enable it or remove any references in your configuration (e.g. config.#{underscored_name}.columns = [...])."
143
+ end
144
+ end
145
+ super
146
+ end
147
+
148
+ def self.method_missing(name, *args)
149
+ klass = "ActiveScaffold::Config::#{name.to_s.titleize}".constantize rescue nil
150
+ if @@actions.include? name.to_s.underscore and klass
151
+ return eval("ActiveScaffold::Config::#{name.to_s.titleize}")
152
+ end
153
+ super
154
+ end
155
+ # some utility methods
156
+ # --------------------
157
+
158
+ def model_id
159
+ @model_id
160
+ end
161
+
162
+ def model
163
+ @model ||= @model_id.to_s.camelize.constantize
164
+ end
165
+
166
+ # warning - this won't work as a per-request dynamic attribute in rails 2.0. You'll need to interact with Controller#generic_view_paths
167
+ def inherited_view_paths
168
+ @inherited_view_paths||=[]
169
+ end
170
+
171
+ # must be a class method so the layout doesn't depend on a controller that uses active_scaffold
172
+ # note that this is unaffected by per-controller frontend configuration.
173
+ def self.asset_path(filename, frontend = self.frontend)
174
+ "active_scaffold/#{frontend}/#{filename}"
175
+ end
176
+
177
+ # must be a class method so the layout doesn't depend on a controller that uses active_scaffold
178
+ # note that this is unaffected by per-controller frontend configuration.
179
+ def self.javascripts(frontend = self.frontend)
180
+ javascript_dir = File.join(Rails.public_path, "javascripts", asset_path('', frontend))
181
+ Dir.entries(javascript_dir).reject { |e| !e.match(/\.js$/) or (!self.dhtml_history? and e.match('dhtml_history')) }
182
+ end
183
+
184
+ def self.available_frontends
185
+ frontends_dir = File.join(Rails.root, "vendor", "plugins", ActiveScaffold::Config::Core.plugin_directory, "frontends")
186
+ Dir.entries(frontends_dir).reject { |e| e.match(/^\./) } # Get rid of files that start with .
187
+ end
188
+ end
189
+ end