browsercms 3.5.7 → 4.0.0.alpha

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 (523) hide show
  1. checksums.yaml +7 -0
  2. data/COPYRIGHT.txt +2 -1
  3. data/README.markdown +3 -3
  4. data/app/assets/fonts/icomoon.dev.svg +61 -0
  5. data/app/assets/fonts/icomoon.eot +0 -0
  6. data/app/assets/fonts/icomoon.svg +61 -0
  7. data/app/assets/fonts/icomoon.ttf +0 -0
  8. data/app/assets/fonts/icomoon.woff +0 -0
  9. data/app/assets/images/ckeditor/plugins/delete_content/icons/deletecontent.png +0 -0
  10. data/app/assets/images/ckeditor/plugins/edit_content/icons/editcontent.png +0 -0
  11. data/app/assets/images/ckeditor/plugins/move_content/icons/movecontentdown.png +0 -0
  12. data/app/assets/images/ckeditor/plugins/move_content/icons/movecontentup.png +0 -0
  13. data/app/assets/images/cms/arrow-down.png +0 -0
  14. data/app/assets/images/cms/arrow-up.png +0 -0
  15. data/app/assets/images/cms/cogs.png +0 -0
  16. data/app/assets/images/cms/dashboard/home.png +0 -0
  17. data/app/assets/images/cms/home.png +0 -0
  18. data/app/assets/images/cms/logo.png +0 -0
  19. data/app/assets/images/cms/pencil.png +0 -0
  20. data/app/assets/images/cms/plus.png +0 -0
  21. data/app/assets/images/cms/user.png +0 -0
  22. data/app/assets/javascripts/bcms/ckeditor_inline.js +23 -0
  23. data/app/assets/javascripts/bcms/ckeditor_standard_config.js +1 -1
  24. data/app/assets/javascripts/ckeditor/plugins/delete_content/plugin.js +36 -0
  25. data/app/assets/javascripts/ckeditor/plugins/edit_content/plugin.js +24 -0
  26. data/app/assets/javascripts/ckeditor/plugins/move_content/plugin.js +25 -0
  27. data/app/assets/javascripts/cms/ajax.js +60 -0
  28. data/app/assets/javascripts/cms/application.js +6 -1
  29. data/app/assets/javascripts/cms/attachment_manager.js.erb +3 -10
  30. data/app/assets/javascripts/cms/content_library.js +31 -12
  31. data/app/assets/javascripts/cms/core_library.js.erb +68 -36
  32. data/app/assets/javascripts/cms/form_builder.js +250 -0
  33. data/app/assets/javascripts/cms/namespace.js +2 -0
  34. data/app/assets/javascripts/cms/new_content_button.js +27 -0
  35. data/app/assets/javascripts/cms/page_editor.js +188 -0
  36. data/app/assets/javascripts/cms/page_toolbar.js +13 -0
  37. data/app/assets/javascripts/cms/site.js +2 -0
  38. data/app/assets/javascripts/cms/sitemap.js +219 -0
  39. data/app/assets/javascripts/cms/toolbar.js +17 -1
  40. data/app/assets/javascripts/cms/user.js +40 -0
  41. data/app/assets/javascripts/jquery.exists.js +5 -0
  42. data/app/assets/javascripts/jquery.taglist.js +37 -23
  43. data/app/assets/stylesheets/cms/_assets.css.scss +55 -0
  44. data/app/assets/stylesheets/cms/_base.css.scss +42 -0
  45. data/app/assets/stylesheets/cms/_cms-buttons.css.scss +73 -0
  46. data/app/assets/stylesheets/cms/_cms-forms.css.scss +70 -0
  47. data/app/assets/stylesheets/cms/_colors.css.scss +20 -0
  48. data/app/assets/stylesheets/cms/_dashboard.css.scss +25 -0
  49. data/app/assets/stylesheets/cms/_glyph.css.scss +60 -0
  50. data/app/assets/stylesheets/cms/_main-area.css.scss +62 -0
  51. data/app/assets/stylesheets/cms/_nav.css.scss +197 -0
  52. data/app/assets/stylesheets/cms/_sidebar.css.scss +64 -0
  53. data/app/assets/stylesheets/cms/_sitemap.css.scss +196 -0
  54. data/app/assets/stylesheets/cms/_submenu.css.scss +48 -0
  55. data/app/assets/stylesheets/cms/application.css.scss +49 -0
  56. data/app/assets/stylesheets/cms/core.css.scss +96 -0
  57. data/app/assets/stylesheets/cms/default-forms.css.scss +3 -0
  58. data/app/assets/stylesheets/cms/includes/_animation.css.scss +2 -0
  59. data/app/assets/stylesheets/cms/includes/_rem.css.scss +120 -0
  60. data/app/assets/stylesheets/cms/includes/animation/_animate.css.scss +31 -0
  61. data/app/assets/stylesheets/cms/includes/animation/_core.css.scss +127 -0
  62. data/app/assets/stylesheets/cms/includes/animation/_shared.css.scss +22 -0
  63. data/app/assets/stylesheets/cms/includes/animation/animate/_attention-seekers.css.scss +152 -0
  64. data/app/assets/stylesheets/cms/includes/animation/animate/_bouncing.css.scss +3 -0
  65. data/app/assets/stylesheets/cms/includes/animation/animate/_classes.css.scss +21 -0
  66. data/app/assets/stylesheets/cms/includes/animation/animate/_fading.css.scss +3 -0
  67. data/app/assets/stylesheets/cms/includes/animation/animate/_flippers.css.scss +87 -0
  68. data/app/assets/stylesheets/cms/includes/animation/animate/_lightspeed.css.scss +24 -0
  69. data/app/assets/stylesheets/cms/includes/animation/animate/_rotating.css.scss +3 -0
  70. data/app/assets/stylesheets/cms/includes/animation/animate/_specials.css.scss +42 -0
  71. data/app/assets/stylesheets/cms/includes/animation/animate/bouncing/_bouncing-entrances.css.scss +68 -0
  72. data/app/assets/stylesheets/cms/includes/animation/animate/bouncing/_bouncing-exits.css.scss +60 -0
  73. data/app/assets/stylesheets/cms/includes/animation/animate/fading/_fading-entrances.css.scss +86 -0
  74. data/app/assets/stylesheets/cms/includes/animation/animate/fading/_fading-exits.css.scss +86 -0
  75. data/app/assets/stylesheets/cms/includes/animation/animate/rotating/_rotating-entrances.css.scss +58 -0
  76. data/app/assets/stylesheets/cms/includes/animation/animate/rotating/_rotating-exits.css.scss +58 -0
  77. data/app/assets/stylesheets/cms/page_content_editing.css.scss +4 -0
  78. data/app/assets/stylesheets/cms/page_editor.css.scss +4 -0
  79. data/app/assets/stylesheets/cms/style.css.scss +138 -0
  80. data/app/assets/stylesheets/cms/styles/_alerts.css.scss +150 -0
  81. data/app/assets/stylesheets/cms/styles/_base-grid.css.scss +299 -0
  82. data/app/assets/stylesheets/cms/styles/_buttons.css.scss +247 -0
  83. data/app/assets/stylesheets/cms/styles/_dropdown.css.scss +155 -0
  84. data/app/assets/stylesheets/cms/styles/_forms.css.scss +728 -0
  85. data/app/assets/stylesheets/cms/styles/_glyph.css.scss +86 -0
  86. data/app/assets/stylesheets/cms/styles/_images.css.scss +75 -0
  87. data/app/assets/stylesheets/cms/styles/_lists.css.scss +115 -0
  88. data/app/assets/stylesheets/cms/styles/_modal.css.scss +174 -0
  89. data/app/assets/stylesheets/cms/styles/_progress.css.scss +43 -0
  90. data/app/assets/stylesheets/cms/styles/_tables.css.scss +141 -0
  91. data/app/assets/stylesheets/cms/styles/_text.css.scss +134 -0
  92. data/app/controllers/cms/application_controller.rb +3 -68
  93. data/app/controllers/cms/attachments_controller.rb +5 -5
  94. data/app/controllers/cms/base_controller.rb +20 -13
  95. data/app/controllers/cms/cache_controller.rb +16 -17
  96. data/app/controllers/cms/category_types_controller.rb +6 -1
  97. data/app/controllers/cms/connectors_controller.rb +12 -7
  98. data/app/controllers/cms/content_block_controller.rb +128 -71
  99. data/app/controllers/cms/content_controller.rb +54 -56
  100. data/app/controllers/cms/dashboard_controller.rb +5 -6
  101. data/app/controllers/cms/dynamic_views_controller.rb +12 -9
  102. data/app/controllers/cms/email_messages_controller.rb +18 -13
  103. data/app/controllers/cms/form_entries_controller.rb +119 -0
  104. data/app/controllers/cms/form_fields_controller.rb +74 -0
  105. data/app/controllers/cms/forms_controller.rb +35 -0
  106. data/app/controllers/cms/groups_controller.rb +13 -16
  107. data/app/controllers/cms/html_blocks_controller.rb +2 -2
  108. data/app/controllers/cms/inline_content_controller.rb +48 -0
  109. data/app/controllers/cms/links_controller.rb +58 -46
  110. data/app/controllers/cms/page_components_controller.rb +20 -0
  111. data/app/controllers/cms/page_routes_controller.rb +44 -40
  112. data/app/controllers/cms/pages_controller.rb +111 -97
  113. data/app/controllers/cms/passwords_controller.rb +17 -0
  114. data/app/controllers/cms/portlet_controller.rb +0 -1
  115. data/app/controllers/cms/portlets_controller.rb +20 -27
  116. data/app/controllers/cms/redirects_controller.rb +13 -9
  117. data/app/controllers/cms/resource_controller.rb +15 -4
  118. data/app/controllers/cms/routes_controller.rb +2 -4
  119. data/app/controllers/cms/section_nodes_controller.rb +6 -37
  120. data/app/controllers/cms/sections_controller.rb +13 -8
  121. data/app/controllers/cms/sessions_controller.rb +8 -66
  122. data/app/controllers/cms/sites/passwords_controller.rb +27 -0
  123. data/app/controllers/cms/sites/sessions_controller.rb +20 -0
  124. data/app/controllers/cms/tags_controller.rb +12 -12
  125. data/app/controllers/cms/tasks_controller.rb +45 -46
  126. data/app/controllers/cms/user_controller.rb +8 -0
  127. data/app/controllers/cms/users_controller.rb +91 -68
  128. data/app/helpers/cms/application_helper.rb +58 -52
  129. data/app/helpers/cms/content_block_helper.rb +8 -7
  130. data/app/helpers/cms/form_tag_helper.rb +21 -25
  131. data/app/helpers/cms/menu_helper.rb +1 -3
  132. data/app/helpers/cms/mobile_helper.rb +12 -2
  133. data/app/helpers/cms/nav_menu_helper.rb +23 -0
  134. data/app/helpers/cms/page_helper.rb +72 -30
  135. data/app/helpers/cms/path_helper.rb +46 -70
  136. data/app/helpers/cms/rendering_helper.rb +68 -12
  137. data/app/helpers/cms/section_nodes_helper.rb +92 -31
  138. data/app/helpers/cms/sites/authentication_helper.rb +25 -0
  139. data/app/helpers/cms/sites/devise_shim_helper.rb +31 -0
  140. data/app/helpers/cms/template_support.rb +1 -7
  141. data/app/helpers/cms/ui_elements_helper.rb +147 -6
  142. data/app/helpers/forgot_password_portlet_helper.rb +9 -0
  143. data/app/helpers/login_portlet_helper.rb +10 -0
  144. data/app/inputs/attachments_input.rb +14 -0
  145. data/app/inputs/cms_text_area_input.rb +10 -0
  146. data/app/inputs/cms_text_field_input.rb +29 -0
  147. data/app/inputs/date_picker_input.rb +8 -0
  148. data/app/inputs/file_picker_input.rb +75 -0
  149. data/app/inputs/path_input.rb +18 -0
  150. data/app/inputs/tag_list_input.rb +3 -0
  151. data/app/inputs/template_editor_input.rb +24 -0
  152. data/app/inputs/text_editor_input.rb +19 -0
  153. data/app/models/cms/abstract_file_block.rb +10 -6
  154. data/app/models/cms/attachment.rb +20 -27
  155. data/app/models/cms/category.rb +17 -7
  156. data/app/models/cms/category_type.rb +8 -4
  157. data/app/models/cms/connector.rb +32 -20
  158. data/app/models/cms/content.rb +31 -0
  159. data/app/models/cms/content_type.rb +114 -62
  160. data/app/models/cms/dynamic_view.rb +19 -45
  161. data/app/models/cms/email_message.rb +32 -2
  162. data/app/models/cms/external_user.rb +60 -0
  163. data/app/models/cms/file_block.rb +1 -0
  164. data/app/models/cms/form.rb +47 -0
  165. data/app/models/cms/form_entry.rb +71 -0
  166. data/app/models/cms/form_field.rb +78 -0
  167. data/app/models/cms/group.rb +19 -9
  168. data/app/models/cms/group_permission.rb +1 -1
  169. data/app/models/cms/group_section.rb +1 -1
  170. data/app/models/cms/group_type.rb +5 -5
  171. data/app/models/cms/group_type_permission.rb +1 -1
  172. data/app/models/cms/html_block.rb +14 -19
  173. data/app/models/cms/image_block.rb +1 -0
  174. data/app/models/cms/link.rb +8 -6
  175. data/app/models/cms/page.rb +156 -59
  176. data/app/models/cms/page_component.rb +43 -0
  177. data/app/models/cms/page_partial.rb +16 -8
  178. data/app/models/cms/page_route.rb +1 -1
  179. data/app/models/cms/page_route_condition.rb +1 -1
  180. data/app/models/cms/page_route_option.rb +1 -1
  181. data/app/models/cms/page_route_requirement.rb +1 -1
  182. data/app/models/cms/page_template.rb +14 -9
  183. data/app/models/cms/permission.rb +4 -2
  184. data/app/models/cms/persistent_user.rb +208 -0
  185. data/app/models/cms/portlet.rb +56 -9
  186. data/app/models/cms/redirect.rb +1 -1
  187. data/app/models/cms/search_filter.rb +18 -0
  188. data/app/models/cms/section.rb +39 -28
  189. data/app/models/cms/section_node.rb +32 -5
  190. data/app/models/cms/site.rb +3 -3
  191. data/app/models/cms/tag.rb +14 -12
  192. data/app/models/cms/tagging.rb +2 -2
  193. data/app/models/cms/task.rb +14 -21
  194. data/app/models/cms/templates.rb +1 -2
  195. data/app/models/cms/user.rb +21 -160
  196. data/app/models/cms/user_group_membership.rb +2 -2
  197. data/app/portlets/deprecated_placeholder.rb +12 -0
  198. data/app/portlets/dynamic_portlet.rb +1 -1
  199. data/app/portlets/email_page_portlet.rb +10 -3
  200. data/app/portlets/forgot_password_portlet.rb +9 -28
  201. data/app/portlets/login_portlet.rb +8 -5
  202. data/app/portlets/tag_cloud_portlet.rb +3 -1
  203. data/app/presenters/cms/user_presenter.rb +24 -0
  204. data/app/views/cms/application/_add_content_modal.html.erb +3 -0
  205. data/app/views/cms/application/_buttons.html.erb +7 -0
  206. data/app/views/cms/{shared → application}/_exception.html.erb +0 -0
  207. data/app/views/cms/application/_form_errors.html.erb +7 -0
  208. data/app/views/cms/application/_form_with_buttons.html.erb +10 -0
  209. data/app/views/cms/application/_main_content.html.erb +3 -0
  210. data/app/views/cms/application/_main_with_sidebar.html.erb +8 -0
  211. data/app/views/cms/application/_mobile_toolbar.html.erb +16 -0
  212. data/app/views/cms/application/_page_title.html.erb +5 -0
  213. data/app/views/cms/application/_pagination.html.erb +26 -0
  214. data/app/views/cms/application/_row.html.erb +1 -0
  215. data/app/views/cms/application/_save_buttons.html.erb +7 -0
  216. data/app/views/cms/application/_sidebar_layout.html.erb +3 -0
  217. data/app/views/cms/application/_version.html.erb +23 -0
  218. data/app/views/cms/{shared → application}/_version_conflict_diff.html.erb +0 -0
  219. data/app/views/cms/{shared → application}/_version_conflict_error.html.erb +0 -0
  220. data/app/views/cms/attachments/_attachment_manager.html.erb +22 -0
  221. data/app/views/cms/attachments/_no_attachments_defined.html.erb +1 -0
  222. data/app/views/cms/cache/show.html.erb +5 -10
  223. data/app/views/cms/categories/_form.html.erb +15 -24
  224. data/app/views/cms/category_types/_form.html.erb +1 -1
  225. data/app/views/cms/connectors/new.html.erb +33 -64
  226. data/app/views/cms/content/editing_frame.html.erb +1 -0
  227. data/app/views/cms/content/no_page.html.erb +9 -27
  228. data/app/views/cms/content/show.html.erb +14 -15
  229. data/app/views/cms/content_block/_block_form.html.erb +15 -0
  230. data/app/views/cms/content_block/_buttonbar.html.erb +29 -0
  231. data/app/views/cms/content_block/_buttons.html.erb +13 -0
  232. data/app/views/cms/content_block/_hidden_fields.html.erb +13 -0
  233. data/app/views/cms/content_block/_sidebar.html.erb +35 -0
  234. data/app/views/cms/content_block/edit.html.erb +3 -0
  235. data/app/views/cms/content_block/index.html.erb +87 -0
  236. data/app/views/cms/content_block/new.html.erb +3 -0
  237. data/app/views/cms/content_block/render_block_in_main_container.html.erb +10 -0
  238. data/app/views/cms/content_block/show.html.erb +1 -0
  239. data/app/views/cms/content_block/show_in_isolation.html.erb +15 -0
  240. data/app/views/cms/content_block/versions.html.erb +24 -0
  241. data/app/views/cms/dashboard/_page_drafts.html.erb +12 -22
  242. data/app/views/cms/dashboard/_tasks.html.erb +32 -45
  243. data/app/views/cms/dashboard/index.html.erb +11 -13
  244. data/app/views/cms/dynamic_views/_form.html.erb +8 -10
  245. data/app/views/cms/dynamic_views/edit.html.erb +2 -3
  246. data/app/views/cms/dynamic_views/index.html.erb +22 -44
  247. data/app/views/cms/dynamic_views/new.html.erb +2 -3
  248. data/app/views/cms/email_messages/index.html.erb +31 -34
  249. data/app/views/cms/email_messages/show.html.erb +45 -52
  250. data/app/views/cms/file_blocks/_form.html.erb +2 -4
  251. data/app/views/cms/form_entries/_buttons.html.erb +2 -0
  252. data/app/views/cms/form_entries/_form.html.erb +7 -0
  253. data/app/views/cms/form_entries/_internal_form.html.erb +9 -0
  254. data/app/views/cms/form_entries/edit.html.erb +5 -0
  255. data/app/views/cms/form_entries/error.html.erb +3 -0
  256. data/app/views/cms/form_entries/index.html.erb +4 -0
  257. data/app/views/cms/form_entries/new.html.erb +5 -0
  258. data/app/views/cms/form_entries/show.html.erb +13 -0
  259. data/app/views/cms/form_entries/submit.html.erb +1 -0
  260. data/app/views/cms/form_fields/_form.html.erb +8 -0
  261. data/app/views/cms/form_fields/_select.html.erb +3 -0
  262. data/app/views/cms/form_fields/_text_area.html.erb +3 -0
  263. data/app/views/cms/form_fields/_text_field.html.erb +3 -0
  264. data/app/views/cms/form_fields/edit.html.erb +0 -0
  265. data/app/views/cms/form_fields/new.html.erb +26 -0
  266. data/app/views/cms/form_fields/preview.html.erb +16 -0
  267. data/app/views/cms/forms/_form.html.erb +66 -0
  268. data/app/views/cms/forms/render.html.erb +15 -0
  269. data/app/views/cms/forms/show.html.erb +6 -0
  270. data/app/views/cms/groups/_form.html.erb +32 -38
  271. data/app/views/cms/groups/_permissions.html.erb +11 -34
  272. data/app/views/cms/groups/_sections.html.erb +11 -17
  273. data/app/views/cms/groups/edit.html.erb +1 -3
  274. data/app/views/cms/groups/index.html.erb +10 -32
  275. data/app/views/cms/groups/new.html.erb +2 -4
  276. data/app/views/cms/html_blocks/_form.html.erb +2 -2
  277. data/app/views/cms/html_blocks/render.html.erb +1 -1
  278. data/app/views/cms/image_blocks/_form.html.erb +3 -3
  279. data/app/views/cms/links/_form.html.erb +6 -11
  280. data/app/views/cms/links/edit.html.erb +3 -12
  281. data/app/views/cms/links/new.html.erb +4 -13
  282. data/app/views/cms/page_components/_content.html.erb +18 -0
  283. data/app/views/cms/page_components/new.html.erb +12 -0
  284. data/app/views/cms/page_routes/_form.html.erb +11 -10
  285. data/app/views/cms/page_routes/edit.html.erb +2 -3
  286. data/app/views/cms/page_routes/index.html.erb +25 -48
  287. data/app/views/cms/page_routes/new.html.erb +2 -3
  288. data/app/views/cms/pages/_edit_content.html.erb +28 -0
  289. data/app/views/cms/pages/_form.html.erb +20 -37
  290. data/app/views/cms/pages/_main_form.html.erb +23 -0
  291. data/app/views/cms/pages/_simple_container.html.erb +8 -0
  292. data/app/views/cms/pages/edit.html.erb +2 -23
  293. data/app/views/cms/pages/new.html.erb +2 -16
  294. data/app/views/cms/pages/versions.html.erb +18 -87
  295. data/app/views/cms/redirects/_form.html.erb +6 -14
  296. data/app/views/cms/redirects/edit.html.erb +2 -3
  297. data/app/views/cms/redirects/index.html.erb +24 -50
  298. data/app/views/cms/redirects/new.html.erb +2 -3
  299. data/app/views/cms/routes/index.html.erb +15 -20
  300. data/app/views/cms/section_nodes/_children.html.erb +3 -0
  301. data/app/views/cms/section_nodes/_row_buttons.html.erb +11 -0
  302. data/app/views/cms/section_nodes/_section_node.html.erb +24 -10
  303. data/app/views/cms/section_nodes/_sitemap_buttons.html.erb +47 -0
  304. data/app/views/cms/section_nodes/_status.html.erb +5 -0
  305. data/app/views/cms/section_nodes/show.html.erb +9 -0
  306. data/app/views/cms/sections/_buttons.html.erb +6 -0
  307. data/app/views/cms/sections/_form.html.erb +22 -49
  308. data/app/views/cms/sections/edit.html.erb +3 -8
  309. data/app/views/cms/sections/new.html.erb +4 -20
  310. data/app/views/cms/sessions/new.html.erb +16 -31
  311. data/app/views/cms/shared/access_denied.html.erb +1 -2
  312. data/app/views/cms/shared/error.html.erb +5 -5
  313. data/app/views/cms/sites/_flash.html.erb +8 -0
  314. data/app/views/cms/sites/passwords/new.html.erb +2 -0
  315. data/app/views/cms/sites/sessions/new.html.erb +2 -0
  316. data/app/views/cms/tags/_form.html.erb +1 -1
  317. data/app/views/cms/tags/render.html.erb +0 -1
  318. data/app/views/cms/tasks/new.html.erb +18 -32
  319. data/app/views/cms/toolbar/_new_pages_menu.html.erb +10 -0
  320. data/app/views/cms/users/_form.html.erb +8 -11
  321. data/app/views/cms/users/_password.html.erb +2 -8
  322. data/app/views/cms/users/_user_fields.html.erb +7 -20
  323. data/app/views/cms/users/change_password.html.erb +12 -21
  324. data/app/views/cms/users/edit.html.erb +1 -15
  325. data/app/views/cms/users/index.html.erb +61 -58
  326. data/app/views/cms/users/new.html.erb +1 -12
  327. data/app/views/devise/confirmations/new.html.erb +16 -0
  328. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  329. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  330. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  331. data/app/views/devise/passwords/edit.html.erb +19 -0
  332. data/app/views/devise/passwords/new.html.erb +15 -0
  333. data/app/views/devise/registrations/edit.html.erb +28 -0
  334. data/app/views/devise/registrations/new.html.erb +18 -0
  335. data/app/views/devise/shared/_links.erb +25 -0
  336. data/app/views/devise/unlocks/new.html.erb +16 -0
  337. data/app/views/layouts/cms/_content_types.html.erb +13 -0
  338. data/app/views/layouts/cms/_footer.erb +2 -2
  339. data/app/views/layouts/cms/_head.html.erb +8 -18
  340. data/app/views/layouts/cms/_main_menu.html.erb +78 -0
  341. data/app/views/layouts/cms/application.html.erb +19 -24
  342. data/app/views/layouts/cms/content_page.html.erb +5 -0
  343. data/app/views/layouts/cms/page_editor.html.erb +90 -0
  344. data/app/views/portlets/deprecated_placeholders/_form.html.erb +1 -0
  345. data/app/views/portlets/deprecated_placeholders/render.html.erb +8 -0
  346. data/app/views/portlets/dynamic/_form.html.erb +3 -3
  347. data/app/views/portlets/email_page/_form.html.erb +5 -6
  348. data/app/views/portlets/forgot_password/_form.html.erb +2 -3
  349. data/app/views/portlets/forgot_password/render.html.erb +2 -14
  350. data/app/views/portlets/login/_form.html.erb +4 -6
  351. data/app/views/portlets/login/render.html.erb +8 -27
  352. data/app/views/portlets/portlets/_form.html.erb +7 -6
  353. data/app/views/portlets/tag_cloud/_form.html.erb +4 -4
  354. data/app/views/tests/pretend/open_with_layout.html.erb +1 -1
  355. data/bin/bcms +13 -16
  356. data/config/routes.rb +58 -29
  357. data/db/browsercms.seeds.rb +0 -6
  358. data/db/migrate/{20080815014337_browsercms_3_0_0.rb → 20080815014337_browsercms300.rb} +94 -73
  359. data/db/migrate/20130327184912_browsercms400.rb +90 -0
  360. data/db/migrate/20131206214021_devise_create_users.rb +47 -0
  361. data/db/migrate/20131211223908_kill_reset_password.rb +5 -0
  362. data/db/migrate/20131218222005_create_cms_external_users.rb +10 -0
  363. data/doc/features/design_integration.md +45 -0
  364. data/doc/features/external_user.md +7 -0
  365. data/doc/features/form_builder.md +40 -0
  366. data/doc/features/simple_form_refactor.md +60 -0
  367. data/doc/release_notes.md +224 -10
  368. data/lib/acts_as_list.rb +72 -71
  369. data/lib/browsercms.rb +41 -1
  370. data/lib/cms/acts/content_block.rb +12 -2
  371. data/lib/cms/acts/content_page.rb +3 -4
  372. data/lib/cms/admin_tab.rb +15 -0
  373. data/lib/cms/attachments/configuration.rb +1 -1
  374. data/lib/cms/authentication/controller.rb +83 -177
  375. data/lib/cms/authentication/test_password_strategy.rb +19 -0
  376. data/lib/cms/behaviors.rb +1 -0
  377. data/lib/cms/behaviors/archiving.rb +2 -2
  378. data/lib/cms/behaviors/attaching.rb +21 -45
  379. data/lib/cms/behaviors/connecting.rb +14 -4
  380. data/lib/cms/behaviors/dynamic_attributes.rb +3 -3
  381. data/lib/cms/behaviors/hiding.rb +2 -2
  382. data/lib/cms/behaviors/namespacing.rb +6 -36
  383. data/lib/cms/behaviors/publishing.rb +92 -45
  384. data/lib/cms/behaviors/rendering.rb +15 -7
  385. data/lib/cms/behaviors/searching.rb +5 -4
  386. data/lib/cms/behaviors/soft_deleting.rb +13 -16
  387. data/lib/cms/behaviors/taggable.rb +17 -10
  388. data/lib/cms/behaviors/versioning.rb +12 -16
  389. data/lib/cms/commands/to_version400.rb +10 -0
  390. data/lib/cms/concerns.rb +7 -0
  391. data/lib/cms/concerns/can_be_addressable.rb +326 -0
  392. data/lib/cms/concerns/has_content_type.rb +46 -0
  393. data/lib/cms/concerns/ignores_publishing.rb +9 -0
  394. data/lib/cms/configuration.rb +14 -4
  395. data/lib/cms/configuration/configurable_template.rb +24 -0
  396. data/lib/cms/configuration/devise.rb +256 -0
  397. data/lib/cms/configure_simple_form.rb +142 -0
  398. data/lib/cms/configure_simple_form_bootstrap.rb +49 -0
  399. data/lib/cms/content_filter.rb +18 -0
  400. data/lib/cms/content_page.rb +77 -0
  401. data/lib/cms/content_rendering_support.rb +25 -16
  402. data/lib/cms/controllers/admin_controller.rb +78 -0
  403. data/lib/cms/data_loader.rb +30 -11
  404. data/lib/cms/default_accessible.rb +6 -6
  405. data/lib/cms/domain_support.rb +0 -4
  406. data/lib/cms/engine.rb +52 -20
  407. data/lib/cms/engine_helper.rb +41 -51
  408. data/{app/controllers → lib}/cms/error_handling.rb +11 -5
  409. data/lib/cms/extensions.rb +2 -1
  410. data/lib/cms/extensions/active_model/name.rb +13 -0
  411. data/lib/cms/extensions/active_record/connection_adapters/abstract/schema_statements.rb +49 -89
  412. data/lib/cms/extensions/hash.rb +0 -12
  413. data/lib/cms/form_builder/content_block_form_builder.rb +45 -0
  414. data/lib/cms/form_builder/default_input.rb +13 -0
  415. data/lib/cms/form_builder/deprecated_inputs.rb +40 -0
  416. data/lib/cms/form_builder/workflow_buttons.rb +38 -0
  417. data/lib/cms/module.rb +1 -7
  418. data/lib/cms/polymorphic_single_table_inheritance.rb +19 -0
  419. data/lib/cms/publish_workflow.rb +26 -0
  420. data/lib/cms/responders/content_responder.rb +14 -0
  421. data/lib/cms/route_extensions.rb +112 -20
  422. data/lib/cms/version.rb +1 -1
  423. data/lib/generators/browser_cms/demo_site/templates/demo.seeds.rb +0 -2
  424. data/lib/generators/cms/content_block/content_block_generator.rb +19 -46
  425. data/lib/generators/cms/content_block/templates/_form.html.erb +22 -28
  426. data/lib/generators/cms/project/templates/devise.rb.erb +7 -0
  427. metadata +383 -150
  428. data/app/assets/javascripts/cms/sitemap.js.erb +0 -464
  429. data/app/assets/stylesheets/browsercms/application.css +0 -7
  430. data/app/assets/stylesheets/cms/administration.css.erb +0 -91
  431. data/app/assets/stylesheets/cms/application.css.erb +0 -171
  432. data/app/assets/stylesheets/cms/attachment_manager.css.scss +0 -28
  433. data/app/assets/stylesheets/cms/block.css +0 -26
  434. data/app/assets/stylesheets/cms/buttons.css.erb +0 -120
  435. data/app/assets/stylesheets/cms/content_library.css.erb +0 -139
  436. data/app/assets/stylesheets/cms/content_types.css +0 -4
  437. data/app/assets/stylesheets/cms/dashboard.css.erb +0 -118
  438. data/app/assets/stylesheets/cms/data_table.css.erb.erb +0 -156
  439. data/app/assets/stylesheets/cms/date_picker.css.erb +0 -82
  440. data/app/assets/stylesheets/cms/form_layout.css.erb +0 -282
  441. data/app/assets/stylesheets/cms/login.css.erb +0 -78
  442. data/app/assets/stylesheets/cms/menu.css.erb +0 -116
  443. data/app/assets/stylesheets/cms/nav.css.erb +0 -99
  444. data/app/assets/stylesheets/cms/page_toolbar.css.erb +0 -135
  445. data/app/assets/stylesheets/cms/reset.css +0 -46
  446. data/app/assets/stylesheets/cms/selectbox.css.erb +0 -56
  447. data/app/assets/stylesheets/cms/sitemap.css.erb +0 -390
  448. data/app/assets/stylesheets/cms/taglist.css +0 -18
  449. data/app/controllers/application_controller.rb +0 -14
  450. data/app/controllers/cms/content_types_controller.rb +0 -9
  451. data/app/helpers/application_helper.rb +0 -5
  452. data/app/helpers/cms/form_builder.rb +0 -241
  453. data/app/models/cms/content_type_group.rb +0 -15
  454. data/app/models/cms/forgot_password_mailer.rb +0 -14
  455. data/app/portlets/reset_password_portlet.rb +0 -28
  456. data/app/views/cms/blocks/_hidden_fields.html.erb +0 -10
  457. data/app/views/cms/blocks/_toolbar.html.erb +0 -9
  458. data/app/views/cms/blocks/_toolbar_for_collection.html.erb +0 -23
  459. data/app/views/cms/blocks/_toolbar_for_member.html.erb +0 -36
  460. data/app/views/cms/blocks/edit.html.erb +0 -28
  461. data/app/views/cms/blocks/index.html.erb +0 -86
  462. data/app/views/cms/blocks/new.html.erb +0 -19
  463. data/app/views/cms/blocks/show.html.erb +0 -43
  464. data/app/views/cms/blocks/usages.html.erb +0 -44
  465. data/app/views/cms/blocks/versions.html.erb +0 -90
  466. data/app/views/cms/content_types/index.html.erb +0 -14
  467. data/app/views/cms/form_builder/_cms_attachment_manager.html.erb +0 -27
  468. data/app/views/cms/form_builder/_cms_check_box.html.erb +0 -7
  469. data/app/views/cms/form_builder/_cms_date_picker.html.erb +0 -12
  470. data/app/views/cms/form_builder/_cms_datetime_select.html.erb +0 -12
  471. data/app/views/cms/form_builder/_cms_drop_down.html.erb +0 -12
  472. data/app/views/cms/form_builder/_cms_fancy_drop_down.html.erb +0 -9
  473. data/app/views/cms/form_builder/_cms_file_field.html.erb +0 -28
  474. data/app/views/cms/form_builder/_cms_instructions.html.erb +0 -4
  475. data/app/views/cms/form_builder/_cms_tag_list.html.erb +0 -15
  476. data/app/views/cms/form_builder/_cms_template_editor.html.erb +0 -9
  477. data/app/views/cms/form_builder/_cms_text_area.html.erb +0 -10
  478. data/app/views/cms/form_builder/_cms_text_editor.html.erb +0 -19
  479. data/app/views/cms/form_builder/_cms_text_field.html.erb +0 -12
  480. data/app/views/cms/links/destroy.js.rjs +0 -2
  481. data/app/views/cms/page_routes/show.html.erb +0 -10
  482. data/app/views/cms/pages/_edit_connector.html.erb +0 -19
  483. data/app/views/cms/pages/_edit_container.html.erb +0 -11
  484. data/app/views/cms/section_nodes/_link.html.erb +0 -14
  485. data/app/views/cms/section_nodes/_node.html.erb +0 -44
  486. data/app/views/cms/section_nodes/_page.html.erb +0 -20
  487. data/app/views/cms/section_nodes/_section.html.erb +0 -28
  488. data/app/views/cms/section_nodes/index.html.erb +0 -43
  489. data/app/views/cms/sections/_page.html.erb +0 -4
  490. data/app/views/cms/sections/_section.html.erb +0 -8
  491. data/app/views/cms/sections/destroy.js.rjs +0 -2
  492. data/app/views/cms/sections/index.html.erb +0 -23
  493. data/app/views/cms/shared/_admin_sidebar.html.erb +0 -36
  494. data/app/views/cms/shared/_pagination.html.erb +0 -31
  495. data/app/views/cms/toolbar/_mobile_toggle.html.erb +0 -33
  496. data/app/views/cms/toolbar/index.html.erb +0 -1
  497. data/app/views/cms/users/_groups.html.erb +0 -12
  498. data/app/views/cms/users/_toolbar.html.erb +0 -24
  499. data/app/views/cms/users/show.html.erb +0 -50
  500. data/app/views/layouts/_cms_toolbar.html.erb +0 -54
  501. data/app/views/layouts/_page_toolbar.html.erb +0 -119
  502. data/app/views/layouts/cms/administration.html.erb +0 -51
  503. data/app/views/layouts/cms/content_library.html.erb +0 -96
  504. data/app/views/layouts/cms/dashboard.html.erb +0 -16
  505. data/app/views/layouts/cms/login.html.erb +0 -31
  506. data/app/views/layouts/cms/section_nodes.html.erb +0 -20
  507. data/app/views/layouts/cms/toolbar.html.erb +0 -23
  508. data/app/views/portlets/reset_password/_form.html.erb +0 -3
  509. data/app/views/portlets/reset_password/render.html.erb +0 -22
  510. data/bin/bcms-upgrade +0 -332
  511. data/db/migrate/20091109175123_browsercms_3_0_5.rb +0 -9
  512. data/db/migrate/20100117144038_browsercms314.rb +0 -20
  513. data/db/migrate/20100117144039_browsercms315.rb +0 -95
  514. data/db/migrate/20100705083859_browsercms_3_3_0.rb +0 -56
  515. data/db/migrate/20111130221145_browsercms340.rb +0 -56
  516. data/db/migrate/20120329144406_browsercms350.rb +0 -32
  517. data/db/migrate/20120717182827_browsercms353.rb +0 -19
  518. data/db/migrate/20120813180110_browsercms354.rb +0 -9
  519. data/lib/cms/addressable.rb +0 -93
  520. data/lib/cms/authentication/model.rb +0 -116
  521. data/lib/cms/behaviors/pagination.rb +0 -212
  522. data/lib/cms/upgrades/v3_4_0.rb +0 -31
  523. data/lib/cms/upgrades/v3_5_0.rb +0 -227
