alchemy_cms 2.5.3.1 → 2.6.0.rc5

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 (331) hide show
  1. data/.gitignore +1 -1
  2. data/.travis.yml +5 -13
  3. data/Gemfile +6 -3
  4. data/README.md +3 -2
  5. data/alchemy_cms.gemspec +22 -22
  6. data/app/assets/fonts/alchemy-icons.eot +0 -0
  7. data/app/assets/fonts/alchemy-icons.svg +54 -0
  8. data/app/assets/fonts/alchemy-icons.ttf +0 -0
  9. data/app/assets/fonts/alchemy-icons.woff +0 -0
  10. data/app/assets/images/alchemy/icons.png +0 -0
  11. data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +151 -0
  12. data/app/assets/javascripts/alchemy/alchemy.buttons.js.coffee +3 -2
  13. data/app/assets/javascripts/alchemy/alchemy.datepicker.js.coffee +31 -0
  14. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js +1 -1
  15. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +98 -0
  16. data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +23 -24
  17. data/app/assets/javascripts/alchemy/alchemy.growler.js.coffee +27 -0
  18. data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +11 -8
  19. data/app/assets/javascripts/alchemy/alchemy.hotkeys.js.coffee +32 -0
  20. data/app/assets/javascripts/alchemy/alchemy.image_cropper.js.coffee +46 -0
  21. data/app/assets/javascripts/alchemy/alchemy.js +8 -2
  22. data/app/assets/javascripts/alchemy/alchemy.link_overlay.js.coffee +5 -4
  23. data/app/assets/javascripts/alchemy/alchemy.list_filter.js.coffee +49 -0
  24. data/app/assets/javascripts/alchemy/alchemy.onload.js.coffee +3 -0
  25. data/app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee +71 -0
  26. data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +61 -0
  27. data/app/assets/javascripts/alchemy/alchemy.spinner.js.coffee +35 -0
  28. data/app/assets/javascripts/alchemy/alchemy.string_extension.js.coffee +11 -0
  29. data/app/assets/javascripts/alchemy/alchemy.windows.js.coffee +278 -0
  30. data/app/assets/stylesheets/alchemy/admin.css.scss +2 -0
  31. data/app/assets/stylesheets/alchemy/archive.scss +109 -65
  32. data/app/assets/stylesheets/alchemy/base.scss +16 -188
  33. data/app/assets/stylesheets/alchemy/dashboard.scss +2 -2
  34. data/app/assets/stylesheets/alchemy/defaults.scss +2 -1
  35. data/app/assets/stylesheets/alchemy/elements.scss +58 -94
  36. data/app/assets/stylesheets/alchemy/errors.scss +2 -2
  37. data/app/assets/stylesheets/alchemy/{mixins.scss → extends.scss} +104 -80
  38. data/app/assets/stylesheets/alchemy/flash.scss +4 -6
  39. data/app/assets/stylesheets/alchemy/fonts.scss +46 -0
  40. data/app/assets/stylesheets/alchemy/form_elements.scss +46 -45
  41. data/app/assets/stylesheets/alchemy/frame.scss +20 -15
  42. data/app/assets/stylesheets/alchemy/icons.scss +22 -9
  43. data/app/assets/stylesheets/alchemy/jquery-ui.scss +476 -399
  44. data/app/assets/stylesheets/alchemy/login.scss +1 -1
  45. data/app/assets/stylesheets/alchemy/menubar.css.scss +1 -1
  46. data/app/assets/stylesheets/alchemy/notices.scss +5 -5
  47. data/app/assets/stylesheets/alchemy/pagination.scss +25 -13
  48. data/app/assets/stylesheets/alchemy/search.scss +29 -17
  49. data/app/assets/stylesheets/alchemy/sitemap.scss +41 -36
  50. data/app/assets/stylesheets/alchemy/tables.scss +102 -50
  51. data/app/assets/stylesheets/alchemy/tinymce_dialog.css.scss +18 -16
  52. data/app/assets/stylesheets/alchemy/toolbar.scss +84 -24
  53. data/app/assets/stylesheets/alchemy/upload.scss +14 -9
  54. data/app/assets/stylesheets/alchemy/variables.scss +1 -0
  55. data/app/assets/stylesheets/tiny_mce/plugins/inlinepopups/skins/alchemy/window.css.scss +18 -21
  56. data/app/controllers/alchemy/admin/attachments_controller.rb +29 -39
  57. data/app/controllers/alchemy/admin/base_controller.rb +3 -9
  58. data/app/controllers/alchemy/admin/clipboard_controller.rb +1 -1
  59. data/app/controllers/alchemy/admin/contents_controller.rb +1 -1
  60. data/app/controllers/alchemy/admin/dashboard_controller.rb +1 -1
  61. data/app/controllers/alchemy/admin/elements_controller.rb +3 -3
  62. data/app/controllers/alchemy/admin/essence_files_controller.rb +1 -1
  63. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +5 -5
  64. data/app/controllers/alchemy/admin/languages_controller.rb +1 -1
  65. data/app/controllers/alchemy/admin/pages_controller.rb +18 -16
  66. data/app/controllers/alchemy/admin/pictures_controller.rb +11 -10
  67. data/app/controllers/alchemy/admin/resources_controller.rb +87 -14
  68. data/app/controllers/alchemy/admin/tags_controller.rb +3 -3
  69. data/app/controllers/alchemy/admin/trash_controller.rb +3 -3
  70. data/app/controllers/alchemy/admin/users_controller.rb +6 -11
  71. data/app/controllers/alchemy/attachments_controller.rb +8 -9
  72. data/app/controllers/alchemy/base_controller.rb +17 -10
  73. data/app/controllers/alchemy/pages_controller.rb +7 -19
  74. data/app/controllers/alchemy/passwords_controller.rb +15 -3
  75. data/app/controllers/alchemy/user_sessions_controller.rb +5 -4
  76. data/app/controllers/alchemy/users_controller.rb +1 -1
  77. data/app/helpers/alchemy/admin/attachments_helper.rb +2 -2
  78. data/app/helpers/alchemy/admin/base_helper.rb +62 -90
  79. data/app/helpers/alchemy/admin/elements_helper.rb +13 -5
  80. data/app/helpers/alchemy/admin/essences_helper.rb +3 -5
  81. data/app/helpers/alchemy/admin/pages_helper.rb +6 -3
  82. data/app/helpers/alchemy/admin/tags_helper.rb +60 -0
  83. data/app/helpers/alchemy/base_helper.rb +16 -20
  84. data/app/helpers/alchemy/elements_helper.rb +7 -11
  85. data/app/helpers/alchemy/essences_helper.rb +2 -2
  86. data/app/helpers/alchemy/pages_helper.rb +31 -69
  87. data/app/helpers/alchemy/url_helper.rb +11 -3
  88. data/app/models/alchemy/attachment.rb +73 -45
  89. data/app/models/alchemy/cell.rb +1 -1
  90. data/app/models/alchemy/content.rb +20 -9
  91. data/app/models/alchemy/element.rb +9 -7
  92. data/app/models/alchemy/page.rb +15 -248
  93. data/app/models/alchemy/page/cells.rb +71 -0
  94. data/app/models/alchemy/page/elements.rb +147 -0
  95. data/app/models/alchemy/page/naming.rb +90 -0
  96. data/app/models/alchemy/picture.rb +18 -13
  97. data/app/models/alchemy/tag.rb +1 -1
  98. data/app/models/alchemy/user.rb +38 -6
  99. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +14 -7
  100. data/app/views/alchemy/admin/attachments/_attachment.html.erb +17 -12
  101. data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +3 -8
  102. data/app/views/alchemy/admin/attachments/_files_list.html.erb +20 -12
  103. data/app/views/alchemy/admin/attachments/_overlay_file_list.html.erb +11 -0
  104. data/app/views/alchemy/admin/attachments/_tag_list.html.erb +31 -0
  105. data/app/views/alchemy/admin/attachments/archive_overlay.js.erb +4 -0
  106. data/app/views/alchemy/admin/attachments/edit.html.erb +8 -7
  107. data/app/views/alchemy/admin/attachments/index.html.erb +19 -12
  108. data/app/views/alchemy/admin/attachments/new.html.erb +2 -2
  109. data/app/views/alchemy/admin/attachments/show.html.erb +3 -0
  110. data/app/views/alchemy/admin/contents/_missing.html.erb +4 -4
  111. data/app/views/alchemy/admin/contents/create.js.erb +1 -1
  112. data/app/views/alchemy/admin/contents/new.html.erb +6 -3
  113. data/app/views/alchemy/admin/dashboard/_locked_pages.html.erb +1 -1
  114. data/app/views/alchemy/admin/dashboard/_users.html.erb +1 -1
  115. data/app/views/alchemy/admin/dashboard/index.html.erb +3 -3
  116. data/app/views/alchemy/admin/dashboard/info.html.erb +16 -13
  117. data/app/views/alchemy/admin/elements/_add_picture.html.erb +1 -1
  118. data/app/views/alchemy/admin/elements/_element_foot.html.erb +4 -4
  119. data/app/views/alchemy/admin/elements/_element_head.html.erb +1 -7
  120. data/app/views/alchemy/admin/elements/_elements_select.html.erb +2 -2
  121. data/app/views/alchemy/admin/elements/_new_element_form.html.erb +4 -4
  122. data/app/views/alchemy/admin/elements/_picture_gallery_editor.html.erb +1 -1
  123. data/app/views/alchemy/admin/elements/create.js.erb +2 -2
  124. data/app/views/alchemy/admin/elements/fold.js.erb +3 -6
  125. data/app/views/alchemy/admin/elements/new.html.erb +1 -1
  126. data/app/views/alchemy/admin/elements/order.js.erb +1 -1
  127. data/app/views/alchemy/admin/elements/trash.js.erb +1 -1
  128. data/app/views/alchemy/admin/elements/update.js.erb +2 -2
  129. data/app/views/alchemy/admin/essence_files/edit.html.erb +4 -4
  130. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +17 -18
  131. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +2 -2
  132. data/app/views/alchemy/admin/essence_pictures/update.js.erb +1 -0
  133. data/app/views/alchemy/admin/languages/_form.html.erb +12 -10
  134. data/app/views/alchemy/admin/languages/_language.html.erb +2 -1
  135. data/app/views/alchemy/admin/languages/_table.html.erb +3 -3
  136. data/app/views/alchemy/admin/languages/index.html.erb +15 -15
  137. data/app/views/alchemy/admin/layoutpages/_layoutpage.html.erb +6 -6
  138. data/app/views/alchemy/admin/layoutpages/index.html.erb +41 -40
  139. data/app/views/alchemy/admin/pages/_contactform_links.html.erb +4 -4
  140. data/app/views/alchemy/admin/pages/_create_language_form.html.erb +6 -6
  141. data/app/views/alchemy/admin/pages/_external_link.html.erb +2 -2
  142. data/app/views/alchemy/admin/pages/_file_link.html.erb +3 -3
  143. data/app/views/alchemy/admin/pages/_internal_link.html.erb +1 -1
  144. data/app/views/alchemy/admin/pages/_new_page_form.html.erb +1 -1
  145. data/app/views/alchemy/admin/pages/_page.html.erb +13 -13
  146. data/app/views/alchemy/admin/pages/_page_for_links.html.erb +2 -4
  147. data/app/views/alchemy/admin/pages/_sitemap.html.erb +5 -0
  148. data/app/views/alchemy/admin/pages/configure.html.erb +7 -7
  149. data/app/views/alchemy/admin/pages/configure_external.html.erb +4 -4
  150. data/app/views/alchemy/admin/pages/edit.html.erb +23 -30
  151. data/app/views/alchemy/admin/pages/index.html.erb +34 -23
  152. data/app/views/alchemy/admin/pages/new.html.erb +1 -1
  153. data/app/views/alchemy/admin/pages/sort.js.erb +1 -1
  154. data/app/views/alchemy/admin/partials/_flash_upload.html.erb +2 -3
  155. data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +2 -2
  156. data/app/views/alchemy/admin/partials/_search_form.html.erb +3 -3
  157. data/app/views/alchemy/admin/partials/_upload_form.html.erb +2 -2
  158. data/app/views/alchemy/admin/pictures/_archive.html.erb +7 -7
  159. data/app/views/alchemy/admin/pictures/_archive_overlay.html.erb +1 -1
  160. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +6 -6
  161. data/app/views/alchemy/admin/pictures/_filter_bar.html.erb +4 -4
  162. data/app/views/alchemy/admin/pictures/_overlay_picture_list.html.erb +1 -1
  163. data/app/views/alchemy/admin/pictures/_picture.html.erb +3 -8
  164. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +9 -14
  165. data/app/views/alchemy/admin/pictures/_tag_list.html.erb +27 -25
  166. data/app/views/alchemy/admin/pictures/archive_overlay.js.erb +3 -1
  167. data/app/views/alchemy/admin/pictures/index.html.erb +49 -42
  168. data/app/views/alchemy/admin/pictures/new.html.erb +2 -2
  169. data/app/views/alchemy/admin/pictures/show.html.erb +11 -0
  170. data/app/views/alchemy/admin/resources/_boolean.html.erb +2 -2
  171. data/app/views/alchemy/admin/resources/_datetime.html.erb +2 -2
  172. data/app/views/alchemy/admin/resources/_form.html.erb +9 -8
  173. data/app/views/alchemy/admin/resources/_resource.html.erb +15 -21
  174. data/app/views/alchemy/admin/resources/_string.html.erb +2 -2
  175. data/app/views/alchemy/admin/resources/_table.html.erb +11 -13
  176. data/app/views/alchemy/admin/resources/_text.html.erb +2 -2
  177. data/app/views/alchemy/admin/resources/index.csv.erb +13 -0
  178. data/app/views/alchemy/admin/resources/index.html.erb +24 -15
  179. data/app/views/alchemy/admin/sites/index.html.erb +23 -0
  180. data/app/views/alchemy/admin/tags/_radio_tag.html.erb +1 -1
  181. data/app/views/alchemy/admin/tags/_tag.html.erb +2 -1
  182. data/app/views/alchemy/admin/tags/edit.html.erb +1 -1
  183. data/app/views/alchemy/admin/tags/index.html.erb +16 -11
  184. data/app/views/alchemy/admin/tags/new.html.erb +3 -3
  185. data/app/views/alchemy/admin/trash/clear.js.coffee +1 -1
  186. data/app/views/alchemy/admin/users/_table.html.erb +12 -5
  187. data/app/views/alchemy/admin/users/_user.html.erb +16 -16
  188. data/app/views/alchemy/admin/users/index.html.erb +28 -16
  189. data/app/views/alchemy/breadcrumb/_page.html.erb +15 -0
  190. data/app/views/alchemy/breadcrumb/_spacer.html.erb +1 -0
  191. data/app/views/alchemy/elements/_editor_not_found.html.erb +1 -1
  192. data/app/views/alchemy/essences/_essence_file_editor.html.erb +16 -16
  193. data/app/views/alchemy/essences/_essence_file_view.html.erb +8 -9
  194. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +3 -6
  195. data/app/views/alchemy/essences/_essence_picture_tools.html.erb +9 -8
  196. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +0 -5
  197. data/app/views/alchemy/essences/_linkable_essence_tools.html.erb +2 -2
  198. data/app/views/alchemy/navigation/_link.html.erb +7 -7
  199. data/app/views/alchemy/navigation/_renderer.html.erb +29 -36
  200. data/app/views/alchemy/notifications/admin_user_created.de.text.erb +5 -1
  201. data/app/views/alchemy/notifications/admin_user_created.en.text.erb +5 -1
  202. data/app/views/alchemy/notifications/registered_user_created.de.text.erb +13 -0
  203. data/app/views/alchemy/notifications/registered_user_created.en.text.erb +13 -0
  204. data/app/views/alchemy/search/_result.html.erb +4 -6
  205. data/app/views/alchemy/search/_results.html.erb +4 -5
  206. data/app/views/alchemy/user_sessions/leave.html.erb +1 -1
  207. data/app/views/alchemy/user_sessions/new.html.erb +2 -2
  208. data/app/views/kaminari/_first_page.html.erb +11 -0
  209. data/app/views/kaminari/_gap.html.erb +1 -1
  210. data/app/views/kaminari/_last_page.html.erb +11 -0
  211. data/app/views/kaminari/_next_page.html.erb +2 -2
  212. data/app/views/kaminari/_page.html.erb +1 -1
  213. data/app/views/kaminari/_paginator.html.erb +2 -0
  214. data/app/views/kaminari/_prev_page.html.erb +2 -2
  215. data/app/views/layouts/alchemy/admin.html.erb +4 -5
  216. data/config/alchemy/config.yml +8 -12
  217. data/config/authorization_rules.rb +4 -3
  218. data/config/initializers/dragonfly.rb +20 -12
  219. data/config/locales/alchemy.de.yml +20 -15
  220. data/config/locales/alchemy.en.yml +15 -10
  221. data/config/locales/devise.de.yml +1 -0
  222. data/config/routes.rb +3 -3
  223. data/{spec/dummy/db/migrate/20121118000000_alchemy_two_point_four.rb → db/migrate/20130214233001_alchemy_two_point_five.rb} +50 -36
  224. data/db/migrate/20130221200514_migrate_attachments_to_dragonfly.rb +21 -0
  225. data/db/migrate/20130312205327_change_alchemy_users_role_to_roles.rb +11 -0
  226. data/lib/alchemy/capistrano.rb +10 -8
  227. data/lib/alchemy/errors.rb +7 -0
  228. data/lib/alchemy/filetypes.rb +33 -0
  229. data/lib/alchemy/i18n.rb +9 -1
  230. data/lib/alchemy/name_conversions.rb +28 -0
  231. data/lib/alchemy/page_layout.rb +5 -3
  232. data/lib/alchemy/resource.rb +132 -29
  233. data/lib/alchemy/resources_helper.rb +81 -12
  234. data/lib/alchemy/upgrader.rb +14 -276
  235. data/lib/alchemy/version.rb +1 -1
  236. data/lib/alchemy_cms.rb +17 -2
  237. data/lib/rails/generators/alchemy/deploy_script/templates/deploy.rb.tt +1 -1
  238. data/lib/rails/generators/alchemy/scaffold/scaffold_generator.rb +1 -1
  239. data/lib/tasks/alchemy/convert.rake +39 -0
  240. data/lib/tasks/alchemy/install.rake +4 -6
  241. data/lib/tasks/alchemy/upgrade.rake +18 -1
  242. data/spec/controllers/admin/clipboard_controller_spec.rb +4 -4
  243. data/spec/controllers/admin/elements_controller_spec.rb +23 -23
  244. data/spec/controllers/admin/pages_controller_spec.rb +15 -0
  245. data/spec/controllers/admin/resources_controller_spec.rb +1 -11
  246. data/spec/controllers/admin/trash_controller_spec.rb +9 -9
  247. data/spec/controllers/attachments_controller_spec.rb +3 -3
  248. data/spec/controllers/elements_controller_spec.rb +2 -2
  249. data/spec/controllers/pages_controller_spec.rb +160 -129
  250. data/spec/controllers/pictures_controller_spec.rb +2 -2
  251. data/spec/controllers/user_sessions_controller_spec.rb +3 -3
  252. data/spec/controllers/users_controller_spec.rb +2 -2
  253. data/spec/dummy/app/models/event.rb +2 -2
  254. data/spec/dummy/app/models/location.rb +4 -0
  255. data/spec/dummy/app/views/layouts/application.html.erb +6 -42
  256. data/spec/dummy/config/routes.rb +1 -1
  257. data/spec/dummy/db/migrate/20121026104128_create_events.rb +0 -1
  258. data/{db/migrate/20121118000000_alchemy_two_point_four.rb → spec/dummy/db/migrate/20130214233001_alchemy_two_point_five.rb} +50 -36
  259. data/spec/dummy/db/migrate/20130221200514_migrate_attachments_to_dragonfly.rb +21 -0
  260. data/spec/dummy/db/migrate/20130312205327_change_alchemy_users_role_to_roles.rb +11 -0
  261. data/spec/dummy/db/migrate/20130328101418_create_locations.rb +9 -0
  262. data/spec/dummy/db/schema.rb +15 -6
  263. data/spec/factories.rb +4 -4
  264. data/spec/{integration → features}/admin/link_overlay_spec.rb +0 -0
  265. data/spec/{integration → features}/admin/modules_integration_spec.rb +1 -1
  266. data/spec/{integration → features}/admin/pages_controller_spec.rb +9 -4
  267. data/spec/{integration → features}/admin/picture_library_integration_spec.rb +5 -5
  268. data/spec/{integration → features}/admin/resources_integration_spec.rb +1 -1
  269. data/spec/{integration → features}/navigation_spec.rb +0 -0
  270. data/spec/{integration → features}/pages_controller_spec.rb +42 -112
  271. data/spec/{integration → features}/picture_security_spec.rb +2 -2
  272. data/spec/{integration → features}/security_spec.rb +7 -7
  273. data/spec/{integration → features}/translation_integration_spec.rb +0 -0
  274. data/spec/helpers/admin/base_helper_spec.rb +0 -50
  275. data/spec/helpers/admin/tags_helper_spec.rb +53 -0
  276. data/spec/helpers/base_helper_spec.rb +19 -3
  277. data/spec/helpers/pages_helper_spec.rb +92 -44
  278. data/spec/{url_helpers_spec.rb → helpers/picture_url_helpers_spec.rb} +7 -7
  279. data/spec/helpers/url_helper_spec.rb +92 -72
  280. data/spec/{config_spec.rb → libraries/config_spec.rb} +0 -0
  281. data/spec/libraries/resource_spec.rb +215 -76
  282. data/spec/libraries/resources_helper_spec.rb +70 -28
  283. data/spec/models/attachment_spec.rb +75 -9
  284. data/spec/models/clipboard_spec.rb +1 -1
  285. data/spec/models/element_spec.rb +7 -0
  286. data/spec/models/page_spec.rb +144 -25
  287. data/spec/models/picture_spec.rb +5 -5
  288. data/spec/models/resource_spec.rb +47 -10
  289. data/spec/models/user_spec.rb +115 -3
  290. data/spec/{routing_spec.rb → routing/routing_spec.rb} +8 -20
  291. data/spec/spec_helper.rb +5 -6
  292. data/spec/support/alchemy/specs_helpers.rb +1 -1
  293. data/spec/support/ci/install_phantomjs +1 -1
  294. data/spec/support/image with spaces.png +0 -0
  295. data/vendor/assets/javascripts/jquery_plugins/jquery.Jcrop.min.js +18 -18
  296. data/vendor/assets/javascripts/jquery_plugins/{jquery.dialogextend.1_0_1.js → jquery.dialogextend.js} +25 -17
  297. data/vendor/assets/javascripts/jquery_plugins/jquery.scrollTo.min.js +7 -0
  298. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.tabspaging.js +7 -7
  299. data/vendor/assets/javascripts/keymage.min.js +6 -0
  300. data/vendor/assets/javascripts/spin.min.js +1 -0
  301. metadata +122 -124
  302. data/app/assets/images/alchemy/ajax_loader.gif +0 -0
  303. data/app/assets/images/alchemy/gui/toggle.png +0 -0
  304. data/app/assets/images/alchemy/image_loader.gif +0 -0
  305. data/app/assets/images/alchemy/shading.png +0 -0
  306. data/app/assets/images/alchemy/tabs.gif +0 -0
  307. data/app/assets/javascripts/alchemy/alchemy.base.js +0 -172
  308. data/app/assets/javascripts/alchemy/alchemy.datepicker.js +0 -47
  309. data/app/assets/javascripts/alchemy/alchemy.element_editor_selector.js +0 -91
  310. data/app/assets/javascripts/alchemy/alchemy.growler.js +0 -46
  311. data/app/assets/javascripts/alchemy/alchemy.image_cropper.js +0 -60
  312. data/app/assets/javascripts/alchemy/alchemy.js_extensions.js +0 -15
  313. data/app/assets/javascripts/alchemy/alchemy.preview_window.js +0 -97
  314. data/app/assets/javascripts/alchemy/alchemy.windows.js +0 -321
  315. data/app/models/alchemy/clipboard_spec.rb +0 -0
  316. data/app/views/alchemy/admin/pictures/show_in_window.html.erb +0 -8
  317. data/app/views/alchemy/notifications/registered_user_created.text.erb +0 -11
  318. data/db/migrate/20121121162313_switch_from_fleximage_to_dragonfly.rb +0 -21
  319. data/db/migrate/20121205155004_create_alchemy_sites.rb +0 -14
  320. data/db/migrate/20121211163003_add_public_to_alchemy_sites.rb +0 -6
  321. data/db/migrate/20121220102223_add_aliases_to_site.rb +0 -6
  322. data/db/migrate/20130110212411_create_alchemy_legacy_page_urls.rb +0 -11
  323. data/db/migrate/20130121092645_migrate_to_devise.rb +0 -24
  324. data/spec/alchemy_spec.rb +0 -7
  325. data/spec/dummy/db/migrate/20121121162313_switch_from_fleximage_to_dragonfly.rb +0 -21
  326. data/spec/dummy/db/migrate/20121205155004_create_alchemy_sites.rb +0 -14
  327. data/spec/dummy/db/migrate/20121211163003_add_public_to_alchemy_sites.rb +0 -6
  328. data/spec/dummy/db/migrate/20121220102223_add_aliases_to_site.rb +0 -6
  329. data/spec/dummy/db/migrate/20130110212411_create_alchemy_legacy_page_urls.rb +0 -11
  330. data/spec/dummy/db/migrate/20130121092645_migrate_to_devise.rb +0 -24
  331. data/vendor/assets/javascripts/jquery_plugins/jquery.scrollTo-1.4.2-min.js +0 -11
