forest_cms 0.98.1

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 (411) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +204 -0
  4. data/Rakefile +37 -0
  5. data/app/assets/config/forest_manifest.js +2 -0
  6. data/app/assets/fonts/FontAwesome.otf +0 -0
  7. data/app/assets/fonts/fontawesome-webfont.eot +0 -0
  8. data/app/assets/fonts/fontawesome-webfont.svg +2671 -0
  9. data/app/assets/fonts/fontawesome-webfont.ttf +0 -0
  10. data/app/assets/fonts/fontawesome-webfont.woff +0 -0
  11. data/app/assets/fonts/fontawesome-webfont.woff2 +0 -0
  12. data/app/assets/images/forest/favicons/android-chrome-192x192.png +0 -0
  13. data/app/assets/images/forest/favicons/android-chrome-512x512.png +0 -0
  14. data/app/assets/images/forest/favicons/apple-touch-icon.png +0 -0
  15. data/app/assets/images/forest/favicons/browserconfig.xml +9 -0
  16. data/app/assets/images/forest/favicons/favicon-16x16.png +0 -0
  17. data/app/assets/images/forest/favicons/favicon-32x32.png +0 -0
  18. data/app/assets/images/forest/favicons/favicon.ico +0 -0
  19. data/app/assets/images/forest/favicons/manifest.json.erb +18 -0
  20. data/app/assets/images/forest/favicons/mstile-150x150.png +0 -0
  21. data/app/assets/images/forest/favicons/safari-pinned-tab.svg +21 -0
  22. data/app/assets/images/forest/forest-low.jpg +0 -0
  23. data/app/assets/images/forest/forest.jpg +0 -0
  24. data/app/assets/javascripts/forest/admin/lib/jquery_plugins.js +32 -0
  25. data/app/assets/javascripts/forest/admin/main.js +59 -0
  26. data/app/assets/javascripts/forest/admin/partials/add_block.js +22 -0
  27. data/app/assets/javascripts/forest/admin/partials/block_collapser.js +49 -0
  28. data/app/assets/javascripts/forest/admin/partials/block_errors.js +11 -0
  29. data/app/assets/javascripts/forest/admin/partials/block_selector_inputs.js +61 -0
  30. data/app/assets/javascripts/forest/admin/partials/cocoon_events.js +3 -0
  31. data/app/assets/javascripts/forest/admin/partials/cocoon_sortable_field_sets.js +55 -0
  32. data/app/assets/javascripts/forest/admin/partials/collage_inputs.js +286 -0
  33. data/app/assets/javascripts/forest/admin/partials/color_inputs.js +24 -0
  34. data/app/assets/javascripts/forest/admin/partials/datepicker_init.js +70 -0
  35. data/app/assets/javascripts/forest/admin/partials/documentation_sidebar_affix.js +22 -0
  36. data/app/assets/javascripts/forest/admin/partials/dropdown_block_selector.js +106 -0
  37. data/app/assets/javascripts/forest/admin/partials/edit_header.js +22 -0
  38. data/app/assets/javascripts/forest/admin/partials/file_upload_init.js +111 -0
  39. data/app/assets/javascripts/forest/admin/partials/forest_tables.js +42 -0
  40. data/app/assets/javascripts/forest/admin/partials/infinite_loader.js +89 -0
  41. data/app/assets/javascripts/forest/admin/partials/markdown_text_editor_init.js +89 -0
  42. data/app/assets/javascripts/forest/admin/partials/media_item_chooser_modal.js.erb +259 -0
  43. data/app/assets/javascripts/forest/admin/partials/menus.js +79 -0
  44. data/app/assets/javascripts/forest/admin/partials/multi_checkbox_selector.js +27 -0
  45. data/app/assets/javascripts/forest/admin/partials/persisted_value_warnings.js +38 -0
  46. data/app/assets/javascripts/forest/admin/partials/repeater_inputs.js +24 -0
  47. data/app/assets/javascripts/forest/admin/partials/select2_init.js +165 -0
  48. data/app/assets/javascripts/forest/admin/partials/select_tag_form_submitter.js +40 -0
  49. data/app/assets/javascripts/forest/admin/partials/sortable_gallery.js +45 -0
  50. data/app/assets/javascripts/forest/admin/partials/sortable_page_block_position_setter.js +37 -0
  51. data/app/assets/javascripts/forest/admin/partials/status_scheduler.js +16 -0
  52. data/app/assets/javascripts/forest/admin/partials/tab_templates.js +93 -0
  53. data/app/assets/javascripts/forest/admin/partials/tables.js +7 -0
  54. data/app/assets/javascripts/forest/admin/partials/tooltips.js +7 -0
  55. data/app/assets/javascripts/forest/admin/partials/turboform_form_submitter.js +15 -0
  56. data/app/assets/javascripts/forest/admin/vendor/imagesloaded.pkgd.min.js +7 -0
  57. data/app/assets/javascripts/forest/admin/vendor/jquery-ui-timepicker-addon.js +2291 -0
  58. data/app/assets/javascripts/forest/admin/vendor/jquery.ba-throttle-debounce.min.js +9 -0
  59. data/app/assets/javascripts/forest/admin/vendor/jquery.nestable.js +756 -0
  60. data/app/assets/javascripts/forest/admin/vendor/select2.full.min.js +3 -0
  61. data/app/assets/javascripts/forest/admin/vendor/simplemde.min.js +15 -0
  62. data/app/assets/javascripts/forest/application_admin.js +29 -0
  63. data/app/assets/javascripts/forest/application_admin_from_host_app.js +1 -0
  64. data/app/assets/javascripts/forest/application_public.js +19 -0
  65. data/app/assets/javascripts/forest/cable.js +13 -0
  66. data/app/assets/javascripts/forest/lib/jquery-3.3.1.min.js +2 -0
  67. data/app/assets/javascripts/forest/main.js +59 -0
  68. data/app/assets/javascripts/forest/public/partials/analytics.js +16 -0
  69. data/app/assets/stylesheets/forest/admin/_bootstrap-variables.scss +877 -0
  70. data/app/assets/stylesheets/forest/admin/_variables.scss +13 -0
  71. data/app/assets/stylesheets/forest/admin/base/_foundation.scss +17 -0
  72. data/app/assets/stylesheets/forest/admin/mixins/_breakpoints.scss +26 -0
  73. data/app/assets/stylesheets/forest/admin/mixins/_glyphicons.scss +278 -0
  74. data/app/assets/stylesheets/forest/admin/mixins/_layout.scss +13 -0
  75. data/app/assets/stylesheets/forest/admin/mixins/_links.scss +10 -0
  76. data/app/assets/stylesheets/forest/admin/mixins/_lists.scss +10 -0
  77. data/app/assets/stylesheets/forest/admin/mixins/_mixins.scss +6 -0
  78. data/app/assets/stylesheets/forest/admin/mixins/_triangles.scss +21 -0
  79. data/app/assets/stylesheets/forest/admin/partials/_admin.scss +57 -0
  80. data/app/assets/stylesheets/forest/admin/partials/_affix.scss +5 -0
  81. data/app/assets/stylesheets/forest/admin/partials/_block_errors.scss +15 -0
  82. data/app/assets/stylesheets/forest/admin/partials/_block_layout.scss +48 -0
  83. data/app/assets/stylesheets/forest/admin/partials/_block_type_edit_ui.scss +15 -0
  84. data/app/assets/stylesheets/forest/admin/partials/_bootstrap_customizations.scss +12 -0
  85. data/app/assets/stylesheets/forest/admin/partials/_collage_inputs.scss +122 -0
  86. data/app/assets/stylesheets/forest/admin/partials/_documentation.scss +7 -0
  87. data/app/assets/stylesheets/forest/admin/partials/_dropdown_block_selector.scss +19 -0
  88. data/app/assets/stylesheets/forest/admin/partials/_edit_header.scss +16 -0
  89. data/app/assets/stylesheets/forest/admin/partials/_file_upload.scss +3 -0
  90. data/app/assets/stylesheets/forest/admin/partials/_forest_tables.scss +20 -0
  91. data/app/assets/stylesheets/forest/admin/partials/_forms_and_inputs.scss +72 -0
  92. data/app/assets/stylesheets/forest/admin/partials/_helper_classes.scss +24 -0
  93. data/app/assets/stylesheets/forest/admin/partials/_infinite_loader.scss +8 -0
  94. data/app/assets/stylesheets/forest/admin/partials/_markdown_editor.scss +12 -0
  95. data/app/assets/stylesheets/forest/admin/partials/_media_item_chooser.scss +168 -0
  96. data/app/assets/stylesheets/forest/admin/partials/_media_library.scss +109 -0
  97. data/app/assets/stylesheets/forest/admin/partials/_pages.scss +6 -0
  98. data/app/assets/stylesheets/forest/admin/partials/_pagination.scss +5 -0
  99. data/app/assets/stylesheets/forest/admin/partials/_repeater_inputs.scss +57 -0
  100. data/app/assets/stylesheets/forest/admin/partials/_resizable_ui.scss +1 -0
  101. data/app/assets/stylesheets/forest/admin/partials/_select2_custom.scss +20 -0
  102. data/app/assets/stylesheets/forest/admin/partials/_sessions.scss +13 -0
  103. data/app/assets/stylesheets/forest/admin/partials/_slug_attributes.scss +9 -0
  104. data/app/assets/stylesheets/forest/admin/partials/_sortable_field_sets.scss +22 -0
  105. data/app/assets/stylesheets/forest/admin/partials/_sortable_select2.scss +18 -0
  106. data/app/assets/stylesheets/forest/admin/partials/_sortable_ui.scss +15 -0
  107. data/app/assets/stylesheets/forest/admin/partials/_status_indicators.scss +33 -0
  108. data/app/assets/stylesheets/forest/admin/partials/_status_scheduler.scss +9 -0
  109. data/app/assets/stylesheets/forest/admin/partials/_tooltips.scss +5 -0
  110. data/app/assets/stylesheets/forest/admin/partials/_turbolinks.scss +5 -0
  111. data/app/assets/stylesheets/forest/admin/partials/_typography.scss +19 -0
  112. data/app/assets/stylesheets/forest/admin/partials/_ui.scss +32 -0
  113. data/app/assets/stylesheets/forest/admin/sprockets/font-awesome.scss +2337 -0
  114. data/app/assets/stylesheets/forest/admin/sprockets/main_bootstrap.scss +3 -0
  115. data/app/assets/stylesheets/forest/admin/vendor/_jquery-ui-timepicker-addon.scss +30 -0
  116. data/app/assets/stylesheets/forest/admin/vendor/_nestable.scss +347 -0
  117. data/app/assets/stylesheets/forest/admin/vendor/_select2_1_core.scss +484 -0
  118. data/app/assets/stylesheets/forest/admin/vendor/_select2_2_bootstrap.scss +612 -0
  119. data/app/assets/stylesheets/forest/admin/vendor/_simplemde.min.scss +7 -0
  120. data/app/assets/stylesheets/forest/admin_overrides.scss +1 -0
  121. data/app/assets/stylesheets/forest/application_admin.css +23 -0
  122. data/app/assets/stylesheets/forest/application_public.css +16 -0
  123. data/app/assets/stylesheets/forest/main_admin.scss +16 -0
  124. data/app/assets/stylesheets/forest/main_public.scss +4 -0
  125. data/app/assets/stylesheets/forest/public/base/_admin_error_messages.scss +15 -0
  126. data/app/assets/stylesheets/forest/public/base/_foundation.scss +24 -0
  127. data/app/assets/stylesheets/forest/public/base/_images.scss +14 -0
  128. data/app/assets/stylesheets/forest/scaffolds.scss +87 -0
  129. data/app/assets/stylesheets/jquery.fileupload.scss +37 -0
  130. data/app/classes/forest/block_set.rb +26 -0
  131. data/app/classes/forest/error.rb +15 -0
  132. data/app/classes/forest/markdown_renderer.rb +31 -0
  133. data/app/classes/search_index_manager.rb +83 -0
  134. data/app/controllers/admin/block_kinds_controller.rb +31 -0
  135. data/app/controllers/admin/block_layouts_controller.rb +47 -0
  136. data/app/controllers/admin/cache_purge_controller.rb +11 -0
  137. data/app/controllers/admin/dashboard_controller.rb +6 -0
  138. data/app/controllers/admin/documentation_controller.rb +5 -0
  139. data/app/controllers/admin/errors_controller.rb +9 -0
  140. data/app/controllers/admin/forest_controller.rb +96 -0
  141. data/app/controllers/admin/imports_controller.rb +34 -0
  142. data/app/controllers/admin/media_items_controller.rb +107 -0
  143. data/app/controllers/admin/menus_controller.rb +69 -0
  144. data/app/controllers/admin/pages_controller.rb +105 -0
  145. data/app/controllers/admin/settings_controller.rb +66 -0
  146. data/app/controllers/admin/translations_controller.rb +58 -0
  147. data/app/controllers/admin/user_groups_controller.rb +69 -0
  148. data/app/controllers/admin/users_controller.rb +88 -0
  149. data/app/controllers/application_controller.rb +2 -0
  150. data/app/controllers/errors_controller.rb +26 -0
  151. data/app/controllers/forest_controller.rb +39 -0
  152. data/app/controllers/media_items_controller.rb +12 -0
  153. data/app/controllers/pages_controller.rb +39 -0
  154. data/app/controllers/public_controller.rb +5 -0
  155. data/app/helpers/admin_helper.rb +95 -0
  156. data/app/helpers/admin_info_helper.rb +12 -0
  157. data/app/helpers/admin_settings_helper.rb +16 -0
  158. data/app/helpers/application_helper.rb +2 -0
  159. data/app/helpers/block_helper.rb +25 -0
  160. data/app/helpers/cache_helper.rb +23 -0
  161. data/app/helpers/forest_errors_helper.rb +34 -0
  162. data/app/helpers/form_helper.rb +93 -0
  163. data/app/helpers/image_helper.rb +65 -0
  164. data/app/helpers/markdown_helper.rb +25 -0
  165. data/app/helpers/meta_helper.rb +238 -0
  166. data/app/helpers/navigation_helper.rb +18 -0
  167. data/app/helpers/status_indicator_helper.rb +7 -0
  168. data/app/inputs/block_selector_input.rb +16 -0
  169. data/app/inputs/collage_input.rb +63 -0
  170. data/app/inputs/color_input.rb +30 -0
  171. data/app/inputs/currency_input.rb +22 -0
  172. data/app/inputs/datepicker_input.rb +19 -0
  173. data/app/inputs/gallery_input.rb +67 -0
  174. data/app/inputs/grouped_collection_select_input.rb +19 -0
  175. data/app/inputs/image_input.rb +82 -0
  176. data/app/inputs/repeater_input.rb +58 -0
  177. data/app/jobs/forest/application_job.rb +4 -0
  178. data/app/mailers/forest/application_mailer.rb +6 -0
  179. data/app/models/application_record.rb +13 -0
  180. data/app/models/block_kind.rb +54 -0
  181. data/app/models/block_layout.rb +19 -0
  182. data/app/models/block_slot.rb +49 -0
  183. data/app/models/blocks/base_block.rb +134 -0
  184. data/app/models/cache_record.rb +2 -0
  185. data/app/models/concerns/attachable.rb +126 -0
  186. data/app/models/concerns/blockable.rb +65 -0
  187. data/app/models/concerns/filter_controller_scopes.rb +13 -0
  188. data/app/models/concerns/forest/cache_buster.rb +112 -0
  189. data/app/models/concerns/searchable.rb +200 -0
  190. data/app/models/concerns/sluggable.rb +70 -0
  191. data/app/models/concerns/statusable.rb +71 -0
  192. data/app/models/concerns/versionable.rb +13 -0
  193. data/app/models/forest/application_record.rb +111 -0
  194. data/app/models/import.rb +43 -0
  195. data/app/models/media_item.rb +136 -0
  196. data/app/models/menu.rb +65 -0
  197. data/app/models/page.rb +154 -0
  198. data/app/models/setting.rb +142 -0
  199. data/app/models/translation.rb +97 -0
  200. data/app/models/user.rb +45 -0
  201. data/app/models/user_group.rb +17 -0
  202. data/app/policies/application_policy.rb +71 -0
  203. data/app/policies/block_kind_policy.rb +2 -0
  204. data/app/policies/block_layout_policy.rb +2 -0
  205. data/app/policies/block_record_policy.rb +13 -0
  206. data/app/policies/dashboard_policy.rb +19 -0
  207. data/app/policies/media_item_policy.rb +5 -0
  208. data/app/policies/menu_policy.rb +2 -0
  209. data/app/policies/page_policy.rb +9 -0
  210. data/app/policies/setting_policy.rb +2 -0
  211. data/app/policies/translation_policy.rb +2 -0
  212. data/app/policies/user_group_policy.rb +2 -0
  213. data/app/policies/user_policy.rb +17 -0
  214. data/app/views/admin/_file_upload.html.erb +75 -0
  215. data/app/views/admin/_flash_notifications.html.erb +20 -0
  216. data/app/views/admin/_navigation.html.erb +61 -0
  217. data/app/views/admin/api/index/_header.json.jbuilder +2 -0
  218. data/app/views/admin/api/index/_records.json.jbuilder +6 -0
  219. data/app/views/admin/block_kinds/_form.html.erb +34 -0
  220. data/app/views/admin/block_kinds/edit.html.erb +3 -0
  221. data/app/views/admin/block_kinds/index.html.erb +31 -0
  222. data/app/views/admin/block_layouts/_form.html.erb +33 -0
  223. data/app/views/admin/block_layouts/edit.html.erb +3 -0
  224. data/app/views/admin/block_layouts/index.html.erb +29 -0
  225. data/app/views/admin/block_layouts/new.html.erb +3 -0
  226. data/app/views/admin/block_layouts/show.html.erb +24 -0
  227. data/app/views/admin/block_record/_block_layout.html.erb +67 -0
  228. data/app/views/admin/block_record/_block_slot_field_buttons.html.erb +15 -0
  229. data/app/views/admin/block_record/_block_slot_fields.html.erb +37 -0
  230. data/app/views/admin/block_record/_block_slot_fields_template.html.erb +50 -0
  231. data/app/views/admin/dashboard/_panel.html.erb +30 -0
  232. data/app/views/admin/dashboard/index.html.erb +18 -0
  233. data/app/views/admin/documentation/_body.html.erb +9 -0
  234. data/app/views/admin/documentation/_sidebar.html.erb +17 -0
  235. data/app/views/admin/documentation/index.html.erb +87 -0
  236. data/app/views/admin/form_inputs/_slug.html.erb +11 -0
  237. data/app/views/admin/form_inputs/_status.html.erb +20 -0
  238. data/app/views/admin/form_inputs/collage/_media_item_fields.html.erb +41 -0
  239. data/app/views/admin/headers/_edit.html.erb +68 -0
  240. data/app/views/admin/headers/_index.html.erb +61 -0
  241. data/app/views/admin/headers/_new.html.erb +14 -0
  242. data/app/views/admin/headers/_show.html.erb +37 -0
  243. data/app/views/admin/imports/edit.html.erb +60 -0
  244. data/app/views/admin/media_items/_form.html.erb +54 -0
  245. data/app/views/admin/media_items/_media_item_grid_layout.html.erb +23 -0
  246. data/app/views/admin/media_items/_media_item_list_layout.html.erb +32 -0
  247. data/app/views/admin/media_items/_modal.html.erb +62 -0
  248. data/app/views/admin/media_items/edit.html.erb +3 -0
  249. data/app/views/admin/media_items/index.html.erb +58 -0
  250. data/app/views/admin/media_items/index.json.jbuilder +2 -0
  251. data/app/views/admin/media_items/new.html.erb +3 -0
  252. data/app/views/admin/menus/_form.html.erb +92 -0
  253. data/app/views/admin/menus/_list_item.html.erb +39 -0
  254. data/app/views/admin/menus/edit.html.erb +3 -0
  255. data/app/views/admin/menus/index.html.erb +29 -0
  256. data/app/views/admin/menus/new.html.erb +3 -0
  257. data/app/views/admin/menus/show.html.erb +3 -0
  258. data/app/views/admin/navigation/_resources_dropdown.html.erb +12 -0
  259. data/app/views/admin/pages/_additional_inputs.html.erb +1 -0
  260. data/app/views/admin/pages/_form.html.erb +52 -0
  261. data/app/views/admin/pages/_table_row.html.erb +14 -0
  262. data/app/views/admin/pages/edit.html.erb +3 -0
  263. data/app/views/admin/pages/index.html.erb +33 -0
  264. data/app/views/admin/pages/index.json.jbuilder +2 -0
  265. data/app/views/admin/pages/new.html.erb +3 -0
  266. data/app/views/admin/pages/show.html.erb +3 -0
  267. data/app/views/admin/settings/_form.html.erb +25 -0
  268. data/app/views/admin/settings/edit.html.erb +3 -0
  269. data/app/views/admin/settings/index.html.erb +38 -0
  270. data/app/views/admin/settings/new.html.erb +3 -0
  271. data/app/views/admin/settings/show.html.erb +19 -0
  272. data/app/views/admin/settings/types/_boolean.html.erb +1 -0
  273. data/app/views/admin/settings/types/_image.html.erb +10 -0
  274. data/app/views/admin/settings/types/_integer.html.erb +5 -0
  275. data/app/views/admin/settings/types/_string.html.erb +5 -0
  276. data/app/views/admin/settings/types/_text.html.erb +5 -0
  277. data/app/views/admin/shared/_admin_head_additions.html.erb +1 -0
  278. data/app/views/admin/shared/navigation/_navbar.html.erb +8 -0
  279. data/app/views/admin/translations/_form.html.erb +31 -0
  280. data/app/views/admin/translations/edit.html.erb +3 -0
  281. data/app/views/admin/translations/index.html.erb +41 -0
  282. data/app/views/admin/translations/new.html.erb +3 -0
  283. data/app/views/admin/translations/show.html.erb +19 -0
  284. data/app/views/admin/user_groups/_form.html.erb +11 -0
  285. data/app/views/admin/user_groups/edit.html.erb +3 -0
  286. data/app/views/admin/user_groups/index.html.erb +29 -0
  287. data/app/views/admin/user_groups/new.html.erb +3 -0
  288. data/app/views/admin/user_groups/show.html.erb +9 -0
  289. data/app/views/admin/users/_form.html.erb +41 -0
  290. data/app/views/admin/users/edit.html.erb +3 -0
  291. data/app/views/admin/users/index.html.erb +35 -0
  292. data/app/views/admin/users/new.html.erb +3 -0
  293. data/app/views/admin/users/show.html.erb +4 -0
  294. data/app/views/blocks/_show.html.erb +21 -0
  295. data/app/views/devise/confirmations/new.html.erb +28 -0
  296. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  297. data/app/views/devise/mailer/password_change.html.erb +3 -0
  298. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  299. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  300. data/app/views/devise/passwords/edit.html.erb +31 -0
  301. data/app/views/devise/passwords/new.html.erb +27 -0
  302. data/app/views/devise/registrations/edit.html.erb +39 -0
  303. data/app/views/devise/registrations/new.html.erb +1 -0
  304. data/app/views/devise/sessions/_default_login.html.erb +25 -0
  305. data/app/views/devise/sessions/_first_time_login.html.erb +22 -0
  306. data/app/views/devise/sessions/new.html.erb +12 -0
  307. data/app/views/devise/shared/_flash_notifications.html.erb +3 -0
  308. data/app/views/devise/shared/_links.html.erb +25 -0
  309. data/app/views/devise/unlocks/new.html.erb +28 -0
  310. data/app/views/errors/internal_server_error.html.erb +2 -0
  311. data/app/views/errors/internal_server_error.json.jbuilder +4 -0
  312. data/app/views/errors/not_found.html.erb +2 -0
  313. data/app/views/errors/not_found.json.jbuilder +4 -0
  314. data/app/views/errors/unprocessable.html.erb +2 -0
  315. data/app/views/errors/unprocessable.json.jbuilder +4 -0
  316. data/app/views/forest/_analytics.html.erb +10 -0
  317. data/app/views/forest/_favicons.html.erb +7 -0
  318. data/app/views/kaminari/_first_page.html.erb +11 -0
  319. data/app/views/kaminari/_gap.html.erb +8 -0
  320. data/app/views/kaminari/_last_page.html.erb +11 -0
  321. data/app/views/kaminari/_next_page.html.erb +11 -0
  322. data/app/views/kaminari/_page.html.erb +12 -0
  323. data/app/views/kaminari/_paginator.html.erb +25 -0
  324. data/app/views/kaminari/_prev_page.html.erb +11 -0
  325. data/app/views/layouts/_shared_head.html.erb +48 -0
  326. data/app/views/layouts/admin.html.erb +19 -0
  327. data/app/views/layouts/application.html.erb +15 -0
  328. data/app/views/layouts/devise.html.erb +12 -0
  329. data/app/views/layouts/mailer.html.erb +13 -0
  330. data/app/views/layouts/mailer.text.erb +1 -0
  331. data/app/views/media_items/show.html.erb +29 -0
  332. data/app/views/pages/show.html.erb +1 -0
  333. data/app/views/public/index.html.erb +2 -0
  334. data/app/views/shared/_footer.html.erb +9 -0
  335. data/app/views/shared/_header.html.erb +9 -0
  336. data/app/views/shared/_header_colophon.html.erb +7 -0
  337. data/app/views/shared/_menu.html.erb +5 -0
  338. data/app/views/shared/_menu_item.html.erb +30 -0
  339. data/app/views/shared/_subnav.html.erb +7 -0
  340. data/config/initializers/aws.rb +17 -0
  341. data/config/initializers/devise.rb +275 -0
  342. data/config/initializers/forest.rb +5 -0
  343. data/config/initializers/paperclip.rb +1 -0
  344. data/config/initializers/rails_extensions.rb +6 -0
  345. data/config/initializers/simple_form.rb +164 -0
  346. data/config/initializers/simple_form/markdown.rb +21 -0
  347. data/config/initializers/simple_form/remote.rb +38 -0
  348. data/config/initializers/simple_form/sortable.rb +28 -0
  349. data/config/initializers/simple_form_bootstrap.rb +155 -0
  350. data/config/locales/devise.en.yml +62 -0
  351. data/config/locales/en.yml +24 -0
  352. data/config/locales/simple_form.en.yml +31 -0
  353. data/config/routes.rb +61 -0
  354. data/db/migrate/20161217191000_devise_create_users.rb +48 -0
  355. data/db/migrate/20161217200300_create_pages.rb +21 -0
  356. data/db/migrate/20161217205353_create_menus.rb +12 -0
  357. data/db/migrate/20161219033747_create_settings.rb +14 -0
  358. data/db/migrate/20161219231741_create_media_items.rb +18 -0
  359. data/db/migrate/20161225212203_create_user_groups.rb +10 -0
  360. data/db/migrate/20161225212258_create_join_table_user_groups_users.rb +8 -0
  361. data/db/migrate/20170109175932_create_block_kinds.rb +14 -0
  362. data/db/migrate/20170109180818_create_block_slots.rb +17 -0
  363. data/db/migrate/20170109185414_create_base_blocks.rb +8 -0
  364. data/db/migrate/20170818025124_create_block_layouts.rb +13 -0
  365. data/db/migrate/20170818025229_add_block_layout_to_block_slots.rb +5 -0
  366. data/db/migrate/20170818025500_remove_layout_from_block_slots.rb +5 -0
  367. data/db/migrate/20170821161755_add_unique_index_to_block_layouts.rb +6 -0
  368. data/db/migrate/20170826173346_create_translations.rb +12 -0
  369. data/db/migrate/20170910204934_index_attachment_content_type_on_media_items.rb +5 -0
  370. data/db/migrate/20180206035546_create_cache_records.rb +14 -0
  371. data/db/migrate/20180415034427_add_redirect_to_pages.rb +5 -0
  372. data/db/migrate/20180618190248_add_index_created_at_to_media_items.rb +5 -0
  373. data/db/migrate/20180625172226_add_blockable_metadata_to_pages.rb +6 -0
  374. data/db/migrate/20180626182949_remove_attachable_from_media_items.rb +7 -0
  375. data/db/migrate/20180712162414_add_media_item_status_to_media_items.rb +6 -0
  376. data/db/migrate/20190223155013_add_type_to_block_kinds.rb +6 -0
  377. data/db/migrate/20190423173909_add_seo_title_to_pages.rb +5 -0
  378. data/lib/forest.rb +9 -0
  379. data/lib/forest/engine.rb +51 -0
  380. data/lib/forest/migrations.rb +86 -0
  381. data/lib/forest/rails/active_record/has_many_ordered.rb +30 -0
  382. data/lib/forest/rails/active_record/has_repeatable.rb +19 -0
  383. data/lib/forest/rails/core_ext/enumerable.rb +17 -0
  384. data/lib/forest/version.rb +3 -0
  385. data/lib/generators/forest/block/USAGE +8 -0
  386. data/lib/generators/forest/block/block_generator.rb +103 -0
  387. data/lib/generators/forest/block/templates/_block.html.erb +2 -0
  388. data/lib/generators/forest/block/templates/_block.scss.erb +5 -0
  389. data/lib/generators/forest/block/templates/_block_edit_fields.html.erb +21 -0
  390. data/lib/generators/forest/block/templates/create_table_migration.rb +31 -0
  391. data/lib/generators/forest/block/templates/model.rb +41 -0
  392. data/lib/generators/forest/install/USAGE +2 -0
  393. data/lib/generators/forest/install/install_generator.rb +72 -0
  394. data/lib/generators/forest/scaffold/USAGE +8 -0
  395. data/lib/generators/forest/scaffold/scaffold_generator.rb +133 -0
  396. data/lib/generators/forest/scaffold/templates/admin_controller.rb +67 -0
  397. data/lib/generators/forest/scaffold/templates/controller.rb +20 -0
  398. data/lib/generators/forest/scaffold/templates/create_table_migration.rb +35 -0
  399. data/lib/generators/forest/scaffold/templates/model.rb +21 -0
  400. data/lib/generators/forest/scaffold/templates/policy.rb +2 -0
  401. data/lib/generators/forest/scaffold/templates/views/admin/_form.html.erb +56 -0
  402. data/lib/generators/forest/scaffold/templates/views/admin/edit.html.erb +3 -0
  403. data/lib/generators/forest/scaffold/templates/views/admin/index.html.erb +58 -0
  404. data/lib/generators/forest/scaffold/templates/views/admin/index.json.jbuilder +2 -0
  405. data/lib/generators/forest/scaffold/templates/views/admin/new.html.erb +3 -0
  406. data/lib/generators/forest/scaffold/templates/views/admin/show.html.erb +12 -0
  407. data/lib/generators/forest/scaffold/templates/views/public/index.html.erb +1 -0
  408. data/lib/generators/forest/scaffold/templates/views/public/show.html.erb +17 -0
  409. data/lib/tasks/forest_db_tasks.rake +176 -0
  410. data/lib/tasks/forest_elasticsearch_tasks.rake +22 -0
  411. metadata +719 -0