@@ -2,6 +2,7 @@ module Cms
2
2
  class FileBlock < Cms::AbstractFileBlock
3
3
 
4
4
  acts_as_content_block :taggable => true
5
+ content_module :core
5
6
 
6
7
  has_attachment :file
7
8
  validates_attachment_presence :file, :message => "You must upload a file"
@@ -0,0 +1,47 @@
1
+ module Cms
2
+ class Form < ActiveRecord::Base
3
+ acts_as_content_block
4
+ content_module :forms
5
+ is_addressable path: '/forms', template: 'default'
6
+
7
+ has_many :fields, -> {order(:position)}, class_name: 'Cms::FormField'
8
+ has_many :entries, class_name: 'Cms::FormEntry'
9
+
10
+ validates_format_of :notification_email, :with => /@/, unless: lambda { |form| form.notification_email.blank? }
11
+
12
+ # Copy any field related errors into the model :base so they get displayed at the top of the form.
13
+ after_validation do
14
+ unless errors[:fields].empty?
15
+ fields.each do |field|
16
+ field.errors.each do |attribute, error|
17
+ errors[:base] << field.errors.full_message(attribute, error)
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+
24
+ def field(name)
25
+ fields.select {|f| f.name == name}.first
26
+ end
27
+
28
+ def required?(name)
29
+ field = field(name)
30
+ field ? field.required? : false
31
+ end
32
+
33
+ def field_names
34
+ fields.collect { |f| f.name }
35
+ end
36
+
37
+ def show_text?
38
+ confirmation_behavior.to_sym == :show_text
39
+ end
40
+
41
+ # Provides a sample Entry for the form.
42
+ # This allows us to use SimpleForm to layout out elements but ignore the input when the form submits.
43
+ def new_entry
44
+ Cms::Entry.new(form: self)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,71 @@
1
+ module Cms
2
+ class FormEntry < ActiveRecord::Base
3
+
4
+ store :data_columns
5
+ belongs_to :form, class_name: 'Cms::Form'
6
+
7
+ after_initialize :add_field_accessors
8
+
9
+ def permitted_params
10
+ form.field_names
11
+ end
12
+
13
+ # Returns a copy of the persisted object. This is required so that existing records fetched from the db can
14
+ # have validation during update operations.
15
+ #
16
+ # @return [Cms::FormEntry] A copy of this record with validations enabled on it.
17
+ def enable_validations
18
+ entry = FormEntry.for(form)
19
+ entry.attributes = self.attributes
20
+ entry.instance_variable_set(:@new_record, false)
21
+ entry
22
+ end
23
+
24
+ class << self
25
+
26
+ # Create an Entry for a specific Form. It will have validation and accessors based on the fields of the form.
27
+ #
28
+ # @param [Cms::Form] form
29
+ def for(form)
30
+ entry = FormEntry.ish(form: form) {
31
+ form.field_names.each do |field_name|
32
+ if form.required?(field_name)
33
+ validates field_name, presence: true
34
+ end
35
+ end
36
+ }
37
+ entry
38
+ end
39
+
40
+ # Create an instance of a FormEntry with the given methods.
41
+ def ish(*args, &block)
42
+ dup(&block).new(*args)
43
+ end
44
+
45
+ # Creates a faux class with singleton methods. Solves this problem:
46
+ # https://github.com/rails/rails/issues/5449
47
+ def dup(&block)
48
+ super.tap do |dup|
49
+ def dup.name()
50
+ FormEntry.name
51
+ end
52
+
53
+ dup.class_eval(&block) if block
54
+ end
55
+ end
56
+ end
57
+ private
58
+
59
+ # Add a single field accessor to the current instance of the object. (I.e. not shared with others)
60
+ def add_store_accessor(field_name)
61
+ singleton_class.class_eval { store_accessor :data_columns, field_name }
62
+ end
63
+
64
+ def add_field_accessors
65
+ return unless form
66
+ form.field_names.each do |field_name|
67
+ add_store_accessor(field_name)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,78 @@
1
+ module Cms
2
+ class FormField < ActiveRecord::Base
3
+ extend DefaultAccessible
4
+
5
+ belongs_to :form
6
+ acts_as_list scope: :form
7
+
8
+ attr_accessor :edit_path, :delete_path
9
+
10
+ # Name is assigned when the Field is created, and should not be changed afterwords.
11
+ # Otherwise existing entries will not display their data correctly.
12
+ #
13
+ # FormField#name is used for input fields. I.e. <%= f.input field.name %>
14
+ before_validation(on: :create) do
15
+ self.name = label.parameterize.underscore.to_sym if label
16
+ end
17
+
18
+ validates :name, :uniqueness => {:scope => :form_id, message: "can only be used once per form."}
19
+
20
+ def as_json(options={})
21
+ super(:methods => [:edit_path, :delete_path])
22
+ end
23
+
24
+
25
+ # Return the form widget that should be used to render this field.
26
+ #
27
+ # @return [Symbol] A SimpleForm input mapping (i.e. :string, :text)
28
+ def as
29
+ case field_type
30
+ when "text_field"
31
+ :string
32
+ when "text_area"
33
+ :text
34
+ else
35
+ field_type.to_sym
36
+ end
37
+ end
38
+
39
+ # Return options to be passed to a SimpleForm input.
40
+ # @return [Hash]
41
+ # @param [Hash] config
42
+ # @option config [Boolean] :disabled If the field should be disabled.
43
+ # @option config [FormEntry] :entry
44
+ def options(config={})
45
+ opts = {label: label}
46
+ if field_type != "text_field"
47
+ opts[:as] = self.as
48
+ end
49
+ if config[:disabled]
50
+ opts[:disabled] = true
51
+ opts[:readonly] = 'readonly'
52
+ end
53
+ opts[:required] = !!required
54
+ opts[:hint] = instructions if instructions
55
+ unless choices.blank?
56
+ opts[:collection] = parse_choices
57
+ opts[:prompt] = !self.required?
58
+ end
59
+ unless config[:entry] && config[:entry].send(name)
60
+ opts[:input_html] = {value: default_value}
61
+ end
62
+ opts
63
+ end
64
+
65
+
66
+ # Don't allow name to be set via UI.
67
+ def self.permitted_params
68
+ super - [:name]
69
+ end
70
+
71
+ private
72
+
73
+ # Choices is a single text area where choices are divided by endlines.
74
+ def parse_choices
75
+ choices.split( /\r?\n/ )
76
+ end
77
+ end
78
+ end
@@ -3,10 +3,10 @@
3
3
  # their permissions from all groups combined represents what they can do.