@@ -0,0 +1,71 @@
1
+ module Alchemy
2
+ module Page::Cells
3
+
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ has_many :cells, :dependent => :destroy
8
+ after_create :create_cells, :if => :can_have_cells?, :unless => :systempage?
9
+ end
10
+
11
+ module ClassMethods
12
+
13
+ # Copy page cells
14
+ #
15
+ # @param source [Alchemy::Page]
16
+ # @param target [Alchemy::Page]
17
+ # @return [Array]
18
+ #
19
+ def copy_cells(source, target)
20
+ new_cells = []
21
+ source.cells.each do |cell|
22
+ new_cells << Cell.create(:name => cell.name, :page_id => target.id)
23
+ end
24
+ new_cells
25
+ end
26
+
27
+ end
28
+
29
+ # Returns true, if the page's page_layout defines cells.
30
+ def can_have_cells?
31
+ definition['cells'].present?
32
+ end
33
+
34
+ # Returns true, if the page has cells.
35
+ def has_cells?
36
+ cells.any?
37
+ end
38
+
39
+ # Returns the cell definitions from page's page_layout defintion.
40
+ def cell_definitions
41
+ cell_names = self.layout_description['cells']
42
+ return [] if cell_names.blank?
43
+ Cell.all_definitions_for(cell_names)
44
+ end
45
+
46
+ # Returns elements grouped by cell.
47
+ def elements_grouped_by_cells
48
+ elements.not_trashed.in_cell.group_by(&:cell)
49
+ end
50
+
51
+ # Returns element names from cell definition.
52
+ def element_names_from_cells
53
+ cell_definitions.collect { |c| c['elements'] }.flatten.uniq
54
+ end
55
+
56
+ # Returns element names that are not defined in a cell.
57
+ def element_names_not_in_cell
58
+ layout_description['elements'].uniq - element_names_from_cells
59
+ end
60
+
61
+ private
62
+
63
+ # Creates cells that are defined in page's page_layout definition.
64
+ def create_cells
65
+ definition['cells'].each do |cellname|
66
+ cells.create!(:name => cellname)
67
+ end
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,147 @@
1
+ module Alchemy
2
+ module Page::Elements
3
+
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ attr_accessor :do_not_autogenerate
8
+
9
+ has_many :elements, :order => :position
10
+ has_many :contents, :through => :elements
11
+ has_and_belongs_to_many :to_be_sweeped_elements, :class_name => 'Alchemy::Element', :uniq => true, :join_table => 'alchemy_elements_alchemy_pages'
12
+
13
+ after_create :autogenerate_elements, :unless => proc { systempage? || do_not_autogenerate }
14
+ after_update :trash_not_allowed_elements, :if => :page_layout_changed?
15
+ after_update :autogenerate_elements, :if => :page_layout_changed?
16
+ after_destroy { elements.each { |el| el.destroy unless el.trashed? } }
17
+ end
18
+
19
+ module ClassMethods
20
+
21
+ # Copy page elements
22
+ #
23
+ # @param source [Alchemy::Page]
24
+ # @param target [Alchemy::Page]
25
+ # @return [Array]
26
+ #
27
+ def copy_elements(source, target)
28
+ new_elements = []
29
+ source.elements.not_trashed.each do |element|
30
+ # detect cell for element
31
+ if element.cell
32
+ cell = target.cells.detect { |c| c.name == element.cell.name }
33
+ else
34
+ cell = nil
35
+ end
36
+ # if cell is nil also pass nil to element.cell_id
37
+ new_element = Element.copy(element, :page_id => target.id, :cell_id => (cell.blank? ? nil : cell.id))
38
+ # move element to bottom of the list
39
+ new_element.move_to_bottom
40
+ new_elements << new_element
41
+ end
42
+ new_elements
43
+ end
44
+
45
+ end
46
+
47
+ # Finds selected elements from page.
48
+ #
49
+ # Returns only public elements by default.
50
+ # Pass true as second argument to get all elements.
51
+ #
52
+ # === Options are:
53
+ #
54
+ # :only => Array of element names # Returns only elements with given names
55
+ # :except => Array of element names # Returns all elements except the ones with given names
56
+ # :count => Integer # Limit the count of returned elements
57
+ # :offset => Integer # Starts with an offset while returning elements
58
+ # :random => Boolean # Return elements randomly shuffled
59
+ # :from_cell => Cell or String # Return elements from given cell
60
+ #
61
+ def find_selected_elements(options = {}, show_non_public = false)
62
+ if options[:from_cell].class.name == 'Alchemy::Cell'
63
+ elements = options[:from_cell].elements
64
+ elsif !options[:from_cell].blank? && options[:from_cell].class.name == 'String'
65
+ cell = cells.find_by_name(options[:from_cell])
66
+ if cell
67
+ elements = cell.elements
68
+ else
69
+ warn("Cell with name `#{options[:from_cell]}` could not be found!")
70
+ # Returns an empty relation. Can be removed with the release of Rails 4
71
+ elements = self.elements.where('1 = 0')
72
+ end
73
+ else
74
+ elements = self.elements.not_in_cell
75
+ end
76
+ if !options[:only].blank?
77
+ elements = elements.named(options[:only])
78
+ elsif !options[:except].blank?
79
+ elements = elements.excluded(options[:except])
80
+ end
81
+ elements = elements.reverse_order if options[:reverse_sort] || options[:reverse]
82
+ elements = elements.offset(options[:offset]).limit(options[:count])
83
+ elements = elements.order("RAND()") if options[:random]
84
+ show_non_public ? elements : elements.published
85
+ end
86
+
87
+ # What is this? A Kind of proxy method? Why not rendering the elements directly if you already have them????
88
+ def find_elements(options = {}, show_non_public = false)
89
+ if !options[:collection].blank? && options[:collection].is_a?(Array)
90
+ return options[:collection]
91
+ else
92
+ find_selected_elements(options, show_non_public)
93
+ end
94
+ end
95
+
96
+ # Returns all elements that should be feeded via rss.
97
+ #
98
+ # Define feedable elements in your +page_layouts.yml+:
99
+ #
100
+ # - name: news
101
+ # feed: true
102
+ # feed_elements: [element_name, element_2_name]
103
+ #
104
+ def feed_elements
105
+ elements.named(definition['feed_elements'])
106
+ end
107
+
108
+ private
109
+
110
+ # Looks in the page_layout descripion, if there are elements to autogenerate.
111
+ #
112
+ # And if so, it generates them.
113
+ #
114
+ # If the page has cells, it looks if there are elements to generate.
115
+ #
116
+ def autogenerate_elements
117
+ elements_already_on_page = self.elements.available.collect(&:name)
118
+ elements = self.layout_description["autogenerate"]
119
+ if elements.present?
120
+ elements.each do |element|
121
+ next if elements_already_on_page.include?(element)
122
+ Element.create_from_scratch(attributes_for_element_name(element))
123
+ end
124
+ end
125
+ end
126
+
127
+ # Returns a hash of attributes for given element name
128
+ def attributes_for_element_name(element)
129
+ if self.has_cells? && (cell_definition = cell_definitions.detect { |c| c['elements'].include?(element) })
130
+ cell = self.cells.find_by_name(cell_definition['name'])
131
+ if cell
132
+ return {:page_id => self.id, :cell_id => cell.id, :name => element}
133
+ else
134
+ raise "Cell not found for page #{self.inspect}"
135
+ end
136
+ else
137
+ return {:page_id => self.id, :name => element}
138
+ end
139
+ end
140
+
141
+ # Trashes all elements that are not allowed for this page_layout.
142
+ def trash_not_allowed_elements
143
+ elements.select { |e| !definition['elements'].include?(e.name) }.map(&:trash)
144
+ end
145
+
146
+ end
147
+ end
@@ -0,0 +1,90 @@
1
+ module Alchemy
2
+ module Page::Naming
3
+
4
+ extend ActiveSupport::Concern
5
+ include NameConversions
6
+ RESERVED_URLNAMES = %w(admin messages new)
7
+
8
+ included do
9
+ before_validation :set_urlname, :if => :renamed?, :unless => proc { systempage? || redirects_to_external? }
10
+
11
+ validates_presence_of :name
12
+ validates_length_of :urlname, :minimum => 3, :if => 'urlname.present?'
13
+ validates_uniqueness_of(
14
+ :urlname,
15
+ :scope => [:language_id, :layoutpage],
16
+ :if => 'urlname.present?'
17
+ )
18
+ validates :urlname, :exclusion => {:in => RESERVED_URLNAMES}
19
+
20
+ before_save :set_title, :if => 'title.blank?', :unless => proc { systempage? || redirects_to_external? }
21
+ after_update(:if => proc { Config.get(:url_nesting) && (urlname_changed? || visible_changed?) }) do
22
+ self.reload
23
+ self.descendants.map(&:update_urlname!)
24
+ end
25
+ after_move :update_urlname!, :if => proc { Config.get(:url_nesting) }
26
+ end
27
+
28
+ # Returns true if name or urlname has changed.
29
+ def renamed?
30
+ name_changed? || urlname_changed?
31
+ end
32
+
33
+ # Makes a slug of all ancestors urlnames including mine and delimit them be slash.
34
+ # So the whole path is stored as urlname in tha database.
35
+ def update_urlname!
36
+ names = ancestors.visible.contentpages.where(language_root: nil).map(&:slug).compact
37
+ new_urlname = (names << slug).join('/')
38
+ # update without callbacks
39
+ if new_record?
40
+ write_attribute :urlname, new_urlname
41
+ else
42
+ if urlname != new_urlname
43
+ legacy_urls.create(:urlname => urlname)
44
+ end
45
+ update_column :urlname, new_urlname
46
+ end
47
+ end
48
+
49
+ # Returns always the last part of a urlname path
50
+ def slug
51
+ urlname.to_s.split('/').last
52
+ end
53
+
54
+ private
55
+
56
+ # Sets the urlname to a url friendly slug.
57
+ # Either from name, or if present, from urlname.
58
+ # If url_nesting is enabled the urlname contains the whole path.
59
+ def set_urlname
60
+ if Config.get(:url_nesting)
61
+ url_name = [
62
+ parent.nil? || parent.language_root? ? nil : parent.urlname,
63
+ convert_url_name((urlname.blank? ? name : slug))
64
+ ].compact.join('/')
65
+ else
66
+ url_name = convert_url_name((urlname.blank? ? name : urlname))
67
+ end
68
+ write_attribute :urlname, url_name
69
+ end
70
+
71
+ def set_title
72
+ write_attribute :title, name
73
+ end
74
+
75
+ # Converts the given name into an url friendly string.
76
+ #
77
+ # Names shorter than 3 will be filled up with dashes,
78
+ # so it does not collidate with the language code.
79
+ #
80
+ def convert_url_name(name)
81
+ url_name = convert_to_urlname(name)
82
+ if url_name.length < 3
83
+ ('-' * (3 - url_name.length)) + url_name
84
+ else
85
+ url_name
86
+ end
87
+ end
88
+
89
+ end
90
+ end
@@ -1,5 +1,6 @@
1
1
  module Alchemy
