lc_alchemy_cms 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (744) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +23 -0
  3. data/.gitignore +21 -0
  4. data/.hound.yml +2 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +861 -0
  7. data/.teatro.yml +7 -0
  8. data/.travis.yml +27 -0
  9. data/.yardopts +5 -0
  10. data/CODE_OF_CONDUCT.md +13 -0
  11. data/CONTRIBUTING.md +73 -0
  12. data/Gemfile +34 -0
  13. data/LICENSE +27 -0
  14. data/README.md +297 -0
  15. data/Rakefile +48 -0
  16. data/alchemy_cms.gemspec +81 -0
  17. data/app/assets/fonts/alchemy/icons.eot +0 -0
  18. data/app/assets/fonts/alchemy/icons.svg +71 -0
  19. data/app/assets/fonts/alchemy/icons.ttf +0 -0
  20. data/app/assets/fonts/alchemy/icons.woff +0 -0
  21. data/app/assets/images/alchemy/alchemy-logo.svg +70 -0
  22. data/app/assets/images/alchemy/favicon.ico +0 -0
  23. data/app/assets/images/alchemy/icon.svg +14 -0
  24. data/app/assets/images/alchemy/icons.png +0 -0
  25. data/app/assets/images/alchemy/lupe.cur +0 -0
  26. data/app/assets/images/alchemy/ui-icons_666666_256x240.png +0 -0
  27. data/app/assets/images/sassy-ie-overlay.png +0 -0
  28. data/app/assets/javascripts/alchemy/alchemy.autocomplete.js.coffee +30 -0
  29. data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +142 -0
  30. data/app/assets/javascripts/alchemy/alchemy.browser.js.coffee +22 -0
  31. data/app/assets/javascripts/alchemy/alchemy.buttons.js.coffee +32 -0
  32. data/app/assets/javascripts/alchemy/alchemy.char_counter.js.coffee +19 -0
  33. data/app/assets/javascripts/alchemy/alchemy.confirm_dialog.js.coffee +85 -0
  34. data/app/assets/javascripts/alchemy/alchemy.custom.js +1 -0
  35. data/app/assets/javascripts/alchemy/alchemy.datepicker.js.coffee +31 -0
  36. data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +266 -0
  37. data/app/assets/javascripts/alchemy/alchemy.dirty.js.coffee +70 -0
  38. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +84 -0
  39. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +138 -0
  40. data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +89 -0
  41. data/app/assets/javascripts/alchemy/alchemy.file_progress.js.coffee +63 -0
  42. data/app/assets/javascripts/alchemy/alchemy.growler.js.coffee +27 -0
  43. data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +22 -0
  44. data/app/assets/javascripts/alchemy/alchemy.hotkeys.js.coffee +49 -0
  45. data/app/assets/javascripts/alchemy/alchemy.html5.js +22 -0
  46. data/app/assets/javascripts/alchemy/alchemy.i18n.js.coffee +26 -0
  47. data/app/assets/javascripts/alchemy/alchemy.image_cropper.js.coffee +44 -0
  48. data/app/assets/javascripts/alchemy/alchemy.initializer.js.coffee +63 -0
  49. data/app/assets/javascripts/alchemy/alchemy.jquery_loader.js +42 -0
  50. data/app/assets/javascripts/alchemy/alchemy.js +52 -0
  51. data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +250 -0
  52. data/app/assets/javascripts/alchemy/alchemy.list_filter.js.coffee +49 -0
  53. data/app/assets/javascripts/alchemy/alchemy.page_sorter.js +48 -0
  54. data/app/assets/javascripts/alchemy/alchemy.preview.js.coffee +106 -0
  55. data/app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee +58 -0
  56. data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +50 -0
  57. data/app/assets/javascripts/alchemy/alchemy.spinner.js.coffee +49 -0
  58. data/app/assets/javascripts/alchemy/alchemy.string_extension.js.coffee +11 -0
  59. data/app/assets/javascripts/alchemy/alchemy.tinymce.js.coffee +66 -0
  60. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +132 -0
  61. data/app/assets/javascripts/alchemy/alchemy.uploader.js.coffee +102 -0
  62. data/app/assets/javascripts/alchemy/alchemy.windows.js.coffee +42 -0
  63. data/app/assets/javascripts/alchemy/menubar.js.coffee +8 -0
  64. data/app/assets/javascripts/alchemy/preview.js +1 -0
  65. data/app/assets/javascripts/tinymce/plugins/alchemy_link/plugin.min.js +19 -0
  66. data/app/assets/stylesheets/alchemy/_defaults.scss +8 -0
  67. data/app/assets/stylesheets/alchemy/_extends.scss +93 -0
  68. data/app/assets/stylesheets/alchemy/_mixins.scss +112 -0
  69. data/app/assets/stylesheets/alchemy/_variables.scss +61 -0
  70. data/app/assets/stylesheets/alchemy/admin.scss +31 -0
  71. data/app/assets/stylesheets/alchemy/archive.scss +436 -0
  72. data/app/assets/stylesheets/alchemy/base.scss +609 -0
  73. data/app/assets/stylesheets/alchemy/buttons.scss +259 -0
  74. data/app/assets/stylesheets/alchemy/custom.scss +1 -0
  75. data/app/assets/stylesheets/alchemy/dashboard.scss +104 -0
  76. data/app/assets/stylesheets/alchemy/dialogs.scss +214 -0
  77. data/app/assets/stylesheets/alchemy/elements.scss +772 -0
  78. data/app/assets/stylesheets/alchemy/errors.scss +39 -0
  79. data/app/assets/stylesheets/alchemy/flash.scss +65 -0
  80. data/app/assets/stylesheets/alchemy/form_fields.scss +89 -0
  81. data/app/assets/stylesheets/alchemy/forms.scss +193 -0
  82. data/app/assets/stylesheets/alchemy/frame.scss +301 -0
  83. data/app/assets/stylesheets/alchemy/icon-font.scss +67 -0
  84. data/app/assets/stylesheets/alchemy/icons.scss +324 -0
  85. data/app/assets/stylesheets/alchemy/jquery-ui.scss +1511 -0
  86. data/app/assets/stylesheets/alchemy/menubar.scss +81 -0
  87. data/app/assets/stylesheets/alchemy/modules.scss +33 -0
  88. data/app/assets/stylesheets/alchemy/notices.scss +64 -0
  89. data/app/assets/stylesheets/alchemy/pagination.scss +65 -0
  90. data/app/assets/stylesheets/alchemy/print.scss +34 -0
  91. data/app/assets/stylesheets/alchemy/search.scss +73 -0
  92. data/app/assets/stylesheets/alchemy/selects.scss +235 -0
  93. data/app/assets/stylesheets/alchemy/sitemap.scss +385 -0
  94. data/app/assets/stylesheets/alchemy/tables.scss +218 -0
  95. data/app/assets/stylesheets/alchemy/toolbar.scss +146 -0
  96. data/app/assets/stylesheets/alchemy/upload.scss +121 -0
  97. data/app/assets/stylesheets/tinymce/skins/alchemy/content.min.css.scss +90 -0
  98. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/readme.md +1 -0
  99. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.eot +0 -0
  100. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.svg +175 -0
  101. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.ttf +0 -0
  102. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.woff +0 -0
  103. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.eot +0 -0
  104. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.svg +153 -0
  105. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.ttf +0 -0
  106. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.woff +0 -0
  107. data/app/assets/stylesheets/tinymce/skins/alchemy/img/anchor.gif +0 -0
  108. data/app/assets/stylesheets/tinymce/skins/alchemy/img/loader.gif +0 -0
  109. data/app/assets/stylesheets/tinymce/skins/alchemy/img/object.gif +0 -0
  110. data/app/assets/stylesheets/tinymce/skins/alchemy/img/trans.gif +0 -0
  111. data/app/assets/stylesheets/tinymce/skins/alchemy/img/wline.gif +0 -0
  112. data/app/assets/stylesheets/tinymce/skins/alchemy/skin.ie7.min.css +1 -0
  113. data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +1810 -0
  114. data/app/controllers/alchemy/admin/attachments_controller.rb +106 -0
  115. data/app/controllers/alchemy/admin/base_controller.rb +168 -0
  116. data/app/controllers/alchemy/admin/clipboard_controller.rb +51 -0
  117. data/app/controllers/alchemy/admin/contents_controller.rb +76 -0
  118. data/app/controllers/alchemy/admin/dashboard_controller.rb +89 -0
  119. data/app/controllers/alchemy/admin/elements_controller.rb +190 -0
  120. data/app/controllers/alchemy/admin/essence_files_controller.rb +47 -0
  121. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +120 -0
  122. data/app/controllers/alchemy/admin/languages_controller.rb +17 -0
  123. data/app/controllers/alchemy/admin/layoutpages_controller.rb +19 -0
  124. data/app/controllers/alchemy/admin/legacy_page_urls_controller.rb +39 -0
  125. data/app/controllers/alchemy/admin/pages_controller.rb +359 -0
  126. data/app/controllers/alchemy/admin/pictures_controller.rb +168 -0
  127. data/app/controllers/alchemy/admin/resources_controller.rb +185 -0
  128. data/app/controllers/alchemy/admin/sites_controller.rb +6 -0
  129. data/app/controllers/alchemy/admin/tags_controller.rb +76 -0
  130. data/app/controllers/alchemy/admin/trash_controller.rb +27 -0
  131. data/app/controllers/alchemy/api/base_controller.rb +19 -0
  132. data/app/controllers/alchemy/api/contents_controller.rb +35 -0
  133. data/app/controllers/alchemy/api/elements_controller.rb +29 -0
  134. data/app/controllers/alchemy/api/pages_controller.rb +32 -0
  135. data/app/controllers/alchemy/attachments_controller.rb +35 -0
  136. data/app/controllers/alchemy/base_controller.rb +106 -0
  137. data/app/controllers/alchemy/elements_controller.rb +27 -0
  138. data/app/controllers/alchemy/messages_controller.rb +114 -0
  139. data/app/controllers/alchemy/pages_controller.rb +211 -0
  140. data/app/controllers/alchemy/pictures_controller.rb +82 -0
  141. data/app/helpers/alchemy/admin/attachments_helper.rb +12 -0
  142. data/app/helpers/alchemy/admin/base_helper.rb +471 -0
  143. data/app/helpers/alchemy/admin/contents_helper.rb +113 -0
  144. data/app/helpers/alchemy/admin/elements_helper.rb +134 -0
  145. data/app/helpers/alchemy/admin/essences_helper.rb +120 -0
  146. data/app/helpers/alchemy/admin/form_helper.rb +30 -0
  147. data/app/helpers/alchemy/admin/navigation_helper.rb +238 -0
  148. data/app/helpers/alchemy/admin/pages_helper.rb +70 -0
  149. data/app/helpers/alchemy/admin/pictures_helper.rb +30 -0
  150. data/app/helpers/alchemy/admin/tags_helper.rb +102 -0
  151. data/app/helpers/alchemy/base_helper.rb +81 -0
  152. data/app/helpers/alchemy/elements_block_helper.rb +162 -0
  153. data/app/helpers/alchemy/elements_helper.rb +291 -0
  154. data/app/helpers/alchemy/essences_helper.rb +138 -0
  155. data/app/helpers/alchemy/pages_helper.rb +417 -0
  156. data/app/helpers/alchemy/url_helper.rb +76 -0
  157. data/app/mailers/alchemy/messages.rb +15 -0
  158. data/app/models/alchemy.rb +7 -0
  159. data/app/models/alchemy/attachment.rb +129 -0
  160. data/app/models/alchemy/cell.rb +94 -0
  161. data/app/models/alchemy/content.rb +255 -0
  162. data/app/models/alchemy/content/factory.rb +190 -0
  163. data/app/models/alchemy/element.rb +513 -0
  164. data/app/models/alchemy/element/definitions.rb +52 -0
  165. data/app/models/alchemy/element/presenters.rb +87 -0
  166. data/app/models/alchemy/element_to_page.rb +7 -0
  167. data/app/models/alchemy/essence_boolean.rb +19 -0
  168. data/app/models/alchemy/essence_date.rb +24 -0
  169. data/app/models/alchemy/essence_file.rb +42 -0
  170. data/app/models/alchemy/essence_html.rb +23 -0
  171. data/app/models/alchemy/essence_link.rb +20 -0
  172. data/app/models/alchemy/essence_picture.rb +152 -0
  173. data/app/models/alchemy/essence_richtext.rb +47 -0
  174. data/app/models/alchemy/essence_select.rb +18 -0
  175. data/app/models/alchemy/essence_text.rb +22 -0
  176. data/app/models/alchemy/folded_page.rb +16 -0
  177. data/app/models/alchemy/language.rb +144 -0
  178. data/app/models/alchemy/language/code.rb +22 -0
  179. data/app/models/alchemy/legacy_page_url.rb +20 -0
  180. data/app/models/alchemy/message.rb +40 -0
  181. data/app/models/alchemy/page.rb +409 -0
  182. data/app/models/alchemy/page/page_cells.rb +71 -0
  183. data/app/models/alchemy/page/page_elements.rb +272 -0
  184. data/app/models/alchemy/page/page_naming.rb +122 -0
  185. data/app/models/alchemy/page/page_natures.rb +114 -0
  186. data/app/models/alchemy/page/page_scopes.rb +95 -0
  187. data/app/models/alchemy/page/page_users.rb +58 -0
  188. data/app/models/alchemy/picture.rb +220 -0
  189. data/app/models/alchemy/picture/sweeping.rb +17 -0
  190. data/app/models/alchemy/picture/transformations.rb +256 -0
  191. data/app/models/alchemy/site.rb +91 -0
  192. data/app/models/alchemy/site/layout.rb +38 -0
  193. data/app/models/alchemy/tag.rb +24 -0
  194. data/app/models/alchemy/translations.rb +7 -0
  195. data/app/models/alchemy/translations/essence_body_updater.rb +64 -0
  196. data/app/models/alchemy/translations/translation_pusher.rb +18 -0
  197. data/app/models/alchemy/tree_node.rb +4 -0
  198. data/app/serializers/alchemy/attachment_serializer.rb +15 -0
  199. data/app/serializers/alchemy/cell_serializer.rb +18 -0
  200. data/app/serializers/alchemy/content_serializer.rb +20 -0
  201. data/app/serializers/alchemy/element_serializer.rb +20 -0
  202. data/app/serializers/alchemy/essence_boolean_serializer.rb +11 -0
  203. data/app/serializers/alchemy/essence_date_serializer.rb +11 -0
  204. data/app/serializers/alchemy/essence_file_serializer.rb +12 -0
  205. data/app/serializers/alchemy/essence_html_serializer.rb +11 -0
  206. data/app/serializers/alchemy/essence_link_serializer.rb +14 -0
  207. data/app/serializers/alchemy/essence_picture_serializer.rb +28 -0
  208. data/app/serializers/alchemy/essence_richtext_serializer.rb +12 -0
  209. data/app/serializers/alchemy/essence_select_serializer.rb +11 -0
  210. data/app/serializers/alchemy/essence_text_serializer.rb +22 -0
  211. data/app/serializers/alchemy/legacy_element_serializer.rb +17 -0
  212. data/app/serializers/alchemy/page_serializer.rb +29 -0
  213. data/app/serializers/alchemy/picture_serializer.rb +16 -0
  214. data/app/views/alchemy/_menubar.html.erb +16 -0
  215. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +32 -0
  216. data/app/views/alchemy/admin/attachments/_attachment.html.erb +63 -0
  217. data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +15 -0
  218. data/app/views/alchemy/admin/attachments/_files_list.html.erb +39 -0
  219. data/app/views/alchemy/admin/attachments/_overlay_file_list.html.erb +11 -0
  220. data/app/views/alchemy/admin/attachments/_tag_list.html.erb +14 -0
  221. data/app/views/alchemy/admin/attachments/archive_overlay.js.erb +7 -0
  222. data/app/views/alchemy/admin/attachments/create.js.erb +11 -0
  223. data/app/views/alchemy/admin/attachments/destroy.js.erb +1 -0
  224. data/app/views/alchemy/admin/attachments/edit.html.erb +10 -0
  225. data/app/views/alchemy/admin/attachments/index.html.erb +29 -0
  226. data/app/views/alchemy/admin/attachments/new.html.erb +14 -0
  227. data/app/views/alchemy/admin/attachments/show.html.erb +3 -0
  228. data/app/views/alchemy/admin/clipboard/clear.js.erb +3 -0
  229. data/app/views/alchemy/admin/clipboard/index.html.erb +22 -0
  230. data/app/views/alchemy/admin/clipboard/insert.js.erb +19 -0
  231. data/app/views/alchemy/admin/clipboard/remove.js.erb +10 -0
  232. data/app/views/alchemy/admin/contents/_missing.html.erb +19 -0
  233. data/app/views/alchemy/admin/contents/create.js.erb +56 -0
  234. data/app/views/alchemy/admin/contents/destroy.js.erb +4 -0
  235. data/app/views/alchemy/admin/contents/new.html.erb +11 -0
  236. data/app/views/alchemy/admin/contents/order.js.erb +3 -0
  237. data/app/views/alchemy/admin/dashboard/_locked_pages.html.erb +38 -0
  238. data/app/views/alchemy/admin/dashboard/_recent_pages.html.erb +22 -0
  239. data/app/views/alchemy/admin/dashboard/_sites.html.erb +23 -0
  240. data/app/views/alchemy/admin/dashboard/_users.html.erb +19 -0
  241. data/app/views/alchemy/admin/dashboard/help.html.erb +21 -0
  242. data/app/views/alchemy/admin/dashboard/index.html.erb +44 -0
  243. data/app/views/alchemy/admin/dashboard/info.html.erb +64 -0
  244. data/app/views/alchemy/admin/elements/_add_picture.html.erb +14 -0
  245. data/app/views/alchemy/admin/elements/_element.html.erb +23 -0
  246. data/app/views/alchemy/admin/elements/_element_foot.html.erb +36 -0
  247. data/app/views/alchemy/admin/elements/_element_head.html.erb +23 -0
  248. data/app/views/alchemy/admin/elements/_new_element_form.html.erb +26 -0
  249. data/app/views/alchemy/admin/elements/_picture_gallery_editor.html.erb +24 -0
  250. data/app/views/alchemy/admin/elements/_refresh_editor.js.erb +8 -0
  251. data/app/views/alchemy/admin/elements/create.js.erb +46 -0
  252. data/app/views/alchemy/admin/elements/fold.js.erb +28 -0
  253. data/app/views/alchemy/admin/elements/index.html.erb +26 -0
  254. data/app/views/alchemy/admin/elements/list.html.erb +16 -0
  255. data/app/views/alchemy/admin/elements/new.html.erb +25 -0
  256. data/app/views/alchemy/admin/elements/order.js.erb +14 -0
  257. data/app/views/alchemy/admin/elements/trash.js.erb +12 -0
  258. data/app/views/alchemy/admin/elements/update.js.erb +28 -0
  259. data/app/views/alchemy/admin/essence_files/assign.js.erb +9 -0
  260. data/app/views/alchemy/admin/essence_files/edit.html.erb +18 -0
  261. data/app/views/alchemy/admin/essence_pictures/assign.js.erb +18 -0
  262. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +50 -0
  263. data/app/views/alchemy/admin/essence_pictures/destroy.js.erb +24 -0
  264. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +28 -0
  265. data/app/views/alchemy/admin/essence_pictures/save_link.js.erb +3 -0
  266. data/app/views/alchemy/admin/essence_pictures/update.js.erb +9 -0
  267. data/app/views/alchemy/admin/languages/_form.html.erb +14 -0
  268. data/app/views/alchemy/admin/languages/_language.html.erb +42 -0
  269. data/app/views/alchemy/admin/languages/_table.html.erb +37 -0
  270. data/app/views/alchemy/admin/languages/index.html.erb +23 -0
  271. data/app/views/alchemy/admin/layoutpages/_layoutpage.html.erb +63 -0
  272. data/app/views/alchemy/admin/layoutpages/edit.html.erb +15 -0
  273. data/app/views/alchemy/admin/layoutpages/index.html.erb +41 -0
  274. data/app/views/alchemy/admin/leave.html.erb +11 -0
  275. data/app/views/alchemy/admin/legacy_page_urls/_form.html.erb +5 -0
  276. data/app/views/alchemy/admin/legacy_page_urls/_label.html.erb +1 -0
  277. data/app/views/alchemy/admin/legacy_page_urls/_legacy_page_url.html.erb +13 -0
  278. data/app/views/alchemy/admin/legacy_page_urls/_new.html.erb +20 -0
  279. data/app/views/alchemy/admin/legacy_page_urls/create.js.erb +10 -0
  280. data/app/views/alchemy/admin/legacy_page_urls/destroy.js.erb +6 -0
  281. data/app/views/alchemy/admin/legacy_page_urls/update.js.erb +2 -0
  282. data/app/views/alchemy/admin/pages/_create_language_form.html.erb +54 -0
  283. data/app/views/alchemy/admin/pages/_external_link.html.erb +31 -0
  284. data/app/views/alchemy/admin/pages/_file_link.html.erb +31 -0
  285. data/app/views/alchemy/admin/pages/_form.html.erb +62 -0
  286. data/app/views/alchemy/admin/pages/_internal_link.html.erb +41 -0
  287. data/app/views/alchemy/admin/pages/_legacy_urls.html.erb +23 -0
  288. data/app/views/alchemy/admin/pages/_locked_page.html.erb +24 -0
  289. data/app/views/alchemy/admin/pages/_new_page_form.html.erb +11 -0
  290. data/app/views/alchemy/admin/pages/_page.html.erb +112 -0
  291. data/app/views/alchemy/admin/pages/_page_for_links.html.erb +45 -0
  292. data/app/views/alchemy/admin/pages/_page_status.html.erb +14 -0
  293. data/app/views/alchemy/admin/pages/_sitemap.html.erb +8 -0
  294. data/app/views/alchemy/admin/pages/_tinymce_custom_config.html.erb +13 -0
  295. data/app/views/alchemy/admin/pages/configure.html.erb +16 -0
  296. data/app/views/alchemy/admin/pages/configure_external.html.erb +33 -0
  297. data/app/views/alchemy/admin/pages/destroy.js.erb +19 -0
  298. data/app/views/alchemy/admin/pages/edit.html.erb +206 -0
  299. data/app/views/alchemy/admin/pages/flush.js.erb +2 -0
  300. data/app/views/alchemy/admin/pages/fold.js.erb +3 -0
  301. data/app/views/alchemy/admin/pages/index.html.erb +101 -0
  302. data/app/views/alchemy/admin/pages/info.html.erb +43 -0
  303. data/app/views/alchemy/admin/pages/link.html.erb +16 -0
  304. data/app/views/alchemy/admin/pages/locked.html.erb +3 -0
  305. data/app/views/alchemy/admin/pages/new.html.erb +26 -0
  306. data/app/views/alchemy/admin/pages/show.html.erb +1 -0
  307. data/app/views/alchemy/admin/pages/sort.js.erb +5 -0
  308. data/app/views/alchemy/admin/pages/unlock.js.erb +8 -0
  309. data/app/views/alchemy/admin/pages/update.js.erb +37 -0
  310. data/app/views/alchemy/admin/partials/_autocomplete_tag_list.html.erb +1 -0
  311. data/app/views/alchemy/admin/partials/_flash.html.erb +4 -0
  312. data/app/views/alchemy/admin/partials/_flash_notices.html.erb +5 -0
  313. data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +11 -0
  314. data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +12 -0
  315. data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +33 -0
  316. data/app/views/alchemy/admin/partials/_routes.html.erb +25 -0
  317. data/app/views/alchemy/admin/partials/_search_form.html.erb +20 -0
  318. data/app/views/alchemy/admin/partials/_sub_navigation.html.erb +8 -0
  319. data/app/views/alchemy/admin/partials/_toolbar_button.html.erb +25 -0
  320. data/app/views/alchemy/admin/partials/_upload_form.html.erb +67 -0
  321. data/app/views/alchemy/admin/pictures/_archive.html.erb +53 -0
  322. data/app/views/alchemy/admin/pictures/_archive_overlay.html.erb +14 -0
  323. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +78 -0
  324. data/app/views/alchemy/admin/pictures/_filter_bar.html.erb +33 -0
  325. data/app/views/alchemy/admin/pictures/_overlay_picture_list.html.erb +11 -0
  326. data/app/views/alchemy/admin/pictures/_picture.html.erb +87 -0
  327. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +28 -0
  328. data/app/views/alchemy/admin/pictures/_tag_list.html.erb +16 -0
  329. data/app/views/alchemy/admin/pictures/archive_overlay.js.erb +8 -0
  330. data/app/views/alchemy/admin/pictures/edit.html.erb +13 -0
  331. data/app/views/alchemy/admin/pictures/edit_multiple.html.erb +30 -0
  332. data/app/views/alchemy/admin/pictures/flush.js.erb +2 -0
  333. data/app/views/alchemy/admin/pictures/index.html.erb +109 -0
  334. data/app/views/alchemy/admin/pictures/index.js.erb +3 -0
  335. data/app/views/alchemy/admin/pictures/info.html.erb +38 -0
  336. data/app/views/alchemy/admin/pictures/new.html.erb +16 -0
  337. data/app/views/alchemy/admin/pictures/show.html.erb +11 -0
  338. data/app/views/alchemy/admin/resources/_form.html.erb +13 -0
  339. data/app/views/alchemy/admin/resources/_resource.html.erb +30 -0
  340. data/app/views/alchemy/admin/resources/_table.html.erb +25 -0
  341. data/app/views/alchemy/admin/resources/edit.html.erb +1 -0
  342. data/app/views/alchemy/admin/resources/index.csv.erb +13 -0
  343. data/app/views/alchemy/admin/resources/index.html.erb +32 -0
  344. data/app/views/alchemy/admin/resources/new.html.erb +1 -0
  345. data/app/views/alchemy/admin/sites/index.html.erb +23 -0
  346. data/app/views/alchemy/admin/tags/_radio_tag.html.erb +6 -0
  347. data/app/views/alchemy/admin/tags/_tag.html.erb +30 -0
  348. data/app/views/alchemy/admin/tags/edit.html.erb +24 -0
  349. data/app/views/alchemy/admin/tags/index.html.erb +52 -0
  350. data/app/views/alchemy/admin/tags/new.html.erb +7 -0
  351. data/app/views/alchemy/admin/trash/clear.js.erb +4 -0
  352. data/app/views/alchemy/admin/trash/index.html.erb +29 -0
  353. data/app/views/alchemy/attachments/show.html.erb +1 -0
  354. data/app/views/alchemy/base/500.html.erb +26 -0
  355. data/app/views/alchemy/base/error_notice.html.erb +1 -0
  356. data/app/views/alchemy/base/error_notice.js.erb +2 -0
  357. data/app/views/alchemy/base/permission_denied.js.erb +3 -0
  358. data/app/views/alchemy/base/redirect.js.erb +12 -0
  359. data/app/views/alchemy/base/update.js.erb +5 -0
  360. data/app/views/alchemy/breadcrumb/_page.html.erb +16 -0
  361. data/app/views/alchemy/breadcrumb/_separator.html.erb +1 -0
  362. data/app/views/alchemy/breadcrumb/_wrapper.html.erb +13 -0
  363. data/app/views/alchemy/elements/_editor_not_found.html.erb +5 -0
  364. data/app/views/alchemy/elements/_view_not_found.html.erb +1 -0
  365. data/app/views/alchemy/elements/show.html.erb +1 -0
  366. data/app/views/alchemy/elements/show.js.erb +1 -0
  367. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +16 -0
  368. data/app/views/alchemy/essences/_essence_boolean_view.html.erb +3 -0
  369. data/app/views/alchemy/essences/_essence_date_editor.html.erb +19 -0
  370. data/app/views/alchemy/essences/_essence_date_view.html.erb +11 -0
  371. data/app/views/alchemy/essences/_essence_file_editor.html.erb +57 -0
  372. data/app/views/alchemy/essences/_essence_file_view.html.erb +10 -0
  373. data/app/views/alchemy/essences/_essence_html_editor.html.erb +9 -0
  374. data/app/views/alchemy/essences/_essence_html_view.html.erb +3 -0
  375. data/app/views/alchemy/essences/_essence_link_editor.html.erb +25 -0
  376. data/app/views/alchemy/essences/_essence_link_view.html.erb +11 -0
  377. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +59 -0
  378. data/app/views/alchemy/essences/_essence_picture_view.html.erb +5 -0
  379. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +13 -0
  380. data/app/views/alchemy/essences/_essence_richtext_view.html.erb +5 -0
  381. data/app/views/alchemy/essences/_essence_select_editor.html.erb +25 -0
  382. data/app/views/alchemy/essences/_essence_select_view.html.erb +3 -0
  383. data/app/views/alchemy/essences/_essence_text_editor.html.erb +18 -0
  384. data/app/views/alchemy/essences/_essence_text_view.html.erb +18 -0
  385. data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +61 -0
  386. data/app/views/alchemy/essences/shared/_linkable_essence_tools.html.erb +19 -0
  387. data/app/views/alchemy/language_links/_language.html.erb +12 -0
  388. data/app/views/alchemy/language_links/_spacer.html.erb +1 -0
  389. data/app/views/alchemy/messages/contact_form_mail.de.text.erb +12 -0
  390. data/app/views/alchemy/messages/contact_form_mail.en.text.erb +12 -0
  391. data/app/views/alchemy/messages/contact_form_mail.es.text.erb +12 -0
  392. data/app/views/alchemy/messages/new.html.erb +1 -0
  393. data/app/views/alchemy/navigation/_image_link.html.erb +14 -0
  394. data/app/views/alchemy/navigation/_link.html.erb +20 -0
  395. data/app/views/alchemy/navigation/_renderer.html.erb +30 -0
  396. data/app/views/alchemy/pages/show.html.erb +1 -0
  397. data/app/views/alchemy/pages/show.rss.builder +20 -0
  398. data/app/views/alchemy/pages/sitemap.xml.erb +6 -0
  399. data/app/views/kaminari/alchemy/_first_page.html.erb +11 -0
  400. data/app/views/kaminari/alchemy/_gap.html.erb +8 -0
  401. data/app/views/kaminari/alchemy/_last_page.html.erb +11 -0
  402. data/app/views/kaminari/alchemy/_next_page.html.erb +13 -0
  403. data/app/views/kaminari/alchemy/_page.html.erb +14 -0
  404. data/app/views/kaminari/alchemy/_paginator.html.erb +23 -0
  405. data/app/views/kaminari/alchemy/_prev_page.html.erb +13 -0
  406. data/app/views/layouts/alchemy/admin.html.erb +109 -0
  407. data/app/views/layouts/alchemy/sitemap.xml.erb +4 -0
  408. data/bin/alchemy +267 -0
  409. data/bin/rails +8 -0
  410. data/config/alchemy/config.yml +189 -0
  411. data/config/alchemy/modules.yml +88 -0
  412. data/config/initializers/dragonfly.rb +25 -0
  413. data/config/initializers/simple_form.rb +144 -0
  414. data/config/locales/alchemy.de.yml +918 -0
  415. data/config/locales/alchemy.en.yml +920 -0
  416. data/config/locales/alchemy.es.yml +958 -0
  417. data/config/locales/alchemy.fr.yml +942 -0
  418. data/config/locales/alchemy.nl.yml +921 -0
  419. data/config/locales/alchemy.ru.yml +837 -0
  420. data/config/locales/simple_form.de.yml +26 -0
  421. data/config/locales/simple_form.en.yml +25 -0
  422. data/config/locales/simple_form.es.yml +6 -0
  423. data/config/locales/simple_form.fr.yml +26 -0
  424. data/config/locales/simple_form.nl.yml +25 -0
  425. data/config/locales/simple_form.ru.yml +25 -0
  426. data/config/routes.rb +164 -0
  427. data/db/migrate/20130827094554_alchemy_two_point_six.rb +380 -0
  428. data/db/migrate/20130828121054_remove_do_not_index_from_alchemy_essence_texts.rb +5 -0
  429. data/db/migrate/20130828121120_remove_do_not_index_from_alchemy_essence_richtexts.rb +5 -0
  430. data/db/migrate/20130918201742_add_published_at_to_alchemy_pages.rb +5 -0
  431. data/lib/alchemy/auth_accessors.rb +104 -0
  432. data/lib/alchemy/cache_digests/template_tracker.rb +65 -0
  433. data/lib/alchemy/config.rb +65 -0
  434. data/lib/alchemy/configuration_methods.rb +29 -0
  435. data/lib/alchemy/controller_actions.rb +138 -0
  436. data/lib/alchemy/engine.rb +104 -0
  437. data/lib/alchemy/errors.rb +82 -0
  438. data/lib/alchemy/essence.rb +232 -0
  439. data/lib/alchemy/filetypes.rb +33 -0
  440. data/lib/alchemy/forms/builder.rb +23 -0
  441. data/lib/alchemy/hints.rb +57 -0
  442. data/lib/alchemy/i18n.rb +70 -0
  443. data/lib/alchemy/kaminari/scoped_pagination_url_helper.rb +13 -0
  444. data/lib/alchemy/locale.rb +65 -0
  445. data/lib/alchemy/logger.rb +15 -0
  446. data/lib/alchemy/middleware/rescue_old_cookies.rb +27 -0
  447. data/lib/alchemy/modules.rb +75 -0
  448. data/lib/alchemy/mount_point.rb +47 -0
  449. data/lib/alchemy/name_conversions.rb +28 -0
  450. data/lib/alchemy/on_page_layout.rb +58 -0
  451. data/lib/alchemy/page_layout.rb +183 -0
  452. data/lib/alchemy/permissions.rb +221 -0
  453. data/lib/alchemy/picture_attributes.rb +29 -0
  454. data/lib/alchemy/resource.rb +238 -0
  455. data/lib/alchemy/resources_helper.rb +135 -0
  456. data/lib/alchemy/routing_constraints.rb +49 -0
  457. data/lib/alchemy/seeder.rb +53 -0
  458. data/lib/alchemy/shell.rb +102 -0
  459. data/lib/alchemy/ssl_protection.rb +30 -0
  460. data/lib/alchemy/tasks/helpers.rb +83 -0
  461. data/lib/alchemy/test_support/controller_requests.rb +73 -0
  462. data/lib/alchemy/test_support/essence_shared_examples.rb +286 -0
  463. data/lib/alchemy/test_support/factories.rb +147 -0
  464. data/lib/alchemy/test_support/integration_helpers.rb +33 -0
  465. data/lib/alchemy/tinymce.rb +68 -0
  466. data/lib/alchemy/touching.rb +41 -0
  467. data/lib/alchemy/upgrader.rb +80 -0
  468. data/lib/alchemy/upgrader/three_point_one.rb +54 -0
  469. data/lib/alchemy/upgrader/three_point_two.rb +69 -0
  470. data/lib/alchemy/upgrader/three_point_zero.rb +93 -0
  471. data/lib/alchemy/userstamp.rb +10 -0
  472. data/lib/alchemy/version.rb +7 -0
  473. data/lib/alchemy_cms.rb +5 -0
  474. data/lib/rails/generators/alchemy/base.rb +41 -0
  475. data/lib/rails/generators/alchemy/elements/elements_generator.rb +37 -0
  476. data/lib/rails/generators/alchemy/elements/templates/editor.html.erb +14 -0
  477. data/lib/rails/generators/alchemy/elements/templates/editor.html.haml +13 -0
  478. data/lib/rails/generators/alchemy/elements/templates/editor.html.slim +12 -0
  479. data/lib/rails/generators/alchemy/elements/templates/view.html.erb +27 -0
  480. data/lib/rails/generators/alchemy/elements/templates/view.html.haml +20 -0
  481. data/lib/rails/generators/alchemy/elements/templates/view.html.slim +20 -0
  482. data/lib/rails/generators/alchemy/essence/essence_generator.rb +52 -0
  483. data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +17 -0
  484. data/lib/rails/generators/alchemy/essence/templates/view.html.erb +2 -0
  485. data/lib/rails/generators/alchemy/install/files/_article_editor.html.erb +5 -0
  486. data/lib/rails/generators/alchemy/install/files/_article_view.html.erb +7 -0
  487. data/lib/rails/generators/alchemy/install/files/_standard.html.erb +1 -0
  488. data/lib/rails/generators/alchemy/install/files/alchemy.de.yml +31 -0
  489. data/lib/rails/generators/alchemy/install/files/alchemy.elements.css.scss +30 -0
  490. data/lib/rails/generators/alchemy/install/files/alchemy.en.yml +31 -0
  491. data/lib/rails/generators/alchemy/install/files/alchemy.es.yml +31 -0
  492. data/lib/rails/generators/alchemy/install/files/application.html.erb +14 -0
  493. data/lib/rails/generators/alchemy/install/install_generator.rb +69 -0
  494. data/lib/rails/generators/alchemy/install/templates/elements.yml.tt +21 -0
  495. data/lib/rails/generators/alchemy/install/templates/page_layouts.yml.tt +10 -0
  496. data/lib/rails/generators/alchemy/module/module_generator.rb +30 -0
  497. data/lib/rails/generators/alchemy/module/templates/ability.rb.tt +11 -0
  498. data/lib/rails/generators/alchemy/module/templates/controller.rb.tt +2 -0
  499. data/lib/rails/generators/alchemy/module/templates/module_config.rb.tt +17 -0
  500. data/lib/rails/generators/alchemy/page_layouts/page_layouts_generator.rb +24 -0
  501. data/lib/rails/generators/alchemy/page_layouts/templates/layout.html.erb +1 -0
  502. data/lib/rails/generators/alchemy/page_layouts/templates/layout.html.haml +1 -0
  503. data/lib/rails/generators/alchemy/page_layouts/templates/layout.html.slim +1 -0
  504. data/lib/rails/generators/alchemy/site_layouts/site_layouts_generator.rb +23 -0
  505. data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.erb +1 -0
  506. data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.haml +1 -0
  507. data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.slim +1 -0
  508. data/lib/rails/generators/alchemy/views/views_generator.rb +41 -0
  509. data/lib/rails/templates/alchemy.rb +7 -0
  510. data/lib/tasks/alchemy/convert.rake +39 -0
  511. data/lib/tasks/alchemy/db.rake +22 -0
  512. data/lib/tasks/alchemy/install.rake +61 -0
  513. data/lib/tasks/alchemy/tidy.rake +102 -0
  514. data/lib/tasks/alchemy/upgrade.rake +28 -0
  515. data/spec/controllers/admin/attachments_controller_spec.rb +211 -0
  516. data/spec/controllers/admin/base_controller_spec.rb +74 -0
  517. data/spec/controllers/admin/clipboard_controller_spec.rb +60 -0
  518. data/spec/controllers/admin/contents_controller_spec.rb +72 -0
  519. data/spec/controllers/admin/dashboard_controller_spec.rb +139 -0
  520. data/spec/controllers/admin/elements_controller_spec.rb +473 -0
  521. data/spec/controllers/admin/essence_files_controller_spec.rb +71 -0
  522. data/spec/controllers/admin/essence_pictures_controller_spec.rb +202 -0
  523. data/spec/controllers/admin/languages_controller_spec.rb +61 -0
  524. data/spec/controllers/admin/layoutpages_controller_spec.rb +27 -0
  525. data/spec/controllers/admin/pages_controller_spec.rb +553 -0
  526. data/spec/controllers/admin/pictures_controller_spec.rb +358 -0
  527. data/spec/controllers/admin/resources_controller_spec.rb +53 -0
  528. data/spec/controllers/admin/trash_controller_spec.rb +68 -0
  529. data/spec/controllers/alchemy/admin/tags_controller_spec.rb +63 -0
  530. data/spec/controllers/alchemy/api/contents_controller_spec.rb +126 -0
  531. data/spec/controllers/alchemy/api/elements_controller_spec.rb +125 -0
  532. data/spec/controllers/alchemy/api/pages_controller_spec.rb +134 -0
  533. data/spec/controllers/attachments_controller_spec.rb +64 -0
  534. data/spec/controllers/base_controller_spec.rb +51 -0
  535. data/spec/controllers/elements_controller_spec.rb +48 -0
  536. data/spec/controllers/messages_controller_spec.rb +199 -0
  537. data/spec/controllers/pages_controller_spec.rb +265 -0
  538. data/spec/controllers/pictures_controller_spec.rb +393 -0
  539. data/spec/dummy/Rakefile +6 -0
  540. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  541. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  542. data/spec/dummy/app/controllers/admin/events_controller.rb +3 -0
  543. data/spec/dummy/app/controllers/application_controller.rb +15 -0
  544. data/spec/dummy/app/controllers/login_controller.rb +5 -0
  545. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  546. data/spec/dummy/app/mailers/.gitkeep +0 -0
  547. data/spec/dummy/app/models/ability.rb +9 -0
  548. data/spec/dummy/app/models/dummy_model.rb +3 -0
  549. data/spec/dummy/app/models/dummy_user.rb +11 -0
  550. data/spec/dummy/app/models/event.rb +10 -0
  551. data/spec/dummy/app/models/location.rb +3 -0
  552. data/spec/dummy/app/views/alchemy/elements/_all_you_can_eat_editor.html.erb +11 -0
  553. data/spec/dummy/app/views/alchemy/elements/_article_editor.html.erb +10 -0
  554. data/spec/dummy/app/views/alchemy/elements/_article_view.html.erb +25 -0
  555. data/spec/dummy/app/views/alchemy/elements/_headline_editor.html.erb +1 -0
  556. data/spec/dummy/app/views/alchemy/elements/_headline_view.html.erb +1 -0
  557. data/spec/dummy/app/views/alchemy/elements/_news_view.html.erb +11 -0
  558. data/spec/dummy/app/views/alchemy/page_layouts/_standard.html.erb +14 -0
  559. data/spec/dummy/app/views/layouts/application.html.erb +17 -0
  560. data/spec/dummy/bin/bundle +3 -0
  561. data/spec/dummy/bin/rails +4 -0
  562. data/spec/dummy/bin/rake +4 -0
  563. data/spec/dummy/config.ru +4 -0
  564. data/spec/dummy/config/alchemy/cells.yml +5 -0
  565. data/spec/dummy/config/alchemy/elements.yml +112 -0
  566. data/spec/dummy/config/alchemy/page_layouts.yml +32 -0
  567. data/spec/dummy/config/application.rb +32 -0
  568. data/spec/dummy/config/boot.rb +5 -0
  569. data/spec/dummy/config/database.yml +32 -0
  570. data/spec/dummy/config/environment.rb +5 -0
  571. data/spec/dummy/config/environments/development.rb +41 -0
  572. data/spec/dummy/config/environments/production.rb +77 -0
  573. data/spec/dummy/config/environments/test.rb +43 -0
  574. data/spec/dummy/config/initializers/alchemy.rb +2 -0
  575. data/spec/dummy/config/initializers/assets.rb +11 -0
  576. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  577. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  578. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  579. data/spec/dummy/config/initializers/inflections.rb +16 -0
  580. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  581. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  582. data/spec/dummy/config/initializers/session_store.rb +3 -0
  583. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  584. data/spec/dummy/config/routes.rb +12 -0
  585. data/spec/dummy/config/secrets.yml +22 -0
  586. data/spec/dummy/db/migrate/20121026104128_create_events.rb +20 -0
  587. data/spec/dummy/db/migrate/20130328101418_create_locations.rb +9 -0
  588. data/spec/dummy/db/migrate/20130827094554_alchemy_two_point_six.rb +380 -0
  589. data/spec/dummy/db/migrate/20130828121054_remove_do_not_index_from_alchemy_essence_texts.rb +5 -0
  590. data/spec/dummy/db/migrate/20130828121120_remove_do_not_index_from_alchemy_essence_richtexts.rb +5 -0
  591. data/spec/dummy/db/migrate/20130918201742_add_published_at_to_alchemy_pages.rb +5 -0
  592. data/spec/dummy/db/migrate/20131209225243_create_dummy_users.rb +9 -0
  593. data/spec/dummy/db/migrate/20150122213511_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb +31 -0
  594. data/spec/dummy/db/migrate/20150122213512_add_missing_unique_indices.acts_as_taggable_on_engine.rb +20 -0
  595. data/spec/dummy/db/migrate/20150122213513_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb +15 -0
  596. data/spec/dummy/db/migrate/20150122213514_add_missing_taggable_index.acts_as_taggable_on_engine.rb +10 -0
  597. data/spec/dummy/db/migrate/20150412103152_create_dummy_model.rb +7 -0
  598. data/spec/dummy/db/schema.rb +322 -0
  599. data/spec/dummy/db/seeds.rb +1 -0
  600. data/spec/dummy/lib/assets/.gitkeep +0 -0
  601. data/spec/dummy/public/404.html +67 -0
  602. data/spec/dummy/public/422.html +67 -0
  603. data/spec/dummy/public/500.html +66 -0
  604. data/spec/dummy/public/favicon.ico +0 -0
  605. data/spec/features/admin/dashboard_spec.rb +82 -0
  606. data/spec/features/admin/language_tree_feature_spec.rb +33 -0
  607. data/spec/features/admin/legacy_page_url_management_spec.rb +62 -0
  608. data/spec/features/admin/link_overlay_spec.rb +54 -0
  609. data/spec/features/admin/locale_select_feature_spec.rb +25 -0
  610. data/spec/features/admin/modules_integration_spec.rb +24 -0
  611. data/spec/features/admin/navigation_feature_spec.rb +13 -0
  612. data/spec/features/admin/page_creation_feature_spec.rb +51 -0
  613. data/spec/features/admin/page_editing_feature_spec.rb +135 -0
  614. data/spec/features/admin/picture_library_integration_spec.rb +62 -0
  615. data/spec/features/admin/resources_integration_spec.rb +133 -0
  616. data/spec/features/admin/site_select_feature_spec.rb +32 -0
  617. data/spec/features/admin/tinymce_feature_spec.rb +34 -0
  618. data/spec/features/navigation_spec.rb +9 -0
  619. data/spec/features/page_feature_spec.rb +287 -0
  620. data/spec/features/picture_security_spec.rb +35 -0
  621. data/spec/features/security_spec.rb +24 -0
  622. data/spec/features/translation_integration_spec.rb +51 -0
  623. data/spec/fixtures/500x500.png +0 -0
  624. data/spec/fixtures/80x60.png +0 -0
  625. data/spec/fixtures/image with spaces.png +0 -0
  626. data/spec/fixtures/image.png +0 -0
  627. data/spec/fixtures/image2.PNG +0 -0
  628. data/spec/fixtures/image3.jpeg +0 -0
  629. data/spec/helpers/admin/attachments_helper_spec.rb +15 -0
  630. data/spec/helpers/admin/base_helper_spec.rb +270 -0
  631. data/spec/helpers/admin/contents_helper_spec.rb +65 -0
  632. data/spec/helpers/admin/elements_helper_spec.rb +178 -0
  633. data/spec/helpers/admin/essences_helper_spec.rb +140 -0
  634. data/spec/helpers/admin/navigation_helper_spec.rb +288 -0
  635. data/spec/helpers/admin/pages_helper_spec.rb +95 -0
  636. data/spec/helpers/admin/pictures_helper_spec.rb +29 -0
  637. data/spec/helpers/admin/tags_helper_spec.rb +113 -0
  638. data/spec/helpers/base_helper_spec.rb +45 -0
  639. data/spec/helpers/elements_block_helper_spec.rb +135 -0
  640. data/spec/helpers/elements_helper_spec.rb +311 -0
  641. data/spec/helpers/essences_helper_spec.rb +156 -0
  642. data/spec/helpers/pages_helper_spec.rb +413 -0
  643. data/spec/helpers/picture_url_helpers_spec.rb +35 -0
  644. data/spec/helpers/url_helper_spec.rb +174 -0
  645. data/spec/javascripts/alchemy/dialog_spec.coffee +82 -0
  646. data/spec/javascripts/alchemy/link_overlay_spec.coffee +25 -0
  647. data/spec/javascripts/alchemy_integration_spec.coffee +3 -0
  648. data/spec/javascripts/fixtures/select.html +3 -0
  649. data/spec/javascripts/helpers/mock-ajax.js +199 -0
  650. data/spec/javascripts/helpers/test_responses/test_responses.js +1 -0
  651. data/spec/javascripts/support/jasmine.yml +29 -0
  652. data/spec/libraries/auth_accessors_spec.rb +40 -0
  653. data/spec/libraries/config_spec.rb +112 -0
  654. data/spec/libraries/controller_actions_spec.rb +133 -0
  655. data/spec/libraries/i18n_spec.rb +30 -0
  656. data/spec/libraries/kaminari/scoped_pagination_url_helper_spec.rb +30 -0
  657. data/spec/libraries/modules_spec.rb +67 -0
  658. data/spec/libraries/mount_point_spec.rb +77 -0
  659. data/spec/libraries/on_page_layout_spec.rb +112 -0
  660. data/spec/libraries/page_layout_spec.rb +144 -0
  661. data/spec/libraries/permissions_spec.rb +261 -0
  662. data/spec/libraries/resource_spec.rb +371 -0
  663. data/spec/libraries/resources_helper_spec.rb +144 -0
  664. data/spec/libraries/shell_spec.rb +125 -0
  665. data/spec/libraries/template_tracker_spec.rb +94 -0
  666. data/spec/libraries/tinymce_spec.rb +67 -0
  667. data/spec/libraries/userstamp_spec.rb +10 -0
  668. data/spec/mailers/messages_spec.rb +23 -0
  669. data/spec/models/attachment_spec.rb +227 -0
  670. data/spec/models/cell_spec.rb +102 -0
  671. data/spec/models/content_spec.rb +404 -0
  672. data/spec/models/dummy_model_spec.rb +11 -0
  673. data/spec/models/element_spec.rb +617 -0
  674. data/spec/models/element_to_page_spec.rb +14 -0
  675. data/spec/models/essence_boolean_spec.rb +10 -0
  676. data/spec/models/essence_date_spec.rb +29 -0
  677. data/spec/models/essence_file_spec.rb +43 -0
  678. data/spec/models/essence_html_spec.rb +18 -0
  679. data/spec/models/essence_link_spec.rb +10 -0
  680. data/spec/models/essence_picture_spec.rb +183 -0
  681. data/spec/models/essence_richtext_spec.rb +18 -0
  682. data/spec/models/essence_select_spec.rb +10 -0
  683. data/spec/models/essence_text_spec.rb +114 -0
  684. data/spec/models/language_spec.rb +123 -0
  685. data/spec/models/legacy_page_url_spec.rb +21 -0
  686. data/spec/models/message_spec.rb +55 -0
  687. data/spec/models/page_spec.rb +1896 -0
  688. data/spec/models/picture_spec.rb +330 -0
  689. data/spec/models/site_spec.rb +233 -0
  690. data/spec/models/tag_spec.rb +31 -0
  691. data/spec/routing/api_routing_spec.rb +150 -0
  692. data/spec/routing/routing_spec.rb +234 -0
  693. data/spec/spec_helper.rb +89 -0
  694. data/spec/support/ci/install_phantomjs +7 -0
  695. data/spec/support/hint_examples.rb +30 -0
  696. data/spec/support/rspec-activemodel-mocks_patch.rb +8 -0
  697. data/spec/support/test_tweaks.rb +31 -0
  698. data/spec/support/transformation_examples.rb +180 -0
  699. data/spec/tasks/helpers_spec.rb +219 -0
  700. data/spec/views/essences/essence_boolean_editor_spec.rb +33 -0
  701. data/spec/views/essences/essence_boolean_view_spec.rb +25 -0
  702. data/spec/views/essences/essence_date_view_spec.rb +39 -0
  703. data/spec/views/essences/essence_file_editor_spec.rb +61 -0
  704. data/spec/views/essences/essence_file_view_spec.rb +24 -0
  705. data/spec/views/essences/essence_html_view_spec.rb +22 -0
  706. data/spec/views/essences/essence_link_view_spec.rb +41 -0
  707. data/spec/views/essences/essence_picture_view_spec.rb +129 -0
  708. data/spec/views/essences/essence_richtext_view_spec.rb +32 -0
  709. data/spec/views/essences/essence_select_view_spec.rb +12 -0
  710. data/spec/views/essences/essence_text_view_spec.rb +52 -0
  711. data/vendor/assets/images/Jcrop.gif +0 -0
  712. data/vendor/assets/javascripts/fileupload/jquery.fileupload-process.js +175 -0
  713. data/vendor/assets/javascripts/fileupload/jquery.fileupload-validate.js +122 -0
  714. data/vendor/assets/javascripts/fileupload/jquery.fileupload.js +1467 -0
  715. data/vendor/assets/javascripts/fileupload/jquery.iframe-transport.js +217 -0
  716. data/vendor/assets/javascripts/jquery_plugins/jquery.Jcrop.min.js +22 -0
  717. data/vendor/assets/javascripts/jquery_plugins/jquery.floatThead.min.js +3 -0
  718. data/vendor/assets/javascripts/jquery_plugins/jquery.scrollTo.min.js +7 -0
  719. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +435 -0
  720. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.tabspaging.js +296 -0
  721. data/vendor/assets/javascripts/keymaster.js +296 -0
  722. data/vendor/assets/javascripts/requestAnimationFrame.js +31 -0
  723. data/vendor/assets/javascripts/spin.min.js +1 -0
  724. data/vendor/assets/javascripts/tinymce/langs/de.js +200 -0
  725. data/vendor/assets/javascripts/tinymce/langs/es.js +200 -0
  726. data/vendor/assets/javascripts/tinymce/langs/fr.js +200 -0
  727. data/vendor/assets/javascripts/tinymce/langs/nl.js +200 -0
  728. data/vendor/assets/javascripts/tinymce/langs/ru.js +200 -0
  729. data/vendor/assets/javascripts/tinymce/license.txt +504 -0
  730. data/vendor/assets/javascripts/tinymce/plugins/anchor/plugin.min.js +1 -0
  731. data/vendor/assets/javascripts/tinymce/plugins/autoresize/plugin.min.js +1 -0
  732. data/vendor/assets/javascripts/tinymce/plugins/charmap/plugin.min.js +1 -0
  733. data/vendor/assets/javascripts/tinymce/plugins/code/plugin.min.js +1 -0
  734. data/vendor/assets/javascripts/tinymce/plugins/directionality/plugin.min.js +1 -0
  735. data/vendor/assets/javascripts/tinymce/plugins/fullscreen/plugin.min.js +1 -0
  736. data/vendor/assets/javascripts/tinymce/plugins/hr/plugin.min.js +1 -0
  737. data/vendor/assets/javascripts/tinymce/plugins/link/plugin.min.js +1 -0
  738. data/vendor/assets/javascripts/tinymce/plugins/paste/plugin.min.js +1 -0
  739. data/vendor/assets/javascripts/tinymce/plugins/tabfocus/plugin.min.js +1 -0
  740. data/vendor/assets/javascripts/tinymce/plugins/table/plugin.min.js +1 -0
  741. data/vendor/assets/javascripts/tinymce/themes/modern/theme.min.js +1 -0
  742. data/vendor/assets/javascripts/tinymce/tinymce.min.js +13 -0
  743. data/vendor/assets/stylesheets/jquery.Jcrop.min.css +28 -0
  744. metadata +1453 -0