4
4
  #
5
5
  class Cms::Group < ActiveRecord::Base
6
- GUEST_CODE = "guest"
6
+ GUEST_CODE = "guest"
7
7
 
8
8
  has_many :user_group_memberships, :class_name => 'Cms::UserGroupMembership'
9
- has_many :users, :through => :user_group_memberships, :class_name => 'Cms::User'
9
+ has_many :users, :through => :user_group_memberships, :class_name => 'Cms::PersistentUser'
10
10
 
11
11
  has_many :group_permissions, :class_name => 'Cms::GroupPermission'
12
12
  has_many :permissions, :through => :group_permissions, :class_name => 'Cms::Permission'
@@ -16,18 +16,28 @@ class Cms::Group < ActiveRecord::Base
16
16
 
17
17
  belongs_to :group_type, :class_name => 'Cms::GroupType'
18
18
 
19
- # :group_type might be a bad idea, but only Admins should be modifying groups anyway
20
- attr_accessible :name, :code, :group_type, :permission_ids, :section_ids
21
- include Cms::DefaultAccessible
19
+ extend Cms::DefaultAccessible
20
+
21
+ # @override Add extra params
22
+ def self.permitted_params
23
+ super + [:group_type_id] +[section_ids: [], permission_ids: []]
24
+ end
25
+
22
26
 
