alchemy_cms 2.5.3.1 → 2.6.0.rc5

Sign up to get free protection for your applications and to get access to all the features.
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!