2
2
  class Picture < ActiveRecord::Base
3
+ include NameConversions
3
4
 
4
5
  has_many :essence_pictures, :class_name => 'Alchemy::EssencePicture', :foreign_key => 'picture_id'
5
6
  has_many :contents, :through => :essence_pictures
@@ -22,7 +23,8 @@ module Alchemy
22
23
  end
23
24
 
24
25
  validates_presence_of :image_file
25
- validates_property :format, :of => :image_file, :in => Config.get('uploader')['allowed_filetypes']['pictures'], :case_sensitive => false, :message => I18n.t("not a valid image")
26
+ validates_size_of :image_file, :maximum => Config.get(:uploader)['file_size_limit'].megabytes
27
+ validates_property :format, :of => :image_file, :in => Config.get(:uploader)['allowed_filetypes']['pictures'], :case_sensitive => false, :message => I18n.t("not a valid image")
26
28
 
27
29
  acts_as_taggable
28
30
 
@@ -38,21 +40,24 @@ module Alchemy
38
40
  scope :recent, where("#{self.table_name}.created_at > ?", Time.now-24.hours).order(:created_at)
39
41
  scope :deletable, where("alchemy_pictures.id NOT IN (SELECT picture_id FROM alchemy_essence_pictures)")
40
42
 