23
27
  validates_presence_of :name
24
28
 
25
- scope :named, lambda { |n| {:conditions => {:name => n}} }
26
- scope :with_code, lambda { |c| {:conditions => {:code => c}} }
29
+ class << self
30
+ def named(n)
31
+ where name: n
32
+ end
27
33
 
34
+ def with_code(c)
35
+ where code: c
36
+ end
37
+ end
28
38
 
29
- scope :public, :include => :group_type, :conditions => ["#{Cms::GroupType.table_name}.cms_access = ?", false]
30
- scope :cms_access, :include => :group_type, :conditions => ["#{Cms::GroupType.table_name}.cms_access = ?", true]
39
+ scope :public, -> { where(["#{Cms::GroupType.table_name}.cms_access = ?", false]).includes(:group_type).references(:group_type) }
40
+ scope :cms_access, -> { where(["#{Cms::GroupType.table_name}.cms_access = ?", true]).includes(:group_type).references(:group_type) }
31
41
 
32
42
  def guest?
33
43
  group_type && group_type.guest?
@@ -1,7 +1,7 @@
1
1
  module Cms
2
2
  class GroupPermission < ActiveRecord::Base
3
3
 
4
- include DefaultAccessible
4
+ extend DefaultAccessible
5
5
 
6
6
  belongs_to :group, :class_name => 'Cms::Group'