@@ -0,0 +1,190 @@
1
+ module Alchemy
2
+ module Admin
3
+ class ElementsController < Alchemy::Admin::BaseController
4
+ before_action :load_element, only: [:update, :trash, :fold]
5
+ authorize_resource class: Alchemy::Element
6
+
7
+ def index
8
+ @page = Page.find(params[:page_id])
9
+ @cells = @page.cells
10
+ if @cells.blank?
11
+ @elements = @page.elements.not_trashed
12
+ else
13
+ @elements = @page.elements_grouped_by_cells
14
+ end
15
+ end
16
+
17
+ def list
18
+ @page_id = params[:page_id]
19
+ if @page_id.blank? && !params[:page_urlname].blank?
20
+ @page_id = Language.current.pages.find_by(urlname: params[:page_urlname]).id
21
+ end
22
+ @elements = Element.published.where(page_id: @page_id)
23
+ end
24
+
25
+ def new
26
+ @page = Page.find_by_id(params[:page_id])
27
+ @element = @page.elements.build
28
+ @elements = @page.available_element_definitions
29
+ @clipboard = get_clipboard('elements')
30
+ @clipboard_items = Element.all_from_clipboard_for_page(@clipboard, @page)
31
+ end
32
+
33
+ # Creates a element as discribed in config/alchemy/elements.yml on page via AJAX.
34
+ def create
35
+ @page = Page.find(params[:element][:page_id])
36
+ Element.transaction do
37
+ if @paste_from_clipboard = params[:paste_from_clipboard].present?
38
+ @element = paste_element_from_clipboard
39
+ @cell = @element.cell
40
+ else
41
+ @element = Element.new_from_scratch(params[:element])
42
+ if @page.can_have_cells?
43
+ @cell = find_or_create_cell
44
+ @element.cell = @cell
45
+ end
46
+ @element.save
47
+ end
48
+ if @page.definition['insert_elements_at'] == 'top'
49
+ @insert_at_top = true
50
+ @element.move_to_top
51
+ end
52
+ end
53
+ @cell_name = @cell.nil? ? "for_other_elements" : @cell.name
54
+ if @element.valid?
55
+ render :create
56
+ else
57
+ @element.page = @page
58
+ @elements = @page.available_element_definitions
59
+ @clipboard = get_clipboard('elements')
60
+ @clipboard_items = Element.all_from_clipboard_for_page(@clipboard, @page)
61
+ render :new
62
+ end
63
+ end
64
+
65
+ # Updates the element.
66
+ #
67
+ # And update all contents in the elements by calling update_contents.
68
+ #
69
+ def update
70
+ if @element.update_contents(contents_params)
71
+ @page = @element.page
72
+ @element_validated = @element.update_attributes!(element_params)
73
+
74
+ Rails.logger.info "[ALCHEMY_LOCALE] updating contents for element in elements_controller#update: #{@element}"
75
+ update_translations(@element) if @element.page.language.language_code == 'en'
76
+ else
77
+ @element_validated = false
78
+ @notice = _t('Validation failed')
79
+ @error_message = "<h2>#{@notice}</h2><p>#{_t(:content_validations_headline)}</p>".html_safe
80
+ end
81
+ end
82
+
83
+ # Trashes the Element instead of deleting it.
84
+ def trash
85
+ @page = @element.page
86
+ @element.trash!
87
+ end
88
+
89
+ def order
90
+ @trashed_element_ids = Element.trashed.where(id: params[:element_ids]).pluck(:id)
91
+ Element.transaction do
92
+ params[:element_ids].each_with_index do |element_id, idx|
93
+ # Ensure to set page_id and cell_id to the current page and
94
+ # cell because of trashed elements could still have old values
95
+ Element.where(id: element_id).update_all(
96
+ page_id: params[:page_id],
97
+ cell_id: params[:cell_id],
98
+ position: idx + 1
99
+ )
100
+ end
101
+ end
102
+ end
103
+
104
+ def fold
105
+ @page = @element.page
106
+ @element.folded = !@element.folded
107
+ @element.save
108
+ end
109
+
110
+ private
111
+ def update_translations(element)
112
+ locale = element.page.language.language_code
113
+
114
+ # do _not_ update foreign languages from alchemy
115
+ return unless locale == 'en'
116
+
117
+ element.essences.each do |essence|
118
+ next unless [Alchemy::EssenceText,Alchemy::EssenceRichtext,Alchemy::EssenceHtml].include? essence.class
119
+ key = essence.content.name
120
+ description = essence.body
121
+
122
+ Rails.logger.info "[ALCHEMY_LOCALE] locale/key/value added to localeapp queue: #{locale}/#{key}/#{description}"
123
+
124
+ Localeapp.missing_translations.add(locale, "#{Alchemy::Translations::TRANSLATION_PREFIX}#{key}", description)
125
+ end
126
+
127
+ Rails.logger.info "[ALCHEMY_LOCALE] posting missing translations to locale"
128
+
129
+ Localeapp.sender.post_missing_translations
130
+ end
131
+
132
+ def load_element
133
+ @element = Element.find(params[:id])
134
+ end
135
+
136
+ # Returns the cell for element name in params.
137
+ # Creates the cell if necessary.
138
+ def find_or_create_cell
139
+ if @paste_from_clipboard
140
+ element_with_cell_name = params[:paste_from_clipboard]
141
+ else
142
+ element_with_cell_name = params[:element][:name]
143
+ end
144
+ return nil if element_with_cell_name.blank?
145
+ return nil unless element_with_cell_name.include?('#')
146
+ cell_name = element_with_cell_name.split('#').last
147
+ cell_definition = Cell.definition_for(cell_name)
148
+ if cell_definition.blank?
149
+ raise CellDefinitionError, "Cell definition not found for #{cell_name}"
150
+ end
151
+ @page.cells.find_or_create_by(name: cell_definition['name'])
152
+ end
153
+
154
+ def element_from_clipboard
155
+ @element_from_clipboard ||= begin
156
+ @clipboard = get_clipboard('elements')
157
+ @clipboard.detect { |item| item['id'].to_i == params[:paste_from_clipboard].to_i }
158
+ end
159
+ end
160
+
161
+ def paste_element_from_clipboard
162
+ @source_element = Element.find(element_from_clipboard['id'])
163
+ new_attributes = {:page_id => @page.id}
164
+ if @page.can_have_cells?
165
+ new_attributes = new_attributes.merge({:cell_id => find_or_create_cell.try(:id)})
166
+ end
167
+ element = Element.copy(@source_element, new_attributes)
168
+ if element_from_clipboard['action'] == 'cut'
169
+ cut_element
170
+ end
171
+ element
172
+ end
173
+
174
+ def cut_element
175
+ @cutted_element_id = @source_element.id
176
+ @clipboard.delete_if { |item| item['id'] == @source_element.id.to_s }
177
+ @source_element.destroy
178
+ end
179
+
180
+ def contents_params
181
+ params.fetch(:contents, {}).permit!
182
+ end
183
+
184
+ def element_params
185
+ params.require(:element).permit(:public, :tag_list)
186
+ end
187
+
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,47 @@
1
+ module Alchemy
2
+ module Admin
3
+ class EssenceFilesController < Alchemy::Admin::BaseController
4
+ authorize_resource class: Alchemy::EssenceFile
5
+
6
+ before_filter :load_essence_file, only: [:edit, :update]
7
+
8
+ helper "Alchemy::Admin::Contents"
9
+
10
+ def edit
11
+ @content = @essence_file.content
12
+ @options = options_from_params
13
+ end
14
+
15
+ def update
16
+ @essence_file.update(essence_file_params)
17
+ end
18
+
19
+ # Assigns file, but does not saves it.
20
+ #
21
+ # When the user saves the element the content gets updated as well.
22
+ #
23
+ def assign
24
+ @content = Content.find_by(id: params[:content_id])
25
+ @attachment = Attachment.find_by(id: params[:attachment_id])
26
+ @content.essence.attachment = @attachment
27
+ @options = options_from_params
28
+
29
+ # We need to update timestamp here because we don't save yet,
30
+ # but the cache needs to be get invalid.
31
+ # And we don't user @content.touch here, because that updates
32
+ # also the element and page timestamps what we don't want yet.
33
+ @content.update_column(:updated_at, Time.now)
34
+ end
35
+
36
+ private
37
+
38
+ def essence_file_params
39
+ params.require(:essence_file).permit(:title, :css_class)
40
+ end
41
+
42
+ def load_essence_file
43
+ @essence_file = EssenceFile.find(params[:id])
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,120 @@
1
+ module Alchemy
2
+ module Admin
3
+ class EssencePicturesController < Alchemy::Admin::BaseController
4
+ authorize_resource class: Alchemy::EssencePicture
5
+
6
+ before_filter :load_essence_picture, only: [:edit, :crop, :update]
7
+ before_filter :load_content, only: [:edit, :update, :assign]
8
+ before_filter :load_options
9
+
10
+ helper 'alchemy/admin/contents'
11
+ helper 'alchemy/admin/essences'
12
+ helper 'alchemy/url'
13
+
14
+ def edit
15
+ end
16
+
17
+ def crop
18
+ if @picture = @essence_picture.picture
19
+ @content = @essence_picture.content
20
+ @options[:format] ||= (configuration(:image_store_format) or 'png')
21
+
22
+ @min_size = sizes_from_essence_or_params
23
+ @ratio = ratio_from_size_or_params
24
+ infer_width_or_height_from_ratio
25
+
26
+ @default_box = @essence_picture.default_mask(@min_size)
27
+ @initial_box = @essence_picture.cropping_mask || @default_box
28
+ else
29
+ @no_image_notice = _t(:no_image_for_cropper_found)
30
+ end
31
+ end
32
+
33
+ def update
34
+ @essence_picture.update(essence_picture_params)
35
+ end
36
+
37
+ # Assigns picture, but does not saves it.
38
+ #
39
+ # When the user saves the element the content gets updated as well.
40
+ #
41
+ def assign
42
+ @picture = Picture.find_by(id: params[:picture_id])
43
+ @content.essence.picture = @picture
44
+ @element = @content.element
45
+ @dragable = @options[:grouped]
46
+ @options = @options.merge(dragable: @dragable)
47
+
48
+ # We need to update timestamp here because we don't save yet,
49
+ # but the cache needs to be get invalid.
50
+ # And we don't user @content.touch here, because that updates
51
+ # also the element and page timestamps what we don't want yet.
52
+ @content.update_column(:updated_at, Time.now)
53
+ end
54
+
55
+ def destroy
56
+ @content = Content.find_by(id: params[:id])
57
+ @element = @content.element
58
+ @content_id = @content.id
59
+ @content.destroy
60
+ @essence_pictures = @element.contents.essence_pictures
61
+ end
62
+
63
+ private
64
+
65
+ def load_options
66
+ @options = options_from_params
67
+ end
68
+
69
+ def load_essence_picture
70
+ @essence_picture = EssencePicture.find(params[:id])
71
+ end
72
+
73
+ def load_content
74
+ @content = Content.find(params[:content_id])
75
+ end
76
+
77
+ # Gets the minimum size of the image to be rendered. the database render_size
78
+ # has preference over the image_size parameter.
79
+ #
80
+ def sizes_from_essence_or_params
81
+ if @essence_picture.render_size? && !@essence_picture.render_size.blank?
82
+ @essence_picture.sizes_from_string(@essence_picture.render_size)
83
+ elsif @options[:image_size]
84
+ @essence_picture.sizes_from_string(@options[:image_size])
85
+ else
86
+ { width: 0, height: 0 }
87
+ end
88
+ end
89
+
90
+ # Infers the aspect ratio from size or parameters. If you don't want a fixed
91
+ # aspect ratio, don't specify a size or only width or height.
92
+ #
93
+ def ratio_from_size_or_params
94
+ if @min_size.has_value?(0) && @options[:fixed_ratio]
95
+ @options[:fixed_ratio].to_f
96
+ elsif !@min_size[:width].zero? && !@min_size[:height].zero?
97
+ @min_size[:width].to_f / @min_size[:height].to_f
98
+ else
99
+ false
100
+ end
101
+ end
102
+
103
+ # Infers the minimum width or height if the aspect ratio and one dimension
104
+ # is specified.
105
+ #
106
+ def infer_width_or_height_from_ratio
107
+ if @min_size[:height].zero?
108
+ @min_size[:height] = (@min_size[:width] / @ratio).to_i if @ratio
109
+ else
110
+ @min_size[:width] = (@min_size[:height] * @ratio).to_i if @ratio
111
+ end
112
+ end
113
+
114
+ def essence_picture_params
115
+ params.require(:essence_picture).permit(:alt_tag, :caption, :css_class, :render_size, :title, :crop_from, :crop_size)
116
+ end
117
+
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,17 @@
1
+ module Alchemy
2
+ module Admin
3
+ class LanguagesController < ResourcesController
4
+
5
+ def new
6
+ @language = Language.new
7
+ @language.page_layout = configured_page_layout || @language.page_layout
8
+ end
9
+
10
+ private
11
+
12
+ def configured_page_layout
13
+ Config.get(:default_language).try('[]', 'page_layout')
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ module Alchemy
2
+ module Admin
3
+ class LayoutpagesController < Alchemy::Admin::BaseController
4
+ authorize_resource class: :alchemy_admin_layoutpages
5
+
6
+ def index
7
+ @locked_pages = Page.from_current_site.all_locked_by(current_alchemy_user)
8
+ @layout_root = Page.find_or_create_layout_root_for(Language.current.id)
9
+ @languages = Language.all
10
+ end
11
+
12
+ def edit
13
+ @page = Page.find(params[:id])
14
+ @page_layouts = PageLayout.layouts_with_own_for_select(@page.page_layout, Language.current.id, true)
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,39 @@
1
+ module Alchemy
2
+ class Admin::LegacyPageUrlsController < Alchemy::Admin::ResourcesController
3
+ before_action :load_page
4
+
5
+ def new
6
+ @legacy_page_url = @page.legacy_urls.build
7
+ end
8
+
9
+ def create
10
+ @legacy_page_url = @page.legacy_urls.build(legacy_page_url_params)
11
+ @legacy_page_url.save
12
+ end
13
+
14
+ def update
15
+ @legacy_page_url = LegacyPageUrl.find(params[:id])
16
+ if @legacy_page_url.update(legacy_page_url_params)
17
+ render :update
18
+ else
19
+ render :edit
20
+ end
21
+ end
22
+
23
+ def destroy
24
+ @legacy_page_url = LegacyPageUrl.find(params[:id])
25
+ @legacy_page_url.destroy
26
+ end
27
+
28
+ private
29
+
30
+ def load_page
31
+ @page = Page.find(params[:page_id])
32
+ end
33
+
34
+ def legacy_page_url_params
35
+ params.require(:legacy_page_url).permit(:urlname)
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,359 @@
1
+ module Alchemy
2
+ module Admin
3
+ class PagesController < Alchemy::Admin::BaseController
4
+ helper 'alchemy/pages'
5
+
6
+ before_action :set_translation,
7
+ except: [:show]
8
+
9
+ before_action :load_page,
10
+ only: [:show, :info, :unlock, :visit, :publish, :configure, :edit, :update, :destroy, :fold]
11
+
12
+ before_action :set_root_page,
13
+ only: [:index, :show, :sort, :order]
14
+
15
+ authorize_resource class: Alchemy::Page, except: :index
16
+
17
+ def index
18
+ authorize! :index, :alchemy_admin_pages
19
+
20
+ @locked_pages = Page.from_current_site.all_locked_by(current_alchemy_user)
21
+ @languages = Language.all
22
+ if !@page_root
23
+ @language = Language.current
24
+ @languages_with_page_tree = Language.with_root_page
25
+ end
26
+ end
27
+
28
+ # Used by page preview iframe in Page#edit view.
29
+ #
30
+ def show
31
+ @preview_mode = true
32
+ Page.current_preview = @page
33
+ # Setting the locale to pages language, so the page content has it's correct translations.
34
+ ::I18n.locale = @page.language_code
35
+ render layout: 'application'
36
+ end
37
+
38
+ def info
39
+ render layout: !request.xhr?
40
+ end
41
+
42
+ def new
43
+ @page = Page.new(layoutpage: params[:layoutpage] == 'true', parent_id: params[:parent_id])
44
+ @page_layouts = PageLayout.layouts_for_select(Language.current.id, @page.layoutpage?)
45
+ @clipboard = get_clipboard('pages')
46
+ @clipboard_items = Page.all_from_clipboard_for_select(@clipboard, Language.current.id, @page.layoutpage?)
47
+ end
48
+
49
+ def create
50
+ @page = paste_from_clipboard || Page.new(page_params)
51
+ if @page.save
52
+ flash[:notice] = _t("Page created", name: @page.name)
53
+ do_redirect_to(redirect_path_after_create_page)
54
+ else
55
+ @page_layouts = PageLayout.layouts_for_select(Language.current.id, @page.layoutpage?)
56
+ @clipboard = get_clipboard('pages')
57
+ @clipboard_items = Page.all_from_clipboard_for_select(@clipboard, Language.current.id, @page.layoutpage?)
58
+ render :new
59
+ end
60
+ end
61
+
62
+ # Edit the content of the page and all its elements and contents.
63
+ def edit
64
+ # fetching page via before filter
65
+ if page_is_locked?
66
+ flash[:notice] = _t('This page is locked', name: @page.locker_name)
67
+ redirect_to admin_pages_path
68
+ else
69
+ @page.lock_to!(current_alchemy_user)
70
+ @locked_pages = Page.from_current_site.all_locked_by(current_alchemy_user)
71
+ end
72
+ @layoutpage = @page.layoutpage?
73
+ end
74
+
75
+ # Set page configuration like page names, meta tags and states.
76
+ def configure
77
+ @page_layouts = PageLayout.layouts_with_own_for_select(@page.page_layout, Language.current.id, @page.layoutpage?)
78
+ render @page.redirects_to_external? ? 'configure_external' : 'configure'
79
+ end
80
+
81
+ # Updates page
82
+ #
83
+ # * fetches page via before filter
84
+ #
85
+ def update
86
+ # stores old page_layout value, because unfurtunally rails @page.changes does not work here.
87
+ @old_page_layout = @page.page_layout
88
+ if @page.update_attributes(page_params)
89
+ @notice = _t("Page saved", :name => @page.name)
90
+ @while_page_edit = request.referer.include?('edit')
91
+ else
92
+ configure
93
+ end
94
+ end
95
+
96
+ def destroy
97
+ # fetching page via before filter
98
+ name = @page.name
99
+ @page_id = @page.id
100
+ @layoutpage = @page.layoutpage?
101
+ if @page.destroy
102
+ set_root_page
103
+ @message = _t("Page deleted", :name => name)
104
+ flash[:notice] = @message
105
+ respond_to do |format|
106
+ format.js
107
+ end
108
+ # remove from clipboard
109
+ @clipboard = get_clipboard('pages')
110
+ @clipboard.delete_if { |item| item['id'] == @page_id.to_s }
111
+ end
112
+ end
113
+
114
+ def link
115
+ @url_prefix = ""
116
+ if configuration(:show_real_root)
117
+ @page_root = Page.root
118
+ else
119
+ set_root_page
120
+ end
121
+ @area_name = params[:area_name]
122
+ @content_id = params[:content_id]
123
+ @attachments = Attachment.all.collect { |f| [f.name, download_attachment_path(:id => f.id, :name => f.urlname)] }
124
+ if params[:link_urls_for] == "newsletter"
125
+ @url_prefix = current_server
126
+ end
127
+ if multi_language?
128
+ @url_prefix = "#{Language.current.code}/"
129
+ end
130
+ end
131
+
132
+ def fold
133
+ # @page is fetched via before filter
134
+ @page.fold!(current_alchemy_user.id, !@page.folded?(current_alchemy_user.id))
135
+ respond_to do |format|
136
+ format.js
137
+ end
138
+ end
139
+
140
+ # Leaves the page editing mode and unlocks the page for other users
141
+ def unlock
142
+ # fetching page via before filter
143
+ @page.unlock!
144
+ flash[:notice] = _t(:unlocked_page, :name => @page.name)
145
+ @pages_locked_by_user = Page.from_current_site.all_locked_by(current_alchemy_user)
146
+ respond_to do |format|
147
+ format.js
148
+ format.html {
149
+ redirect_to params[:redirect_to].blank? ? admin_pages_path : params[:redirect_to]
150
+ }
151
+ end
152
+ end
153
+
154
+ def visit
155
+ @page.unlock!
156
+ redirect_to show_page_path(urlname: @page.urlname, locale: multi_language? ? @page.language_code : nil)
157
+ end
158
+
159
+ # Sets the page public and updates the published_at attribute that is used as cache_key
160
+ #
161
+ def publish
162
+ # fetching page via before filter
163
+ @page.publish!
164
+ flash[:notice] = _t(:page_published, :name => @page.name)
165
+ redirect_back_or_to_default(admin_pages_path)
166
+ end
167
+
168
+ def copy_language_tree
169
+ language_root_to_copy_from.copy_children_to(copy_of_language_root)
170
+ flash[:notice] = _t(:language_pages_copied)
171
+ redirect_to admin_pages_path
172
+ end
173
+
174
+ def sort
175
+ @sorting = true
176
+ end
177
+
178
+ # Receives a JSON object representing a language tree to be ordered
179
+ # and updates all pages in that language structure to their correct indexes
180
+ def order
181
+ neworder = JSON.parse(params[:set])
182
+ tree = create_tree(neworder, @page_root)
183
+
184
+ Alchemy::Page.transaction do
185
+ tree.each do |key, node|
186
+ dbitem = Page.find(key)
187
+ dbitem.update_node!(node)
188
+ end
189
+ end
190
+
191
+ flash[:notice] = _t("Pages order saved")
192
+ do_redirect_to admin_pages_path
193
+ end
194
+
195
+ def switch_language
196
+ set_alchemy_language(params[:language_id])
197
+ do_redirect_to redirect_path_for_switch_language
198
+ end
199
+
200
+ def flush
201
+ Language.current.pages.flushables.each do |page|
202
+ page.publish!
203
+ end
204
+ respond_to do |format|
205
+ format.js
206
+ end
207
+ end
208
+
209
+ private
210
+
211
+ def copy_of_language_root
212
+ page_copy = Page.copy(
213
+ language_root_to_copy_from,
214
+ language_id: params[:languages][:new_lang_id],
215
+ language_code: Language.current.code
216
+ )
217
+ page_copy.move_to_child_of Page.root
218
+ page_copy
219
+ end
220
+
221
+ def language_root_to_copy_from
222
+ Page.language_root_for(params[:languages][:old_lang_id])
223
+ end
224
+
225
+ # Returns the current left index and the aggregated hash of tree nodes indexed by page id visited so far
226
+ #
227
+ # Visits a batch of children nodes, assigns them the correct ordering indexes and spuns recursively the same
228
+ # procedure on their children, if any
229
+ #
230
+ # @param [Array]
231
+ # An array of children nodes to be visited
232
+ # @param [Integer]
233
+ # The lft attribute that should be given to the first node in the array
234
+ # @param [Integer]
235
+ # The page id of the parent of this batch of children nodes
236
+ # @param [Integer]
237
+ # The depth at which these children reside
238
+ # @param [Hash]
239
+ # A Hash of TreeNode's indexed by their page ids
240
+ # @param [String]
241
+ # The url for the parent node of these children
242
+ # @param [Boolean]
243
+ # Whether these children reside in a restricted branch according to their ancestors
244
+ #
245
+ def visit_nodes(nodes, my_left, parent, depth, tree, url, restricted)
246
+ nodes.each do |item|
247
+ my_right = my_left + 1
248
+ my_restricted = item['restricted'] || restricted
249
+ urls = process_url(url, item)
250
+
251
+ if item['children']
252
+ my_right, tree = visit_nodes(item['children'], my_left + 1, item['id'], depth + 1, tree, urls[:children_path], my_restricted)
253
+ end
254
+
255
+ tree[item['id']] = TreeNode.new(my_left, my_right, parent, depth, urls[:my_urlname], my_restricted)
256
+ my_left = my_right + 1
257
+ end
258
+
259
+ [my_left, tree]
260
+ end
261
+
262
+ # Returns a Hash of TreeNode's indexed by their page ids
263
+ #
264
+ # Grabs the array representing a tree structure of pages passed as a parameter,
265
+ # visits it and creates a map of TreeNodes indexed by page id featuring Nested Set
266
+ # ordering information consisting of the left, right, depth and parent_id indexes as
267
+ # well as a node's url and restricted status
268
+ #
269
+ # @param [Array]
270
+ # An Array representing a tree of Alchemy::Page's
271
+ # @param [Alchemy::Page]
272
+ # The root page for the language being ordered
273
+ #
274
+ def create_tree(items, rootpage)
275
+ _, tree = visit_nodes(items, rootpage.lft + 1, rootpage.id, rootpage.depth + 1, {}, "", rootpage.restricted)
276
+ tree
277
+ end
278
+
279
+ # Returns a pair, the path that a given tree node should take, and the path its children should take
280
+ #
281
+ # This function will add a node's own slug into their ancestor's path
282
+ # in order to create the full URL of a node
283
+ #
284
+ # NOTE: external and invisible pages are not part of the full path of their children
285
+ #
286
+ # @param [String]
287
+ # The node's ancestors path
288
+ # @param [Hash]
289
+ # A children node
290
+ #
291
+ def process_url(ancestors_path, item)
292
+ default_urlname = (ancestors_path.blank? ? "" : "#{ancestors_path}/") + item['slug'].to_s
293
+
294
+ pair = {my_urlname: default_urlname, children_path: default_urlname}
295
+
296
+ if item['external'] == true || item['visible'] == false
297
+ # children ignore an ancestor in their path if external or invisible
298
+ pair[:children_path] = ancestors_path
299
+ end
300
+
301
+ pair
302
+ end
303
+
304
+ def load_page
305
+ @page = Page.find(params[:id])
306
+ end
307
+
308
+ def pages_from_raw_request
309
+ request.raw_post.split('&').map { |i| i = {i.split('=')[0].gsub(/[^0-9]/, '') => i.split('=')[1]} }
310
+ end
311
+
312
+ def redirect_path_for_switch_language
313
+ if request.referer && request.referer.include?('admin/layoutpages')
314
+ admin_layoutpages_path
315
+ else
316
+ admin_pages_path
317
+ end
318
+ end
319
+
320
+ def redirect_path_after_create_page
321
+ if @page.redirects_to_external?
322
+ admin_pages_path
323
+ else
324
+ params[:redirect_to] || edit_admin_page_path(@page)
325
+ end
326
+ end
327
+
328
+ def page_params
329
+ params.require(:page).permit(*secure_attributes)
330
+ end
331
+
332
+ def secure_attributes
333
+ if can?(:create, Alchemy::Page)
334
+ Page::PERMITTED_ATTRIBUTES + [:language_root, :parent_id, :language_id, :language_code]
335
+ else
336
+ Page::PERMITTED_ATTRIBUTES
337
+ end
338
+ end
339
+
340
+ def page_is_locked?
341
+ return if !@page.locker.try(:logged_in?)
342
+ @page.locked? && @page.locker != current_alchemy_user
343
+ end
344
+
345
+ def paste_from_clipboard
346
+ if params[:paste_from_clipboard]
347
+ source = Page.find(params[:paste_from_clipboard])
348
+ parent = Page.find_by(id: params[:page][:parent_id]) || Page.root
349
+ Page.copy_and_paste(source, parent, params[:page][:name])
350
+ end
351
+ end
352
+
353
+ def set_root_page
354
+ @page_root = Language.current_root_page
355
+ end
356
+
357
+ end
358
+ end
359
+ end