41
- def self.find_paginated(params, per_page)
42
- Picture.where("name LIKE ?", "%#{params[:query]}%").page(params[:page] || 1).per(per_page).order(:name)
43
- end
43
+ # Class methods
44
44
 
45
- def self.last_upload
46
- last_picture = Picture.last
47
- return Picture.scoped unless last_picture
48
- Picture.where(:upload_hash => last_picture.upload_hash)
49
- end
45
+ class << self
46
+
47
+ def find_paginated(params, per_page)
48
+ Picture.where("name LIKE ?", "%#{params[:query]}%").page(params[:page] || 1).per(per_page).order(:name)
49
+ end
50
+
51
+ def last_upload
52
+ last_picture = Picture.last
53
+ return Picture.scoped unless last_picture
54
+ Picture.where(:upload_hash => last_picture.upload_hash)
55
+ end
50
56
 
51
- # Returning the filepath relative to Rails.root public folder.
52
- def public_file_path
53
- self.file_path.gsub("#{::Rails.root}/public", '')
54
57
  end
55
58
 
59
+ # Instance methods
60
+
56
61
  def urlname
57
62
  if self.name.blank?
58
63
  "image_#{self.id}"
@@ -67,7 +72,7 @@ module Alchemy
67
72
 
68
73
  def humanized_name