7
7
  belongs_to :permission, :class_name => 'Cms::Permission'
@@ -1,7 +1,7 @@
1
1
  module Cms
2
2
  class GroupSection < ActiveRecord::Base
3
3
 
4
- include DefaultAccessible
4
+ extend DefaultAccessible
5
5
 
6
6
  belongs_to :group, :class_name => 'Cms::Group'
7
7
  belongs_to :section, :class_name => 'Cms::Section'
@@ -1,16 +1,16 @@
1
1
  module Cms
2
2
  class GroupType < ActiveRecord::Base
3
- attr_accessible :name, :guest, :cms_access
3
+ #attr_accessible :name, :guest, :cms_access
4
4
 
5
5
  has_many :groups, :class_name => 'Cms::Group'
6
6
  has_many :group_type_permissions, :class_name => 'Cms::GroupTypePermission'
7
7
  has_many :permissions, :through => :group_type_permissions, :class_name => 'Cms::Permission'
8
8
 
9
- scope :guest, :conditions => ["#{GroupType.table_name}.guest = ?", true]
10
- scope :non_guest, :conditions => ["#{GroupType.table_name}.guest = ?", false]
9
+ scope :guest, -> {where( ["#{GroupType.table_name}.guest = ?", true])}
10
+ scope :non_guest, -> {where( ["#{GroupType.table_name}.guest = ?", false])}
11
11
 
