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,17 @@
1
+ module Enumerable
2
+ # clumps adjacent elements together
3
+ # >> [2,2,2,3,3,4,2,2,1].cluster{|x| x}
4
+ # => [[2, 2, 2], [3, 3], [4], [2, 2], [1]]
5
+ # http://apidock.com/rails/Enumerable/group_by#508-Array-clustering
6
+ def cluster
7
+ cluster = []
8
+ each do |element|
9
+ if cluster.last && yield(cluster.last.last) == yield(element)
10
+ cluster.last << element
11
+ else
12
+ cluster << [element]
13
+ end
14
+ end
15
+ cluster
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module Forest
2
+ VERSION = '0.98.1'
3
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Generates a migration to create a new block type.
3
+
4
+ Example:
5
+ rails generate block TitleBlock
6
+
7
+ This will create:
8
+ TODO
@@ -0,0 +1,103 @@
1
+ class Forest::BlockGenerator < Rails::Generators::NamedBase
2
+ include Rails::Generators::Migration
3
+
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ argument :attributes, type: :array, default: [], banner: "field[:type][:index] field[:type][:index]"
7
+
8
+ def self.next_migration_number(dirname)
9
+ next_migration_number = current_migration_number(dirname) + 1
10
+ ActiveRecord::Migration.next_migration_number(next_migration_number)
11
+ end
12
+
13
+ def create_model_file
14
+ template 'model.rb', File.join('app/models/blocks', "#{file_name}.rb")
15
+ end
16
+
17
+ def create_view_files
18
+ template "_block.html.erb", File.join('app/views/blocks', file_name, "_show.html.erb")
19
+ template "_block_edit_fields.html.erb", File.join('app/views/blocks', file_name, "_edit.html.erb")
20
+ end
21
+
22
+ def create_migration_file
23
+ set_local_assigns!
24
+ validate_file_name!
25
+ migration_template 'create_table_migration.rb', "db/migrate/create_#{table_name}.rb"
26
+ end
27
+
28
+ def create_stylesheet
29
+ template '_block.scss.erb', File.join('app/assets/stylesheets/blocks', "_#{file_name}.scss")
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :migration_action, :join_tables
35
+
36
+ # Sets the default migration template that is being used for the generation of the migration.
37
+ # Depending on command line arguments, the migration template and the table name instance
38
+ # variables are set up.
39
+ def set_local_assigns!
40
+ @migration_template = "migration.rb"
41
+ case file_name
42
+ when /^(add|remove)_.*_(?:to|from)_(.*)/
43
+ @migration_action = $1
44
+ @table_name = normalize_table_name($2)
45
+ when /join_table/
46
+ if attributes.length == 2
47
+ @migration_action = "join"
48
+ @join_tables = pluralize_table_names? ? attributes.map(&:plural_name) : attributes.map(&:singular_name)
49
+
50
+ set_index_names
51
+ end
52
+ when /^create_(.+)/
53
+ @table_name = normalize_table_name($1)
54
+ @migration_template = "create_table_migration.rb"
55
+ end
56
+ end
57
+
58
+ def set_index_names
59
+ attributes.each_with_index do |attr, i|
60
+ attr.index_name = [attr, attributes[i - 1]].map { |a| index_name_for(a) }
61
+ end
62
+ end
63
+
64
+ def index_name_for(attribute)
65
+ if attribute.foreign_key?
66
+ attribute.name
67
+ else
68
+ attribute.name.singularize.foreign_key
69
+ end.to_sym
70
+ end
71
+
72
+ def attributes_with_index
73
+ attributes.select { |a| !a.reference? && a.has_index? }
74
+ end
75
+
76
+ # A migration file name can only contain underscores (_), lowercase characters,
77
+ # and numbers 0-9. Any other file name will raise an IllegalMigrationNameError.
78
+ def validate_file_name!
79
+ unless /^[_a-z0-9]+$/.match?(file_name)
80
+ raise IllegalMigrationNameError.new(file_name)
81
+ end
82
+ end
83
+
84
+ def normalize_table_name(_table_name)
85
+ pluralize_table_names? ? _table_name.pluralize : _table_name.singularize
86
+ end
87
+
88
+ def block_record_type
89
+ escape_quotes (ENV['BLOCK_RECORD_TYPE'].presence || 'default')
90
+ end
91
+
92
+ def block_category
93
+ escape_quotes (ENV['BLOCK_CATEGORY'].presence || 'default')
94
+ end
95
+
96
+ def block_description
97
+ escape_quotes (ENV['BLOCK_DESCRIPTION'].presence || '')
98
+ end
99
+
100
+ def escape_quotes(string)
101
+ string.gsub(/[']/, '\\\\\'')
102
+ end
103
+ end
@@ -0,0 +1,2 @@
1
+ <p><%%= block.class.name %> <%%= block.id %></p>
2
+ <p>Find me in /app/views/blocks/<%%= block.model_name.singular %>/_show.html.erb</p>
@@ -0,0 +1,5 @@
1
+ // <%= singular_name.titleize %>
2
+
3
+ .<%= singular_name.dasherize %> {
4
+
5
+ }
@@ -0,0 +1,21 @@
1
+ <%- if attributes.present? -%>
2
+ <%- attributes.each do |attribute| -%>
3
+ <%- if attribute.reference? -%>
4
+ <%- if attribute.name =~ /media_item/ -%>
5
+ <%%= f.association :<%= attribute.name %>, as: :image %>
6
+ <%- else -%>
7
+ <%%= f.association :<%= attribute.name %> %>
8
+ <%- end -%>
9
+ <%- else -%>
10
+ <%- if attribute.name =~ /date/ -%>
11
+ <%%= f.input :<%= attribute.name %>, as: :datepicker %>
12
+ <%- elsif attribute.name =~ /text/ -%>
13
+ <%%= f.input :<%= attribute.name %>, markdown: true %>
14
+ <%- else -%>
15
+ <%%= f.input :<%= attribute.name %> %>
16
+ <%- end -%>
17
+ <%- end -%>
18
+ <%- end -%>
19
+ <%- else -%>
20
+ <%%#= f.input :attribute_name %>
21
+ <%- end -%>
@@ -0,0 +1,31 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ def change
3
+ create_table :<%= table_name %> do |t|
4
+ <% attributes.each do |attribute| -%>
5
+ t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %>
6
+ <% end -%>
7
+ t.timestamps
8
+ end
9
+ <% attributes.select(&:token?).each do |attribute| -%>
10
+ add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>, unique: true
11
+ <% end -%>
12
+ <% attributes_with_index.each do |attribute| -%>
13
+ add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
14
+ <% end -%>
15
+
16
+ reversible do |change|
17
+ change.up do
18
+ unless BlockKind.find_by_name('<%= class_name %>')
19
+ BlockKind.create name: '<%= class_name %>',
20
+ record_type: '<%= block_record_type %>',
21
+ category: '<%= block_category %>',
22
+ description: '<%= block_description %>'
23
+ end
24
+ end
25
+
26
+ change.down do
27
+ BlockKind.where(name: '<%= class_name %>').destroy_all
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,41 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %> < BaseBlock
3
+ <% attributes.each do |attribute| %><% if attribute.reference? -%>
4
+ belongs_to :<%= attribute.name %>
5
+
6
+ <% end -%><% end -%>
7
+ def self.permitted_params
8
+ [<%= attributes.collect { |attribute| ":#{attribute.column_name}" }.join(', ') %>]
9
+ end
10
+
11
+ def self.display_name
12
+ '<%= class_name.titleize %>'
13
+ end
14
+
15
+ <% if class_name.match(/image/i) -%>
16
+ def self.display_icon
17
+ 'glyphicon glyphicon-picture'
18
+ end
19
+ <% elsif class_name.match(/video/i) -%>
20
+ def self.display_icon
21
+ 'glyphicon glyphicon-play'
22
+ end
23
+ <% elsif class_name.match(/title/i) -%>
24
+ def self.display_icon
25
+ 'glyphicon glyphicon-font'
26
+ end
27
+ <% elsif class_name.match(/text/i) -%>
28
+ def self.display_icon
29
+ 'glyphicon glyphicon-align-left'
30
+ end
31
+ <% elsif class_name.match(/accordion/i) -%>
32
+ def self.display_icon
33
+ 'glyphicon glyphicon-th-list'
34
+ end
35
+ <% else -%>
36
+ # def self.display_icon
37
+ # 'glyphicon glyphicon-align-left'
38
+ # end
39
+ <% end -%>
40
+ end
41
+ <% end -%>
@@ -0,0 +1,2 @@
1
+ Description:
2
+ Forest ininitialization.
@@ -0,0 +1,72 @@
1
+ module Forest
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ # TODO: the install generator should:
7
+ # - seed default settings
8
+ # - block kinds
9
+ # - install forest's migrations, or prompt the user to do this
10
+
11
+ puts "[Forest] Install Generator"
12
+
13
+ # Prompt to install migrations
14
+ if ActiveRecord::Base.connection.table_exists? 'settings'
15
+ puts "[Forest] -- Seeding database"
16
+
17
+ # Settings
18
+ puts "[Forest] ---- Creating default settings"
19
+
20
+ if Setting.find_by_title('Site Title').blank?
21
+ Setting.create(title: 'Site Title', value: 'Default Site Title', value_type: 'string')
22
+ end
23
+
24
+ if Setting.find_by_title('Description').blank?
25
+ Setting.create(title: 'Description', value: 'A Site Built With Forest')
26
+ end
27
+
28
+ if Setting.find_by_title('Featured Image').blank?
29
+ Setting.create(title: 'Featured Image', value: nil, value_type: 'image', description: "The featured image may be used when sharing the site on social media.")
30
+ end
31
+
32
+ # TODO
33
+ # if Setting.find_by_title('Locales').blank?
34
+ # Setting.create(title: 'Locales', value: [:en], value_type: 'array')
35
+ # end
36
+
37
+ # User groups
38
+ puts "[Forest] ---- Creating user groups"
39
+
40
+ UserGroup.find_or_create_by(name: 'admin')
41
+ UserGroup.find_or_create_by(name: 'editor')
42
+ UserGroup.find_or_create_by(name: 'contributor')
43
+
44
+ # Block layouts
45
+ puts "[Forest] ---- Creating default block layouts"
46
+ if BlockLayout.find_by_slug('default').blank?
47
+ BlockLayout.create(slug: 'default', display_name: 'Content Blocks', description: "")
48
+ end
49
+
50
+ puts "[Forest]"
51
+ puts "[Forest] 🌲 all done!"
52
+ puts "[Forest]"
53
+ puts "[Forest] Post-install"
54
+
55
+ # Application config
56
+ puts "[Forest] -- Add the following to application.rb"
57
+ puts '[Forest] config.autoload_paths << "#{config.root}/app/models/blocks"'
58
+
59
+ # Create your first block
60
+ puts "[Forest] -- Create a Block by running this command:"
61
+ puts '[Forest] rails g forest:block TextBlock text:text'
62
+
63
+ # Visit the site and create an admin user
64
+ puts "[Forest] -- Visit the admin area of the website at localhost:3000/admin to create the admin user."
65
+ else
66
+ puts "[Forest] -- ✋ Import Forest's migrations by running the following command."
67
+ puts "[Forest] -- After installing migrations, run this generator again to seed the database."
68
+ puts "[Forest] rails railties:install:migrations"
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Generates a Forest scaffold for a new object type.
3
+
4
+ Example:
5
+ rails generate scaffold Artist first_name:string last_name:string bio:text
6
+
7
+ This will create:
8
+ TODO
@@ -0,0 +1,133 @@
1
+ require "rails/generators/rails/resource/resource_generator"
2
+
3
+ class Forest::ScaffoldGenerator < Rails::Generators::NamedBase
4
+ include Rails::Generators::Migration
5
+
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ argument :attributes, type: :array, default: [], banner: "field[:type][:index] field[:type][:index]"
9
+ class_option :skip_public, type: :boolean, default: false, description: 'Skip public controller and views'
10
+ class_option :skip_blockable, type: :boolean, default: false, description: 'Skip blockable concern'
11
+ class_option :skip_statusable, type: :boolean, default: false, description: 'Skip statusable concern'
12
+ class_option :skip_sluggable, type: :boolean, default: false, description: 'Skip sluggable concern'
13
+
14
+ def self.next_migration_number(dirname)
15
+ next_migration_number = current_migration_number(dirname) + 1
16
+ ActiveRecord::Migration.next_migration_number(next_migration_number)
17
+ end
18
+
19
+ def create_model_file
20
+ template 'model.rb', File.join('app/models', "#{file_name}.rb")
21
+ end
22
+
23
+ def create_view_files
24
+ admin_views.each do |view|
25
+ filename = "#{view}.html.erb"
26
+ template "views/admin/#{filename}", File.join("app/views/admin", plural_name, filename)
27
+ end
28
+
29
+ template "views/admin/index.json.jbuilder", File.join("app/views/admin", plural_name, 'index.json.jbuilder')
30
+
31
+ unless options.skip_public?
32
+ public_views.each do |view|
33
+ filename = "#{view}.html.erb"
34
+ template "views/public/#{filename}", File.join("app/views", plural_name, filename)
35
+ end
36
+ end
37
+ end
38
+
39
+ def create_migration_file
40
+ set_local_assigns!
41
+ validate_file_name!
42
+ migration_template 'create_table_migration.rb', "db/migrate/create_#{table_name}.rb"
43
+ end
44
+
45
+ def create_controller
46
+ template 'admin_controller.rb', "app/controllers/admin/#{plural_name}_controller.rb"
47
+
48
+ unless options.skip_public?
49
+ template 'controller.rb', "app/controllers/#{plural_name}_controller.rb"
50
+ end
51
+
52
+ route_lines = []
53
+ route_lines << "# TODO: sort these new admin routes"
54
+ route_lines << "namespace :admin do"
55
+ route_lines << " resources :#{plural_name}"
56
+ route_lines << "end\n"
57
+
58
+ unless options.skip_public?
59
+ route_lines << "# TODO: sort these new public routes"
60
+ route_lines << "resources :#{plural_name}, only: [:index, :show]\n\n"
61
+ end
62
+
63
+ route route_lines.join("\n")
64
+ end
65
+
66
+ def create_policy
67
+ template 'policy.rb', "app/policies/#{singular_name}_policy.rb"
68
+ end
69
+
70
+ private
71
+
72
+ attr_reader :migration_action, :join_tables
73
+
74
+ # Sets the default migration template that is being used for the generation of the migration.
75
+ # Depending on command line arguments, the migration template and the table name instance
76
+ # variables are set up.
77
+ def set_local_assigns!
78
+ @migration_template = "migration.rb"
79
+ case file_name
80
+ when /^(add|remove)_.*_(?:to|from)_(.*)/
81
+ @migration_action = $1
82
+ @table_name = normalize_table_name($2)
83
+ when /join_table/
84
+ if attributes.length == 2
85
+ @migration_action = "join"
86
+ @join_tables = pluralize_table_names? ? attributes.map(&:plural_name) : attributes.map(&:singular_name)
87
+
88
+ set_index_names
89
+ end
90
+ when /^create_(.+)/
91
+ @table_name = normalize_table_name($1)
92
+ @migration_template = "create_table_migration.rb"
93
+ end
94
+ end
95
+
96
+ def set_index_names
97
+ attributes.each_with_index do |attr, i|
98
+ attr.index_name = [attr, attributes[i - 1]].map { |a| index_name_for(a) }
99
+ end
100
+ end
101
+
102
+ def index_name_for(attribute)
103
+ if attribute.foreign_key?
104
+ attribute.name
105
+ else
106
+ attribute.name.singularize.foreign_key
107
+ end.to_sym
108
+ end
109
+
110
+ def attributes_with_index
111
+ attributes.select { |a| !a.reference? && a.has_index? }
112
+ end
113
+
114
+ # A migration file name can only contain underscores (_), lowercase characters,
115
+ # and numbers 0-9. Any other file name will raise an IllegalMigrationNameError.
116
+ def validate_file_name!
117
+ unless /^[_a-z0-9]+$/.match?(file_name)
118
+ raise IllegalMigrationNameError.new(file_name)
119
+ end
120
+ end
121
+
122
+ def normalize_table_name(_table_name)
123
+ pluralize_table_names? ? _table_name.pluralize : _table_name.singularize
124
+ end
125
+
126
+ def admin_views
127
+ %w(_form edit index new show)
128
+ end
129
+
130
+ def public_views
131
+ %w(index show)
132
+ end
133
+ end