dm_cms 4.2.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (298) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +22 -0
  3. data/README.md +31 -0
  4. data/Rakefile +34 -0
  5. data/app/assets/javascripts/dm_cms/admin.js +58 -0
  6. data/app/assets/javascripts/dm_cms/application.js +16 -0
  7. data/app/assets/stylesheets/dm_cms/admin.css +3 -0
  8. data/app/assets/stylesheets/dm_cms/application.css +13 -0
  9. data/app/controllers/dm_cms/admin/admin_controller.rb +14 -0
  10. data/app/controllers/dm_cms/admin/cms_blogs_controller.rb +89 -0
  11. data/app/controllers/dm_cms/admin/cms_contentitems_controller.rb +96 -0
  12. data/app/controllers/dm_cms/admin/cms_pages_controller.rb +100 -0
  13. data/app/controllers/dm_cms/admin/cms_posts_controller.rb +67 -0
  14. data/app/controllers/dm_cms/admin/cms_snippets_controller.rb +73 -0
  15. data/app/controllers/dm_cms/admin/dashboard_controller.rb +12 -0
  16. data/app/controllers/dm_cms/admin/media_files_controller.rb +80 -0
  17. data/app/controllers/dm_cms/application_controller.rb +9 -0
  18. data/app/controllers/dm_cms/blogs_controller.rb +50 -0
  19. data/app/controllers/dm_cms/comments_controller.rb +3 -0
  20. data/app/controllers/dm_cms/contact_form_controller.rb +27 -0
  21. data/app/controllers/dm_cms/pages_controller.rb +67 -0
  22. data/app/controllers/dm_cms/posts_controller.rb +69 -0
  23. data/app/datatables/blog_user_datatable.rb +79 -0
  24. data/app/helpers/dm_cms/analytics_helper.rb +27 -0
  25. data/app/helpers/dm_cms/application_helper.rb +4 -0
  26. data/app/helpers/dm_cms/cms_contentitems_helper.rb +8 -0
  27. data/app/helpers/dm_cms/cms_pages_helper.rb +30 -0
  28. data/app/helpers/dm_cms/pages_helper.rb +204 -0
  29. data/app/helpers/dm_cms/posts_helper.rb +26 -0
  30. data/app/helpers/dm_cms/render_helper.rb +50 -0
  31. data/app/inputs/media_input.rb +17 -0
  32. data/app/liquid/tags/markdown.rb +30 -0
  33. data/app/mailers/post_notify_mailer.rb +36 -0
  34. data/app/models/cms_blog.rb +89 -0
  35. data/app/models/cms_contentitem.rb +76 -0
  36. data/app/models/cms_page.rb +227 -0
  37. data/app/models/cms_post.rb +76 -0
  38. data/app/models/cms_snippet.rb +42 -0
  39. data/app/models/contact_form.rb +28 -0
  40. data/app/models/dm_cms/concerns/ability.rb +54 -0
  41. data/app/models/dm_cms/permitted_params.rb +34 -0
  42. data/app/models/media_file.rb +102 -0
  43. data/app/presenters/cms_blog_presenter.rb +15 -0
  44. data/app/presenters/cms_page_presenter.rb +23 -0
  45. data/app/presenters/cms_post_presenter.rb +11 -0
  46. data/app/presenters/cms_snippet_presenter.rb +10 -0
  47. data/app/uploaders/media_uploader.rb +169 -0
  48. data/app/views/customized/analytics/_google_analytics.html.erb +11 -0
  49. data/app/views/dm_cms/admin/cms_blogs/_form.html.erb +34 -0
  50. data/app/views/dm_cms/admin/cms_blogs/edit.html.erb +2 -0
  51. data/app/views/dm_cms/admin/cms_blogs/index.html.erb +44 -0
  52. data/app/views/dm_cms/admin/cms_blogs/new.html.erb +2 -0
  53. data/app/views/dm_cms/admin/cms_blogs/show.html.erb +167 -0
  54. data/app/views/dm_cms/admin/cms_contentitems/_form.html.erb +43 -0
  55. data/app/views/dm_cms/admin/cms_contentitems/_form_dialog.html.erb +17 -0
  56. data/app/views/dm_cms/admin/cms_contentitems/edit.html.erb +1 -0
  57. data/app/views/dm_cms/admin/cms_contentitems/markdown.html.erb +21 -0
  58. data/app/views/dm_cms/admin/cms_contentitems/new_content.html.erb +1 -0
  59. data/app/views/dm_cms/admin/cms_pages/_content_toolbar.html.erb +11 -0
  60. data/app/views/dm_cms/admin/cms_pages/_form.html.erb +50 -0
  61. data/app/views/dm_cms/admin/cms_pages/_tree.html.erb +20 -0
  62. data/app/views/dm_cms/admin/cms_pages/_tree_sidebar.html.erb +8 -0
  63. data/app/views/dm_cms/admin/cms_pages/edit.html.erb +2 -0
  64. data/app/views/dm_cms/admin/cms_pages/index.html.erb +32 -0
  65. data/app/views/dm_cms/admin/cms_pages/new_page.html.erb +2 -0
  66. data/app/views/dm_cms/admin/cms_pages/show.html.erb +54 -0
  67. data/app/views/dm_cms/admin/cms_posts/_form.html.erb +59 -0
  68. data/app/views/dm_cms/admin/cms_posts/edit.html.erb +2 -0
  69. data/app/views/dm_cms/admin/cms_posts/new.html.erb +1 -0
  70. data/app/views/dm_cms/admin/cms_snippets/_form.html.erb +28 -0
  71. data/app/views/dm_cms/admin/cms_snippets/edit.html.erb +1 -0
  72. data/app/views/dm_cms/admin/cms_snippets/index.html.erb +29 -0
  73. data/app/views/dm_cms/admin/cms_snippets/new.html.erb +1 -0
  74. data/app/views/dm_cms/admin/dashboard/_widget_blog_comments.html.erb +37 -0
  75. data/app/views/dm_cms/admin/dashboard/widget_blog_comments.js.erb +1 -0
  76. data/app/views/dm_cms/admin/media_files/_form.html.erb +102 -0
  77. data/app/views/dm_cms/admin/media_files/edit.html.erb +3 -0
  78. data/app/views/dm_cms/admin/media_files/index.html.erb +98 -0
  79. data/app/views/dm_cms/admin/media_files/new.html.erb +3 -0
  80. data/app/views/dm_cms/admin/shared/_liquid_tags_ref.html.erb +35 -0
  81. data/app/views/dm_cms/blogs/show.html.erb +0 -0
  82. data/app/views/dm_cms/blogs/toggle_follow.js.coffee +5 -0
  83. data/app/views/dm_cms/contact_form/create.html.erb +2 -0
  84. data/app/views/dm_cms/contact_form/create.js.erb +2 -0
  85. data/app/views/dm_cms/pages/_content_fragment.html.erb +13 -0
  86. data/app/views/dm_cms/pages/_snippet_fragment.html.erb +12 -0
  87. data/app/views/dm_cms/pages/coming_soon.html.erb +2 -0
  88. data/app/views/dm_cms/pages/show.html.erb +0 -0
  89. data/app/views/dm_cms/posts/show.html.erb +0 -0
  90. data/app/views/dm_cms/shared/_comment.html.erb +22 -0
  91. data/app/views/dm_cms/shared/_comment_form.html.erb +16 -0
  92. data/app/views/dm_cms/shared/_comment_list.html.erb +11 -0
  93. data/app/views/dm_cms/shared/_social_buttons.html.erb +6 -0
  94. data/app/views/layouts/email_templates/dm_cms_email_layout.html.erb +320 -0
  95. data/app/views/layouts/email_templates/dm_cms_email_layout.text.erb +1 -0
  96. data/app/views/layouts/email_templates/dm_cms_post_notify.html.erb +13 -0
  97. data/app/views/layouts/email_templates/dm_cms_post_notify.text.erb +9 -0
  98. data/app/views/liquid_tags/_contact_form.html.erb +17 -0
  99. data/config/initializers/liquid_init.rb +2 -0
  100. data/config/locales/cms.cs.yml +42 -0
  101. data/config/locales/cms.de.yml +42 -0
  102. data/config/locales/cms.en.yml +42 -0
  103. data/config/locales/cms.fi.yml +42 -0
  104. data/config/locales/cms.ja.yml +42 -0
  105. data/config/routes.rb +70 -0
  106. data/db/migrate/20121103181909_create_cms.rb +91 -0
  107. data/db/migrate/20130206213720_add_account_to_cms.rb +10 -0
  108. data/db/migrate/20130507123255_create_blog.rb +61 -0
  109. data/db/migrate/20130531212537_add_notification_sent.rb +5 -0
  110. data/db/migrate/20130605184116_add_blog_comment.rb +7 -0
  111. data/db/migrate/20131128201053_add_blog_image.rb +5 -0
  112. data/db/migrate/20140217135228_rename_snippet_slug.rb +13 -0
  113. data/db/migrate/20140303121217_add_requires_subscription_blog.rb +7 -0
  114. data/db/migrate/20140328205246_add_pages_ranked_model.rb +22 -0
  115. data/db/migrate/20140423113417_add_blog_owner.rb +6 -0
  116. data/db/migrate/20140428122156_create_media_files.rb +29 -0
  117. data/db/migrate/20140523134543_add_cmspage_summary.rb +6 -0
  118. data/db/migrate/20140601151631_add_blog_image_email_header.rb +5 -0
  119. data/db/migrate/20141004154725_add_header_image.rb +9 -0
  120. data/db/migrate/20160821150108_index_foreign_keys_in_cms_blogs.rb +6 -0
  121. data/db/migrate/20160821150109_index_foreign_keys_in_cms_media_files.rb +6 -0
  122. data/db/migrate/20160821150110_index_foreign_keys_in_cms_posts.rb +6 -0
  123. data/lib/dm_cms.rb +4 -0
  124. data/lib/dm_cms/engine.rb +16 -0
  125. data/lib/dm_cms/liquid/filters/liquid_filters.rb +11 -0
  126. data/lib/dm_cms/liquid/tags/contact_form.rb +35 -0
  127. data/lib/dm_cms/liquid/tags/div.rb +42 -0
  128. data/lib/dm_cms/liquid/tags/image.rb +76 -0
  129. data/lib/dm_cms/liquid/tags/quote.rb +38 -0
  130. data/lib/dm_cms/liquid/tags/snippet.rb +37 -0
  131. data/lib/dm_cms/liquid/tags/url_asset.rb +41 -0
  132. data/lib/dm_cms/liquid/tags/url_media.rb +42 -0
  133. data/lib/dm_cms/liquid/tags/url_protected.rb +31 -0
  134. data/lib/tasks/dm_cms_tasks.rake +4 -0
  135. data/spec/controllers/admin/cms_blogs_controller_spec.rb +173 -0
  136. data/spec/controllers/admin/cms_pages_controller_spec.rb +182 -0
  137. data/spec/controllers/admin/cms_posts_controller_spec.rb +166 -0
  138. data/spec/dummy/README.rdoc +28 -0
  139. data/spec/dummy/Rakefile +6 -0
  140. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  141. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  142. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  143. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  144. data/spec/dummy/app/models/ability.rb +12 -0
  145. data/spec/dummy/app/models/user.rb +6 -0
  146. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  147. data/spec/dummy/bin/bundle +3 -0
  148. data/spec/dummy/bin/rails +4 -0
  149. data/spec/dummy/bin/rake +4 -0
  150. data/spec/dummy/config.ru +4 -0
  151. data/spec/dummy/config/application.rb +26 -0
  152. data/spec/dummy/config/boot.rb +5 -0
  153. data/spec/dummy/config/database.yml +25 -0
  154. data/spec/dummy/config/environment.rb +5 -0
  155. data/spec/dummy/config/environments/development.rb +37 -0
  156. data/spec/dummy/config/environments/production.rb +82 -0
  157. data/spec/dummy/config/environments/test.rb +39 -0
  158. data/spec/dummy/config/initializers/_themes_for_rails.rb +39 -0
  159. data/spec/dummy/config/initializers/account_initialization.rb +28 -0
  160. data/spec/dummy/config/initializers/assets.rb +8 -0
  161. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  162. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  163. data/spec/dummy/config/initializers/dm_core.rb +6 -0
  164. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  165. data/spec/dummy/config/initializers/inflections.rb +16 -0
  166. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  167. data/spec/dummy/config/initializers/session_store.rb +3 -0
  168. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  169. data/spec/dummy/config/locales/en.yml +23 -0
  170. data/spec/dummy/config/routes.rb +19 -0
  171. data/spec/dummy/config/secrets.yml +22 -0
  172. data/spec/dummy/db/development.sqlite3 +0 -0
  173. data/spec/dummy/db/migrate/20141114170927_add_globalize_countries.dm_core.rb +50 -0
  174. data/spec/dummy/db/migrate/20141114170928_devise_create_users.dm_core.rb +46 -0
  175. data/spec/dummy/db/migrate/20141114170929_add_user_fields.dm_core.rb +14 -0
  176. data/spec/dummy/db/migrate/20141114170930_rolify_create_roles.dm_core.rb +20 -0
  177. data/spec/dummy/db/migrate/20141114170931_add_last_access.dm_core.rb +10 -0
  178. data/spec/dummy/db/migrate/20141114170932_create_versions.dm_core.rb +19 -0
  179. data/spec/dummy/db/migrate/20141114170933_add_object_changes_column_to_versions.dm_core.rb +12 -0
  180. data/spec/dummy/db/migrate/20141114170934_create_dm_core_accounts.dm_core.rb +13 -0
  181. data/spec/dummy/db/migrate/20141114170935_add_account_to_users.dm_core.rb +9 -0
  182. data/spec/dummy/db/migrate/20141114170936_create_preferences.dm_core.rb +13 -0
  183. data/spec/dummy/db/migrate/20141114170937_create_comments.dm_core.rb +22 -0
  184. data/spec/dummy/db/migrate/20141114170938_add_activity.dm_core.rb +21 -0
  185. data/spec/dummy/db/migrate/20141114170939_add_type_to_comments.dm_core.rb +9 -0
  186. data/spec/dummy/db/migrate/20141114170940_add_category.dm_core.rb +28 -0
  187. data/spec/dummy/db/migrate/20141114170941_create_email_table.dm_core.rb +26 -0
  188. data/spec/dummy/db/migrate/20141114170942_add_user_profile.dm_core.rb +46 -0
  189. data/spec/dummy/db/migrate/20141114170943_add_profile_email.dm_core.rb +14 -0
  190. data/spec/dummy/db/migrate/20141114170944_create_payment_history.dm_core.rb +37 -0
  191. data/spec/dummy/db/migrate/20141114170945_change_anchor_field.dm_core.rb +10 -0
  192. data/spec/dummy/db/migrate/20141114170946_create_user_site_profile.dm_core.rb +27 -0
  193. data/spec/dummy/db/migrate/20141114170947_add_avatar.dm_core.rb +12 -0
  194. data/spec/dummy/db/migrate/20141114170948_add_notify_to_payment_history.dm_core.rb +8 -0
  195. data/spec/dummy/db/migrate/20141114170949_acts_as_votable_migration.dm_core.rb +28 -0
  196. data/spec/dummy/db/migrate/20141114170950_add_user_site_profile_uuid.dm_core.rb +19 -0
  197. data/spec/dummy/db/migrate/20141114170951_add_invoice_id.dm_core.rb +7 -0
  198. data/spec/dummy/db/migrate/20141114170952_acts_as_follower_migration.dm_core.rb +18 -0
  199. data/spec/dummy/db/migrate/20141114170953_rename_invoice_id.dm_core.rb +12 -0
  200. data/spec/dummy/db/migrate/20141114170954_add_core_addresses.dm_core.rb +18 -0
  201. data/spec/dummy/db/migrate/20141114170955_papertrail_increase_column.dm_core.rb +9 -0
  202. data/spec/dummy/db/migrate/20141114170956_acts_as_taggable_on_migration.dm_core.rb +32 -0
  203. data/spec/dummy/db/migrate/20141114170957_add_missing_unique_indices.dm_core.rb +23 -0
  204. data/spec/dummy/db/migrate/20141114170958_add_taggings_counter_cache_to_tags.dm_core.rb +16 -0
  205. data/spec/dummy/db/migrate/20141114170959_create_custom_fields.dm_core.rb +40 -0
  206. data/spec/dummy/db/migrate/20141114170960_add_missing_taggable_index.dm_core.rb +11 -0
  207. data/spec/dummy/db/migrate/20141114170961_create_documents.dm_knowledge.rb +19 -0
  208. data/spec/dummy/db/migrate/20141114170962_add_document_notes.dm_knowledge.rb +7 -0
  209. data/spec/dummy/db/migrate/20160128134522_add_favored_locale.dm_core.rb +17 -0
  210. data/spec/dummy/db/migrate/20160128134523_update_papertrail_v4.dm_core.rb +41 -0
  211. data/spec/dummy/db/schema.rb +590 -0
  212. data/spec/dummy/db/seeds.rb +18 -0
  213. data/spec/dummy/public/404.html +67 -0
  214. data/spec/dummy/public/422.html +67 -0
  215. data/spec/dummy/public/500.html +66 -0
  216. data/spec/dummy/public/favicon.ico +0 -0
  217. data/spec/dummy/themes/_mbus/_readme.md +6 -0
  218. data/spec/dummy/themes/_mbus/_theme.yml +21 -0
  219. data/spec/dummy/themes/_mbus/theme_assets/_mbus/javascripts/application.js +9 -0
  220. data/spec/dummy/themes/_mbus/theme_assets/_mbus/javascripts/bootstrap.js +2114 -0
  221. data/spec/dummy/themes/_mbus/theme_assets/_mbus/javascripts/bootstrap.min.js +6 -0
  222. data/spec/dummy/themes/_mbus/theme_assets/_mbus/javascripts/contact_me.js +75 -0
  223. data/spec/dummy/themes/_mbus/theme_assets/_mbus/javascripts/jqBootstrapValidation.js +912 -0
  224. data/spec/dummy/themes/_mbus/theme_assets/_mbus/javascripts/jquery-1.11.0.js +4 -0
  225. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/application.css +14 -0
  226. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/bootstrap.css +6203 -0
  227. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/bootstrap.min.css +5 -0
  228. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/css/font-awesome.css +1566 -0
  229. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/css/font-awesome.min.css +4 -0
  230. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/fonts/FontAwesome.otf +0 -0
  231. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/fonts/fontawesome-webfont.eot +0 -0
  232. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/fonts/fontawesome-webfont.svg +504 -0
  233. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/fonts/fontawesome-webfont.ttf +0 -0
  234. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/fonts/fontawesome-webfont.woff +0 -0
  235. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/bordered-pulled.less +16 -0
  236. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/core.less +12 -0
  237. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/fixed-width.less +6 -0
  238. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/font-awesome.less +17 -0
  239. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/icons.less +506 -0
  240. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/larger.less +13 -0
  241. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/list.less +19 -0
  242. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/mixins.less +20 -0
  243. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/path.less +14 -0
  244. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/rotated-flipped.less +9 -0
  245. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/spinning.less +32 -0
  246. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/stacked.less +20 -0
  247. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/less/variables.less +515 -0
  248. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_bordered-pulled.scss +16 -0
  249. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_core.scss +12 -0
  250. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_fixed-width.scss +6 -0
  251. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_icons.scss +506 -0
  252. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_larger.scss +13 -0
  253. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_list.scss +19 -0
  254. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_mixins.scss +20 -0
  255. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_path.scss +14 -0
  256. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_rotated-flipped.scss +9 -0
  257. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_spinning.scss +32 -0
  258. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_stacked.scss +20 -0
  259. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/_variables.scss +515 -0
  260. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/font-awesome-4.1.0/scss/font-awesome.scss +17 -0
  261. data/spec/dummy/themes/_mbus/theme_assets/_mbus/stylesheets/modern-business.css +93 -0
  262. data/spec/dummy/themes/_mbus/theme_support/config/load_theme.rb +0 -0
  263. data/spec/dummy/themes/_mbus/theme_support/locales/site.cs.yml +57 -0
  264. data/spec/dummy/themes/_mbus/theme_support/locales/site.de.yml +57 -0
  265. data/spec/dummy/themes/_mbus/theme_support/locales/site.en.yml +57 -0
  266. data/spec/dummy/themes/_mbus/theme_support/locales/site.fi.yml +58 -0
  267. data/spec/dummy/themes/_mbus/theme_support/locales/site.ja.yml +57 -0
  268. data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_blog_right_sidebar.html.erb +91 -0
  269. data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_comment.html.erb +21 -0
  270. data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_comment_form.html.erb +16 -0
  271. data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_comment_list.html.erb +7 -0
  272. data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_comment_section.html.erb +17 -0
  273. data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_page_footer.html.erb +11 -0
  274. data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_page_header.html.erb +39 -0
  275. data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_page_top.html.erb +24 -0
  276. data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_post_summary_item.html.erb +11 -0
  277. data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/_social_buttons_initialization.html.erb +10 -0
  278. data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/blog.html.erb +47 -0
  279. data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/blog_post.html.erb +55 -0
  280. data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/content_full_width.html.erb +28 -0
  281. data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/content_with_left_nav.html.erb +44 -0
  282. data/spec/dummy/themes/_mbus/theme_support/views/layouts/cms_templates/index.html.erb +19 -0
  283. data/spec/dummy/themes/local/_theme.yml +8 -0
  284. data/spec/factories/accounts.rb +17 -0
  285. data/spec/factories/blogs.rb +19 -0
  286. data/spec/factories/posts.rb +23 -0
  287. data/spec/factories/user_profiles.rb +10 -0
  288. data/spec/factories/users.rb +19 -0
  289. data/spec/features/admin/blog_admin_spec.rb +16 -0
  290. data/spec/models/cms_blog_spec.rb +37 -0
  291. data/spec/models/cms_page_spec.rb +9 -0
  292. data/spec/models/cms_post_spec.rb +44 -0
  293. data/spec/rails_helper.rb +70 -0
  294. data/spec/spec_helper.rb +85 -0
  295. data/spec/support/accounts.rb +17 -0
  296. data/spec/support/devise.rb +44 -0
  297. data/spec/support/fix_locale.rb +57 -0
  298. metadata +545 -0