12
- scope :cms_access, :conditions => ["#{GroupType.table_name}.cms_access = ?", true]
13
- scope :non_cms_access, :conditions => ["#{GroupType.table_name}.cms_access = ?", false]
12
+ scope :cms_access, -> {where( ["#{GroupType.table_name}.cms_access = ?", true])}
13
+ scope :non_cms_access, -> {where( ["#{GroupType.table_name}.cms_access = ?", false])}
14
14
 
15
15
  end
16
16
  end
@@ -3,6 +3,6 @@ module Cms
3
3
  belongs_to :group_type, :class_name => 'Cms::GroupType'
4
4
  belongs_to :permission, :class_name => 'Cms::Permission'
5
5
 
6
- include DefaultAccessible
6
+ extend DefaultAccessible
7
7
  end
8
8
  end
@@ -2,34 +2,29 @@ module Cms
2
2
  class HtmlBlock < ActiveRecord::Base
3
3
 
4
4
  acts_as_content_block :taggable => true
5
+ content_module :core
5
6
 
6
7
  # This shouldn't be necessary but it is for browsercms.seeds.rb'
7
- attr_accessible :name, :content
8
+ #attr_accessible :name, :content
8
9
 
9
10
  validates_presence_of :name
10
11
 
12
+ def self.eager_matching(term)
13
+ "%#{term}%"
14
+ end
11
15
  # Override of search scope from searching behavior to deal with include_body
12
- scope :search, lambda { |search_params|
16
+ def self.search(search_params)
13
17
  term = search_params.is_a?(Hash) ? search_params[:term] : search_params
14
18
  include_body = search_params.is_a?(Hash) ? search_params[:include_body] : false
15
- conditions = []
16
- columns = ["name"]
17
- columns << "content" if include_body
18
- unless term.blank?
19
- columns.each do |c|
20
- if conditions.empty?
21
- conditions = ["lower(#{table_name}.#{c}) like lower(?)"]
22
- else
23
- conditions.first << "or lower(#{table_name}.#{c}) like (?)"
24
- end
25
- conditions << "%#{term}%"
26
- end
27
- conditions[0] = "(#{conditions[0]})"
19
+
20
+
21
+ conditions = ["name like lower(?)", eager_matching(term)]
22
+ if include_body
23
+ conditions[0] << "OR content like lower(?)"
24
+ conditions << eager_matching(term)
28
25
  end
29
- scope = {}
30
- scope[:conditions] = conditions if conditions
31
- scope
32
- }
26
+ where(conditions)
27
+ end
33
28
 
34
29
  def self.display_name
35
30
  "Text"
@@ -2,6 +2,7 @@ module Cms
2
2
  class ImageBlock < Cms::AbstractFileBlock