69
74
  return "" if image_file_name.blank?
70
- (image_file_name.downcase.gsub(/\.#{::Regexp.quote(suffix)}$/, '')).humanize
75
+ convert_to_humanized_name(image_file_name, suffix)
71
76
  end
72
77
 
73
78
  # Returning true if picture's width is greater than it's height
@@ -1,7 +1,7 @@
1
1
  # Just holds some useful tag methods.
2
2
  # The original Tag model is ActsAsTaggableOn::Tag
3
3
  module Alchemy
4
- class Tag
4
+ class Tag < ActsAsTaggableOn::Tag
5
5
 
6
6
  # Replaces tag with new tag on all models tagged with tag.
7
7
  def self.replace(tag, new_tag)
@@ -14,15 +14,17 @@ module Alchemy
14
14
  :login,
15
15
  :email,
16
16
  :gender,
17
- :role,
18
17
  :language,
19
18
  :password,
20
19
  :password_confirmation,
20
+ :roles,
21
21
  :tag_list
22
22
  )
23
23
 
24
24
  has_many :folded_pages
25
25
 
26
+ validates_presence_of :roles
27
+
26
28
  # Unlock all locked pages before destroy and before the user gets logged out.
27
29
  before_destroy :unlock_pages!
28
30
  Warden::Manager.before_logout do |user, auth, opts|
@@ -31,7 +33,10 @@ module Alchemy
31
33
  end
32
34
  end
33
35
 
34
- scope :admins, where(:role => 'admin')
36
+ scope :admins, where(arel_table[:roles].matches("%admin%")) # not pleased with that approach
37
+ # mysql regexp word matching would be much nicer, but it's not included in SQLite functions per se.
38
+ # scope :admins, where("#{table_name}.roles REGEXP '[[:<:]]admin[[:>:]]'")
39
+
35
40
  scope :logged_in, lambda { where("last_request_at > ?", logged_in_timeout.seconds.ago) }
36
41
  scope :logged_out, lambda { where("last_request_at is NULL or last_request_at <= ?", logged_in_timeout.seconds.ago) }
37
42
 
@@ -55,15 +60,40 @@ module Alchemy
55
60
  end
56
61
 
57
62
  def role_symbols
58
- [role.to_sym]
63
+ roles.map(&:to_sym)
64
+ end
65
+
66
+ def role
67
+ roles.first
68
+ end
69
+
70
+ def roles
71
+ read_attribute(:roles).split(' ')
72
+ end
73
+
74
+ def roles=(roles_string)
75
+ if roles_string.is_a? Array
76
+ write_attribute(:roles, roles_string.join(' '))
77
+ elsif roles_string.is_a? String
78
+ write_attribute(:roles, roles_string)
79
+ end
80
+ end
81
+
82
+ def add_role(role)
83
+ self.roles = self.roles.push(role.to_s).uniq
59
84
  end
60
85
 
61
86
  # Returns true if the user ahs admin role
62
87
  def is_admin?
63
- role == "admin"
88
+ has_role? 'admin'
64
89
  end
65
90
  alias_method :admin?, :is_admin?
66
91
 
92
+ # Returns true if the user has the given role.
93
+ def has_role?(role)
94
+ roles.include? role.to_s
95
+ end
96
+
67
97
  # Calls unlock on all locked pages
68
98
  def unlock_pages!
69
99
  pages_locked_by_me.map(&:unlock)
@@ -107,8 +137,10 @@ module Alchemy
107
137
  !logged_in?
108
138
  end
109
139
 
110
- def human_role_name
111
- self.class.human_rolename(self.role)
140
+ def human_roles_string
141
+ roles.map do |role|
142
+ self.class.human_rolename(role)
143
+ end.to_sentence
112
144
  end
113
145
 
114
146
  def store_request_time!