@@ -0,0 +1,66 @@
1
+ class Admin::SettingsController < Admin::ForestController
2
+ before_action :set_setting, only: [:show, :edit, :update, :destroy]
3
+
4
+ # GET /settings
5
+ def index
6
+ @settings = apply_scopes(Setting.all).by_title.page params[:page]
7
+ authorize @settings
8
+ end
9
+
10
+ # GET /settings/1
11
+ def show
12
+ authorize @setting
13
+ end
14
+
15
+ # TODO: better pattern for disabling new actions
16
+ # GET /settings/new
17
+ # def new
18
+ # @setting = Setting.new
19
+ # authorize @setting
20
+ # end
21
+
22
+ # GET /settings/1/edit
23
+ def edit
24
+ authorize @setting
25
+ end
26
+
27
+ # POST /settings
28
+ def create
29
+ @setting = Setting.new(setting_params)
30
+ authorize @setting
31
+
32
+ if @setting.save
33
+ redirect_to edit_admin_setting_path(@setting), notice: 'Setting was successfully created.'
34
+ else
35
+ render :new
36
+ end
37
+ end
38
+
39
+ # PATCH/PUT /settings/1
40
+ def update
41
+ authorize @setting
42
+ if @setting.update(setting_params)
43
+ redirect_to edit_admin_setting_path(@setting), notice: 'Setting was successfully updated.'
44
+ else
45
+ render :edit
46
+ end
47
+ end
48
+
49
+ # DELETE /settings/1
50
+ # def destroy
51
+ # authorize @setting
52
+ # @setting.destroy
53
+ # redirect_to admin_settings_url, notice: 'Setting was successfully destroyed.'
54
+ # end
55
+
56
+ private
57
+ # Use callbacks to share common setup or constraints between actions.
58
+ def set_setting
59
+ @setting = Setting.find(params[:id])
60
+ end
61
+
62
+ # Only allow a trusted parameter "white list" through.
63
+ def setting_params
64
+ params.require(:setting).permit(:value, :title, :slug, :value_type)
65
+ end
66
+ end
@@ -0,0 +1,58 @@
1
+ class Admin::TranslationsController < Admin::ForestController
2
+ before_action :set_translation, only: [:show, :edit, :update, :destroy]
3
+
4
+ def index
5
+ @translations = apply_scopes(Translation).by_key.page params[:page]
6
+ end
7
+
8
+ def show
9
+ authorize @translation
10
+ end
11
+
12
+ def new
13
+ @translation = Translation.new
14
+ authorize @translation
15
+ end
16
+
17
+ def edit
18
+ authorize @translation
19
+ end
20
+
21
+ def create
22
+ @translation = Translation.new(translation_params)
23
+ authorize @translation
24
+
25
+ if @translation.save
26
+ redirect_to edit_admin_translation_path(@translation), notice: 'Translation was successfully created.'
27
+ else
28
+ render :new
29
+ end
30
+ end
31
+
32
+ def update
33
+ authorize @translation
34
+
35
+ if @translation.update(translation_params)
36
+ redirect_to edit_admin_translation_path(@translation), notice: 'Translation was successfully updated.'
37
+ else
38
+ render :edit
39
+ end
40
+ end
41
+
42
+ def destroy
43
+ authorize @translation
44
+ @translation.destroy
45
+ redirect_to admin_translations_url, notice: 'Translation was successfully destroyed.'
46
+ end
47
+
48
+ private
49
+
50
+ def translation_params
51
+ # Add blockable params to the permitted attributes if this record is blockable `**BlockSlot.blockable_params`
52
+ params.require(:translation).permit(:key, :value, :description, )
53
+ end
54
+
55
+ def set_translation
56
+ @translation = Translation.find(params[:id])
57
+ end
58
+ end
@@ -0,0 +1,69 @@
1
+ class Admin::UserGroupsController < Admin::ForestController
2
+ include FilterControllerScopes
3
+
4
+ before_action :set_user_group, only: [:show, :edit, :update, :destroy]
5
+
6
+ has_scope :by_name
7
+
8
+ # GET /user_groups
9
+ def index
10
+ @user_groups = apply_scopes(UserGroup).by_name.page params[:page]
11
+ authorize @user_groups
12
+ end
13
+
14
+ # GET /user_groups/1
15
+ def show
16
+ authorize @user_group
17
+ end
18
+
19
+ # GET /user_groups/new
20
+ def new
21
+ @user_group = UserGroup.new
22
+ authorize @user_group
23
+ end
24
+
25
+ # GET /user_groups/1/edit
26
+ def edit
27
+ authorize @user_group
28
+ end
29
+
30
+ # POST /user_groups
31
+ def create
32
+ @user_group = UserGroup.new(user_group_params)
33
+ authorize @user_group
34
+
35
+ if @user_group.save
36
+ redirect_to edit_admin_user_group_path(@user_group), notice: 'User group was successfully created.'
37
+ else
38
+ render :new
39
+ end
40
+ end
41
+
42
+ # PATCH/PUT /user_groups/1
43
+ def update
44
+ authorize @user_group
45
+ if @user_group.update(user_group_params)
46
+ redirect_to edit_admin_user_group_path(@user_group), notice: 'User group was successfully updated.'
47
+ else
48
+ render :edit
49
+ end
50
+ end
51
+
52
+ # DELETE /user_groups/1
53
+ def destroy
54
+ authorize @user_group
55
+ @user_group.destroy
56
+ redirect_to admin_user_groups_url, notice: 'User group was successfully destroyed.'
57
+ end
58
+
59
+ private
60
+ # Use callbacks to share common setup or constraints between actions.
61
+ def set_user_group
62
+ @user_group = UserGroup.find(params[:id])
63
+ end
64
+
65
+ # Only allow a trusted parameter "white list" through.
66
+ def user_group_params
67
+ params.require(:user_group).permit(:name)
68
+ end
69
+ end
@@ -0,0 +1,88 @@
1
+ class Admin::UsersController < Admin::ForestController
2
+ include FilterControllerScopes
3
+
4
+ before_action :set_user, only: [:show, :edit, :update, :destroy]
5
+
6
+ has_scope :by_email
7
+ has_scope :by_last_name
8
+ has_scope :by_first_name
9
+
10
+ # GET /users
11
+ def index
12
+ @users = apply_scopes(User.includes(:user_groups)).by_id.page params[:page]
13
+ authorize @users
14
+ end
15
+
16
+ # GET /users/1
17
+ def show
18
+ authorize @user
19
+ end
20
+
21
+ # GET /users/new
22
+ def new
23
+ @user = User.new
24
+ authorize @user
25
+ end
26
+
27
+ # GET /users/1/edit
28
+ def edit
29
+ authorize @user
30
+ end
31
+
32
+ # POST /users
33
+ def create
34
+ @user = User.new(user_params)
35
+ authorize @user
36
+
37
+ if @user.save
38
+ redirect_to edit_admin_user_path(@user), notice: 'User was successfully created.'
39
+ else
40
+ render :new
41
+ end
42
+ end
43
+
44
+ # PATCH/PUT /users/1
45
+ def update
46
+ authorize @user
47
+
48
+ if params[:user][:password].blank? && params[:user][:password_confirmation].blank?
49
+ params[:user].delete(:password)
50
+ params[:user].delete(:password_confirmation)
51
+ end
52
+
53
+ if @user.update(user_params)
54
+ redirect_to edit_admin_user_path(@user), notice: 'User was successfully updated.'
55
+ else
56
+ render :edit
57
+ end
58
+ end
59
+
60
+ def reset_password
61
+ @user = User.find(params[:user_id])
62
+ authorize @user
63
+
64
+ if @user.send_reset_password_instructions
65
+ redirect_to edit_admin_user_path(@user), notice: 'User password reset link was successfully sent.'
66
+ else
67
+ render :edit
68
+ end
69
+ end
70
+
71
+ # DELETE /users/1
72
+ def destroy
73
+ authorize @user
74
+ @user.destroy
75
+ redirect_to admin_users_url, notice: 'User was successfully destroyed.'
76
+ end
77
+
78
+ private
79
+ # Use callbacks to share common setup or constraints between actions.
80
+ def set_user
81
+ @user = User.find(params[:id])
82
+ end
83
+
84
+ # Only allow a trusted parameter "white list" through.
85
+ def user_params
86
+ params.require(:user).permit(:email, :first_name, :last_name, :password, :password_confirmation, user_group_ids: [])
87
+ end
88
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationController < ActionController::Base
2
+ end
@@ -0,0 +1,26 @@
1
+ class ErrorsController < ForestController
2
+ before_action :filter_by_request_type
3
+
4
+ def not_found
5
+ @page_title = '404 - Not Found'
6
+ render status: 404
7
+ end
8
+
9
+ def unprocessable
10
+ @page_title = '422 - Unprocessable'
11
+ render status: 422
12
+ end
13
+
14
+ def internal_server_error
15
+ @page_title = '500 - Error'
16
+ render status: 500
17
+ end
18
+
19
+ private
20
+
21
+ def filter_by_request_type
22
+ if %i(html json).none?(request.format.symbol)
23
+ render status: 404
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,39 @@
1
+ class ForestController < ApplicationController
2
+ include Pundit
3
+
4
+ protect_from_forgery with: :exception, prepend: true
5
+ skip_before_action :verify_authenticity_token, if: -> { controller_name == 'sessions' && action_name == 'create' }
6
+
7
+ layout :layout_by_resource
8
+
9
+ before_action :set_body_classes
10
+ before_action :reset_class_method_cache
11
+
12
+ def after_sign_in_path_for(resource)
13
+ main_app.admin_path
14
+ end
15
+
16
+ private
17
+
18
+ def layout_by_resource
19
+ devise_controller? ? 'devise' : 'application'
20
+ end
21
+
22
+ def set_body_classes
23
+ controller_heirarchy = self.class.name.split('::').reject(&:blank?)
24
+ controller_heirarchy.pop
25
+ controller_heirarchy = controller_heirarchy.collect { |a| "controller-class--#{a.underscore}" }.join(' ')
26
+
27
+ @body_classes ||= []
28
+ @body_classes << controller_heirarchy
29
+ @body_classes << "controller--#{controller_name}"
30
+ @body_classes << "action--#{action_name}"
31
+ @body_classes << 'current-user--admin' if current_user&.admin?
32
+ end
33
+
34
+ def reset_class_method_cache
35
+ Menu.reset_method_cache!
36
+ Setting.reset_method_cache!
37
+ Translation.reset_method_cache!
38
+ end
39
+ end
@@ -0,0 +1,12 @@
1
+ class MediaItemsController < ForestController
2
+ before_action :set_media_item, only: [:show]
3
+
4
+ def show
5
+ end
6
+
7
+ private
8
+
9
+ def set_media_item
10
+ @media_item = MediaItem.find_by_slug(params[:id])
11
+ end
12
+ end
@@ -0,0 +1,39 @@
1
+ class PagesController < ForestController
2
+ before_action :set_page, only: [:show]
3
+
4
+ def show
5
+ unless @page
6
+ if Rails.configuration.consider_all_requests_local
7
+ raise ActionController::RoutingError.new('Not Found')
8
+ else
9
+ logger.error("[Forest][Error] 404 page not found. Looked for path \"#{request.fullpath.force_encoding('utf-8')}\"")
10
+ @body_classes ||= []
11
+ @body_classes << 'controller--errors action--not_found'
12
+ @page_title = '404 - Not Found'
13
+ return render 'errors/not_found'
14
+ end
15
+ end
16
+ authorize @page
17
+
18
+ if @page.redirect.present?
19
+ return redirect_to @page.redirect
20
+ end
21
+
22
+ @body_classes << "page--#{@page.slug}"
23
+ end
24
+
25
+ def edit
26
+ @page = Page.where(path: params[:page_path]).try(:first)
27
+ if @page
28
+ return redirect_to edit_admin_page_path(@page)
29
+ else
30
+ return redirect_to admin_pages_path
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def set_page
37
+ @page = Page.find_by_path(params[:page_path].presence || 'home')
38
+ end
39
+ end
@@ -0,0 +1,5 @@
1
+ class PublicController < ForestController
2
+ def index
3
+ @page_title = 'Home'
4
+ end
5
+ end
@@ -0,0 +1,95 @@
1
+ module AdminHelper
2
+ def table_sorter(options = {})
3
+ title = options.fetch :title
4
+ path = options.fetch :path
5
+ scope = options.fetch :scope
6
+ default_order = options.fetch :default_order, :asc
7
+ opposite_order = default_order == :asc ? :desc : :asc
8
+ is_default_order = params[scope]&.to_sym == default_order
9
+ active_class = params[scope].present? ? 'active ' : ''
10
+
11
+ link_to title,
12
+ send(path, "#{scope}": (is_default_order ? opposite_order : default_order)),
13
+ class: "#{active_class}#{(is_default_order ? 'order--default' : 'order--reverse')}"
14
+ end
15
+
16
+ def table_thumbnail(image)
17
+ if image&.attachment.present?
18
+ content_tag :div, class: 'table-thumbnail' do
19
+ image_tag image.attachment.url(:thumb)
20
+ end
21
+ end
22
+ end
23
+
24
+ def table_color_representation(color)
25
+ content_tag :div, '', class: 'table-color-representation', style: "background-color: #{color};"
26
+ end
27
+
28
+ def forest_date(datetime)
29
+ return if datetime.blank?
30
+ datetime_format = datetime.is_a?(Date) ? '%m&#8209;%d&#8209;%Y' : '%m&#8209;%d&#8209;%Y %l:%M&nbsp;%p'
31
+ datetime.strftime(datetime_format).html_safe
32
+ end
33
+
34
+ def admin_page_level_indicator(level)
35
+ (level + 1).times.collect{}.join('&mdash; ').html_safe
36
+ end
37
+
38
+ def admin_navbar_class
39
+ return unless (@page && @page.statusable?)
40
+
41
+ # if @page.scheduled?
42
+ # 'bg-info'
43
+ # elsif !@page.published?
44
+ # 'bg-warning'
45
+ # end
46
+
47
+ !@page.published?
48
+ end
49
+
50
+ def admin_navbar_active_class(nav_item_path)
51
+ 'active' if nav_item_path == request.path
52
+ end
53
+
54
+ def admin_area?
55
+ request_parts.first == 'admin'
56
+ end
57
+
58
+ def public_area?
59
+ !admin_area?
60
+ end
61
+
62
+ def request_parts
63
+ request.path.split('/').reject(&:blank?)
64
+ end
65
+
66
+ def record_name(record)
67
+ return unless record.present?
68
+ record.try(:display_name).presence || record.try(:title).presence || record.try(:name).presence || "#{record.model_name.human} #{record.id}"
69
+ end
70
+
71
+ def admin_header_tag(record, &block)
72
+ record = record.first if record.respond_to?(:join)
73
+ content_tag :div, capture(&block), class: "admin-header", data: {
74
+ record_type: record&.class&.model_name&.singular,
75
+ record_id: record.try(:id)
76
+ }
77
+ end
78
+
79
+ def back_button(default_url)
80
+ if request.referer.present?
81
+ request.referer
82
+ else
83
+ default_url
84
+ end
85
+ end
86
+
87
+ def jquery_include_tag
88
+ if Rails.env.production?
89
+ jquery_url = 'https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js'
90
+ else
91
+ jquery_url = 'forest/lib/jquery-3.3.1.min'
92
+ end
93
+ javascript_include_tag jquery_url, data: { turbolinks_eval: false, turbolinks_suppress_warning: true }
94
+ end
95
+ end