3
3
 
4
4
  acts_as_content_block :taggable => true
5
+ content_module :core
5
6
  has_attachment :file, :styles => {:thumb => "80x80"}
6
7
  validates_attachment_presence :file, :message => "You must upload a file"
7
8
 
@@ -1,18 +1,20 @@
1
1
  class Cms::Link < ActiveRecord::Base
2
- acts_as_content_block :connectable => false
2
+ acts_as_content_block connectable: false, content_module: false
3
3
 
4
- scope :named, lambda{|name| {:conditions => ["#{table_name}.name = ?", name]}}
5
-
6
- has_one :section_node, :as => :node, :dependent => :destroy, :inverse_of => :node, :class_name => 'Cms::SectionNode'
4
+ scope :named, lambda { |name| {:conditions => ["#{table_name}.name = ?", name]} }
7
5
 
8
6
  validates_presence_of :name
9
7
 
10
- include Cms::Addressable
11
- include Cms::Addressable::DeprecatedPageAccessors
8
+ is_addressable
9
+ include Cms::Concerns::Addressable::DeprecatedPageAccessors
12
10
 
13
11
  #needed by menu_helper
14
12
  def path
15
13
  url
16
14
  end
17
15
 
16
+ # @override
17
+ def self.permitted_params
18
+ super + [:publish_on_save]
19
+ end
18
20
  end
@@ -12,45 +12,55 @@ class Cms::Page < ActiveRecord::Base
12
12
  is_userstamped
13
13
  is_versioned
14
14
 
15
- has_many :connectors, :class_name => 'Cms::Connector', :order => "#{Cms::Connector.table_name}.container, #{Cms::Connector.table_name}.position"
15
+ has_many :connectors, -> { order("#{Cms::Connector.table_name}.container, #{Cms::Connector.table_name}.position") }, :class_name => 'Cms::Connector'
16
16
  has_many :page_routes, :class_name => 'Cms::PageRoute'
17
17
  has_many :tasks
18
18
 
19
- include Cms::DefaultAccessible
20
- attr_accessible :name, :path, :template_file_name, :hidden, :cacheable # Needs to be explicit so seed data will work.
21
-
22
- scope :named, lambda { |name| {:conditions => ["#{table_name}.name = ?", name]} }
23
- scope :with_path, lambda { |path| {:conditions => ["#{table_name}.path = ?", path]} }
24
-
25
- # This scope will accept a connectable object or a Hash. The Hash is expect to have
26
- # a value for the key :connectable, which is the connectable object, and possibly
27
- # a value for the key :version. The Hash contains a versioned connectable object,
28
- # it will use the value in :version if present, otherwise it will use the version
29
- # of the object. In either case of a connectable object or a Hash, if the object
30
- # is not versioned, no version will be used
31
- scope :connected_to, lambda { |b|
32
- if b.is_a?(Hash)
33
- obj = b[:connectable]
34
- if obj.class.versioned?
35
- ver = b[:version] ? b[:version] : obj.version
19
+ extend Cms::DefaultAccessible
20
+
21
+ class << self
22
+ def named(name)
23
+ where(["#{table_name}.name = ?", name])
24
+ end
25
+
26
+ def with_path(path)
27
+ where(["#{table_name}.path = ?", path])
28
+ end
29
+
30
+ # This scope will accept a connectable object or a Hash. The Hash is expect to have
31
+ # a value for the key :connectable, which is the connectable object, and possibly
32
+ # a value for the key :version. The Hash contains a versioned connectable object,
33
+ # it will use the value in :version if present, otherwise it will use the version
34
+ # of the object. In either case of a connectable object or a Hash, if the object
35
+ # is not versioned, no version will be used
36
+ def connected_to(b)
37
+ if b.is_a?(Hash)
38
+ obj = b[:connectable]
39
+ if obj.class.versioned?
40
+ ver = b[:version] ? b[:version] : obj.version
41
+ else
42
+ ver = nil
43
+ end
36
44
  else
37
- ver = nil
45
+ obj = b
46
+ ver = obj.class.versioned? ? obj.version : nil
38
47
  end
39
- else
40
- obj = b
41
- ver = obj.class.versioned? ? obj.version : nil
42
- end
43
48
 
44
- if ver
45
- {:include => :connectors,
46
- :conditions => ["#{Cms::Connector.table_name}.connectable_id = ? and #{Cms::Connector.table_name}.connectable_type = ? and #{Cms::Connector.table_name}.connectable_version = ?", obj.id, obj.class.base_class.name, ver]}
47
- else
48
- {:include => :connectors,
49
- :conditions => ["#{Cms::Connector.table_name}.connectable_id = ? and #{Cms::Connector.table_name}.connectable_type = ?", obj.id, obj.class.base_class.name]}
49
+ if ver
50
+ query = where(["#{Cms::Connector.table_name}.connectable_id = ? and #{Cms::Connector.table_name}.connectable_type = ? and #{Cms::Connector.table_name}.connectable_version = ?", obj.id, obj.class.base_class.name, ver])
51
+ else
52
+ query = where(["#{Cms::Connector.table_name}.connectable_id = ? and #{Cms::Connector.table_name}.connectable_type = ?", obj.id, obj.class.base_class.name])
53
+ end
54
+ query.includes(:connectors).references(:connectors)
55
+
50
56
  end
51
- }
52
57
 
53
- # currently_connected_to tightens the scope of connected_to by restricting to the
58
+ # @override
59
+ def permitted_params
60
+ super + [:visibility, :publish_on_save]
61
+ end
62
+ end
63
+ # currently_connected_to tightens the scope of connected_to by restricting to the
54
64
  # results to matches on current versions of pages only. This renders obj versions
55
65
  # useless, as the older objects will very likely have older versions of pages and
56
66
  # thus return no results.
@@ -59,19 +69,14 @@ class Cms::Page < ActiveRecord::Base
59
69
 
60
70
  ver = obj.class.versioned? ? obj.version : nil
61
71
  if ver
62
- {:include => :connectors,
63
- :conditions => ["#{connectors_table}.connectable_id = ? and #{connectors_table}.connectable_type = ? and #{connectors_table}.connectable_version = ? and #{connectors_table}.page_version = #{Cms::Page.table_name}.version", obj.id, obj.class.base_class.name, ver]}
72
+ where(["#{connectors_table}.connectable_id = ? and #{connectors_table}.connectable_type = ? and #{connectors_table}.connectable_version = ? and #{connectors_table}.page_version = #{Cms::Page.table_name}.version", obj.id, obj.class.base_class.name, ver]).includes(:connectors).references(:connectors)
64
73
  else
65
- {:include => :connectors,
66
- :conditions => ["#{connectors_table}.connectable_id = ? and #{connectors_table}.connectable_type = ? and #{connectors_table}.page_version = #{Cms::Page.table_name}.version", obj.id, obj.class.base_class.name]}
74
+ where(["#{connectors_table}.connectable_id = ? and #{connectors_table}.connectable_type = ? and #{connectors_table}.page_version = #{Cms::Page.table_name}.version", obj.id, obj.class.base_class.name]).includes(:connectors).references(:connectors)
67
75
  end
68
76
  }
69
77
 
70
- has_one :section_node, :as => :node, :dependent => :destroy, :inverse_of => :node, :class_name => 'Cms::SectionNode'
71
-
72
-
73
- include Cms::Addressable
74
- include Cms::Addressable::DeprecatedPageAccessors
78
+ is_addressable(no_dynamic_path: true)
79
+ include Cms::Concerns::Addressable::DeprecatedPageAccessors
75
80
 
76
81
 
77
82
  before_validation :append_leading_slash_to_path, :remove_trailing_slash_from_path
@@ -80,9 +85,62 @@ class Cms::Page < ActiveRecord::Base
80
85
  validates_presence_of :name, :path
81
86
 
82
87
  # Paths must be unique among undeleted records
83
- validates_uniqueness_of :path, :scope=>:deleted
88
+ validates_uniqueness_of :path, :scope => :deleted
84
89
  validate :path_not_reserved
85
90
 