@@ -0,0 +1,76 @@
1
+ class CmsPost < ActiveRecord::Base
2
+
3
+ # --- globalize (don't use versioning: true, translations erased when updating regular model data. Maybe fixed in github version)
4
+ translates :title, :summary, :content, :fallbacks_for_empty_translations => true #, :versioning => true
5
+ globalize_accessors :locales => DmCore::Language.language_array
6
+
7
+ # --- FriendlyId
8
+ extend FriendlyId
9
+ include DmCore::Concerns::FriendlyId
10
+
11
+ # --- re-define so it can be scoped to the blog as well
12
+ friendly_id :model_slug, use: :scoped, scope: [:account_id, :cms_blog]
13
+
14
+ acts_as_commentable
15
+
16
+ belongs_to :cms_blog
17
+ belongs_to :account
18
+
19
+ default_scope { where(account_id: Account.current.id) }
20
+ scope :published, -> { where("published_on IS NOT NULL AND published_on <= ?", Time.now ) }
21
+
22
+ validates :title, presence_default_locale: true
23
+ validates :summary, liquid: { :locales => true }, presence_default_locale: true
24
+ validates :content, liquid: { :locales => true }, presence_default_locale: true
25
+ validates_uniqueness_of :slug, scope: [:account_id, :cms_blog_id]
26
+
27
+ self.per_page = 10
28
+
29
+ # Base the slug on the default locale
30
+ #------------------------------------------------------------------------------
31
+ def model_slug
32
+ send("title_#{Account.current.preferred_default_locale}")
33
+ end
34
+
35
+ #------------------------------------------------------------------------------
36
+ def is_published?
37
+ !published_on.nil? && published_on <= Time.now
38
+ end
39
+
40
+ # Allow comments if also enabled in the blog
41
+ #------------------------------------------------------------------------------
42
+ def comments_allowed?
43
+ cms_blog.comments_allowed? && comments_allowed
44
+ end
45
+
46
+ # Send post notification to any members and followers. Updates the
47
+ # :notification_sent_on column after emails sent.
48
+ # Use 'sets' to only end up with a unique list of users
49
+ #------------------------------------------------------------------------------
50
+ def send_notification_emails(test_user = nil)
51
+ if test_user
52
+ email = PostNotifyMailer.post_notify(test_user, self, self.account).deliver_now
53
+ return (email ? 1 : 0)
54
+ else
55
+ user_list = cms_blog.member_list(:all).to_set
56
+ cms_blog.followers.each {|follower| user_list << follower.user}
57
+ async_send_notification_emails(user_list)
58
+ return user_list.size
59
+ end
60
+
61
+ end
62
+
63
+ #------------------------------------------------------------------------------
64
+ def async_send_notification_emails(user_list)
65
+ success = failed = 0
66
+ Rails.logger.info "=== Sending #{user_list.size} emails for blog post '#{title}'"
67
+ user_list.each do |user|
68
+ email = PostNotifyMailer.post_notify(user, self, self.account).deliver_later
69
+ success += 1 if email
70
+ failed += 1 if email.nil?
71
+ end
72
+ update_attribute(:notification_sent_on, Time.now)
73
+ Rails.logger.info " Completed sending: successes (#{success}) -- failures (#{failed}) "
74
+ end
75
+
76
+ end
@@ -0,0 +1,42 @@
1
+ # Note: fragment caching is used during rendering. The cache key is based
2
+ # on both the model and the current locale (because each model supports
3
+ # multiple translations). The cache will be busted automatically since
4
+ # the updated_at attribute will be updated on save.
5
+ #------------------------------------------------------------------------------
6
+ class CmsSnippet < ActiveRecord::Base
7
+ class Translation < ::Globalize::ActiveRecord::Translation
8
+ has_paper_trail
9
+ end
10
+
11
+ # --- FriendlyId
12
+ extend FriendlyId
13
+ include DmCore::Concerns::FriendlyId
14
+
15
+ default_scope { where(account_id: Account.current.id) }
16
+
17
+ # --- globalize (don't use versioning: true, translations erased when updating regular model data. Maybe fixed in github version)
18
+ translates :content, :fallbacks_for_empty_translations => true
19
+ globalize_accessors :locales => DmCore::Language.language_array
20
+
21
+ # --- versioning - skip anything translated
22
+ has_paper_trail :skip => :content
23
+
24
+ # --- validations
25
+ validates_presence_of :itemtype, :slug
26
+ validates_length_of :itemtype, :maximum => 30
27
+ validates :content, liquid: { :locales => true }, presence_default_locale: true
28
+
29
+ # --- content types supported
30
+ CONTENT_TYPES = [ 'Markdown', 'Textile', 'HTML' ]
31
+
32
+ #------------------------------------------------------------------------------
33
+ def is_published?
34
+ published
35
+ end
36
+
37
+ #------------------------------------------------------------------------------
38
+ def to_liquid
39
+ {}
40
+ end
41
+
42
+ end
@@ -0,0 +1,28 @@
1
+ # Generic contact form class. If changes are needed, then a new version should
2
+ # be created in the theme's models folder
3
+ #------------------------------------------------------------------------------
4
+ class ContactForm < ::MailForm::Base
5
+
6
+ attribute :name, :validate => true
7
+ attribute :email, :validate => /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
8
+ attribute :organization # Not validated
9
+ attribute :subject, :validate => true
10
+ attribute :message, :validate => true
11
+ attribute :reason, :validate => true
12
+ attribute :nickname, :captcha => true
13
+
14
+ # append :remote_ip, :user_agent, :session # append these values to the end of all emails
15
+
16
+ # for a contact form, the "from" address should be a valid email address
17
+ # within the domain that is doing the actual sending, instead of the contacter's
18
+ # address. This important for services like Sparkpost or Mandrill, that checks
19
+ # the validity of the sending domain.
20
+ #------------------------------------------------------------------------------
21
+ def headers
22
+ { subject: "#{I18n.t('cms.contact_form.subject_prefix')}: #{reason}: #{subject}" ,
23
+ to: Account.current.preferred_support_email,
24
+ from: Account.current.preferred_support_email,
25
+ reply_to: %("#{name}" <#{email}>)
26
+ }
27
+ end
28
+ end
@@ -0,0 +1,54 @@
1
+ # Wrap blog/cms specific CanCan rules. Should be included in the main app's
2
+ # Ability class.
3
+ # NOTE: When checking abilities, don't check for Class level abilities,
4
+ # unless you don't care about the instance level. For example, don't
5
+ # use both styles
6
+ # can? :moderate, Forum
7
+ # can? :moderate, @forum
8
+ # In this case, if you need to check the class level, then use specific
9
+ # current_user.has_role? :moderator, Forum
10
+ #------------------------------------------------------------------------------
11
+
12
+ module DmCms
13
+ module Concerns
14
+ module Ability
15
+ def dm_cms_abilities(user)
16
+ if user
17
+ #--- Admin
18
+ if user.has_role?(:content_manager)
19
+ can :manage_content, :all
20
+ can :access_admin, :all
21
+ end
22
+
23
+ #--- Blog
24
+ can(:read, CmsBlog) { |blog| blog.can_be_read_by?(user) }
25
+ can(:reply, CmsBlog) { |blog| blog.can_be_replied_by?(user) }
26
+ # can :moderate, CmsBlog, :id => CmsBlog.published.with_role(:moderator, user).map(&:id)
27
+
28
+ can(:read, CmsPost) { |post| post.is_published? || user.has_role?(:reviewer) || user.has_role?(:content_manager)}
29
+
30
+ #--- Pages
31
+ can(:read, CmsPage) { |page| page.is_published? || user.has_role?(:reviewer) || user.has_role?(:content_manager)}
32
+ else
33
+ #--- can only read/see public blogs when not logged in
34
+ can(:read, CmsBlog) { |blog| blog.can_be_read_by?(user) }
35
+ can(:read, CmsPost) { |post| post.is_published? }
36
+ can(:read, CmsPage) { |page| page.is_published? }
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ #------------------------------------------------------------------------------
44
+ # The abilities get basically compiled. So if you use
45
+ #
46
+ # can :moderate, Forum, :id => Forum.with_role(:moderator, user).map(&:id)
47
+ #
48
+ # this will execute the Forum.with_role query once during Ability.new. However
49
+ #
50
+ # can :moderate, Forum do |forum|
51
+ # user.has_role? :moderator, forum
52
+ # end
53
+ #
54
+ # this will execute the has_role? block on each call to can?
@@ -0,0 +1,34 @@
1
+ module DmCms
2
+ module PermittedParams
3
+
4
+ #------------------------------------------------------------------------------
5
+ def cms_snippet_params
6
+ params.require(:cms_snippet).permit! if can? :manage_content, :all
7
+ end
8
+
9
+ #------------------------------------------------------------------------------
10
+ def cms_blog_params
11
+ params.require(:cms_blog).permit! if can? :manage_content, :all
12
+ end
13
+
14
+ #------------------------------------------------------------------------------
15
+ def cms_post_params
16
+ params.require(:cms_post).permit! if can? :manage_content, :all
17
+ end
18
+
19
+ #------------------------------------------------------------------------------
20
+ def cms_page_params
21
+ params.require(:cms_page).permit! if can? :manage_content, :all
22
+ end
23
+
24
+ #------------------------------------------------------------------------------
25
+ def cms_contentitem_params
26
+ params.require(:cms_contentitem).permit! if can? :manage_content, :all
27
+ end
28
+
29
+ #------------------------------------------------------------------------------
30
+ def media_file_params
31
+ params.require(:media_file).permit! if can? :manage_content, :all
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,102 @@
1
+ #------------------------------------------------------------------------------
2
+ class MediaFile < ActiveRecord::Base
3
+
4
+ self.table_name = 'cms_media_files'
5
+
6
+ translates :title, :description, fallbacks_for_empty_translations: true
7
+ globalize_accessors :locales => DmCore::Language.language_array
8
+ acts_as_taggable
9
+
10
+ belongs_to :user
11
+ default_scope { where(account_id: Account.current.id) }
12
+ validate :validate_name_is_unique
13
+
14
+ #--- Using Carrierwave
15
+ mount_uploader :media, MediaUploader
16
+ before_save :prepare_attributes
17
+
18
+ #------------------------------------------------------------------------------
19
+ def image?
20
+ self.media_content_type.start_with? 'image'
21
+ end
22
+
23
+ #------------------------------------------------------------------------------
24
+ def pdf?
25
+ self.media_content_type.end_with? 'pdf'
26
+ end
27
+
28
+ #------------------------------------------------------------------------------
29
+ def short_location(version = nil)
30
+ filename = version ? self.media.versions[version].file.filename : self.media.file.filename
31
+ folder.blank? ? filename : "#{folder}/#{filename}"
32
+ end
33
+
34
+ # return a list of tags for all media objects
35
+ #------------------------------------------------------------------------------
36
+ def self.tag_list_all
37
+ MediaFile.tag_counts_on(:tags).map(&:name).sort
38
+ end
39
+
40
+ # Given a name in the form 'folder/filename.ext', grab the url with the correct version
41
+ # Use 'version: :original' to allow the original version to be pulled
42
+ #------------------------------------------------------------------------------
43
+ def self.url_by_name(name, options = {version: :original})
44
+ asset = MediaFile.find_by_name(name)
45
+ if asset
46
+ options[:version] == :original ? asset.media.url : asset.media.url(options[:version])
47
+ else
48
+ nil
49
+ end
50
+ end
51
+
52
+ # Given a name in the form 'folder/filename.ext', check if the version exists.
53
+ # Use 'version: :original' to allow the original version to be pulled
54
+ #------------------------------------------------------------------------------
55
+ def self.version_exists?(name, options = {version: :original})
56
+ asset = MediaFile.find_by_name(name)
57
+ if asset
58
+ options[:version] == :original ? true : asset.media.version_exists?(options[:version])
59
+ else
60
+ false
61
+ end
62
+ end
63
+
64
+ # Given a name in the form 'folder/filename.ext', return the correct media file
65
+ #------------------------------------------------------------------------------
66
+ def self.find_by_name(name)
67
+ components = name.split('/')
68
+ filename = components[-1]
69
+ folder = components[-2] || ''
70
+ asset = MediaFile.where(folder: folder, media: filename).first
71
+ end
72
+
73
+ private
74
+
75
+ #------------------------------------------------------------------------------
76
+ def validate_name_is_unique
77
+ if self.new_record?
78
+ if self.media.file.nil?
79
+ errors.add :media, "please select a file to upload"
80
+ elsif MediaFile.where(media: self.media.file.original_filename, folder: self.folder, account_id: self.account_id).count > 0
81
+ errors.add :media, "'#{self.short_location}' already exists"
82
+ end
83
+ end
84
+ end
85
+
86
+ # Save the media metadata, and add the 'folder' as a tag
87
+ #------------------------------------------------------------------------------
88
+ def prepare_attributes
89
+ if media.present? && media_changed?
90
+ self.media_content_type = media.file.content_type
91
+ self.media_file_size = media.file.size
92
+ end
93
+
94
+ if self.new_record?
95
+ self.folder = self.folder.sanitize_filename
96
+ self.tag_list.add(self.folder)
97
+ self.tag_list.add(media.file.extension)
98
+ end
99
+ end
100
+
101
+
102
+ end
@@ -0,0 +1,15 @@
1
+ class CmsBlogPresenter < BasePresenter
2
+
3
+ presents :cms_blog
4
+
5
+ #------------------------------------------------------------------------------
6
+ def label_published
7
+ cms_blog.is_published? ? h.colored_label('Published', :success) : h.colored_label('Draft')
8
+ end
9
+
10
+ #------------------------------------------------------------------------------
11
+ def visibility
12
+ cms_blog.visibility_to_s
13
+ end
14
+
15
+ end
@@ -0,0 +1,23 @@
1
+ class CmsPagePresenter < BasePresenter
2
+
3
+ presents :cms_page
4
+
5
+ #------------------------------------------------------------------------------
6
+ def label_published
7
+ cms_page.is_published? ? h.colored_label('Published', :success) : h.colored_label('Draft')
8
+ end
9
+
10
+ # Prepare a title for admin Page views. page/menu title with slug in <small>
11
+ #------------------------------------------------------------------------------
12
+ def admin_edit_title
13
+ main_title = (cms_page.title.present? ? cms_page.title : (cms_page.menutitle.present? ? cms_page.menutitle : '(no title)'))
14
+ sub_title = cms_page.slug
15
+
16
+ #--- make sure it's built safely...
17
+ html = "".html_safe
18
+ html << main_title
19
+ html << "<small>".html_safe
20
+ html << sub_title
21
+ html << "</small>".html_safe
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ class CmsPostPresenter < BasePresenter
2
+
3
+ presents :cms_post
4
+
5
+ #------------------------------------------------------------------------------
6
+ def label_published
7
+ date_formatted = cms_post.published_on.nil? ? 'Draft' : format_datetime(cms_post.published_on)
8
+ cms_post.is_published? ? h.colored_label(date_formatted, :success) : h.colored_label(date_formatted)
9
+ end
10
+
11
+ end
@@ -0,0 +1,10 @@
1
+ class CmsSnippetPresenter < BasePresenter
2
+
3
+ presents :cms_snippet
4
+
5
+ #------------------------------------------------------------------------------
6
+ def label_published
7
+ cms_snippet.is_published? ? h.colored_label('Published', :success) : h.colored_label('Draft')
8
+ end
9
+
10
+ end
@@ -0,0 +1,169 @@
1
+ # For uploading files into the media library. Creates versions based on
2
+ # settings in the Account. Will also create retina versions automatically.
3
+ # Files are stored in the theme's 'media' folder. User can specify a single
4
+ # subfolder to store the file, giving a little extra flexibility.
5
+ # At the moment, files are in the public folders. Future version will
6
+ # allow uploading protected files.
7
+ #
8
+ # make sure ghostscript is installed for PDF thumbnailing
9
+ # on OSX, `brew install ghostscript`
10
+ #------------------------------------------------------------------------------
11
+ class MediaUploader < CarrierWave::Uploader::Base
12
+ include DmCore::AccountHelper
13
+
14
+ # Include RMagick or MiniMagick support:
15
+ include CarrierWave::MimeTypes
16
+ include CarrierWave::MiniMagick
17
+
18
+ # Choose what kind of storage to use for this uploader:
19
+ storage :file
20
+ process :set_content_type
21
+
22
+ # Everything gets stored in the 'media' folder
23
+ #------------------------------------------------------------------------------
24
+ def store_dir
25
+ partition_dir = model.folder
26
+ "#{account_site_assets_media(false)}/#{partition_dir}"
27
+ end
28
+
29
+ # We basically want the width to be the max, allowing the height to grow
30
+ #------------------------------------------------------------------------------
31
+ def resize_to_width(width)
32
+ manipulate! do |img|
33
+ img.resize "#{width}>"
34
+ img = yield(img) if block_given?
35
+ img
36
+ end
37
+ end
38
+
39
+ # If a pdf, convert to jpg and size, maintain aspect ration and pad to square
40
+ # If an image, resize it to a cropped square
41
+ #------------------------------------------------------------------------------
42
+ def thumb_image_pdf(width, height)
43
+ if pdf?(self)
44
+ self.convert(:jpg)
45
+ self.resize_and_pad(width, height)
46
+ else
47
+ self.resize_to_fill(width, height)
48
+ end
49
+ end
50
+
51
+ # Convert to png if a pdf, then size to a specfic width
52
+ #------------------------------------------------------------------------------
53
+ def size_image_pdf(width)
54
+ self.convert(:jpg) if pdf?(self)
55
+ self.resize_to_width(width)
56
+ end
57
+
58
+ # From: https://github.com/jhnvz/retina_rails
59
+ # Process retina quality of the image.
60
+ # Works with ImageMagick and MiniMagick
61
+ # === Parameters
62
+ #
63
+ # [percentage (Int)] quality in percentage
64
+ #
65
+ def retina_quality(percentage)
66
+ manipulate! do |img|
67
+ if defined?(Magick)
68
+ img.write(current_path) { self.quality = percentage } unless img.quality == percentage
69
+ elsif defined?(MiniMagick)
70
+ img.quality(percentage.to_s)
71
+ end
72
+ img = yield(img) if block_given?
73
+ img
74
+ end
75
+ end
76
+
77
+ # Create different versions of image files
78
+ # Retina naming: http://blog.remarkablelabs.com/2013/01/creating-retina-images-with-carrierwave
79
+ #------------------------------------------------------------------------------
80
+ version :retina_lg, :if => :thumbnable_retina? do
81
+ # process :size_image_pdf => [Account.current.preferred_image_large_width * 2]
82
+ process :size_image_pdf => [900 * 2]
83
+ process :retina_quality => 60
84
+ def full_filename(for_file = model.media.file)
85
+ name = super.tap {|file_name| file_name.gsub!(/\.+[0-9a-zA-Z]{3,4}$/){ "@2x#{$&}" }.gsub!('retina_', '') }
86
+ model.pdf? ? (name.chomp(File.extname(name)) + '.jpg') : name
87
+ end
88
+ end
89
+ version :lg, :if => :thumbnable? do
90
+ # process :size_image_pdf => [Account.current.preferred_image_large_width]
91
+ process :size_image_pdf => [900]
92
+ def full_filename (for_file = model.file.file)
93
+ model.pdf? ? (super.chomp(File.extname(super)) + '.jpg') : super
94
+ end
95
+ end
96
+
97
+ version :retina_md, :if => :thumbnable_retina?, :from_version => :retina_lg do
98
+ # process :size_image_pdf => [Account.current.preferred_image_medium_width * 2]
99
+ process :size_image_pdf => [600 * 2]
100
+ process :retina_quality => 60
101
+ def full_filename(for_file = model.media.file)
102
+ name = super.tap {|file_name| file_name.gsub!(/\.+[0-9a-zA-Z]{3,4}$/){ "@2x#{$&}" }.gsub!('retina_', '') }
103
+ model.pdf? ? (name.chomp(File.extname(name)) + '.jpg') : name
104
+ end
105
+ end
106
+ version :md, :if => :thumbnable?, :from_version => :lg do
107
+ # process :size_image_pdf => [Account.current.preferred_image_medium_width]
108
+ process :size_image_pdf => [600]
109
+ def full_filename (for_file = model.file.file)
110
+ model.pdf? ? (super.chomp(File.extname(super)) + '.jpg') : super
111
+ end
112
+ end
113
+
114
+ version :retina_sm, :if => :thumbnable_retina?, :from_version => :retina_md do
115
+ # process :size_image_pdf => [Account.current.preferred_image_small_width * 2]
116
+ process :size_image_pdf => [300 * 2]
117
+ process :retina_quality => 60
118
+ def full_filename(for_file = model.media.file)
119
+ name = super.tap {|file_name| file_name.gsub!(/\.+[0-9a-zA-Z]{3,4}$/){ "@2x#{$&}" }.gsub!('retina_', '') }
120
+ model.pdf? ? (name.chomp(File.extname(name)) + '.jpg') : name
121
+ end
122
+ end
123
+ version :sm, :if => :thumbnable?, :from_version => :retina_md do
124
+ # process :size_image_pdf => [Account.current.preferred_image_small_width]
125
+ process :size_image_pdf => [300]
126
+ def full_filename (for_file = model.file.file)
127
+ model.pdf? ? (super.chomp(File.extname(super)) + '.jpg') : super
128
+ end
129
+ end
130
+
131
+ version :thumb, :if => :thumbnable?, :from_version => :retina_md do
132
+ # process thumb_image_pdf: [Account.current.preferred_image_thumbnail_width, Account.current.preferred_image_thumbnail_width]
133
+ process thumb_image_pdf: [200, 200]
134
+ def full_filename (for_file = model.file.file)
135
+ model.pdf? ? (super.chomp(File.extname(super)) + '.jpg') : super
136
+ end
137
+ end
138
+
139
+
140
+ # Add a white list of extensions which are allowed to be uploaded.
141
+ # For images you might use something like this:
142
+ #------------------------------------------------------------------------------
143
+ def extension_white_list
144
+ %w(jpg jpeg gif png mp3 mp4 m4v ogg webm pdf css js)
145
+ end
146
+
147
+ protected
148
+
149
+ #------------------------------------------------------------------------------
150
+ def thumbnable?(new_file)
151
+ image?(new_file) || pdf?(new_file)
152
+ end
153
+
154
+ #------------------------------------------------------------------------------
155
+ def thumbnable_retina?(new_file)
156
+ model.generate_retina? ? (image?(new_file) || pdf?(new_file)) : false
157
+ end
158
+
159
+ #------------------------------------------------------------------------------
160
+ def image?(new_file)
161
+ new_file.content_type.start_with? 'image'
162
+ end
163
+
164
+ #------------------------------------------------------------------------------
165
+ def pdf?(new_file)
166
+ new_file.content_type.end_with? 'pdf'
167
+ end
168
+
169
+ end