91
+ # Find the latest draft of a given page.
92
+ #
93
+ # @param [Integer | String] id_or_path The id or path of the page
94
+ # @return [Cms::Page::Version] The version of the page as of the current Draft.
95
+ # @raises [Cms::Errors::ContentNotFound] if no record could be found.
96
+ def self.find_draft(id_or_path)
97
+ if id_or_path.is_a? String
98
+ current = self.with_path(id_or_path).first
99
+ else
100
+ current = self.find(id_or_path)
101
+ end
102
+ if current
103
+ current.as_of_draft_version
104
+ else
105
+ raise Cms::Errors::DraftNotFound
106
+ end
107
+ end
108
+
109
+ # Finds the live version of a Page.
110
+ # @param [String] path The relative path to the page
111
+ # @return [Cms::Page] The page if found
112
+ # @rais [Cms::Errors::ContentNotFound] If no published page was found with the given path.
113
+ def self.find_live(path)
114
+ result = find_live_by_path(path)
115
+ unless result
116
+ raise Cms::Errors::ContentNotFound
117
+ end
118
+ result
119
+ end
120
+
121
+ # Find live version of a page.
122
+ # @return [Cms::Page] Or nil if not found.
123
+ def self.find_live_by_path(path)
124
+ published.not_archived.where(path: path).first
125
+ end
126
+
127
+ # Returns all content for the current page, excluding any deleted ones.
128
+ # @return [Array<ContentBlock>]
129
+ def contents
130
+ current_connectors.map(&:connectable_with_deleted)
131
+ end
132
+
133
+ # Return a list of all connectors for the current version of the page.
134
+ # @param [Symbol] container The name of the container to match (Optional - Return all)
135
+ def current_connectors(container=nil)
136
+ @current_connectors ||= self.connectors.for_page_version(self.version)
137
+ if (container)
138
+ @current_connectors.select { |c| c.container.to_sym == container }
139
+ else
140
+ @current_connectors
141
+ end
142
+ end
143
+
86
144
  # Implements Versioning Callback.
87
145
  def after_build_new_version(new_version)
88
146
  copy_connectors(
@@ -96,7 +154,7 @@ class Cms::Page < ActiveRecord::Base
96
154
  # Publish all
97
155
  def after_publish
98
156
  self.reload # Get's the correct version number loaded
99
- self.connectors.for_page_version(self.version).all(:order => "position").each do |c|
157
+ self.connectors.for_page_version(self.version).order("position").to_a.each do |c|
100
158
  if c.connectable_type.constantize.publishable? && con = c.connectable
101
159
  con.publish
102
160
  end
@@ -108,7 +166,7 @@ class Cms::Page < ActiveRecord::Base
108
166
  def copy_connectors(options={})
109
167
  logger.debug { "Copying connectors from Page #{id} v#{options[:from_version_number]} to v#{options[:to_version_number]}." }
110
168
 
111
- c_found = connectors.for_page_version(options[:from_version_number]).all(:order => "#{Cms::Connector.table_name}.container, #{Cms::Connector.table_name}.position")
169
+ c_found = connectors.for_page_version(options[:from_version_number]).order("#{Cms::Connector.table_name}.container, #{Cms::Connector.table_name}.position").to_a
112
170
  logger.debug { "Found connectors #{c_found}" }
113
171
  c_found.each do |c|
114
172
 
@@ -134,11 +192,11 @@ class Cms::Page < ActiveRecord::Base
134
192
  logger.debug "When copying block #{connectable.inspect} version is '#{version}'"
135
193
 
136
194
  new_connector = connectors.create(
137
- :page_version => options[:to_version_number],
138
- :connectable => connectable,
139
- :connectable_version => version,
140
- :container => c.container,
141
- :position => c.position
195
+ :page_version => options[:to_version_number],
196
+ :connectable => connectable,
197
+ :connectable_version => version,
198
+ :container => c.container,
199
+ :position => c.position
142
200
  )
143
201
  logger.debug { "Built new connector #{new_connector}." }
144
202
  end
@@ -147,18 +205,21 @@ class Cms::Page < ActiveRecord::Base
147
205
  end
148
206
 
149
207
  # Adds a Content block to this page.
208
+ #
150
209
  # @param [ContentBlock] connectable The content block to be added
151
210
  # @param [Symbol] container The container to add it in (default :main)
152
211
  def add_content(connectable, container=:main)
153
212
  transaction do
154
213
  raise "Connectable is nil" unless connectable
155
214
  raise "Container is required" if container.blank?
215
+ #should_publish = published? &&
216
+ # connectable.connected_page &&
217
+ # (connectable.class.publishable? ? connectable.published? : true)
218
+ should_publish = false
156
219
  update_attributes(
157
220
  :version_comment => "#{connectable} was added to the '#{container}' container",
158
- :publish_on_save => (
159
- published? &&
160
- connectable.connected_page &&
161
- (connectable.class.publishable? ? connectable.published? : true)))
221
+ :publish_on_save => should_publish
222
+ )
162
223
  connectors.create(
163
224
  :page_version => draft.version,
164
225
  :connectable => connectable,
@@ -167,14 +228,16 @@ class Cms::Page < ActiveRecord::Base
167
228
  end
168
229
  end
169
230
 
231
+ # @deprecated
170
232
  alias_method :create_connector, :add_content
171
233
 
234
+ # Moves a specific connector up or down within its container for a page.
172
235
  def move_connector(connector, direction)
173
236
  transaction do
174
237
  raise "Connector is nil" unless connector
175
238
  raise "Direction is nil" unless direction
176
239
  orientation = direction[/_/] ? "#{direction.sub('_', ' the ')} of" : "#{direction} within"
177
- update_attributes(:version_comment => "#{connector.connectable} was moved #{orientation} the '#{connector.container}' container")
240
+ update_attributes(:version_comment => "#{connector.connectable} was moved #{orientation} the '#{connector.container}' container", :publish_on_save => false)
178
241
  connectors.for_page_version(draft.version).like(connector).first.send("move_#{direction}")
179
242
  end
180
243
  end
@@ -188,7 +251,7 @@ class Cms::Page < ActiveRecord::Base
188
251
  def remove_connector(connector)
189
252
  transaction do
190
253
  raise "Connector is nil" unless connector
191
- update_attributes(:version_comment => "#{connector.connectable} was removed from the '#{connector.container}' container")
254
+ update_attributes(version_comment: "#{connector.connectable} was removed from the '#{connector.container}' container", publish_on_save: false)
192
255
 
193
256
  #The logic of this is to go ahead and let the container get copied forward, then delete the new connector
194
257
  if new_connector = connectors.for_page_version(draft.version).like(connector).first
@@ -201,7 +264,7 @@ class Cms::Page < ActiveRecord::Base
201
264
 
202
265
  # Pages that get deleted should be 'disconnected' from any blocks they were associated with.
203
266
  def delete_connectors
204
- connectors.for_page_version(version).all.each { |c| c.destroy }
267
+ connectors.for_page_version(version).to_a.each { |c| c.destroy }
205
268
  end
206
269
 
207
270
  #This is done to let copy_connectors know which version to pull from
@@ -216,6 +279,14 @@ class Cms::Page < ActiveRecord::Base
216
279
  "NA"
217
280
  end
218
281
 
282
+ # Whether or not this page is considered the 'landing' page for its parent section. These 'Overview' pages
283
+ # will have the same path as their parent.
284
+ #
285
+ # @return [Boolean]
286
+ def landing_page?
287
+ parent.path == path
288
+ end
289
+
219
290
  def public?
220
291
  section ? section.public? : false
221
292
  end
@@ -298,15 +369,16 @@ class Cms::Page < ActiveRecord::Base
298
369
  connectors.for_page_version(version).in_container(container.to_s).count
299
370
  end
300
371
 
301
- def self.find_live_by_path(path)
302
- published.not_archived.first(:conditions => {:path => path})
303
- end
304
-
305
372
  def name_with_section_path
306
373
  a = ancestors
307
374
  (a[1..a.size].map { |a| a.name } + [name]).join(" / ")
308
375
  end
309
376
 
377
+ # @return [Boolean] true if this page is the home page of the site.
378
+ def home?
379
+ path == "/"
380
+ end
381
+
310
382
  # This will return the "top level section" for this page, which is the section directly
311
383
  # below the root (a.k.a My Site) that this page is in. If this page is in root,
312
384
  # then this will return root.
@@ -331,4 +403,29 @@ class Cms::Page < ActiveRecord::Base
331
403
  assigned_to == user
332
404
  end
333
405
 
406
+ # Return a collection of the available visibility statuses this model will accept via #visibility=
407
+ def visibilities
408
+ [['Public', :public], ['Archived', :archived], ['Hidden' , :hidden]]
409
+ end
410
+
411
+ def visibility
412
+ if archived?
413
+ :archived
414
+ elsif hidden?
415
+ :hidden
416
+ else
417
+ :public
418
+ end
419
+ end
420
+
421
+ def visibility=(new_state)
422
+ self.archived = false
423
+ self.hidden = false
424
+ if new_state.to_sym == :archived
425
+ self.archived = true
426
+ elsif new_state.to_sym == :hidden
427
+ self.hidden = true
428
+ end
429
+ end
430
+
334
431
  end